Add a generic mmio gpio controller based driver and probe it through device tree. Use aliases for base calculation until we converted all users to device tree or named gpios. Convert bcm63xx_enet's ephy-reset gpio to use a named gpio. While at it, remove the duplicate reset gpio defintion for livebox. Signed-off-by: Jonas Gorski <jogo@openwrt.org> SVN-Revision: 44565master
parent
1efb7398e1
commit
eea227c60d
@ -0,0 +1,161 @@ |
||||
From dbe94a8daaa63ef81b7414f2a17bca8e36dd6daa Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Fri, 20 Feb 2015 19:55:32 +0100
|
||||
Subject: [PATCH 1/6] gpio: add a simple GPIO driver for bcm63xx
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
drivers/gpio/Kconfig | 8 +++
|
||||
drivers/gpio/Makefile | 1 +
|
||||
drivers/gpio/gpio-bcm63xx.c | 117 +++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 126 insertions(+)
|
||||
create mode 100644 drivers/gpio/gpio-bcm63xx.c
|
||||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -821,6 +821,14 @@ config GPIO_BCM_KONA
|
||||
help
|
||||
Turn on GPIO support for Broadcom "Kona" chips.
|
||||
|
||||
+config GPIO_BCM63XX
|
||||
+ bool "Broadcom BCM63XX GPIO"
|
||||
+ depends on MIPS || COMPILE_TEST
|
||||
+ select GPIO_GENERIC
|
||||
+ help
|
||||
+ Turn on GPIO support for Broadcom BCM63XX xDSL chips.
|
||||
+
|
||||
+
|
||||
comment "USB GPIO expanders:"
|
||||
|
||||
config GPIO_VIPERBOARD
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp55
|
||||
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
||||
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
|
||||
+obj-$(CONFIG_GPIO_BCM63XX) += gpio-bcm63xx.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-bcm63xx.c
|
||||
@@ -0,0 +1,117 @@
|
||||
+/*
|
||||
+ * Driver for BCM63XX memory-mapped GPIO controllers, based on
|
||||
+ * Generic driver for memory-mapped GPIO controllers.
|
||||
+ *
|
||||
+ * Copyright 2008 MontaVista Software, Inc.
|
||||
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
|
||||
+ * Copyright 2015 Jonas Gorski <jogo@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/bug.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/ioport.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/basic_mmio_gpio.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+
|
||||
+static int bcm63xx_gpio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct resource *dat_r, *dirout_r;
|
||||
+ void __iomem *dat;
|
||||
+ void __iomem *dirout;
|
||||
+ unsigned long sz;
|
||||
+ int err;
|
||||
+ struct bgpio_chip *bgc;
|
||||
+ struct bgpio_pdata *pdata = dev_get_platdata(dev);
|
||||
+
|
||||
+ dat_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ dirout_r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
+ if (!dat_r || !dirout_r)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (resource_size(dat_r) != resource_size(dirout_r))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ sz = resource_size(dat_r);
|
||||
+
|
||||
+ dat = devm_ioremap_resource(dev, dat_r);
|
||||
+ if (IS_ERR(dat))
|
||||
+ return PTR_ERR(dat);
|
||||
+
|
||||
+ dirout = devm_ioremap_resource(dev, dirout_r);
|
||||
+ if (IS_ERR(dirout))
|
||||
+ return PTR_ERR(dirout);
|
||||
+
|
||||
+ bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
|
||||
+ if (!bgc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ err = bgpio_init(bgc, dev, sz, dat, NULL, NULL, dirout, NULL,
|
||||
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, bgc);
|
||||
+
|
||||
+ if (dev->of_node) {
|
||||
+ u32 ngpios;
|
||||
+
|
||||
+ if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
|
||||
+ bgc->gc.ngpio = ngpios;
|
||||
+
|
||||
+ } else if (pdata) {
|
||||
+ bgc->gc.base = pdata->base;
|
||||
+ if (pdata->ngpio > 0)
|
||||
+ bgc->gc.ngpio = pdata->ngpio;
|
||||
+ }
|
||||
+
|
||||
+ return gpiochip_add(&bgc->gc);
|
||||
+}
|
||||
+
|
||||
+static int bcm63xx_gpio_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bgpio_chip *bgc = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ return bgpio_remove(bgc);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct of_device_id bcm63xx_gpio_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm6345-gpio" },
|
||||
+ { },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver bcm63xx_gpio_driver = {
|
||||
+ .probe = bcm63xx_gpio_probe,
|
||||
+ .remove = bcm63xx_gpio_remove,
|
||||
+ .driver = {
|
||||
+ .name = "bcm63xx-gpio",
|
||||
+ .of_match_table = of_match_ptr(bcm63xx_gpio_of_match),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(bcm63xx_gpio_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Driver for BCM63XX memory-mapped GPIO controllers");
|
||||
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,216 @@ |
||||
From cc99dca188bb63ba390008e2f7fa62d0300233e0 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Fri, 20 Feb 2015 23:58:54 +0100
|
||||
Subject: [PATCH 2/6] MIPS: BCM63XX: switch to new gpio driver
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_common.c | 2 +
|
||||
arch/mips/bcm63xx/gpio.c | 147 +++++++------------------------
|
||||
arch/mips/bcm63xx/prom.c | 3 -
|
||||
3 files changed, 33 insertions(+), 119 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -204,6 +204,8 @@ int __init board_register_devices(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ bcm63xx_gpio_init();
|
||||
+
|
||||
if (board.has_uart0)
|
||||
bcm63xx_uart_register(0);
|
||||
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -5,147 +5,62 @@
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org>
|
||||
+ * Copyright (C) Jonas Gorski <jogo@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
-#include <linux/module.h>
|
||||
-#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/basic_mmio_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
-#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
-static u32 gpio_out_low_reg;
|
||||
-
|
||||
-static void bcm63xx_gpio_out_low_reg_init(void)
|
||||
+static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
|
||||
{
|
||||
- switch (bcm63xx_get_cpu_id()) {
|
||||
- case BCM6345_CPU_ID:
|
||||
- gpio_out_low_reg = GPIO_DATA_LO_REG_6345;
|
||||
- break;
|
||||
- default:
|
||||
- gpio_out_low_reg = GPIO_DATA_LO_REG;
|
||||
- break;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
|
||||
-static u32 gpio_out_low, gpio_out_high;
|
||||
+ struct resource res[2];
|
||||
+ struct bgpio_pdata pdata;
|
||||
|
||||
-static void bcm63xx_gpio_set(struct gpio_chip *chip,
|
||||
- unsigned gpio, int val)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
- u32 *v;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
-
|
||||
- if (gpio < 32) {
|
||||
- reg = gpio_out_low_reg;
|
||||
- mask = 1 << gpio;
|
||||
- v = &gpio_out_low;
|
||||
- } else {
|
||||
- reg = GPIO_DATA_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- v = &gpio_out_high;
|
||||
- }
|
||||
-
|
||||
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
- if (val)
|
||||
- *v |= mask;
|
||||
- else
|
||||
- *v &= ~mask;
|
||||
- bcm_gpio_writel(*v, reg);
|
||||
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
-}
|
||||
+ memset(res, 0, sizeof(res));
|
||||
+ memset(&pdata, 0, sizeof(pdata));
|
||||
|
||||
-static int bcm63xx_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
+ res[0].flags = IORESOURCE_MEM;
|
||||
+ res[0].start = bcm63xx_regset_address(RSET_GPIO);
|
||||
+ res[0].start += data;
|
||||
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
+ res[0].end = res[0].start + 3;
|
||||
|
||||
- if (gpio < 32) {
|
||||
- reg = gpio_out_low_reg;
|
||||
- mask = 1 << gpio;
|
||||
- } else {
|
||||
- reg = GPIO_DATA_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- }
|
||||
+ res[1].flags = IORESOURCE_MEM;
|
||||
+ res[1].start = bcm63xx_regset_address(RSET_GPIO);
|
||||
+ res[1].start += dir;
|
||||
|
||||
- return !!(bcm_gpio_readl(reg) & mask);
|
||||
-}
|
||||
+ res[1].end = res[1].start + 3;
|
||||
|
||||
-static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
|
||||
- unsigned gpio, int dir)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
- u32 tmp;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
-
|
||||
- if (gpio < 32) {
|
||||
- reg = GPIO_CTL_LO_REG;
|
||||
- mask = 1 << gpio;
|
||||
- } else {
|
||||
- reg = GPIO_CTL_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- }
|
||||
-
|
||||
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
- tmp = bcm_gpio_readl(reg);
|
||||
- if (dir == BCM63XX_GPIO_DIR_IN)
|
||||
- tmp &= ~mask;
|
||||
- else
|
||||
- tmp |= mask;
|
||||
- bcm_gpio_writel(tmp, reg);
|
||||
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
+ pdata.base = id * 32;
|
||||
+ pdata.ngpio = ngpio;
|
||||
|
||||
- return 0;
|
||||
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
+ &pdata, sizeof(pdata));
|
||||
}
|
||||
|
||||
-static int bcm63xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
+int __init bcm63xx_gpio_init(void)
|
||||
{
|
||||
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_IN);
|
||||
-}
|
||||
+ int ngpio = bcm63xx_gpio_count();
|
||||
+ int data_low_reg;
|
||||
|
||||
-static int bcm63xx_gpio_direction_output(struct gpio_chip *chip,
|
||||
- unsigned gpio, int value)
|
||||
-{
|
||||
- bcm63xx_gpio_set(chip, gpio, value);
|
||||
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_OUT);
|
||||
-}
|
||||
+ if (BCMCPU_IS_6345())
|
||||
+ data_low_reg = GPIO_DATA_LO_REG_6345;
|
||||
+ else
|
||||
+ data_low_reg = GPIO_DATA_LO_REG;
|
||||
|
||||
+ bcm63xx_gpio_init_one(0, data_low_reg, GPIO_CTL_LO_REG, min(ngpio, 32));
|
||||
|
||||
-static struct gpio_chip bcm63xx_gpio_chip = {
|
||||
- .label = "bcm63xx-gpio",
|
||||
- .direction_input = bcm63xx_gpio_direction_input,
|
||||
- .direction_output = bcm63xx_gpio_direction_output,
|
||||
- .get = bcm63xx_gpio_get,
|
||||
- .set = bcm63xx_gpio_set,
|
||||
- .base = 0,
|
||||
-};
|
||||
+ if (ngpio <= 32)
|
||||
+ return 0;
|
||||
|
||||
-int __init bcm63xx_gpio_init(void)
|
||||
-{
|
||||
- bcm63xx_gpio_out_low_reg_init();
|
||||
+ bcm63xx_gpio_init_one(1, GPIO_DATA_HI_REG, GPIO_CTL_HI_REG, ngpio - 32);
|
||||
|
||||
- gpio_out_low = bcm_gpio_readl(gpio_out_low_reg);
|
||||
- if (!BCMCPU_IS_6345())
|
||||
- gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG);
|
||||
- bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
|
||||
- pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
|
||||
+ return 0;
|
||||
|
||||
- return gpiochip_add(&bcm63xx_gpio_chip);
|
||||
}
|
||||
--- a/arch/mips/bcm63xx/prom.c
|
||||
+++ b/arch/mips/bcm63xx/prom.c
|
||||
@@ -54,9 +54,6 @@ void __init prom_init(void)
|
||||
reg &= ~mask;
|
||||
bcm_perf_writel(reg, PERF_CKCTL_REG);
|
||||
|
||||
- /* register gpiochip */
|
||||
- bcm63xx_gpio_init();
|
||||
-
|
||||
/* detect and setup flash access */
|
||||
bcm63xx_flash_detect();
|
||||
|
@ -0,0 +1,49 @@ |
||||
From ec905f2ea78ec40602a685ede31c5e4f9893d196 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 16:35:07 +0100
|
||||
Subject: [PATCH 3/6] net: bcm63xx_enet: use named gpio for ephy reset gpio
|
||||
|
||||
Allow using a named optional gpio for ephy reset gpio registration.
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/if_vlan.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include "bcm63xx_enet.h"
|
||||
@@ -2852,10 +2853,18 @@ static int bcm_enet_shared_probe(struct
|
||||
{
|
||||
struct resource *res;
|
||||
void __iomem *p[3];
|
||||
+ struct gpio_desc *ephy_reset;
|
||||
unsigned int i;
|
||||
|
||||
memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base));
|
||||
|
||||
+ ephy_reset = devm_gpiod_get(&pdev->dev, "ephy-reset");
|
||||
+ if (IS_ERR(ephy_reset)) {
|
||||
+ if (PTR_ERR(ephy_reset) != -ENOENT)
|
||||
+ return PTR_ERR(ephy_reset);
|
||||
+ ephy_reset = NULL;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < 3; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
p[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
@@ -2865,6 +2874,9 @@ static int bcm_enet_shared_probe(struct
|
||||
|
||||
memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base));
|
||||
|
||||
+ if (ephy_reset)
|
||||
+ gpiod_direction_output(ephy_reset, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,138 @@ |
||||
From d13bdf92ec885105cf107183f8464c40e5f3b93b Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 17:21:59 +0100
|
||||
Subject: [PATCH 4/6] MIPS: BCM63XX: register lookup for ephy-reset gpio
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
|
||||
arch/mips/bcm63xx/boards/board_common.c | 7 +++--
|
||||
arch/mips/bcm63xx/gpio.c | 32 ++++++++++++++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 ++
|
||||
.../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 5 +--
|
||||
5 files changed, 42 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -59,7 +59,7 @@ static struct board_info __initdata boar
|
||||
},
|
||||
|
||||
.ephy_reset_gpio = 36,
|
||||
- .ephy_reset_gpio_flags = GPIOF_INIT_HIGH,
|
||||
+ .ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
|
||||
};
|
||||
#endif
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -278,9 +278,10 @@ int __init board_register_devices(void)
|
||||
platform_device_register(&bcm63xx_gpio_leds);
|
||||
}
|
||||
|
||||
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
|
||||
- gpio_request_one(board.ephy_reset_gpio,
|
||||
- board.ephy_reset_gpio_flags, "ephy-reset");
|
||||
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) {
|
||||
+ bcm63xx_gpio_ephy_reset(board.ephy_reset_gpio,
|
||||
+ board.ephy_reset_gpio_flags);
|
||||
+ }
|
||||
|
||||
/* count number of BUTTONs defined by this device */
|
||||
while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -8,15 +8,24 @@
|
||||
* Copyright (C) Jonas Gorski <jogo@openwrt.org>
|
||||
*/
|
||||
|
||||
+#include <asm/addrspace.h>
|
||||
+
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/basic_mmio_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
+/* for registering lookups; make them large enough to hold OF names */
|
||||
+static char *gpio_chip_labels[] = {
|
||||
+ "xxxxxxxx.gpio-controller",
|
||||
+ "xxxxxxxx.gpio-controller",
|
||||
+};
|
||||
+
|
||||
static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
|
||||
{
|
||||
struct resource res[2];
|
||||
@@ -40,6 +49,7 @@ static void __init bcm63xx_gpio_init_one
|
||||
pdata.base = id * 32;
|
||||
pdata.ngpio = ngpio;
|
||||
|
||||
+ sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
&pdata, sizeof(pdata));
|
||||
}
|
||||
@@ -64,3 +74,25 @@ int __init bcm63xx_gpio_init(void)
|
||||
return 0;
|
||||
|
||||
}
|
||||
+
|
||||
+static struct gpiod_lookup_table ephy_reset = {
|
||||
+ .dev_id = "bcm63xx_enet_shared.0",
|
||||
+ .table = {
|
||||
+ { /* filled at runtime */ },
|
||||
+ { },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+
|
||||
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags)
|
||||
+{
|
||||
+ if (ephy_reset.table[0].chip_label)
|
||||
+ return;
|
||||
+
|
||||
+ ephy_reset.table[0].chip_label = gpio_chip_labels[hw_gpio / 32];
|
||||
+ ephy_reset.table[0].chip_hwnum = hw_gpio % 32;
|
||||
+ ephy_reset.table[0].con_id = "ephy-reset";
|
||||
+ ephy_reset.table[0].flags = flags;
|
||||
+
|
||||
+ gpiod_add_lookup_table(&ephy_reset);
|
||||
+}
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
|
||||
@@ -2,9 +2,11 @@
|
||||
#define BCM63XX_GPIO_H
|
||||
|
||||
#include <linux/init.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
|
||||
int __init bcm63xx_gpio_init(void);
|
||||
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags);
|
||||
|
||||
static inline unsigned long bcm63xx_gpio_count(void)
|
||||
{
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
#include <linux/leds.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
@@ -58,8 +59,8 @@ struct board_info {
|
||||
/* External PHY reset GPIO */
|
||||
unsigned int ephy_reset_gpio;
|
||||
|
||||
- /* External PHY reset GPIO flags from gpio.h */
|
||||
- unsigned long ephy_reset_gpio_flags;
|
||||
+ /* External PHY reset GPIO flags from gpio/machine.h */
|
||||
+ enum gpio_lookup_flags ephy_reset_gpio_flags;
|
||||
|
||||
/* fallback sprom config */
|
||||
struct fallback_sprom_data fallback_sprom;
|
@ -0,0 +1,49 @@ |
||||
From e55892aac9d5508a000647ca66f0e678e02be3bb Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 17:26:50 +0100
|
||||
Subject: [PATCH 5/6] MIPS: BCM63XX: calculate labels for DT registered
|
||||
controllers
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/gpio.c | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/mips/bcm63xx/gpio.c b/arch/mips/bcm63xx/gpio.c
|
||||
index 70cd05b..cf0b819 100644
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
+#include "boards/board_common.h"
|
||||
+
|
||||
/* for registering lookups; make them large enough to hold OF names */
|
||||
static char *gpio_chip_labels[] = {
|
||||
"xxxxxxxx.gpio-controller",
|
||||
@@ -49,9 +51,17 @@ static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
|
||||
pdata.base = id * 32;
|
||||
pdata.ngpio = ngpio;
|
||||
|
||||
- sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
- platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
- &pdata, sizeof(pdata));
|
||||
+ if (board_of_device_present("gpio0")) {
|
||||
+ unsigned long base = res[0].start;
|
||||
+
|
||||
+ if (base < 0xf0000000U)
|
||||
+ base = CPHYSADDR(base);
|
||||
+ sprintf(gpio_chip_labels[id], "%lx.gpio-controller", base);
|
||||
+ } else {
|
||||
+ sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res,
|
||||
+ 2, &pdata, sizeof(pdata));
|
||||
+ }
|
||||
}
|
||||
|
||||
int __init bcm63xx_gpio_init(void)
|
||||
--
|
||||
1.7.10.4
|
||||
|
@ -0,0 +1,34 @@ |
||||
From 6759a62f28bb1995afe6562c0adfbbb6e8540933 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 22 Feb 2015 12:57:58 +0100
|
||||
Subject: [PATCH 6/6] gpio: gpio-bcm63xx: use alias id for base calculation
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
drivers/gpio/gpio-bcm63xx.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/gpio/gpio-bcm63xx.c
|
||||
+++ b/drivers/gpio/gpio-bcm63xx.c
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
+#define BCM63XX_GPIOS_PER_BANK 32
|
||||
+
|
||||
static int bcm63xx_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -73,8 +75,12 @@ static int bcm63xx_gpio_probe(struct pla
|
||||
platform_set_drvdata(pdev, bgc);
|
||||
|
||||
if (dev->of_node) {
|
||||
+ int id = of_alias_get_id(dev->of_node, "gpio");
|
||||
u32 ngpios;
|
||||
|
||||
+ if (id >= 0)
|
||||
+ bgc->gc.base = id * BCM63XX_GPIOS_PER_BANK;
|
||||
+
|
||||
if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
|
||||
bgc->gc.ngpio = ngpios;
|
||||
|
@ -0,0 +1,161 @@ |
||||
From dbe94a8daaa63ef81b7414f2a17bca8e36dd6daa Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Fri, 20 Feb 2015 19:55:32 +0100
|
||||
Subject: [PATCH 1/6] gpio: add a simple GPIO driver for bcm63xx
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
drivers/gpio/Kconfig | 8 +++
|
||||
drivers/gpio/Makefile | 1 +
|
||||
drivers/gpio/gpio-bcm63xx.c | 117 +++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 126 insertions(+)
|
||||
create mode 100644 drivers/gpio/gpio-bcm63xx.c
|
||||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -892,6 +892,14 @@ config GPIO_BCM_KONA
|
||||
help
|
||||
Turn on GPIO support for Broadcom "Kona" chips.
|
||||
|
||||
+config GPIO_BCM63XX
|
||||
+ bool "Broadcom BCM63XX GPIO"
|
||||
+ depends on MIPS || COMPILE_TEST
|
||||
+ select GPIO_GENERIC
|
||||
+ help
|
||||
+ Turn on GPIO support for Broadcom BCM63XX xDSL chips.
|
||||
+
|
||||
+
|
||||
comment "USB GPIO expanders:"
|
||||
|
||||
config GPIO_VIPERBOARD
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -19,6 +19,7 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp55
|
||||
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
||||
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
|
||||
+obj-$(CONFIG_GPIO_BCM63XX) += gpio-bcm63xx.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-bcm63xx.c
|
||||
@@ -0,0 +1,117 @@
|
||||
+/*
|
||||
+ * Driver for BCM63XX memory-mapped GPIO controllers, based on
|
||||
+ * Generic driver for memory-mapped GPIO controllers.
|
||||
+ *
|
||||
+ * Copyright 2008 MontaVista Software, Inc.
|
||||
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
|
||||
+ * Copyright 2015 Jonas Gorski <jogo@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/bug.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/ioport.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/basic_mmio_gpio.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+
|
||||
+static int bcm63xx_gpio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct resource *dat_r, *dirout_r;
|
||||
+ void __iomem *dat;
|
||||
+ void __iomem *dirout;
|
||||
+ unsigned long sz;
|
||||
+ int err;
|
||||
+ struct bgpio_chip *bgc;
|
||||
+ struct bgpio_pdata *pdata = dev_get_platdata(dev);
|
||||
+
|
||||
+ dat_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ dirout_r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
+ if (!dat_r || !dirout_r)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (resource_size(dat_r) != resource_size(dirout_r))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ sz = resource_size(dat_r);
|
||||
+
|
||||
+ dat = devm_ioremap_resource(dev, dat_r);
|
||||
+ if (IS_ERR(dat))
|
||||
+ return PTR_ERR(dat);
|
||||
+
|
||||
+ dirout = devm_ioremap_resource(dev, dirout_r);
|
||||
+ if (IS_ERR(dirout))
|
||||
+ return PTR_ERR(dirout);
|
||||
+
|
||||
+ bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
|
||||
+ if (!bgc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ err = bgpio_init(bgc, dev, sz, dat, NULL, NULL, dirout, NULL,
|
||||
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, bgc);
|
||||
+
|
||||
+ if (dev->of_node) {
|
||||
+ u32 ngpios;
|
||||
+
|
||||
+ if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
|
||||
+ bgc->gc.ngpio = ngpios;
|
||||
+
|
||||
+ } else if (pdata) {
|
||||
+ bgc->gc.base = pdata->base;
|
||||
+ if (pdata->ngpio > 0)
|
||||
+ bgc->gc.ngpio = pdata->ngpio;
|
||||
+ }
|
||||
+
|
||||
+ return gpiochip_add(&bgc->gc);
|
||||
+}
|
||||
+
|
||||
+static int bcm63xx_gpio_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct bgpio_chip *bgc = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ return bgpio_remove(bgc);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_OF
|
||||
+static struct of_device_id bcm63xx_gpio_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm6345-gpio" },
|
||||
+ { },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver bcm63xx_gpio_driver = {
|
||||
+ .probe = bcm63xx_gpio_probe,
|
||||
+ .remove = bcm63xx_gpio_remove,
|
||||
+ .driver = {
|
||||
+ .name = "bcm63xx-gpio",
|
||||
+ .of_match_table = of_match_ptr(bcm63xx_gpio_of_match),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(bcm63xx_gpio_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Driver for BCM63XX memory-mapped GPIO controllers");
|
||||
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,216 @@ |
||||
From cc99dca188bb63ba390008e2f7fa62d0300233e0 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Fri, 20 Feb 2015 23:58:54 +0100
|
||||
Subject: [PATCH 2/6] MIPS: BCM63XX: switch to new gpio driver
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_common.c | 2 +
|
||||
arch/mips/bcm63xx/gpio.c | 147 +++++++------------------------
|
||||
arch/mips/bcm63xx/prom.c | 3 -
|
||||
3 files changed, 33 insertions(+), 119 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -204,6 +204,8 @@ int __init board_register_devices(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ bcm63xx_gpio_init();
|
||||
+
|
||||
if (board.has_uart0)
|
||||
bcm63xx_uart_register(0);
|
||||
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -5,147 +5,62 @@
|
||||
*
|
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
|
||||
* Copyright (C) 2008-2011 Florian Fainelli <florian@openwrt.org>
|
||||
+ * Copyright (C) Jonas Gorski <jogo@openwrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
-#include <linux/module.h>
|
||||
-#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/basic_mmio_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
-#include <bcm63xx_io.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
-static u32 gpio_out_low_reg;
|
||||
-
|
||||
-static void bcm63xx_gpio_out_low_reg_init(void)
|
||||
+static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
|
||||
{
|
||||
- switch (bcm63xx_get_cpu_id()) {
|
||||
- case BCM6345_CPU_ID:
|
||||
- gpio_out_low_reg = GPIO_DATA_LO_REG_6345;
|
||||
- break;
|
||||
- default:
|
||||
- gpio_out_low_reg = GPIO_DATA_LO_REG;
|
||||
- break;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
|
||||
-static u32 gpio_out_low, gpio_out_high;
|
||||
+ struct resource res[2];
|
||||
+ struct bgpio_pdata pdata;
|
||||
|
||||
-static void bcm63xx_gpio_set(struct gpio_chip *chip,
|
||||
- unsigned gpio, int val)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
- u32 *v;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
-
|
||||
- if (gpio < 32) {
|
||||
- reg = gpio_out_low_reg;
|
||||
- mask = 1 << gpio;
|
||||
- v = &gpio_out_low;
|
||||
- } else {
|
||||
- reg = GPIO_DATA_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- v = &gpio_out_high;
|
||||
- }
|
||||
-
|
||||
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
- if (val)
|
||||
- *v |= mask;
|
||||
- else
|
||||
- *v &= ~mask;
|
||||
- bcm_gpio_writel(*v, reg);
|
||||
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
-}
|
||||
+ memset(res, 0, sizeof(res));
|
||||
+ memset(&pdata, 0, sizeof(pdata));
|
||||
|
||||
-static int bcm63xx_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
+ res[0].flags = IORESOURCE_MEM;
|
||||
+ res[0].start = bcm63xx_regset_address(RSET_GPIO);
|
||||
+ res[0].start += data;
|
||||
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
+ res[0].end = res[0].start + 3;
|
||||
|
||||
- if (gpio < 32) {
|
||||
- reg = gpio_out_low_reg;
|
||||
- mask = 1 << gpio;
|
||||
- } else {
|
||||
- reg = GPIO_DATA_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- }
|
||||
+ res[1].flags = IORESOURCE_MEM;
|
||||
+ res[1].start = bcm63xx_regset_address(RSET_GPIO);
|
||||
+ res[1].start += dir;
|
||||
|
||||
- return !!(bcm_gpio_readl(reg) & mask);
|
||||
-}
|
||||
+ res[1].end = res[1].start + 3;
|
||||
|
||||
-static int bcm63xx_gpio_set_direction(struct gpio_chip *chip,
|
||||
- unsigned gpio, int dir)
|
||||
-{
|
||||
- u32 reg;
|
||||
- u32 mask;
|
||||
- u32 tmp;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- if (gpio >= chip->ngpio)
|
||||
- BUG();
|
||||
-
|
||||
- if (gpio < 32) {
|
||||
- reg = GPIO_CTL_LO_REG;
|
||||
- mask = 1 << gpio;
|
||||
- } else {
|
||||
- reg = GPIO_CTL_HI_REG;
|
||||
- mask = 1 << (gpio - 32);
|
||||
- }
|
||||
-
|
||||
- spin_lock_irqsave(&bcm63xx_gpio_lock, flags);
|
||||
- tmp = bcm_gpio_readl(reg);
|
||||
- if (dir == BCM63XX_GPIO_DIR_IN)
|
||||
- tmp &= ~mask;
|
||||
- else
|
||||
- tmp |= mask;
|
||||
- bcm_gpio_writel(tmp, reg);
|
||||
- spin_unlock_irqrestore(&bcm63xx_gpio_lock, flags);
|
||||
+ pdata.base = id * 32;
|
||||
+ pdata.ngpio = ngpio;
|
||||
|
||||
- return 0;
|
||||
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
+ &pdata, sizeof(pdata));
|
||||
}
|
||||
|
||||
-static int bcm63xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
+int __init bcm63xx_gpio_init(void)
|
||||
{
|
||||
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_IN);
|
||||
-}
|
||||
+ int ngpio = bcm63xx_gpio_count();
|
||||
+ int data_low_reg;
|
||||
|
||||
-static int bcm63xx_gpio_direction_output(struct gpio_chip *chip,
|
||||
- unsigned gpio, int value)
|
||||
-{
|
||||
- bcm63xx_gpio_set(chip, gpio, value);
|
||||
- return bcm63xx_gpio_set_direction(chip, gpio, BCM63XX_GPIO_DIR_OUT);
|
||||
-}
|
||||
+ if (BCMCPU_IS_6345())
|
||||
+ data_low_reg = GPIO_DATA_LO_REG_6345;
|
||||
+ else
|
||||
+ data_low_reg = GPIO_DATA_LO_REG;
|
||||
|
||||
+ bcm63xx_gpio_init_one(0, data_low_reg, GPIO_CTL_LO_REG, min(ngpio, 32));
|
||||
|
||||
-static struct gpio_chip bcm63xx_gpio_chip = {
|
||||
- .label = "bcm63xx-gpio",
|
||||
- .direction_input = bcm63xx_gpio_direction_input,
|
||||
- .direction_output = bcm63xx_gpio_direction_output,
|
||||
- .get = bcm63xx_gpio_get,
|
||||
- .set = bcm63xx_gpio_set,
|
||||
- .base = 0,
|
||||
-};
|
||||
+ if (ngpio <= 32)
|
||||
+ return 0;
|
||||
|
||||
-int __init bcm63xx_gpio_init(void)
|
||||
-{
|
||||
- bcm63xx_gpio_out_low_reg_init();
|
||||
+ bcm63xx_gpio_init_one(1, GPIO_DATA_HI_REG, GPIO_CTL_HI_REG, ngpio - 32);
|
||||
|
||||
- gpio_out_low = bcm_gpio_readl(gpio_out_low_reg);
|
||||
- if (!BCMCPU_IS_6345())
|
||||
- gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG);
|
||||
- bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
|
||||
- pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
|
||||
+ return 0;
|
||||
|
||||
- return gpiochip_add(&bcm63xx_gpio_chip);
|
||||
}
|
||||
--- a/arch/mips/bcm63xx/prom.c
|
||||
+++ b/arch/mips/bcm63xx/prom.c
|
||||
@@ -54,9 +54,6 @@ void __init prom_init(void)
|
||||
reg &= ~mask;
|
||||
bcm_perf_writel(reg, PERF_CKCTL_REG);
|
||||
|
||||
- /* register gpiochip */
|
||||
- bcm63xx_gpio_init();
|
||||
-
|
||||
/* detect and setup flash access */
|
||||
bcm63xx_flash_detect();
|
||||
|
@ -0,0 +1,46 @@ |
||||
From ec905f2ea78ec40602a685ede31c5e4f9893d196 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 16:35:07 +0100
|
||||
Subject: [PATCH 3/6] net: bcm63xx_enet: use named gpio for ephy reset gpio
|
||||
|
||||
Allow using a named optional gpio for ephy reset gpio registration.
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/if_vlan.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include "bcm63xx_enet.h"
|
||||
@@ -2848,10 +2849,15 @@ static int bcm_enet_shared_probe(struct
|
||||
{
|
||||
struct resource *res;
|
||||
void __iomem *p[3];
|
||||
+ struct gpio_desc *ephy_reset;
|
||||
unsigned int i;
|
||||
|
||||
memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base));
|
||||
|
||||
+ ephy_reset = devm_gpiod_get_optional(&pdev->dev, "ephy-reset");
|
||||
+ if (IS_ERR(ephy_reset))
|
||||
+ return PTR_ERR(ephy_reset);
|
||||
+
|
||||
for (i = 0; i < 3; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
p[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
@@ -2861,6 +2867,9 @@ static int bcm_enet_shared_probe(struct
|
||||
|
||||
memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base));
|
||||
|
||||
+ if (ephy_reset)
|
||||
+ gpiod_direction_output(ephy_reset, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,138 @@ |
||||
From d13bdf92ec885105cf107183f8464c40e5f3b93b Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 17:21:59 +0100
|
||||
Subject: [PATCH 4/6] MIPS: BCM63XX: register lookup for ephy-reset gpio
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
|
||||
arch/mips/bcm63xx/boards/board_common.c | 7 +++--
|
||||
arch/mips/bcm63xx/gpio.c | 32 ++++++++++++++++++++
|
||||
arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 ++
|
||||
.../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 5 +--
|
||||
5 files changed, 42 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
|
||||
@@ -59,7 +59,7 @@ static struct board_info __initdata boar
|
||||
},
|
||||
|
||||
.ephy_reset_gpio = 36,
|
||||
- .ephy_reset_gpio_flags = GPIOF_INIT_HIGH,
|
||||
+ .ephy_reset_gpio_flags = GPIO_ACTIVE_LOW,
|
||||
};
|
||||
#endif
|
||||
|
||||
--- a/arch/mips/bcm63xx/boards/board_common.c
|
||||
+++ b/arch/mips/bcm63xx/boards/board_common.c
|
||||
@@ -278,9 +278,10 @@ int __init board_register_devices(void)
|
||||
platform_device_register(&bcm63xx_gpio_leds);
|
||||
}
|
||||
|
||||
- if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags)
|
||||
- gpio_request_one(board.ephy_reset_gpio,
|
||||
- board.ephy_reset_gpio_flags, "ephy-reset");
|
||||
+ if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) {
|
||||
+ bcm63xx_gpio_ephy_reset(board.ephy_reset_gpio,
|
||||
+ board.ephy_reset_gpio_flags);
|
||||
+ }
|
||||
|
||||
/* count number of BUTTONs defined by this device */
|
||||
while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -8,15 +8,24 @@
|
||||
* Copyright (C) Jonas Gorski <jogo@openwrt.org>
|
||||
*/
|
||||
|
||||
+#include <asm/addrspace.h>
|
||||
+
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/basic_mmio_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
+#include <linux/gpio/machine.h>
|
||||
|
||||
#include <bcm63xx_cpu.h>
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
+/* for registering lookups; make them large enough to hold OF names */
|
||||
+static char *gpio_chip_labels[] = {
|
||||
+ "xxxxxxxx.gpio-controller",
|
||||
+ "xxxxxxxx.gpio-controller",
|
||||
+};
|
||||
+
|
||||
static void __init bcm63xx_gpio_init_one(int id, int dir, int data, int ngpio)
|
||||
{
|
||||
struct resource res[2];
|
||||
@@ -40,6 +49,7 @@ static void __init bcm63xx_gpio_init_one
|
||||
pdata.base = id * 32;
|
||||
pdata.ngpio = ngpio;
|
||||
|
||||
+ sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
&pdata, sizeof(pdata));
|
||||
}
|
||||
@@ -64,3 +74,25 @@ int __init bcm63xx_gpio_init(void)
|
||||
return 0;
|
||||
|
||||
}
|
||||
+
|
||||
+static struct gpiod_lookup_table ephy_reset = {
|
||||
+ .dev_id = "bcm63xx_enet_shared.0",
|
||||
+ .table = {
|
||||
+ { /* filled at runtime */ },
|
||||
+ { },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+
|
||||
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags)
|
||||
+{
|
||||
+ if (ephy_reset.table[0].chip_label)
|
||||
+ return;
|
||||
+
|
||||
+ ephy_reset.table[0].chip_label = gpio_chip_labels[hw_gpio / 32];
|
||||
+ ephy_reset.table[0].chip_hwnum = hw_gpio % 32;
|
||||
+ ephy_reset.table[0].con_id = "ephy-reset";
|
||||
+ ephy_reset.table[0].flags = flags;
|
||||
+
|
||||
+ gpiod_add_lookup_table(&ephy_reset);
|
||||
+}
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
|
||||
@@ -2,9 +2,11 @@
|
||||
#define BCM63XX_GPIO_H
|
||||
|
||||
#include <linux/init.h>
|
||||
+#include <linux/gpio/machine.h>
|
||||
#include <bcm63xx_cpu.h>
|
||||
|
||||
int __init bcm63xx_gpio_init(void);
|
||||
+void bcm63xx_gpio_ephy_reset(int hw_gpio, enum gpio_lookup_flags flags);
|
||||
|
||||
static inline unsigned long bcm63xx_gpio_count(void)
|
||||
{
|
||||
--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
|
||||
+++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
+#include <linux/gpio/machine.h>
|
||||
#include <linux/leds.h>
|
||||
#include <bcm63xx_dev_enet.h>
|
||||
#include <bcm63xx_dev_usb_usbd.h>
|
||||
@@ -58,8 +59,8 @@ struct board_info {
|
||||
/* External PHY reset GPIO */
|
||||
unsigned int ephy_reset_gpio;
|
||||
|
||||
- /* External PHY reset GPIO flags from gpio.h */
|
||||
- unsigned long ephy_reset_gpio_flags;
|
||||
+ /* External PHY reset GPIO flags from gpio/machine.h */
|
||||
+ enum gpio_lookup_flags ephy_reset_gpio_flags;
|
||||
|
||||
/* fallback sprom config */
|
||||
struct fallback_sprom_data fallback_sprom;
|
@ -0,0 +1,44 @@ |
||||
From e55892aac9d5508a000647ca66f0e678e02be3bb Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sat, 21 Feb 2015 17:26:50 +0100
|
||||
Subject: [PATCH 5/6] MIPS: BCM63XX: calculate labels for DT registered
|
||||
controllers
|
||||
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
arch/mips/bcm63xx/gpio.c | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm63xx/gpio.c
|
||||
+++ b/arch/mips/bcm63xx/gpio.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <bcm63xx_gpio.h>
|
||||
#include <bcm63xx_regs.h>
|
||||
|
||||
+#include "boards/board_common.h"
|
||||
+
|
||||
/* for registering lookups; make them large enough to hold OF names */
|
||||
static char *gpio_chip_labels[] = {
|
||||
"xxxxxxxx.gpio-controller",
|
||||
@@ -49,9 +51,17 @@ static void __init bcm63xx_gpio_init_one
|
||||
pdata.base = id * 32;
|
||||
pdata.ngpio = ngpio;
|
||||
|
||||
- sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
- platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res, 2,
|
||||
- &pdata, sizeof(pdata));
|
||||
+ if (board_of_device_present("gpio0")) {
|
||||
+ unsigned long base = res[0].start;
|
||||
+
|
||||
+ if (base < 0xf0000000U)
|
||||
+ base = CPHYSADDR(base);
|
||||
+ sprintf(gpio_chip_labels[id], "%lx.gpio-controller", base);
|
||||
+ } else {
|
||||
+ sprintf(gpio_chip_labels[id], "bcm63xx-gpio.%d", id);
|
||||
+ platform_device_register_resndata(NULL, "bcm63xx-gpio", id, res,
|
||||
+ 2, &pdata, sizeof(pdata));
|
||||
+ }
|
||||
}
|
||||
|
||||
int __init bcm63xx_gpio_init(void)
|
@ -0,0 +1,34 @@ |
||||
From 6759a62f28bb1995afe6562c0adfbbb6e8540933 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jogo@openwrt.org>
|
||||
Date: Sun, 22 Feb 2015 12:57:58 +0100
|
||||
Subject: [PATCH 6/6] gpio: gpio-bcm63xx: use alias id for base calculation
|
||||
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
---
|
||||
drivers/gpio/gpio-bcm63xx.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/gpio/gpio-bcm63xx.c
|
||||
+++ b/drivers/gpio/gpio-bcm63xx.c
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
+#define BCM63XX_GPIOS_PER_BANK 32
|
||||
+
|
||||
static int bcm63xx_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -73,8 +75,12 @@ static int bcm63xx_gpio_probe(struct pla
|
||||
platform_set_drvdata(pdev, bgc);
|
||||
|
||||
if (dev->of_node) {
|
||||
+ int id = of_alias_get_id(dev->of_node, "gpio");
|
||||
u32 ngpios;
|
||||
|
||||
+ if (id >= 0)
|
||||
+ bgc->gc.base = id * BCM63XX_GPIOS_PER_BANK;
|
||||
+
|
||||
if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
|
||||
bgc->gc.ngpio = ngpios;
|
||||
|
Loading…
Reference in new issue