2 * ADM5120 generic GPIO API support via GPIOLIB
4 * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
12 #include <linux/init.h>
13 #include <linux/types.h>
14 #include <linux/module.h>
15 #include <linux/irq.h>
16 #include <linux/delay.h>
17 #include <linux/platform_device.h>
19 #include <linux/gpio.h>
21 #include <asm/addrspace.h>
23 #include <asm/mach-adm5120/adm5120_defs.h>
24 #include <asm/mach-adm5120/adm5120_info.h>
25 #include <asm/mach-adm5120/adm5120_switch.h>
27 #define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r)
30 void __iomem
*reg
; /* register address */
31 u8 iv_shift
; /* shift amount for input bit */
32 u8 mode_shift
; /* shift amount for mode bits */
35 #define GPIO1_DESC(p, l) { \
36 .reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \
37 .iv_shift = LED0_IV_SHIFT + (l), \
38 .mode_shift = (l) * 4 \
41 static struct gpio1_desc gpio1_table
[15] = {
42 GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2),
43 GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2),
44 GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2),
45 GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2),
46 GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2)
49 static u32 gpio_conf2
;
51 int adm5120_gpio_to_irq(unsigned gpio
)
56 case ADM5120_GPIO_PIN2
:
57 ret
= ADM5120_IRQ_GPIO2
;
59 case ADM5120_GPIO_PIN4
:
60 ret
= ADM5120_IRQ_GPIO4
;
69 EXPORT_SYMBOL(adm5120_gpio_to_irq
);
71 int adm5120_irq_to_gpio(unsigned irq
)
76 case ADM5120_IRQ_GPIO2
:
77 ret
= ADM5120_GPIO_PIN2
;
79 case ADM5120_IRQ_GPIO4
:
80 ret
= ADM5120_GPIO_PIN4
;
89 EXPORT_SYMBOL(adm5120_irq_to_gpio
);
92 * Helpers for GPIO lines in GPIO_CONF0 register
94 #define PIN_IM(p) ((1 << GPIO_CONF0_IM_SHIFT) << p)
95 #define PIN_IV(p) ((1 << GPIO_CONF0_IV_SHIFT) << p)
96 #define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p)
97 #define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p)
99 int __adm5120_gpio0_get_value(unsigned offset
)
104 reg
= GPIO_REG(SWITCH_REG_GPIO_CONF0
);
106 t
= __raw_readl(reg
);
107 if ((t
& PIN_IM(offset
)) != 0)
114 EXPORT_SYMBOL(__adm5120_gpio0_get_value
);
116 void __adm5120_gpio0_set_value(unsigned offset
, int value
)
121 reg
= GPIO_REG(SWITCH_REG_GPIO_CONF0
);
123 t
= __raw_readl(reg
);
125 t
&= ~(PIN_OV(offset
));
129 __raw_writel(t
, reg
);
131 EXPORT_SYMBOL(__adm5120_gpio0_set_value
);
133 static int adm5120_gpio0_get_value(struct gpio_chip
*chip
, unsigned offset
)
135 return __adm5120_gpio0_get_value(offset
);
138 static void adm5120_gpio0_set_value(struct gpio_chip
*chip
,
139 unsigned offset
, int value
)
141 __adm5120_gpio0_set_value(offset
, value
);
144 static int adm5120_gpio0_direction_input(struct gpio_chip
*chip
,
150 reg
= GPIO_REG(SWITCH_REG_GPIO_CONF0
);
152 t
= __raw_readl(reg
);
153 t
&= ~(PIN_OE(offset
));
155 __raw_writel(t
, reg
);
160 static int adm5120_gpio0_direction_output(struct gpio_chip
*chip
,
161 unsigned offset
, int value
)
166 reg
= GPIO_REG(SWITCH_REG_GPIO_CONF0
);
168 t
= __raw_readl(reg
);
169 t
&= ~(PIN_IM(offset
) | PIN_OV(offset
));
175 __raw_writel(t
, reg
);
180 static struct gpio_chip adm5120_gpio0_chip
= {
181 .label
= "adm5120 gpio0",
182 .get
= adm5120_gpio0_get_value
,
183 .set
= adm5120_gpio0_set_value
,
184 .direction_input
= adm5120_gpio0_direction_input
,
185 .direction_output
= adm5120_gpio0_direction_output
,
186 .base
= ADM5120_GPIO_PIN0
,
187 .ngpio
= ADM5120_GPIO_PIN7
- ADM5120_GPIO_PIN0
+ 1,
190 int __adm5120_gpio1_get_value(unsigned offset
)
195 reg
= gpio1_table
[offset
].reg
;
197 t
= __raw_readl(reg
);
198 m
= (t
>> gpio1_table
[offset
].mode_shift
) & LED_MODE_MASK
;
199 if (m
== LED_MODE_INPUT
)
200 return (t
>> gpio1_table
[offset
].iv_shift
) & 1;
202 if (m
== LED_MODE_OUT_LOW
)
207 EXPORT_SYMBOL(__adm5120_gpio1_get_value
);
209 void __adm5120_gpio1_set_value(unsigned offset
, int value
)
214 reg
= gpio1_table
[offset
].reg
;
215 s
= gpio1_table
[offset
].mode_shift
;
217 t
= __raw_readl(reg
);
218 t
&= ~(LED_MODE_MASK
<< s
);
221 case ADM5120_GPIO_LOW
:
222 t
|= (LED_MODE_OUT_LOW
<< s
);
224 case ADM5120_GPIO_FLASH
:
225 case ADM5120_GPIO_LINK
:
226 case ADM5120_GPIO_SPEED
:
227 case ADM5120_GPIO_DUPLEX
:
228 case ADM5120_GPIO_ACT
:
229 case ADM5120_GPIO_COLL
:
230 case ADM5120_GPIO_LINK_ACT
:
231 case ADM5120_GPIO_DUPLEX_COLL
:
232 case ADM5120_GPIO_10M_ACT
:
233 case ADM5120_GPIO_100M_ACT
:
234 t
|= ((value
& LED_MODE_MASK
) << s
);
237 t
|= (LED_MODE_OUT_HIGH
<< s
);
241 __raw_writel(t
, reg
);
243 EXPORT_SYMBOL(__adm5120_gpio1_set_value
);
245 static int adm5120_gpio1_get_value(struct gpio_chip
*chip
, unsigned offset
)
247 return __adm5120_gpio1_get_value(offset
);
250 static void adm5120_gpio1_set_value(struct gpio_chip
*chip
,
251 unsigned offset
, int value
)
253 __adm5120_gpio1_set_value(offset
, value
);
256 static int adm5120_gpio1_direction_input(struct gpio_chip
*chip
,
262 reg
= gpio1_table
[offset
].reg
;
263 t
= __raw_readl(reg
);
264 t
&= ~(LED_MODE_MASK
<< gpio1_table
[offset
].mode_shift
);
265 __raw_writel(t
, reg
);
270 static int adm5120_gpio1_direction_output(struct gpio_chip
*chip
,
271 unsigned offset
, int value
)
273 __adm5120_gpio1_set_value(offset
, value
);
277 static struct gpio_chip adm5120_gpio1_chip
= {
278 .label
= "adm5120 gpio1",
279 .get
= adm5120_gpio1_get_value
,
280 .set
= adm5120_gpio1_set_value
,
281 .direction_input
= adm5120_gpio1_direction_input
,
282 .direction_output
= adm5120_gpio1_direction_output
,
283 .base
= ADM5120_GPIO_P0L0
,
284 .ngpio
= ADM5120_GPIO_P4L2
- ADM5120_GPIO_P0L0
+ 1,
287 void __init
adm5120_gpio_csx0_enable(void)
289 gpio_conf2
|= GPIO_CONF2_CSX0
;
290 SW_WRITE_REG(SWITCH_REG_GPIO_CONF2
, gpio_conf2
);
292 gpio_request(ADM5120_GPIO_PIN1
, "CSX0");
295 void __init
adm5120_gpio_csx1_enable(void)
297 gpio_conf2
|= GPIO_CONF2_CSX1
;
298 SW_WRITE_REG(SWITCH_REG_GPIO_CONF2
, gpio_conf2
);
300 gpio_request(ADM5120_GPIO_PIN3
, "CSX1");
303 void __init
adm5120_gpio_ew_enable(void)
305 gpio_conf2
|= GPIO_CONF2_EW
;
306 SW_WRITE_REG(SWITCH_REG_GPIO_CONF2
, gpio_conf2
);
308 gpio_request(ADM5120_GPIO_PIN0
, "EW");
311 void __init
adm5120_gpio_init(void)
315 SW_WRITE_REG(SWITCH_REG_GPIO_CONF2
, gpio_conf2
);
317 if (adm5120_package_pqfp())
318 adm5120_gpio0_chip
.ngpio
= 4;
320 err
= gpiochip_add(&adm5120_gpio0_chip
);
322 panic("cannot add ADM5120 GPIO0 chip, error=%d", err
);
324 err
= gpiochip_add(&adm5120_gpio1_chip
);
326 panic("cannot add ADM5120 GPIO1 chip, error=%d", err
);