/* tspi.c David Rowe 21 June 2006 Linux device driver for Blackfin that implements unit tests for the Blackfin-SPI-SiLabs 3050 interface. Tested on Blackfin BF533 STAMP with a Digium X100M module wired to SPORT0 and an external 2.048MHz clock. The basic premise of the test is that if all is well register 2 of the si3050 will have 0x3 in it (see p61 3050 data sheet). NOTE: To get the Si3050 to reset correctly every time and make the SPI interface work reliably across all SPI clock speeds took several days effort, much tougher (at least for me) than I thought it would be. I spent about 5 days on this, so I thought it was a good idea to carefully document all the traps and have an fairly extensive unit test to make sure I don't get caught again. See below for running instructions. */ /* Copyright (C) 2006 David Rowe This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include /* Need to do include bfsi module this way due to kbuild restrictions. I would rather have it as seperately compiled module but I couldn't work out how to specify the path I wanted */ #include "../../src/bfsi.c" #define BIT_RESET 4 /* GPIO bit tied to nRESET on Si chips */ #define SPI_SPISEL3 3 #define TESTS 100 /*----------------------- TEST PARAMETERS -----------------------------*/ static int baud = 4; /* gives max for sys clock = 100 MHz for Si3050 */ static int verbose = 0; static int tests = 100; /*-------------------------- SPORT FUNCTION ----------------------------*/ /* Simple SPORT config for this test - we just want an 8kHz FS (generated by the Rx side of the SPORT) to feed to the SiLab chips FSYNC pin. SiLabs chip won't reset properly without this signal. */ static void sport0_init(void) { /* ensure serial ports disabled before modifying */ bfin_write_SPORT0_TCR1(bfin_read_SPORT0_TCR1() & ~TSPEN); bfin_write_SPORT0_RCR1(bfin_read_SPORT0_RCR1() & ~RSPEN); /* set up 8kHz FSYNC using rx FS pin and external clock */ bfin_write_SPORT0_RFSDIV(255); /* 8 kHz FSYNC with 2.048MHz PCLK */ /* 8 bit word length, external tx clk and tx FS */ bfin_write_SPORT0_TCR2(7); bfin_write_SPORT0_TCR1(0); /* 8 bit word length, internal frame sync */ bfin_write_SPORT0_RCR2(7); /* 8 bit word length */ bfin_write_SPORT0_RCR1(IRFS | RFSR); /* enable sport0 Tx and Rx */ bfin_write_SPORT0_TCR1(bfin_read_SPORT0_TCR1() | TSPEN); bfin_write_SPORT0_RCR1(bfin_read_SPORT0_RCR1() | RSPEN); } /*------------------------MODULE INIT FUNCTION --------------------------*/ /* The test can be controlled by command line parameters when the module is installed. The test runs by simply installing the module suing insmod, to run again rmmod the module and insmod again. For example: root:~> insmod tspi.ko itializing module baud: 2 tests: 100 passes: 100 PASSED! Some other options: root:~> rmmod tspi.ko ;insmod tspi.ko baud=0xff tests=10 verbose=1 root:~> rmmod tspi.ko ;insmod tspi.ko baud=0xffff tests=100 */ static int __init tspi_init_module (void) { int i, passed, passes; u8 reg; printk("initializing module\n"); /* init SPI here to ensure that the SPI nCS pin on the SiLabs chip is H when the chip is RESET. This is required to configure the chip for SPI/PCM mode. */ bfsi_spi_init(baud, 1<