[U-Boot] [PATCH] S5P: new spi gpio bitbang driver

This patch adds basic support for spi mode 0~3 by control gpio bitbang in S5P. Original name of this patch was "support spi gpio driver by control gpio bitbang". But, it had arch-specific features, S5P, so changed to this name.
It uses several gpio pin and emulates spi chipselect signal, clock signal and sda signal as if spi controller generate spi signal.
I think it is going to use LCD Panel driver that using spi interface.
Signed-off-by: Donghwa Lee dh09.lee@samsung.com
--- arch/arm/include/asm/arch-s5pc1xx/spi.h | 53 +++++++++++ drivers/spi/Makefile | 1 + drivers/spi/s5p-spi.c | 154 +++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-s5pc1xx/spi.h create mode 100644 drivers/spi/s5p-spi.c
diff --git a/arch/arm/include/asm/arch-s5pc1xx/spi.h b/arch/arm/include/asm/arch-s5pc1xx/spi.h new file mode 100644 index 0000000..c7ae4dc --- /dev/null +++ b/arch/arm/include/asm/arch-s5pc1xx/spi.h @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2010 SAMSUNG Electronics + * Donghwa Lee dh09.lee@samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARCH_SPI_H_ +#define __ASM_ARCH_SPI_H_ + +#ifndef __ASSEMBLY__ + + +#define COMMAND_ONLY 0xFE +#define DATA_ONLY 0xFF +#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1 + + +struct s5p_spi_platdata { + struct s5p_gpio_bank *cs_bank; + struct s5p_gpio_bank *clk_bank; + struct s5p_gpio_bank *si_bank; + struct s5p_gpio_bank *so_bank; + + unsigned int cs_num; + unsigned int clk_num; + unsigned int si_num; + unsigned int so_num; + + unsigned int mode; + unsigned int cs_active; + unsigned int word_len; +}; + +void s5p_spi_write(struct s5p_spi_platdata *spi, + unsigned int address, unsigned int command); + +#endif /* __ASSEMBLY__ */ +#endif diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index dfcbb8b..e3c38e8 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -36,6 +36,7 @@ COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o +COBJS-$(CONFIG_S5P) += s5p-spi.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/spi/s5p-spi.c b/drivers/spi/s5p-spi.c new file mode 100644 index 0000000..6fa8634 --- /dev/null +++ b/drivers/spi/s5p-spi.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 Samsung Electronics + * Donghwa Lee dh09.lee@samsung.com + * s5p_spi_gpio.c - SPI master driver using generic bitbanged GPIO + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <asm/arch/gpio.h> +#include <asm/arch/spi.h> +#include <spi.h> + +static void s5p_spi_gpio_set_sck(struct s5p_spi_platdata *spi, int is_on) +{ + gpio_set_value(spi->clk_bank, spi->clk_num, is_on); +} + +static void s5p_spi_gpio_set_mosi(struct s5p_spi_platdata *spi, int is_on) +{ + gpio_set_value(spi->si_bank, spi->si_num, is_on); +} + +static void s5p_spi_gpio_chipselect(struct s5p_spi_platdata *spi, + int cpol) +{ + gpio_set_value(spi->cs_bank, spi->cs_num, + !spi->cs_active); + + /* set initial clock polarity */ + if (cpol) + s5p_spi_gpio_set_sck(spi, spi->mode & SPI_CPOL); + + /* SPI is normally active-low */ + gpio_set_value(spi->cs_bank, spi->cs_num, + spi->cs_active); +} + +static void +s5p_spi_gpio_tx_cpha0(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int cpol, + unsigned int word, unsigned int bits) +{ + int i; + unsigned int data; + + data = (word << spi->word_len) + bits; + + s5p_spi_gpio_chipselect(spi, cpol); + + /* clock starts at inactive polarity */ + for (i = spi->word_len; i >= 0; i--) { + + /* data high or low */ + if ((data >> i) & 0x1) + s5p_spi_gpio_set_mosi(spi, 1); + else + s5p_spi_gpio_set_mosi(spi, 0); + + udelay(nsecs); + + s5p_spi_gpio_set_sck(spi, !cpol); + udelay(nsecs); + + s5p_spi_gpio_set_sck(spi, cpol); + } +} + +static void +s5p_spi_gpio_tx_cpha1(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int cpol, + unsigned int word, unsigned int bits) +{ + int i; + unsigned int data; + + data = (word << spi->word_len) + bits; + + s5p_spi_gpio_chipselect(spi, cpol); + + /* clock starts at inactive polarity */ + for (i = spi->word_len; i >= 0; i--) { + + /* setup MSB (to slave) on leading edge */ + s5p_spi_gpio_set_sck(spi, !cpol); + + /* data high or low */ + if ((data >> i) & 0x1) + s5p_spi_gpio_set_mosi(spi, 1); + else + s5p_spi_gpio_set_mosi(spi, 0); + + udelay(nsecs); + + s5p_spi_gpio_set_sck(spi, cpol); + udelay(nsecs); + } +} + +static void s5p_spi_gpio_tx_word_mode0(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int word, unsigned int bits) +{ + return s5p_spi_gpio_tx_cpha0(spi, nsecs, 0, word, bits); +} + +static void s5p_spi_gpio_tx_word_mode1(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int word, unsigned int bits) +{ + return s5p_spi_gpio_tx_cpha1(spi, nsecs, 0, word, bits); +} + +static void s5p_spi_gpio_tx_word_mode2(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int word, unsigned int bits) +{ + return s5p_spi_gpio_tx_cpha0(spi, nsecs, 1, word, bits); +} + +static void s5p_spi_gpio_tx_word_mode3(struct s5p_spi_platdata *spi, + unsigned int nsecs, unsigned int word, unsigned int bits) +{ + return s5p_spi_gpio_tx_cpha1(spi, nsecs, 1, word, bits); +} + +void s5p_spi_gpio_write(struct s5p_spi_platdata *spi, + unsigned int address, unsigned int command) +{ + switch (spi->mode) { + case SPI_MODE_0: + s5p_spi_gpio_tx_word_mode0(spi, + 1, address, command); + case SPI_MODE_1: + s5p_spi_gpio_tx_word_mode1(spi, + 1, address, command); + case SPI_MODE_2: + s5p_spi_gpio_tx_word_mode2(spi, + 1, address, command); + case SPI_MODE_3: + s5p_spi_gpio_tx_word_mode3(spi, + 1, address, command); + } +}

