1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21ea29b39SMartin Sperl /* 31ea29b39SMartin Sperl * Driver for Broadcom BCM2835 auxiliary SPI Controllers 41ea29b39SMartin Sperl * 51ea29b39SMartin Sperl * the driver does not rely on the native chipselects at all 61ea29b39SMartin Sperl * but only uses the gpio type chipselects 71ea29b39SMartin Sperl * 81ea29b39SMartin Sperl * Based on: spi-bcm2835.c 91ea29b39SMartin Sperl * 101ea29b39SMartin Sperl * Copyright (C) 2015 Martin Sperl 111ea29b39SMartin Sperl */ 121ea29b39SMartin Sperl 131ea29b39SMartin Sperl #include <linux/clk.h> 141ea29b39SMartin Sperl #include <linux/completion.h> 158048d151SMartin Sperl #include <linux/debugfs.h> 161ea29b39SMartin Sperl #include <linux/delay.h> 171ea29b39SMartin Sperl #include <linux/err.h> 181ea29b39SMartin Sperl #include <linux/interrupt.h> 191ea29b39SMartin Sperl #include <linux/io.h> 201ea29b39SMartin Sperl #include <linux/kernel.h> 211ea29b39SMartin Sperl #include <linux/module.h> 221ea29b39SMartin Sperl #include <linux/of.h> 231ea29b39SMartin Sperl #include <linux/of_address.h> 241ea29b39SMartin Sperl #include <linux/of_device.h> 251ea29b39SMartin Sperl #include <linux/of_gpio.h> 261ea29b39SMartin Sperl #include <linux/of_irq.h> 271ea29b39SMartin Sperl #include <linux/regmap.h> 281ea29b39SMartin Sperl #include <linux/spi/spi.h> 291ea29b39SMartin Sperl #include <linux/spinlock.h> 301ea29b39SMartin Sperl 315fd917afSMartin Sperl /* define polling limits */ 321a8fa516Skbuild test robot static unsigned int polling_limit_us = 30; 335fd917afSMartin Sperl module_param(polling_limit_us, uint, 0664); 345fd917afSMartin Sperl MODULE_PARM_DESC(polling_limit_us, 355fd917afSMartin Sperl "time in us to run a transfer in polling mode - if zero no polling is used\n"); 365fd917afSMartin Sperl 371ea29b39SMartin Sperl /* 381ea29b39SMartin Sperl * spi register defines 391ea29b39SMartin Sperl * 401ea29b39SMartin Sperl * note there is garbage in the "official" documentation, 411ea29b39SMartin Sperl * so some data is taken from the file: 421ea29b39SMartin Sperl * brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h 431ea29b39SMartin Sperl * inside of: 441ea29b39SMartin Sperl * http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz 451ea29b39SMartin Sperl */ 461ea29b39SMartin Sperl 471ea29b39SMartin Sperl /* SPI register offsets */ 481ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0 0x00 491ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1 0x04 501ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT 0x08 511ea29b39SMartin Sperl #define BCM2835_AUX_SPI_PEEK 0x0C 521ea29b39SMartin Sperl #define BCM2835_AUX_SPI_IO 0x20 531ea29b39SMartin Sperl #define BCM2835_AUX_SPI_TXHOLD 0x30 541ea29b39SMartin Sperl 551ea29b39SMartin Sperl /* Bitfields in CNTL0 */ 561ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED 0xFFF00000 571ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xFFF 581ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20 591ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CS 0x000E0000 601ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000 611ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000 621ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 631ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 641ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 65e9dd4edcSStephan Olbrich #define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400 661ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 67e9dd4edcSStephan Olbrich #define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100 681ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 691ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 701ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F 711ea29b39SMartin Sperl 721ea29b39SMartin Sperl /* Bitfields in CNTL1 */ 731ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700 74fe0e2304SStephan Olbrich #define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080 75fe0e2304SStephan Olbrich #define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040 761ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002 771ea29b39SMartin Sperl #define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001 781ea29b39SMartin Sperl 791ea29b39SMartin Sperl /* Bitfields in STAT */ 801ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_LVL 0xFF000000 811ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_LVL 0x00FF0000 821ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400 831ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200 841ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100 851ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080 861ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 871ea29b39SMartin Sperl #define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F 881ea29b39SMartin Sperl 891ea29b39SMartin Sperl struct bcm2835aux_spi { 901ea29b39SMartin Sperl void __iomem *regs; 911ea29b39SMartin Sperl struct clk *clk; 921ea29b39SMartin Sperl int irq; 931ea29b39SMartin Sperl u32 cntl[2]; 941ea29b39SMartin Sperl const u8 *tx_buf; 951ea29b39SMartin Sperl u8 *rx_buf; 961ea29b39SMartin Sperl int tx_len; 971ea29b39SMartin Sperl int rx_len; 9872aac02bSMartin Sperl int pending; 998048d151SMartin Sperl 1008048d151SMartin Sperl u64 count_transfer_polling; 1018048d151SMartin Sperl u64 count_transfer_irq; 1028048d151SMartin Sperl u64 count_transfer_irq_after_poll; 1038048d151SMartin Sperl 1048048d151SMartin Sperl struct dentry *debugfs_dir; 1051ea29b39SMartin Sperl }; 1061ea29b39SMartin Sperl 1078048d151SMartin Sperl #if defined(CONFIG_DEBUG_FS) 1088048d151SMartin Sperl static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs, 1098048d151SMartin Sperl const char *dname) 1108048d151SMartin Sperl { 1118048d151SMartin Sperl char name[64]; 1128048d151SMartin Sperl struct dentry *dir; 1138048d151SMartin Sperl 1148048d151SMartin Sperl /* get full name */ 1158048d151SMartin Sperl snprintf(name, sizeof(name), "spi-bcm2835aux-%s", dname); 1168048d151SMartin Sperl 1178048d151SMartin Sperl /* the base directory */ 1188048d151SMartin Sperl dir = debugfs_create_dir(name, NULL); 1198048d151SMartin Sperl bs->debugfs_dir = dir; 1208048d151SMartin Sperl 1218048d151SMartin Sperl /* the counters */ 1228048d151SMartin Sperl debugfs_create_u64("count_transfer_polling", 0444, dir, 1238048d151SMartin Sperl &bs->count_transfer_polling); 1248048d151SMartin Sperl debugfs_create_u64("count_transfer_irq", 0444, dir, 1258048d151SMartin Sperl &bs->count_transfer_irq); 1268048d151SMartin Sperl debugfs_create_u64("count_transfer_irq_after_poll", 0444, dir, 1278048d151SMartin Sperl &bs->count_transfer_irq_after_poll); 1288048d151SMartin Sperl } 1298048d151SMartin Sperl 1308048d151SMartin Sperl static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs) 1318048d151SMartin Sperl { 1328048d151SMartin Sperl debugfs_remove_recursive(bs->debugfs_dir); 1338048d151SMartin Sperl bs->debugfs_dir = NULL; 1348048d151SMartin Sperl } 1358048d151SMartin Sperl #else 1369b186e9aSYueHaibing static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs, 1379b186e9aSYueHaibing const char *dname) 1388048d151SMartin Sperl { 1398048d151SMartin Sperl } 1408048d151SMartin Sperl 1418048d151SMartin Sperl static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs) 1428048d151SMartin Sperl { 1438048d151SMartin Sperl } 1448048d151SMartin Sperl #endif /* CONFIG_DEBUG_FS */ 1458048d151SMartin Sperl 1461ea29b39SMartin Sperl static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg) 1471ea29b39SMartin Sperl { 1481ea29b39SMartin Sperl return readl(bs->regs + reg); 1491ea29b39SMartin Sperl } 1501ea29b39SMartin Sperl 1511ea29b39SMartin Sperl static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg, 1521ea29b39SMartin Sperl u32 val) 1531ea29b39SMartin Sperl { 1541ea29b39SMartin Sperl writel(val, bs->regs + reg); 1551ea29b39SMartin Sperl } 1561ea29b39SMartin Sperl 1571ea29b39SMartin Sperl static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs) 1581ea29b39SMartin Sperl { 1591ea29b39SMartin Sperl u32 data; 1601ea29b39SMartin Sperl int count = min(bs->rx_len, 3); 1611ea29b39SMartin Sperl 1621ea29b39SMartin Sperl data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO); 1631ea29b39SMartin Sperl if (bs->rx_buf) { 16472aac02bSMartin Sperl switch (count) { 16572aac02bSMartin Sperl case 3: 16672aac02bSMartin Sperl *bs->rx_buf++ = (data >> 16) & 0xff; 167df561f66SGustavo A. R. Silva fallthrough; 16872aac02bSMartin Sperl case 2: 16972aac02bSMartin Sperl *bs->rx_buf++ = (data >> 8) & 0xff; 170df561f66SGustavo A. R. Silva fallthrough; 17172aac02bSMartin Sperl case 1: 17272aac02bSMartin Sperl *bs->rx_buf++ = (data >> 0) & 0xff; 17372aac02bSMartin Sperl /* fallthrough - no default */ 17472aac02bSMartin Sperl } 1751ea29b39SMartin Sperl } 1761ea29b39SMartin Sperl bs->rx_len -= count; 17772aac02bSMartin Sperl bs->pending -= count; 1781ea29b39SMartin Sperl } 1791ea29b39SMartin Sperl 1801ea29b39SMartin Sperl static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs) 1811ea29b39SMartin Sperl { 1821ea29b39SMartin Sperl u32 data; 1831ea29b39SMartin Sperl u8 byte; 1841ea29b39SMartin Sperl int count; 1851ea29b39SMartin Sperl int i; 1861ea29b39SMartin Sperl 1871ea29b39SMartin Sperl /* gather up to 3 bytes to write to the FIFO */ 1881ea29b39SMartin Sperl count = min(bs->tx_len, 3); 1891ea29b39SMartin Sperl data = 0; 1901ea29b39SMartin Sperl for (i = 0; i < count; i++) { 1911ea29b39SMartin Sperl byte = bs->tx_buf ? *bs->tx_buf++ : 0; 1921ea29b39SMartin Sperl data |= byte << (8 * (2 - i)); 1931ea29b39SMartin Sperl } 1941ea29b39SMartin Sperl 1951ea29b39SMartin Sperl /* and set the variable bit-length */ 1961ea29b39SMartin Sperl data |= (count * 8) << 24; 1971ea29b39SMartin Sperl 1981ea29b39SMartin Sperl /* and decrement length */ 1991ea29b39SMartin Sperl bs->tx_len -= count; 20072aac02bSMartin Sperl bs->pending += count; 2011ea29b39SMartin Sperl 2021ea29b39SMartin Sperl /* write to the correct TX-register */ 2031ea29b39SMartin Sperl if (bs->tx_len) 2041ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data); 2051ea29b39SMartin Sperl else 2061ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data); 2071ea29b39SMartin Sperl } 2081ea29b39SMartin Sperl 2091ea29b39SMartin Sperl static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs) 2101ea29b39SMartin Sperl { 2111ea29b39SMartin Sperl /* disable spi clearing fifo and interrupts */ 2121ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0); 2131ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, 2141ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL0_CLEARFIFO); 2151ea29b39SMartin Sperl } 2161ea29b39SMartin Sperl 2177188a6f0SMartin Sperl static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs) 2181ea29b39SMartin Sperl { 21973b114eeSMartin Sperl u32 stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT); 22073b114eeSMartin Sperl 2211ea29b39SMartin Sperl /* check if we have data to read */ 22273b114eeSMartin Sperl for (; bs->rx_len && (stat & BCM2835_AUX_SPI_STAT_RX_LVL); 22373b114eeSMartin Sperl stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT)) 2241ea29b39SMartin Sperl bcm2835aux_rd_fifo(bs); 2251ea29b39SMartin Sperl 2261ea29b39SMartin Sperl /* check if we have data to write */ 2271ea29b39SMartin Sperl while (bs->tx_len && 22872aac02bSMartin Sperl (bs->pending < 12) && 2291ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 2301ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_TX_FULL))) { 2311ea29b39SMartin Sperl bcm2835aux_wr_fifo(bs); 2321ea29b39SMartin Sperl } 2337188a6f0SMartin Sperl } 2347188a6f0SMartin Sperl 2357188a6f0SMartin Sperl static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) 2367188a6f0SMartin Sperl { 2377188a6f0SMartin Sperl struct spi_master *master = dev_id; 2387188a6f0SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2397188a6f0SMartin Sperl 2407188a6f0SMartin Sperl /* IRQ may be shared, so return if our interrupts are disabled */ 2417188a6f0SMartin Sperl if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & 2427188a6f0SMartin Sperl (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) 2437188a6f0SMartin Sperl return IRQ_NONE; 2447188a6f0SMartin Sperl 2457188a6f0SMartin Sperl /* do common fifo handling */ 2467188a6f0SMartin Sperl bcm2835aux_spi_transfer_helper(bs); 2471ea29b39SMartin Sperl 248f29ab184SStephan Olbrich if (!bs->tx_len) { 249f29ab184SStephan Olbrich /* disable tx fifo empty interrupt */ 250f29ab184SStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | 251f29ab184SStephan Olbrich BCM2835_AUX_SPI_CNTL1_IDLE); 252f29ab184SStephan Olbrich } 253f29ab184SStephan Olbrich 254b4e2adefSStephan Olbrich /* and if rx_len is 0 then disable interrupts and wake up completion */ 2551ea29b39SMartin Sperl if (!bs->rx_len) { 256b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 2571ea29b39SMartin Sperl complete(&master->xfer_completion); 2581ea29b39SMartin Sperl } 2591ea29b39SMartin Sperl 2607188a6f0SMartin Sperl return IRQ_HANDLED; 2611ea29b39SMartin Sperl } 2621ea29b39SMartin Sperl 2631ea29b39SMartin Sperl static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master, 2641ea29b39SMartin Sperl struct spi_device *spi, 2651ea29b39SMartin Sperl struct spi_transfer *tfr) 2661ea29b39SMartin Sperl { 2671ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2681ea29b39SMartin Sperl 2691ea29b39SMartin Sperl /* enable interrupts */ 2701ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | 2711ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL1_TXEMPTY | 2721ea29b39SMartin Sperl BCM2835_AUX_SPI_CNTL1_IDLE); 2731ea29b39SMartin Sperl 2741ea29b39SMartin Sperl /* and wait for finish... */ 2751ea29b39SMartin Sperl return 1; 2761ea29b39SMartin Sperl } 2771ea29b39SMartin Sperl 2781ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master, 2791ea29b39SMartin Sperl struct spi_device *spi, 2801ea29b39SMartin Sperl struct spi_transfer *tfr) 2811ea29b39SMartin Sperl { 2821ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 2831ea29b39SMartin Sperl 2848048d151SMartin Sperl /* update statistics */ 2858048d151SMartin Sperl bs->count_transfer_irq++; 2868048d151SMartin Sperl 2871ea29b39SMartin Sperl /* fill in registers and fifos before enabling interrupts */ 2881ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 2891ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 2901ea29b39SMartin Sperl 2911ea29b39SMartin Sperl /* fill in tx fifo with data before enabling interrupts */ 2921ea29b39SMartin Sperl while ((bs->tx_len) && 29372aac02bSMartin Sperl (bs->pending < 12) && 2941ea29b39SMartin Sperl (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & 2951ea29b39SMartin Sperl BCM2835_AUX_SPI_STAT_TX_FULL))) { 2961ea29b39SMartin Sperl bcm2835aux_wr_fifo(bs); 2971ea29b39SMartin Sperl } 2981ea29b39SMartin Sperl 2991ea29b39SMartin Sperl /* now run the interrupt mode */ 3001ea29b39SMartin Sperl return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr); 3011ea29b39SMartin Sperl } 3021ea29b39SMartin Sperl 3031ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, 3041ea29b39SMartin Sperl struct spi_device *spi, 30572aac02bSMartin Sperl struct spi_transfer *tfr) 3061ea29b39SMartin Sperl { 3071ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 3081ea29b39SMartin Sperl unsigned long timeout; 3091ea29b39SMartin Sperl 3108048d151SMartin Sperl /* update statistics */ 3118048d151SMartin Sperl bs->count_transfer_polling++; 3128048d151SMartin Sperl 3131ea29b39SMartin Sperl /* configure spi */ 3141ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 3151ea29b39SMartin Sperl bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 3161ea29b39SMartin Sperl 3175fd917afSMartin Sperl /* set the timeout to at least 2 jiffies */ 3185fd917afSMartin Sperl timeout = jiffies + 2 + HZ * polling_limit_us / 1000000; 3191ea29b39SMartin Sperl 3201ea29b39SMartin Sperl /* loop until finished the transfer */ 3211ea29b39SMartin Sperl while (bs->rx_len) { 3221ea29b39SMartin Sperl 3237188a6f0SMartin Sperl /* do common fifo handling */ 3247188a6f0SMartin Sperl bcm2835aux_spi_transfer_helper(bs); 3251ea29b39SMartin Sperl 3261ea29b39SMartin Sperl /* there is still data pending to read check the timeout */ 3271ea29b39SMartin Sperl if (bs->rx_len && time_after(jiffies, timeout)) { 3281ea29b39SMartin Sperl dev_dbg_ratelimited(&spi->dev, 3291ea29b39SMartin Sperl "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n", 3301ea29b39SMartin Sperl jiffies - timeout, 3311ea29b39SMartin Sperl bs->tx_len, bs->rx_len); 3321ea29b39SMartin Sperl /* forward to interrupt handler */ 3338048d151SMartin Sperl bs->count_transfer_irq_after_poll++; 3341ea29b39SMartin Sperl return __bcm2835aux_spi_transfer_one_irq(master, 3351ea29b39SMartin Sperl spi, tfr); 3361ea29b39SMartin Sperl } 3371ea29b39SMartin Sperl } 3381ea29b39SMartin Sperl 3391ea29b39SMartin Sperl /* and return without waiting for completion */ 3401ea29b39SMartin Sperl return 0; 3411ea29b39SMartin Sperl } 3421ea29b39SMartin Sperl 3431ea29b39SMartin Sperl static int bcm2835aux_spi_transfer_one(struct spi_master *master, 3441ea29b39SMartin Sperl struct spi_device *spi, 3451ea29b39SMartin Sperl struct spi_transfer *tfr) 3461ea29b39SMartin Sperl { 3471ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 3485e94c3cdSMartin Sperl unsigned long spi_hz, clk_hz, speed; 3495fd917afSMartin Sperl unsigned long hz_per_byte, byte_limit; 3501ea29b39SMartin Sperl 3511ea29b39SMartin Sperl /* calculate the registers to handle 3521ea29b39SMartin Sperl * 3531ea29b39SMartin Sperl * note that we use the variable data mode, which 3541ea29b39SMartin Sperl * is not optimal for longer transfers as we waste registers 3551ea29b39SMartin Sperl * resulting (potentially) in more interrupts when transferring 3561ea29b39SMartin Sperl * more than 12 bytes 3571ea29b39SMartin Sperl */ 3581ea29b39SMartin Sperl 3591ea29b39SMartin Sperl /* set clock */ 3601ea29b39SMartin Sperl spi_hz = tfr->speed_hz; 3611ea29b39SMartin Sperl clk_hz = clk_get_rate(bs->clk); 3621ea29b39SMartin Sperl 3631ea29b39SMartin Sperl if (spi_hz >= clk_hz / 2) { 3641ea29b39SMartin Sperl speed = 0; 3651ea29b39SMartin Sperl } else if (spi_hz) { 3661ea29b39SMartin Sperl speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1; 3671ea29b39SMartin Sperl if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX) 3681ea29b39SMartin Sperl speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; 3691ea29b39SMartin Sperl } else { /* the slowest we can go */ 3701ea29b39SMartin Sperl speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; 3711ea29b39SMartin Sperl } 372b4e2adefSStephan Olbrich /* mask out old speed from previous spi_transfer */ 373b4e2adefSStephan Olbrich bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED); 374b4e2adefSStephan Olbrich /* set the new speed */ 3751ea29b39SMartin Sperl bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; 3761ea29b39SMartin Sperl 3775e94c3cdSMartin Sperl tfr->effective_speed_hz = clk_hz / (2 * (speed + 1)); 3781ea29b39SMartin Sperl 3791ea29b39SMartin Sperl /* set transmit buffers and length */ 3801ea29b39SMartin Sperl bs->tx_buf = tfr->tx_buf; 3811ea29b39SMartin Sperl bs->rx_buf = tfr->rx_buf; 3821ea29b39SMartin Sperl bs->tx_len = tfr->len; 3831ea29b39SMartin Sperl bs->rx_len = tfr->len; 38472aac02bSMartin Sperl bs->pending = 0; 3851ea29b39SMartin Sperl 386d704afffSTrent Piepho /* Calculate the estimated time in us the transfer runs. Note that 387d704afffSTrent Piepho * there are are 2 idle clocks cycles after each chunk getting 388d704afffSTrent Piepho * transferred - in our case the chunk size is 3 bytes, so we 389d704afffSTrent Piepho * approximate this by 9 cycles/byte. This is used to find the number 390d704afffSTrent Piepho * of Hz per byte per polling limit. E.g., we can transfer 1 byte in 391d704afffSTrent Piepho * 30 µs per 300,000 Hz of bus clock. 39272aac02bSMartin Sperl */ 3935fd917afSMartin Sperl hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0; 3945e94c3cdSMartin Sperl byte_limit = hz_per_byte ? tfr->effective_speed_hz / hz_per_byte : 1; 3955fd917afSMartin Sperl 3961ea29b39SMartin Sperl /* run in polling mode for short transfers */ 3975fd917afSMartin Sperl if (tfr->len < byte_limit) 39872aac02bSMartin Sperl return bcm2835aux_spi_transfer_one_poll(master, spi, tfr); 3991ea29b39SMartin Sperl 4001ea29b39SMartin Sperl /* run in interrupt mode for all others */ 4011ea29b39SMartin Sperl return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); 4021ea29b39SMartin Sperl } 4031ea29b39SMartin Sperl 404b4e2adefSStephan Olbrich static int bcm2835aux_spi_prepare_message(struct spi_master *master, 405b4e2adefSStephan Olbrich struct spi_message *msg) 406b4e2adefSStephan Olbrich { 407b4e2adefSStephan Olbrich struct spi_device *spi = msg->spi; 408b4e2adefSStephan Olbrich struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 409b4e2adefSStephan Olbrich 410b4e2adefSStephan Olbrich bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | 411b4e2adefSStephan Olbrich BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | 412b4e2adefSStephan Olbrich BCM2835_AUX_SPI_CNTL0_MSBF_OUT; 413b4e2adefSStephan Olbrich bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; 414b4e2adefSStephan Olbrich 415b4e2adefSStephan Olbrich /* handle all the modes */ 416e9dd4edcSStephan Olbrich if (spi->mode & SPI_CPOL) { 417b4e2adefSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; 418e9dd4edcSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING; 419e9dd4edcSStephan Olbrich } else { 420e9dd4edcSStephan Olbrich bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING; 421e9dd4edcSStephan Olbrich } 422b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); 423b4e2adefSStephan Olbrich bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); 424b4e2adefSStephan Olbrich 425b4e2adefSStephan Olbrich return 0; 426b4e2adefSStephan Olbrich } 427b4e2adefSStephan Olbrich 428b4e2adefSStephan Olbrich static int bcm2835aux_spi_unprepare_message(struct spi_master *master, 429b4e2adefSStephan Olbrich struct spi_message *msg) 430b4e2adefSStephan Olbrich { 431b4e2adefSStephan Olbrich struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 432b4e2adefSStephan Olbrich 433b4e2adefSStephan Olbrich bcm2835aux_spi_reset_hw(bs); 434b4e2adefSStephan Olbrich 435b4e2adefSStephan Olbrich return 0; 436b4e2adefSStephan Olbrich } 437b4e2adefSStephan Olbrich 4381ea29b39SMartin Sperl static void bcm2835aux_spi_handle_err(struct spi_master *master, 4391ea29b39SMartin Sperl struct spi_message *msg) 4401ea29b39SMartin Sperl { 4411ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 4421ea29b39SMartin Sperl 4431ea29b39SMartin Sperl bcm2835aux_spi_reset_hw(bs); 4441ea29b39SMartin Sperl } 4451ea29b39SMartin Sperl 446519f2c22SMartin Sperl static int bcm2835aux_spi_setup(struct spi_device *spi) 447519f2c22SMartin Sperl { 448519f2c22SMartin Sperl int ret; 449519f2c22SMartin Sperl 450519f2c22SMartin Sperl /* sanity check for native cs */ 451519f2c22SMartin Sperl if (spi->mode & SPI_NO_CS) 452519f2c22SMartin Sperl return 0; 453ccd978b7SMartin Sperl if (gpio_is_valid(spi->cs_gpio)) { 454ccd978b7SMartin Sperl /* with gpio-cs set the GPIO to the correct level 455ccd978b7SMartin Sperl * and as output (in case the dt has the gpio not configured 456ccd978b7SMartin Sperl * as output but native cs) 457ccd978b7SMartin Sperl */ 458ccd978b7SMartin Sperl ret = gpio_direction_output(spi->cs_gpio, 459ccd978b7SMartin Sperl (spi->mode & SPI_CS_HIGH) ? 0 : 1); 460ccd978b7SMartin Sperl if (ret) 461ccd978b7SMartin Sperl dev_err(&spi->dev, 462ccd978b7SMartin Sperl "could not set gpio %i as output: %i\n", 463ccd978b7SMartin Sperl spi->cs_gpio, ret); 464ccd978b7SMartin Sperl 465ccd978b7SMartin Sperl return ret; 466ccd978b7SMartin Sperl } 467519f2c22SMartin Sperl 468519f2c22SMartin Sperl /* for dt-backwards compatibility: only support native on CS0 469519f2c22SMartin Sperl * known things not supported with broken native CS: 470519f2c22SMartin Sperl * * multiple chip-selects: cs0-cs2 are all 471519f2c22SMartin Sperl * simultaniously asserted whenever there is a transfer 472519f2c22SMartin Sperl * this even includes SPI_NO_CS 473519f2c22SMartin Sperl * * SPI_CS_HIGH: cs are always asserted low 474519f2c22SMartin Sperl * * cs_change: cs is deasserted after each spi_transfer 475519f2c22SMartin Sperl * * cs_delay_usec: cs is always deasserted one SCK cycle 476519f2c22SMartin Sperl * after the last transfer 477519f2c22SMartin Sperl * probably more... 478519f2c22SMartin Sperl */ 479519f2c22SMartin Sperl dev_warn(&spi->dev, 480519f2c22SMartin Sperl "Native CS is not supported - please configure cs-gpio in device-tree\n"); 481519f2c22SMartin Sperl 482519f2c22SMartin Sperl if (spi->chip_select == 0) 483519f2c22SMartin Sperl return 0; 484519f2c22SMartin Sperl 485519f2c22SMartin Sperl dev_warn(&spi->dev, "Native CS is not working for cs > 0\n"); 486519f2c22SMartin Sperl 487519f2c22SMartin Sperl return -EINVAL; 488519f2c22SMartin Sperl } 489519f2c22SMartin Sperl 4901ea29b39SMartin Sperl static int bcm2835aux_spi_probe(struct platform_device *pdev) 4911ea29b39SMartin Sperl { 4921ea29b39SMartin Sperl struct spi_master *master; 4931ea29b39SMartin Sperl struct bcm2835aux_spi *bs; 4941ea29b39SMartin Sperl unsigned long clk_hz; 4951ea29b39SMartin Sperl int err; 4961ea29b39SMartin Sperl 4971ea29b39SMartin Sperl master = spi_alloc_master(&pdev->dev, sizeof(*bs)); 498bf93b951SHoan Nguyen An if (!master) 4991ea29b39SMartin Sperl return -ENOMEM; 5001ea29b39SMartin Sperl 5011ea29b39SMartin Sperl platform_set_drvdata(pdev, master); 502e9dd4edcSStephan Olbrich master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); 5031ea29b39SMartin Sperl master->bits_per_word_mask = SPI_BPW_MASK(8); 504509c5836SMartin Sperl /* even though the driver never officially supported native CS 505509c5836SMartin Sperl * allow a single native CS for legacy DT support purposes when 506509c5836SMartin Sperl * no cs-gpio is configured. 507509c5836SMartin Sperl * Known limitations for native cs are: 508509c5836SMartin Sperl * * multiple chip-selects: cs0-cs2 are all simultaniously asserted 509509c5836SMartin Sperl * whenever there is a transfer - this even includes SPI_NO_CS 510509c5836SMartin Sperl * * SPI_CS_HIGH: is ignores - cs are always asserted low 511509c5836SMartin Sperl * * cs_change: cs is deasserted after each spi_transfer 512509c5836SMartin Sperl * * cs_delay_usec: cs is always deasserted one SCK cycle after 513509c5836SMartin Sperl * a spi_transfer 514509c5836SMartin Sperl */ 515509c5836SMartin Sperl master->num_chipselect = 1; 516519f2c22SMartin Sperl master->setup = bcm2835aux_spi_setup; 5171ea29b39SMartin Sperl master->transfer_one = bcm2835aux_spi_transfer_one; 5181ea29b39SMartin Sperl master->handle_err = bcm2835aux_spi_handle_err; 519b4e2adefSStephan Olbrich master->prepare_message = bcm2835aux_spi_prepare_message; 520b4e2adefSStephan Olbrich master->unprepare_message = bcm2835aux_spi_unprepare_message; 5211ea29b39SMartin Sperl master->dev.of_node = pdev->dev.of_node; 5221ea29b39SMartin Sperl 5231ea29b39SMartin Sperl bs = spi_master_get_devdata(master); 5241ea29b39SMartin Sperl 5251ea29b39SMartin Sperl /* the main area */ 526d1975d05SYueHaibing bs->regs = devm_platform_ioremap_resource(pdev, 0); 5271ea29b39SMartin Sperl if (IS_ERR(bs->regs)) { 5281ea29b39SMartin Sperl err = PTR_ERR(bs->regs); 5291ea29b39SMartin Sperl goto out_master_put; 5301ea29b39SMartin Sperl } 5311ea29b39SMartin Sperl 5321ea29b39SMartin Sperl bs->clk = devm_clk_get(&pdev->dev, NULL); 533bfc7af6dSYueHaibing if (IS_ERR(bs->clk)) { 5341ea29b39SMartin Sperl err = PTR_ERR(bs->clk); 5351ea29b39SMartin Sperl dev_err(&pdev->dev, "could not get clk: %d\n", err); 5361ea29b39SMartin Sperl goto out_master_put; 5371ea29b39SMartin Sperl } 5381ea29b39SMartin Sperl 53907bce09eSMartin Sperl bs->irq = platform_get_irq(pdev, 0); 5401ea29b39SMartin Sperl if (bs->irq <= 0) { 5411ea29b39SMartin Sperl err = bs->irq ? bs->irq : -ENODEV; 5421ea29b39SMartin Sperl goto out_master_put; 5431ea29b39SMartin Sperl } 5441ea29b39SMartin Sperl 5451ea29b39SMartin Sperl /* this also enables the HW block */ 5461ea29b39SMartin Sperl err = clk_prepare_enable(bs->clk); 5471ea29b39SMartin Sperl if (err) { 5481ea29b39SMartin Sperl dev_err(&pdev->dev, "could not prepare clock: %d\n", err); 5491ea29b39SMartin Sperl goto out_master_put; 5501ea29b39SMartin Sperl } 5511ea29b39SMartin Sperl 5521ea29b39SMartin Sperl /* just checking if the clock returns a sane value */ 5531ea29b39SMartin Sperl clk_hz = clk_get_rate(bs->clk); 5541ea29b39SMartin Sperl if (!clk_hz) { 5551ea29b39SMartin Sperl dev_err(&pdev->dev, "clock returns 0 Hz\n"); 5561ea29b39SMartin Sperl err = -ENODEV; 5571ea29b39SMartin Sperl goto out_clk_disable; 5581ea29b39SMartin Sperl } 5591ea29b39SMartin Sperl 56007bce09eSMartin Sperl /* reset SPI-HW block */ 56107bce09eSMartin Sperl bcm2835aux_spi_reset_hw(bs); 56207bce09eSMartin Sperl 5631ea29b39SMartin Sperl err = devm_request_irq(&pdev->dev, bs->irq, 5641ea29b39SMartin Sperl bcm2835aux_spi_interrupt, 5651ea29b39SMartin Sperl IRQF_SHARED, 5661ea29b39SMartin Sperl dev_name(&pdev->dev), master); 5671ea29b39SMartin Sperl if (err) { 5681ea29b39SMartin Sperl dev_err(&pdev->dev, "could not request IRQ: %d\n", err); 5691ea29b39SMartin Sperl goto out_clk_disable; 5701ea29b39SMartin Sperl } 5711ea29b39SMartin Sperl 572b9dd3f6dSLukas Wunner err = spi_register_master(master); 5731ea29b39SMartin Sperl if (err) { 5741ea29b39SMartin Sperl dev_err(&pdev->dev, "could not register SPI master: %d\n", err); 5751ea29b39SMartin Sperl goto out_clk_disable; 5761ea29b39SMartin Sperl } 5771ea29b39SMartin Sperl 5788048d151SMartin Sperl bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev)); 5798048d151SMartin Sperl 5801ea29b39SMartin Sperl return 0; 5811ea29b39SMartin Sperl 5821ea29b39SMartin Sperl out_clk_disable: 5831ea29b39SMartin Sperl clk_disable_unprepare(bs->clk); 5841ea29b39SMartin Sperl out_master_put: 5851ea29b39SMartin Sperl spi_master_put(master); 5861ea29b39SMartin Sperl return err; 5871ea29b39SMartin Sperl } 5881ea29b39SMartin Sperl 5891ea29b39SMartin Sperl static int bcm2835aux_spi_remove(struct platform_device *pdev) 5901ea29b39SMartin Sperl { 5911ea29b39SMartin Sperl struct spi_master *master = platform_get_drvdata(pdev); 5921ea29b39SMartin Sperl struct bcm2835aux_spi *bs = spi_master_get_devdata(master); 5931ea29b39SMartin Sperl 5948048d151SMartin Sperl bcm2835aux_debugfs_remove(bs); 5958048d151SMartin Sperl 596b9dd3f6dSLukas Wunner spi_unregister_master(master); 597b9dd3f6dSLukas Wunner 5981ea29b39SMartin Sperl bcm2835aux_spi_reset_hw(bs); 5991ea29b39SMartin Sperl 6001ea29b39SMartin Sperl /* disable the HW block by releasing the clock */ 6011ea29b39SMartin Sperl clk_disable_unprepare(bs->clk); 6021ea29b39SMartin Sperl 6031ea29b39SMartin Sperl return 0; 6041ea29b39SMartin Sperl } 6051ea29b39SMartin Sperl 6061ea29b39SMartin Sperl static const struct of_device_id bcm2835aux_spi_match[] = { 6071ea29b39SMartin Sperl { .compatible = "brcm,bcm2835-aux-spi", }, 6081ea29b39SMartin Sperl {} 6091ea29b39SMartin Sperl }; 6101ea29b39SMartin Sperl MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match); 6111ea29b39SMartin Sperl 6121ea29b39SMartin Sperl static struct platform_driver bcm2835aux_spi_driver = { 6131ea29b39SMartin Sperl .driver = { 6141ea29b39SMartin Sperl .name = "spi-bcm2835aux", 6151ea29b39SMartin Sperl .of_match_table = bcm2835aux_spi_match, 6161ea29b39SMartin Sperl }, 6171ea29b39SMartin Sperl .probe = bcm2835aux_spi_probe, 6181ea29b39SMartin Sperl .remove = bcm2835aux_spi_remove, 6191ea29b39SMartin Sperl }; 6201ea29b39SMartin Sperl module_platform_driver(bcm2835aux_spi_driver); 6211ea29b39SMartin Sperl 6221ea29b39SMartin Sperl MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux"); 6231ea29b39SMartin Sperl MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>"); 62422bf6cd2SStefan Wahren MODULE_LICENSE("GPL"); 625