/* For SSC SPI as MASTER, TX/RX is handled as follows: 1. Fill the TX_FIFO with up to (SSC_TXFIFO_SIZE - 1) words, and enable TX_FIFO_EMPTY interrupts. 2. When the last word of TX_FIFO is copied to the shift register, a TX_FIFO_EMPTY interrupt is issued, and the last word will *start* being shifted out/in. 3. On receiving a TX_FIFO_EMPTY interrupt, copy all *available* received words from the RX_FIFO. Note, depending on the time taken to shift out/in the 'last' word compared to the IRQ latency, the 'last' word may not be available yet in the RX_FIFO. 4. If there are more bytes to TX, refill the TX_FIFO. Since the 'last' word from the previous iteration may still be (or about to be) in the RX_FIFO, only add up to (SSC_TXFIFO_SIZE - 1) words. If all bytes have been transmitted, disable TX and set completion. 5. If we are interested in the received data, check to see if the 'last' word has been received. If not, then wait the period of shifting 1 word, then read the 'last' word from the RX_FIFO. */ static void spi_stmssc_fill_tx_fifo(struct spi_stm_ssc *st_ssc) { union { u8 bytes[4]; u32 dword; } tmp = {.dword = 0,}; int i; for (i = 0; i < SSC_TXFIFO_SIZE - 1 && st_ssc->tx_bytes_pending > 0; i++) { if (st_ssc->bits_per_word > 8) { if (st_ssc->tx_ptr) { tmp.bytes[1] = *st_ssc->tx_ptr++; tmp.bytes[0] = *st_ssc->tx_ptr++; } else { tmp.bytes[1] = 0; tmp.bytes[0] = 0; } st_ssc->tx_bytes_pending -= 2; } else { if (st_ssc->tx_ptr) tmp.bytes[0] = *st_ssc->tx_ptr++; else tmp.bytes[0] = 0; st_ssc->tx_bytes_pending--; } ssc_store32(st_ssc, SSC_TBUF, tmp.dword); } } static int spi_stmssc_rx_mopup(struct spi_stm_ssc *st_ssc) { unsigned long word_period_ns; u32 rx_fifo_status; union { u8 bytes[4]; u32 dword; } tmp = {.dword = 0,}; dgb_print("\n"); word_period_ns = 1000000000 / st_ssc->baud; word_period_ns *= st_ssc->bits_per_word; /* delay for period equivalent to shifting 1 complete word out of and into shift register */ ndelay(word_period_ns); /* Check 'last' word is actually there! */ rx_fifo_status = ssc_load32(st_ssc, SSC_RX_FSTAT); if (rx_fifo_status == 1) { tmp.dword = ssc_load32(st_ssc, SSC_RBUF); if (st_ssc->bits_per_word > 8) { if (st_ssc->rx_ptr) { *st_ssc->rx_ptr++ = tmp.bytes[1]; *st_ssc->rx_ptr++ = tmp.bytes[0]; } st_ssc->rx_bytes_pending -= 2; } else { if (st_ssc->rx_ptr) *st_ssc->rx_ptr++ = tmp.bytes[0]; st_ssc->rx_bytes_pending--; } } else { dgb_print("should only be one word in RX_FIFO" "(rx_fifo_status = %d)\n", rx_fifo_status); } return 0; } static int spi_stmssc_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { struct spi_stm_ssc *st_ssc; dgb_print("\n"); st_ssc = spi_master_get_devdata(spi->master); st_ssc->tx_ptr = t->tx_buf; st_ssc->rx_ptr = t->rx_buf; st_ssc->tx_bytes_pending = t->len; st_ssc->rx_bytes_pending = t->len; INIT_COMPLETION(st_ssc->done); /* fill TX_FIFO */ spi_stmssc_fill_tx_fifo(st_ssc); /* enable TX_FIFO_EMPTY interrupts */ ssc_store32(st_ssc, SSC_IEN, SSC_IEN_TIEN); /* wait for all bytes to be transmitted*/ wait_for_completion(&st_ssc->done); /* check 'last' byte has been received */ /* NOTE: need to read rxbuf, even if ignoring the result! */ if (st_ssc->rx_bytes_pending) spi_stmssc_rx_mopup(st_ssc); /* disable ints */ ssc_store32(st_ssc, SSC_IEN, 0x0); return t->len - st_ssc->tx_bytes_pending; } static irqreturn_t spi_stmssc_irq(int irq, void *dev_id) { struct spi_stm_ssc *st_ssc = (struct spi_stm_ssc *)dev_id; unsigned int rx_fifo_status; u32 ssc_status; union { u8 bytes[4]; u32 dword; } tmp = {.dword = 0,}; ssc_status = ssc_load32(st_ssc, SSC_STA); /* FIFO_TX_EMPTY */ if (ssc_status & SSC_STA_TIR) { /* Find number of words available in RX_FIFO: 8 if RX_FIFO_FULL, else SSC_RX_FSTAT (0-7) */ rx_fifo_status = (ssc_status & SSC_STA_RIR) ? 8 : ssc_load32(st_ssc, SSC_RX_FSTAT); /* Read all available words from RX_FIFO */ while (rx_fifo_status) { tmp.dword = ssc_load32(st_ssc, SSC_RBUF); if (st_ssc->bits_per_word > 8) { if (st_ssc->rx_ptr) { *st_ssc->rx_ptr++ = tmp.bytes[1]; *st_ssc->rx_ptr++ = tmp.bytes[0]; } st_ssc->rx_bytes_pending -= 2; } else { if (st_ssc->rx_ptr) *st_ssc->rx_ptr++ = tmp.bytes[0]; st_ssc->rx_bytes_pending--; } rx_fifo_status = ssc_load32(st_ssc, SSC_RX_FSTAT); } /* See if there is more data to send */ if (st_ssc->tx_bytes_pending > 0) spi_stmssc_fill_tx_fifo(st_ssc); else { /* No more data to send */ ssc_store32(st_ssc, SSC_IEN, 0x0); complete(&st_ssc->done); } } return IRQ_HANDLED; } static int __init spi_stm_probe(struct platform_device *pdev) { struct ssc_pio_t *pio_info = (struct ssc_pio_t *)pdev->dev.platform_data; struct spi_master *master; struct resource *res; struct spi_stm_ssc *st_ssc; u32 reg; master = spi_alloc_master(&pdev->dev, sizeof(struct spi_stm_ssc)); if (!master) return -ENOMEM; platform_set_drvdata(pdev, master); st_ssc = spi_master_get_devdata(master); st_ssc->bitbang.master = spi_master_get(master); st_ssc->bitbang.setup_transfer = spi_stmssc_setup_transfer; st_ssc->bitbang.txrx_bufs = spi_stmssc_txrx_bufs; st_ssc->bitbang.master->setup = spi_stmssc_setup; if (pio_info->chipselect) st_ssc->bitbang.chipselect = (void (*) (struct spi_device *, int)) pio_info->chipselect; else st_ssc->bitbang.chipselect = spi_stpio_chipselect; master->num_chipselect = SPI_NO_CHIPSELECT + 1; master->bus_num = pdev->id; init_completion(&st_ssc->done); /* Get resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; if (!devm_request_mem_region(&pdev->dev, res->start, res->end - res->start, "spi")) { printk(KERN_ERR NAME " Request mem 0x%x region failed\n", res->start); return -ENOMEM; } st_ssc->base = (unsigned long) devm_ioremap_nocache(&pdev->dev, res->start, res->end - res->start); if (!st_ssc->base) { printk(KERN_ERR NAME " Request iomem 0x%x region failed\n", res->start); return -ENOMEM; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { printk(KERN_ERR NAME " Request irq %d failed\n", res->start); return -ENODEV; } if (devm_request_irq(&pdev->dev, res->start, spi_stmssc_irq, IRQF_DISABLED, "stspi", st_ssc) < 0) { printk(KERN_ERR NAME " Request irq failed\n"); return -ENODEV; } /* Check for hard wired SSC which doesn't use PIO pins */ if (pio_info->pio[0].pio_port == SSC_NO_PIO) goto ssc_hard_wired; /* Get PIO pins */ pio_info->clk = stpio_request_set_pin(pio_info->pio[0].pio_port, pio_info->pio[0].pio_pin, "SPI Clock", STPIO_BIDIR, 0); if (!pio_info->clk) { printk(KERN_ERR NAME " Failed to allocate clk pin (PIO%d[%d])\n", pio_info->pio[0].pio_port, pio_info->pio[0].pio_pin); return -ENODEV; } pio_info->sdout = stpio_request_set_pin(pio_info->pio[1].pio_port, pio_info->pio[1].pio_pin, "SPI Data out", STPIO_BIDIR, 0); if (!pio_info->sdout) { printk(KERN_ERR NAME " Failed to allocate sdo pin (PIO%d[%d])\n", pio_info->pio[1].pio_port, pio_info->pio[1].pio_pin); return -ENODEV; } pio_info->sdin = stpio_request_pin(pio_info->pio[2].pio_port, pio_info->pio[2].pio_pin, "SPI Data in", STPIO_IN); if (!pio_info->sdin) { printk(KERN_ERR NAME " Failed to allocate sdi pin (PIO%d[%d])\n", pio_info->pio[2].pio_port, pio_info->pio[2].pio_pin); return -ENODEV; } ssc_hard_wired: /* Disable I2C and Reset SSC */ ssc_store32(st_ssc, SSC_I2C, 0x0); reg = ssc_load16(st_ssc, SSC_CTL); reg |= SSC_CTL_SR; ssc_store32(st_ssc, SSC_CTL, reg); udelay(1); reg = ssc_load32(st_ssc, SSC_CTL); reg &= ~SSC_CTL_SR; ssc_store32(st_ssc, SSC_CTL, reg); /* Set SSC into slave mode before reconfiguring PIO pins */ reg = ssc_load32(st_ssc, SSC_CTL); reg &= ~SSC_CTL_MS; ssc_store32(st_ssc, SSC_CTL, reg); if (pio_info->pio[0].pio_port == SSC_NO_PIO) goto ssc_hard_wired2; #ifdef CONFIG_CPU_SUBTYPE_STX7141 stpio_configure_pin(pio_info->clk, STPIO_OUT); stpio_configure_pin(pio_info->sdout, STPIO_OUT); stpio_configure_pin(pio_info->sdin, STPIO_IN); #else stpio_configure_pin(pio_info->clk, STPIO_ALT_OUT); stpio_configure_pin(pio_info->sdout, STPIO_ALT_OUT); stpio_configure_pin(pio_info->sdin, STPIO_IN); #endif ssc_hard_wired2: st_ssc->fcomms = clk_get_rate(clk_get(NULL, "comms_clk"));; /* Start bitbang worker */ if (spi_bitbang_start(&st_ssc->bitbang)) { printk(KERN_ERR NAME " The SPI Core refuses the spi_stm_ssc adapter\n"); return -1; } printk(KERN_INFO NAME ": Registered SPI Bus %d: " "CLK[%d,%d] SDOUT[%d, %d] SDIN[%d, %d]\n", master->bus_num, pio_info->pio[0].pio_port, pio_info->pio[0].pio_pin, pio_info->pio[1].pio_port, pio_info->pio[1].pio_pin, pio_info->pio[2].pio_port, pio_info->pio[2].pio_pin); return 0; } static int spi_stm_remove(struct platform_device *pdev) { struct spi_stm_ssc *st_ssc; struct spi_master *master; struct ssc_pio_t *pio_info = (struct ssc_pio_t *)pdev->dev.platform_data; master = platform_get_drvdata(pdev); st_ssc = spi_master_get_devdata(master); spi_bitbang_stop(&st_ssc->bitbang); if (pio_info->sdin) { stpio_free_pin(pio_info->sdin); stpio_free_pin(pio_info->clk); stpio_free_pin(pio_info->sdout); } return 0; } static struct platform_driver spi_hw_driver = { .driver.name = "spi_st_ssc", .driver.owner = THIS_MODULE, .probe = spi_stm_probe, .remove = spi_stm_remove, }; static int __init spi_stm_ssc_init(void) { printk(KERN_INFO NAME ": SSC SPI Driver\n"); return platform_driver_register(&spi_hw_driver); } static void __exit spi_stm_ssc_exit(void) { dgb_print("\n"); platform_driver_unregister(&spi_hw_driver); } module_init(spi_stm_ssc_init); module_exit(spi_stm_ssc_exit); MODULE_AUTHOR("STMicroelectronics <www.st.com>"); MODULE_DESCRIPTION("STM SSC SPI driver"); MODULE_LICENSE("GPL");
static int __init spi_stm_probe(struct platform_device *pdev) { struct stm_plat_ssc_data *plat_data = pdev->dev.platform_data; struct spi_master *master; struct resource *res; struct spi_stm *spi_stm; u32 reg; int status = 0; master = spi_alloc_master(&pdev->dev, sizeof(struct spi_stm)); if (!master) { dev_err(&pdev->dev, "failed to allocate spi master\n"); status = -ENOMEM; goto err0; } platform_set_drvdata(pdev, master); spi_stm = spi_master_get_devdata(master); spi_stm->bitbang.master = spi_master_get(master); spi_stm->bitbang.setup_transfer = spi_stm_setup_transfer; spi_stm->bitbang.txrx_bufs = spi_stm_txrx_bufs; spi_stm->bitbang.master->setup = spi_stm_setup; spi_stm->bitbang.master->cleanup = spi_stm_cleanup; if (plat_data->spi_chipselect) spi_stm->bitbang.chipselect = plat_data->spi_chipselect; else spi_stm->bitbang.chipselect = spi_stm_gpio_chipselect; /* the spi->mode bits understood by this driver: */ master->mode_bits = MODEBITS; /* chip_select field of spi_device is declared as u8 and therefore * limits number of GPIOs that can be used as a CS line. Sorry. */ master->num_chipselect = sizeof(((struct spi_device *)0)->chip_select) * 256; master->bus_num = pdev->id; init_completion(&spi_stm->done); /* Get resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to find IOMEM resource\n"); status = -ENOENT; goto err1; } spi_stm->r_mem = *res; if (!request_mem_region(res->start, res->end - res->start + 1, NAME)) { dev_err(&pdev->dev, "request memory region failed [0x%x]\n", res->start); status = -EBUSY; goto err1; } spi_stm->base = ioremap_nocache(res->start, res->end - res->start + 1); if (!spi_stm->base) { dev_err(&pdev->dev, "ioremap memory failed [0x%x]\n", res->start); status = -ENXIO; goto err2; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(&pdev->dev, "failed to find IRQ resource\n"); status = -ENOENT; goto err3; } spi_stm->r_irq = *res; if (request_irq(res->start, spi_stm_irq, IRQF_DISABLED, dev_name(&pdev->dev), spi_stm)) { dev_err(&pdev->dev, "irq request failed\n"); status = -EBUSY; goto err3; } spi_stm->pad_state = stm_pad_claim(plat_data->pad_config, dev_name(&pdev->dev)); if (!spi_stm->pad_state) { dev_err(&pdev->dev, "pads request failed\n"); status = -EBUSY; goto err4; } /* Disable I2C and Reset SSC */ ssc_store32(spi_stm, SSC_I2C, 0x0); reg = ssc_load16(spi_stm, SSC_CTL); reg |= SSC_CTL_SR; ssc_store32(spi_stm, SSC_CTL, reg); udelay(1); reg = ssc_load32(spi_stm, SSC_CTL); reg &= ~SSC_CTL_SR; ssc_store32(spi_stm, SSC_CTL, reg); /* Set SSC into slave mode before reconfiguring PIO pins */ reg = ssc_load32(spi_stm, SSC_CTL); reg &= ~SSC_CTL_MS; ssc_store32(spi_stm, SSC_CTL, reg); spi_stm->clk = clk_get(&pdev->dev, "comms_clk"); if (!spi_stm->clk) { dev_err(&pdev->dev, "Comms clock not found!\n"); goto err5; } clk_enable(spi_stm->clk); /* Start "bitbang" worker */ status = spi_bitbang_start(&spi_stm->bitbang); if (status) { dev_err(&pdev->dev, "bitbang start failed [%d]\n", status); goto err5; } dev_info(&pdev->dev, "registered SPI Bus %d\n", master->bus_num); return status; err5: stm_pad_release(spi_stm->pad_state); err4: free_irq(spi_stm->r_irq.start, spi_stm); err3: iounmap(spi_stm->base); err2: release_mem_region(spi_stm->r_mem.start, resource_size(&spi_stm->r_mem)); err1: spi_master_put(spi_stm->bitbang.master); platform_set_drvdata(pdev, NULL); err0: return status; }