OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From c12fb1774deaa9c9408b19db8d43d3612f6e47a0 Mon Sep 17 00:00:00 2001 |
2 | From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> |
||
3 | Date: Wed, 26 Sep 2018 21:31:03 +0200 |
||
4 | Subject: [PATCH] pinctrl: bcm: add Northstar driver |
||
5 | MIME-Version: 1.0 |
||
6 | Content-Type: text/plain; charset=UTF-8 |
||
7 | Content-Transfer-Encoding: 8bit |
||
8 | |||
9 | This driver provides support for Northstar mux controller. It differs |
||
10 | from Northstar Plus one so a new binding and driver were needed. |
||
11 | |||
12 | Signed-off-by: Rafał Miłecki <rafal@milecki.pl> |
||
13 | Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
||
14 | --- |
||
15 | drivers/pinctrl/bcm/Kconfig | 13 ++ |
||
16 | drivers/pinctrl/bcm/Makefile | 1 + |
||
17 | drivers/pinctrl/bcm/pinctrl-ns.c | 372 +++++++++++++++++++++++++++++++++++++++ |
||
18 | 3 files changed, 386 insertions(+) |
||
19 | create mode 100644 drivers/pinctrl/bcm/pinctrl-ns.c |
||
20 | |||
21 | --- a/drivers/pinctrl/bcm/Kconfig |
||
22 | +++ b/drivers/pinctrl/bcm/Kconfig |
||
23 | @@ -73,6 +73,19 @@ config PINCTRL_CYGNUS_MUX |
||
24 | configuration, with the exception that certain individual pins |
||
25 | can be overridden to GPIO function |
||
26 | |||
27 | +config PINCTRL_NS |
||
28 | + bool "Broadcom Northstar pins driver" |
||
29 | + depends on OF && (ARCH_BCM_5301X || COMPILE_TEST) |
||
30 | + select PINMUX |
||
31 | + select GENERIC_PINCONF |
||
32 | + default ARCH_BCM_5301X |
||
33 | + help |
||
34 | + Say yes here to enable the Broadcom NS SoC pins driver. |
||
35 | + |
||
36 | + The Broadcom Northstar pins driver supports muxing multi-purpose pins |
||
37 | + that can be used for various functions (e.g. SPI, I2C, UART) as well |
||
38 | + as GPIOs. |
||
39 | + |
||
40 | config PINCTRL_NSP_GPIO |
||
41 | bool "Broadcom NSP GPIO (with PINCONF) driver" |
||
42 | depends on OF_GPIO && (ARCH_BCM_NSP || COMPILE_TEST) |
||
43 | --- a/drivers/pinctrl/bcm/Makefile |
||
44 | +++ b/drivers/pinctrl/bcm/Makefile |
||
45 | @@ -5,6 +5,7 @@ obj-$(CONFIG_PINCTRL_BCM281XX) += pinct |
||
46 | obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o |
||
47 | obj-$(CONFIG_PINCTRL_IPROC_GPIO) += pinctrl-iproc-gpio.o |
||
48 | obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o |
||
49 | +obj-$(CONFIG_PINCTRL_NS) += pinctrl-ns.o |
||
50 | obj-$(CONFIG_PINCTRL_NSP_GPIO) += pinctrl-nsp-gpio.o |
||
51 | obj-$(CONFIG_PINCTRL_NS2_MUX) += pinctrl-ns2-mux.o |
||
52 | obj-$(CONFIG_PINCTRL_NSP_MUX) += pinctrl-nsp-mux.o |
||
53 | --- /dev/null |
||
54 | +++ b/drivers/pinctrl/bcm/pinctrl-ns.c |
||
55 | @@ -0,0 +1,372 @@ |
||
56 | +// SPDX-License-Identifier: GPL-2.0 |
||
57 | +/* |
||
58 | + * Copyright (C) 2018 Rafał Miłecki <rafal@milecki.pl> |
||
59 | + */ |
||
60 | + |
||
61 | +#include <linux/err.h> |
||
62 | +#include <linux/io.h> |
||
63 | +#include <linux/module.h> |
||
64 | +#include <linux/of.h> |
||
65 | +#include <linux/of_device.h> |
||
66 | +#include <linux/pinctrl/pinconf-generic.h> |
||
67 | +#include <linux/pinctrl/pinctrl.h> |
||
68 | +#include <linux/pinctrl/pinmux.h> |
||
69 | +#include <linux/platform_device.h> |
||
70 | +#include <linux/slab.h> |
||
71 | + |
||
72 | +#define FLAG_BCM4708 BIT(1) |
||
73 | +#define FLAG_BCM4709 BIT(2) |
||
74 | +#define FLAG_BCM53012 BIT(3) |
||
75 | + |
||
76 | +struct ns_pinctrl { |
||
77 | + struct device *dev; |
||
78 | + unsigned int chipset_flag; |
||
79 | + struct pinctrl_dev *pctldev; |
||
80 | + void __iomem *base; |
||
81 | + |
||
82 | + struct pinctrl_desc pctldesc; |
||
83 | + struct ns_pinctrl_group *groups; |
||
84 | + unsigned int num_groups; |
||
85 | + struct ns_pinctrl_function *functions; |
||
86 | + unsigned int num_functions; |
||
87 | +}; |
||
88 | + |
||
89 | +/* |
||
90 | + * Pins |
||
91 | + */ |
||
92 | + |
||
93 | +static const struct pinctrl_pin_desc ns_pinctrl_pins[] = { |
||
94 | + { 0, "spi_clk", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
95 | + { 1, "spi_ss", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
96 | + { 2, "spi_mosi", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
97 | + { 3, "spi_miso", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
98 | + { 4, "i2c_scl", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
99 | + { 5, "i2c_sda", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
100 | + { 6, "mdc", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
101 | + { 7, "mdio", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
102 | + { 8, "pwm0", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
103 | + { 9, "pwm1", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
104 | + { 10, "pwm2", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
105 | + { 11, "pwm3", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
106 | + { 12, "uart1_rx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
107 | + { 13, "uart1_tx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
108 | + { 14, "uart1_cts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
109 | + { 15, "uart1_rts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, |
||
110 | + { 16, "uart2_rx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
111 | + { 17, "uart2_tx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
112 | +/* TODO { ??, "xtal_out", (void *)(FLAG_BCM4709) }, */ |
||
113 | + { 22, "sdio_pwr", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
114 | + { 23, "sdio_en_1p8v", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, |
||
115 | +}; |
||
116 | + |
||
117 | +/* |
||
118 | + * Groups |
||
119 | + */ |
||
120 | + |
||
121 | +struct ns_pinctrl_group { |
||
122 | + const char *name; |
||
123 | + const unsigned int *pins; |
||
124 | + const unsigned int num_pins; |
||
125 | + unsigned int chipsets; |
||
126 | +}; |
||
127 | + |
||
128 | +static const unsigned int spi_pins[] = { 0, 1, 2, 3 }; |
||
129 | +static const unsigned int i2c_pins[] = { 4, 5 }; |
||
130 | +static const unsigned int mdio_pins[] = { 6, 7 }; |
||
131 | +static const unsigned int pwm0_pins[] = { 8 }; |
||
132 | +static const unsigned int pwm1_pins[] = { 9 }; |
||
133 | +static const unsigned int pwm2_pins[] = { 10 }; |
||
134 | +static const unsigned int pwm3_pins[] = { 11 }; |
||
135 | +static const unsigned int uart1_pins[] = { 12, 13, 14, 15 }; |
||
136 | +static const unsigned int uart2_pins[] = { 16, 17 }; |
||
137 | +static const unsigned int sdio_pwr_pins[] = { 22 }; |
||
138 | +static const unsigned int sdio_1p8v_pins[] = { 23 }; |
||
139 | + |
||
140 | +#define NS_GROUP(_name, _pins, _chipsets) \ |
||
141 | +{ \ |
||
142 | + .name = _name, \ |
||
143 | + .pins = _pins, \ |
||
144 | + .num_pins = ARRAY_SIZE(_pins), \ |
||
145 | + .chipsets = _chipsets, \ |
||
146 | +} |
||
147 | + |
||
148 | +static const struct ns_pinctrl_group ns_pinctrl_groups[] = { |
||
149 | + NS_GROUP("spi_grp", spi_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
150 | + NS_GROUP("i2c_grp", i2c_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
151 | + NS_GROUP("mdio_grp", mdio_pins, FLAG_BCM4709 | FLAG_BCM53012), |
||
152 | + NS_GROUP("pwm0_grp", pwm0_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
153 | + NS_GROUP("pwm1_grp", pwm1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
154 | + NS_GROUP("pwm2_grp", pwm2_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
155 | + NS_GROUP("pwm3_grp", pwm3_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
156 | + NS_GROUP("uart1_grp", uart1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
157 | + NS_GROUP("uart2_grp", uart2_pins, FLAG_BCM4709 | FLAG_BCM53012), |
||
158 | + NS_GROUP("sdio_pwr_grp", sdio_pwr_pins, FLAG_BCM4709 | FLAG_BCM53012), |
||
159 | + NS_GROUP("sdio_1p8v_grp", sdio_1p8v_pins, FLAG_BCM4709 | FLAG_BCM53012), |
||
160 | +}; |
||
161 | + |
||
162 | +/* |
||
163 | + * Functions |
||
164 | + */ |
||
165 | + |
||
166 | +struct ns_pinctrl_function { |
||
167 | + const char *name; |
||
168 | + const char * const *groups; |
||
169 | + const unsigned int num_groups; |
||
170 | + unsigned int chipsets; |
||
171 | +}; |
||
172 | + |
||
173 | +static const char * const spi_groups[] = { "spi_grp" }; |
||
174 | +static const char * const i2c_groups[] = { "i2c_grp" }; |
||
175 | +static const char * const mdio_groups[] = { "mdio_grp" }; |
||
176 | +static const char * const pwm_groups[] = { "pwm0_grp", "pwm1_grp", "pwm2_grp", |
||
177 | + "pwm3_grp" }; |
||
178 | +static const char * const uart1_groups[] = { "uart1_grp" }; |
||
179 | +static const char * const uart2_groups[] = { "uart2_grp" }; |
||
180 | +static const char * const sdio_groups[] = { "sdio_pwr_grp", "sdio_1p8v_grp" }; |
||
181 | + |
||
182 | +#define NS_FUNCTION(_name, _groups, _chipsets) \ |
||
183 | +{ \ |
||
184 | + .name = _name, \ |
||
185 | + .groups = _groups, \ |
||
186 | + .num_groups = ARRAY_SIZE(_groups), \ |
||
187 | + .chipsets = _chipsets, \ |
||
188 | +} |
||
189 | + |
||
190 | +static const struct ns_pinctrl_function ns_pinctrl_functions[] = { |
||
191 | + NS_FUNCTION("spi", spi_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
192 | + NS_FUNCTION("i2c", i2c_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
193 | + NS_FUNCTION("mdio", mdio_groups, FLAG_BCM4709 | FLAG_BCM53012), |
||
194 | + NS_FUNCTION("pwm", pwm_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
195 | + NS_FUNCTION("uart1", uart1_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), |
||
196 | + NS_FUNCTION("uart2", uart2_groups, FLAG_BCM4709 | FLAG_BCM53012), |
||
197 | + NS_FUNCTION("sdio", sdio_groups, FLAG_BCM4709 | FLAG_BCM53012), |
||
198 | +}; |
||
199 | + |
||
200 | +/* |
||
201 | + * Groups code |
||
202 | + */ |
||
203 | + |
||
204 | +static int ns_pinctrl_get_groups_count(struct pinctrl_dev *pctrl_dev) |
||
205 | +{ |
||
206 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
207 | + |
||
208 | + return ns_pinctrl->num_groups; |
||
209 | +} |
||
210 | + |
||
211 | +static const char *ns_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev, |
||
212 | + unsigned int selector) |
||
213 | +{ |
||
214 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
215 | + |
||
216 | + return ns_pinctrl->groups[selector].name; |
||
217 | +} |
||
218 | + |
||
219 | +static int ns_pinctrl_get_group_pins(struct pinctrl_dev *pctrl_dev, |
||
220 | + unsigned int selector, |
||
221 | + const unsigned int **pins, |
||
222 | + unsigned int *num_pins) |
||
223 | +{ |
||
224 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
225 | + |
||
226 | + *pins = ns_pinctrl->groups[selector].pins; |
||
227 | + *num_pins = ns_pinctrl->groups[selector].num_pins; |
||
228 | + |
||
229 | + return 0; |
||
230 | +} |
||
231 | + |
||
232 | +static const struct pinctrl_ops ns_pinctrl_ops = { |
||
233 | + .get_groups_count = ns_pinctrl_get_groups_count, |
||
234 | + .get_group_name = ns_pinctrl_get_group_name, |
||
235 | + .get_group_pins = ns_pinctrl_get_group_pins, |
||
236 | + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, |
||
237 | + .dt_free_map = pinconf_generic_dt_free_map, |
||
238 | +}; |
||
239 | + |
||
240 | +/* |
||
241 | + * Functions code |
||
242 | + */ |
||
243 | + |
||
244 | +static int ns_pinctrl_get_functions_count(struct pinctrl_dev *pctrl_dev) |
||
245 | +{ |
||
246 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
247 | + |
||
248 | + return ns_pinctrl->num_functions; |
||
249 | +} |
||
250 | + |
||
251 | +static const char *ns_pinctrl_get_function_name(struct pinctrl_dev *pctrl_dev, |
||
252 | + unsigned int selector) |
||
253 | +{ |
||
254 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
255 | + |
||
256 | + return ns_pinctrl->functions[selector].name; |
||
257 | +} |
||
258 | + |
||
259 | +static int ns_pinctrl_get_function_groups(struct pinctrl_dev *pctrl_dev, |
||
260 | + unsigned int selector, |
||
261 | + const char * const **groups, |
||
262 | + unsigned * const num_groups) |
||
263 | +{ |
||
264 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
265 | + |
||
266 | + *groups = ns_pinctrl->functions[selector].groups; |
||
267 | + *num_groups = ns_pinctrl->functions[selector].num_groups; |
||
268 | + |
||
269 | + return 0; |
||
270 | +} |
||
271 | + |
||
272 | +static int ns_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, |
||
273 | + unsigned int func_select, |
||
274 | + unsigned int grp_select) |
||
275 | +{ |
||
276 | + struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); |
||
277 | + u32 unset = 0; |
||
278 | + u32 tmp; |
||
279 | + int i; |
||
280 | + |
||
281 | + for (i = 0; i < ns_pinctrl->groups[grp_select].num_pins; i++) { |
||
282 | + int pin_number = ns_pinctrl->groups[grp_select].pins[i]; |
||
283 | + |
||
284 | + unset |= BIT(pin_number); |
||
285 | + } |
||
286 | + |
||
287 | + tmp = readl(ns_pinctrl->base); |
||
288 | + tmp &= ~unset; |
||
289 | + writel(tmp, ns_pinctrl->base); |
||
290 | + |
||
291 | + return 0; |
||
292 | +} |
||
293 | + |
||
294 | +static const struct pinmux_ops ns_pinctrl_pmxops = { |
||
295 | + .get_functions_count = ns_pinctrl_get_functions_count, |
||
296 | + .get_function_name = ns_pinctrl_get_function_name, |
||
297 | + .get_function_groups = ns_pinctrl_get_function_groups, |
||
298 | + .set_mux = ns_pinctrl_set_mux, |
||
299 | +}; |
||
300 | + |
||
301 | +/* |
||
302 | + * Controller code |
||
303 | + */ |
||
304 | + |
||
305 | +static struct pinctrl_desc ns_pinctrl_desc = { |
||
306 | + .name = "pinctrl-ns", |
||
307 | + .pctlops = &ns_pinctrl_ops, |
||
308 | + .pmxops = &ns_pinctrl_pmxops, |
||
309 | +}; |
||
310 | + |
||
311 | +static const struct of_device_id ns_pinctrl_of_match_table[] = { |
||
312 | + { .compatible = "brcm,bcm4708-pinmux", .data = (void *)FLAG_BCM4708, }, |
||
313 | + { .compatible = "brcm,bcm4709-pinmux", .data = (void *)FLAG_BCM4709, }, |
||
314 | + { .compatible = "brcm,bcm53012-pinmux", .data = (void *)FLAG_BCM53012, }, |
||
315 | + { } |
||
316 | +}; |
||
317 | + |
||
318 | +static int ns_pinctrl_probe(struct platform_device *pdev) |
||
319 | +{ |
||
320 | + struct device *dev = &pdev->dev; |
||
321 | + const struct of_device_id *of_id; |
||
322 | + struct ns_pinctrl *ns_pinctrl; |
||
323 | + struct pinctrl_desc *pctldesc; |
||
324 | + struct pinctrl_pin_desc *pin; |
||
325 | + struct ns_pinctrl_group *group; |
||
326 | + struct ns_pinctrl_function *function; |
||
327 | + struct resource *res; |
||
328 | + int i; |
||
329 | + |
||
330 | + ns_pinctrl = devm_kzalloc(dev, sizeof(*ns_pinctrl), GFP_KERNEL); |
||
331 | + if (!ns_pinctrl) |
||
332 | + return -ENOMEM; |
||
333 | + pctldesc = &ns_pinctrl->pctldesc; |
||
334 | + platform_set_drvdata(pdev, ns_pinctrl); |
||
335 | + |
||
336 | + /* Set basic properties */ |
||
337 | + |
||
338 | + ns_pinctrl->dev = dev; |
||
339 | + |
||
340 | + of_id = of_match_device(ns_pinctrl_of_match_table, dev); |
||
341 | + if (!of_id) |
||
342 | + return -EINVAL; |
||
343 | + ns_pinctrl->chipset_flag = (unsigned int)of_id->data; |
||
344 | + |
||
345 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
||
346 | + "cru_gpio_control"); |
||
347 | + ns_pinctrl->base = devm_ioremap_resource(dev, res); |
||
348 | + if (IS_ERR(ns_pinctrl->base)) { |
||
349 | + dev_err(dev, "Failed to map pinctrl regs\n"); |
||
350 | + return PTR_ERR(ns_pinctrl->base); |
||
351 | + } |
||
352 | + |
||
353 | + memcpy(pctldesc, &ns_pinctrl_desc, sizeof(*pctldesc)); |
||
354 | + |
||
355 | + /* Set pinctrl properties */ |
||
356 | + |
||
357 | + pctldesc->pins = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_pins), |
||
358 | + sizeof(struct pinctrl_pin_desc), |
||
359 | + GFP_KERNEL); |
||
360 | + if (!pctldesc->pins) |
||
361 | + return -ENOMEM; |
||
362 | + for (i = 0, pin = (struct pinctrl_pin_desc *)&pctldesc->pins[0]; |
||
363 | + i < ARRAY_SIZE(ns_pinctrl_pins); i++) { |
||
364 | + const struct pinctrl_pin_desc *src = &ns_pinctrl_pins[i]; |
||
365 | + unsigned int chipsets = (unsigned int)src->drv_data; |
||
366 | + |
||
367 | + if (chipsets & ns_pinctrl->chipset_flag) { |
||
368 | + memcpy(pin++, src, sizeof(*src)); |
||
369 | + pctldesc->npins++; |
||
370 | + } |
||
371 | + } |
||
372 | + |
||
373 | + ns_pinctrl->groups = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_groups), |
||
374 | + sizeof(struct ns_pinctrl_group), |
||
375 | + GFP_KERNEL); |
||
376 | + if (!ns_pinctrl->groups) |
||
377 | + return -ENOMEM; |
||
378 | + for (i = 0, group = &ns_pinctrl->groups[0]; |
||
379 | + i < ARRAY_SIZE(ns_pinctrl_groups); i++) { |
||
380 | + const struct ns_pinctrl_group *src = &ns_pinctrl_groups[i]; |
||
381 | + |
||
382 | + if (src->chipsets & ns_pinctrl->chipset_flag) { |
||
383 | + memcpy(group++, src, sizeof(*src)); |
||
384 | + ns_pinctrl->num_groups++; |
||
385 | + } |
||
386 | + } |
||
387 | + |
||
388 | + ns_pinctrl->functions = devm_kcalloc(dev, |
||
389 | + ARRAY_SIZE(ns_pinctrl_functions), |
||
390 | + sizeof(struct ns_pinctrl_function), |
||
391 | + GFP_KERNEL); |
||
392 | + if (!ns_pinctrl->functions) |
||
393 | + return -ENOMEM; |
||
394 | + for (i = 0, function = &ns_pinctrl->functions[0]; |
||
395 | + i < ARRAY_SIZE(ns_pinctrl_functions); i++) { |
||
396 | + const struct ns_pinctrl_function *src = &ns_pinctrl_functions[i]; |
||
397 | + |
||
398 | + if (src->chipsets & ns_pinctrl->chipset_flag) { |
||
399 | + memcpy(function++, src, sizeof(*src)); |
||
400 | + ns_pinctrl->num_functions++; |
||
401 | + } |
||
402 | + } |
||
403 | + |
||
404 | + /* Register */ |
||
405 | + |
||
406 | + ns_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, ns_pinctrl); |
||
407 | + if (IS_ERR(ns_pinctrl->pctldev)) { |
||
408 | + dev_err(dev, "Failed to register pinctrl\n"); |
||
409 | + return PTR_ERR(ns_pinctrl->pctldev); |
||
410 | + } |
||
411 | + |
||
412 | + return 0; |
||
413 | +} |
||
414 | + |
||
415 | +static struct platform_driver ns_pinctrl_driver = { |
||
416 | + .probe = ns_pinctrl_probe, |
||
417 | + .driver = { |
||
418 | + .name = "ns-pinmux", |
||
419 | + .of_match_table = ns_pinctrl_of_match_table, |
||
420 | + }, |
||
421 | +}; |
||
422 | + |
||
423 | +module_platform_driver(ns_pinctrl_driver); |
||
424 | + |
||
425 | +MODULE_AUTHOR("Rafał Miłecki"); |
||
426 | +MODULE_LICENSE("GPL v2"); |
||
427 | +MODULE_DEVICE_TABLE(of, ns_pinctrl_of_match_table); |