* [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio
@ 2012-03-07 12:23 Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 2/4 v4] spi/atmel: add DT support Jean-Christophe PLAGNIOL-VILLARD
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-03-07 12:23 UTC (permalink / raw)
To: linux-arm-kernel
This will allow to use gpio for chip select with no modification in the
driver binding
When use the cs-gpios, the gpio number will be passed via the cs_gpio field
and the number of chip select will automatically increased.
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: spi-devel-general at lists.sourceforge.net
---
v4:
use cs_gpio to pass the gpio number
Best Regards,
J.
Documentation/devicetree/bindings/spi/spi-bus.txt | 6 ++
drivers/spi/spi.c | 57 +++++++++++++++++++-
include/linux/spi/spi.h | 6 ++
3 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index e782add..c253379 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -12,6 +12,7 @@ The SPI master node requires the following properties:
- #size-cells - should be zero.
- compatible - name of SPI bus controller following generic names
recommended practice.
+- cs-gpios - (optional) gpios chip select.
No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for
@@ -21,6 +22,8 @@ assumption that board specific platform code will be used to manage
chip selects. Individual drivers can define additional properties to
support describing the chip select layout.
+If cs-gpios is used the number of chip select will automatically increased.
+
SPI slave nodes must be children of the SPI master node and can
contain the following properties.
- reg - (required) chip select address of device.
@@ -34,6 +37,9 @@ contain the following properties.
- spi-cs-high - (optional) Empty property indicating device requires
chip select active high
+If a gpio chipselect is used for the SPI slave the gpio number will be passed
+via the controller_data
+
SPI example for an MPC5200 SPI bus:
spi at f00 {
#address-cells = <1>;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b2ccdea..c1d0955 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -28,6 +28,7 @@
#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/of_spi.h>
+#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/export.h>
@@ -322,6 +323,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
spi->dev.parent = &master->dev;
spi->dev.bus = &spi_bus_type;
spi->dev.release = spidev_release;
+ spi->cs_gpio = -EINVAL;
device_initialize(&spi->dev);
return spi;
}
@@ -339,15 +341,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
- struct device *dev = spi->master->dev.parent;
+ struct spi_master *master = spi->master;
+ struct device *dev = master->dev.parent;
struct device *d;
int status;
/* Chipselects are numbered 0..max; validate. */
- if (spi->chip_select >= spi->master->num_chipselect) {
+ if (spi->chip_select >= master->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
- spi->master->num_chipselect);
+ master->num_chipselect);
return -EINVAL;
}
@@ -371,6 +374,13 @@ int spi_add_device(struct spi_device *spi)
goto done;
}
+ if (master->num_gpio_cs &&
+ spi->chip_select >= master->first_gpio_cs) {
+ int num = spi->chip_select - master->first_gpio_cs;
+
+ spi->cs_gpio = master->cs_gpios[num];
+ }
+
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
@@ -561,6 +571,43 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
}
EXPORT_SYMBOL_GPL(spi_alloc_master);
+#ifdef CONFIG_OF
+static int of_spi_register_master(struct spi_master *master)
+{
+ int nb, i;
+ int *cs;
+ struct device_node *np = master->dev.of_node;
+
+ if (!np)
+ return 0;
+
+ nb = of_gpio_named_count(np, "cs-gpios");
+
+ if (nb < 1)
+ return 0;
+
+ cs = devm_kzalloc(&master->dev, sizeof(int) * nb, GFP_KERNEL);
+ master->cs_gpios = cs;
+
+ if (!master->cs_gpios)
+ return -ENOMEM;
+
+ master->first_gpio_cs = master->num_chipselect;
+ master->num_chipselect += nb;
+ master->num_gpio_cs = nb;
+
+ for (i = 0; i < nb; i++)
+ cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+
+ return 0;
+}
+#else
+static int of_spi_register_master(struct spi_master *master)
+{
+ return 0;
+}
+#endif
+
/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
@@ -592,6 +639,10 @@ int spi_register_master(struct spi_master *master)
if (!dev)
return -ENODEV;
+ status = of_spi_register_master(master);
+ if (status)
+ return status;
+
/* even if it's just one always-selected device, there must
* be@least one chipselect
*/
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 176fce9..7dcf031 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -89,6 +89,7 @@ struct spi_device {
void *controller_state;
void *controller_data;
char modalias[SPI_NAME_SIZE];
+ int cs_gpio; /* chip select gpio */
/*
* likely need more hooks for more protocol options affecting how
@@ -318,6 +319,11 @@ struct spi_master {
/* called on release() to free memory provided by spi_master */
void (*cleanup)(struct spi_device *spi);
+
+ /* gpio chip select */
+ int *cs_gpios;
+ int first_gpio_cs;
+ int num_gpio_cs;
};
static inline void *spi_master_get_devdata(struct spi_master *master)
--
1.7.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4 v4] spi/atmel: add DT support
2012-03-07 12:23 [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Jean-Christophe PLAGNIOL-VILLARD
@ 2012-03-07 12:23 ` Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 3/4 v4] ARM: at91: sam9g20 add spi " Jean-Christophe PLAGNIOL-VILLARD
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-03-07 12:23 UTC (permalink / raw)
To: linux-arm-kernel
The atmel_spi use only gpio for chip select.
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: spi-devel-general at lists.sourceforge.net
---
.../devicetree/bindings/spi/spi_atmel.txt | 6 +++++
drivers/spi/spi-atmel.c | 21 ++++++++++++++++---
2 files changed, 23 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/spi/spi_atmel.txt
diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt
new file mode 100644
index 0000000..7ec3d8d
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt
@@ -0,0 +1,6 @@
+Atmel SPI device
+
+Required properties:
+- compatible : should be "atmel,at91rm9200-spi".
+- reg: Address and length of the register set for the device
+- interrupts: Should contain macb interrupt
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 16d6a83..efbc5f8 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <asm/io.h>
#include <mach/board.h>
@@ -695,7 +696,7 @@ static int atmel_spi_setup(struct spi_device *spi)
u32 scbr, csr;
unsigned int bits = spi->bits_per_word;
unsigned long bus_hz;
- unsigned int npcs_pin;
+ int npcs_pin;
int ret;
as = spi_master_get_devdata(spi->master);
@@ -767,7 +768,9 @@ static int atmel_spi_setup(struct spi_device *spi)
csr |= SPI_BF(DLYBCT, 0);
/* chipselect must have been muxed as GPIO (e.g. in board setup) */
- npcs_pin = (unsigned int)spi->controller_data;
+ if (!gpio_is_valid(spi->cs_gpio))
+ spi->cs_gpio = (int)spi->controller_data;
+ npcs_pin = spi->cs_gpio;
asd = spi->controller_state;
if (!asd) {
asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
@@ -887,7 +890,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
{
struct atmel_spi *as = spi_master_get_devdata(spi->master);
struct atmel_spi_device *asd = spi->controller_state;
- unsigned gpio = (unsigned) spi->controller_data;
+ unsigned gpio = spi->cs_gpio;
unsigned long flags;
if (!asd)
@@ -938,7 +941,8 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bus_num = pdev->id;
- master->num_chipselect = 4;
+ master->dev.of_node = pdev->dev.of_node;
+ master->num_chipselect = master->dev.of_node ? 0 : 4;
master->setup = atmel_spi_setup;
master->transfer = atmel_spi_transfer;
master->cleanup = atmel_spi_cleanup;
@@ -1064,11 +1068,20 @@ static int atmel_spi_resume(struct platform_device *pdev)
#define atmel_spi_resume NULL
#endif
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_spi_dt_ids[] = {
+ { .compatible = "atmel,at91rm9200-spi" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids);
+#endif
static struct platform_driver atmel_spi_driver = {
.driver = {
.name = "atmel_spi",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(atmel_spi_dt_ids),
},
.suspend = atmel_spi_suspend,
.resume = atmel_spi_resume,
--
1.7.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4 v4] ARM: at91: sam9g20 add spi DT support
2012-03-07 12:23 [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 2/4 v4] spi/atmel: add DT support Jean-Christophe PLAGNIOL-VILLARD
@ 2012-03-07 12:23 ` Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 4/4 v4] ARM: at91: sam9g45 " Jean-Christophe PLAGNIOL-VILLARD
2012-03-09 15:14 ` [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Grant Likely
3 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-03-07 12:23 UTC (permalink / raw)
To: linux-arm-kernel
usb_a9g20:
add mmc spi support
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
---
arch/arm/boot/dts/at91sam9g20.dtsi | 18 ++++++++++++++++++
arch/arm/boot/dts/usb_a9g20.dts | 13 +++++++++++++
arch/arm/mach-at91/at91sam9260.c | 2 ++
3 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index 3cb4226..aef3d5be 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -203,6 +203,24 @@
interrupts = <10 4>;
status = "disabled";
};
+
+ spi0: spi at fffc8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "atmel,at91rm9200-spi";
+ reg = <0xfffc8000 0x4000>;
+ interrupts = <12 4>;
+ status = "disabled";
+ };
+
+ spi1: spi at fffcc000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "atmel,at91rm9200-spi";
+ reg = <0xfffcc000 0x4000>;
+ interrupts = <13 4>;
+ status = "disabled";
+ };
};
nand0: nand at 40000000 {
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
index 390c481..9efaff3 100644
--- a/arch/arm/boot/dts/usb_a9g20.dts
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -46,6 +46,19 @@
atmel,vbus-gpio = <&pioC 5 0>;
status = "okay";
};
+
+ spi1: spi at fffcc000 {
+ cs-gpios = <&pioB 3 0>;
+ status = "okay";
+ mmc-slot at 0 {
+ compatible = "mmc-spi-slot";
+ reg = <0>;
+ gpios = <&pioC 4 0 /* CD */
+ >;
+ voltage-ranges = <3200 3400>;
+ spi-max-frequency = <20000000>;
+ };
+ };
};
nand0: nand at 40000000 {
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index d1e5750..c6e5d0f 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -217,6 +217,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffc8000.spi", &spi0_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffcc000.spi", &spi1_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
--
1.7.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4 v4] ARM: at91: sam9g45 add spi DT support
2012-03-07 12:23 [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 2/4 v4] spi/atmel: add DT support Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 3/4 v4] ARM: at91: sam9g20 add spi " Jean-Christophe PLAGNIOL-VILLARD
@ 2012-03-07 12:23 ` Jean-Christophe PLAGNIOL-VILLARD
2012-03-09 15:14 ` [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Grant Likely
3 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-03-07 12:23 UTC (permalink / raw)
To: linux-arm-kernel
at91sam9m10g45ek:
add dataflash support
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
---
arch/arm/boot/dts/at91sam9g45.dtsi | 18 ++++++++++++++++++
arch/arm/boot/dts/at91sam9m10g45ek.dts | 23 +++++++++++++++++++++++
arch/arm/mach-at91/at91sam9g45.c | 2 ++
3 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 7a685f9..8a11530 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -271,6 +271,24 @@
atmel,can-isoc = <1>;
};
};
+
+ spi0: spi at fffa4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "atmel,at91rm9200-spi";
+ reg = <0xfffa4000 0x4000>;
+ interrupts = <14 4>;
+ status = "disabled";
+ };
+
+ spi1: spi at fffa8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "atmel,at91rm9200-spi";
+ reg = <0xfffa8000 0x4000>;
+ interrupts = <15 4>;
+ status = "disabled";
+ };
};
nand0: nand at 40000000 {
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index b9382e3..2b96ab2 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -51,6 +51,29 @@
atmel,vbus-gpio = <&pioB 19 0>;
status = "okay";
};
+
+ spi0: spi at fffa4000 {
+ cs-gpios = <&pioB 3 0>;
+ status = "okay";
+ flash: at45db321d at 0 {
+ compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+ reg = <0>;
+ spi-max-frequency = <15000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition at 0 {
+ label = "U-Boot";
+ reg = <0x0 0x40110>;
+ read-only;
+ };
+
+ partition at 40110 {
+ label = "Kernel";
+ reg = <0x40110 0x3dfef0>;
+ };
+ };
+ };
};
nand0: nand at 40000000 {
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index da80f0c..06547bf 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -236,6 +236,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
CLKDEV_CON_DEV_ID("hclk", "600000.gadget", &utmi_clk),
CLKDEV_CON_DEV_ID("pclk", "600000.gadget", &udphs_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
+ CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
--
1.7.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio
2012-03-07 12:23 [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Jean-Christophe PLAGNIOL-VILLARD
` (2 preceding siblings ...)
2012-03-07 12:23 ` [PATCH 4/4 v4] ARM: at91: sam9g45 " Jean-Christophe PLAGNIOL-VILLARD
@ 2012-03-09 15:14 ` Grant Likely
2012-03-09 18:02 ` Jean-Christophe PLAGNIOL-VILLARD
3 siblings, 1 reply; 6+ messages in thread
From: Grant Likely @ 2012-03-09 15:14 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 7 Mar 2012 13:23:06 +0100, Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> This will allow to use gpio for chip select with no modification in the
> driver binding
>
> When use the cs-gpios, the gpio number will be passed via the cs_gpio field
> and the number of chip select will automatically increased.
>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: devicetree-discuss at lists.ozlabs.org
> Cc: spi-devel-general at lists.sourceforge.net
> ---
> v4:
> use cs_gpio to pass the gpio number
>
> Best Regards,
> J.
> Documentation/devicetree/bindings/spi/spi-bus.txt | 6 ++
> drivers/spi/spi.c | 57 +++++++++++++++++++-
> include/linux/spi/spi.h | 6 ++
> 3 files changed, 66 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
> index e782add..c253379 100644
> --- a/Documentation/devicetree/bindings/spi/spi-bus.txt
> +++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
> @@ -12,6 +12,7 @@ The SPI master node requires the following properties:
> - #size-cells - should be zero.
> - compatible - name of SPI bus controller following generic names
> recommended practice.
> +- cs-gpios - (optional) gpios chip select.
> No other properties are required in the SPI bus node. It is assumed
> that a driver for an SPI bus device will understand that it is an SPI bus.
> However, the binding does not attempt to define the specific method for
> @@ -21,6 +22,8 @@ assumption that board specific platform code will be used to manage
> chip selects. Individual drivers can define additional properties to
> support describing the chip select layout.
>
> +If cs-gpios is used the number of chip select will automatically increased.
> +
> SPI slave nodes must be children of the SPI master node and can
> contain the following properties.
> - reg - (required) chip select address of device.
> @@ -34,6 +37,9 @@ contain the following properties.
> - spi-cs-high - (optional) Empty property indicating device requires
> chip select active high
>
> +If a gpio chipselect is used for the SPI slave the gpio number will be passed
> +via the controller_data
> +
> SPI example for an MPC5200 SPI bus:
> spi at f00 {
> #address-cells = <1>;
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index b2ccdea..c1d0955 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -28,6 +28,7 @@
> #include <linux/mod_devicetable.h>
> #include <linux/spi/spi.h>
> #include <linux/of_spi.h>
> +#include <linux/of_gpio.h>
> #include <linux/pm_runtime.h>
> #include <linux/export.h>
>
> @@ -322,6 +323,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
> spi->dev.parent = &master->dev;
> spi->dev.bus = &spi_bus_type;
> spi->dev.release = spidev_release;
> + spi->cs_gpio = -EINVAL;
> device_initialize(&spi->dev);
> return spi;
> }
> @@ -339,15 +341,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
> int spi_add_device(struct spi_device *spi)
> {
> static DEFINE_MUTEX(spi_add_lock);
> - struct device *dev = spi->master->dev.parent;
> + struct spi_master *master = spi->master;
> + struct device *dev = master->dev.parent;
> struct device *d;
> int status;
>
> /* Chipselects are numbered 0..max; validate. */
> - if (spi->chip_select >= spi->master->num_chipselect) {
> + if (spi->chip_select >= master->num_chipselect) {
> dev_err(dev, "cs%d >= max %d\n",
> spi->chip_select,
> - spi->master->num_chipselect);
> + master->num_chipselect);
> return -EINVAL;
> }
>
> @@ -371,6 +374,13 @@ int spi_add_device(struct spi_device *spi)
> goto done;
> }
>
> + if (master->num_gpio_cs &&
> + spi->chip_select >= master->first_gpio_cs) {
> + int num = spi->chip_select - master->first_gpio_cs;
> +
> + spi->cs_gpio = master->cs_gpios[num];
spi->cs_gpio isn't used anywhere.
> + }
> +
> /* Drivers may modify this initial i/o setup, but will
> * normally rely on the device being setup. Devices
> * using SPI_CS_HIGH can't coexist well otherwise...
> @@ -561,6 +571,43 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
> }
> EXPORT_SYMBOL_GPL(spi_alloc_master);
>
> +#ifdef CONFIG_OF
> +static int of_spi_register_master(struct spi_master *master)
> +{
> + int nb, i;
> + int *cs;
> + struct device_node *np = master->dev.of_node;
> +
> + if (!np)
> + return 0;
> +
> + nb = of_gpio_named_count(np, "cs-gpios");
> +
> + if (nb < 1)
> + return 0;
> +
> + cs = devm_kzalloc(&master->dev, sizeof(int) * nb, GFP_KERNEL);
> + master->cs_gpios = cs;
> +
> + if (!master->cs_gpios)
> + return -ENOMEM;
> +
> + master->first_gpio_cs = master->num_chipselect;
> + master->num_chipselect += nb;
> + master->num_gpio_cs = nb;
I think this can be simplified. Rather than trying to optimize by having
a set of integrated cs lines followed by a gpio set, I think it would be
better to have a single cs_gpios table that covers the whole range of
num_chipselect; even if they overlap natural cs lines. That will make for
an easier to use binding since users won't need to remember how many natural
cs lines are on the device when filling the cs-gpios property. It will
also make the code simpler because first_gpio_cs and num_gpio_cs can both
be eliminated. It also means the core can have exact knowledge about which
gpio is associated with which cs number.
> +
> + for (i = 0; i < nb; i++)
> + cs[i] = of_get_named_gpio(np, "cs-gpios", i);
> +
> + return 0;
> +}
> +#else
> +static int of_spi_register_master(struct spi_master *master)
> +{
> + return 0;
> +}
> +#endif
> +
> /**
> * spi_register_master - register SPI master controller
> * @master: initialized master, originally from spi_alloc_master()
> @@ -592,6 +639,10 @@ int spi_register_master(struct spi_master *master)
> if (!dev)
> return -ENODEV;
>
> + status = of_spi_register_master(master);
> + if (status)
> + return status;
> +
> /* even if it's just one always-selected device, there must
> * be at least one chipselect
> */
> diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
> index 176fce9..7dcf031 100644
> --- a/include/linux/spi/spi.h
> +++ b/include/linux/spi/spi.h
> @@ -89,6 +89,7 @@ struct spi_device {
> void *controller_state;
> void *controller_data;
> char modalias[SPI_NAME_SIZE];
> + int cs_gpio; /* chip select gpio */
>
> /*
> * likely need more hooks for more protocol options affecting how
> @@ -318,6 +319,11 @@ struct spi_master {
>
> /* called on release() to free memory provided by spi_master */
> void (*cleanup)(struct spi_device *spi);
> +
> + /* gpio chip select */
> + int *cs_gpios;
> + int first_gpio_cs;
> + int num_gpio_cs;
> };
>
> static inline void *spi_master_get_devdata(struct spi_master *master)
> --
> 1.7.7
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
--
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies,Ltd.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio
2012-03-09 15:14 ` [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Grant Likely
@ 2012-03-09 18:02 ` Jean-Christophe PLAGNIOL-VILLARD
0 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-03-09 18:02 UTC (permalink / raw)
To: linux-arm-kernel
On 08:14 Fri 09 Mar , Grant Likely wrote:
> On Wed, 7 Mar 2012 13:23:06 +0100, Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> wrote:
> > This will allow to use gpio for chip select with no modification in the
> > driver binding
> >
> > When use the cs-gpios, the gpio number will be passed via the cs_gpio field
> > and the number of chip select will automatically increased.
> >
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > Cc: devicetree-discuss at lists.ozlabs.org
> > Cc: spi-devel-general at lists.sourceforge.net
> > ---
> > v4:
> > use cs_gpio to pass the gpio number
> >
> > Best Regards,
> > J.
> > Documentation/devicetree/bindings/spi/spi-bus.txt | 6 ++
> > drivers/spi/spi.c | 57 +++++++++++++++++++-
> > include/linux/spi/spi.h | 6 ++
> > 3 files changed, 66 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
> > index e782add..c253379 100644
> > --- a/Documentation/devicetree/bindings/spi/spi-bus.txt
> > +++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
> > @@ -12,6 +12,7 @@ The SPI master node requires the following properties:
> > - #size-cells - should be zero.
> > - compatible - name of SPI bus controller following generic names
> > recommended practice.
> > +- cs-gpios - (optional) gpios chip select.
> > No other properties are required in the SPI bus node. It is assumed
> > that a driver for an SPI bus device will understand that it is an SPI bus.
> > However, the binding does not attempt to define the specific method for
> > @@ -21,6 +22,8 @@ assumption that board specific platform code will be used to manage
> > chip selects. Individual drivers can define additional properties to
> > support describing the chip select layout.
> >
> > +If cs-gpios is used the number of chip select will automatically increased.
> > +
> > SPI slave nodes must be children of the SPI master node and can
> > contain the following properties.
> > - reg - (required) chip select address of device.
> > @@ -34,6 +37,9 @@ contain the following properties.
> > - spi-cs-high - (optional) Empty property indicating device requires
> > chip select active high
> >
> > +If a gpio chipselect is used for the SPI slave the gpio number will be passed
> > +via the controller_data
> > +
> > SPI example for an MPC5200 SPI bus:
> > spi at f00 {
> > #address-cells = <1>;
> > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> > index b2ccdea..c1d0955 100644
> > --- a/drivers/spi/spi.c
> > +++ b/drivers/spi/spi.c
> > @@ -28,6 +28,7 @@
> > #include <linux/mod_devicetable.h>
> > #include <linux/spi/spi.h>
> > #include <linux/of_spi.h>
> > +#include <linux/of_gpio.h>
> > #include <linux/pm_runtime.h>
> > #include <linux/export.h>
> >
> > @@ -322,6 +323,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
> > spi->dev.parent = &master->dev;
> > spi->dev.bus = &spi_bus_type;
> > spi->dev.release = spidev_release;
> > + spi->cs_gpio = -EINVAL;
> > device_initialize(&spi->dev);
> > return spi;
> > }
> > @@ -339,15 +341,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
> > int spi_add_device(struct spi_device *spi)
> > {
> > static DEFINE_MUTEX(spi_add_lock);
> > - struct device *dev = spi->master->dev.parent;
> > + struct spi_master *master = spi->master;
> > + struct device *dev = master->dev.parent;
> > struct device *d;
> > int status;
> >
> > /* Chipselects are numbered 0..max; validate. */
> > - if (spi->chip_select >= spi->master->num_chipselect) {
> > + if (spi->chip_select >= master->num_chipselect) {
> > dev_err(dev, "cs%d >= max %d\n",
> > spi->chip_select,
> > - spi->master->num_chipselect);
> > + master->num_chipselect);
> > return -EINVAL;
> > }
> >
> > @@ -371,6 +374,13 @@ int spi_add_device(struct spi_device *spi)
> > goto done;
> > }
> >
> > + if (master->num_gpio_cs &&
> > + spi->chip_select >= master->first_gpio_cs) {
> > + int num = spi->chip_select - master->first_gpio_cs;
> > +
> > + spi->cs_gpio = master->cs_gpios[num];
>
> spi->cs_gpio isn't used anywhere.
driver
as example atmel spi
I choose to let the driver to manage it as they may need to manange specific
register when using both hw and gpio cs
>
> > + }
> > +
> > /* Drivers may modify this initial i/o setup, but will
> > * normally rely on the device being setup. Devices
> > * using SPI_CS_HIGH can't coexist well otherwise...
> > @@ -561,6 +571,43 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
> > }
> > EXPORT_SYMBOL_GPL(spi_alloc_master);
> >
> > +#ifdef CONFIG_OF
> > +static int of_spi_register_master(struct spi_master *master)
> > +{
> > + int nb, i;
> > + int *cs;
> > + struct device_node *np = master->dev.of_node;
> > +
> > + if (!np)
> > + return 0;
> > +
> > + nb = of_gpio_named_count(np, "cs-gpios");
> > +
> > + if (nb < 1)
> > + return 0;
> > +
> > + cs = devm_kzalloc(&master->dev, sizeof(int) * nb, GFP_KERNEL);
> > + master->cs_gpios = cs;
> > +
> > + if (!master->cs_gpios)
> > + return -ENOMEM;
> > +
> > + master->first_gpio_cs = master->num_chipselect;
> > + master->num_chipselect += nb;
> > + master->num_gpio_cs = nb;
>
> I think this can be simplified. Rather than trying to optimize by having
> a set of integrated cs lines followed by a gpio set, I think it would be
> better to have a single cs_gpios table that covers the whole range of
> num_chipselect; even if they overlap natural cs lines. That will make for
> an easier to use binding since users won't need to remember how many natural
> cs lines are on the device when filling the cs-gpios property. It will
> also make the code simpler because first_gpio_cs and num_gpio_cs can both
> be eliminated. It also means the core can have exact knowledge about which
> gpio is associated with which cs number.
ok why not so I feel the array with -EINVAL for hw cs;
Best Regards,
J.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-03-09 18:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-07 12:23 [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 2/4 v4] spi/atmel: add DT support Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 3/4 v4] ARM: at91: sam9g20 add spi " Jean-Christophe PLAGNIOL-VILLARD
2012-03-07 12:23 ` [PATCH 4/4 v4] ARM: at91: sam9g45 " Jean-Christophe PLAGNIOL-VILLARD
2012-03-09 15:14 ` [PATCH 1/4 v4] of_spi: add generic binding support to specify cs gpio Grant Likely
2012-03-09 18:02 ` Jean-Christophe PLAGNIOL-VILLARD
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).