OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001 |
2 | From: John Crispin <blogic@openwrt.org> |
||
3 | Date: Sun, 27 Jul 2014 09:34:05 +0100 |
||
4 | Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver |
||
5 | |||
6 | Signed-off-by: John Crispin <blogic@openwrt.org> |
||
7 | --- |
||
8 | arch/mips/Kconfig | 2 + |
||
9 | drivers/pinctrl/Kconfig | 5 + |
||
10 | drivers/pinctrl/Makefile | 1 + |
||
11 | drivers/pinctrl/pinctrl-rt2880.c | 474 ++++++++++++++++++++++++++++++++++++++ |
||
12 | 4 files changed, 482 insertions(+) |
||
13 | create mode 100644 drivers/pinctrl/pinctrl-rt2880.c |
||
14 | |||
15 | --- a/arch/mips/Kconfig |
||
16 | +++ b/arch/mips/Kconfig |
||
3 | office | 17 | @@ -628,6 +628,8 @@ config RALINK |
1 | office | 18 | select CLKDEV_LOOKUP |
19 | select ARCH_HAS_RESET_CONTROLLER |
||
20 | select RESET_CONTROLLER |
||
21 | + select PINCTRL |
||
22 | + select PINCTRL_RT2880 |
||
23 | |||
24 | config SGI_IP22 |
||
25 | bool "SGI IP22 (Indy/Indigo2)" |
||
26 | --- a/drivers/pinctrl/Kconfig |
||
27 | +++ b/drivers/pinctrl/Kconfig |
||
28 | @@ -143,6 +143,11 @@ config PINCTRL_LPC18XX |
||
29 | help |
||
30 | Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU). |
||
31 | |||
32 | +config PINCTRL_RT2880 |
||
33 | + bool |
||
34 | + depends on RALINK |
||
35 | + select PINMUX |
||
36 | + |
||
37 | config PINCTRL_FALCON |
||
38 | bool |
||
39 | depends on SOC_FALCON |
||
40 | --- a/drivers/pinctrl/Makefile |
||
41 | +++ b/drivers/pinctrl/Makefile |
||
42 | @@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl- |
||
43 | obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o |
||
44 | obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o |
||
45 | obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o |
||
46 | +obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o |
||
47 | obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o |
||
48 | obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o |
||
49 | obj-$(CONFIG_PINCTRL_SIRF) += sirf/ |
||
50 | --- /dev/null |
||
51 | +++ b/drivers/pinctrl/pinctrl-rt2880.c |
||
52 | @@ -0,0 +1,472 @@ |
||
53 | +/* |
||
54 | + * linux/drivers/pinctrl/pinctrl-rt2880.c |
||
55 | + * |
||
56 | + * This program is free software; you can redistribute it and/or modify |
||
57 | + * it under the terms of the GNU General Public License version 2 as |
||
58 | + * publishhed by the Free Software Foundation. |
||
59 | + * |
||
60 | + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> |
||
61 | + */ |
||
62 | + |
||
63 | +#include <linux/module.h> |
||
64 | +#include <linux/device.h> |
||
65 | +#include <linux/io.h> |
||
66 | +#include <linux/platform_device.h> |
||
67 | +#include <linux/slab.h> |
||
68 | +#include <linux/of.h> |
||
69 | +#include <linux/pinctrl/pinctrl.h> |
||
70 | +#include <linux/pinctrl/pinconf.h> |
||
71 | +#include <linux/pinctrl/pinmux.h> |
||
72 | +#include <linux/pinctrl/consumer.h> |
||
73 | +#include <linux/pinctrl/machine.h> |
||
74 | + |
||
75 | +#include <asm/mach-ralink/ralink_regs.h> |
||
76 | +#include <asm/mach-ralink/pinmux.h> |
||
77 | +#include <asm/mach-ralink/mt7620.h> |
||
78 | + |
||
79 | +#include "core.h" |
||
80 | + |
||
81 | +#define SYSC_REG_GPIO_MODE 0x60 |
||
82 | +#define SYSC_REG_GPIO_MODE2 0x64 |
||
83 | + |
||
84 | +struct rt2880_priv { |
||
85 | + struct device *dev; |
||
86 | + |
||
87 | + struct pinctrl_pin_desc *pads; |
||
88 | + struct pinctrl_desc *desc; |
||
89 | + |
||
90 | + struct rt2880_pmx_func **func; |
||
91 | + int func_count; |
||
92 | + |
||
93 | + struct rt2880_pmx_group *groups; |
||
94 | + const char **group_names; |
||
95 | + int group_count; |
||
96 | + |
||
97 | + uint8_t *gpio; |
||
98 | + int max_pins; |
||
99 | +}; |
||
100 | + |
||
101 | +static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) |
||
102 | +{ |
||
103 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
104 | + |
||
105 | + return p->group_count; |
||
106 | +} |
||
107 | + |
||
108 | +static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, |
||
109 | + unsigned group) |
||
110 | +{ |
||
111 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
112 | + |
||
113 | + if (group >= p->group_count) |
||
114 | + return NULL; |
||
115 | + |
||
116 | + return p->group_names[group]; |
||
117 | +} |
||
118 | + |
||
119 | +static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, |
||
120 | + unsigned group, |
||
121 | + const unsigned **pins, |
||
122 | + unsigned *num_pins) |
||
123 | +{ |
||
124 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
125 | + |
||
126 | + if (group >= p->group_count) |
||
127 | + return -EINVAL; |
||
128 | + |
||
129 | + *pins = p->groups[group].func[0].pins; |
||
130 | + *num_pins = p->groups[group].func[0].pin_count; |
||
131 | + |
||
132 | + return 0; |
||
133 | +} |
||
134 | + |
||
135 | +static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, |
||
136 | + struct pinctrl_map *map, unsigned num_maps) |
||
137 | +{ |
||
138 | + int i; |
||
139 | + |
||
140 | + for (i = 0; i < num_maps; i++) |
||
141 | + if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || |
||
142 | + map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) |
||
143 | + kfree(map[i].data.configs.configs); |
||
144 | + kfree(map); |
||
145 | +} |
||
146 | + |
||
147 | +static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, |
||
148 | + struct seq_file *s, |
||
149 | + unsigned offset) |
||
150 | +{ |
||
151 | + seq_printf(s, "ralink pio"); |
||
152 | +} |
||
153 | + |
||
154 | +static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, |
||
155 | + struct device_node *np, |
||
156 | + struct pinctrl_map **map) |
||
157 | +{ |
||
158 | + const char *function; |
||
159 | + int func = of_property_read_string(np, "ralink,function", &function); |
||
160 | + int grps = of_property_count_strings(np, "ralink,group"); |
||
161 | + int i; |
||
162 | + |
||
163 | + if (func || !grps) |
||
164 | + return; |
||
165 | + |
||
166 | + for (i = 0; i < grps; i++) { |
||
167 | + const char *group; |
||
168 | + |
||
169 | + of_property_read_string_index(np, "ralink,group", i, &group); |
||
170 | + |
||
171 | + (*map)->type = PIN_MAP_TYPE_MUX_GROUP; |
||
172 | + (*map)->name = function; |
||
173 | + (*map)->data.mux.group = group; |
||
174 | + (*map)->data.mux.function = function; |
||
175 | + (*map)++; |
||
176 | + } |
||
177 | +} |
||
178 | + |
||
179 | +static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, |
||
180 | + struct device_node *np_config, |
||
181 | + struct pinctrl_map **map, |
||
182 | + unsigned *num_maps) |
||
183 | +{ |
||
184 | + int max_maps = 0; |
||
185 | + struct pinctrl_map *tmp; |
||
186 | + struct device_node *np; |
||
187 | + |
||
188 | + for_each_child_of_node(np_config, np) { |
||
189 | + int ret = of_property_count_strings(np, "ralink,group"); |
||
190 | + |
||
191 | + if (ret >= 0) |
||
192 | + max_maps += ret; |
||
193 | + } |
||
194 | + |
||
195 | + if (!max_maps) |
||
196 | + return -EINVAL; |
||
197 | + |
||
198 | + *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); |
||
199 | + if (!*map) |
||
200 | + return -ENOMEM; |
||
201 | + |
||
202 | + tmp = *map; |
||
203 | + |
||
204 | + for_each_child_of_node(np_config, np) |
||
205 | + rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); |
||
206 | + *num_maps = max_maps; |
||
207 | + |
||
208 | + return 0; |
||
209 | +} |
||
210 | + |
||
211 | +static const struct pinctrl_ops rt2880_pctrl_ops = { |
||
212 | + .get_groups_count = rt2880_get_group_count, |
||
213 | + .get_group_name = rt2880_get_group_name, |
||
214 | + .get_group_pins = rt2880_get_group_pins, |
||
215 | + .pin_dbg_show = rt2880_pinctrl_pin_dbg_show, |
||
216 | + .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, |
||
217 | + .dt_free_map = rt2880_pinctrl_dt_free_map, |
||
218 | +}; |
||
219 | + |
||
220 | +static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) |
||
221 | +{ |
||
222 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
223 | + |
||
224 | + return p->func_count; |
||
225 | +} |
||
226 | + |
||
227 | +static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, |
||
228 | + unsigned func) |
||
229 | +{ |
||
230 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
231 | + |
||
232 | + return p->func[func]->name; |
||
233 | +} |
||
234 | + |
||
235 | +static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, |
||
236 | + unsigned func, |
||
237 | + const char * const **groups, |
||
238 | + unsigned * const num_groups) |
||
239 | +{ |
||
240 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
241 | + |
||
242 | + if (p->func[func]->group_count == 1) |
||
243 | + *groups = &p->group_names[p->func[func]->groups[0]]; |
||
244 | + else |
||
245 | + *groups = p->group_names; |
||
246 | + |
||
247 | + *num_groups = p->func[func]->group_count; |
||
248 | + |
||
249 | + return 0; |
||
250 | +} |
||
251 | + |
||
252 | +static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, |
||
253 | + unsigned func, |
||
254 | + unsigned group) |
||
255 | +{ |
||
256 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
257 | + u32 mode = 0; |
||
258 | + u32 reg = SYSC_REG_GPIO_MODE; |
||
259 | + int i; |
||
260 | + int shift; |
||
261 | + |
||
262 | + /* dont allow double use */ |
||
263 | + if (p->groups[group].enabled) { |
||
264 | + dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); |
||
265 | + return -EBUSY; |
||
266 | + } |
||
267 | + |
||
268 | + p->groups[group].enabled = 1; |
||
269 | + p->func[func]->enabled = 1; |
||
270 | + |
||
271 | + shift = p->groups[group].shift; |
||
272 | + if (shift >= 32) { |
||
273 | + shift -= 32; |
||
274 | + reg = SYSC_REG_GPIO_MODE2; |
||
275 | + } |
||
276 | + mode = rt_sysc_r32(reg); |
||
277 | + mode &= ~(p->groups[group].mask << shift); |
||
278 | + |
||
279 | + /* mark the pins as gpio */ |
||
280 | + for (i = 0; i < p->groups[group].func[0].pin_count; i++) |
||
281 | + p->gpio[p->groups[group].func[0].pins[i]] = 1; |
||
282 | + |
||
283 | + /* function 0 is gpio and needs special handling */ |
||
284 | + if (func == 0) { |
||
285 | + mode |= p->groups[group].gpio << shift; |
||
286 | + } else { |
||
287 | + for (i = 0; i < p->func[func]->pin_count; i++) |
||
288 | + p->gpio[p->func[func]->pins[i]] = 0; |
||
289 | + mode |= p->func[func]->value << shift; |
||
290 | + } |
||
291 | + rt_sysc_w32(mode, reg); |
||
292 | + |
||
293 | + return 0; |
||
294 | +} |
||
295 | + |
||
296 | +static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, |
||
297 | + struct pinctrl_gpio_range *range, |
||
298 | + unsigned pin) |
||
299 | +{ |
||
300 | + struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); |
||
301 | + |
||
302 | + if (!p->gpio[pin]) { |
||
303 | + dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); |
||
304 | + return -EINVAL; |
||
305 | + } |
||
306 | + |
||
307 | + return 0; |
||
308 | +} |
||
309 | + |
||
310 | +static const struct pinmux_ops rt2880_pmx_group_ops = { |
||
311 | + .get_functions_count = rt2880_pmx_func_count, |
||
312 | + .get_function_name = rt2880_pmx_func_name, |
||
313 | + .get_function_groups = rt2880_pmx_group_get_groups, |
||
314 | + .set_mux = rt2880_pmx_group_enable, |
||
315 | + .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, |
||
316 | +}; |
||
317 | + |
||
318 | +static struct pinctrl_desc rt2880_pctrl_desc = { |
||
319 | + .owner = THIS_MODULE, |
||
320 | + .name = "rt2880-pinmux", |
||
321 | + .pctlops = &rt2880_pctrl_ops, |
||
322 | + .pmxops = &rt2880_pmx_group_ops, |
||
323 | +}; |
||
324 | + |
||
325 | +static struct rt2880_pmx_func gpio_func = { |
||
326 | + .name = "gpio", |
||
327 | +}; |
||
328 | + |
||
329 | +static int rt2880_pinmux_index(struct rt2880_priv *p) |
||
330 | +{ |
||
331 | + struct rt2880_pmx_func **f; |
||
332 | + struct rt2880_pmx_group *mux = p->groups; |
||
333 | + int i, j, c = 0; |
||
334 | + |
||
335 | + /* count the mux functions */ |
||
336 | + while (mux->name) { |
||
337 | + p->group_count++; |
||
338 | + mux++; |
||
339 | + } |
||
340 | + |
||
341 | + /* allocate the group names array needed by the gpio function */ |
||
342 | + p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); |
||
343 | + if (!p->group_names) |
||
344 | + return -1; |
||
345 | + |
||
346 | + for (i = 0; i < p->group_count; i++) { |
||
347 | + p->group_names[i] = p->groups[i].name; |
||
348 | + p->func_count += p->groups[i].func_count; |
||
349 | + } |
||
350 | + |
||
351 | + /* we have a dummy function[0] for gpio */ |
||
352 | + p->func_count++; |
||
353 | + |
||
354 | + /* allocate our function and group mapping index buffers */ |
||
355 | + f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); |
||
356 | + gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); |
||
357 | + if (!f || !gpio_func.groups) |
||
358 | + return -1; |
||
359 | + |
||
360 | + /* add a backpointer to the function so it knows its group */ |
||
361 | + gpio_func.group_count = p->group_count; |
||
362 | + for (i = 0; i < gpio_func.group_count; i++) |
||
363 | + gpio_func.groups[i] = i; |
||
364 | + |
||
365 | + f[c] = &gpio_func; |
||
366 | + c++; |
||
367 | + |
||
368 | + /* add remaining functions */ |
||
369 | + for (i = 0; i < p->group_count; i++) { |
||
370 | + for (j = 0; j < p->groups[i].func_count; j++) { |
||
371 | + f[c] = &p->groups[i].func[j]; |
||
372 | + f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); |
||
373 | + f[c]->groups[0] = i; |
||
374 | + f[c]->group_count = 1; |
||
375 | + c++; |
||
376 | + } |
||
377 | + } |
||
378 | + return 0; |
||
379 | +} |
||
380 | + |
||
381 | +static int rt2880_pinmux_pins(struct rt2880_priv *p) |
||
382 | +{ |
||
383 | + int i, j; |
||
384 | + |
||
385 | + /* loop over the functions and initialize the pins array. also work out the highest pin used */ |
||
386 | + for (i = 0; i < p->func_count; i++) { |
||
387 | + int pin; |
||
388 | + |
||
389 | + if (!p->func[i]->pin_count) |
||
390 | + continue; |
||
391 | + |
||
392 | + p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); |
||
393 | + for (j = 0; j < p->func[i]->pin_count; j++) |
||
394 | + p->func[i]->pins[j] = p->func[i]->pin_first + j; |
||
395 | + |
||
396 | + pin = p->func[i]->pin_first + p->func[i]->pin_count; |
||
397 | + if (pin > p->max_pins) |
||
398 | + p->max_pins = pin; |
||
399 | + } |
||
400 | + |
||
401 | + /* the buffer that tells us which pins are gpio */ |
||
402 | + p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, |
||
403 | + GFP_KERNEL); |
||
404 | + /* the pads needed to tell pinctrl about our pins */ |
||
405 | + p->pads = devm_kzalloc(p->dev, |
||
406 | + sizeof(struct pinctrl_pin_desc) * p->max_pins, |
||
407 | + GFP_KERNEL); |
||
408 | + if (!p->pads || !p->gpio ) { |
||
409 | + dev_err(p->dev, "Failed to allocate gpio data\n"); |
||
410 | + return -ENOMEM; |
||
411 | + } |
||
412 | + |
||
413 | + memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); |
||
414 | + for (i = 0; i < p->func_count; i++) { |
||
415 | + if (!p->func[i]->pin_count) |
||
416 | + continue; |
||
417 | + |
||
418 | + for (j = 0; j < p->func[i]->pin_count; j++) |
||
419 | + p->gpio[p->func[i]->pins[j]] = 0; |
||
420 | + } |
||
421 | + |
||
422 | + /* pin 0 is always a gpio */ |
||
423 | + p->gpio[0] = 1; |
||
424 | + |
||
425 | + /* set the pads */ |
||
426 | + for (i = 0; i < p->max_pins; i++) { |
||
427 | + /* strlen("ioXY") + 1 = 5 */ |
||
428 | + char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); |
||
429 | + |
||
430 | + if (!name) { |
||
431 | + dev_err(p->dev, "Failed to allocate pad name\n"); |
||
432 | + return -ENOMEM; |
||
433 | + } |
||
434 | + snprintf(name, 5, "io%d", i); |
||
435 | + p->pads[i].number = i; |
||
436 | + p->pads[i].name = name; |
||
437 | + } |
||
438 | + p->desc->pins = p->pads; |
||
439 | + p->desc->npins = p->max_pins; |
||
440 | + |
||
441 | + return 0; |
||
442 | +} |
||
443 | + |
||
444 | +static int rt2880_pinmux_probe(struct platform_device *pdev) |
||
445 | +{ |
||
446 | + struct rt2880_priv *p; |
||
447 | + struct pinctrl_dev *dev; |
||
448 | + struct device_node *np; |
||
449 | + |
||
450 | + if (!rt2880_pinmux_data) |
||
451 | + return -ENOSYS; |
||
452 | + |
||
453 | + /* setup the private data */ |
||
454 | + p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); |
||
455 | + if (!p) |
||
456 | + return -ENOMEM; |
||
457 | + |
||
458 | + p->dev = &pdev->dev; |
||
459 | + p->desc = &rt2880_pctrl_desc; |
||
460 | + p->groups = rt2880_pinmux_data; |
||
461 | + platform_set_drvdata(pdev, p); |
||
462 | + |
||
463 | + /* init the device */ |
||
464 | + if (rt2880_pinmux_index(p)) { |
||
465 | + dev_err(&pdev->dev, "failed to load index\n"); |
||
466 | + return -EINVAL; |
||
467 | + } |
||
468 | + if (rt2880_pinmux_pins(p)) { |
||
469 | + dev_err(&pdev->dev, "failed to load pins\n"); |
||
470 | + return -EINVAL; |
||
471 | + } |
||
472 | + dev = pinctrl_register(p->desc, &pdev->dev, p); |
||
473 | + if (IS_ERR(dev)) |
||
474 | + return PTR_ERR(dev); |
||
475 | + |
||
476 | + /* finalize by adding gpio ranges for enables gpio controllers */ |
||
477 | + for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { |
||
478 | + const __be32 *ngpio, *gpiobase; |
||
479 | + struct pinctrl_gpio_range *range; |
||
480 | + char *name; |
||
481 | + |
||
482 | + if (!of_device_is_available(np)) |
||
483 | + continue; |
||
484 | + |
||
3 | office | 485 | + ngpio = of_get_property(np, "ralink,num-gpios", NULL); |
1 | office | 486 | + gpiobase = of_get_property(np, "ralink,gpio-base", NULL); |
487 | + if (!ngpio || !gpiobase) { |
||
488 | + dev_err(&pdev->dev, "failed to load chip info\n"); |
||
489 | + return -EINVAL; |
||
490 | + } |
||
491 | + |
||
492 | + range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); |
||
493 | + range->name = name = (char *) &range[1]; |
||
494 | + sprintf(name, "pio"); |
||
495 | + range->npins = __be32_to_cpu(*ngpio); |
||
496 | + range->base = __be32_to_cpu(*gpiobase); |
||
497 | + range->pin_base = range->base; |
||
498 | + pinctrl_add_gpio_range(dev, range); |
||
499 | + } |
||
500 | + |
||
501 | + return 0; |
||
502 | +} |
||
503 | + |
||
504 | +static const struct of_device_id rt2880_pinmux_match[] = { |
||
505 | + { .compatible = "ralink,rt2880-pinmux" }, |
||
506 | + {}, |
||
507 | +}; |
||
508 | +MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); |
||
509 | + |
||
510 | +static struct platform_driver rt2880_pinmux_driver = { |
||
511 | + .probe = rt2880_pinmux_probe, |
||
512 | + .driver = { |
||
513 | + .name = "rt2880-pinmux", |
||
514 | + .owner = THIS_MODULE, |
||
515 | + .of_match_table = rt2880_pinmux_match, |
||
516 | + }, |
||
517 | +}; |
||
518 | + |
||
519 | +int __init rt2880_pinmux_init(void) |
||
520 | +{ |
||
521 | + return platform_driver_register(&rt2880_pinmux_driver); |
||
522 | +} |
||
523 | + |
||
524 | +core_initcall_sync(rt2880_pinmux_init); |