Refresh patches to make them apply to kernel 5.4. The removed patches have been merged upstream. Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
		
			
				
	
	
		
			227 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
 | 
						|
From: Jonas Gorski <jonas.gorski@gmail.com>
 | 
						|
Date: Fri, 24 Jun 2016 22:07:42 +0200
 | 
						|
Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
 | 
						|
 | 
						|
Setup directory and add a helper for bcm63xx pinctrl support.
 | 
						|
 | 
						|
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
 | 
						|
---
 | 
						|
 drivers/pinctrl/Kconfig                   |   1 +
 | 
						|
 drivers/pinctrl/Makefile                  |   1 +
 | 
						|
 drivers/pinctrl/bcm63xx/Kconfig           |   3 +
 | 
						|
 drivers/pinctrl/bcm63xx/Makefile          |   1 +
 | 
						|
 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
 | 
						|
 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h |  14 +++
 | 
						|
 7 files changed, 163 insertions(+)
 | 
						|
 create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
 | 
						|
 create mode 100644 drivers/pinctrl/bcm63xx/Makefile
 | 
						|
 create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
 | 
						|
 create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
 | 
						|
 | 
						|
--- a/drivers/pinctrl/Kconfig
 | 
						|
+++ b/drivers/pinctrl/Kconfig
 | 
						|
@@ -387,6 +387,7 @@ config PINCTRL_OCELOT
 | 
						|
 source "drivers/pinctrl/actions/Kconfig"
 | 
						|
 source "drivers/pinctrl/aspeed/Kconfig"
 | 
						|
 source "drivers/pinctrl/bcm/Kconfig"
 | 
						|
+source "drivers/pinctrl/bcm63xx/Kconfig"
 | 
						|
 source "drivers/pinctrl/berlin/Kconfig"
 | 
						|
 source "drivers/pinctrl/freescale/Kconfig"
 | 
						|
 source "drivers/pinctrl/intel/Kconfig"
 | 
						|
--- a/drivers/pinctrl/Makefile
 | 
						|
+++ b/drivers/pinctrl/Makefile
 | 
						|
@@ -50,6 +50,7 @@ obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-
 | 
						|
 obj-y				+= actions/
 | 
						|
 obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
 | 
						|
 obj-y				+= bcm/
 | 
						|
+obj-y				+= bcm63xx/
 | 
						|
 obj-$(CONFIG_PINCTRL_BERLIN)	+= berlin/
 | 
						|
 obj-y				+= freescale/
 | 
						|
 obj-$(CONFIG_X86)		+= intel/
 | 
						|
--- /dev/null
 | 
						|
+++ b/drivers/pinctrl/bcm63xx/Kconfig
 | 
						|
@@ -0,0 +1,3 @@
 | 
						|
+config PINCTRL_BCM63XX
 | 
						|
+	bool
 | 
						|
+	select GPIO_GENERIC
 | 
						|
--- /dev/null
 | 
						|
+++ b/drivers/pinctrl/bcm63xx/Makefile
 | 
						|
@@ -0,0 +1 @@
 | 
						|
+obj-$(CONFIG_PINCTRL_BCM63XX)	+= pinctrl-bcm63xx.o
 | 
						|
--- /dev/null
 | 
						|
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
 | 
						|
@@ -0,0 +1,155 @@
 | 
						|
+/*
 | 
						|
+ * This file is subject to the terms and conditions of the GNU General Public
 | 
						|
+ * License.  See the file "COPYING" in the main directory of this archive
 | 
						|
+ * for more details.
 | 
						|
+ *
 | 
						|
+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
 | 
						|
+ */
 | 
						|
+
 | 
						|
+#include <linux/bitops.h>
 | 
						|
+#include <linux/device.h>
 | 
						|
+#include <linux/gpio/driver.h>
 | 
						|
+#include <linux/of_irq.h>
 | 
						|
+
 | 
						|
+#include "pinctrl-bcm63xx.h"
 | 
						|
+#include "../core.h"
 | 
						|
+
 | 
						|
+#define BANK_SIZE	sizeof(u32)
 | 
						|
+#define PINS_PER_BANK	(BANK_SIZE * BITS_PER_BYTE)
 | 
						|
+
 | 
						|
+#ifdef CONFIG_OF
 | 
						|
+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
 | 
						|
+				 const struct of_phandle_args *gpiospec,
 | 
						|
+				 u32 *flags)
 | 
						|
+{
 | 
						|
+	struct gpio_chip *base = gpiochip_get_data(gc);
 | 
						|
+	int pin = gpiospec->args[0];
 | 
						|
+
 | 
						|
+	if (gc != &base[pin / PINS_PER_BANK])
 | 
						|
+		return -EINVAL;
 | 
						|
+
 | 
						|
+	pin = pin % PINS_PER_BANK;
 | 
						|
+
 | 
						|
+	if (pin >= gc->ngpio)
 | 
						|
+		return -EINVAL;
 | 
						|
+
 | 
						|
+	if (flags)
 | 
						|
+		*flags = gpiospec->args[1];
 | 
						|
+
 | 
						|
+	return pin;
 | 
						|
+}
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
 | 
						|
