10
#include <drivers/common/memory.h>
11
#include <drivers/spi.h>
12
#include <embox/unit.h>
13
#include <framework/mod/options.h>
17
#include <kernel/printk.h>
21
#include <drivers/dma/pl330_dma.h>
23
#include <drivers/gpio/gpio.h>
24
#include <drivers/gpio/bcm283x/bcm283x_gpio.h>
25
#include <drivers/spi.h>
27
#include "bcm283x_spi0.h"
28
#include "bcm283x_spi_dev.h"
30
#define PBASE OPTION_GET(NUMBER,base_addr)
31
#define SPI_BUS_CLOCK_DIVISOR OPTION_GET(NUMBER,spi_bus_clock_divisor)
32
#define SPI_INT0 OPTION_GET(NUMBER,spi_int)
37
#define MEM_ALGN_256 (0x00000020)
41
#define DRIVER_TESTING
42
#define PIN ( 1 << 25 )
53
#define DLEN_NO_DMA_VALUE 2;
55
struct bcm283x_spi_regs {
89
#define REGS_SPI0 ((struct bcm283x_spi_regs *)(PBASE))
90
#define BCM283X_SPI0_TX_FIFO_LEN (16*sizeof(uint32_t))
91
#define BCM283X_SPI0_RX_FIFO_LEN (16*sizeof(uint32_t))
92
#define BCM283X_SPI0_TX_FIFO_FL (4*sizeof(uint32_t))
93
#define BCM283X_SPI0_RX_FIFO_HW (3*sizeof(uint32_t))
95
#define BCM283X_PRIV(x) ((struct bcm283x_spi_dev *)(x)->priv)
97
static int bcm283x_spi0_init(void) {
98
uint32_t pins_spi_Alt0 =( 1 << 7 ) | ( 1 << 8 ) | ( 1 << 9 ) | ( 1 << 10 ) | ( 1 << 11 );
99
gpio_setup_mode(GPIO_PORT_A, pins_spi_Alt0, GPIO_MODE_OUT_ALTERNATE | GPIO_ALTERNATE(GFAlt0) );
102
gpio_setup_mode(GPIO_PORT_A, PIN, GPIO_MODE_OUTPUT);
108
REGS_SPI0->cs = SPI0_CS(0);
109
REGS_SPI0->clk = SPI_BUS_CLOCK_DIVISOR;
110
REGS_SPI0->dlen = DLEN_NO_DMA_VALUE;
115
static irq_return_t bcm283x_spi_intrd_irq_handler(unsigned int irq_nr, void *data);
117
static int bcm283x_spi0_attach(struct spi_device *dev) {
120
if( !(REGS_SPI0->cs & SPI0_CS_INTD) && !(REGS_SPI0->cs & SPI0_CS_INTR) ) {
121
res = irq_attach(SPI_INT0, bcm283x_spi_intrd_irq_handler, 0x00, dev, "SPI0 IRQ");
126
static int bcm283x_spi0_select(struct spi_device *dev, int cs) {
128
if (cs < 0 || cs > 3) {
129
log_error("Only cs=0..3 are avalable!");
132
if( dev->flags & SPI_CS_ACTIVE ) {
134
if( dev->flags & SPI_CS_INACTIVE ) {
138
if( dev->flags & SPI_CS_IRQD ) {
139
res = bcm283x_spi0_attach(dev);
140
REGS_SPI0->cs |= SPI0_CS_INTD;
142
if( dev->flags & SPI_CS_IRQR ) {
143
res = bcm283x_spi0_attach(dev);
144
REGS_SPI0->cs |= SPI0_CS_INTR;
147
if( !(dev->flags & SPI_CS_IRQR) && !(dev->flags & SPI_CS_IRQD)
148
&& irq_nr_valid(SPI_INT0) == 0 ) {
149
res = irq_detach(SPI_INT0, dev);
153
if( dev->flags & SPI_CS_DMAEN
154
&& !(REGS_SPI0->cs & SPI0_CS_DMAEN) ) {
155
assert( BCM283X_PRIV(dev)->dma_chan_out != BCM283X_PRIV(dev)->dma_chan_in );
157
REGS_SPI0->cs |= SPI0_CS_DMAEN;
158
REGS_SPI0->dc = BCM283X_PRIV(dev)->dma_levels;
163
dma_config_extended(BCM283X_PRIV(dev)->dma_chan_in, NULL, DMA_CS_PANIC_PRIORITY(0x0C) | DMA_CS_PRIORITY(0x06) );
165
dma_config_extended(BCM283X_PRIV(dev)->dma_chan_out, BCM283X_PRIV(dev)->dma_complete,
166
DMA_CS_PANIC_PRIORITY(0x0C) | DMA_CS_PRIORITY(0x06));
171
if( !(dev->flags & SPI_CS_DMAEN) && (REGS_SPI0->cs & SPI0_CS_DMAEN) ) {
172
dma_config_extended(BCM283X_PRIV(dev)->dma_chan_out, NULL, 0x00);
173
REGS_SPI0->cs &= ~( SPI0_CS_DMAEN );
177
REGS_SPI0->cs &= ~(SPI0_CS_CPOL | SPI0_CS_CPHA);
178
if(dev->flags & SPI_CS_MODE(SPI_MODE_1)) REGS_SPI0->cs |= SPI0_CS_CPHA;
179
if(dev->flags & SPI_CS_MODE(SPI_MODE_2)) REGS_SPI0->cs |= SPI0_CS_CPOL;
182
if( (dev->flags >> 16) ) {
183
REGS_SPI0->clk = (dev->flags >> 16);
187
REGS_SPI0->cs &= ~SPI0_CS(0xFF);
188
REGS_SPI0->cs |= SPI0_CS(cs);
195
static int bcm283x_spi0_do_transfer(struct spi_device *dev, uint8_t *inbuf
196
, uint8_t *outbuf, int tx_count, int rx_count) {
202
while ( ( tx_cnt < tx_count && inbuf != NULL )
203
|| (rx_cnt < rx_count && outbuf != NULL ) ) {
204
if(tx_cnt < tx_count ) {
205
if( inbuf != NULL ) {
207
while( !(REGS_SPI0->cs & SPI0_CS_TXD) ) {
209
gpio_set(GPIO_PORT_A, PIN, GPIO_PIN_HIGH );
210
gpio_set(GPIO_PORT_A, PIN, GPIO_PIN_LOW );
213
REGS_SPI0->fifo = inbuf[tx_cnt++];
216
REGS_SPI0->fifo = 0x00;
219
if( rx_cnt < rx_count && outbuf != NULL ) {
220
while ( !(REGS_SPI0->cs & SPI0_CS_RXD) );
221
outbuf[rx_cnt++] = REGS_SPI0->fifo;
225
while( REGS_SPI0->cs & SPI0_CS_RXD ) {
227
discard += REGS_SPI0->fifo;
230
while( !(REGS_SPI0->cs & SPI0_CS_DONE) ) {
232
gpio_set(GPIO_PORT_A, PIN, GPIO_PIN_HIGH );
233
gpio_set(GPIO_PORT_A, PIN, GPIO_PIN_LOW );
238
return max(tx_cnt, rx_cnt);
242
static irq_return_t bcm283x_spi_intrd_irq_handler(unsigned int irq_nr, void *data) {
243
irq_return_t ret = IRQ_HANDLED;
244
struct spi_device *dev = (struct spi_device*) data;
247
if ((REGS_SPI0->cs & (SPI0_CS_DONE | SPI0_CS_TA))
248
&& BCM283X_PRIV(dev)->count > 0) {
249
BCM283X_PRIV(dev)->count -= bcm283x_spi0_do_transfer(dev,
250
BCM283X_PRIV(dev)->in, BCM283X_PRIV(dev)->out,
251
min(BCM283X_SPI0_TX_FIFO_FL, BCM283X_PRIV(dev)->count),
252
min(BCM283X_SPI0_TX_FIFO_FL, BCM283X_PRIV(dev)->count));
253
if (BCM283X_PRIV(dev)->count <= 0) {
254
REGS_SPI0->cs &= ~SPI0_CS_TA;
256
if (BCM283X_PRIV(dev)->send_complete && BCM283X_PRIV(dev)->count <= 0) {
257
BCM283X_PRIV(dev)->send_complete(dev, BCM283X_PRIV(dev)->count);
262
if ((REGS_SPI0->cs & SPI0_CS_RXR)) {
263
BCM283X_PRIV(dev)->count = bcm283x_spi0_do_transfer(dev,
264
BCM283X_PRIV(dev)->in, BCM283X_PRIV(dev)->out,
265
min(BCM283X_SPI0_RX_FIFO_HW, BCM283X_PRIV(dev)->count),
266
min(BCM283X_SPI0_RX_FIFO_HW, BCM283X_PRIV(dev)->count));
267
if (BCM283X_PRIV(dev)->received_data && BCM283X_PRIV(dev)->count > 0) {
268
BCM283X_PRIV(dev)->send_complete(dev, BCM283X_PRIV(dev)->count);
274
static struct dma_ctrl_blk *bcm283x_init_dma_block_spi_in(struct spi_device *dev,
275
struct dma_mem_handle *mem_handle, uint32_t offset, void *src, uint32_t bytes,
276
struct dma_ctrl_blk *next_conbk, bool int_enable) {
278
assert( (((uint32_t)(mem_handle->physical_addr) + offset) & ~MEM_ALGN_256 ) == ((uint32_t)(mem_handle->physical_addr) + offset));
280
struct dma_ctrl_blk *cbp = (struct dma_ctrl_blk *)(mem_handle->physical_addr + offset);
281
cbp->ti = DMA_TI_PERMAP(DMA_PERMAP_SPI_TX) | DMA_TI_SRC_INC | DMA_TI_DEST_DREQ | DMA_TI_WAIT_RESP;
282
cbp->dest_ad = (uint32_t)DMA_PERF_TO_BUS((uint32_t)&(REGS_SPI0->fifo));
285
cbp->source_ad = (uint32_t)DMA_PHYS_TO_BUS((uint32_t)src);
286
cbp->txfr_len = bytes;
287
cbp->nextconbk = ( next_conbk == NULL ? 0x00 : (uint32_t)DMA_PHYS_TO_BUS((uint32_t)next_conbk) );
290
cbp->ti |= DMA_TI_INTEN;
293
cbp->ti &= ~DMA_TI_INTEN;
299
static struct dma_ctrl_blk *bcm283x_init_dma_block_spi_out(struct spi_device *dev,
300
struct dma_mem_handle *mem_handle, uint32_t offset, void *dest, uint32_t bytes,
301
struct dma_ctrl_blk *next_conbk, bool int_enable) {
303
assert( (((uint32_t)(mem_handle->physical_addr) + offset) & ~MEM_ALGN_256 ) == ((uint32_t)(mem_handle->physical_addr) + offset));
305
struct dma_ctrl_blk *cbp = (struct dma_ctrl_blk *)(mem_handle->physical_addr + offset);
306
cbp->ti = DMA_TI_PERMAP(DMA_PERMAP_SPI_RX) | DMA_TI_DEST_INC | DMA_TI_SRC_DREQ | DMA_TI_WAIT_RESP;
307
cbp->source_ad = (uint32_t)DMA_PERF_TO_BUS((uint32_t)&(REGS_SPI0->fifo));
310
cbp->dest_ad = (uint32_t)DMA_PHYS_TO_BUS((uint32_t)dest);
311
cbp->txfr_len = bytes;
312
cbp->nextconbk = ( next_conbk == NULL ? 0x00 : (uint32_t)DMA_PHYS_TO_BUS((uint32_t)next_conbk) );
315
cbp->ti |= DMA_TI_INTEN;
318
cbp->ti &= ~DMA_TI_INTEN;
331
static int bcm283x_spi0_transfer(struct spi_device *dev, uint8_t *inbuf, uint8_t *outbuf, int count) {
334
if( ( (REGS_SPI0->cs & SPI0_CS_INTD) || (REGS_SPI0->cs & SPI0_CS_INTR) ) ) {
337
BCM283X_PRIV(dev)->count = -1 * count;
338
BCM283X_PRIV(dev)->in = inbuf;
339
BCM283X_PRIV(dev)->out = outbuf;
340
REGS_SPI0->dlen = DLEN_NO_DMA_VALUE;
341
REGS_SPI0->cs |= SPI0_CS_CLEAR( SPI0_tx_fifo | SPI0_rx_fifo ) | SPI0_CS_TA;
345
BCM283X_PRIV(dev)->count -= bcm283x_spi0_do_transfer(dev, inbuf, outbuf, min(BCM283X_SPI0_TX_FIFO_FL,count), BCM283X_SPI0_RX_FIFO_HW);
346
REGS_SPI0->cs &= ~SPI0_CS_TA;
352
if(REGS_SPI0->cs & SPI0_CS_DMAEN) {
353
REGS_SPI0->dlen = count;
356
dma_transfer_conbk(BCM283X_PRIV(dev)->dma_chan_out, (volatile struct dma_ctrl_blk *)outbuf);
358
dma_transfer_conbk(BCM283X_PRIV(dev)->dma_chan_in, (volatile struct dma_ctrl_blk *)inbuf);
360
REGS_SPI0->cs |= SPI0_CS_ADCS | SPI0_CS_CLEAR( SPI0_tx_fifo | SPI0_rx_fifo ) | SPI0_CS_TA;
363
REGS_SPI0->cs |= SPI0_CS_CLEAR( SPI0_tx_fifo | SPI0_rx_fifo ) | SPI0_CS_TA;
366
REGS_SPI0->dlen = DLEN_NO_DMA_VALUE;
368
bcm283x_spi0_do_transfer(dev, inbuf, outbuf, count, count);
369
REGS_SPI0->cs &= ~SPI0_CS_TA;
374
struct spi_ops bcm283x_spi0_ops = {
375
.select = bcm283x_spi0_select,
376
.transfer = bcm283x_spi0_transfer,
379
PERIPH_MEMORY_DEFINE(bcm283x_spi0, PBASE, sizeof(struct bcm283x_spi_regs));
381
static struct bcm283x_spi_dev bcm283x_spi_dev = {
383
.init_dma_block_spi_in = bcm283x_init_dma_block_spi_in,
384
.init_dma_block_spi_out = bcm283x_init_dma_block_spi_out
387
SPI_DEV_DEF("spi0", &bcm283x_spi0_ops, &bcm283x_spi_dev, 0);
389
EMBOX_UNIT_INIT(bcm283x_spi0_init);