=================================================================== RCS file: /cvs/funnyos/arch/sam7s64/dev/saspi.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- funnyos/arch/sam7s64/dev/saspi.c 2007/12/18 15:44:21 1.1 +++ funnyos/arch/sam7s64/dev/saspi.c 2007/12/19 16:08:56 1.2 @@ -1,20 +1,32 @@ /* - * $Id: saspi.c,v 1.1 2007/12/18 15:44:21 nbrk Exp $ + * $Id: saspi.c,v 1.2 2007/12/19 16:08:56 nbrk Exp $ */ #include #include #include +#include +#include #include /* * SPI driver. */ +struct saspi_dd { + struct spi_bus_handle sd_sbh; + + struct bus_handle *sd_bhp; +}; + + int saspi_attach(struct device *, uint32_t, uint8_t); +void saspi_init(struct saspi_dd *ddp) +uint8_t saspi_transmit(struct saspi_dd *ddp, uint8_t data); + struct driver spi_dr = { - 1, + sizeof(struct saspi_dd), spi_attach, NULL, NULL @@ -22,11 +34,91 @@ int -spi_attach(struct device *self, uint32_t loc, uint8_t flags) +saspi_attach(struct device *self, uint32_t loc, uint8_t flags) { - struct XXX_dd *ddp = self->dv_devdata; + struct saspi_dd *ddp = self->dv_devdata; + /* grab bus_handle */ + ddp->sd_bhp = self->dv_parent->dv_aux; + printf("SAM7 SPI\n"); + + /* + * Initialize ourselfes and provide spi_bus_handle to children throught dv_aux. + */ + + saspi_init(ddp); + + ddp->sd_sbh.sb_transmitfunc = saspi_transmit; + ddp->sd_dd = ddp; + return(0); +} + + +void +saspi_init(struct saspi_dd *ddp) +{ + /* + * Initialize on-chip SPI controller. + */ + + /* 'Card Present' on PA15 */ +// bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ODR, 1 << 15); +// bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PER, 1 << 15); + + /* + * Disassociate SPI chip select, clock and data lines from PIO. + * + * PA11 - NPCS0 + * PA12 - MISO + * PA13 - MOSI + * PA14 - SPCK + */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14); + + /* assign pins to Peripheral A */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ASR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14); + + /* reset and enable SPI */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN | AT91C_SPI_SWRST); + /* XXX just to be sure */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN); + + /* set SPI mode to master; disable decoding of Chip Select; PCS 1110 (using fixed CS line) */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | 0x0e << 15); + + /* + * Configure Chip Select Register no. 0 (so no offset from SPI_CSR). + * CPOL (Clock Polarity) is 0 (SPCK inactive is logic 0); + * NCPHA (Clock Phase) is 1; + * 8 bits per transfer; + * XXX SCBR=4a; + */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CSR, AT91C_SPI_NCPHA | 0x4a00); + + /* enable PDC transfers to/from SPI */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PDC_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN); + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN); +} + + +uint8_t +saspi_transmit(struct saspi_dd *ddp, uint8_t data) +{ + /* + * Shift byte on the SPI bus. + */ + /* wait for Transmit Data Register Empty flag */ + while((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR) & AT91C_SPI_TDRE) == 0) + ; + + /* okay, send our byte */ + bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_TDR, 0x0000ffff & data); + + /* wait while Receive Register is full and read it */ + while((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR) & AT91C_SPI_RDRF) == 0) + ; + return( bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_RDR) & 0x0000ffff ); }