+{
 | 
						|
+	struct gpio_chip *base = gpiochip_get_data(chip);
 | 
						|
+	char irq_name[7]; /* "gpioXX" */
 | 
						|
+
 | 
						|
+	/* FIXME: this is ugly */
 | 
						|
+	sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
 | 
						|
+	return of_irq_get_byname(chip->of_node, irq_name);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
 | 
						|
+			      void __iomem *dirout, void __iomem *data,
 | 
						|
+			      size_t sz, int ngpio)
 | 
						|
+
 | 
						|
+{
 | 
						|
+	int banks, chips, i, ret = -EINVAL;
 | 
						|
+
 | 
						|
+	chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
 | 
						|
+	banks = sz / BANK_SIZE;
 | 
						|
+
 | 
						|
+	for (i = 0; i < chips; i++) {
 | 
						|
+		int offset, pins;
 | 
						|
+		int reg_offset;
 | 
						|
+		char *label;
 | 
						|
+
 | 
						|
+		label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
 | 
						|
+		if (!label)
 | 
						|
+			return -ENOMEM;
 | 
						|
+
 | 
						|
+		offset = i * PINS_PER_BANK;
 | 
						|
+		pins = min_t(int, ngpio - offset, PINS_PER_BANK);
 | 
						|
+
 | 
						|
+		/* the registers are treated like a huge big endian register */
 | 
						|
+		reg_offset = (banks - i - 1) * BANK_SIZE;
 | 
						|
+
 | 
						|
+		ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
 | 
						|
+				 NULL, NULL, dirout + reg_offset, NULL,
 | 
						|
+				 BGPIOF_BIG_ENDIAN_BYTE_ORDER);
 | 
						|
+		if (ret)
 | 
						|
+			return ret;
 | 
						|
+
 | 
						|
+		gc[i].request = gpiochip_generic_request;
 | 
						|
+		gc[i].free = gpiochip_generic_free;
 | 
						|
+
 | 
						|
+		if (of_get_property(dev->of_node, "interrupt-names", NULL))
 | 
						|
+			gc[i].to_irq = bcm63xx_gpio_to_irq;
 | 
						|
+
 | 
						|
+#ifdef CONFIG_OF
 | 
						|
+		gc[i].of_gpio_n_cells = 2;
 | 
						|
+		gc[i].of_xlate = bcm63xx_gpio_of_xlate;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+		gc[i].label = label;
 | 
						|
+		gc[i].ngpio = pins;
 | 
						|
+
 | 
						|
+		devm_gpiochip_add_data(dev, &gc[i], gc);
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
 | 
						|
+				    int ngpio)
 | 
						|
+{
 | 
						|
+	int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
 | 
						|
+
 | 
						|
+	for (i = 0; i < chips; i++) {
 | 
						|
+		int offset, pins;
 | 
						|
+
 | 
						|
+		offset = i * PINS_PER_BANK;
 | 
						|
+		pins = min_t(int, ngpio - offset, PINS_PER_BANK);
 | 
						|
+
 | 
						|
+		gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
 | 
						|
+					     struct pinctrl_desc *desc,
 | 
						|
+					     void *priv, struct gpio_chip *gc,
 | 
						|
+					     int ngpio)
 | 
						|
+{
 | 
						|
+	struct pinctrl_dev *pctldev;
 | 
						|
+	struct resource *res;
 | 
						|
+	void __iomem *dirout, *data;
 | 
						|
+	size_t sz;
 | 
						|
+	int ret;
 | 
						|
+
 | 
						|
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
 | 
						|
+	dirout = devm_ioremap_resource(&pdev->dev, res);
 | 
						|
+	if (IS_ERR(dirout))
 | 
						|
+		return ERR_CAST(dirout);
 | 
						|
+
 | 
						|
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 | 
						|
+	data = devm_ioremap_resource(&pdev->dev, res);
 | 
						|
+	if (IS_ERR(data))
 | 
						|
+		return ERR_CAST(data);
 | 
						|
+
 | 
						|
+	sz = resource_size(res);
 | 
						|
+
 | 
						|
+	ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
 | 
						|
+	if (ret)
 | 
						|
+		return ERR_PTR(ret);
 | 
						|
+
 | 
						|
+	pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
 | 
						|
+	if (IS_ERR(pctldev))
 | 
						|
+		return pctldev;
 | 
						|
+
 | 
						|
+	bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
 | 
						|
+
 | 
						|
+	dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
 | 
						|
+
 | 
						|
+	return pctldev;
 | 
						|
+}
 | 
						|
--- /dev/null
 | 
						|
+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
 | 
						|
@@ -0,0 +1,14 @@
 | 
						|
+#ifndef __PINCTRL_BCM63XX
 | 
						|
+#define __PINCTRL_BCM63XX
 | 
						|
+
 | 
						|
+#include <linux/kernel.h>
 | 
						|
+#include <linux/gpio.h>
 | 
						|
+#include <linux/pinctrl/pinctrl.h>
 | 
						|
+#include <linux/platform_device.h>
 | 
						|
+
 | 
						|
+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
 | 
						|
+					     struct pinctrl_desc *desc,
 | 
						|
+					     void *priv, struct gpio_chip *gc,
 | 
						|
+					     int ngpio);
 | 
						|
+
 | 
						|
+#endif
 |