source: trunk/target/linux/generic-2.6/patches-2.6.28/921-gpio_spi_driver.patch @ 14465

Last change on this file since 14465 was 14465, checked in by mb, 8 years ago

Port SPI-GPIO driver from 2.6.29-rc4

File size: 10.5 KB
  • new file linux-2.6.28.2/include/linux/spi/spi_gpio_old.h

    THIS CODE IS DEPRECATED.
    
    Please use the new mainline SPI-GPIO driver, as of 2.6.29.
    
    --mb
    
    
    
    - +  
     1/* 
     2 * spi_gpio interface to platform code 
     3 * 
     4 * Copyright (c) 2008 Piotr Skamruk 
     5 * Copyright (c) 2008 Michael Buesch 
     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#ifndef _LINUX_SPI_SPI_GPIO 
     12#define _LINUX_SPI_SPI_GPIO 
     13 
     14#include <linux/types.h> 
     15#include <linux/spi/spi.h> 
     16 
     17 
     18/** 
     19 * struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device. 
     20 * 
     21 * This structure holds information about a GPIO-based SPI device. 
     22 * 
     23 * @pin_clk: The GPIO pin number of the CLOCK pin. 
     24 * 
     25 * @pin_miso: The GPIO pin number of the MISO pin. 
     26 * 
     27 * @pin_mosi: The GPIO pin number of the MOSI pin. 
     28 * 
     29 * @pin_cs: The GPIO pin number of the CHIPSELECT pin. 
     30 * 
     31 * @cs_activelow: If true, the chip is selected when the CS line is low. 
     32 * 
     33 * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging. 
     34 *                Note that doing no delay is not standards compliant, 
     35 *                but it might be needed to speed up transfers on some 
     36 *                slow embedded machines. 
     37 * 
     38 * @boardinfo_setup: This callback is called after the 
     39 *                   SPI master device was registered, but before the 
     40 *                   device is registered. 
     41 * @boardinfo_setup_data: Data argument passed to boardinfo_setup(). 
     42 */ 
     43struct spi_gpio_platform_data { 
     44        unsigned int pin_clk; 
     45        unsigned int pin_miso; 
     46        unsigned int pin_mosi; 
     47        unsigned int pin_cs; 
     48        bool cs_activelow; 
     49        bool no_spi_delay; 
     50        int (*boardinfo_setup)(struct spi_board_info *bi, 
     51                               struct spi_master *master, 
     52                               void *data); 
     53        void *boardinfo_setup_data; 
     54}; 
     55 
     56/** 
     57 * SPI_GPIO_PLATDEV_NAME - The platform device name string. 
     58 * 
     59 * The name string that has to be used for platform_device_alloc 
     60 * when allocating a spi-gpio device. 
     61 */ 
     62#define SPI_GPIO_PLATDEV_NAME   "spi-gpio" 
     63 
     64/** 
     65 * spi_gpio_next_id - Get another platform device ID number. 
     66 * 
     67 * This returns the next platform device ID number that has to be used 
     68 * for platform_device_alloc. The ID is opaque and should not be used for 
     69 * anything else. 
     70 */ 
     71int spi_gpio_next_id(void); 
     72 
     73#endif /* _LINUX_SPI_SPI_GPIO */ 
  • new file linux-2.6.28.2/drivers/spi/spi_gpio_old.c

    - +  
     1/* 
     2 * Bitbanging SPI bus driver using GPIO API 
     3 * 
     4 * Copyright (c) 2008 Piotr Skamruk 
     5 * Copyright (c) 2008 Michael Buesch 
     6 * 
     7 * based on spi_s3c2410_gpio.c 
     8 *   Copyright (c) 2006 Ben Dooks 
     9 *   Copyright (c) 2006 Simtec Electronics 
     10 * and on i2c-gpio.c 
     11 *   Copyright (C) 2007 Atmel Corporation 
     12 * 
     13 * This program is free software; you can redistribute it and/or modify 
     14 * it under the terms of the GNU General Public License version 2 as 
     15 * published by the Free Software Foundation. 
     16 */ 
     17 
     18#include <linux/kernel.h> 
     19#include <linux/init.h> 
     20#include <linux/delay.h> 
     21#include <linux/spinlock.h> 
     22#include <linux/workqueue.h> 
     23#include <linux/module.h> 
     24#include <linux/platform_device.h> 
     25#include <linux/spi/spi.h> 
     26#include <linux/spi/spi_bitbang.h> 
     27#include <linux/spi/spi_gpio_old.h> 
     28#include <linux/gpio.h> 
     29#include <asm/atomic.h> 
     30 
     31 
     32struct spi_gpio { 
     33        struct spi_bitbang bitbang; 
     34        struct spi_gpio_platform_data *info; 
     35        struct platform_device *pdev; 
     36        struct spi_board_info bi; 
     37}; 
     38 
     39 
     40static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev) 
     41{ 
     42        return dev->controller_data; 
     43} 
     44 
     45static inline void setsck(struct spi_device *dev, int val) 
     46{ 
     47        struct spi_gpio *sp = spidev_to_sg(dev); 
     48        gpio_set_value(sp->info->pin_clk, val ? 1 : 0); 
     49} 
     50 
     51static inline void setmosi(struct spi_device *dev, int val) 
     52{ 
     53        struct spi_gpio *sp = spidev_to_sg(dev); 
     54        gpio_set_value(sp->info->pin_mosi, val ? 1 : 0); 
     55} 
     56 
     57static inline u32 getmiso(struct spi_device *dev) 
     58{ 
     59        struct spi_gpio *sp = spidev_to_sg(dev); 
     60        return gpio_get_value(sp->info->pin_miso) ? 1 : 0; 
     61} 
     62 
     63static inline void do_spidelay(struct spi_device *dev, unsigned nsecs) 
     64{ 
     65        struct spi_gpio *sp = spidev_to_sg(dev); 
     66 
     67        if (!sp->info->no_spi_delay) 
     68                ndelay(nsecs); 
     69} 
     70 
     71#define spidelay(nsecs) do {                                    \ 
     72        /* Steal the spi_device pointer from our caller.        \ 
     73         * The bitbang-API should probably get fixed here... */ \ 
     74        do_spidelay(spi, nsecs);                                \ 
     75  } while (0) 
     76 
     77#define EXPAND_BITBANG_TXRX 
     78#include <linux/spi/spi_bitbang.h> 
     79 
     80static u32 spi_gpio_txrx_mode0(struct spi_device *spi, 
     81                               unsigned nsecs, u32 word, u8 bits) 
     82{ 
     83        return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); 
     84} 
     85 
     86static u32 spi_gpio_txrx_mode1(struct spi_device *spi, 
     87                               unsigned nsecs, u32 word, u8 bits) 
     88{ 
     89        return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); 
     90} 
     91 
     92static u32 spi_gpio_txrx_mode2(struct spi_device *spi, 
     93                               unsigned nsecs, u32 word, u8 bits) 
     94{ 
     95        return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); 
     96} 
     97 
     98static u32 spi_gpio_txrx_mode3(struct spi_device *spi, 
     99                               unsigned nsecs, u32 word, u8 bits) 
     100{ 
     101        return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); 
     102} 
     103 
     104static void spi_gpio_chipselect(struct spi_device *dev, int on) 
     105{ 
     106        struct spi_gpio *sp = spidev_to_sg(dev); 
     107 
     108        if (sp->info->cs_activelow) 
     109                on = !on; 
     110        gpio_set_value(sp->info->pin_cs, on ? 1 : 0); 
     111} 
     112 
     113static int spi_gpio_probe(struct platform_device *pdev) 
     114{ 
     115        struct spi_master *master; 
     116        struct spi_gpio_platform_data *pdata; 
     117        struct spi_gpio *sp; 
     118        struct spi_device *spidev; 
     119        int err; 
     120 
     121        pdata = pdev->dev.platform_data; 
     122        if (!pdata) 
     123                return -ENXIO; 
     124 
     125        err = -ENOMEM; 
     126        master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio)); 
     127        if (!master) 
     128                goto err_alloc_master; 
     129 
     130        sp = spi_master_get_devdata(master); 
     131        platform_set_drvdata(pdev, sp); 
     132        sp->info = pdata; 
     133 
     134        err = gpio_request(pdata->pin_clk, "spi_clock"); 
     135        if (err) 
     136                goto err_request_clk; 
     137        err = gpio_request(pdata->pin_mosi, "spi_mosi"); 
     138        if (err) 
     139                goto err_request_mosi; 
     140        err = gpio_request(pdata->pin_miso, "spi_miso"); 
     141        if (err) 
     142                goto err_request_miso; 
     143        err = gpio_request(pdata->pin_cs, "spi_cs"); 
     144        if (err) 
     145                goto err_request_cs; 
     146 
     147        sp->bitbang.master = spi_master_get(master); 
     148        sp->bitbang.master->bus_num = -1; 
     149        sp->bitbang.master->num_chipselect = 1; 
     150        sp->bitbang.chipselect = spi_gpio_chipselect; 
     151        sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0; 
     152        sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1; 
     153        sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2; 
     154        sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3; 
     155 
     156        gpio_direction_output(pdata->pin_clk, 0); 
     157        gpio_direction_output(pdata->pin_mosi, 0); 
     158        gpio_direction_output(pdata->pin_cs, 
     159                              pdata->cs_activelow ? 1 : 0); 
     160        gpio_direction_input(pdata->pin_miso); 
     161 
     162        err = spi_bitbang_start(&sp->bitbang); 
     163        if (err) 
     164                goto err_no_bitbang; 
     165        err = pdata->boardinfo_setup(&sp->bi, master, 
     166                                     pdata->boardinfo_setup_data); 
     167        if (err) 
     168                goto err_bi_setup; 
     169        sp->bi.controller_data = sp; 
     170        spidev = spi_new_device(master, &sp->bi); 
     171        if (!spidev) 
     172                goto err_new_dev; 
     173 
     174        return 0; 
     175 
     176err_new_dev: 
     177err_bi_setup: 
     178        spi_bitbang_stop(&sp->bitbang); 
     179err_no_bitbang: 
     180        spi_master_put(sp->bitbang.master); 
     181        gpio_free(pdata->pin_cs); 
     182err_request_cs: 
     183        gpio_free(pdata->pin_miso); 
     184err_request_miso: 
     185        gpio_free(pdata->pin_mosi); 
     186err_request_mosi: 
     187        gpio_free(pdata->pin_clk); 
     188err_request_clk: 
     189        kfree(master); 
     190 
     191err_alloc_master: 
     192        return err; 
     193} 
     194 
     195static int __devexit spi_gpio_remove(struct platform_device *pdev) 
     196{ 
     197        struct spi_gpio *sp; 
     198        struct spi_gpio_platform_data *pdata; 
     199 
     200        pdata = pdev->dev.platform_data; 
     201        sp = platform_get_drvdata(pdev); 
     202 
     203        gpio_free(pdata->pin_clk); 
     204        gpio_free(pdata->pin_mosi); 
     205        gpio_free(pdata->pin_miso); 
     206        gpio_free(pdata->pin_cs); 
     207        spi_bitbang_stop(&sp->bitbang); 
     208        spi_master_put(sp->bitbang.master); 
     209 
     210        return 0; 
     211} 
     212 
     213static struct platform_driver spi_gpio_driver = { 
     214        .driver         = { 
     215                .name   = SPI_GPIO_PLATDEV_NAME, 
     216                .owner  = THIS_MODULE, 
     217        }, 
     218        .probe          = spi_gpio_probe, 
     219        .remove         = __devexit_p(spi_gpio_remove), 
     220}; 
     221 
     222int spi_gpio_next_id(void) 
     223{ 
     224        static atomic_t counter = ATOMIC_INIT(-1); 
     225 
     226        return atomic_inc_return(&counter); 
     227} 
     228EXPORT_SYMBOL(spi_gpio_next_id); 
     229 
     230static int __init spi_gpio_init(void) 
     231{ 
     232        int err; 
     233 
     234        err = platform_driver_register(&spi_gpio_driver); 
     235        if (err) 
     236                printk(KERN_ERR "spi-gpio: register failed: %d\n", err); 
     237 
     238        return err; 
     239} 
     240module_init(spi_gpio_init); 
     241 
     242static void __exit spi_gpio_exit(void) 
     243{ 
     244        platform_driver_unregister(&spi_gpio_driver); 
     245} 
     246module_exit(spi_gpio_exit); 
     247 
     248MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>"); 
     249MODULE_AUTHOR("Michael Buesch"); 
     250MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver"); 
     251MODULE_LICENSE("GPL v2"); 
  • drivers/spi/Kconfig

    old new config SPI_GPIO 
    116116          GPIO operations, you should be able to leverage that for better 
    117117          speed with a custom version of this driver; see the source code. 
    118118 
     119config SPI_GPIO_OLD 
     120        tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)" 
     121        depends on SPI_MASTER && GENERIC_GPIO 
     122        select SPI_BITBANG 
     123        help 
     124          This code is deprecated. Please use the new mainline SPI-GPIO driver. 
     125 
     126          If unsure, say N. 
     127 
    119128config SPI_IMX 
    120129        tristate "Freescale iMX SPI controller" 
    121130        depends on ARCH_IMX && EXPERIMENTAL 
  • drivers/spi/Makefile

    old new obj-$(CONFIG_SPI_BITBANG) += spi_bitban 
    1717obj-$(CONFIG_SPI_AU1550)                += au1550_spi.o 
    1818obj-$(CONFIG_SPI_BUTTERFLY)             += spi_butterfly.o 
    1919obj-$(CONFIG_SPI_GPIO)                  += spi_gpio.o 
     20obj-$(CONFIG_SPI_GPIO_OLD)              += spi_gpio_old.o 
    2021obj-$(CONFIG_SPI_IMX)                   += spi_imx.o 
    2122obj-$(CONFIG_SPI_LM70_LLP)              += spi_lm70llp.o 
    2223obj-$(CONFIG_SPI_PXA2XX)                += pxa2xx_spi.o 
Note: See TracBrowser for help on using the repository browser.