]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpio/gpio-ath79.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide
[karo-tx-linux.git] / drivers / gpio / gpio-ath79.c
1 /*
2  *  Atheros AR71XX/AR724X/AR913X GPIO API support
3  *
4  *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
6  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7  *
8  *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
9  *
10  *  This program is free software; you can redistribute it and/or modify it
11  *  under the terms of the GNU General Public License version 2 as published
12  *  by the Free Software Foundation.
13  */
14
15 #include <linux/gpio/driver.h>
16 #include <linux/platform_data/gpio-ath79.h>
17 #include <linux/of_device.h>
18
19 #include <asm/mach-ath79/ar71xx_regs.h>
20
21 struct ath79_gpio_ctrl {
22         struct gpio_chip chip;
23         void __iomem *base;
24         spinlock_t lock;
25 };
26
27 #define to_ath79_gpio_ctrl(c) container_of(c, struct ath79_gpio_ctrl, chip)
28
29 static void ath79_gpio_set_value(struct gpio_chip *chip,
30                                 unsigned gpio, int value)
31 {
32         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
33
34         if (value)
35                 __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET);
36         else
37                 __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR);
38 }
39
40 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
41 {
42         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
43
44         return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
45 }
46
47 static int ath79_gpio_direction_input(struct gpio_chip *chip,
48                                        unsigned offset)
49 {
50         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
51         unsigned long flags;
52
53         spin_lock_irqsave(&ctrl->lock, flags);
54
55         __raw_writel(
56                 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
57                 ctrl->base + AR71XX_GPIO_REG_OE);
58
59         spin_unlock_irqrestore(&ctrl->lock, flags);
60
61         return 0;
62 }
63
64 static int ath79_gpio_direction_output(struct gpio_chip *chip,
65                                         unsigned offset, int value)
66 {
67         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
68         unsigned long flags;
69
70         spin_lock_irqsave(&ctrl->lock, flags);
71
72         if (value)
73                 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
74         else
75                 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
76
77         __raw_writel(
78                 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
79                 ctrl->base + AR71XX_GPIO_REG_OE);
80
81         spin_unlock_irqrestore(&ctrl->lock, flags);
82
83         return 0;
84 }
85
86 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
87 {
88         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
89         unsigned long flags;
90
91         spin_lock_irqsave(&ctrl->lock, flags);
92
93         __raw_writel(
94                 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
95                 ctrl->base + AR71XX_GPIO_REG_OE);
96
97         spin_unlock_irqrestore(&ctrl->lock, flags);
98
99         return 0;
100 }
101
102 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
103                                         int value)
104 {
105         struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
106         unsigned long flags;
107
108         spin_lock_irqsave(&ctrl->lock, flags);
109
110         if (value)
111                 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
112         else
113                 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
114
115         __raw_writel(
116                 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset),
117                 ctrl->base + AR71XX_GPIO_REG_OE);
118
119         spin_unlock_irqrestore(&ctrl->lock, flags);
120
121         return 0;
122 }
123
124 static const struct gpio_chip ath79_gpio_chip = {
125         .label                  = "ath79",
126         .get                    = ath79_gpio_get_value,
127         .set                    = ath79_gpio_set_value,
128         .direction_input        = ath79_gpio_direction_input,
129         .direction_output       = ath79_gpio_direction_output,
130         .base                   = 0,
131 };
132
133 static const struct of_device_id ath79_gpio_of_match[] = {
134         { .compatible = "qca,ar7100-gpio" },
135         { .compatible = "qca,ar9340-gpio" },
136         {},
137 };
138
139 static int ath79_gpio_probe(struct platform_device *pdev)
140 {
141         struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
142         struct device_node *np = pdev->dev.of_node;
143         struct ath79_gpio_ctrl *ctrl;
144         struct resource *res;
145         u32 ath79_gpio_count;
146         bool oe_inverted;
147         int err;
148
149         ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
150         if (!ctrl)
151                 return -ENOMEM;
152
153         if (np) {
154                 err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
155                 if (err) {
156                         dev_err(&pdev->dev, "ngpios property is not valid\n");
157                         return err;
158                 }
159                 if (ath79_gpio_count >= 32) {
160                         dev_err(&pdev->dev, "ngpios must be less than 32\n");
161                         return -EINVAL;
162                 }
163                 oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
164         } else if (pdata) {
165                 ath79_gpio_count = pdata->ngpios;
166                 oe_inverted = pdata->oe_inverted;
167         } else {
168                 dev_err(&pdev->dev, "No DT node or platform data found\n");
169                 return -EINVAL;
170         }
171
172         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
173         ctrl->base = devm_ioremap_nocache(
174                 &pdev->dev, res->start, resource_size(res));
175         if (!ctrl->base)
176                 return -ENOMEM;
177
178         spin_lock_init(&ctrl->lock);
179         memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip));
180         ctrl->chip.dev = &pdev->dev;
181         ctrl->chip.ngpio = ath79_gpio_count;
182         if (oe_inverted) {
183                 ctrl->chip.direction_input = ar934x_gpio_direction_input;
184                 ctrl->chip.direction_output = ar934x_gpio_direction_output;
185         }
186
187         err = gpiochip_add(&ctrl->chip);
188         if (err) {
189                 dev_err(&pdev->dev,
190                         "cannot add AR71xx GPIO chip, error=%d", err);
191                 return err;
192         }
193
194         return 0;
195 }
196
197 static struct platform_driver ath79_gpio_driver = {
198         .driver = {
199                 .name = "ath79-gpio",
200                 .of_match_table = ath79_gpio_of_match,
201         },
202         .probe = ath79_gpio_probe,
203 };
204
205 module_platform_driver(ath79_gpio_driver);