source: trunk/target/linux/brcm63xx/patches-2.6.32/240-spi.patch @ 21631

Last change on this file since 21631 was 21631, checked in by cshore, 6 years ago

brcm63xx: Fixed 96348GW (Tecom Gx00) LED definitions to match reality (vs reference design)

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

    old new  
    5555 
    5656static const int bcm96338_irqs[] = { 
    5757        [IRQ_TIMER]             = BCM_6338_TIMER_IRQ, 
     58        [IRQ_SPI]               = BCM_6338_SPI_IRQ, 
    5859        [IRQ_UART0]             = BCM_6338_UART0_IRQ, 
    5960        [IRQ_DSL]               = BCM_6338_DSL_IRQ, 
    6061        [IRQ_ENET0]             = BCM_6338_ENET0_IRQ, 
     
    127128 
    128129static const int bcm96348_irqs[] = { 
    129130        [IRQ_TIMER]             = BCM_6348_TIMER_IRQ, 
     131        [IRQ_SPI]               = BCM_6348_SPI_IRQ, 
    130132        [IRQ_UART0]             = BCM_6348_UART0_IRQ, 
    131133        [IRQ_DSL]               = BCM_6348_DSL_IRQ, 
    132134        [IRQ_ENET0]             = BCM_6348_ENET0_IRQ, 
     
    169171 
    170172static const int bcm96358_irqs[] = { 
    171173        [IRQ_TIMER]             = BCM_6358_TIMER_IRQ, 
     174        [IRQ_SPI]               = BCM_6358_SPI_IRQ, 
    172175        [IRQ_UART0]             = BCM_6358_UART0_IRQ, 
    173176        [IRQ_DSL]               = BCM_6358_DSL_IRQ, 
    174177        [IRQ_ENET0]             = BCM_6358_ENET0_IRQ, 
  • new file linux-2.6.32.13/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 Florian Fainelli <florian@openwrt.org> 
     7 */ 
     8 
     9#include <linux/init.h> 
     10#include <linux/kernel.h> 
     11#include <linux/platform_device.h> 
     12 
     13#include <bcm63xx_cpu.h> 
     14#include <bcm63xx_dev_spi.h> 
     15#include <bcm63xx_regs.h> 
     16 
     17static struct resource spi_resources[] = { 
     18        { 
     19                .start          = -1, /* filled at runtime */ 
     20                .end            = -1, /* filled at runtime */ 
     21                .flags          = IORESOURCE_MEM, 
     22        }, 
     23        { 
     24                .start          = -1, /* filled at runtime */ 
     25                .flags          = IORESOURCE_IRQ, 
     26        }, 
     27}; 
     28 
     29static struct bcm63xx_spi_pdata spi_pdata = { 
     30        .bus_num                = 0, 
     31        .num_chipselect         = 4, 
     32        .speed_hz               = 50000000,     /* Fclk */ 
     33}; 
     34 
     35static struct platform_device bcm63xx_spi_device = { 
     36        .name           = "bcm63xx-spi", 
     37        .id             = 0, 
     38        .num_resources  = ARRAY_SIZE(spi_resources), 
     39        .resource       = spi_resources, 
     40        .dev            = { 
     41                .platform_data = &spi_pdata, 
     42        }, 
     43}; 
     44 
     45int __init bcm63xx_spi_register(void) 
     46{ 
     47        spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); 
     48        spi_resources[0].end = spi_resources[0].start; 
     49        spi_resources[0].end += RSET_SPI_SIZE - 1; 
     50        spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); 
     51 
     52        /* Fill in platform data */ 
     53        if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) 
     54                spi_pdata.fifo_size = SPI_BCM_6338_SPI_MSG_DATA_SIZE; 
     55 
     56        if (BCMCPU_IS_6358()) 
     57                spi_pdata.fifo_size = SPI_BCM_6358_SPI_MSG_DATA_SIZE; 
     58 
     59        return platform_device_register(&bcm63xx_spi_device); 
     60} 
  • arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h

    old new  
    108108#define RSET_WDT_SIZE                   12 
    109109#define RSET_ENET_SIZE                  2048 
    110110#define RSET_ENETDMA_SIZE               2048 
     111#define RSET_SPI_SIZE                   256 
    111112#define RSET_UART_SIZE                  24 
    112113#define RSET_UDC_SIZE                   256 
    113114#define RSET_OHCI_SIZE                  256 
     
    209210#define BCM_6358_WDT_BASE               (0xfffe005c) 
    210211#define BCM_6358_UART0_BASE             (0xfffe0100) 
    211212#define BCM_6358_GPIO_BASE              (0xfffe0080) 
    212 #define BCM_6358_SPI_BASE               (0xdeadbeef) 
     213#define BCM_6358_SPI_BASE               (0xfffe0800) 
    213214#define BCM_6358_UDC0_BASE              (0xfffe0400) 
    214215#define BCM_6358_OHCI0_BASE             (0xfffe1400) 
    215216#define BCM_6358_OHCI_PRIV_BASE         (0xdeadbeef) 
     
    428429 */ 
    429430enum bcm63xx_irq { 
    430431        IRQ_TIMER = 0, 
     432        IRQ_SPI, 
    431433        IRQ_UART0, 
    432434        IRQ_DSL, 
    433435        IRQ_UDC0, 
     
    493495 * 6348 irqs 
    494496 */ 
    495497#define BCM_6348_TIMER_IRQ              (IRQ_INTERNAL_BASE + 0) 
     498#define BCM_6348_SPI_IRQ                (IRQ_INTERNAL_BASE + 1) 
    496499#define BCM_6348_UART0_IRQ              (IRQ_INTERNAL_BASE + 2) 
    497500#define BCM_6348_DSL_IRQ                (IRQ_INTERNAL_BASE + 4) 
    498501#define BCM_6348_UDC0_IRQ               (IRQ_INTERNAL_BASE + 6) 
     
    517520 * 6358 irqs 
    518521 */ 
    519522#define BCM_6358_TIMER_IRQ              (IRQ_INTERNAL_BASE + 0) 
     523#define BCM_6358_SPI_IRQ                (IRQ_INTERNAL_BASE + 1) 
    520524#define BCM_6358_UART0_IRQ              (IRQ_INTERNAL_BASE + 2) 
    521525#define BCM_6358_OHCI0_IRQ              (IRQ_INTERNAL_BASE + 5) 
    522526#define BCM_6358_ENET1_IRQ              (IRQ_INTERNAL_BASE + 6) 
  • arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h

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

    - +  
     1/* 
     2 * Broadcom BCM63xx SPI controller support 
     3 * 
     4 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> 
     5 * 
     6 * This program is free software; you can redistribute it and/or 
     7 * modify it under the terms of the GNU General Public License 
     8 * as published by the Free Software Foundation; either version 2 
     9 * of the License, or (at your option) any later version. 
     10 * 
     11 * This program is distributed in the hope that it will be useful, 
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     14 * GNU General Public License for more details. 
     15 * 
     16 * You should have received a copy of the GNU General Public License 
     17 * along with this program; if not, write to the 
     18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
     19 */ 
     20 
     21#include <linux/kernel.h> 
     22#include <linux/init.h> 
     23#include <linux/clk.h> 
     24#include <linux/module.h> 
     25#include <linux/platform_device.h> 
     26#include <linux/delay.h> 
     27#include <linux/interrupt.h> 
     28#include <linux/spi/spi.h> 
     29#include <linux/spi/spi_bitbang.h> 
     30#include <linux/gpio.h> 
     31#include <linux/completion.h> 
     32#include <linux/err.h> 
     33 
     34#include <bcm63xx_io.h> 
     35#include <bcm63xx_regs.h> 
     36#include <bcm63xx_dev_spi.h> 
     37 
     38#define PFX             KBUILD_MODNAME 
     39#define DRV_VER         "0.1.2" 
     40 
     41enum bcm63xx_regs_spi { 
     42        SPI_CMD, 
     43        SPI_INT_STATUS, 
     44        SPI_INT_MASK_ST, 
     45        SPI_INT_MASK, 
     46        SPI_ST, 
     47        SPI_CLK_CFG, 
     48        SPI_FILL_BYTE, 
     49        SPI_MSG_TAIL, 
     50        SPI_RX_TAIL, 
     51        SPI_MSG_CTL, 
     52        SPI_MSG_DATA, 
     53        SPI_RX_DATA, 
     54}; 
     55 
     56/* 
     57 * register offsets 
     58 */ 
     59static const unsigned long bcm96338_regs_spi[] = { 
     60        [SPI_CMD]               = SPI_BCM_6338_SPI_CMD, 
     61        [SPI_INT_STATUS]        = SPI_BCM_6338_SPI_INT_STATUS, 
     62        [SPI_INT_MASK_ST]       = SPI_BCM_6338_SPI_MASK_INT_ST, 
     63        [SPI_INT_MASK]          = SPI_BCM_6338_SPI_INT_MASK, 
     64        [SPI_ST]                = SPI_BCM_6338_SPI_ST, 
     65        [SPI_CLK_CFG]           = SPI_BCM_6338_SPI_CLK_CFG, 
     66        [SPI_FILL_BYTE]         = SPI_BCM_6338_SPI_FILL_BYTE, 
     67        [SPI_MSG_TAIL]          = SPI_BCM_6338_SPI_MSG_TAIL, 
     68        [SPI_RX_TAIL]           = SPI_BCM_6338_SPI_RX_TAIL, 
     69        [SPI_MSG_CTL]           = SPI_BCM_6338_SPI_MSG_CTL, 
     70        [SPI_MSG_DATA]          = SPI_BCM_6338_SPI_MSG_DATA, 
     71        [SPI_RX_DATA]           = SPI_BCM_6338_SPI_RX_DATA, 
     72}; 
     73 
     74static const unsigned long bcm96348_regs_spi[] = { 
     75        [SPI_CMD]               = SPI_BCM_6348_SPI_CMD, 
     76        [SPI_INT_STATUS]        = SPI_BCM_6348_SPI_INT_STATUS, 
     77        [SPI_INT_MASK_ST]       = SPI_BCM_6348_SPI_MASK_INT_ST, 
     78        [SPI_INT_MASK]          = SPI_BCM_6348_SPI_INT_MASK, 
     79        [SPI_ST]                = SPI_BCM_6348_SPI_ST, 
     80        [SPI_CLK_CFG]           = SPI_BCM_6348_SPI_CLK_CFG, 
     81        [SPI_FILL_BYTE]         = SPI_BCM_6348_SPI_FILL_BYTE, 
     82        [SPI_MSG_TAIL]          = SPI_BCM_6348_SPI_MSG_TAIL, 
     83        [SPI_RX_TAIL]           = SPI_BCM_6348_SPI_RX_TAIL, 
     84        [SPI_MSG_CTL]           = SPI_BCM_6348_SPI_MSG_CTL, 
     85        [SPI_MSG_DATA]          = SPI_BCM_6348_SPI_MSG_DATA, 
     86        [SPI_RX_DATA]           = SPI_BCM_6348_SPI_RX_DATA, 
     87}; 
     88 
     89static const unsigned long bcm96358_regs_spi[] = { 
     90        [SPI_CMD]               = SPI_BCM_6358_SPI_CMD, 
     91        [SPI_INT_STATUS]        = SPI_BCM_6358_SPI_INT_STATUS, 
     92        [SPI_INT_MASK_ST]       = SPI_BCM_6358_SPI_MASK_INT_ST, 
     93        [SPI_INT_MASK]          = SPI_BCM_6358_SPI_INT_MASK, 
     94        [SPI_ST]                = SPI_BCM_6358_SPI_STATUS, 
     95        [SPI_CLK_CFG]           = SPI_BCM_6358_SPI_CLK_CFG, 
     96        [SPI_FILL_BYTE]         = SPI_BCM_6358_SPI_FILL_BYTE, 
     97        [SPI_MSG_TAIL]          = SPI_BCM_6358_SPI_MSG_TAIL, 
     98        [SPI_RX_TAIL]           = SPI_BCM_6358_SPI_RX_TAIL, 
     99        [SPI_MSG_CTL]           = SPI_BCM_6358_MSG_CTL, 
     100        [SPI_MSG_DATA]          = SPI_BCM_6358_SPI_MSG_DATA, 
     101        [SPI_RX_DATA]           = SPI_BCM_6358_SPI_RX_DATA, 
     102}; 
     103 
     104 
     105#ifdef BCMCPU_RUNTIME_DETECT 
     106static const unsigned long *bcm63xx_regs_spi; 
     107 
     108static __init void bcm63xx_spi_regs_init(void) 
     109{ 
     110        if (BCMCPU_IS_6338()) 
     111                bcm63xx_regs_spi = bcm96338_regs_spi; 
     112        if (BCMCPU_IS_6348()) 
     113                bcm63xx_regs_spi = bcm96348_regs_spi; 
     114        if (BCMCPU_IS_6358()) 
     115                bcm63xx_regs_spi = bcm96358_regs_spi; 
     116} 
     117#else 
     118static __init void bcm63xx_spi_regs_init(void) { } 
     119#endif 
     120 
     121static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) 
     122{ 
     123#ifdef BCMCPU_RUNTIME_DETECT 
     124        return bcm63xx_regs_spi[reg]; 
     125#else 
     126#ifdef CONFIG_BCM63XX_CPU_6338 
     127switch (reg) { 
     128        case SPI_CMD: 
     129                return SPI_BCM_6338_SPI_CMD; 
     130        case SPI_INT_STATUS: 
     131                return SPI_BCM_6338_SPI_INT_STATUS; 
     132        case SPI_INT_MASK_ST: 
     133                return SPI_BCM_6338_SPI_MASK_INT_ST; 
     134        case SPI_INT_MASK: 
     135                return SPI_BCM_6338_SPI_INT_MASK; 
     136        case SPI_ST: 
     137                return SPI_BCM_6338_SPI_ST; 
     138        case SPI_CLK_CFG: 
     139                return SPI_BCM_6338_SPI_CLK_CFG; 
     140        case SPI_FILL_BYTE: 
     141                return SPI_BCM_6338_SPI_FILL_BYTE; 
     142        case SPI_MSG_TAIL: 
     143                return SPI_BCM_6338_SPI_MSG_TAIL; 
     144        case SPI_RX_TAIL: 
     145                return SPI_BCM_6338_SPI_RX_TAIL; 
     146        case SPI_MSG_CTL: 
     147                return SPI_BCM_6338_SPI_MSG_CTL; 
     148        case SPI_MSG_DATA: 
     149                return SPI_BCM_6338_SPI_MSG_DATA; 
     150        case SPI_RX_DATA: 
     151                return SPI_BCM_6338_SPI_RX_DATA; 
     152} 
     153#endif 
     154#ifdef CONFIG_BCM63XX_CPU_6348 
     155switch (reg) { 
     156        case SPI_CMD: 
     157                return SPI_BCM_6348_SPI_CMD; 
     158        case SPI_INT_MASK_ST: 
     159                return SPI_BCM_6348_SPI_MASK_INT_ST; 
     160        case SPI_INT_MASK: 
     161                return SPI_BCM_6348_SPI_INT_MASK; 
     162        case SPI_INT_STATUS: 
     163                return SPI_BCM_6348_SPI_INT_STATUS; 
     164        case SPI_ST: 
     165                return SPI_BCM_6348_SPI_ST; 
     166        case SPI_CLK_CFG: 
     167                return SPI_BCM_6348_SPI_CLK_CFG; 
     168        case SPI_FILL_BYTE: 
     169                return SPI_BCM_6348_SPI_FILL_BYTE; 
     170        case SPI_MSG_TAIL: 
     171                return SPI_BCM_6348_SPI_MSG_TAIL; 
     172        case SPI_RX_TAIL: 
     173                return SPI_BCM_6348_SPI_RX_TAIL; 
     174        case SPI_MSG_CTL: 
     175                return SPI_BCM_6348_SPI_MSG_CTL; 
     176        case SPI_MSG_DATA: 
     177                return SPI_BCM_6348_SPI_MSG_DATA; 
     178        case SPI_RX_DATA: 
     179                return SPI_BCM_6348_SPI_RX_DATA; 
     180} 
     181#endif 
     182#ifdef CONFIG_BCM63XX_CPU_6358 
     183switch (reg) { 
     184        case SPI_CMD: 
     185                return SPI_BCM_6358_SPI_CMD; 
     186        case SPI_INT_STATUS: 
     187                return SPI_BCM_6358_SPI_INT_STATUS; 
     188        case SPI_INT_MASK_ST: 
     189                return SPI_BCM_6358_SPI_MASK_INT_ST; 
     190        case SPI_INT_MASK: 
     191                return SPI_BCM_6358_SPI_INT_MASK; 
     192        case SPI_ST: 
     193                return SPI_BCM_6358_SPI_STATUS; 
     194        case SPI_CLK_CFG: 
     195                return SPI_BCM_6358_SPI_CLK_CFG; 
     196        case SPI_FILL_BYTE: 
     197                return SPI_BCM_6358_SPI_FILL_BYTE; 
     198        case SPI_MSG_TAIL: 
     199                return SPI_BCM_6358_SPI_MSG_TAIL; 
     200        case SPI_RX_TAIL: 
     201                return SPI_BCM_6358_SPI_RX_TAIL; 
     202        case SPI_MSG_CTL: 
     203                return SPI_BCM_6358_MSG_CTL; 
     204        case SPI_MSG_DATA: 
     205                return SPI_BCM_6358_SPI_MSG_DATA; 
     206        case SPI_RX_DATA: 
     207                return SPI_BCM_6358_SPI_RX_DATA; 
     208} 
     209#endif 
     210#endif 
     211        return 0; 
     212} 
     213 
     214/* 
     215 * helpers for the SPI register sets 
     216 */ 
     217#define bcm_spi_readb(b,o)      bcm_readb((b) + bcm63xx_spireg(o)) 
     218#define bcm_spi_readw(b,o)      bcm_readw((b) + bcm63xx_spireg(o)) 
     219#define bcm_spi_writeb(v,b,o)   bcm_writeb((v), (b) + bcm63xx_spireg(o)) 
     220#define bcm_spi_writew(v,b,o)   bcm_writew((v), (b) + bcm63xx_spireg(o)) 
     221 
     222struct bcm63xx_spi { 
     223        /* bitbang has to be first */ 
     224        struct spi_bitbang      bitbang; 
     225        struct completion       done; 
     226 
     227        void __iomem            *regs; 
     228        int                     irq; 
     229 
     230        /* Platform data */ 
     231        u32                     speed_hz; 
     232        unsigned                fifo_size; 
     233 
     234        /* Data buffers */ 
     235        const unsigned char     *tx_ptr; 
     236        unsigned char           *rx_ptr; 
     237        int                     remaining_bytes; 
     238 
     239        struct clk              *clk; 
     240        struct resource         *ioarea; 
     241        struct platform_device  *pdev; 
     242}; 
     243 
     244static void bcm63xx_spi_chipselect(struct spi_device *spi, int is_on) 
     245{ 
     246        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     247        u16 val; 
     248 
     249        val = bcm_spi_readw(bs->regs, SPI_CMD); 
     250        if (is_on == BITBANG_CS_INACTIVE) 
     251                val |= SPI_CMD_NOOP; 
     252        else if (is_on == BITBANG_CS_ACTIVE) 
     253                val |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); 
     254 
     255        bcm_spi_writew(val, bs->regs, SPI_CMD); 
     256} 
     257 
     258static int bcm63xx_spi_setup_transfer(struct spi_device *spi, 
     259                                        struct spi_transfer *t) 
     260{ 
     261        u8 bits_per_word; 
     262        u8 clk_cfg; 
     263        u32 hz; 
     264        unsigned int div; 
     265 
     266        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     267 
     268        bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; 
     269        hz = (t) ? t->speed_hz : spi->max_speed_hz; 
     270        if (bits_per_word != 8) { 
     271                dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", 
     272                        __func__, bits_per_word); 
     273                return -EINVAL; 
     274        } 
     275 
     276        if (spi->chip_select > spi->master->num_chipselect) { 
     277                dev_err(&spi->dev, "%s, unsupported slave %d\n", 
     278                        __func__, spi->chip_select); 
     279                return -EINVAL; 
     280        } 
     281 
     282        /* Check clock setting */ 
     283        div = (bs->speed_hz / hz); 
     284        switch (div) { 
     285        case 2: 
     286                clk_cfg = SPI_CLK_25MHZ; 
     287                break; 
     288        case 4: 
     289                clk_cfg = SPI_CLK_12_50MHZ; 
     290                break; 
     291        case 8: 
     292                clk_cfg = SPI_CLK_6_250MHZ; 
     293                break; 
     294        case 16: 
     295                clk_cfg = SPI_CLK_3_125MHZ; 
     296                break; 
     297        case 32: 
     298                clk_cfg = SPI_CLK_1_563MHZ; 
     299                break; 
     300        case 128: 
     301                clk_cfg = SPI_CLK_0_781MHZ; 
     302                break; 
     303        case 64: 
     304        default: 
     305                /* Set to slowest mode for compatibility */ 
     306                clk_cfg = SPI_CLK_0_781MHZ; 
     307                break; 
     308        } 
     309 
     310        bcm_spi_writeb(clk_cfg, bs->regs, SPI_CLK_CFG); 
     311        dev_dbg(&spi->dev, "Setting clock register to %d (hz %d, cmd %02x)\n", 
     312                                                                div, hz, clk_cfg); 
     313 
     314        return 0; 
     315} 
     316 
     317/* the spi->mode bits understood by this driver: */ 
     318#define MODEBITS (SPI_CPOL | SPI_CPHA) 
     319 
     320static int bcm63xx_spi_setup(struct spi_device *spi) 
     321{ 
     322        struct spi_bitbang *bitbang; 
     323        struct bcm63xx_spi *bs; 
     324        int retval; 
     325 
     326        bs = spi_master_get_devdata(spi->master); 
     327        bitbang = &bs->bitbang; 
     328 
     329        if (!spi->bits_per_word) 
     330                spi->bits_per_word = 8; 
     331 
     332        if (spi->mode & ~MODEBITS) { 
     333                dev_err(&spi->dev, "%s, unsupported mode bits %x\n", 
     334                        __func__, spi->mode & ~MODEBITS); 
     335                return -EINVAL; 
     336        } 
     337 
     338        retval = bcm63xx_spi_setup_transfer(spi, NULL); 
     339        if (retval < 0) { 
     340                dev_err(&spi->dev, "setup: unsupported mode bits %x\n", 
     341                        spi->mode & ~MODEBITS); 
     342                return retval; 
     343        } 
     344 
     345        dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n", 
     346                __func__, spi->mode & MODEBITS, spi->bits_per_word, 0); 
     347 
     348        return 0; 
     349} 
     350 
     351/* Fill the TX FIFO with as many bytes as possible */ 
     352static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) 
     353{ 
     354        u8 tail; 
     355 
     356        /* Fill the Tx FIFO with as many bytes as possible */ 
     357        tail = bcm_spi_readb(bs->regs, SPI_MSG_TAIL); 
     358        while ((tail < bs->fifo_size) && (bs->remaining_bytes > 0)) { 
     359                if (bs->tx_ptr) 
     360                        bcm_spi_writeb(*bs->tx_ptr++, bs->regs, SPI_MSG_DATA); 
     361                else 
     362                        bcm_spi_writeb(0, bs->regs, SPI_MSG_DATA); 
     363                bs->remaining_bytes--; 
     364                tail = bcm_spi_readb(bs->regs, SPI_MSG_TAIL); 
     365        } 
     366} 
     367 
     368static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) 
     369{ 
     370        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); 
     371        u8 msg_ctl; 
     372        u16 cmd; 
     373 
     374        dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", 
     375                                t->tx_buf, t->rx_buf, t->len); 
     376 
     377        /* Transmitter is inhibited */ 
     378        bs->tx_ptr = t->tx_buf; 
     379        bs->rx_ptr = t->rx_buf; 
     380        bs->remaining_bytes = t->len; 
     381        init_completion(&bs->done); 
     382 
     383        bcm63xx_spi_fill_tx_fifo(bs); 
     384 
     385        /* Enable the command done interrupt which 
     386         * we use to determine completion of a command */ 
     387        bcm_spi_writeb(SPI_INTR_CMD_DONE, bs->regs, SPI_INT_MASK); 
     388 
     389        /* Fill in the Message control register */ 
     390        msg_ctl = bcm_spi_readb(bs->regs, SPI_MSG_CTL); 
     391        msg_ctl |= (t->len << SPI_BYTE_CNT_SHIFT); 
     392        msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT); 
     393        bcm_spi_writeb(msg_ctl, bs->regs, SPI_MSG_CTL); 
     394 
     395        /* Issue the transfer */ 
     396        cmd = bcm_spi_readw(bs->regs, SPI_CMD); 
     397        cmd |= SPI_CMD_START_IMMEDIATE; 
     398        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); 
     399        bcm_spi_writew(cmd, bs->regs, SPI_CMD); 
     400 
     401        wait_for_completion(&bs->done); 
     402 
     403        /* Disable the CMD_DONE interrupt */ 
     404        bcm_spi_writeb(~(SPI_INTR_CMD_DONE), bs->regs, SPI_INT_MASK); 
     405 
     406        return t->len - bs->remaining_bytes; 
     407} 
     408 
     409/* This driver supports single master mode only. Hence 
     410 * CMD_DONE is the only interrupt we care about 
     411 */ 
     412static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) 
     413{ 
     414        struct spi_master *master = (struct spi_master *)dev_id; 
     415        struct bcm63xx_spi *bs = spi_master_get_devdata(master); 
     416        u8 intr; 
     417        u16 cmd; 
     418 
     419        /* Read interupts and clear them immediately */ 
     420        intr = bcm_spi_readb(bs->regs, SPI_INT_STATUS); 
     421        bcm_spi_writeb(SPI_INTR_CLEAR_ALL, bs->regs, SPI_INT_MASK); 
     422 
     423        /* A tansfer completed */ 
     424        if (intr & SPI_INTR_CMD_DONE) { 
     425                u8 rx_empty; 
     426 
     427                rx_empty = bcm_spi_readb(bs->regs, SPI_ST); 
     428                /* Read out all the data */ 
     429                while ((rx_empty & SPI_RX_EMPTY) == 0) { 
     430                        u8 data; 
     431 
     432                        data = bcm_spi_readb(bs->regs, SPI_RX_DATA); 
     433                        if (bs->rx_ptr) 
     434                                *bs->rx_ptr++ = data; 
     435 
     436                        rx_empty = bcm_spi_readb(bs->regs, SPI_RX_EMPTY); 
     437                } 
     438 
     439                /* See if there is more data to send */ 
     440                if (bs->remaining_bytes > 0) { 
     441                        bcm63xx_spi_fill_tx_fifo(bs); 
     442 
     443                        /* Start the transfer */ 
     444                        cmd = bcm_spi_readw(bs->regs, SPI_CMD); 
     445                        cmd |= SPI_CMD_START_IMMEDIATE; 
     446                        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); 
     447                        bcm_spi_writew(cmd, bs->regs, SPI_CMD); 
     448                } else 
     449                        complete(&bs->done); 
     450        } 
     451 
     452        return IRQ_HANDLED; 
     453} 
     454 
     455 
     456static int __init bcm63xx_spi_probe(struct platform_device *pdev) 
     457{ 
     458        struct resource *r; 
     459        struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data; 
     460        int irq; 
     461        struct spi_master *master; 
     462        struct clk *clk; 
     463        struct bcm63xx_spi *bs; 
     464        int ret; 
     465 
     466        r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     467        if (!r) { 
     468                ret = -ENXIO; 
     469                goto out; 
     470        } 
     471 
     472        irq = platform_get_irq(pdev, 0); 
     473        if (irq < 0) { 
     474                ret = -ENXIO; 
     475                goto out; 
     476        } 
     477 
     478        bcm63xx_spi_regs_init(); 
     479 
     480        clk = clk_get(&pdev->dev, "spi"); 
     481        if (IS_ERR(clk)) { 
     482                dev_err(&pdev->dev, "No clock for device\n"); 
     483                ret = -ENODEV; 
     484                goto out; 
     485        } 
     486 
     487        master = spi_alloc_master(&pdev->dev, sizeof(struct bcm63xx_spi)); 
     488        if (!master) { 
     489                ret = -ENOMEM; 
     490                goto out_free; 
     491        } 
     492 
     493        bs = spi_master_get_devdata(master); 
     494        bs->bitbang.master = spi_master_get(master); 
     495        bs->bitbang.chipselect = bcm63xx_spi_chipselect; 
     496        bs->bitbang.setup_transfer = bcm63xx_spi_setup_transfer; 
     497        bs->bitbang.txrx_bufs = bcm63xx_txrx_bufs; 
     498        bs->bitbang.master->setup = bcm63xx_spi_setup; 
     499        init_completion(&bs->done); 
     500 
     501        platform_set_drvdata(pdev, master); 
     502        bs->pdev = pdev; 
     503 
     504        if (!request_mem_region(r->start, 
     505                        r->end - r->start, PFX)) { 
     506                ret = -ENXIO; 
     507                goto out_free; 
     508        } 
     509 
     510        bs->regs = ioremap_nocache(r->start, r->end - r->start); 
     511        if (!bs->regs) { 
     512                printk(KERN_ERR PFX " unable to ioremap regs\n"); 
     513                ret = -ENOMEM; 
     514                goto out_free; 
     515        } 
     516        bs->irq = irq; 
     517        bs->clk = clk; 
     518        bs->fifo_size = pdata->fifo_size; 
     519 
     520        ret = request_irq(irq, bcm63xx_spi_interrupt, 0, 
     521                                pdev->name, master); 
     522        if (ret) { 
     523                printk(KERN_ERR PFX " unable to request irq\n"); 
     524                goto out_unmap; 
     525        } 
     526 
     527        master->bus_num = pdata->bus_num; 
     528        master->num_chipselect = pdata->num_chipselect; 
     529        bs->speed_hz = pdata->speed_hz; 
     530 
     531        /* Initialize hardware */ 
     532        clk_enable(bs->clk); 
     533        bcm_spi_writeb(SPI_INTR_CLEAR_ALL, bs->regs, SPI_INT_MASK); 
     534 
     535        dev_info(&pdev->dev, " at 0x%08x (irq %d, FIFOs size %d) v%s\n", 
     536                                r->start, irq, bs->fifo_size, DRV_VER); 
     537 
     538        ret = spi_bitbang_start(&bs->bitbang); 
     539        if (ret) { 
     540                dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); 
     541                goto out_reset_hw; 
     542        } 
     543 
     544        return ret; 
     545 
     546out_reset_hw: 
     547        clk_disable(clk); 
     548        free_irq(irq, master); 
     549out_unmap: 
     550        iounmap(bs->regs); 
     551out_free: 
     552        clk_put(clk); 
     553        spi_master_put(master); 
     554out: 
     555        return ret; 
     556} 
     557 
     558static int __exit bcm63xx_spi_remove(struct platform_device *pdev) 
     559{ 
     560        struct spi_master       *master = platform_get_drvdata(pdev); 
     561        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     562 
     563        spi_bitbang_stop(&bs->bitbang); 
     564        clk_disable(bs->clk); 
     565        clk_put(bs->clk); 
     566        free_irq(bs->irq, master); 
     567        iounmap(bs->regs); 
     568        platform_set_drvdata(pdev, 0); 
     569        spi_master_put(bs->bitbang.master); 
     570 
     571        return 0; 
     572} 
     573 
     574#ifdef CONFIG_PM 
     575static int bcm63xx_spi_suspend(struct platform_device *pdev, pm_message_t mesg) 
     576{ 
     577        struct spi_master       *master = platform_get_drvdata(pdev); 
     578        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     579 
     580        clk_disable(bs->clk); 
     581 
     582        return 0; 
     583} 
     584 
     585static int bcm63xx_spi_resume(struct platform_device *pdev) 
     586{ 
     587        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     588        struct bcm63xx_spi      *bs = spi_master_get_devdata(master); 
     589 
     590        clk_enable(bs->clk); 
     591 
     592        return 0; 
     593} 
     594#else 
     595#define bcm63xx_spi_suspend     NULL 
     596#define bcm63xx_spi_resume      NULL 
     597#endif 
     598 
     599static struct platform_driver bcm63xx_spi_driver = { 
     600        .driver = { 
     601                .name   = "bcm63xx-spi", 
     602                .owner  = THIS_MODULE, 
     603        }, 
     604        .probe          = bcm63xx_spi_probe, 
     605        .remove         = bcm63xx_spi_remove, 
     606        .suspend        = bcm63xx_spi_suspend, 
     607        .resume         = bcm63xx_spi_resume, 
     608}; 
     609 
     610 
     611static int __init bcm63xx_spi_init(void) 
     612{ 
     613        return platform_driver_register(&bcm63xx_spi_driver); 
     614} 
     615 
     616static void __exit bcm63xx_spi_exit(void) 
     617{ 
     618        platform_driver_unregister(&bcm63xx_spi_driver); 
     619} 
     620 
     621module_init(bcm63xx_spi_init); 
     622module_exit(bcm63xx_spi_exit); 
     623 
     624MODULE_ALIAS("platform:bcm63xx_spi"); 
     625MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 
     626MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver"); 
     627MODULE_LICENSE("GPL"); 
     628MODULE_VERSION(DRV_VER); 
  • drivers/spi/Kconfig

    old new  
    6060          This selects a driver for the Atmel SPI Controller, present on 
    6161          many AT32 (AVR32) and AT91 (ARM) chips. 
    6262 
     63config SPI_BCM63XX 
     64        tristate "Broadcom BCM63xx SPI controller" 
     65        depends on BCM63XX 
     66        select SPI_BITBANG 
     67        help 
     68          This is the SPI controller master driver for Broadcom BCM63xx SoC. 
     69 
    6370config SPI_BFIN 
    6471        tristate "SPI controller driver for ADI Blackfin5xx" 
    6572        depends on BLACKFIN 
  • drivers/spi/Makefile

    old new  
    3434obj-$(CONFIG_SPI_XILINX)                += xilinx_spi.o 
    3535obj-$(CONFIG_SPI_SH_SCI)                += spi_sh_sci.o 
    3636obj-$(CONFIG_SPI_STMP3XXX)              += spi_stmp.o 
     37obj-$(CONFIG_SPI_BCM63XX)               += bcm63xx_spi.o 
    3738#       ... add above this line ... 
    3839 
    3940# SPI protocol drivers (device/link on bus) 
  • new file linux-2.6.32.13/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 
     6int __init bcm63xx_spi_register(void); 
     7 
     8struct bcm63xx_spi_pdata { 
     9        unsigned int    fifo_size; 
     10        int             bus_num; 
     11        int             num_chipselect; 
     12        u32             speed_hz; 
     13}; 
     14 
     15#endif /* BCM63XX_DEV_SPI_H */ 
  • arch/mips/bcm63xx/Makefile

    old new  
    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

    old new  
    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: " 
     
    14791480        if (board.has_udc0) 
    14801481                bcm63xx_udc_register(); 
    14811482 
     1483        if (!BCMCPU_IS_6345()) 
     1484                bcm63xx_spi_register(); 
     1485 
    14821486        /* Generate MAC address for WLAN and 
    14831487         * register our SPROM */ 
    14841488#ifdef CONFIG_SSB_PCIHOST 
Note: See TracBrowser for help on using the repository browser.