11ea29b39SMartin Sperl /* 21ea29b39SMartin Sperl * Driver for Broadcom BCM2835 auxiliary SPI Controllers 31ea29b39SMartin Sperl * 41ea29b39SMartin Sperl * the driver does not rely on the native chipselects at all 51ea29b39SMartin Sperl * but only uses the gpio type chipselects 61ea29b39SMartin Sperl * 71ea29b39SMartin Sperl * Based on: spi-bcm2835.c 81ea29b39SMartin Sperl * 91ea29b39SMartin Sperl * Copyright (C) 2015 Martin Sperl 101ea29b39SMartin Sperl * 111ea29b39SMartin Sperl * This program is free software; you can redistribute it and/or modify 121ea29b39SMartin Sperl * it under the terms of the GNU General Public License as published by 131ea29b39SMartin Sperl * the Free Software Foundation; either version 2 of the License, or 141ea29b39SMartin Sperl * (at your option) any later version. 151ea29b39SMartin Sperl * 161ea29b39SMartin Sperl * This program is distributed in the hope that it will be useful, 171ea29b39SMartin Sperl * but WITHOUT ANY WARRANTY; without even the implied warranty of 181ea29b39SMartin Sperl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 191ea29b39SMartin Sperl * GNU General Public License for more details. 201ea29b39SMartin Sperl */ 211ea29b39SMartin Sperl 221ea29b39SMartin Sperl #include <linux/clk.h> 231ea29b39SMartin Sperl #include <linux/completion.h> 241ea29b39SMartin Sperl #include <linux/delay.h> 251ea29b39SMartin Sperl #include <linux/err.h> 261ea29b39SMartin Sperl #include <linux/interrupt.h> 271ea29b39SMartin Sperl #include <linux/io.h> 281ea29b39SMartin Sperl #include <linux/kernel.h> 291ea29b39SMartin Sperl #include <linux/module.h> 301ea29b39SMartin Sperl #include <linux/of.h> 311ea29b39SMartin Sperl #include <linux/of_address.h> 321ea29b39SMartin Sperl #include <linux/of_device.h> 331ea29b39SMartin Sperl #include <linux/of_gpio.h> 341ea29b39SMartin Sperl #include <linux/of_irq.h> 351ea29b39SMartin Sperl #include <linux/regmap.h> 361ea29b39SMartin Sperl #include <linux/spi/spi.h> 371ea29b39SMartin Sperl #include <linux/spinlock.h> 381ea29b39SMartin Sperl 391ea29b39SMartin Sperl /* 401ea29b39SMartin Sperl * spi register defines 411ea29b39SMartin Sperl * 421ea29b39SMartin Sperl * note there is garbage in the "official" documentation, 431ea29b39SMartin Sperl * so some data is taken from the file: 441ea29b39SMartin Sperl * brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h 451ea29b39SMartin Sperl * inside of: 461ea29b39SMartin Sperl * http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz 471ea29b39SMartin Sperl */ 481ea29b39SMartin Sperl 491ea29b39SMartin Sperl /* SPI register offsets */ 501ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0 0x00 511ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1 0x04 521ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT 0x08 531ea29b39SMartin Sperl #define BCM2835_AUX_SPI_PEEK 0x0C 541ea29b39SMartin Sperl #define BCM2835_AUX_SPI_IO 0x20 551ea29b39SMartin Sperl #define BCM2835_AUX_SPI_TXHOLD 0x30 561ea29b39SMartin Sperl 571ea29b39SMartin Sperl /* Bitfields in CNTL0 */ 581ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 591ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF 601ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 611ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CS 0x000E0000 621ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 631ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 641ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 651ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 661ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 67e9dd4edcSStephan Olbrich #define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400 681ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 69e9dd4edcSStephan Olbrich #define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100 701ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 711ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 721ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F 731ea29b39SMartin Sperl 741ea29b39SMartin Sperl /* Bitfields in CNTL1 */ 751ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 76fe0e2304SStephan Olbrich #define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080 77fe0e2304SStephan Olbrich #define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040 781ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 791ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 801ea29b39SMartin Sperl 811ea29b39SMartin Sperl /* Bitfields in STAT */ 821ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 831ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 841ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 851ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 861ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 871ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 881ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 891ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F 901ea29b39SMartin Sperl 911ea29b39SMartin Sperl /* timeout values */ 921ea29b39SMartin Sperl #define BCM2835_AUX_SPI_POLLING_LIMIT_US 30 931ea29b39SMartin Sperl #define BCM2835_AUX_SPI_POLLING_JIFFIES 2 941ea29b39SMartin Sperl 951ea29b39SMartin Sperl struct bcm2835aux_spi { 961ea29b39SMartin Sperl void __iomem *regs; 971ea29b39SMartin Sperl struct clk *clk; 981ea29b39SMartin Sperl int irq; 991ea29b39SMartin Sperl u32 cntl[2]; 1001ea29b39SMartin Sperl const u8 *tx_buf; 1011ea29b39SMartin Sperl u8 *rx_buf; 1021ea29b39SMartin Sperl int tx_len; 1031ea29b39SMartin Sperl int rx_len; 10472aac02bSMartin Sperl int pending; 1051ea29b39SMartin Sperl }; 1061ea29b39SMartin Sperl 1071ea29b39SMartin Sperl static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg) 1081ea29b39SMartin Sperl { 1091ea29b39SMartin Sperl return readl(bs->regs + reg); 1101ea29b39SMartin Sperl } 1111ea29b39SMartin Sperl 1121ea29b39SMartin Sperl static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg, 1131ea29b39SMartin Sperl u32 val) 1141ea29b39SMartin Sperl { 1151ea29b39SMartin Sperl writel(val, bs->regs + reg); 1161ea29b39SMartin Sperl } 1171ea29b39SMartin Sperl 1181ea29b39SMartin Sperl static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs) 1191ea29b39SMartin Sperl { 1201ea29b39SMartin Sperl u32 data; 1211ea29b39SMartin Sperl int count = min(bs->rx_len, 3); 1221ea29b39SMartin Sperl 1231ea29b39SMartin Sperl data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO); 1241ea29b39SMartin Sperl if (bs->rx_buf) { 12572aac02bSMartin Sperl switch (count) { 12672aac02bSMartin Sperl case 4: 12772aac02bSMartin Sperl *bs->rx_buf++ = (data >> 24) & 0xff; 12872aac02bSMartin Sperl /* fallthrough */ 12972aac02bSMartin Sperl case 3: 13072aac02bSMartin Sperl *bs->rx_buf++ = (data >> 16) & 0xff; 13172aac02bSMartin Sperl /* fallthrough */ 13272aac02bSMartin Sperl case 2: 13372aac02bSMartin Sperl *bs->rx_buf++ = (data >> 8) & 0xff; 13472aac02bSMartin Sperl /* fallthrough */ 13572aac02bSMartin Sperl case 1: 13672aac02bSMartin Sperl *bs->rx_buf++ = (data >> 0) & 0xff; 13772aac02bSMartin Sperl /* fallthrough - no default */ 13872aac02bSMartin Sperl } 1391ea29b39SMartin Sperl } 1401ea29b39SMartin Sperl bs->rx_len -= count; 14172aac02bSMartin Sperl bs->pending -= count; 1421ea29b39SMartin Sperl } 1431ea29b39SMartin Sperl 1441ea29b39SMartin Sperl static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs) 1451ea29b39SMartin Sperl { 1461ea29b39SMartin Sperl u32 data; 1471ea29b39SMartin Sperl u8 byte; 1481ea29b39SMartin Sperl int count; 1491ea29b39SMartin Sperl int i; 1501ea29b39SMartin Sperl 1511ea29b39SMartin Sperl /* gather up to 3 bytes to write to the FIFO */ 1521ea29b39SMartin Sperl count = min(bs->tx_len, 3); 1531ea29b39SMartin Sperl data = 0; 1541ea29b39SMartin Sperl for (i = 0; i < count; i++) { 1551ea29b39SMartin Sperl byte = bs->tx_buf ? *bs->tx_buf++ : 0; 1561ea29b39SMartin Sperl data |= byte << (8 * (2 - i)); 1571ea29b39SMartin Sperl } 1581ea29b39SMartin Sperl 1591ea29b39SMartin Sperl /* and set the variable bit-length */ 1601ea29b39SMartin Sperl data |= (count * 8) << 24; 1611ea29b39SMartin Sperl 1621ea29b39SMartin Sperl /* and decrement length */ 1631ea29b39SMartin Sperl bs->tx_len -= count; 16472aac02bSMartin Sperl bs->pending += count; 1651ea29b39SMartin Sperl 1661ea29b39SMartin Sperl /* write to the correct TX-register */ 1671ea29b39SMartin Sperl if (bs->tx_len) 1681ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data); 1691ea29b39SMartin Sperl else 1701ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data); 1711ea29b39SMartin Sperl } 1721ea29b39SMartin Sperl 1731ea29b39SMartin Sperl static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs) 1741ea29b39SMartin Sperl { 1751ea29b39SMartin Sperl /* disable spi clearing fifo and interrupts */ 1761ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0); 1771ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, 1781ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL0_CLEARFIFO); 1791ea29b39SMartin Sperl } 1801ea29b39SMartin Sperl 1811ea29b39SMartin Sperl static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) 1821ea29b39SMartin Sperl { 1831ea29b39SMartin Sperl struct spi_master *master = dev_id; 1841ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 1851ea29b39SMartin Sperl irqreturn_t ret = IRQ_NONE; 1861ea29b39SMartin Sperl 187bc519d95SRob Herring /* IRQ may be shared, so return if our interrupts are disabled */ 188bc519d95SRob Herring if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & 189bc519d95SRob Herring (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) 190bc519d95SRob Herring return ret; 191bc519d95SRob Herring 1921ea29b39SMartin Sperl /* check if we have data to read */ 1931ea29b39SMartin Sperl while (bs->rx_len && 1941ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 1951ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_RX_EMPTY))) { 1961ea29b39SMartin Sperl bcm2835aux_rd_fifo(bs); 1971ea29b39SMartin Sperl ret = IRQ_HANDLED; 1981ea29b39SMartin Sperl } 1991ea29b39SMartin Sperl 2001ea29b39SMartin Sperl /* check if we have data to write */ 2011ea29b39SMartin Sperl while (bs->tx_len && 20272aac02bSMartin Sperl (bs->pending < 12) && 2031ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 2041ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_TX_FULL))) { 2051ea29b39SMartin Sperl bcm2835aux_wr_fifo(bs); 2061ea29b39SMartin Sperl ret = IRQ_HANDLED; 2071ea29b39SMartin Sperl } 2081ea29b39SMartin Sperl 2091ea29b39SMartin Sperl /* and check if we have reached "done" */ 2101ea29b39SMartin Sperl while (bs->rx_len && 2111ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 2121ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_BUSY))) { 2131ea29b39SMartin Sperl bcm2835aux_rd_fifo(bs); 2141ea29b39SMartin Sperl ret = IRQ_HANDLED; 2151ea29b39SMartin Sperl } 2161ea29b39SMartin Sperl 217f29ab184SStephan Olbrich if (!bs->tx_len) { 218f29ab184SStephan Olbrich /* disable tx fifo empty interrupt */ 219f29ab184SStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | 220f29ab184SStephan Olbrich BCM2835_AUX_SPI_CNTL1_IDLE); 221f29ab184SStephan Olbrich } 222f29ab184SStephan Olbrich 223b4e2adefSStephan Olbrich /* and if rx_len is 0 then disable interrupts and wake up completion */ 2241ea29b39SMartin Sperl if (!bs->rx_len) { 225b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 2261ea29b39SMartin Sperl complete(&master->xfer_completion); 2271ea29b39SMartin Sperl } 2281ea29b39SMartin Sperl 2291ea29b39SMartin Sperl /* and return */ 2301ea29b39SMartin Sperl return ret; 2311ea29b39SMartin Sperl } 2321ea29b39SMartin Sperl 2331ea29b39SMartin Sperl static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master, 2341ea29b39SMartin Sperl struct spi_device *spi, 2351ea29b39SMartin Sperl struct spi_transfer *tfr) 2361ea29b39SMartin Sperl { 2371ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2381ea29b39SMartin Sperl 2391ea29b39SMartin Sperl /* enable interrupts */ 2401ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | 2411ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL1_TXEMPTY | 2421ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL1_IDLE); 2431ea29b39SMartin Sperl 2441ea29b39SMartin Sperl /* and wait for finish... */ 2451ea29b39SMartin Sperl return 1; 2461ea29b39SMartin Sperl } 2471ea29b39SMartin Sperl 2481ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master, 2491ea29b39SMartin Sperl struct spi_device *spi, 2501ea29b39SMartin Sperl struct spi_transfer *tfr) 2511ea29b39SMartin Sperl { 2521ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2531ea29b39SMartin Sperl 2541ea29b39SMartin Sperl /* fill in registers and fifos before enabling interrupts */ 2551ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 2561ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 2571ea29b39SMartin Sperl 2581ea29b39SMartin Sperl /* fill in tx fifo with data before enabling interrupts */ 2591ea29b39SMartin Sperl while ((bs->tx_len) && 26072aac02bSMartin Sperl (bs->pending < 12) && 2611ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 2621ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_TX_FULL))) { 2631ea29b39SMartin Sperl bcm2835aux_wr_fifo(bs); 2641ea29b39SMartin Sperl } 2651ea29b39SMartin Sperl 2661ea29b39SMartin Sperl /* now run the interrupt mode */ 2671ea29b39SMartin Sperl return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr); 2681ea29b39SMartin Sperl } 2691ea29b39SMartin Sperl 2701ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, 2711ea29b39SMartin Sperl struct spi_device *spi, 27272aac02bSMartin Sperl struct spi_transfer *tfr) 2731ea29b39SMartin Sperl { 2741ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2751ea29b39SMartin Sperl unsigned long timeout; 2761ea29b39SMartin Sperl u32 stat; 2771ea29b39SMartin Sperl 2781ea29b39SMartin Sperl /* configure spi */ 2791ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 2801ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 2811ea29b39SMartin Sperl 2821ea29b39SMartin Sperl /* set the timeout */ 2831ea29b39SMartin Sperl timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES; 2841ea29b39SMartin Sperl 2851ea29b39SMartin Sperl /* loop until finished the transfer */ 2861ea29b39SMartin Sperl while (bs->rx_len) { 2871ea29b39SMartin Sperl /* read status */ 2881ea29b39SMartin Sperl stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT); 2891ea29b39SMartin Sperl 2901ea29b39SMartin Sperl /* fill in tx fifo with remaining data */ 2911ea29b39SMartin Sperl if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) { 2921ea29b39SMartin Sperl bcm2835aux_wr_fifo(bs); 2931ea29b39SMartin Sperl continue; 2941ea29b39SMartin Sperl } 2951ea29b39SMartin Sperl 2961ea29b39SMartin Sperl /* read data from fifo for both cases */ 2971ea29b39SMartin Sperl if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) { 2981ea29b39SMartin Sperl bcm2835aux_rd_fifo(bs); 2991ea29b39SMartin Sperl continue; 3001ea29b39SMartin Sperl } 3011ea29b39SMartin Sperl if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) { 3021ea29b39SMartin Sperl bcm2835aux_rd_fifo(bs); 3031ea29b39SMartin Sperl continue; 3041ea29b39SMartin Sperl } 3051ea29b39SMartin Sperl 3061ea29b39SMartin Sperl /* there is still data pending to read check the timeout */ 3071ea29b39SMartin Sperl if (bs->rx_len && time_after(jiffies, timeout)) { 3081ea29b39SMartin Sperl dev_dbg_ratelimited(&spi->dev, 3091ea29b39SMartin Sperl "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n", 3101ea29b39SMartin Sperl jiffies - timeout, 3111ea29b39SMartin Sperl bs->tx_len, bs->rx_len); 3121ea29b39SMartin Sperl /* forward to interrupt handler */ 3131ea29b39SMartin Sperl return __bcm2835aux_spi_transfer_one_irq(master, 3141ea29b39SMartin Sperl spi, tfr); 3151ea29b39SMartin Sperl } 3161ea29b39SMartin Sperl } 3171ea29b39SMartin Sperl 3181ea29b39SMartin Sperl /* and return without waiting for completion */ 3191ea29b39SMartin Sperl return 0; 3201ea29b39SMartin Sperl } 3211ea29b39SMartin Sperl 3221ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one(struct spi_master *master, 3231ea29b39SMartin Sperl struct spi_device *spi, 3241ea29b39SMartin Sperl struct spi_transfer *tfr) 3251ea29b39SMartin Sperl { 3261ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 3271ea29b39SMartin Sperl unsigned long spi_hz, clk_hz, speed; 32872aac02bSMartin Sperl unsigned long spi_used_hz; 3291ea29b39SMartin Sperl 3301ea29b39SMartin Sperl /* calculate the registers to handle 3311ea29b39SMartin Sperl * 3321ea29b39SMartin Sperl * note that we use the variable data mode, which 3331ea29b39SMartin Sperl * is not optimal for longer transfers as we waste registers 3341ea29b39SMartin Sperl * resulting (potentially) in more interrupts when transferring 3351ea29b39SMartin Sperl * more than 12 bytes 3361ea29b39SMartin Sperl */ 3371ea29b39SMartin Sperl 3381ea29b39SMartin Sperl /* set clock */ 3391ea29b39SMartin Sperl spi_hz = tfr->speed_hz; 3401ea29b39SMartin Sperl clk_hz = clk_get_rate(bs->clk); 3411ea29b39SMartin Sperl 3421ea29b39SMartin Sperl if (spi_hz >= clk_hz / 2) { 3431ea29b39SMartin Sperl speed = 0; 3441ea29b39SMartin Sperl } else if (spi_hz) { 3451ea29b39SMartin Sperl speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1; 3461ea29b39SMartin Sperl if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX) 3471ea29b39SMartin Sperl speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; 3481ea29b39SMartin Sperl } else { /* the slowest we can go */ 3491ea29b39SMartin Sperl speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; 3501ea29b39SMartin Sperl } 351b4e2adefSStephan Olbrich /* mask out old speed from previous spi_transfer */ 352b4e2adefSStephan Olbrich bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED); 353b4e2adefSStephan Olbrich /* set the new speed */ 3541ea29b39SMartin Sperl bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; 3551ea29b39SMartin Sperl 3561ea29b39SMartin Sperl spi_used_hz = clk_hz / (2 * (speed + 1)); 3571ea29b39SMartin Sperl 3581ea29b39SMartin Sperl /* set transmit buffers and length */ 3591ea29b39SMartin Sperl bs->tx_buf = tfr->tx_buf; 3601ea29b39SMartin Sperl bs->rx_buf = tfr->rx_buf; 3611ea29b39SMartin Sperl bs->tx_len = tfr->len; 3621ea29b39SMartin Sperl bs->rx_len = tfr->len; 36372aac02bSMartin Sperl bs->pending = 0; 3641ea29b39SMartin Sperl 365d704afffSTrent Piepho /* Calculate the estimated time in us the transfer runs. Note that 366d704afffSTrent Piepho * there are are 2 idle clocks cycles after each chunk getting 367d704afffSTrent Piepho * transferred - in our case the chunk size is 3 bytes, so we 368d704afffSTrent Piepho * approximate this by 9 cycles/byte. This is used to find the number 369d704afffSTrent Piepho * of Hz per byte per polling limit. E.g., we can transfer 1 byte in 370d704afffSTrent Piepho * 30 µs per 300,000 Hz of bus clock. 37172aac02bSMartin Sperl */ 372d704afffSTrent Piepho #define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US) 3731ea29b39SMartin Sperl /* run in polling mode for short transfers */ 374d704afffSTrent Piepho if (tfr->len < spi_used_hz / HZ_PER_BYTE) 37572aac02bSMartin Sperl return bcm2835aux_spi_transfer_one_poll(master, spi, tfr); 3761ea29b39SMartin Sperl 3771ea29b39SMartin Sperl /* run in interrupt mode for all others */ 3781ea29b39SMartin Sperl return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); 379d704afffSTrent Piepho #undef HZ_PER_BYTE 3801ea29b39SMartin Sperl } 3811ea29b39SMartin Sperl 382b4e2adefSStephan Olbrich static int bcm2835aux_spi_prepare_message(struct spi_master *master, 383b4e2adefSStephan Olbrich struct spi_message *msg) 384b4e2adefSStephan Olbrich { 385b4e2adefSStephan Olbrich struct spi_device *spi = msg->spi; 386b4e2adefSStephan Olbrich struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 387b4e2adefSStephan Olbrich 388b4e2adefSStephan Olbrich bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | 389b4e2adefSStephan Olbrich BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | 390b4e2adefSStephan Olbrich BCM2835_AUX_SPI_CNTL0_MSBF_OUT; 391b4e2adefSStephan Olbrich bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; 392b4e2adefSStephan Olbrich 393b4e2adefSStephan Olbrich /* handle all the modes */ 394e9dd4edcSStephan Olbrich if (spi->mode & SPI_CPOL) { 395b4e2adefSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; 396e9dd4edcSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING; 397e9dd4edcSStephan Olbrich } else { 398e9dd4edcSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING; 399e9dd4edcSStephan Olbrich } 400b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 401b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 402b4e2adefSStephan Olbrich 403b4e2adefSStephan Olbrich return 0; 404b4e2adefSStephan Olbrich } 405b4e2adefSStephan Olbrich 406b4e2adefSStephan Olbrich static int bcm2835aux_spi_unprepare_message(struct spi_master *master, 407b4e2adefSStephan Olbrich struct spi_message *msg) 408b4e2adefSStephan Olbrich { 409b4e2adefSStephan Olbrich struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 410b4e2adefSStephan Olbrich 411b4e2adefSStephan Olbrich bcm2835aux_spi_reset_hw(bs); 412b4e2adefSStephan Olbrich 413b4e2adefSStephan Olbrich return 0; 414b4e2adefSStephan Olbrich } 415b4e2adefSStephan Olbrich 4161ea29b39SMartin Sperl static void bcm2835aux_spi_handle_err(struct spi_master *master, 4171ea29b39SMartin Sperl struct spi_message *msg) 4181ea29b39SMartin Sperl { 4191ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 4201ea29b39SMartin Sperl 4211ea29b39SMartin Sperl bcm2835aux_spi_reset_hw(bs); 4221ea29b39SMartin Sperl } 4231ea29b39SMartin Sperl 4241ea29b39SMartin Sperl static int bcm2835aux_spi_probe(struct platform_device *pdev) 4251ea29b39SMartin Sperl { 4261ea29b39SMartin Sperl struct spi_master *master; 4271ea29b39SMartin Sperl struct bcm2835aux_spi *bs; 4281ea29b39SMartin Sperl struct resource *res; 4291ea29b39SMartin Sperl unsigned long clk_hz; 4301ea29b39SMartin Sperl int err; 4311ea29b39SMartin Sperl 4321ea29b39SMartin Sperl master = spi_alloc_master(&pdev->dev, sizeof(*bs)); 4331ea29b39SMartin Sperl if (!master) { 4341ea29b39SMartin Sperl dev_err(&pdev->dev, "spi_alloc_master() failed\n"); 4351ea29b39SMartin Sperl return -ENOMEM; 4361ea29b39SMartin Sperl } 4371ea29b39SMartin Sperl 4381ea29b39SMartin Sperl platform_set_drvdata(pdev, master); 439e9dd4edcSStephan Olbrich master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); 4401ea29b39SMartin Sperl master->bits_per_word_mask = SPI_BPW_MASK(8); 4411ea29b39SMartin Sperl master->num_chipselect = -1; 4421ea29b39SMartin Sperl master->transfer_one = bcm2835aux_spi_transfer_one; 4431ea29b39SMartin Sperl master->handle_err = bcm2835aux_spi_handle_err; 444b4e2adefSStephan Olbrich master->prepare_message = bcm2835aux_spi_prepare_message; 445b4e2adefSStephan Olbrich master->unprepare_message = bcm2835aux_spi_unprepare_message; 4461ea29b39SMartin Sperl master->dev.of_node = pdev->dev.of_node; 4471ea29b39SMartin Sperl 4481ea29b39SMartin Sperl bs = spi_master_get_devdata(master); 4491ea29b39SMartin Sperl 4501ea29b39SMartin Sperl /* the main area */ 4511ea29b39SMartin Sperl res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 4521ea29b39SMartin Sperl bs->regs = devm_ioremap_resource(&pdev->dev, res); 4531ea29b39SMartin Sperl if (IS_ERR(bs->regs)) { 4541ea29b39SMartin Sperl err = PTR_ERR(bs->regs); 4551ea29b39SMartin Sperl goto out_master_put; 4561ea29b39SMartin Sperl } 4571ea29b39SMartin Sperl 4581ea29b39SMartin Sperl bs->clk = devm_clk_get(&pdev->dev, NULL); 459bfc7af6dSYueHaibing if (IS_ERR(bs->clk)) { 4601ea29b39SMartin Sperl err = PTR_ERR(bs->clk); 4611ea29b39SMartin Sperl dev_err(&pdev->dev, "could not get clk: %d\n", err); 4621ea29b39SMartin Sperl goto out_master_put; 4631ea29b39SMartin Sperl } 4641ea29b39SMartin Sperl 46507bce09eSMartin Sperl bs->irq = platform_get_irq(pdev, 0); 4661ea29b39SMartin Sperl if (bs->irq <= 0) { 4671ea29b39SMartin Sperl dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); 4681ea29b39SMartin Sperl err = bs->irq ? bs->irq : -ENODEV; 4691ea29b39SMartin Sperl goto out_master_put; 4701ea29b39SMartin Sperl } 4711ea29b39SMartin Sperl 4721ea29b39SMartin Sperl /* this also enables the HW block */ 4731ea29b39SMartin Sperl err = clk_prepare_enable(bs->clk); 4741ea29b39SMartin Sperl if (err) { 4751ea29b39SMartin Sperl dev_err(&pdev->dev, "could not prepare clock: %d\n", err); 4761ea29b39SMartin Sperl goto out_master_put; 4771ea29b39SMartin Sperl } 4781ea29b39SMartin Sperl 4791ea29b39SMartin Sperl /* just checking if the clock returns a sane value */ 4801ea29b39SMartin Sperl clk_hz = clk_get_rate(bs->clk); 4811ea29b39SMartin Sperl if (!clk_hz) { 4821ea29b39SMartin Sperl dev_err(&pdev->dev, "clock returns 0 Hz\n"); 4831ea29b39SMartin Sperl err = -ENODEV; 4841ea29b39SMartin Sperl goto out_clk_disable; 4851ea29b39SMartin Sperl } 4861ea29b39SMartin Sperl 48707bce09eSMartin Sperl /* reset SPI-HW block */ 48807bce09eSMartin Sperl bcm2835aux_spi_reset_hw(bs); 48907bce09eSMartin Sperl 4901ea29b39SMartin Sperl err = devm_request_irq(&pdev->dev, bs->irq, 4911ea29b39SMartin Sperl bcm2835aux_spi_interrupt, 4921ea29b39SMartin Sperl IRQF_SHARED, 4931ea29b39SMartin Sperl dev_name(&pdev->dev), master); 4941ea29b39SMartin Sperl if (err) { 4951ea29b39SMartin Sperl dev_err(&pdev->dev, "could not request IRQ: %d\n", err); 4961ea29b39SMartin Sperl goto out_clk_disable; 4971ea29b39SMartin Sperl } 4981ea29b39SMartin Sperl 4991ea29b39SMartin Sperl err = devm_spi_register_master(&pdev->dev, master); 5001ea29b39SMartin Sperl if (err) { 5011ea29b39SMartin Sperl dev_err(&pdev->dev, "could not register SPI master: %d\n", err); 5021ea29b39SMartin Sperl goto out_clk_disable; 5031ea29b39SMartin Sperl } 5041ea29b39SMartin Sperl 5051ea29b39SMartin Sperl return 0; 5061ea29b39SMartin Sperl 5071ea29b39SMartin Sperl out_clk_disable: 5081ea29b39SMartin Sperl clk_disable_unprepare(bs->clk); 5091ea29b39SMartin Sperl out_master_put: 5101ea29b39SMartin Sperl spi_master_put(master); 5111ea29b39SMartin Sperl return err; 5121ea29b39SMartin Sperl } 5131ea29b39SMartin Sperl 5141ea29b39SMartin Sperl static int bcm2835aux_spi_remove(struct platform_device *pdev) 5151ea29b39SMartin Sperl { 5161ea29b39SMartin Sperl struct spi_master *master = platform_get_drvdata(pdev); 5171ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 5181ea29b39SMartin Sperl 5191ea29b39SMartin Sperl bcm2835aux_spi_reset_hw(bs); 5201ea29b39SMartin Sperl 5211ea29b39SMartin Sperl /* disable the HW block by releasing the clock */ 5221ea29b39SMartin Sperl clk_disable_unprepare(bs->clk); 5231ea29b39SMartin Sperl 5241ea29b39SMartin Sperl return 0; 5251ea29b39SMartin Sperl } 5261ea29b39SMartin Sperl 5271ea29b39SMartin Sperl static const struct of_device_id bcm2835aux_spi_match[] = { 5281ea29b39SMartin Sperl { .compatible = "brcm,bcm2835-aux-spi", }, 5291ea29b39SMartin Sperl {} 5301ea29b39SMartin Sperl }; 5311ea29b39SMartin Sperl MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match); 5321ea29b39SMartin Sperl 5331ea29b39SMartin Sperl static struct platform_driver bcm2835aux_spi_driver = { 5341ea29b39SMartin Sperl .driver = { 5351ea29b39SMartin Sperl .name = "spi-bcm2835aux", 5361ea29b39SMartin Sperl .of_match_table = bcm2835aux_spi_match, 5371ea29b39SMartin Sperl }, 5381ea29b39SMartin Sperl .probe = bcm2835aux_spi_probe, 5391ea29b39SMartin Sperl .remove = bcm2835aux_spi_remove, 5401ea29b39SMartin Sperl }; 5411ea29b39SMartin Sperl module_platform_driver(bcm2835aux_spi_driver); 5421ea29b39SMartin Sperl 5431ea29b39SMartin Sperl MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux"); 5441ea29b39SMartin Sperl MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>"); 54522bf6cd2SStefan Wahren MODULE_LICENSE("GPL"); 546