On Tuesday, September 14, 2010 03:38:11 Donghwa Lee wrote:
This patch adds basic support for spi mode 0~3 by control gpio bitbang in S5P. Original name of this patch was "support spi gpio driver by control gpio bitbang". But, it had arch-specific features, S5P, so changed to this name.
so why arent you implementing this with the common spi API ? then any of the code in the tree would be able to use this spi driver without having to change to your arch-specific API.
+++ b/arch/arm/include/asm/arch-s5pc1xx/spi.h @@ -0,0 +1,53 @@
+#ifndef __ASM_ARCH_SPI_H_ +#define __ASM_ARCH_SPI_H_
+#ifndef __ASSEMBLY__
+#define COMMAND_ONLY 0xFE +#define DATA_ONLY 0xFF
i dont see the point in the __ASSEMBLY__ protection. this header isnt included by any header, and you dont actually define anything outside of the __ASSEMBLY__ which means including it from an assembly file doesnt make sense.
+#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1
considering you're already including spi.h, you might as well re-use SPI_CS_HIGH instead of defining your own.
+struct s5p_spi_platdata {
- struct s5p_gpio_bank *cs_bank;
- struct s5p_gpio_bank *clk_bank;
- struct s5p_gpio_bank *si_bank;
- struct s5p_gpio_bank *so_bank;
you need to include the header in this header which defines these structs. -mike

On Tuesday, September 14, 2010 20:48:11 Mike Frysinger wrote:
On Tuesday, September 14, 2010 03:38:11 Donghwa Lee wrote:
This patch adds basic support for spi mode 0~3 by control gpio bitbang in S5P. Original name of this patch was "support spi gpio driver by control gpio bitbang". But, it had arch-specific features, S5P, so changed to this name.
so why arent you implementing this with the common spi API ? then any of the code in the tree would be able to use this spi driver without having to change to your arch-specific API.
I think common spi API is not appropriate for S5P arch. For example, arch-S5P gpio framework consists of many gpio bank structure, and gpio number. From here, gpio bank structures are groups of many gpio pin and gpio number indicates specific gpio pin of gpio bank group. To control any gpio pin in arch S5P, must know about gpio bank and its specific number. But, existing spi API is different from avobe. For example, spi_setup_slave() function, consists of 4 function parameter, bus, cs, max_hz and mode. bus and cs is specific gpio number that not gpio bank group. so I think it is hard to control gpio without modifying API format.
This is reason that I had implemented new s5p-spi.c code. Implemented code can operating whole SPI_MODE and maybe easily use it. If you use gpio framework that similar with S5P gpio framework, you can use this spi driver easily.
+++ b/arch/arm/include/asm/arch-s5pc1xx/spi.h @@ -0,0 +1,53 @@
+#ifndef __ASM_ARCH_SPI_H_ +#define __ASM_ARCH_SPI_H_
+#ifndef __ASSEMBLY__
+#define COMMAND_ONLY 0xFE +#define DATA_ONLY 0xFF
i dont see the point in the __ASSEMBLY__ protection. this header isnt included by any header, and you dont actually define anything outside of the __ASSEMBLY__ which means including it from an assembly file doesnt make sense.
yes, I agree your opinion. It should be removed.
+#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1
considering you're already including spi.h, you might as well re-use SPI_CS_HIGH instead of defining your own.
yes, I agree your opinion. SPI_CS_HIGH can be re-used
+struct s5p_spi_platdata {
- struct s5p_gpio_bank *cs_bank;
- struct s5p_gpio_bank *clk_bank;
- struct s5p_gpio_bank *si_bank;
- struct s5p_gpio_bank *so_bank;
you need to include the header in this header which defines these structs. -mike
yes, it need to include the header file "<asm/arch/gpio.h>".
thank you for your opinion.

On Wednesday, September 15, 2010 01:15:08 Donghwa Lee wrote:
On Tuesday, September 14, 2010 20:48:11 Mike Frysinger wrote:
On Tuesday, September 14, 2010 03:38:11 Donghwa Lee wrote:
This patch adds basic support for spi mode 0~3 by control gpio bitbang in S5P. Original name of this patch was "support spi gpio driver by control gpio bitbang". But, it had arch-specific features, S5P, so changed to this name.
so why arent you implementing this with the common spi API ? then any of the code in the tree would be able to use this spi driver without having to change to your arch-specific API.
I think common spi API is not appropriate for S5P arch. For example, arch-S5P gpio framework consists of many gpio bank structure, and gpio number. From here, gpio bank structures are groups of many gpio pin and gpio number indicates specific gpio pin of gpio bank group. To control any gpio pin in arch S5P, must know about gpio bank and its specific number. But, existing spi API is different from avobe. For example, spi_setup_slave() function, consists of 4 function parameter, bus, cs, max_hz and mode. bus and cs is specific gpio number that not gpio bank group. so I think it is hard to control gpio without modifying API format.
i dont see how this matters. implement the common gpio api and handle the binding of a unique number to specific bank/pin there. then the spi/gpio layer need not care about how gpios are implement on any arch.
the Blackfin port already does this. each variant has a different number of gpio ports with a different number of pins in each bank. you can see in arch/blackfin/include/asm/mach-*/gpio.h how we then normalize the banks/pins into numbers from 0 to <gpio max for that arch>. then spi layer simply says "give me gpio 12" and the gpio layer takes care of the port/pin layer. -mike

On Thursday, September 16, 2010 03:06:11 Mike Frysinger wrote:
On Wednesday, September 15, 2010 01:15:08 Donghwa Lee wrote:
On Tuesday, September 14, 2010 20:48:11 Mike Frysinger wrote:
On Tuesday, September 14, 2010 03:38:11 Donghwa Lee wrote:
This patch adds basic support for spi mode 0~3 by control gpio bitbang in S5P. Original name of this patch was "support spi gpio driver by control gpio bitbang". But, it had arch-specific features, S5P, so changed to this name.
so why arent you implementing this with the common spi API ? then any of the code in the tree would be able to use this spi driver without having to change to your arch-specific API.
I think common spi API is not appropriate for S5P arch. For example, arch-S5P gpio framework consists of many gpio bank structure, and gpio number. From here, gpio bank structures are groups of many gpio pin and gpio number indicates specific gpio pin of gpio bank group. To control any gpio pin in arch S5P, must know about gpio bank and its specific number. But, existing spi API is different from avobe. For example, spi_setup_slave() function, consists of 4 function parameter, bus, cs, max_hz and mode. bus and cs is specific gpio number that not gpio bank group. so I think it is hard to control gpio without modifying API format.
i dont see how this matters. implement the common gpio api and handle the binding of a unique number to specific bank/pin there. then the spi/gpio layer need not care about how gpios are implement on any arch.
the Blackfin port already does this. each variant has a different number of gpio ports with a different number of pins in each bank. you can see in arch/blackfin/include/asm/mach-*/gpio.h how we then normalize the banks/pins into numbers from 0 to <gpio max for that arch>. then spi layer simply says "give me gpio 12" and the gpio layer takes care of the port/pin layer. -mike
I had checked blackfin gpio framework. Blackfin includes only maximum 20 ports, 160 pins, but, s5pc110 includes about 53 banks and 415 gpio pins. If it will be included s5pc100, amounts of gpio pins are tremendous. And construction of arch-s5pc1xx gpio framework is not similar with blackfin. And actually, I think arch-blackfin doesn't use gpio pins that implemented in arch/blackpin/include/asm/mach-*/gpio.h as spi initialization parameter probably. It maybe coded in bf518f-ezbrd.c only specific fixed number '0' and '1' by cs and bus number, not using gpio framework.
But I want to use gpio framework to spi interface by setting platform data. It can easily use cs, bus and data line by modifying in platform data. I want to use without modifying arch-s5p gpio framework and want to use appropriately for arch-s5p.
thank you for your comments.

On Wednesday, September 15, 2010 22:38:18 Donghwa Lee wrote:
I had checked blackfin gpio framework. Blackfin includes only maximum 20 ports, 160 pins, but, s5pc110 includes about 53 banks and 415 gpio pins.
why does the # of pins matter ? the id is an "unsigned" value which easily accommodates 415 pins. the current blackfin "max" for the bf54x is 160 only because that is how many gpios it has, not because of any limitation in the software architecture.
If it will be included s5pc100, amounts of gpio pins are tremendous. And construction of arch-s5pc1xx gpio framework is not similar with blackfin.
the internals arent terribly relevant. you simply need to support the generic gpio layer just like under Linux.
And actually, I think arch-blackfin doesn't use gpio pins that implemented in arch/blackpin/include/asm/mach-*/gpio.h as spi initialization parameter probably. It maybe coded in bf518f-ezbrd.c only specific fixed number '0' and '1' by cs and bus number, not using gpio framework.
the blackfin spi driver is not built on top of gpios because it doesnt make any sense to. there is already a hardware spi peripheral to take care of the pins. and it supports both hardware cs (0..7) as well as a gpio as cs.
But I want to use gpio framework to spi interface by setting platform data. It can easily use cs, bus and data line by modifying in platform data. I want to use without modifying arch-s5p gpio framework and want to use appropriately for arch-s5p.
and if your gpio layer were properly architected behind the common gpio layer, the spi code would not care what gpio implementation it is sitting on top of. and you could simply put into your board config ("platform data") something like "#define CONFIG_SPI_GPIO_MOSI GPIO_xxx". -mike
participants (2)
-
Donghwa Lee
-
Mike Frysinger