From: Anders Berg <anders.b...@lsi.com>

Add gpiochip driver for the 5 chip select signals provided by the SSP block.
This makes it possible to use the device tree for all SPI configuration,
instead of having it in the platform specific code.

Signed-off-by: Anders Berg <anders.b...@lsi.com>
---
 arch/arm/mach-axxia/Makefile   |    1 +
 arch/arm/mach-axxia/axxia.c    |   62 -------------------
 arch/arm/mach-axxia/clock.c    |    2 +-
 arch/arm/mach-axxia/ssp-gpio.c |  132 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+), 63 deletions(-)
 create mode 100644 arch/arm/mach-axxia/ssp-gpio.c

diff --git a/arch/arm/mach-axxia/Makefile b/arch/arm/mach-axxia/Makefile
index 8e7dec4..62197f1 100644
--- a/arch/arm/mach-axxia/Makefile
+++ b/arch/arm/mach-axxia/Makefile
@@ -4,6 +4,7 @@
 obj-y                                  += axxia.o
 obj-y                                  += clock.o
 obj-y                                   += io.o
+obj-y                                   += ssp-gpio.o
 obj-y                                  += ncr.o
 obj-y                                  += timers.o
 obj-y                                  += pci.o
diff --git a/arch/arm/mach-axxia/axxia.c b/arch/arm/mach-axxia/axxia.c
index dcb6305..d73e11b 100644
--- a/arch/arm/mach-axxia/axxia.c
+++ b/arch/arm/mach-axxia/axxia.c
@@ -34,7 +34,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/smsc911x.h>
-#include <linux/spi/spi.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #ifdef CONFIG_ARM_ARCH_TIMER
@@ -62,8 +61,6 @@ static const char *axxia_dt_match[] __initconst = {
        NULL
 };
 
