fb39f7f588aa89262065adc522fa027351fbc858
[openwrt.git] / target / linux / adm8668 / files-3.14 / arch / mips / adm8668 / gpio.c
1 /*
2  * Infineon/ADMTek ADM8668 WildPass GPIO support
3  *
4  * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
5  *
6  * Licensed under the terms of GPLv2.
7  *
8  */
9 #include <linux/kernel.h>
10 #include <linux/gpio.h>
11 #include <linux/io.h>
12
13 #include <adm8668.h>
14
15 #define GPIO_MASK       0x3f
16
17 #define GPIO_IN_OFS     0
18 #define GPIO_OUT_OFS    6
19 #define GPIO_OE_OFS     12
20
21 struct adm8668_gpio_chip {
22         void __iomem    *base;
23         struct gpio_chip chip;
24 };
25
26 static int adm8668_gpio_dir_out(struct gpio_chip *chip,
27                                 unsigned offset, int value)
28 {
29         struct adm8668_gpio_chip *c =
30                 container_of(chip, struct adm8668_gpio_chip, chip);
31         u32 mask;
32
33         /* clear input, set output enable and output value */
34         mask = __raw_readl(c->base);
35         mask &= ~(1 << offset);
36         mask |= (1 << (offset + GPIO_OE_OFS));
37         if (value)
38                 mask |= (1 << (offset + GPIO_OUT_OFS));
39         else
40                 mask &= ~(1 << (offset + GPIO_OUT_OFS));
41         __raw_writel(mask, c->base);
42
43         return 0;
44 }
45
46 static int adm8668_gpio_dir_in(struct gpio_chip *chip,
47                                 unsigned offset)
48 {
49         struct adm8668_gpio_chip *c =
50                 container_of(chip, struct adm8668_gpio_chip, chip);
51         u32 mask;
52
53         mask = __raw_readl(c->base);
54         mask &= ~(((1 << (offset + GPIO_OE_OFS)) | (1 << (offset + GPIO_OUT_OFS))));
55         mask |= (1 << offset);
56         __raw_writel(mask, c->base);
57
58         return 0;
59 }
60
61 static void adm8668_gpio_set(struct gpio_chip *chip,
62                                 unsigned offset, int value)
63 {
64         struct adm8668_gpio_chip *c =
65                 container_of(chip, struct adm8668_gpio_chip, chip);
66         u32 mask;
67
68         mask = __raw_readl(c->base);
69         if (value)
70                 mask |= (1 << (offset + GPIO_OUT_OFS));
71         else
72                 mask &= ~(1 << (offset + GPIO_OUT_OFS));
73         __raw_writel(mask, c->base);
74 }
75
76 static int adm8668_gpio_get(struct gpio_chip *chip,
77                                 unsigned offset)
78 {
79         struct adm8668_gpio_chip *c =
80                 container_of(chip, struct adm8668_gpio_chip, chip);
81         u32 value;
82
83         value = __raw_readl(c->base) & GPIO_MASK;
84
85         return value & (1 << offset);
86 }
87
88 static struct adm8668_gpio_chip adm8668_gpio_cpu = {
89         .base = (void __iomem *)KSEG1ADDR(ADM8668_CONFIG_BASE + CRGPIO_REG),
90         .chip = {
91                 .label                  = "adm8668-cpu-gpio",
92                 .direction_output       = adm8668_gpio_dir_out,
93                 .direction_input        = adm8668_gpio_dir_in,
94                 .set                    = adm8668_gpio_set,
95                 .get                    = adm8668_gpio_get,
96                 .ngpio                  = 6,
97         },
98 };
99
100 static struct adm8668_gpio_chip adm8668_gpio_wlan = {
101         .base = (void __iomem *)KSEG1ADDR(ADM8668_WLAN_BASE + GPIO_REG),
102         .chip = {
103                 .label                  = "adm8668-wlan-gpio",
104                 .direction_output       = adm8668_gpio_dir_out,
105                 .direction_input        = adm8668_gpio_dir_in,
106                 .set                    = adm8668_gpio_set,
107                 .get                    = adm8668_gpio_get,
108                 .ngpio                  = 6,
109                 .base                   = 6,
110         },
111 };
112
113 static int __init adm8668_gpio_init(void)
114 {
115         int ret;
116
117         ret = gpiochip_add(&adm8668_gpio_cpu.chip);
118         if (ret)
119                 return ret;
120
121         return gpiochip_add(&adm8668_gpio_wlan.chip);
122 }
123 arch_initcall(adm8668_gpio_init);