123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- From ab2f33e35e35905a76204138143875251f3e1088 Mon Sep 17 00:00:00 2001
- From: Jonas Gorski <[email protected]>
- 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 <[email protected]>
- ---
- 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
- @@ -258,6 +258,7 @@ config PINCTRL_ZYNQ
-
- 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
- @@ -39,6 +39,7 @@ obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zy
-
- 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 <[email protected]>
- + */
- +
- +#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
|