主题 : mini2440 spi 总线 驱动 同一总线 多设备片选解决方法 复制链接 | 浏览器收藏 | 打印
jbx
级别: 新手上路
UID: 13121
精华: 0
发帖: 19
金钱: 100 两
威望: 20 点
贡献值: 0 点
综合积分: 38 分
注册时间: 2010-01-19
最后登录: 2012-04-04
楼主  发表于: 2012-03-14 13:33

 mini2440 spi 总线 驱动 同一总线 多设备片选解决方法

最近正在做个项目 用2440上的gpio模拟spi总线。
2.6.32.2内核里有spi_gpio的驱动,但是似乎没有实现同一总线上多个设备的片选。
于是自己实现了一种解决方法,实际使用下来是可行的。
在这里分享一下,望各位大侠不吝指教。

From 14f975c9cfaabcecc52feaba86e44438b79afaa9 Mon Sep 17 00:00:00 2001
From: wangtt <wtt_usst@163.com>
Date: Wed, 14 Mar 2012 13:21:25 +0800
Subject: [PATCH] enable spi gpio

---
arch/arm/mach-s3c2410/include/mach/spi-gpio.h |    3 +-
arch/arm/mach-s3c2440/mach-mini2440.c         |   96 ++++++++++++++++++++++++-
arch/arm/plat-s3c24xx/Kconfig                 |    2 +-
drivers/spi/spi_s3c24xx_gpio.c                |   13 +++-
4 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
index 980a099..e189024 100755
--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
@@ -17,11 +17,12 @@ struct s3c2410_spigpio_info {
     unsigned long         pin_clk;
     unsigned long         pin_mosi;
     unsigned long         pin_miso;
+    unsigned long         *pin_cs_array;

     int             num_chipselect;
     int             bus_num;

-    void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
+    void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs, int chip_select_id);
};


diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index 775750f..9a055d3 100755
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -42,6 +42,7 @@
#include <linux/mtd/partitions.h>
#include <linux/dm9000.h>
#include <linux/mmc/host.h>
+#include <linux/spi/spi.h>//WTT ADD

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -51,10 +52,14 @@

#include <mach/hardware.h>
#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
#include <mach/regs-lcd.h>
#include <mach/leds-gpio.h>
#include <mach/idle.h>
#include <mach/fb.h>
+#include <mach/spi-gpio.h>//WTT ADD
+#include <mach/spi.h>//WTT ADD
+#include <../mach-s3c2410/include/mach/spi.h>

