diff options
author | Florian Fainelli <florian@openwrt.org> | 2010-01-03 15:16:51 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-02-27 06:53:16 -0500 |
commit | 5f3c909881d5deebb9a3ddc836a15937e76daefc (patch) | |
tree | 5306ae518c1da71bdba1814e49e75ad7cd6c2736 /arch | |
parent | 69b427cd23b6f637763bf49e3e166c1236313f69 (diff) |
MIPS: AR7: Implement gpiolib
This patch implements gpiolib for the AR7 SoC.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
To: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/816/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 2 | ||||
-rw-r--r-- | arch/mips/ar7/gpio.c | 113 | ||||
-rw-r--r-- | arch/mips/ar7/platform.c | 1 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-ar7/gpio.h | 86 |
4 files changed, 108 insertions, 94 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 874167153880..db0a85355be7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -41,7 +41,7 @@ config AR7 | |||
41 | select SYS_SUPPORTS_32BIT_KERNEL | 41 | select SYS_SUPPORTS_32BIT_KERNEL |
42 | select SYS_SUPPORTS_LITTLE_ENDIAN | 42 | select SYS_SUPPORTS_LITTLE_ENDIAN |
43 | select SYS_SUPPORTS_ZBOOT_UART16550 | 43 | select SYS_SUPPORTS_ZBOOT_UART16550 |
44 | select GENERIC_GPIO | 44 | select ARCH_REQUIRE_GPIOLIB |
45 | select GCD | 45 | select GCD |
46 | select VLYNQ | 46 | select VLYNQ |
47 | help | 47 | help |
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c index 74e14a3dbf4a..0e9f4e13f427 100644 --- a/arch/mips/ar7/gpio.c +++ b/arch/mips/ar7/gpio.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> | 2 | * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> |
3 | * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> | 3 | * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> |
4 | * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -18,31 +19,113 @@ | |||
18 | */ | 19 | */ |
19 | 20 | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/gpio.h> | ||
21 | 23 | ||
22 | #include <asm/mach-ar7/gpio.h> | 24 | #include <asm/mach-ar7/gpio.h> |
23 | 25 | ||
24 | static const char *ar7_gpio_list[AR7_GPIO_MAX]; | 26 | struct ar7_gpio_chip { |
27 | void __iomem *regs; | ||
28 | struct gpio_chip chip; | ||
29 | }; | ||
25 | 30 | ||
26 | int gpio_request(unsigned gpio, const char *label) | 31 | static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio) |
27 | { | 32 | { |
28 | if (gpio >= AR7_GPIO_MAX) | 33 | struct ar7_gpio_chip *gpch = |
29 | return -EINVAL; | 34 | container_of(chip, struct ar7_gpio_chip, chip); |
35 | void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT; | ||
30 | 36 | ||
31 | if (ar7_gpio_list[gpio]) | 37 | return readl(gpio_in) & (1 << gpio); |
32 | return -EBUSY; | 38 | } |
39 | |||
40 | static void ar7_gpio_set_value(struct gpio_chip *chip, | ||
41 | unsigned gpio, int value) | ||
42 | { | ||
43 | struct ar7_gpio_chip *gpch = | ||
44 | container_of(chip, struct ar7_gpio_chip, chip); | ||
45 | void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT; | ||
46 | unsigned tmp; | ||
47 | |||
48 | tmp = readl(gpio_out) & ~(1 << gpio); | ||
49 | if (value) | ||
50 | tmp |= 1 << gpio; | ||
51 | writel(tmp, gpio_out); | ||
52 | } | ||
53 | |||
54 | static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | ||
55 | { | ||
56 | struct ar7_gpio_chip *gpch = | ||
57 | container_of(chip, struct ar7_gpio_chip, chip); | ||
58 | void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR; | ||
33 | 59 | ||
34 | if (label) | 60 | writel(readl(gpio_dir) | (1 << gpio), gpio_dir); |
35 | ar7_gpio_list[gpio] = label; | ||
36 | else | ||
37 | ar7_gpio_list[gpio] = "busy"; | ||
38 | 61 | ||
39 | return 0; | 62 | return 0; |
40 | } | 63 | } |
41 | EXPORT_SYMBOL(gpio_request); | ||
42 | 64 | ||
43 | void gpio_free(unsigned gpio) | 65 | static int ar7_gpio_direction_output(struct gpio_chip *chip, |
66 | unsigned gpio, int value) | ||
44 | { | 67 | { |
45 | BUG_ON(!ar7_gpio_list[gpio]); | 68 | struct ar7_gpio_chip *gpch = |
46 | ar7_gpio_list[gpio] = NULL; | 69 | container_of(chip, struct ar7_gpio_chip, chip); |
70 | void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR; | ||
71 | |||
72 | ar7_gpio_set_value(chip, gpio, value); | ||
73 | writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static struct ar7_gpio_chip ar7_gpio_chip = { | ||
79 | .chip = { | ||
80 | .label = "ar7-gpio", | ||
81 | .direction_input = ar7_gpio_direction_input, | ||
82 | .direction_output = ar7_gpio_direction_output, | ||
83 | .set = ar7_gpio_set_value, | ||
84 | .get = ar7_gpio_get_value, | ||
85 | .base = 0, | ||
86 | .ngpio = AR7_GPIO_MAX, | ||
87 | } | ||
88 | }; | ||
89 | |||
90 | int ar7_gpio_enable(unsigned gpio) | ||
91 | { | ||
92 | void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE; | ||
93 | |||
94 | writel(readl(gpio_en) | (1 << gpio), gpio_en); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | EXPORT_SYMBOL(ar7_gpio_enable); | ||
99 | |||
100 | int ar7_gpio_disable(unsigned gpio) | ||
101 | { | ||
102 | void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE; | ||
103 | |||
104 | writel(readl(gpio_en) & ~(1 << gpio), gpio_en); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | EXPORT_SYMBOL(ar7_gpio_disable); | ||
109 | |||
110 | static int __init ar7_gpio_init(void) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | ar7_gpio_chip.regs = ioremap_nocache(AR7_REGS_GPIO, | ||
115 | AR7_REGS_GPIO + 0x10); | ||
116 | |||
117 | if (!ar7_gpio_chip.regs) { | ||
118 | printk(KERN_ERR "ar7-gpio: failed to ioremap regs\n"); | ||
119 | return -ENOMEM; | ||
120 | } | ||
121 | |||
122 | ret = gpiochip_add(&ar7_gpio_chip.chip); | ||
123 | if (ret) { | ||
124 | printk(KERN_ERR "ar7-gpio: failed to add gpiochip\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | printk(KERN_INFO "ar7-gpio: registered %d GPIOs\n", | ||
128 | ar7_gpio_chip.chip.ngpio); | ||
129 | return ret; | ||
47 | } | 130 | } |
48 | EXPORT_SYMBOL(gpio_free); | 131 | arch_initcall(ar7_gpio_init); |
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index f70a10a8cc96..5a3fa9407710 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/etherdevice.h> | 34 | #include <linux/etherdevice.h> |
35 | #include <linux/phy.h> | 35 | #include <linux/phy.h> |
36 | #include <linux/phy_fixed.h> | 36 | #include <linux/phy_fixed.h> |
37 | #include <linux/gpio.h> | ||
37 | 38 | ||
38 | #include <asm/addrspace.h> | 39 | #include <asm/addrspace.h> |
39 | #include <asm/mach-ar7/ar7.h> | 40 | #include <asm/mach-ar7/ar7.h> |
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h index cbe9c4f126df..73f9b162c970 100644 --- a/arch/mips/include/asm/mach-ar7/gpio.h +++ b/arch/mips/include/asm/mach-ar7/gpio.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> | 2 | * Copyright (C) 2007-2009 Florian Fainelli <florian@openwrt.org> |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
@@ -22,88 +22,18 @@ | |||
22 | #include <asm/mach-ar7/ar7.h> | 22 | #include <asm/mach-ar7/ar7.h> |
23 | 23 | ||
24 | #define AR7_GPIO_MAX 32 | 24 | #define AR7_GPIO_MAX 32 |
25 | #define NR_BUILTIN_GPIO AR7_GPIO_MAX | ||
25 | 26 | ||
26 | extern int gpio_request(unsigned gpio, const char *label); | 27 | #define gpio_to_irq(gpio) NULL |
27 | extern void gpio_free(unsigned gpio); | ||
28 | 28 | ||
29 | /* Common GPIO layer */ | 29 | #define gpio_get_value __gpio_get_value |
30 | static inline int gpio_get_value(unsigned gpio) | 30 | #define gpio_set_value __gpio_set_value |
31 | { | ||
32 | void __iomem *gpio_in = | ||
33 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT); | ||
34 | 31 | ||
35 | return readl(gpio_in) & (1 << gpio); | 32 | #define gpio_cansleep __gpio_cansleep |
36 | } | ||
37 | |||
38 | static inline void gpio_set_value(unsigned gpio, int value) | ||
39 | { | ||
40 | void __iomem *gpio_out = | ||
41 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT); | ||
42 | unsigned tmp; | ||
43 | |||
44 | tmp = readl(gpio_out) & ~(1 << gpio); | ||
45 | if (value) | ||
46 | tmp |= 1 << gpio; | ||
47 | writel(tmp, gpio_out); | ||
48 | } | ||
49 | |||
50 | static inline int gpio_direction_input(unsigned gpio) | ||
51 | { | ||
52 | void __iomem *gpio_dir = | ||
53 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); | ||
54 | |||
55 | if (gpio >= AR7_GPIO_MAX) | ||
56 | return -EINVAL; | ||
57 | |||
58 | writel(readl(gpio_dir) | (1 << gpio), gpio_dir); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static inline int gpio_direction_output(unsigned gpio, int value) | ||
64 | { | ||
65 | void __iomem *gpio_dir = | ||
66 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); | ||
67 | |||
68 | if (gpio >= AR7_GPIO_MAX) | ||
69 | return -EINVAL; | ||
70 | |||
71 | gpio_set_value(gpio, value); | ||
72 | writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static inline int gpio_to_irq(unsigned gpio) | ||
78 | { | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | |||
82 | static inline int irq_to_gpio(unsigned irq) | ||
83 | { | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | 33 | ||
87 | /* Board specific GPIO functions */ | 34 | /* Board specific GPIO functions */ |
88 | static inline int ar7_gpio_enable(unsigned gpio) | 35 | int ar7_gpio_enable(unsigned gpio); |
89 | { | 36 | int ar7_gpio_disable(unsigned gpio); |
90 | void __iomem *gpio_en = | ||
91 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); | ||
92 | |||
93 | writel(readl(gpio_en) | (1 << gpio), gpio_en); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static inline int ar7_gpio_disable(unsigned gpio) | ||
99 | { | ||
100 | void __iomem *gpio_en = | ||
101 | (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); | ||
102 | |||
103 | writel(readl(gpio_en) & ~(1 << gpio), gpio_en); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | 37 | ||
108 | #include <asm-generic/gpio.h> | 38 | #include <asm-generic/gpio.h> |
109 | 39 | ||