From 5d23ae4a89f2da38a6b436417ec24c9c60b8a857 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Thu, 6 Dec 2012 22:41:04 +0000
Subject: [adm8668] add a gpiolib driver

Signed-off-by: Florian Fainelli <florian@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34564 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 target/linux/adm8668/config-3.3                    |   4 +
 .../linux/adm8668/files/arch/mips/adm8668/gpio.c   | 123 +++++++++++++++++++++
 .../arch/mips/include/asm/mach-adm8668/gpio.h      |  13 +++
 .../adm8668/patches-3.3/001-adm8668_arch.patch     |   5 +-
 4 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/adm8668/files/arch/mips/adm8668/gpio.c
 create mode 100644 target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h

(limited to 'target/linux')

diff --git a/target/linux/adm8668/config-3.3 b/target/linux/adm8668/config-3.3
index 169245d1cc..e63f14053c 100644
--- a/target/linux/adm8668/config-3.3
+++ b/target/linux/adm8668/config-3.3
@@ -2,6 +2,7 @@ CONFIG_ADM8668=y
 CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
 CONFIG_ARCH_DISCARD_MEMBLOCK=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_ARM_AMBA=y
 # CONFIG_ARM_SP805_WATCHDOG is not set
@@ -31,8 +32,11 @@ CONFIG_GENERIC_ATOMIC64=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_IRQ_SHOW=y
 CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_HARDWARE_WATCHPOINTS=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
diff --git a/target/linux/adm8668/files/arch/mips/adm8668/gpio.c b/target/linux/adm8668/files/arch/mips/adm8668/gpio.c
new file mode 100644
index 0000000000..fb39f7f588
--- /dev/null
+++ b/target/linux/adm8668/files/arch/mips/adm8668/gpio.c
@@ -0,0 +1,123 @@
+/*
+ * Infineon/ADMTek ADM8668 WildPass GPIO support
+ *
+ * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
+ *
+ * Licensed under the terms of GPLv2.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <adm8668.h>
+
+#define GPIO_MASK	0x3f
+
+#define GPIO_IN_OFS	0
+#define GPIO_OUT_OFS	6
+#define GPIO_OE_OFS	12
+
+struct adm8668_gpio_chip {
+	void __iomem	*base;
+	struct gpio_chip chip;
+};
+
+static int adm8668_gpio_dir_out(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct adm8668_gpio_chip *c =
+		container_of(chip, struct adm8668_gpio_chip, chip);
+	u32 mask;
+
+	/* clear input, set output enable and output value */
+	mask = __raw_readl(c->base);
+	mask &= ~(1 << offset);
+	mask |= (1 << (offset + GPIO_OE_OFS));
+	if (value)
+		mask |= (1 << (offset + GPIO_OUT_OFS));
+	else
+		mask &= ~(1 << (offset + GPIO_OUT_OFS));
+	__raw_writel(mask, c->base);
+
+	return 0;
+}
+
+static int adm8668_gpio_dir_in(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct adm8668_gpio_chip *c =
+		container_of(chip, struct adm8668_gpio_chip, chip);
+	u32 mask;
+
+	mask = __raw_readl(c->base);
+	mask &= ~(((1 << (offset + GPIO_OE_OFS)) | (1 << (offset + GPIO_OUT_OFS))));
+	mask |= (1 << offset);
+	__raw_writel(mask, c->base);
+
+	return 0;
+}
+
+static void adm8668_gpio_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct adm8668_gpio_chip *c =
+		container_of(chip, struct adm8668_gpio_chip, chip);
+	u32 mask;
+
+	mask = __raw_readl(c->base);
+	if (value)
+		mask |= (1 << (offset + GPIO_OUT_OFS));
+	else
+		mask &= ~(1 << (offset + GPIO_OUT_OFS));
+	__raw_writel(mask, c->base);
+}
+
+static int adm8668_gpio_get(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct adm8668_gpio_chip *c =
+		container_of(chip, struct adm8668_gpio_chip, chip);
+	u32 value;
+
+	value = __raw_readl(c->base) & GPIO_MASK;
+
+	return value & (1 << offset);
+}
+
+static struct adm8668_gpio_chip adm8668_gpio_cpu = {
+	.base = (void __iomem *)KSEG1ADDR(ADM8668_CONFIG_BASE + CRGPIO_REG),
+	.chip = {
+		.label			= "adm8668-cpu-gpio",
+		.direction_output	= adm8668_gpio_dir_out,
+		.direction_input	= adm8668_gpio_dir_in,
+		.set			= adm8668_gpio_set,
+		.get			= adm8668_gpio_get,
+		.ngpio			= 6,
+	},
+};
+
+static struct adm8668_gpio_chip adm8668_gpio_wlan = {
+	.base = (void __iomem *)KSEG1ADDR(ADM8668_WLAN_BASE + GPIO_REG),
+	.chip = {
+		.label			= "adm8668-wlan-gpio",
+		.direction_output	= adm8668_gpio_dir_out,
+		.direction_input	= adm8668_gpio_dir_in,
+		.set			= adm8668_gpio_set,
+		.get			= adm8668_gpio_get,
+		.ngpio			= 6,
+		.base			= 6,
+	},
+};
+
+static int __init adm8668_gpio_init(void)
+{
+	int ret;
+
+	ret = gpiochip_add(&adm8668_gpio_cpu.chip);
+	if (ret)
+		return ret;
+
+	return gpiochip_add(&adm8668_gpio_wlan.chip);
+}
+arch_initcall(adm8668_gpio_init);
diff --git a/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h b/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h
new file mode 100644
index 0000000000..b0473fc4b3
--- /dev/null
+++ b/target/linux/adm8668/files/arch/mips/include/asm/mach-adm8668/gpio.h
@@ -0,0 +1,13 @@
+#ifndef __ADM8668_GPIO_H__
+#define __ADM8668_GPIO_H__
+
+#define gpio_to_irq(gpio)       -1
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+
+#define gpio_cansleep __gpio_cansleep
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch b/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch
index 66be46c8d0..1d52bcf97d 100644
--- a/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch
+++ b/target/linux/adm8668/patches-3.3/001-adm8668_arch.patch
@@ -10,7 +10,7 @@
  include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -105,6 +105,25 @@ config BCM47XX
+@@ -105,6 +105,26 @@ config BCM47XX
  	help
  	 Support for BCM47XX based boards
  
@@ -29,6 +29,7 @@
 +	select DMA_NONCOHERENT
 +	select SWAP_IO_SPACE
 +	select SYS_HAS_EARLY_PRINTK
++	select ARCH_REQUIRE_GPIOLIB
 +	help
 +		ADM8668 board support by neutronscott
 +		Scott Nicholas <neutronscott@scottn.us>
@@ -36,7 +37,7 @@
  config BCM63XX
  	bool "Broadcom BCM63XX based boards"
  	select CEVT_R4K
-@@ -813,6 +832,7 @@ config NLM_XLP_BOARD
+@@ -813,6 +833,7 @@ config NLM_XLP_BOARD
  
  endchoice
  
-- 
cgit v1.2.3