#include <plat/regs-serial.h>
#include <plat/iic.h>
@@ -265,6 +270,89 @@ static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {

#endif

+/*WTT ADD*/
+/* SPI GPIO BUS1 */
+unsigned long spi_spio_bus1_cs_array[] = {
+    S3C2410_GPF(1),    //chip select = 0, AD9833 HIGH SPEED
+    S3C2410_GPF(3),    //chip select = 1, AD9833 LOW SPEED
+    S3C2410_GPF(5),    //chip select = 2, AD5160
+};
+
+static void gpio_spi1_chipselect(struct s3c2410_spigpio_info *spi, int cs, int chip_select_id)
+{
+            if(chip_select_id >= spi->num_chipselect)
+            {
+                    printk("***** WTT DEBUG %s: chip_select_id %d is over spi->num_chipselect %d\n",__func__,chip_select_id,spi->num_chipselect);
+                    return;
+            }
+                    printk("***** WTT DEBUG %s: chip_select_id %d\n",__func__,chip_select_id);
+      s3c2410_gpio_setpin(spi_spio_bus1_cs_array[chip_select_id], cs ? 0 : 1);
+}
+
+static struct s3c2410_spigpio_info gpio_spi1_info = {
+      .bus_num  = 1,
+      .pin_clk  = S3C2440_GPJ0,
+      .pin_mosi = S3C2440_GPJ3,
+      .pin_cs_array   = spi_spio_bus1_cs_array,
+      .num_chipselect = ARRAY_SIZE(spi_spio_bus1_cs_array),    //bus total chips num, eg:'4' is for four devices on this bus
+      .chip_select  = gpio_spi1_chipselect,
+};
+
+static struct platform_device  gpio_spi1= {
+      .name   = "spi_s3c24xx_gpio",
+      .id   = 1,
+      .num_resources  = 0,
+      .dev.platform_data = &gpio_spi1_info,
+};
+
+static struct spi_board_info __initdata spi1_slave_devs[] = {
+      [0] = {
+              .modalias = "ad9833_spi",
+              .bus_num  = 1,
+              .chip_select  = 0,    //every chip id on this bus
+                                                                    //value must below s3c2410_spigpio_info->num_chipselect
+              .mode   = SPI_MODE_3, /* CPOL=1, CPHA=1 */
+              .max_speed_hz = 100000,
+              //.platform_data  = &jive_lcm_config,
+            },
+      [1] = {
+              .modalias = "ad9833_spi",
+              .bus_num  = 1,
+              .chip_select  = 1,    //every chip id on this bus
+                                                                    //value must below s3c2410_spigpio_info->num_chipselect
+              .mode   = SPI_MODE_3, /* CPOL=1, CPHA=1 */
+              .max_speed_hz = 100000,
+            }
+};
+
+/* SPI bus0 support */
+static struct s3c2410_spi_info spi0_data = {
+    .pin_cs = S3C2410_GPF(2),
+    .num_cs = 2,                    //bus total chips num
+    .bus_num = 0,
+    .set_cs = NULL,
+    .gpio_setup = s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
+//    void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
+//    void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
+};
+
+static struct spi_board_info __initdata spi0_slave_devs[] = {
+      [0] = {
+              .modalias = "spidev",
+              .bus_num  = 0,    //every chip id on this bus,value must below spi_board_info->num_cs
+              .chip_select  = 0,
+              .mode   = SPI_MODE_3, /* CPOL=1, CPHA=1 */
+              .max_speed_hz = 100000,
+              //.platform_data  = &jive_lcm_config,
+            }, {
+              .modalias = "tlc357x",
+              .bus_num  = 0,
+              .chip_select  = 1,    //every chip id on this bus,value must below spi_board_info->num_cs
+              .mode   = SPI_MODE_0, // CPOL=0, CPHA=0
+              .max_speed_hz = 100000,
+            },
+};
+/*WTT ADD*/
static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data = {
     .l3_clk = S3C2410_GPB(4),
     .l3_data = S3C2410_GPB(3),
@@ -386,6 +474,8 @@ static struct platform_device *mini2440_devices[] __initdata = {
     &s3c_device_lcd,
     &s3c_device_wdt,
     &s3c_device_i2c0,
+    &s3c_device_spi0,//WTT ADD
+    &gpio_spi1,//WTT ADD
     &s3c_device_iis,
     &mini2440_device_eth,
     &s3c24xx_uda134x,
@@ -407,6 +497,11 @@ static void __init mini2440_machine_init(void)
     s3c24xx_fb_set_platdata(&mini2440_fb_info);
#endif
     s3c_i2c0_set_platdata(NULL);
+    spi_register_board_info(spi0_slave_devs, ARRAY_SIZE(spi0_slave_devs));//WTT ADD
+    s3c_device_spi0.dev.platform_data = &spi0_data;//WTT ADD
+
+    spi_register_board_info(spi1_slave_devs, ARRAY_SIZE(spi1_slave_devs));//WTT ADD
+    gpio_spi1.dev.platform_data = &gpio_spi1_info;//WTT ADD

     s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);

@@ -426,4 +521,3 @@ MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")
     .init_machine    = mini2440_machine_init,
     .timer        = &s3c24xx_timer,
MACHINE_END
-
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index 6d302bf..a53a05b 100755
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -129,7 +129,7 @@ config S3C24XX_ADC
# SPI default pin configuration code

config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
-    bool
+    bool "S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13"
     help
       SPI GPIO configuration code for BUS0 when connected to
       GPE11, GPE12 and GPE13.
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index bbf9371..6f51fba 100755
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -23,6 +23,7 @@
#include <linux/spi/spi_bitbang.h>

#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
#include <mach/spi-gpio.h>
#include <mach/hardware.h>

@@ -92,7 +93,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
     struct s3c2410_spigpio *sg = spidev_to_sg(dev);

     if (sg->info && sg->info->chip_select)
-        (sg->info->chip_select)(sg->info, value);
+        (sg->info->chip_select)(sg->info, value, dev->chip_select);
}

static int s3c2410_spigpio_probe(struct platform_device *dev)
@@ -101,6 +102,7 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
     struct spi_master    *master;
     struct s3c2410_spigpio  *sp;
     int ret;
+    int cur_pin = 0;

     master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
     if (master == NULL) {
@@ -132,14 +134,19 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
     s3c2410_gpio_setpin(info->pin_clk, 0);
     s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT);

-    if (info->pin_mosi < S3C2410_GPH10) {
+    if (info->pin_mosi < S3C2443_GPJ13) {
         s3c2410_gpio_setpin(info->pin_mosi, 0);
         s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT);
     }

-    if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10)
+    if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2443_GPJ13)
         s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT);

+    for(cur_pin = 0;cur_pin < info->num_chipselect; cur_pin++)
+    {
+        if (info->pin_cs_array[cur_pin] != S3C2410_GPA0 && info->pin_cs_array[cur_pin] < S3C2443_GPJ13)
+            s3c2410_gpio_cfgpin(info->pin_cs_array[cur_pin], S3C2410_GPIO_OUTPUT);
+    }
     ret = spi_bitbang_start(&sp->bitbang);
     if (ret)
         goto err_no_bitbang;
--
1.7.4.2.406
[ 此帖被jbx在2012-03-14 16:02重新编辑 ]