This driver reuses the core of the driver already present in pinctrl-ingenic.c, and just supplies callbacks to perform the low-level operations. Signed-off-by: Paul Cercueil <paul@xxxxxxxxxxxxxxx> --- drivers/pinctrl/ingenic/Kconfig | 6 ++ drivers/pinctrl/ingenic/Makefile | 1 + drivers/pinctrl/ingenic/pinctrl-jz4780.c | 179 +++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 drivers/pinctrl/ingenic/pinctrl-jz4780.c diff --git a/drivers/pinctrl/ingenic/Kconfig b/drivers/pinctrl/ingenic/Kconfig index 9923ce127183..15b6514c1948 100644 --- a/drivers/pinctrl/ingenic/Kconfig +++ b/drivers/pinctrl/ingenic/Kconfig @@ -12,3 +12,9 @@ config PINCTRL_JZ4740 default y depends on MACH_JZ4740 || COMPILE_TEST select PINCTRL_INGENIC + +config PINCTRL_JZ4780 + bool "Pinctrl driver for the Ingenic JZ4780 SoC" + default y + depends on MACH_JZ4780 || COMPILE_TEST + select PINCTRL_INGENIC diff --git a/drivers/pinctrl/ingenic/Makefile b/drivers/pinctrl/ingenic/Makefile index 8b2c8b789dc9..ad691f053207 100644 --- a/drivers/pinctrl/ingenic/Makefile +++ b/drivers/pinctrl/ingenic/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o obj-$(CONFIG_PINCTRL_JZ4740) += pinctrl-jz4740.o +obj-$(CONFIG_PINCTRL_JZ4780) += pinctrl-jz4780.o diff --git a/drivers/pinctrl/ingenic/pinctrl-jz4780.c b/drivers/pinctrl/ingenic/pinctrl-jz4780.c new file mode 100644 index 000000000000..a191cd1711e7 --- /dev/null +++ b/drivers/pinctrl/ingenic/pinctrl-jz4780.c @@ -0,0 +1,179 @@ +/* + * Ingenic jz4780 pinctrl driver + * + * Copyright (c) 2013 Imagination Technologies + * Copyright (c) 2017 Paul Cercueil <paul@xxxxxxxxxxxxxxx> + * + * Authors: Paul Burton <paul.burton@xxxxxxxxxx>, + * Paul Cercueil <paul@xxxxxxxxxxxxxxx> + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include "pinctrl-ingenic.h" + +#include <dt-bindings/interrupt-controller/irq.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> + +/* GPIO port register offsets */ +#define GPIO_PIN 0x00 +#define GPIO_INT 0x10 +#define GPIO_INTS 0x14 +#define GPIO_INTC 0x18 +#define GPIO_MSK 0x20 +#define GPIO_MSKS 0x24 +#define GPIO_MSKC 0x28 +#define GPIO_PAT1 0x30 +#define GPIO_PAT1S 0x34 +#define GPIO_PAT1C 0x38 +#define GPIO_PAT0 0x40 +#define GPIO_PAT0S 0x44 +#define GPIO_PAT0C 0x48 +#define GPIO_FLG 0x50 +#define GPIO_FLGC 0x58 +#define GPIO_PEN 0x70 +#define GPIO_PENS 0x74 +#define GPIO_PENC 0x78 + +static void jz4780_set_gpio(void __iomem *base, + unsigned int offset, bool output) +{ + writel(1 << offset, base + GPIO_INTC); + writel(1 << offset, base + GPIO_MSKS); + + if (output) + writel(1 << offset, base + GPIO_PAT1C); + else + writel(1 << offset, base + GPIO_PAT1S); +} + +static int jz4780_get_bias(void __iomem *base, unsigned int offset) +{ + return !((readl(base + GPIO_PEN) >> offset) & 0x1); +} + +static void jz4780_set_bias(void __iomem *base, + unsigned int offset, bool enable) +{ + if (enable) + writel(1 << offset, base + GPIO_PENC); + else + writel(1 << offset, base + GPIO_PENS); +} + +static void jz4780_gpio_set_value(void __iomem *base, + unsigned int offset, int value) +{ + if (value) + writel(1 << offset, base + GPIO_PAT0S); + else + writel(1 << offset, base + GPIO_PAT0C); +} + +static int jz4780_gpio_get_value(void __iomem *base, unsigned int offset) +{ + return (readl(base + GPIO_PIN) >> offset) & 0x1; +} + +static u32 jz4780_irq_read(void __iomem *base) +{ + return readl(base + GPIO_FLG); +} + +static void jz4780_irq_mask(void __iomem *base, unsigned int offset, bool mask) +{ + if (mask) + writel(1 << offset, base + GPIO_MSKS); + else + writel(1 << offset, base + GPIO_MSKC); +} + +static void jz4780_irq_ack(void __iomem *base, unsigned int offset) +{ + writel(1 << offset, base + GPIO_FLGC); +} + +static void jz4780_irq_set_type(void __iomem *base, + unsigned int offset, unsigned int type) +{ + enum { + PAT_EDGE_RISING = 0x3, + PAT_EDGE_FALLING = 0x2, + PAT_LEVEL_HIGH = 0x1, + PAT_LEVEL_LOW = 0x0, + } pat; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + pat = PAT_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + pat = PAT_EDGE_FALLING; + break; + case IRQ_TYPE_LEVEL_HIGH: + pat = PAT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + default: + pat = PAT_LEVEL_LOW; + break; + }; + + writel(1 << offset, base + ((pat & 0x2) ? GPIO_PAT1S : GPIO_PAT1C)); + writel(1 << offset, base + ((pat & 0x1) ? GPIO_PAT0S : GPIO_PAT0C)); + writel(1 << offset, base + GPIO_INTS); +} + +static void jz4780_set_function(void __iomem *base, + unsigned int offset, unsigned int func) +{ + writel(1 << offset, base + GPIO_INTC); + writel(1 << offset, base + GPIO_MSKC); + writel(1 << offset, base + ((func & 0x2) ? GPIO_PAT1S : GPIO_PAT1C)); + writel(1 << offset, base + ((func & 0x1) ? GPIO_PAT0S : GPIO_PAT0C)); +} + +static const struct ingenic_pinctrl_ops jz4780_pinctrl_ops = { + .nb_functions = 4, + .set_function = jz4780_set_function, + .set_gpio = jz4780_set_gpio, + .set_bias = jz4780_set_bias, + .get_bias = jz4780_get_bias, + .gpio_set_value = jz4780_gpio_set_value, + .gpio_get_value = jz4780_gpio_get_value, + .irq_read = jz4780_irq_read, + .irq_mask = jz4780_irq_mask, + .irq_ack = jz4780_irq_ack, + .irq_set_type = jz4780_irq_set_type, +}; + +static int jz4780_pinctrl_probe(struct platform_device *pdev) +{ + return ingenic_pinctrl_probe(pdev, &jz4780_pinctrl_ops); +} + +static const struct of_device_id jz4780_pinctrl_dt_match[] = { + { .compatible = "ingenic,jz4780-pinctrl", }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4780_pinctrl_dt_match); + + +static struct platform_driver jz4780_pinctrl_driver = { + .driver = { + .name = "jz4780-pinctrl", + .of_match_table = of_match_ptr(jz4780_pinctrl_dt_match), + .suppress_bind_attrs = true, + }, + .probe = jz4780_pinctrl_probe, +}; + +static int __init jz4780_pinctrl_drv_register(void) +{ + return platform_driver_register(&jz4780_pinctrl_driver); +} +postcore_initcall(jz4780_pinctrl_drv_register); -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html