Ticket #9461: ralink_spi.patch

File ralink_spi.patch, 18.3 KB (added by Sergiy <piratfm@…>, 5 years ago)

SPI bus driver for RT305x/RT288x

  • target/linux/ramips/files/arch/mips/ralink/rt305x/devices.c

     
    217217 
    218218        platform_device_register(&rt305x_wdt_device); 
    219219} 
     220 
     221static struct resource rt305x_spi_resources[] = { 
     222        { 
     223                .name   = "spi-regs", 
     224                .flags  = IORESOURCE_MEM, 
     225                .start  = RT305X_SPI_BASE, 
     226                .end    = RT305X_SPI_BASE + RT305X_SPI_SIZE - 1, 
     227        }, 
     228}; 
     229 
     230static struct platform_device rt305x_spi_device = { 
     231        .name           = "ramips-spi", 
     232        .id             = 0, 
     233        .resource       = rt305x_spi_resources, 
     234        .num_resources  = ARRAY_SIZE(rt305x_spi_resources), 
     235}; 
     236 
     237void __init rt305x_register_spi(void) 
     238{ 
     239        platform_device_register(&rt305x_spi_device); 
     240}; 
  • target/linux/ramips/files/arch/mips/ralink/rt305x/devices.h

     
    2121void rt305x_register_ethernet(void); 
    2222void rt305x_register_wifi(void); 
    2323void rt305x_register_wdt(void); 
     24void rt305x_register_spi(void); 
    2425 
    2526#endif  /* __RT305X_DEVICES_H */ 
    2627 
  • target/linux/ramips/files/arch/mips/include/asm/mach-ralink/ramips_spi.h

     
     1/* 
     2 * SPI Controller 
     3 * 
     4 * Copyright (C) 2011 Sergiy <piratfm@gmail.com> 
     5 * 
     6 * This code is free software; you can redistribute it and/or modify 
     7 * it under the terms of the GNU General Public License version 2 as 
     8 * published by the Free Software Foundation. 
     9 * 
     10 */ 
     11#ifndef __RAMIPS_SPIFLASH_H 
     12#define __RAMIPS_SPIFLASH_H 
     13 
     14#define RAMIPS_SPI_STAT         0x00 
     15#define RAMIPS_SPI_CFG          0x10 
     16#define RAMIPS_SPI_CTL          0x14 
     17#define RAMIPS_SPI_DATA         0x20 
     18 
     19/* SPISTAT register bit field */ 
     20#define SPISTAT_BUSY           0x00000001 
     21 
     22/* SPICFG register bit field */ 
     23#define SPICFG_LSBFIRST                 (0<<8) 
     24#define SPICFG_MSBFIRST                 (1<<8) 
     25#define SPICFG_RXCLKEDGE_FALLING        (1<<5)    /* rx on the falling edge of the SPICLK signal */ 
     26#define SPICFG_TXCLKEDGE_FALLING        (1<<4)    /* tx on the falling edge of the SPICLK signal */ 
     27#define SPICFG_SPICLK_DIV2              (0<<0)    /* system clock rate / 2  */ 
     28#define SPICFG_SPICLK_DIV4              (1<<0)    /* system clock rate / 4  */ 
     29#define SPICFG_SPICLK_DIV8              (2<<0)    /* system clock rate / 8  */ 
     30#define SPICFG_SPICLK_DIV16             (3<<0)    /* system clock rate / 16  */ 
     31#define SPICFG_SPICLK_DIV32             (4<<0)    /* system clock rate / 32  */ 
     32#define SPICFG_SPICLK_DIV64             (5<<0)    /* system clock rate / 64  */ 
     33#define SPICFG_SPICLK_DIV128            (6<<0)    /* system clock rate / 128 */ 
     34#define SPICFG_SPICLK_DISABLE           (7<<0)    /* system clock disabled */ 
     35#define SPICFG_SPICLKPOL                (1<<6)    /* spi clk*/ 
     36 
     37/* SPICTL register bit field */ 
     38#define SPICTL_HIZSDO                   (1<<3) 
     39#define SPICTL_STARTWR                  (1<<2) 
     40#define SPICTL_STARTRD                  (1<<1) 
     41#define SPICTL_SPIENA                   (1<<0) 
     42 
     43#define CFG_CLK_DIV             SPICFG_SPICLK_DIV16 
     44 
     45#endif 
  • target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_regs.h

     
    4242#define RT305X_UART0_SIZE       0x100 
    4343#define RT305X_PIO_SIZE         0x100 
    4444#define RT305X_UART1_SIZE       0x100 
     45#define RT305X_SPI_SIZE         0x100 
    4546#define RT305X_FLASH1_SIZE      (16 * 1024 * 1024) 
    4647#define RT305X_FLASH0_SIZE      (8 * 1024 * 1024) 
    4748 
  • target/linux/ramips/files/drivers/spi/ramips_spi.c

     
     1/* 
     2 * ramips_spi.c -- Ralink RT288x/RT305x SPI controller driver 
     3 * 
     4 * Author: Sergiy <piratfm@gmail.com> 
     5 * Copyright (C) 2011 OpenWrt.org. 
     6 * 
     7 * This program is free software; you can redistribute it and/or modify 
     8 * it under the terms of the GNU General Public License version 2 as 
     9 * published by the Free Software Foundation. 
     10 */ 
     11 
     12#include <linux/init.h> 
     13#include <linux/clk.h> 
     14#include <linux/err.h> 
     15#include <linux/delay.h> 
     16#include <linux/platform_device.h> 
     17#include <linux/err.h> 
     18#include <linux/io.h> 
     19#include <linux/spi/spi.h> 
     20#include <asm/unaligned.h> 
     21 
     22 
     23#if defined(CONFIG_RALINK_RT305X) 
     24#include <rt305x.h> 
     25#include <rt305x_regs.h> 
     26#elif defined(CONFIG_RALINK_RT288X) 
     27#include <rt288x.h> 
     28#include <rt288x_regs.h> 
     29#else 
     30#error "Add support for your platform" 
     31#endif 
     32 
     33#include <asm/mach-ralink/ramips_spi.h> 
     34 
     35#define DRIVER_NAME                     "ramips-spi" 
     36#define RALINK_NUM_CHIPSELECTS          1 /* only one slave is supported*/ 
     37#define RALINK_SPI_WAIT_RDY_MAX_LOOP    2000 /* in usec */ 
     38#define SPICFG_CLK_PRESCALE_MASK        0x07 
     39 
     40//#define DEBUG 
     41 
     42#ifdef DEBUG 
     43#define spi_debug(args...) printk(args) 
     44#else 
     45#define spi_debug(args...) 
     46#endif 
     47 
     48 
     49struct ramips_spi { 
     50        struct work_struct      work; 
     51 
     52        /* Lock access to transfer list.        */ 
     53        spinlock_t              lock; 
     54 
     55        struct list_head        msg_queue; 
     56        struct spi_master       *master; 
     57        void __iomem            *base; 
     58        unsigned int            sys_freq; 
     59        unsigned int            speed; 
     60}; 
     61 
     62static struct workqueue_struct *ramips_spi_wq; 
     63 
     64static inline void __iomem *spi_reg(struct ramips_spi *ramips_spi, u32 reg) 
     65{ 
     66        return ramips_spi->base + reg; 
     67} 
     68 
     69static inline void 
     70ramips_spi_setbits(struct ramips_spi *ramips_spi, u32 reg, u32 mask) 
     71{ 
     72        void __iomem *reg_addr = spi_reg(ramips_spi, reg); 
     73        u32 val; 
     74 
     75        val = readl(reg_addr); 
     76        val |= mask; 
     77        writel(val, reg_addr); 
     78} 
     79 
     80static inline void 
     81ramips_spi_clrbits(struct ramips_spi *ramips_spi, u32 reg, u32 mask) 
     82{ 
     83        void __iomem *reg_addr = spi_reg(ramips_spi, reg); 
     84        u32 val; 
     85 
     86        val = readl(reg_addr); 
     87        val &= ~mask; 
     88        writel(val, reg_addr); 
     89} 
     90 
     91static int ramips_spi_baudrate_set(struct spi_device *spi, unsigned int speed) 
     92{ 
     93 
     94        u32 rate; 
     95        u32 prescale; 
     96        u32 reg; 
     97        struct ramips_spi *ramips_spi = spi_master_get_devdata(spi->master); 
     98 
     99        spi_debug("%s: speed:%u\n", __func__, speed); 
     100 
     101        /* 
     102         * the supported rates are: 2,4,8...128 
     103         * round up as we look for equal or less speed 
     104         */ 
     105        rate = DIV_ROUND_UP(ramips_spi->sys_freq, speed); 
     106        spi_debug("%s: rate-1:%u\n", __func__, rate); 
     107        rate = roundup_pow_of_two(rate); 
     108        spi_debug("%s: rate-2:%u\n", __func__, rate); 
     109 
     110        /* check if requested speed is too small */ 
     111        if (rate > 128) 
     112                return -EINVAL; 
     113 
     114        if (rate < 2) 
     115                rate = 2; 
     116 
     117        /* Convert the rate to SPI clock divisor value. */ 
     118        prescale = ilog2(rate/2); 
     119        spi_debug("%s: prescale:%u\n", __func__, prescale); 
     120 
     121        reg = readl(spi_reg(ramips_spi, RAMIPS_SPI_CFG)); 
     122        reg = ((reg & ~SPICFG_CLK_PRESCALE_MASK) | prescale); 
     123        writel(reg, spi_reg(ramips_spi, RAMIPS_SPI_CFG)); 
     124        ramips_spi->speed = speed; 
     125        return 0; 
     126} 
     127 
     128/* 
     129 * called only when no transfer is active on the bus 
     130 */ 
     131static int 
     132ramips_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) 
     133{ 
     134        struct ramips_spi *ramips_spi = spi_master_get_devdata(spi->master); 
     135        unsigned int speed = spi->max_speed_hz; 
     136        int     rc; 
     137        unsigned int bits_per_word = 8; 
     138 
     139        if ((t != NULL) && t->speed_hz) 
     140                speed = t->speed_hz; 
     141 
     142        if ((t != NULL) && t->bits_per_word) 
     143                bits_per_word = t->bits_per_word; 
     144 
     145        if(ramips_spi->speed != speed){ 
     146                spi_debug("%s: speed_hz:%u\n", __func__, speed); 
     147                rc = ramips_spi_baudrate_set(spi, speed); 
     148                if (rc) 
     149                        return rc; 
     150        } 
     151 
     152        if(bits_per_word != 8) { 
     153                spi_debug("%s: bad bits_per_word: %u\n", __func__, bits_per_word); 
     154                return -EINVAL; 
     155        } 
     156 
     157        return 0; 
     158} 
     159 
     160static void ramips_spi_set_cs(struct ramips_spi *ramips_spi, int enable) 
     161{ 
     162        if (enable) 
     163                ramips_spi_clrbits(ramips_spi, RAMIPS_SPI_CTL, SPICTL_SPIENA); 
     164        else 
     165                ramips_spi_setbits(ramips_spi, RAMIPS_SPI_CTL, SPICTL_SPIENA); 
     166} 
     167 
     168static inline int ramips_spi_wait_till_ready(struct ramips_spi *ramips_spi) 
     169{ 
     170        int i; 
     171 
     172        for (i = 0; i < RALINK_SPI_WAIT_RDY_MAX_LOOP; i++) { 
     173                if (readl(spi_reg(ramips_spi, RAMIPS_SPI_STAT)) & SPISTAT_BUSY) 
     174                        udelay(1); 
     175                else 
     176                        return 1; 
     177        } 
     178 
     179        return -1; 
     180} 
     181 
     182static unsigned int 
     183ramips_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) 
     184{ 
     185        struct ramips_spi *ramips_spi = spi_master_get_devdata(spi->master); 
     186        unsigned count = 0; 
     187        u8 *rx = xfer->rx_buf; 
     188        const u8 *tx = xfer->tx_buf; 
     189        void __iomem *tx_rx_reg = spi_reg(ramips_spi, RAMIPS_SPI_DATA); 
     190 
     191        spi_debug("%s(%d): %s %s\n", __func__, xfer->len, (tx!=NULL)?("tx"):("  "), (rx!=NULL)?("rx"):("  ")); 
     192        if(tx) { 
     193                for(count=0; count<xfer->len; count++){ 
     194                        writel(tx[count], tx_rx_reg); 
     195                        ramips_spi_setbits(ramips_spi, RAMIPS_SPI_CTL, SPICTL_STARTWR); 
     196                        if (ramips_spi_wait_till_ready(ramips_spi) < 0) {