blob: 559ec94c2e190417bf9716d0f2679d1e10b4b680 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
2From: Jonas Gorski <jonas.gorski@gmail.com>
3Date: Fri, 24 Jun 2016 22:07:42 +0200
4Subject: [PATCH 01/13] pinctrl: add bcm63xx base code
5
6Setup directory and add a helper for bcm63xx pinctrl support.
7
8Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
9---
10 drivers/pinctrl/Kconfig | 1 +
11 drivers/pinctrl/Makefile | 1 +
12 drivers/pinctrl/bcm63xx/Kconfig | 3 +
13 drivers/pinctrl/bcm63xx/Makefile | 1 +
14 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c | 142 ++++++++++++++++++++++++++++++
15 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h | 14 +++
16 7 files changed, 163 insertions(+)
17 create mode 100644 drivers/pinctrl/bcm63xx/Kconfig
18 create mode 100644 drivers/pinctrl/bcm63xx/Makefile
19 create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
20 create mode 100644 drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
21
22--- a/drivers/pinctrl/Kconfig
23+++ b/drivers/pinctrl/Kconfig
24@@ -387,6 +387,7 @@ config PINCTRL_OCELOT
25 source "drivers/pinctrl/actions/Kconfig"
26 source "drivers/pinctrl/aspeed/Kconfig"
27 source "drivers/pinctrl/bcm/Kconfig"
28+source "drivers/pinctrl/bcm63xx/Kconfig"
29 source "drivers/pinctrl/berlin/Kconfig"
30 source "drivers/pinctrl/freescale/Kconfig"
31 source "drivers/pinctrl/intel/Kconfig"
32--- a/drivers/pinctrl/Makefile
33+++ b/drivers/pinctrl/Makefile
34@@ -50,6 +50,7 @@ obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-
35 obj-y += actions/
36 obj-$(CONFIG_ARCH_ASPEED) += aspeed/
37 obj-y += bcm/
38+obj-y += bcm63xx/
39 obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
40 obj-y += freescale/
41 obj-$(CONFIG_X86) += intel/
42--- /dev/null
43+++ b/drivers/pinctrl/bcm63xx/Kconfig
44@@ -0,0 +1,3 @@
45+config PINCTRL_BCM63XX
46+ bool
47+ select GPIO_GENERIC
48--- /dev/null
49+++ b/drivers/pinctrl/bcm63xx/Makefile
50@@ -0,0 +1 @@
51+obj-$(CONFIG_PINCTRL_BCM63XX) += pinctrl-bcm63xx.o
52--- /dev/null
53+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.c
54@@ -0,0 +1,155 @@
55+/*
56+ * This file is subject to the terms and conditions of the GNU General Public
57+ * License. See the file "COPYING" in the main directory of this archive
58+ * for more details.
59+ *
60+ * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
61+ */
62+
63+#include <linux/bitops.h>
64+#include <linux/device.h>
65+#include <linux/gpio/driver.h>
66+#include <linux/of_irq.h>
67+
68+#include "pinctrl-bcm63xx.h"
69+#include "../core.h"
70+
71+#define BANK_SIZE sizeof(u32)
72+#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
73+
74+#ifdef CONFIG_OF
75+static int bcm63xx_gpio_of_xlate(struct gpio_chip *gc,
76+ const struct of_phandle_args *gpiospec,
77+ u32 *flags)
78+{
79+ struct gpio_chip *base = gpiochip_get_data(gc);
80+ int pin = gpiospec->args[0];
81+
82+ if (gc != &base[pin / PINS_PER_BANK])
83+ return -EINVAL;
84+
85+ pin = pin % PINS_PER_BANK;
86+
87+ if (pin >= gc->ngpio)
88+ return -EINVAL;
89+
90+ if (flags)
91+ *flags = gpiospec->args[1];
92+
93+ return pin;
94+}
95+#endif
96+
97+static int bcm63xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
98+{
99+ struct gpio_chip *base = gpiochip_get_data(chip);
100+ char irq_name[7]; /* "gpioXX" */
101+
102+ /* FIXME: this is ugly */
103+ sprintf(irq_name, "gpio%d", gpio + PINS_PER_BANK * (chip - base));
104+ return of_irq_get_byname(chip->of_node, irq_name);
105+}
106+
107+static int bcm63xx_setup_gpio(struct device *dev, struct gpio_chip *gc,
108+ void __iomem *dirout, void __iomem *data,
109+ size_t sz, int ngpio)
110+
111+{
112+ int banks, chips, i, ret = -EINVAL;
113+
114+ chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
115+ banks = sz / BANK_SIZE;
116+
117+ for (i = 0; i < chips; i++) {
118+ int offset, pins;
119+ int reg_offset;
120+ char *label;
121+
122+ label = devm_kasprintf(dev, GFP_KERNEL, "bcm63xx-gpio.%i", i);
123+ if (!label)
124+ return -ENOMEM;
125+
126+ offset = i * PINS_PER_BANK;
127+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
128+
129+ /* the registers are treated like a huge big endian register */
130+ reg_offset = (banks - i - 1) * BANK_SIZE;
131+
132+ ret = bgpio_init(&gc[i], dev, BANK_SIZE, data + reg_offset,
133+ NULL, NULL, dirout + reg_offset, NULL,
134+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
135+ if (ret)
136+ return ret;
137+
138+ gc[i].request = gpiochip_generic_request;
139+ gc[i].free = gpiochip_generic_free;
140+
141+ if (of_get_property(dev->of_node, "interrupt-names", NULL))
142+ gc[i].to_irq = bcm63xx_gpio_to_irq;
143+
144+#ifdef CONFIG_OF
145+ gc[i].of_gpio_n_cells = 2;
146+ gc[i].of_xlate = bcm63xx_gpio_of_xlate;
147+#endif
148+
149+ gc[i].label = label;
150+ gc[i].ngpio = pins;
151+
152+ devm_gpiochip_add_data(dev, &gc[i], gc);
153+ }
154+
155+ return 0;
156+}
157+
158+static void bcm63xx_setup_pinranges(struct gpio_chip *gc, const char *name,
159+ int ngpio)
160+{
161+ int i, chips = DIV_ROUND_UP(ngpio, PINS_PER_BANK);
162+
163+ for (i = 0; i < chips; i++) {
164+ int offset, pins;
165+
166+ offset = i * PINS_PER_BANK;
167+ pins = min_t(int, ngpio - offset, PINS_PER_BANK);
168+
169+ gpiochip_add_pin_range(&gc[i], name, 0, offset, pins);
170+ }
171+}
172+
173+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
174+ struct pinctrl_desc *desc,
175+ void *priv, struct gpio_chip *gc,
176+ int ngpio)
177+{
178+ struct pinctrl_dev *pctldev;
179+ struct resource *res;
180+ void __iomem *dirout, *data;
181+ size_t sz;
182+ int ret;
183+
184+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirout");
185+ dirout = devm_ioremap_resource(&pdev->dev, res);
186+ if (IS_ERR(dirout))
187+ return ERR_CAST(dirout);
188+
189+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
190+ data = devm_ioremap_resource(&pdev->dev, res);
191+ if (IS_ERR(data))
192+ return ERR_CAST(data);
193+
194+ sz = resource_size(res);
195+
196+ ret = bcm63xx_setup_gpio(&pdev->dev, gc, dirout, data, sz, ngpio);
197+ if (ret)
198+ return ERR_PTR(ret);
199+
200+ pctldev = devm_pinctrl_register(&pdev->dev, desc, priv);
201+ if (IS_ERR(pctldev))
202+ return pctldev;
203+
204+ bcm63xx_setup_pinranges(gc, pinctrl_dev_get_devname(pctldev), ngpio);
205+
206+ dev_info(&pdev->dev, "registered at mmio %p\n", dirout);
207+
208+ return pctldev;
209+}
210--- /dev/null
211+++ b/drivers/pinctrl/bcm63xx/pinctrl-bcm63xx.h
212@@ -0,0 +1,14 @@
213+#ifndef __PINCTRL_BCM63XX
214+#define __PINCTRL_BCM63XX
215+
216+#include <linux/kernel.h>
217+#include <linux/gpio.h>
218+#include <linux/pinctrl/pinctrl.h>
219+#include <linux/platform_device.h>
220+
221+struct pinctrl_dev *bcm63xx_pinctrl_register(struct platform_device *pdev,
222+ struct pinctrl_desc *desc,
223+ void *priv, struct gpio_chip *gc,
224+ int ngpio);
225+
226+#endif