diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-11-21 21:49:32 +0200 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-12-03 00:13:26 +0200 |
commit | 031e3104c03172a40bff338ef2f15cb220150c86 (patch) | |
tree | 52f7f9a017d22e26cb0819c241b3e2a26105fc90 | |
parent | de4cda674279365ee0a04cea646e49591b040938 (diff) |
Add Andrew's gpio patches. Closes #2.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
4 files changed, 292 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/gpio/rtl_gpio.c b/target/linux/realtek/files/drivers/gpio/rtl_gpio.c new file mode 100644 index 000000000..010f17f12 --- /dev/null +++ b/target/linux/realtek/files/drivers/gpio/rtl_gpio.c @@ -0,0 +1,228 @@ +/* + * RTL819X gpio driver + * + * Copyright 2012 Andrew 'Necromant' Andrianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * + * Please note, that this driver is VERY hacky due to f*cked up nature of + * realtek's kernel. Say thanks to code monkeys from realtek + * (see arch/rlx for emailsand names) and never hire any of them ;) + * This driver should be properly rewritten once 3.x kernels for rlx arrive + * Till then it's a placeholder for a proper driver. + * Current Issues: + * * No interrupt support whatsoever. + * * No proper probing & platform_device defs. + * * Many things hardcoded. Sorry + * + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/spinlock.h> +#include <asm/io.h> + +/* Register Offset Definitions */ +#define RTLGPIO_CNTRL (0) +#define RTLGPIO_DIR (2) +#define RTLGPIO_DATA (3) + +/* rlx missing sizes.h ? */ +#define SZ_4K 4096 + +#define RTL_MUX_ADDR 0xb8000040 + + +static int g_muxdummy; +static uint32_t g_mux_value = 0x340FFF; + +static int param_set_mux(const char *val, struct kernel_param *kp) +{ + volatile uint32_t* mux = (uint32_t*) RTL_MUX_ADDR; + if (!val) + return -EINVAL; + sscanf(val, "0x%x", &g_mux_value); + *mux = g_mux_value; + printk("rtl-gpio: setting mux to 0x%x\n", g_mux_value); + return 0; +} + +static int param_get_mux(char *buffer, struct kernel_param *kp) +{ + volatile uint32_t* mux = (uint32_t*) RTL_MUX_ADDR; + sprintf(buffer, "0x%x", *mux); + return strlen(buffer); +} + +#define param_check_mux(a,b) ;; + +module_param_named(mux, g_muxdummy, mux, S_IRUGO | S_IWUSR) + +struct rtl_gpio_chip { + struct gpio_chip chip; + uint32_t gpio_state; + uint32_t gpio_dir; + volatile uint32_t* regs; + spinlock_t lock; /* Lock used for synchronization */ +}; + +static inline struct rtl_gpio_chip *to_rtl_gpio_chip(struct gpio_chip *gc) +{ + return container_of(gc, struct rtl_gpio_chip, chip); +} + + +/* Dummy to make gpiolib happy */ +int gpio_to_irq(unsigned g) +{ + return 0; +} + +EXPORT_SYMBOL(gpio_to_irq); + +/** + * rtlgpio_get - Read the specified signal of the GPIO device. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * + * This function reads the specified signal of the GPIO device. It returns 0 if + * the signal clear, 1 if signal is set or negative value on error. + */ +static int rtlgpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct rtl_gpio_chip *rgc = to_rtl_gpio_chip(gc); + return (*(rgc->regs + RTLGPIO_DATA) >> gpio) & 1; +} + +/** + * rtlgpio_set - Write the specified signal of the GPIO device. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * This function writes the specified value in to the specified signal of the + * GPIO device. + */ +static void rtlgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + struct rtl_gpio_chip *rgc = to_rtl_gpio_chip(gc); + + spin_lock_irqsave(&rgc->lock, flags); + /* Write to GPIO signal and set its direction to output */ + if (val) + rgc->gpio_state |= 1 << gpio; + else + rgc->gpio_state &= ~(1 << gpio); + *(rgc->regs + RTLGPIO_DATA) = rgc->gpio_state; + spin_unlock_irqrestore(&rgc->lock, flags); +} + +/** + * rtlgpio_dir_in - Set the direction of the specified GPIO signal as input. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * + * This function sets the direction of specified GPIO signal as input. + * It returns 0 if direction of GPIO signals is set as input otherwise it + * returns negative error value. + */ +static int rtlgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + + unsigned long flags; + struct rtl_gpio_chip *rgc = to_rtl_gpio_chip(gc); + + spin_lock_irqsave(&rgc->lock, flags); + /* Set the GPIO bit in shadow register and set direction as input */ + rgc->gpio_dir &= ~(1 << gpio); + *(rgc->regs + RTLGPIO_DIR) = rgc->gpio_dir; + spin_unlock_irqrestore(&rgc->lock, flags); + return 0; +} + +/** + * rtlgpio_dir_out - Set the direction of the specified GPIO signal as output. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * This function sets the direction of specified GPIO signal as output. If all + * GPIO signals of GPIO chip is configured as input then it returns + * error otherwise it returns 0. + */ +static int rtlgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + struct rtl_gpio_chip *rgc = to_rtl_gpio_chip(gc); + spin_lock_irqsave(&rgc->lock, flags); + /* Set the GPIO bit in shadow register and set direction as input */ + rgc->gpio_dir |= (1 << gpio); + *(rgc->regs + RTLGPIO_DIR) = rgc->gpio_dir; + spin_unlock_irqrestore(&rgc->lock, flags); + return 0; +} + + +static struct rtl_gpio_chip rgpio; +static int __init rtlgpio_init(void) +{ +/* volatile uint32_t* regs = ioremap_nocache(0xb8003500, 32); + volatile uint32_t* mux = ioremap_nocache(0xB8000040, 4); +*/ + /* + * Something is definetely not right here. + * Theory says that ioremap is the way, practice says the opposite + * Must be some dark realtek's magic coming from arch/rlx + */ + + volatile uint32_t* regs = (uint32_t*) 0xb8003500; + volatile uint32_t* mux = (uint32_t*) 0xb8000040; + *mux = g_mux_value; + printk("rtl-gpio: Hacky Realtek 819x GPIO Driver (c) Andrew 'Necromant' Andrianov 2012\n"); + rgpio.chip.direction_input = rtlgpio_dir_in; + rgpio.chip.direction_output = rtlgpio_dir_out; + rgpio.chip.get = rtlgpio_get; + rgpio.chip.label = "rtl-gpio"; + rgpio.chip.set = rtlgpio_set; + rgpio.chip.base = 0; + rgpio.chip.ngpio = 32; + spin_lock_init(&rgpio.lock); + rgpio.regs = regs; + rgpio.gpio_state = *(rgpio.regs + RTLGPIO_DATA); + rgpio.gpio_dir = *(rgpio.regs + RTLGPIO_DIR); + printk("rtl-gpio: remaped io regs: 0x%p, mux: 0x%p\n", + regs, + mux); + printk("rtl-gpio: mux:0x%x\n", + *mux); + + printk("rtl-gpio: initial dir: 0x%x, value: 0x%x\n", + rgpio.gpio_state, + rgpio.gpio_dir); + gpiochip_add(&rgpio.chip); + return 0; +} + +/* Make sure we get initialized before anyone else tries to use us */ +subsys_initcall(rtlgpio_init); +/* No exit call at the moment as we cannot unregister of GPIO chips */ + + + +MODULE_AUTHOR("Andrew 'Necromant' Andrianov"); +MODULE_DESCRIPTION("Hacky RTL819x GPIO Driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/realtek/patches-2.6.30/304-add-rtlgpio.patch b/target/linux/realtek/patches-2.6.30/304-add-rtlgpio.patch new file mode 100644 index 000000000..45b62390b --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/304-add-rtlgpio.patch @@ -0,0 +1,28 @@ +--- a/drivers/gpio/Makefile 2012-11-05 14:07:42.074262520 +0400 ++++ b/drivers/gpio/Makefile 2012-11-05 14:08:18.327603410 +0400 +@@ -10,5 +10,6 @@ + obj-$(CONFIG_GPIO_PCA953X) += pca953x.o + obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o + obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o +-obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o ++obj-$(CONFIG_GPIO_RTL) += rtl_gpio.o + obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o ++ +--- a/drivers/gpio/Kconfig 2012-11-05 14:07:47.534263615 +0400 ++++ b/drivers/gpio/Kconfig 2012-11-05 14:07:58.770932541 +0400 +@@ -73,6 +73,15 @@ + help + Say yes here to support the Xilinx FPGA GPIO device + ++config GPIO_RTL ++ bool "Realtek RTL819x GPIO support" ++ help ++ Say yes here to support the Realtek GPIO found in ++ RTL819x boards. Please note, that this is a hacky ++ backport ++ ++ ++ + comment "I2C GPIO expanders:" + + config GPIO_MAX732X diff --git a/target/linux/realtek/patches-2.6.30/305-add-gpio-driver-switching.patch b/target/linux/realtek/patches-2.6.30/305-add-gpio-driver-switching.patch new file mode 100644 index 000000000..9dc6548b6 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/305-add-gpio-driver-switching.patch @@ -0,0 +1,25 @@ +--- linux-2.6.30.9.a/arch/rlx/Kconfig 2012-11-05 14:18:41.701066133 +0400 ++++ linux-2.6.30.9.b/arch/rlx/Kconfig 2012-11-05 14:16:50.864374834 +0400 +@@ -139,6 +139,22 @@ + config RTL_FLASH_MAPPING_ENABLE + bool "Enable Flash Mapping" + ++choice ++prompt "GPIO Driver to use" ++ ++config RTL_GPIO ++ bool "Use realtek's GPIO driver" ++ ++ ++config RTL_NGPIO ++ bool "Use Necromant's gpiolib driver (recommended)" ++ select GENERIC_GPIO ++ select ARCH_REQUIRE_GPIOLIB ++ select GPIO_RTL ++ default y ++ ++endchoice ++ + config POCKET_ROUTER_SUPPORT + bool "Pocket router support" + diff --git a/target/linux/realtek/patches-2.6.30/306-make-gpio-rtl-honor-switch.patch b/target/linux/realtek/patches-2.6.30/306-make-gpio-rtl-honor-switch.patch new file mode 100644 index 000000000..e0c259713 --- /dev/null +++ b/target/linux/realtek/patches-2.6.30/306-make-gpio-rtl-honor-switch.patch @@ -0,0 +1,11 @@ +--- a/drivers/char/Makefile 2012-11-05 14:22:46.404451333 +0400 ++++ b/drivers/char/Makefile 2012-11-05 14:23:57.307799712 +0400 +@@ -98,7 +98,7 @@ + obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o + obj-$(CONFIG_GPIO_TB0219) += tb0219.o + obj-$(CONFIG_TELCLOCK) += tlclk.o +-obj-$(CONFIG_RTL_819X) += rtl_gpio.o ++obj-$(CONFIG_RTL_GPIO) += rtl_gpio.o + obj-$(CONFIG_RTL_NFBI_MDIO) += rtl_mdio/ + + obj-$(CONFIG_MWAVE) += mwave/ |