xref: /openbmc/linux/drivers/gpio/gpio-ath79.c (revision b4e97a61)
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 static void ath79_gpio_set_value(struct gpio_chip *chip,
28 				unsigned gpio, int value)
29 {
30 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
31 
32 	if (value)
33 		__raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET);
34 	else
35 		__raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR);
36 }
37 
38 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
39 {
40 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
41 
42 	return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
43 }
44 
45 static int ath79_gpio_direction_input(struct gpio_chip *chip,
46 				       unsigned offset)
47 {
48 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
49 	unsigned long flags;
50 
51 	spin_lock_irqsave(&ctrl->lock, flags);
52 
53 	__raw_writel(
54 		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
55 		ctrl->base + AR71XX_GPIO_REG_OE);
56 
57 	spin_unlock_irqrestore(&ctrl->lock, flags);
58 
59 	return 0;
60 }
61 
62 static int ath79_gpio_direction_output(struct gpio_chip *chip,
63 					unsigned offset, int value)
64 {
65 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
66 	unsigned long flags;
67 
68 	spin_lock_irqsave(&ctrl->lock, flags);
69 
70 	if (value)
71 		__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
72 	else
73 		__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
74 
75 	__raw_writel(
76 		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
77 		ctrl->base + AR71XX_GPIO_REG_OE);
78 
79 	spin_unlock_irqrestore(&ctrl->lock, flags);
80 
81 	return 0;
82 }
83 
84 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
85 {
86 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
87 	unsigned long flags;
88 
89 	spin_lock_irqsave(&ctrl->lock, flags);
90 
91 	__raw_writel(
92 		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
93 		ctrl->base + AR71XX_GPIO_REG_OE);
94 
95 	spin_unlock_irqrestore(&ctrl->lock, flags);
96 
97 	return 0;
98 }
99 
100 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
101 					int value)
102 {
103 	struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip);
104 	unsigned long flags;
105 
106 	spin_lock_irqsave(&ctrl->lock, flags);
107 
108 	if (value)
109 		__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
110 	else
111 		__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
112 
113 	__raw_writel(
114 		__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
115 		ctrl->base + AR71XX_GPIO_REG_OE);
116 
117 	spin_unlock_irqrestore(&ctrl->lock, flags);
118 
119 	return 0;
120 }
121 
122 static const struct gpio_chip ath79_gpio_chip = {
123 	.label			= "ath79",
124 	.get			= ath79_gpio_get_value,
125 	.set			= ath79_gpio_set_value,
126 	.direction_input	= ath79_gpio_direction_input,
127 	.direction_output	= ath79_gpio_direction_output,
128 	.base			= 0,
129 };
130 
131 static const struct of_device_id ath79_gpio_of_match[] = {
132 	{ .compatible = "qca,ar7100-gpio" },
133 	{ .compatible = "qca,ar9340-gpio" },
134 	{},
135 };
136 
137 static int ath79_gpio_probe(struct platform_device *pdev)
138 {
139 	struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
140 	struct device_node *np = pdev->dev.of_node;
141 	struct ath79_gpio_ctrl *ctrl;
142 	struct resource *res;
143 	u32 ath79_gpio_count;
144 	bool oe_inverted;
145 	int err;
146 
147 	ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
148 	if (!ctrl)
149 		return -ENOMEM;
150 
151 	if (np) {
152 		err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
153 		if (err) {
154 			dev_err(&pdev->dev, "ngpios property is not valid\n");
155 			return err;
156 		}
157 		if (ath79_gpio_count >= 32) {
158 			dev_err(&pdev->dev, "ngpios must be less than 32\n");
159 			return -EINVAL;
160 		}
161 		oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio");
162 	} else if (pdata) {
163 		ath79_gpio_count = pdata->ngpios;
164 		oe_inverted = pdata->oe_inverted;
165 	} else {
166 		dev_err(&pdev->dev, "No DT node or platform data found\n");
167 		return -EINVAL;
168 	}
169 
170 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
171 	ctrl->base = devm_ioremap_nocache(
172 		&pdev->dev, res->start, resource_size(res));
173 	if (!ctrl->base)
174 		return -ENOMEM;
175 
176 	spin_lock_init(&ctrl->lock);
177 	memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip));
178 	ctrl->chip.parent = &pdev->dev;
179 	ctrl->chip.ngpio = ath79_gpio_count;
180 	if (oe_inverted) {
181 		ctrl->chip.direction_input = ar934x_gpio_direction_input;
182 		ctrl->chip.direction_output = ar934x_gpio_direction_output;
183 	}
184 
185 	err = gpiochip_add_data(&ctrl->chip, ctrl);
186 	if (err) {
187 		dev_err(&pdev->dev,
188 			"cannot add AR71xx GPIO chip, error=%d", err);
189 		return err;
190 	}
191 
192 	return 0;
193 }
194 
195 static struct platform_driver ath79_gpio_driver = {
196 	.driver = {
197 		.name = "ath79-gpio",
198 		.of_match_table	= ath79_gpio_of_match,
199 	},
200 	.probe = ath79_gpio_probe,
201 };
202 
203 module_platform_driver(ath79_gpio_driver);
204