-static void __iomem *ssp_base;
-
 static struct map_desc axxia_static_mappings[] __initdata = {
 #ifdef CONFIG_DEBUG_LL
        {
@@ -151,17 +148,9 @@ struct pl061_platform_data gpio1_plat_data = {
        .values     = 0         /* startup values */
 };
 
-static struct pl022_ssp_controller ssp_plat_data = {
-       .bus_id         = 0,
-       .num_chipselect = 5,
-       .enable_dma     = 0
-};
-
 static struct of_dev_auxdata axxia_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("arm,primecell", 0x20101E0000ULL,
                       "mmci",  &mmc_plat_data),
-       OF_DEV_AUXDATA("arm,primecell", 0x2010088000ULL,
-                      "ssp",   &ssp_plat_data),
        OF_DEV_AUXDATA("arm,primecell", 0x2010092000ULL,
                       "gpio0", &gpio0_plat_data),
        OF_DEV_AUXDATA("arm,primecell", 0x2010093000ULL,
@@ -220,49 +209,6 @@ static struct platform_device pmu_device = {
        .dev.platform_data      = &axxia_pmu_platdata,
 };
 
-static inline void
-spidev_chip_select(u32 control, unsigned n)
-{
-       if (control == SSP_CHIP_SELECT)
-               writel(~(1<<n) & 0x1F, ssp_base + 0x30);
-       else
-               writel(0x1F, ssp_base + 0x30);
-}
-
-static void spi_cs_eeprom0(u32 control) { spidev_chip_select(control, 0); }
-static void spi_cs_eeprom1(u32 control) { spidev_chip_select(control, 1); }
-
-struct pl022_config_chip spi_eeprom0 = {
-       .iface      = SSP_INTERFACE_MOTOROLA_SPI,
-       .com_mode   = POLLING_TRANSFER,
-       .cs_control = spi_cs_eeprom0
-};
-
-struct pl022_config_chip spi_eeprom1 = {
-       .iface      = SSP_INTERFACE_MOTOROLA_SPI,
-       .com_mode   = POLLING_TRANSFER,
-       .cs_control = spi_cs_eeprom1
-};
-
-static struct spi_board_info spi_devs[] __initdata = {
-       {
-               .modalias               = "s25fl129p1",
-               .controller_data        = &spi_eeprom0,
-               .bus_num                = 0,
-               .chip_select            = 0,
-               .max_speed_hz           = 25000000,
-               .mode                   = SPI_MODE_0,
-       },
-       {
-               .modalias               = "s25fl129p1",
-               .controller_data        = &spi_eeprom1,
-               .bus_num                = 0,
-               .chip_select            = 1,
-               .max_speed_hz           = 25000000,
-               .mode                   = SPI_MODE_0,
-       }
-};
-
 static int
 axxia_bus_notifier(struct notifier_block *nb, unsigned long event, void *obj)
 {
@@ -299,14 +245,6 @@ void __init axxia_dt_init(void)
        ncr_init();
        axxia_ddr_retention_init();
 
-       spi_register_board_info(spi_devs, ARRAY_SIZE(spi_devs));
-
-       /*
-        * Setup PL022 to handle chip-select signal automatically
-        */
-       ssp_base = of_iomap(of_find_compatible_node(NULL, NULL, "arm,pl022"),
-                           0);
-
        axxia_pcie_init();
 
        platform_device_register(&pmu_device);
diff --git a/arch/arm/mach-axxia/clock.c b/arch/arm/mach-axxia/clock.c
index c8c28cf..6295795 100644
--- a/arch/arm/mach-axxia/clock.c
+++ b/arch/arm/mach-axxia/clock.c
@@ -88,7 +88,7 @@ axxia_init_clocks(int is_sim)
        clk_register_clkdev(clk[clk_per], NULL, "2010083000.uart");
 
        /* PL022 SSP */
-       clk_register_clkdev(clk[clk_per], NULL, "ssp");
+       clk_register_clkdev(clk[clk_per], NULL, "2010088000.ssp");
 
        /* I2C */
        clk_register_clkdev(clk[clk_per], NULL, "2010084000.i2c");
diff --git a/arch/arm/mach-axxia/ssp-gpio.c b/arch/arm/mach-axxia/ssp-gpio.c
new file mode 100644
index 0000000..c718edd
--- /dev/null
+++ b/arch/arm/mach-axxia/ssp-gpio.c
@@ -0,0 +1,132 @@
+/*
+ * GPIO interface for SSP chip select pins.
+ *
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+struct gpio_dev {
+       void __iomem    *regs;
+       struct gpio_chip gpio_chip;
+};
+
+static int
+ssp_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_dev *priv = dev_get_drvdata(chip->dev);
+       u32 tmp = readl(priv->regs + 0x30);
+       return !!(tmp & (1<<offset));
+}
+
+static int
+ssp_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+       /* Pins are only outputs */
+       return 0;
+}
+
+static void
+ssp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct gpio_dev *priv = dev_get_drvdata(chip->dev);
+       u32 tmp = readl(priv->regs + 0x30);
+       if (value)
+               tmp |= (1<<offset);
+       else
+               tmp &= ~(1<<offset);
+       writel(tmp, priv->regs + 0x30);
+}
+
+static int
+ssp_gpio_probe(struct platform_device *pdev)
+{
+       struct gpio_dev *priv;
+       struct resource *io;
+       struct gpio_chip *chip;
+       int ret;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, priv);
+
+       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!io)
+               return -EINVAL;
+
+       priv->regs = devm_ioremap_nocache(&pdev->dev,
+                                          io->start, resource_size(io));
+       if (!priv->regs)
+               return -ENXIO;
+
+       chip = &priv->gpio_chip;
+       chip->dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+       chip->of_node = pdev->dev.of_node;
+#endif
+       chip->get = ssp_gpio_get;
+       chip->direction_output = ssp_gpio_direction_out;
+       chip->set = ssp_gpio_set;
+       chip->label = "ssp-gpio";
+       chip->owner = THIS_MODULE;
+       chip->base = -1;
+       chip->ngpio = 5;
+
+       /* Deassert all */
+       writel(0x1f, priv->regs + 0x30);
+
+       ret = gpiochip_add(chip);
+       if (ret < 0)
+               dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
+
+       return ret;
+}
+
+static int
+ssp_gpio_remove(struct platform_device *pdev)
+{
+       struct gpio_dev *priv = dev_get_drvdata(&pdev->dev);
+       return gpiochip_remove(&priv->gpio_chip);
+}
+
+static const struct of_device_id ssp_gpio_id_table[] = {
+       { .compatible = "lsi,ssp-gpio" },
+       {}
+};
+MODULE_DEVICE_TABLE(platform, ssp_gpio_id_table);
+
+static struct platform_driver ssp_gpio_driver = {
+       .driver = {
+               .name   = "ssp-gpio",
+               .owner  = THIS_MODULE,
+               .of_match_table = ssp_gpio_id_table
+       },
+       .probe          = ssp_gpio_probe,
+       .remove         = ssp_gpio_remove,
+};
+
+module_platform_driver(ssp_gpio_driver);
+
+MODULE_AUTHOR("LSI Corporation");
+MODULE_DESCRIPTION("GPIO interface for SSP chip selects");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to