Annotation of funnyos/arch/sam7s64/dev/saspi.c, Revision 1.4
1.1 nbrk 1: /*
1.4 ! nbrk 2: * $Id: saspi.c,v 1.3 2007/12/20 15:25:44 nbrk Exp $
1.1 nbrk 3: */
4: #include <sys/types.h>
5: #include <sys/device.h>
6: #include <sys/bus.h>
1.3 nbrk 7: #include <sys/bus_spi.h>
1.1 nbrk 8:
1.2 nbrk 9: #include <libkern/printf.h>
1.3 nbrk 10: #include <arch/sam7s64/dev/at91sam7.h>
1.1 nbrk 11:
12: /*
13: * SPI driver.
14: */
15:
1.2 nbrk 16: struct saspi_dd {
17: struct spi_bus_handle sd_sbh;
18:
19: struct bus_handle *sd_bhp;
20: };
21:
22:
1.1 nbrk 23: int saspi_attach(struct device *, uint32_t, uint8_t);
1.3 nbrk 24: void saspi_init(struct saspi_dd *ddp);
25: uint8_t saspi_transmit(void *selfdd, uint8_t data);
1.4 ! nbrk 26: void saspi_cs_low(void *selfdd);
! 27: void saspi_cs_high(void *selfdd);
1.2 nbrk 28:
1.1 nbrk 29:
1.3 nbrk 30: struct driver saspi_dr = {
1.2 nbrk 31: sizeof(struct saspi_dd),
1.3 nbrk 32: saspi_attach,
1.1 nbrk 33: NULL,
34: NULL
35: };
36:
37:
38: int
1.2 nbrk 39: saspi_attach(struct device *self, uint32_t loc, uint8_t flags)
1.1 nbrk 40: {
1.2 nbrk 41: struct saspi_dd *ddp = self->dv_devdata;
42:
43: /* grab bus_handle */
44: ddp->sd_bhp = self->dv_parent->dv_aux;
45:
1.3 nbrk 46: printf("SAM7 SPI: ");
47: /*
48: * XXX Check if card present and fail if it is not.
49: */
50: /* 'Card Present' on PA15 */
51: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ODR, 1 << 15);
52: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PER, 1 << 15);
53: /* Write Protect' on PA16 */
54: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ODR, 1 << 16);
55: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PER, 1 << 16);
56:
57: if((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDSR) & 1 << 15) == 0)
58: printf("card present; ");
59: else {
60: printf("card is not presented\n");
61:
62: return(-1);
63: }
64: printf("write %s\n", (bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDSR) & 1 << 16) ? "protect" : "allowed");
1.2 nbrk 65:
66: /*
67: * Initialize ourselfes and provide spi_bus_handle to children throught dv_aux.
68: */
1.1 nbrk 69:
1.2 nbrk 70: saspi_init(ddp);
71:
72: ddp->sd_sbh.sb_transmitfunc = saspi_transmit;
1.4 ! nbrk 73: ddp->sd_sbh.sb_cslowfunc = saspi_cs_low;
! 74: ddp->sd_sbh.sb_cshighfunc = saspi_cs_high;
1.3 nbrk 75: ddp->sd_sbh.sb_dd = ddp;
76:
77: self->dv_aux = &ddp->sd_sbh;
78:
1.1 nbrk 79:
80: return(0);
1.2 nbrk 81: }
82:
83:
84: void
85: saspi_init(struct saspi_dd *ddp)
86: {
87: /*
88: * Initialize on-chip SPI controller.
89: */
90:
91: /*
92: * Disassociate SPI chip select, clock and data lines from PIO.
93: *
94: * PA11 - NPCS0
95: * PA12 - MISO
96: * PA13 - MOSI
97: * PA14 - SPCK
98: */
99: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14);
100:
101: /* assign pins to Peripheral A */
102: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ASR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14);
103:
1.4 ! nbrk 104: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_BSR, 0);
! 105:
1.2 nbrk 106: /* reset and enable SPI */
107: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN | AT91C_SPI_SWRST);
108: /* XXX just to be sure */
109: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN);
110:
111: /* set SPI mode to master; disable decoding of Chip Select; PCS 1110 (using fixed CS line) */
1.4 ! nbrk 112: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_MR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | 0x0e << 16); /* XXX 15|16 */
! 113: // bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_MR, 0xe0011); /* XXX 15|16 */
1.2 nbrk 114:
115: /*
116: * Configure Chip Select Register no. 0 (so no offset from SPI_CSR).
117: * CPOL (Clock Polarity) is 0 (SPCK inactive is logic 0);
118: * NCPHA (Clock Phase) is 1;
119: * 8 bits per transfer;
120: * XXX SCBR=4a;
121: */
122: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CSR, AT91C_SPI_NCPHA | 0x4a00);
123:
124: /* enable PDC transfers to/from SPI */
1.3 nbrk 125: // bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PDC_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN);
1.2 nbrk 126: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN);
1.3 nbrk 127:
1.2 nbrk 128: }
129:
130:
131: uint8_t
1.3 nbrk 132: saspi_transmit(void *selfdd, uint8_t data)
1.2 nbrk 133: {
1.3 nbrk 134: struct saspi_dd *ddp = (struct saspi_dd *)selfdd;
1.2 nbrk 135: /*
136: * Shift byte on the SPI bus.
137: */
138: /* wait for Transmit Data Register Empty flag */
139: while((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR) & AT91C_SPI_TDRE) == 0)
140: ;
141:
142: /* okay, send our byte */
143: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_TDR, 0x0000ffff & data);
144:
145: /* wait while Receive Register is full and read it */
1.4 ! nbrk 146: while(((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR)) & AT91C_SPI_RDRF) == 0)
1.2 nbrk 147: ;
148: return( bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_RDR) & 0x0000ffff );
1.4 ! nbrk 149: }
! 150:
! 151:
! 152: void
! 153: saspi_cs_low(void *selfdd)
! 154: {
! 155: struct saspi_dd *ddp = selfdd;
! 156: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_CODR, 1 << 11);
! 157: }
! 158:
! 159:
! 160: void
! 161: saspi_cs_high(void *selfdd)
! 162: {
! 163: struct saspi_dd *ddp = selfdd;
! 164: bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_SODR, 1 << 11);
! 165:
1.1 nbrk 166: }
167:
CVSweb