source: trunk/target/linux/brcm63xx/patches-3.0/240-spi.patch @ 27246

Last change on this file since 27246 was 27246, checked in by florian, 5 years ago

[brcm63xx] use macros to generate SPI registers table and switches

File size: 24.8 KB
  • arch/mips/bcm63xx/cpu.c

    a b static const unsigned long bcm96338_regs 
    5858 
    5959static const int bcm96338_irqs[] = { 
    6060        [IRQ_TIMER]             = BCM_6338_TIMER_IRQ, 
     61        [IRQ_SPI]               = BCM_6338_SPI_IRQ, 
    6162        [IRQ_UART0]             = BCM_6338_UART0_IRQ, 
    6263        [IRQ_DSL]               = BCM_6338_DSL_IRQ, 
    6364        [IRQ_ENET0]             = BCM_6338_ENET0_IRQ, 
    static const unsigned long bcm96348_regs 
    132133 
    133134static const int bcm96348_irqs[] = { 
    134135        [IRQ_TIMER]             = BCM_6348_TIMER_IRQ, 
     136        [IRQ_SPI]               = BCM_6348_SPI_IRQ, 
    135137        [IRQ_UART0]             = BCM_6348_UART0_IRQ, 
    136138        [IRQ_DSL]               = BCM_6348_DSL_IRQ, 
    137139        [IRQ_ENET0]             = BCM_6348_ENET0_IRQ, 
    static const unsigned long bcm96358_regs 
    175177 
    176178static const int bcm96358_irqs[] = { 
    177179        [IRQ_TIMER]             = BCM_6358_TIMER_IRQ, 
     180        [IRQ_SPI]               = BCM_6358_SPI_IRQ, 
    178181        [IRQ_UART0]             = BCM_6358_UART0_IRQ, 
    179182        [IRQ_UART1]             = BCM_6358_UART1_IRQ, 
    180183        [IRQ_DSL]               = BCM_6358_DSL_IRQ, 
  • new file arch/mips/bcm63xx/dev-spi.c

    - +  
     1/* 
     2 * This file is subject to the terms and conditions of the GNU General Public 
     3 * License.  See the file "COPYING" in the main directory of this archive 
     4 * for more details. 
     5 * 
     6 * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org> 
     7 * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> 
     8 */ 
     9 
     10#include <linux/init.h> 
     11#include <linux/kernel.h> 
     12#include <linux/platform_device.h> 
     13 
     14#include <bcm63xx_cpu.h> 
     15#include <bcm63xx_dev_spi.h> 
     16#include <bcm63xx_regs.h> 
     17 
     18#ifdef BCMCPU_RUNTIME_DETECT 
     19/* 
     20 * register offsets 
     21 */ 
     22static const unsigned long bcm96338_regs_spi[] = { 
     23        __GEN_SPI_REGS_TABLE(6338) 
     24}; 
     25 
     26static const unsigned long bcm96348_regs_spi[] = { 
     27        __GEN_SPI_REGS_TABLE(6348) 
     28}; 
     29 
     30static const unsigned long bcm96358_regs_spi[] = { 
     31        __GEN_SPI_REGS_TABLE(6358) 
     32}; 
     33 
     34const unsigned long *bcm63xx_regs_spi; 
     35EXPORT_SYMBOL(bcm63xx_regs_spi); 
     36 
     37static __init void bcm63xx_spi_regs_init(void) 
     38{ 
     39        if (BCMCPU_IS_6338()) 
     40                bcm63xx_regs_spi = bcm96338_regs_spi; 
     41        if (BCMCPU_IS_6348()) 
     42                bcm63xx_regs_spi = bcm96348_regs_spi; 
     43        if (BCMCPU_IS_6358()) 
     44                bcm63xx_regs_spi = bcm96358_regs_spi; 
     45} 
     46#else 
     47static __init void bcm63xx_spi_regs_init(void) { } 
     48#endif 
     49 
     50static struct resource spi_resources[] = { 
     51        { 
     52                .start          = -1, /* filled at runtime */ 
     53                .end            = -1, /* filled at runtime */ 
     54                .flags          = IORESOURCE_MEM, 
     55        }, 
     56        { 
     57                .start          = -1, /* filled at runtime */ 
     58                .flags          = IORESOURCE_IRQ, 
     59        }, 
     60}; 
     61 
     62static struct bcm63xx_spi_pdata spi_pdata = { 
     63        .bus_num                = 0, 
     64        .num_chipselect         = 8, 
     65        .speed_hz               = 50000000,     /* Fclk */ 
     66}; 
     67 
     68static struct platform_device bcm63xx_spi_device = { 
     69        .name           = "bcm63xx-spi", 
     70        .id             = 0, 
     71        .num_resources  = ARRAY_SIZE(spi_resources), 
     72        .resource       = spi_resources, 
     73        .dev            = { 
     74                .platform_data = &spi_pdata, 
     75        }, 
     76}; 
     77 
     78int __init bcm63xx_spi_register(void) 
     79{ 
     80        spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); 
     81        spi_resources[0].end = spi_resources[0].start; 
     82        spi_resources[0].end += RSET_SPI_SIZE - 1; 
     83        spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); 
     84 
     85        if (BCMCPU_IS_6345()) 
     86                return -ENODEV; 
     87 
     88        /* Fill in platform data */ 
     89        if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) 
     90                spi_pdata.fifo_size = SPI_BCM_6338_SPI_MSG_DATA_SIZE; 
     91 
     92        if (BCMCPU_IS_6358()) 
     93                spi_pdata.fifo_size = SPI_BCM_6358_SPI_MSG_DATA_SIZE; 
     94 
     95        bcm63xx_spi_regs_init(); 
     96 
     97        return platform_device_register(&bcm63xx_spi_device); 
     98} 
  • arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h

    a b enum bcm63xx_regs_set { 
    109109#define RSET_WDT_SIZE                   12 
    110110#define RSET_ENET_SIZE                  2048 
    111111#define RSET_ENETDMA_SIZE               2048 
     112#define RSET_SPI_SIZE                   256 
    112113#define RSET_UART_SIZE                  24 
    113114#define RSET_UDC_SIZE                   256 
    114115#define RSET_OHCI_SIZE                  256 
    enum bcm63xx_regs_set { 
    214215#define BCM_6358_UART0_BASE             (0xfffe0100) 
    215216#define BCM_6358_UART1_BASE             (0xfffe0120) 
    216217#define BCM_6358_GPIO_BASE              (0xfffe0080) 
    217 #define BCM_6358_SPI_BASE               (0xdeadbeef) 
     218#define BCM_6358_SPI_BASE               (0xfffe0800) 
    218219#define BCM_6358_UDC0_BASE              (0xfffe0400) 
    219220#define BCM_6358_OHCI0_BASE             (0xfffe1400) 
    220221#define BCM_6358_OHCI_PRIV_BASE         (0xdeadbeef) 
    static inline unsigned long bcm63xx_regs 
    441442 */ 
    442443enum bcm63xx_irq { 
    443444        IRQ_TIMER = 0, 
     445        IRQ_SPI, 
    444446        IRQ_UART0, 
    445447        IRQ_UART1, 
    446448        IRQ_DSL, 
    enum bcm63xx_irq { 
    507509 * 6348 irqs 
    508510 */ 
    509511#define BCM_6348_TIMER_IRQ              (IRQ_INTERNAL_BASE + 0) 
     512#define BCM_6348_SPI_IRQ                (IRQ_INTERNAL_BASE + 1) 
    510513#define BCM_6348_UART0_IRQ              (IRQ_INTERNAL_BASE + 2) 
    511514#define BCM_6348_DSL_IRQ                (IRQ_INTERNAL_BASE + 4) 
    512515#define BCM_6348_UDC0_IRQ               (IRQ_INTERNAL_BASE + 6) 
    enum bcm63xx_irq { 
    531534 * 6358 irqs 
    532535 */ 
    533536#define BCM_6358_TIMER_IRQ              (IRQ_INTERNAL_BASE + 0) 
     537#define BCM_6358_SPI_IRQ                (IRQ_INTERNAL_BASE + 1) 
    534538#define BCM_6358_UART0_IRQ              (IRQ_INTERNAL_BASE + 2) 
    535539#define BCM_6358_UART1_IRQ              (IRQ_INTERNAL_BASE + 3) 
    536540#define BCM_6358_OHCI0_IRQ              (IRQ_INTERNAL_BASE + 5) 
  • arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h

    a b  
    771771#define DMIPSPLLCFG_N2_SHIFT            29 
    772772#define DMIPSPLLCFG_N2_MASK             (0x7 << DMIPSPLLCFG_N2_SHIFT) 
    773773 
     774/************************************************************************* 
     775 * _REG relative to RSET_SPI 
     776 *************************************************************************/ 
     777 
     778/* BCM 6338 SPI core */ 
     779#define SPI_BCM_6338_SPI_CMD            0x00    /* 16-bits register */ 
     780#define SPI_BCM_6338_SPI_INT_STATUS     0x02 
     781#define SPI_BCM_6338_SPI_INT_MASK_ST    0x03 
     782#define SPI_BCM_6338_SPI_INT_MASK       0x04 
     783#define SPI_BCM_6338_SPI_ST             0x05 
     784#define SPI_BCM_6338_SPI_CLK_CFG        0x06 
     785#define SPI_BCM_6338_SPI_FILL_BYTE      0x07 
     786#define SPI_BCM_6338_SPI_MSG_TAIL       0x09 
     787#define SPI_BCM_6338_SPI_RX_TAIL        0x0b 
     788#define SPI_BCM_6338_SPI_MSG_CTL        0x40 
     789#define SPI_BCM_6338_SPI_MSG_DATA       0x41 
     790#define SPI_BCM_6338_SPI_MSG_DATA_SIZE  0x3f 
     791#define SPI_BCM_6338_SPI_RX_DATA        0x80 
     792#define SPI_BCM_6338_SPI_RX_DATA_SIZE   0x3f 
     793 
     794/* BCM 6348 SPI core */ 
     795#define SPI_BCM_6348_SPI_INT_MASK_ST    0x00 
     796#define SPI_BCM_6348_SPI_INT_STATUS     0x01 
     797#define SPI_BCM_6348_SPI_CMD            0x02    /* 16-bits register */ 
     798#define SPI_BCM_6348_SPI_FILL_BYTE      0x04 
     799#define SPI_BCM_6348_SPI_CLK_CFG        0x05 
     800#define SPI_BCM_6348_SPI_ST             0x06 
     801#define SPI_BCM_6348_SPI_INT_MASK       0x07 
     802#define SPI_BCM_6348_SPI_RX_TAIL        0x08 
     803#define SPI_BCM_6348_SPI_MSG_TAIL       0x10 
     804#define SPI_BCM_6348_SPI_MSG_DATA       0x40 
     805#define SPI_BCM_6348_SPI_MSG_CTL        0x42 
     806#define SPI_BCM_6348_SPI_MSG_DATA_SIZE  0x3f 
     807#define SPI_BCM_6348_SPI_RX_DATA        0x80 
     808#define SPI_BCM_6348_SPI_RX_DATA_SIZE   0x3f 
     809 
     810/* BCM 6358 SPI core */ 
     811#define SPI_BCM_6358_SPI_MSG_CTL        0x00    /* 16-bits register */ 
     812 
     813#define SPI_BCM_6358_SPI_MSG_DATA       0x02 
     814#define SPI_BCM_6358_SPI_MSG_DATA_SIZE  0x21e 
     815 
     816#define SPI_BCM_6358_SPI_RX_DATA        0x400 
     817#define SPI_BCM_6358_SPI_RX_DATA_SIZE   0x220 
     818 
     819#define SPI_BCM_6358_SPI_CMD            0x700   /* 16-bits register */ 
     820 
     821#define SPI_BCM_6358_SPI_INT_STATUS     0x702 
     822#define SPI_BCM_6358_SPI_INT_MASK_ST    0x703 
     823 
     824#define SPI_BCM_6358_SPI_INT_MASK       0x704 
     825 
     826#define SPI_BCM_6358_SPI_ST             0x705 
     827 
     828#define SPI_BCM_6358_SPI_CLK_CFG        0x706 
     829 
     830#define SPI_BCM_6358_SPI_FILL_BYTE      0x707 
     831#define SPI_BCM_6358_SPI_MSG_TAIL       0x709 
     832#define SPI_BCM_6358_SPI_RX_TAIL        0x70B 
     833 
     834/* Shared SPI definitions */ 
     835 
     836/* Message configuration */ 
     837#define SPI_FD_RW                       0x00 
     838#define SPI_HD_W                        0x01 
     839#define SPI_HD_R                        0x02 
     840#define SPI_BYTE_CNT_SHIFT              0 
     841#define SPI_MSG_TYPE_SHIFT              14 
     842 
     843/* Command */ 
     844#define SPI_CMD_NOOP                    0x01 
     845#define SPI_CMD_SOFT_RESET              0x02 
     846#define SPI_CMD_HARD_RESET              0x04 
     847#define SPI_CMD_START_IMMEDIATE         0x08 
     848#define SPI_CMD_COMMAND_SHIFT           0 
     849#define SPI_CMD_COMMAND_MASK            0x000f 
     850#define SPI_CMD_DEVICE_ID_SHIFT         4 
     851#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT  8 
     852#define SPI_CMD_ONE_BYTE_SHIFT          11 
     853#define SPI_CMD_ONE_WIRE_SHIFT          12 
     854#define SPI_DEV_ID_0                    0 
     855#define SPI_DEV_ID_1                    1 
     856#define SPI_DEV_ID_2                    2 
     857#define SPI_DEV_ID_3                    3 
     858 
     859/* Interrupt mask */ 
     860#define SPI_INTR_CMD_DONE               0x01 
     861#define SPI_INTR_RX_OVERFLOW            0x02 
     862#define SPI_INTR_TX_UNDERFLOW           0x04 
     863#define SPI_INTR_TX_OVERFLOW            0x08 
     864#define SPI_INTR_RX_UNDERFLOW           0x10 
     865#define SPI_INTR_CLEAR_ALL              0x1f 
     866 
     867/* Status */ 
     868#define SPI_RX_EMPTY                    0x02 
     869#define SPI_CMD_BUSY                    0x04 
     870#define SPI_SERIAL_BUSY                 0x08 
     871 
     872/* Clock configuration */ 
     873#define SPI_CLK_20MHZ                   0x00 
     874#define SPI_CLK_0_391MHZ                0x01 
     875#define SPI_CLK_0_781MHZ                0x02 /* default */ 
     876#define SPI_CLK_1_563MHZ                0x03 
     877#define SPI_CLK_3_125MHZ                0x04 
     878#define SPI_CLK_6_250MHZ                0x05 
     879#define SPI_CLK_12_50MHZ                0x06 
     880#define SPI_CLK_25MHZ                   0x07 
     881#define SPI_CLK_MASK                    0x07 
     882#define SPI_SSOFFTIME_MASK              0x38 
     883#define SPI_SSOFFTIME_SHIFT             3 
     884#define SPI_BYTE_SWAP                   0x80 
     885 
    774886#endif /* BCM63XX_REGS_H_ */ 
  • new file drivers/spi/bcm63xx_spi.c

    - +  
     1/* 
     2 * Broadcom BCM63xx SPI controller support 
     3 * 
     4 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> 
     5 * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> 
     6 * 
     7 * This program is free software; you can redistribute it and/or 
     8 * modify it under the terms of the GNU General Public License 
     9 * as published by the Free Software Foundation; either version 2 
     10 * of the License, or (at your option) any later version. 
     11 * 
     12 * This program is distributed in the hope that it will be useful, 
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     15 * GNU General Public License for more details. 
     16 * 
     17 * You should have received a copy of the GNU General Public License 
     18 * along with this program; if not, write to the 
     19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
     20 */ 
     21 
     22#include <linux/kernel.h> 
     23#include <linux/init.h> 
     24#include <linux/clk.h> 
     25#include <linux/module.h> 
     26#include <linux/platform_device.h> 
     27#include <linux/delay.h> 
     28#include <linux/interrupt.h> 
     29#include <linux/spi/spi.h> 
     30#include <linux/completion.h> 
     31#include <linux/err.h> 
     32 
     33#include <bcm63xx_dev_spi.h> 
     34 
     35#define PFX             KBUILD_MODNAME 
     36#define DRV_VER         "0.1.2" 
     37 
     38struct bcm63xx_spi { 
     39        spinlock_t              lock; 
     40        int                     stopping; 
     41        struct completion       done; 
     42 
     43        void __iomem            *regs; 
     44        int                     irq; 
     45 
     46        /* Platform data */ 
     47        u32                     speed_hz; 
     48        unsigned                fifo_size; 
     49 
     50        /* Data buffers */ 
     51        const unsigned char     *tx_ptr; 
     52        unsigned char           *rx_ptr; 
     53 
     54        /* data iomem */ 
     55        u8 __iomem              *tx_io; 
     56        const u8 __iomem        *rx_io; 
     57 
     58        int                     remaining_bytes; 
     59 
     60        struct clk              *clk; 
     61        struct platform_device  *pdev; 
     62}; 
     63 
     64static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs, 
     65                                unsigned int offset) 
     66{ 
     67        return bcm_readw(bs->regs + bcm63xx_spireg(offset)); 
     68} 
     69 
     70static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs, 
     71                                unsigned int offset) 
     72{ 
     73        return bcm_readw(bs->regs + bcm63xx_spireg(offset)); 
     74} 
     75 
     76static inline void bcm_spi_writeb(struct bcm63xx_spi *bs, 
     77                                  u8 value, unsigned int offset) 
     78{ 
     79        bcm_writeb(value, bs->regs + bcm63xx_spireg(offset)); 
     80} 
     81 
     82static inline void bcm_spi_writew(struct bcm63xx_spi *bs, 
     83                                  u16 value, unsigned int offset) 
     84{ 
     85        bcm_writew(value, bs->regs + bcm63xx_spireg(offset)); 
     86} 
     87 
     88static int bcm63xx_spi_setup_transfer(struct spi_device *spi, 
     89                                      struct spi_transfer *t) 
     90{ 
     91        u8 bits_per_word; 
     92        u8 clk_cfg; 
     93        u32 hz; 
     94        unsigned int div; 
     95 
     96        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     97 
     98        bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; 
     99        hz = (t) ? t->speed_hz : spi->max_speed_hz; 
     100        if (bits_per_word != 8) { 
     101                dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", 
     102                        __func__, bits_per_word); 
     103                return -EINVAL; 
     104        } 
     105 
     106        if (spi->chip_select > spi->master->num_chipselect) { 
     107                dev_err(&spi->dev, "%s, unsupported slave %d\n", 
     108                        __func__, spi->chip_select); 
     109                return -EINVAL; 
     110        } 
     111 
     112        /* Check clock setting */ 
     113        div = (bs->speed_hz / hz); 
     114        switch (div) { 
     115        case 2: 
     116                clk_cfg = SPI_CLK_25MHZ; 
     117                break; 
     118        case 4: 
     119                clk_cfg = SPI_CLK_12_50MHZ; 
     120                break; 
     121        case 8: 
     122                clk_cfg = SPI_CLK_6_250MHZ; 
     123                break; 
     124        case 16: 
     125                clk_cfg = SPI_CLK_3_125MHZ; 
     126                break; 
     127        case 32: 
     128                clk_cfg = SPI_CLK_1_563MHZ; 
     129                break; 
     130        case 64: 
     131                clk_cfg = SPI_CLK_0_781MHZ; 
     132                break; 
     133        case 128: 
     134        default: 
     135                /* Set to slowest mode for compatibility */ 
     136                clk_cfg = SPI_CLK_0_391MHZ; 
     137                break; 
     138        } 
     139 
     140        bcm_spi_writeb(bs, clk_cfg, SPI_CLK_CFG); 
     141        dev_dbg(&spi->dev, "Setting clock register to %d (hz %d, cmd %02x)\n", 
     142                div, hz, clk_cfg); 
     143 
     144        return 0; 
     145} 
     146 
     147/* the spi->mode bits understood by this driver: */ 
     148#define MODEBITS (SPI_CPOL | SPI_CPHA) 
     149 
     150static int bcm63xx_spi_setup(struct spi_device *spi) 
     151{ 
     152        struct bcm63xx_spi *bs; 
     153        int ret; 
     154 
     155        bs = spi_master_get_devdata(spi->master); 
     156 
     157        if (bs->stopping) 
     158                return -ESHUTDOWN; 
     159 
     160        if (!spi->bits_per_word) 
     161                spi->bits_per_word = 8; 
     162 
     163        if (spi->mode & ~MODEBITS) { 
     164                dev_err(&spi->dev, "%s, unsupported mode bits %x\n", 
     165                        __func__, spi->mode & ~MODEBITS); 
     166                return -EINVAL; 
     167        } 
     168 
     169        ret = bcm63xx_spi_setup_transfer(spi, NULL); 
     170        if (ret < 0) { 
     171                dev_err(&spi->dev, "setup: unsupported mode bits %x\n", 
     172                        spi->mode & ~MODEBITS); 
     173                return ret; 
     174        } 
     175 
     176        dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n", 
     177                __func__, spi->mode & MODEBITS, spi->bits_per_word, 0); 
     178 
     179        return 0; 
     180} 
     181 
     182/* Fill the TX FIFO with as many bytes as possible */ 
     183static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) 
     184{ 
     185        u8 size; 
     186 
     187        /* Fill the Tx FIFO with as many bytes as possible */ 
     188        size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes : 
     189                bs->fifo_size; 
     190        memcpy_toio(bs->tx_io, bs->tx_ptr, size); 
     191        bs->remaining_bytes -= size; 
     192} 
     193 
     194static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) 
     195{ 
     196        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     197        u16 msg_ctl; 
     198        u16 cmd; 
     199 
     200        dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", 
     201                t->tx_buf, t->rx_buf, t->len); 
     202 
     203        /* Transmitter is inhibited */ 
     204        bs->tx_ptr = t->tx_buf; 
     205        bs->rx_ptr = t->rx_buf; 
     206        init_completion(&bs->done); 
     207 
     208        if (t->tx_buf) { 
     209                bs->remaining_bytes = t->len; 
     210                bcm63xx_spi_fill_tx_fifo(bs); 
     211        } 
     212 
     213        /* Enable the command done interrupt which 
     214         * we use to determine completion of a command */ 
     215        bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); 
     216 
     217        /* Fill in the Message control register */ 
     218        msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); 
     219 
     220        if (t->rx_buf && t->tx_buf) 
     221                msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); 
     222        else if (t->rx_buf) 
     223                msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT); 
     224        else if (t->tx_buf) 
     225                msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT); 
     226 
     227        bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL); 
     228 
     229        /* Issue the transfer */ 
     230        cmd = SPI_CMD_START_IMMEDIATE; 
     231        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); 
     232        cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); 
     233        bcm_spi_writew(bs, cmd, SPI_CMD); 
     234        wait_for_completion(&bs->done); 
     235 
     236        /* Disable the CMD_DONE interrupt */ 
     237        bcm_spi_writeb(bs, 0, SPI_INT_MASK); 
     238 
     239        return t->len - bs->remaining_bytes; 
     240} 
     241 
     242static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m) 
     243{ 
     244        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     245        struct spi_transfer *t; 
     246        int ret = 0; 
     247 
     248        if (unlikely(list_empty(&m->transfers))) 
     249                return -EINVAL; 
     250 
     251        if (bs->stopping) 
     252                return -ESHUTDOWN; 
     253 
     254        list_for_each_entry(t, &m->transfers, transfer_list) { 
     255                ret += bcm63xx_txrx_bufs(spi, t); 
     256        } 
     257 
     258        m->complete(m->context); 
     259 
     260        return ret; 
     261} 
     262 
     263/* This driver supports single master mode only. Hence 
     264 * CMD_DONE is the only interrupt we care about 
     265 */ 
     266static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) 
     267{ 
     268        struct spi_master *master = (struct spi_master *)dev_id; 
     269        struct bcm63xx_spi *bs = spi_master_get_devdata(master); 
     270        u8 intr; 
     271        u16 cmd; 
     272 
     273        /* Read interupts and clear them immediately */ 
     274        intr = bcm_spi_readb(bs, SPI_INT_STATUS); 
     275        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); 
     276        bcm_spi_writeb(bs, 0, SPI_INT_MASK); 
     277 
     278        /* A tansfer completed */ 
     279        if (intr & SPI_INTR_CMD_DONE) { 
     280                u8 rx_tail; 
     281 
     282                rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL); 
     283 
     284                /* Read out all the data */ 
     285                if (rx_tail) 
     286                        memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); 
     287 
     288                /* See if there is more data to send */ 
     289                if (bs->remaining_bytes > 0) { 
     290                        bcm63xx_spi_fill_tx_fifo(bs); 
     291 
     292                        /* Start the transfer */ 
     293                        bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT, 
     294                                       SPI_MSG_CTL); 
     295                        cmd = bcm_spi_readw(bs, SPI_CMD); 
     296                        cmd |= SPI_CMD_START_IMMEDIATE; 
     297                        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); 
     298                        bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); 
     299                        bcm_spi_writew(bs, cmd, SPI_CMD); 
     300                } else { 
     301                        complete(&bs->done); 
     302                } 
     303        } 
     304 
     305        return IRQ_HANDLED; 
     306} 
     307 
     308 
     309static int __init bcm63xx_spi_probe(struct platform_device *pdev) 
     310{ 
     311        struct resource *r; 
     312        struct device *dev = &pdev->dev; 
     313        struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data; 
     314        int irq; 
     315        struct spi_master *master; 
     316        struct clk *clk; 
     317        struct bcm63xx_spi *bs; 
     318        int ret; 
     319 
     320        r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     321        if (!r) { 
     322                dev_err(dev, "no iomem\n"); 
     323                ret = -ENXIO; 
     324                goto out; 
     325        } 
     326 
     327        irq = platform_get_irq(pdev, 0); 
     328        if (irq < 0) { 
     329                dev_err(dev, "no irq\n"); 
     330                ret = -ENXIO; 
     331                goto out; 
     332        } 
     333 
     334        clk = clk_get(dev, "spi"); 
     335        if (IS_ERR(clk)) { 
     336                dev_err(dev, "no clock for device\n"); 
     337                ret = -ENODEV; 
     338                goto out; 
     339        } 
     340 
     341        master = spi_alloc_master(dev, sizeof(*bs)); 
     342        if (!master) { 
     343                dev_err(dev, "out of memory\n"); 
     344                ret = -ENOMEM; 
     345                goto out_free; 
     346        } 
     347 
     348        bs = spi_master_get_devdata(master); 
     349        init_completion(&bs->done); 
     350 
     351        platform_set_drvdata(pdev, master); 
     352        bs->pdev = pdev; 
     353 
     354        if (!request_mem_region(r->start, r->end - r->start, PFX)) { 
     355                dev_err(dev, "iomem request failed\n"); 
     356                ret = -ENXIO; 
     357                goto out_put_master; 
     358        } 
     359 
     360        bs->regs = ioremap_nocache(r->start, r->end - r->start); 
     361        if (!bs->regs) { 
     362                dev_err(dev, "unable to ioremap regs\n"); 
     363                ret = -ENOMEM; 
     364                goto out_put_master; 
     365        } 
     366        bs->irq = irq; 
     367        bs->clk = clk; 
     368        bs->fifo_size = pdata->fifo_size; 
     369 
     370        ret = request_irq(irq, bcm63xx_spi_interrupt, 0, pdev->name, master); 
     371        if (ret) { 
     372                dev_err(dev, "unable to request irq\n"); 
     373                goto out_unmap; 
     374        } 
     375 
     376        master->bus_num = pdata->bus_num; 
     377        master->num_chipselect = pdata->num_chipselect; 
     378        master->setup = bcm63xx_spi_setup; 
     379        master->transfer = bcm63xx_transfer; 
     380        bs->speed_hz = pdata->speed_hz; 
     381        bs->stopping = 0; 
     382        bs->tx_io = (u8*)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); 
     383        bs->rx_io = (const u8*)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); 
     384        spin_lock_init(&bs->lock); 
     385 
     386        /* Initialize hardware */ 
     387        clk_enable(bs->clk); 
     388        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS); 
     389 
     390        /* register and we are done */ 
     391        ret = spi_register_master(master); 
     392        if (ret) { 
     393                dev_err(dev, "spi register failed\n"); 
     394                goto out_reset_hw; 
     395        } 
     396 
     397        dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n", 
     398                 r->start, irq, bs->fifo_size, DRV_VER); 
     399 
     400        return 0; 
     401 
     402out_reset_hw: 
     403        clk_disable(clk); 
     404        free_irq(irq, master); 
     405out_unmap: 
     406        iounmap(bs->regs); 
     407out_put_master: 
     408        spi_master_put(master); 
     409out_free: 
     410        clk_put(clk); 
     411out: 
     412        return ret; 
     413} 
     414 
     415static int __exit bcm63xx_spi_remove(struct platform_device *pdev) 
     416{ 
     417        struct spi_master       *master = platform_get_drvdata(pdev); 
     418        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     419        struct resource         *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     420 
     421        /* reset spi block */ 
     422        bcm_spi_writeb(bs, 0, SPI_INT_MASK); 
     423        spin_lock(&bs->lock); 
     424        bs->stopping = 1; 
     425 
     426        /* HW shutdown */ 
     427        clk_disable(bs->clk); 
     428        clk_put(bs->clk); 
     429 
     430        spin_unlock(&bs->lock); 
     431 
     432        free_irq(bs->irq, master); 
     433        iounmap(bs->regs); 
     434        release_mem_region(r->start, r->end - r->start); 
     435        platform_set_drvdata(pdev, 0); 
     436        spi_unregister_master(master); 
     437 
     438        return 0; 
     439} 
     440 
     441#ifdef CONFIG_PM 
     442static int bcm63xx_spi_suspend(struct platform_device *pdev, pm_message_t mesg) 
     443{ 
     444        struct spi_master       *master = platform_get_drvdata(pdev); 
     445        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     446 
     447        clk_disable(bs->clk); 
     448 
     449        return 0; 
     450} 
     451 
     452static int bcm63xx_spi_resume(struct platform_device *pdev) 
     453{ 
     454        struct spi_master       *master = platform_get_drvdata(pdev); 
     455        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     456 
     457        clk_enable(bs->clk); 
     458 
     459        return 0; 
     460} 
     461#else 
     462#define bcm63xx_spi_suspend     NULL 
     463#define bcm63xx_spi_resume      NULL 
     464#endif 
     465 
     466static struct platform_driver bcm63xx_spi_driver = { 
     467        .driver = { 
     468                .name   = "bcm63xx-spi", 
     469                .owner  = THIS_MODULE, 
     470        }, 
     471        .probe          = bcm63xx_spi_probe, 
     472        .remove         = __exit_p(bcm63xx_spi_remove), 
     473        .suspend        = bcm63xx_spi_suspend, 
     474        .resume         = bcm63xx_spi_resume, 
     475}; 
     476 
     477 
     478static int __init bcm63xx_spi_init(void) 
     479{ 
     480        return platform_driver_register(&bcm63xx_spi_driver); 
     481} 
     482 
     483static void __exit bcm63xx_spi_exit(void) 
     484{ 
     485        platform_driver_unregister(&bcm63xx_spi_driver); 
     486} 
     487 
     488module_init(bcm63xx_spi_init); 
     489module_exit(bcm63xx_spi_exit); 
     490 
     491MODULE_ALIAS("platform:bcm63xx_spi"); 
     492MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 
     493MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>"); 
     494MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver"); 
     495MODULE_LICENSE("GPL"); 
     496MODULE_VERSION(DRV_VER); 
  • drivers/spi/Kconfig

    a b config SPI_ATMEL 
    7474          This selects a driver for the Atmel SPI Controller, present on 
    7575          many AT32 (AVR32) and AT91 (ARM) chips. 
    7676 
     77config SPI_BCM63XX 
     78        tristate "Broadcom BCM63xx SPI controller" 
     79        depends on BCM63XX 
     80        help 
     81          This is the SPI controller master driver for Broadcom BCM63xx SoC. 
     82 
    7783config SPI_BFIN 
    7884        tristate "SPI controller driver for ADI Blackfin5xx" 
    7985        depends on BLACKFIN 
  • drivers/spi/Makefile

    a b obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci. 
    5656obj-$(CONFIG_SPI_SH_MSIOF)              += spi_sh_msiof.o 
    5757obj-$(CONFIG_SPI_STMP3XXX)              += spi_stmp.o 
    5858obj-$(CONFIG_SPI_NUC900)                += spi_nuc900.o 
     59obj-$(CONFIG_SPI_BCM63XX)               += bcm63xx_spi.o 
    5960 
    6061# special build for s3c24xx spi driver with fiq support 
    6162spi_s3c24xx_hw-y                        := spi_s3c24xx.o 
  • new file arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h

    - +  
     1#ifndef BCM63XX_DEV_SPI_H 
     2#define BCM63XX_DEV_SPI_H 
     3 
     4#include <linux/types.h> 
     5#include <bcm63xx_io.h> 
     6#include <bcm63xx_regs.h> 
     7 
     8int __init bcm63xx_spi_register(void); 
     9 
     10struct bcm63xx_spi_pdata { 
     11        unsigned int    fifo_size; 
     12        int             bus_num; 
     13        int             num_chipselect; 
     14        u32             speed_hz; 
     15}; 
     16 
     17enum bcm63xx_regs_spi { 
     18        SPI_CMD, 
     19        SPI_INT_STATUS, 
     20        SPI_INT_MASK_ST, 
     21        SPI_INT_MASK, 
     22        SPI_ST, 
     23        SPI_CLK_CFG, 
     24        SPI_FILL_BYTE, 
     25        SPI_MSG_TAIL, 
     26        SPI_RX_TAIL, 
     27        SPI_MSG_CTL, 
     28        SPI_MSG_DATA, 
     29        SPI_RX_DATA, 
     30}; 
     31 
     32#define __GEN_SPI_RSET_BASE(__cpu, __rset)                              \ 
     33        case SPI_## __rset:                                             \ 
     34                return SPI_BCM_## __cpu ##_SPI_## __rset ##; 
     35 
     36#define __GEN_SPI_RSET(__cpu)                                           \ 
     37        switch (reg) {                                                  \ 
     38        __GEN_SPI_RSET_BASE(__cpu, CMD)                                 \ 
     39        __GEN_SPI_RSET_BASE(__cpu, INT_STATUS)                          \ 
     40        __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST)                         \ 
     41        __GEN_SPI_RSET_BASE(__cpu, INT_MASK)                            \ 
     42        __GEN_SPI_RSET_BASE(__cpu, ST)                                  \ 
     43        __GEN_SPI_RSET_BASE(__cpu, CLK_CFG)                             \ 
     44        __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE)                           \ 
     45        __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL)                            \ 
     46        __GEN_SPI_RSET_BASE(__cpu, RX_TAIL)                             \ 
     47        __GEN_SPI_RSET_BASE(__cpu, MSG_CTL)                             \ 
     48        __GEN_SPI_RSET_BASE(__cpu, MSG_DATA)                            \ 
     49        __GEN_SPI_RSET_BASE(__cpu, RX_DATA)                             \ 
     50        } 
     51 
     52#define __GEN_SPI_REGS_TABLE(__cpu)                                     \ 
     53        [SPI_CMD]               = SPI_BCM_## __cpu ##_SPI_CMD,          \ 
     54        [SPI_INT_STATUS]        = SPI_BCM_## __cpu ##_SPI_INT_STATUS,   \ 
     55        [SPI_INT_MASK_ST]       = SPI_BCM_## __cpu ##_SPI_INT_MASK_ST,  \ 
     56        [SPI_INT_MASK]          = SPI_BCM_## __cpu ##_SPI_INT_MASK,     \ 
     57        [SPI_ST]                = SPI_BCM_## __cpu ##_SPI_ST,           \ 
     58        [SPI_CLK_CFG]           = SPI_BCM_## __cpu ##_SPI_CLK_CFG,      \ 
     59        [SPI_FILL_BYTE]         = SPI_BCM_## __cpu ##_SPI_FILL_BYTE,    \ 
     60        [SPI_MSG_TAIL]          = SPI_BCM_## __cpu ##_SPI_MSG_TAIL,     \ 
     61        [SPI_RX_TAIL]           = SPI_BCM_## __cpu ##_SPI_RX_TAIL,      \ 
     62        [SPI_MSG_CTL]           = SPI_BCM_## __cpu ##_SPI_MSG_CTL,      \ 
     63        [SPI_MSG_DATA]          = SPI_BCM_## __cpu ##_SPI_MSG_DATA,     \ 
     64        [SPI_RX_DATA]           = SPI_BCM_## __cpu ##_SPI_RX_DATA, 
     65 
     66static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) 
     67{ 
     68#ifdef BCMCPU_RUNTIME_DETECT 
     69        extern const unsigned long *bcm63xx_regs_spi; 
     70        return bcm63xx_regs_spi[reg]; 
     71#else 
     72#ifdef CONFIG_BCM63XX_CPU_6338 
     73        __GEN_SPI_RSET(6338) 
     74#endif 
     75#ifdef CONFIG_BCM63XX_CPU_6348 
     76        __GEN_SPI_RSET(6348) 
     77#endif 
     78#ifdef CONFIG_BCM63XX_CPU_6358 
     79        __GEN_SPI_RSET(6358) 
     80#endif 
     81#endif 
     82        return 0; 
     83} 
     84 
     85#endif /* BCM63XX_DEV_SPI_H */ 
  • arch/mips/bcm63xx/Makefile

    a b  
    11obj-y           += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ 
    22                   dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o \ 
    3                    dev-usb-ohci.o dev-usb-ehci.o dev-usb-udc.o 
     3                   dev-usb-ohci.o dev-usb-ehci.o dev-usb-udc.o dev-spi.o 
    44obj-$(CONFIG_EARLY_PRINTK)      += early_printk.o 
    55 
    66obj-y           += boards/ 
  • arch/mips/bcm63xx/boards/board_bcm963xx.c

    a b  
    3030#include <bcm63xx_dev_usb_ohci.h> 
    3131#include <bcm63xx_dev_usb_ehci.h> 
    3232#include <bcm63xx_dev_usb_udc.h> 
     33#include <bcm63xx_dev_spi.h> 
    3334#include <board_bcm963xx.h> 
    3435 
    3536#define PFX     "board_bcm963xx: " 
    int __init board_register_devices(void) 
    943944        if (board.num_spis) 
    944945                spi_register_board_info(board.spis, board.num_spis); 
    945946 
     947        bcm63xx_spi_register(); 
     948 
    946949        /* read base address of boot chip select (0) */ 
    947950        if (BCMCPU_IS_6345()) 
    948951                val = 0x1fc00000; 
Note: See TracBrowser for help on using the repository browser.