1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
10 #include <mach/lpc21xx_gpio.h>
11 #include <mach/lpc21xx_regs.h>
12 #include <drivers/spi.h>
13 #include <drivers/lpc_spi.h>
17 static int lpc_spi_change_device(struct spi_device
*device
)
19 struct lpc_spi
*spi
= device
->master
->spi
;
20 struct lpc_spi_data
*data
= device
->master
->spi_data
;
24 if (device
->mode
& SPI_CPHA
)
26 if (device
->mode
& SPI_CPOL
)
28 spi_cr
|= 1<<5; /* MSTR master mode */
29 if (device
->mode
& SPI_LSB
)
30 spi_cr
|= 1<<6; /* LSBF LSB first */
32 spi_cr
|= 1<<7; /* SPIE interrupt enable */
33 spi
->SPINT
= 1; /* clear old interrupt */
37 tmp
= (data
->pclk
+ device
->clock
-1) / device
->clock
;
43 /* this limits spi clock to pclk/8 */
46 gpio_init(device
->cs_pin
, GPIO_OUTPUT
, 1);
51 static void lpc_spi_tx(struct lpc_spi
*spi
, u8 data
)
56 static struct spi0_irq_data
{
57 struct spi_device
*device
;
58 struct spi_transfer
*transfer
;
62 void __interrupt
spi0_handler()
64 struct lpc_spi
*spi
= spi0_irq_data
.device
->master
->spi
;
65 struct spi_transfer
*transfer
= spi0_irq_data
.transfer
;
66 int pos
= spi0_irq_data
.pos
;
68 spi
->SPINT
= 1; /* clear spi interrupt */
69 VICVectAddr
= 0; /* clear pending interrupt */
71 if ((spi
->SPSR
& 1<<7) == 0) {
72 printf("%s: should error out with spi_transfer_finished\n", __func__
);
73 transfer
->error
= -EINVAL
;
74 spi_transfer_finished(spi0_irq_data
.device
, transfer
);
77 transfer
->rx_buf
[pos
++] = spi
->SPDR
;
79 if (pos
>= transfer
->len
) {
80 gpio_set(spi0_irq_data
.device
->cs_pin
, 1);
81 spi_transfer_finished(spi0_irq_data
.device
, transfer
);
83 lpc_spi_tx(spi
, transfer
->tx_buf
[pos
]);
86 spi0_irq_data
.pos
= pos
;
89 static int lpc_spi_transfer(struct spi_device
*device
, struct spi_transfer
*transfer
)
91 struct lpc_spi
*spi
= device
->master
->spi
;
93 spi0_irq_data
.pos
= 0;
94 spi0_irq_data
.device
= device
;
95 spi0_irq_data
.transfer
= transfer
;
97 gpio_set(device
->cs_pin
, 0);
98 lpc_spi_tx(spi
, transfer
->tx_buf
[0]);
100 /* after this, the irq routine picks up */
106 int lpc_spi_register(struct spi_master
*master
)
108 /* some init goes here... which isn't needed in this case */
110 master
->change_device
= lpc_spi_change_device
;
111 master
->transfer
= lpc_spi_transfer
;