lkml.org 
[lkml]   [2021]   [Mar]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 01/13] gpio: Add Elba SoC gpio driver for spi cs control
Date
This GPIO driver is for the Pensando Elba SoC which
provides control of four chip selects on two SPI busses.

Signed-off-by: Brad Larson <brad@pensando.io>
---
drivers/gpio/Kconfig | 6 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-elba-spics.c | 114 +++++++++++++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 drivers/gpio/gpio-elba-spics.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e3607ec4c2e8..4720459b24f5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -241,6 +241,12 @@ config GPIO_EIC_SPRD
help
Say yes here to support Spreadtrum EIC device.

+config GPIO_ELBA_SPICS
+ bool "Pensando Elba SPI chip-select"
+ depends on (ARCH_PENSANDO_ELBA_SOC || COMPILE_TEST)
+ help
+ Say yes here to support the Penasndo Elba SoC SPI chip-select driver
+
config GPIO_EM
tristate "Emma Mobile GPIO"
depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c58a90a3c3b1..c5c7acad371b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o
+obj-$(CONFIG_GPIO_ELBA_SPICS) += gpio-elba-spics.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
diff --git a/drivers/gpio/gpio-elba-spics.c b/drivers/gpio/gpio-elba-spics.c
new file mode 100644
index 000000000000..351bbaeea033
--- /dev/null
+++ b/drivers/gpio/gpio-elba-spics.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pensando Elba SoC SPI chip select driver
+ *
+ * Copyright (c) 2020-2021, Pensando Systems Inc.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/init.h>
+//#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+/*
+ * pin: 3 2 | 1 0
+ * bit: 7------6------5------4----|---3------2------1------0
+ * cs1 cs1_ovr cs0 cs0_ovr | cs1 cs1_ovr cs0 cs0_ovr
+ * ssi1 | ssi0
+ */
+#define SPICS_PIN_SHIFT(pin) (2 * (pin))
+#define SPICS_MASK(pin) (0x3 << SPICS_PIN_SHIFT(pin))
+#define SPICS_SET(pin, val) ((((val) << 1) | 0x1) << SPICS_PIN_SHIFT(pin))
+
+struct elba_spics_priv {
+ void __iomem *base;
+ spinlock_t lock;
+ struct gpio_chip chip;
+};
+
+static int elba_spics_get_value(struct gpio_chip *chip, unsigned int pin)
+{
+ return -ENOTSUPP;
+}
+
+static void elba_spics_set_value(struct gpio_chip *chip,
+ unsigned int pin, int value)
+{
+ struct elba_spics_priv *p = gpiochip_get_data(chip);
+ unsigned long flags;
+ u32 tmp;
+
+ /* select chip select from register */
+ spin_lock_irqsave(&p->lock, flags);
+ tmp = readl_relaxed(p->base);
+ tmp = (tmp & ~SPICS_MASK(pin)) | SPICS_SET(pin, value);
+ writel_relaxed(tmp, p->base);
+ spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int elba_spics_direction_input(struct gpio_chip *chip, unsigned int pin)
+{
+ return -ENOTSUPP;
+}
+
+static int elba_spics_direction_output(struct gpio_chip *chip,
+ unsigned int pin, int value)
+{
+ elba_spics_set_value(chip, pin, value);
+ return 0;
+}
+
+static int elba_spics_probe(struct platform_device *pdev)
+{
+ struct elba_spics_priv *p;
+ struct resource *res;
+ int ret = 0;
+
+ p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ p->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(p->base))
+ return PTR_ERR(p->base);
+ spin_lock_init(&p->lock);
+ platform_set_drvdata(pdev, p);
+
+ p->chip.ngpio = 4; /* 2 cs pins for spi0, and 2 for spi1 */
+ p->chip.base = -1;
+ p->chip.direction_input = elba_spics_direction_input;
+ p->chip.direction_output = elba_spics_direction_output;
+ p->chip.get = elba_spics_get_value;
+ p->chip.set = elba_spics_set_value;
+ p->chip.label = dev_name(&pdev->dev);
+ p->chip.parent = &pdev->dev;
+ p->chip.owner = THIS_MODULE;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &p->chip, p);
+ if (ret)
+ dev_err(&pdev->dev, "unable to add gpio chip\n");
+ return ret;
+}
+
+static const struct of_device_id elba_spics_of_match[] = {
+ { .compatible = "pensando,elba-spics" },
+ {}
+};
+
+static struct platform_driver elba_spics_driver = {
+ .probe = elba_spics_probe,
+ .driver = {
+ .name = "pensando-elba-spics",
+ .of_match_table = elba_spics_of_match,
+ },
+};
+module_platform_driver(elba_spics_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Pensando Elba SoC SPI chip-select driver");
--
2.17.1
\
 
 \ /
  Last update: 2021-03-29 04:01    [W:2.073 / U:0.812 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site