aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2012-05-16 16:22:47 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-05-21 09:31:53 -0400
commit54f30066178d4ff2da8e62427975736131cdbf96 (patch)
tree24fc3d6d47f1747f1f311a2dead6c50c1b2310cb /drivers/gpio
parenta36e9a1c5fa67cdc965fe011f1d04317adb35953 (diff)
GPIO: MIPS: lantiq: convert gpio-stp-xway to OF
Implements OF support and add code to load custom properties from the DT. The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a peripheral controller used to drive external shift register cascades. At most 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem to drive the 2 LSBs of the cascade automatically. Newer socs are also able to automatically drive some pins via the internal PHYs. The driver currently only supports output functionality. Patches for the input feature found on newer generations of the soc will be provided in a later series. Signed-off-by: John Crispin <blogic@openwrt.org> Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Acked-by: Grant Likely <grant.likely@secretlab.ca> Patchwork: https://patchwork.linux-mips.org/patch/3839/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-stp-xway.c333
1 files changed, 241 insertions, 92 deletions
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index d674f1be237d..e35096bf3cfb 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -3,150 +3,299 @@
3 * under the terms of the GNU General Public License version 2 as published 3 * under the terms of the GNU General Public License version 2 as published
4 * by the Free Software Foundation. 4 * by the Free Software Foundation.
5 * 5 *
6 * Copyright (C) 2007 John Crispin <blogic@openwrt.org> 6 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
7 * 7 *
8 */ 8 */
9 9
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/export.h> 12#include <linux/module.h>
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/platform_device.h> 14#include <linux/of_platform.h>
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <linux/io.h>
17#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/io.h>
18#include <linux/of_gpio.h>
19#include <linux/clk.h>
20#include <linux/err.h>
18 21
19#include <lantiq_soc.h> 22#include <lantiq_soc.h>
20 23
21#define LTQ_STP_CON0 0x00 24/*
22#define LTQ_STP_CON1 0x04 25 * The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a
23#define LTQ_STP_CPU0 0x08 26 * peripheral controller used to drive external shift register cascades. At most
24#define LTQ_STP_CPU1 0x0C 27 * 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem
25#define LTQ_STP_AR 0x10 28 * to drive the 2 LSBs of the cascade automatically.
26 29 */
27#define LTQ_STP_CON_SWU (1 << 31) 30
28#define LTQ_STP_2HZ 0 31/* control register 0 */
29#define LTQ_STP_4HZ (1 << 23) 32#define XWAY_STP_CON0 0x00
30#define LTQ_STP_8HZ (2 << 23) 33/* control register 1 */
31#define LTQ_STP_10HZ (3 << 23) 34#define XWAY_STP_CON1 0x04
32#define LTQ_STP_SPEED_MASK (0xf << 23) 35/* data register 0 */
33#define LTQ_STP_UPD_FPI (1 << 31) 36#define XWAY_STP_CPU0 0x08
34#define LTQ_STP_UPD_MASK (3 << 30) 37/* data register 1 */
35#define LTQ_STP_ADSL_SRC (3 << 24) 38#define XWAY_STP_CPU1 0x0C
36 39/* access register */
37#define LTQ_STP_GROUP0 (1 << 0) 40#define XWAY_STP_AR 0x10
38 41
39#define LTQ_STP_RISING 0 42/* software or hardware update select bit */
40#define LTQ_STP_FALLING (1 << 26) 43#define XWAY_STP_CON_SWU BIT(31)
41#define LTQ_STP_EDGE_MASK (1 << 26) 44
42 45/* automatic update rates */
43#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg) 46#define XWAY_STP_2HZ 0
44#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg) 47#define XWAY_STP_4HZ BIT(23)
45#define ltq_stp_w32_mask(clear, set, reg) \ 48#define XWAY_STP_8HZ BIT(24)
46 ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \ 49#define XWAY_STP_10HZ (BIT(24) | BIT(23))
47 ltq_stp_membase + (reg)) 50#define XWAY_STP_SPEED_MASK (0xf << 23)
48 51
49static int ltq_stp_shadow = 0xffff; 52/* clock source for automatic update */
50static void __iomem *ltq_stp_membase; 53#define XWAY_STP_UPD_FPI BIT(31)
51 54#define XWAY_STP_UPD_MASK (BIT(31) | BIT(30))
52static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value) 55
56/* let the adsl core drive the 2 LSBs */
57#define XWAY_STP_ADSL_SHIFT 24
58#define XWAY_STP_ADSL_MASK 0x3
59
60/* 2 groups of 3 bits can be driven by the phys */
61#define XWAY_STP_PHY_MASK 0x3
62#define XWAY_STP_PHY1_SHIFT 27
63#define XWAY_STP_PHY2_SHIFT 15
64
65/* STP has 3 groups of 8 bits */
66#define XWAY_STP_GROUP0 BIT(0)
67#define XWAY_STP_GROUP1 BIT(1)
68#define XWAY_STP_GROUP2 BIT(2)
69#define XWAY_STP_GROUP_MASK (0x7)
70
71/* Edge configuration bits */
72#define XWAY_STP_FALLING BIT(26)
73#define XWAY_STP_EDGE_MASK BIT(26)
74
75#define xway_stp_r32(m, reg) __raw_readl(m + reg)
76#define xway_stp_w32(m, val, reg) __raw_writel(val, m + reg)
77#define xway_stp_w32_mask(m, clear, set, reg) \
78 ltq_w32((ltq_r32(m + reg) & ~(clear)) | (set), \
79 m + reg)
80
81struct xway_stp {
82 struct gpio_chip gc;
83 void __iomem *virt;
84 u32 edge; /* rising or falling edge triggered shift register */
85 u16 shadow; /* shadow the shift registers state */
86 u8 groups; /* we can drive 1-3 groups of 8bit each */
87 u8 dsl; /* the 2 LSBs can be driven by the dsl core */
88 u8 phy1; /* 3 bits can be driven by phy1 */
89 u8 phy2; /* 3 bits can be driven by phy2 */
90 u8 reserved; /* mask out the hw driven bits in gpio_request */
91};
92
93/**
94 * xway_stp_set() - gpio_chip->set - set gpios.
95 * @gc: Pointer to gpio_chip device structure.
96 * @gpio: GPIO signal number.
97 * @val: Value to be written to specified signal.
98 *
99 * Set the shadow value and call ltq_ebu_apply.
100 */
101static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val)
53{ 102{
54 if (value) 103 struct xway_stp *chip =
55 ltq_stp_shadow |= (1 << offset); 104 container_of(gc, struct xway_stp, gc);
105
106 if (val)
107 chip->shadow |= BIT(gpio);
56 else 108 else
57 ltq_stp_shadow &= ~(1 << offset); 109 chip->shadow &= ~BIT(gpio);
58 ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0); 110 xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0);
111 xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0);
59} 112}
60 113
61static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset, 114/**
62 int value) 115 * xway_stp_dir_out() - gpio_chip->dir_out - set gpio direction.
116 * @gc: Pointer to gpio_chip device structure.
117 * @gpio: GPIO signal number.
118 * @val: Value to be written to specified signal.
119 *
120 * Same as xway_stp_set, always returns 0.
121 */
122static int xway_stp_dir_out(struct gpio_chip *gc, unsigned gpio, int val)
63{ 123{
64 ltq_stp_set(chip, offset, value); 124 xway_stp_set(gc, gpio, val);
65 125
66 return 0; 126 return 0;
67} 127}
68 128
69static struct gpio_chip ltq_stp_chip = { 129/**
70 .label = "ltq_stp", 130 * xway_stp_request() - gpio_chip->request
71 .direction_output = ltq_stp_direction_output, 131 * @gc: Pointer to gpio_chip device structure.
72 .set = ltq_stp_set, 132 * @gpio: GPIO signal number.
73 .base = 48, 133 *
74 .ngpio = 24, 134 * We mask out the HW driven pins
75 .can_sleep = 1, 135 */
76 .owner = THIS_MODULE, 136static int xway_stp_request(struct gpio_chip *gc, unsigned gpio)
77}; 137{
138 struct xway_stp *chip =
139 container_of(gc, struct xway_stp, gc);
140
141 if ((gpio < 8) && (chip->reserved & BIT(gpio))) {
142 dev_err(gc->dev, "GPIO %d is driven by hardware\n", gpio);
143 return -ENODEV;
144 }
78 145
79static int ltq_stp_hw_init(void) 146 return 0;
147}
148
149/**
150 * xway_stp_hw_init() - Configure the STP unit and enable the clock gate
151 * @virt: pointer to the remapped register range
152 */
153static int xway_stp_hw_init(struct xway_stp *chip)
80{ 154{
81 /* sane defaults */ 155 /* sane defaults */
82 ltq_stp_w32(0, LTQ_STP_AR); 156 xway_stp_w32(chip->virt, 0, XWAY_STP_AR);
83 ltq_stp_w32(0, LTQ_STP_CPU0); 157 xway_stp_w32(chip->virt, 0, XWAY_STP_CPU0);
84 ltq_stp_w32(0, LTQ_STP_CPU1); 158 xway_stp_w32(chip->virt, 0, XWAY_STP_CPU1);
85 ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0); 159 xway_stp_w32(chip->virt, XWAY_STP_CON_SWU, XWAY_STP_CON0);
86 ltq_stp_w32(0, LTQ_STP_CON1); 160 xway_stp_w32(chip->virt, 0, XWAY_STP_CON1);
87 161
88 /* rising or falling edge */ 162 /* apply edge trigger settings for the shift register */
89 ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0); 163 xway_stp_w32_mask(chip->virt, XWAY_STP_EDGE_MASK,
164 chip->edge, XWAY_STP_CON0);
90 165
91 /* per default stp 15-0 are set */ 166 /* apply led group settings */
92 ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1); 167 xway_stp_w32_mask(chip->virt, XWAY_STP_GROUP_MASK,
168 chip->groups, XWAY_STP_CON1);
93 169
94 /* stp are update periodically by the FPI bus */ 170 /* tell the hardware which pins are controlled by the dsl modem */
95 ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1); 171 xway_stp_w32_mask(chip->virt,
172 XWAY_STP_ADSL_MASK << XWAY_STP_ADSL_SHIFT,
173 chip->dsl << XWAY_STP_ADSL_SHIFT,
174 XWAY_STP_CON0);
96 175
97 /* set stp update speed */ 176 /* tell the hardware which pins are controlled by the phys */
98 ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1); 177 xway_stp_w32_mask(chip->virt,
178 XWAY_STP_PHY_MASK << XWAY_STP_PHY1_SHIFT,
179 chip->phy1 << XWAY_STP_PHY1_SHIFT,
180 XWAY_STP_CON0);
181 xway_stp_w32_mask(chip->virt,
182 XWAY_STP_PHY_MASK << XWAY_STP_PHY2_SHIFT,
183 chip->phy2 << XWAY_STP_PHY2_SHIFT,
184 XWAY_STP_CON1);
99 185
100 /* tell the hardware that pin (led) 0 and 1 are controlled 186 /* mask out the hw driven bits in gpio_request */
101 * by the dsl arc 187 chip->reserved = (chip->phy2 << 5) | (chip->phy1 << 2) | chip->dsl;
188
189 /*
190 * if we have pins that are driven by hw, we need to tell the stp what
191 * clock to use as a timer.
102 */ 192 */
103 ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0); 193 if (chip->reserved)
194 xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK,
195 XWAY_STP_UPD_FPI, XWAY_STP_CON1);
104 196
105 ltq_pmu_enable(PMU_LED);
106 return 0; 197 return 0;
107} 198}
108 199
109static int __devinit ltq_stp_probe(struct platform_device *pdev) 200static int __devinit xway_stp_probe(struct platform_device *pdev)
110{ 201{
111 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 202 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203 const __be32 *shadow, *groups, *dsl, *phy;
204 struct xway_stp *chip;
205 struct clk *clk;
112 int ret = 0; 206 int ret = 0;
113 207
114 if (!res)
115 return -ENOENT;
116 res = devm_request_mem_region(&pdev->dev, res->start,
117 resource_size(res), dev_name(&pdev->dev));
118 if (!res) { 208 if (!res) {
119 dev_err(&pdev->dev, "failed to request STP memory\n"); 209 dev_err(&pdev->dev, "failed to request STP resource\n");
120 return -EBUSY; 210 return -ENOENT;
121 } 211 }
122 ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start, 212
123 resource_size(res)); 213 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
124 if (!ltq_stp_membase) { 214 if (!chip)
215 return -ENOMEM;
216
217 chip->virt = devm_request_and_ioremap(&pdev->dev, res);
218 if (!chip->virt) {
125 dev_err(&pdev->dev, "failed to remap STP memory\n"); 219 dev_err(&pdev->dev, "failed to remap STP memory\n");
126 return -ENOMEM; 220 return -ENOMEM;
127 } 221 }
128 ret = gpiochip_add(&ltq_stp_chip); 222 chip->gc.dev = &pdev->dev;
223 chip->gc.label = "stp-xway";
224 chip->gc.direction_output = xway_stp_dir_out;
225 chip->gc.set = xway_stp_set;
226 chip->gc.request = xway_stp_request;
227 chip->gc.base = -1;
228 chip->gc.owner = THIS_MODULE;
229
230 /* store the shadow value if one was passed by the devicetree */
231 shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL);
232 if (shadow)
233 chip->shadow = be32_to_cpu(*shadow);
234
235 /* find out which gpio groups should be enabled */
236 groups = of_get_property(pdev->dev.of_node, "lantiq,groups", NULL);
237 if (groups)
238 chip->groups = be32_to_cpu(*groups) & XWAY_STP_GROUP_MASK;
239 else
240 chip->groups = XWAY_STP_GROUP0;
241 chip->gc.ngpio = fls(chip->groups) * 8;
242
243 /* find out which gpios are controlled by the dsl core */
244 dsl = of_get_property(pdev->dev.of_node, "lantiq,dsl", NULL);
245 if (dsl)
246 chip->dsl = be32_to_cpu(*dsl) & XWAY_STP_ADSL_MASK;
247
248 /* find out which gpios are controlled by the phys */
249 if (of_machine_is_compatible("lantiq,ar9") ||
250 of_machine_is_compatible("lantiq,gr9") ||
251 of_machine_is_compatible("lantiq,vr9")) {
252 phy = of_get_property(pdev->dev.of_node, "lantiq,phy1", NULL);
253 if (phy)
254 chip->phy1 = be32_to_cpu(*phy) & XWAY_STP_PHY_MASK;
255 phy = of_get_property(pdev->dev.of_node, "lantiq,phy2", NULL);
256 if (phy)
257 chip->phy2 = be32_to_cpu(*phy) & XWAY_STP_PHY_MASK;
258 }
259
260 /* check which edge trigger we should use, default to a falling edge */
261 if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL))
262 chip->edge = XWAY_STP_FALLING;
263
264 clk = clk_get(&pdev->dev, NULL);
265 if (IS_ERR(clk)) {
266 dev_err(&pdev->dev, "Failed to get clock\n");
267 return PTR_ERR(clk);
268 }
269 clk_enable(clk);
270
271 ret = xway_stp_hw_init(chip);
129 if (!ret) 272 if (!ret)
130 ret = ltq_stp_hw_init(); 273 ret = gpiochip_add(&chip->gc);
274
275 if (!ret)
276 dev_info(&pdev->dev, "Init done\n");
131 277
132 return ret; 278 return ret;
133} 279}
134 280
135static struct platform_driver ltq_stp_driver = { 281static const struct of_device_id xway_stp_match[] = {
136 .probe = ltq_stp_probe, 282 { .compatible = "lantiq,gpio-stp-xway" },
283 {},
284};
285MODULE_DEVICE_TABLE(of, xway_stp_match);
286
287static struct platform_driver xway_stp_driver = {
288 .probe = xway_stp_probe,
137 .driver = { 289 .driver = {
138 .name = "ltq_stp", 290 .name = "gpio-stp-xway",
139 .owner = THIS_MODULE, 291 .owner = THIS_MODULE,
292 .of_match_table = xway_stp_match,
140 }, 293 },
141}; 294};
142 295
143int __init ltq_stp_init(void) 296int __init xway_stp_init(void)
144{ 297{
145 int ret = platform_driver_register(&ltq_stp_driver); 298 return platform_driver_register(&xway_stp_driver);
146
147 if (ret)
148 pr_info("ltq_stp: error registering platfom driver");
149 return ret;
150} 299}
151 300
152postcore_initcall(ltq_stp_init); 301subsys_initcall(xway_stp_init);