diff options
author | Sean Wang <sean.wang@mediatek.com> | 2018-09-08 07:07:37 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-09-18 17:53:37 -0400 |
commit | 89132dd8ffd2218fad3f53a9ca529e609237448a (patch) | |
tree | 937b21be21bbde3710b3933967a8e5b1cc46121e /drivers/pinctrl/mediatek | |
parent | 29686f0151dff68e623475d449f99d8124825b17 (diff) |
pinctrl: mediatek: extend eint build to pinctrl-mtk-common-v2.c
Almost all MediaTek SoCs apply the exact same logic to build eint, so move
the common functions into pinctrl-mtk-common-v2.c to allow each new pinctrl
driver to reuse them. Also, add a protection checker on hw->soc->eint_hw to
avoid invalid memory access when there's certain SoC not to define its
eint_hw properly in the code flow.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/mediatek')
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-moore.c | 124 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 135 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 2 |
3 files changed, 137 insertions, 124 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-moore.c b/drivers/pinctrl/mediatek/pinctrl-moore.c index f0390b34cae5..7cfab0cfd18c 100644 --- a/drivers/pinctrl/mediatek/pinctrl-moore.c +++ b/drivers/pinctrl/mediatek/pinctrl-moore.c | |||
@@ -584,130 +584,6 @@ static int mtk_build_functions(struct mtk_pinctrl *hw) | |||
584 | return 0; | 584 | return 0; |
585 | } | 585 | } |
586 | 586 | ||
587 | static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, | ||
588 | unsigned long eint_n) | ||
589 | { | ||
590 | const struct mtk_pin_desc *desc; | ||
591 | int i = 0; | ||
592 | |||
593 | desc = (const struct mtk_pin_desc *)hw->soc->pins; | ||
594 | |||
595 | while (i < hw->soc->npins) { | ||
596 | if (desc[i].eint.eint_n == eint_n) | ||
597 | return desc[i].number; | ||
598 | i++; | ||
599 | } | ||
600 | |||
601 | return EINT_NA; | ||
602 | } | ||
603 | |||
604 | static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n, | ||
605 | unsigned int *gpio_n, | ||
606 | struct gpio_chip **gpio_chip) | ||
607 | { | ||
608 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
609 | const struct mtk_pin_desc *desc; | ||
610 | |||
611 | desc = (const struct mtk_pin_desc *)hw->soc->pins; | ||
612 | *gpio_chip = &hw->chip; | ||
613 | |||
614 | /* Be greedy to guess first gpio_n is equal to eint_n */ | ||
615 | if (desc[eint_n].eint.eint_n == eint_n) | ||
616 | *gpio_n = eint_n; | ||
617 | else | ||
618 | *gpio_n = mtk_xt_find_eint_num(hw, eint_n); | ||
619 | |||
620 | return *gpio_n == EINT_NA ? -EINVAL : 0; | ||
621 | } | ||
622 | |||
623 | static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n) | ||
624 | { | ||
625 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
626 | struct gpio_chip *gpio_chip; | ||
627 | unsigned int gpio_n; | ||
628 | int err; | ||
629 | |||
630 | err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); | ||
631 | if (err) | ||
632 | return err; | ||
633 | |||
634 | return mtk_gpio_get(gpio_chip, gpio_n); | ||
635 | } | ||
636 | |||
637 | static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n) | ||
638 | { | ||
639 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
640 | const struct mtk_pin_desc *desc; | ||
641 | struct gpio_chip *gpio_chip; | ||
642 | unsigned int gpio_n; | ||
643 | int err; | ||
644 | |||
645 | err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); | ||
646 | if (err) | ||
647 | return err; | ||
648 | |||
649 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n]; | ||
650 | |||
651 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, | ||
652 | desc->eint.eint_m); | ||
653 | if (err) | ||
654 | return err; | ||
655 | |||
656 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT); | ||
657 | if (err) | ||
658 | return err; | ||
659 | |||
660 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE); | ||
661 | if (err) | ||
662 | return err; | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static const struct mtk_eint_xt mtk_eint_xt = { | ||
668 | .get_gpio_n = mtk_xt_get_gpio_n, | ||
669 | .get_gpio_state = mtk_xt_get_gpio_state, | ||
670 | .set_gpio_as_eint = mtk_xt_set_gpio_as_eint, | ||
671 | }; | ||
672 | |||
673 | static int | ||
674 | mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev) | ||
675 | { | ||
676 | struct device_node *np = pdev->dev.of_node; | ||
677 | struct resource *res; | ||
678 | |||
679 | if (!IS_ENABLED(CONFIG_EINT_MTK)) | ||
680 | return 0; | ||
681 | |||
682 | if (!of_property_read_bool(np, "interrupt-controller")) | ||
683 | return -ENODEV; | ||
684 | |||
685 | hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL); | ||
686 | if (!hw->eint) | ||
687 | return -ENOMEM; | ||
688 | |||
689 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint"); | ||
690 | if (!res) { | ||
691 | dev_err(&pdev->dev, "Unable to get eint resource\n"); | ||
692 | return -ENODEV; | ||
693 | } | ||
694 | |||
695 | hw->eint->base = devm_ioremap_resource(&pdev->dev, res); | ||
696 | if (IS_ERR(hw->eint->base)) | ||
697 | return PTR_ERR(hw->eint->base); | ||
698 | |||
699 | hw->eint->irq = irq_of_parse_and_map(np, 0); | ||
700 | if (!hw->eint->irq) | ||
701 | return -EINVAL; | ||
702 | |||
703 | hw->eint->dev = &pdev->dev; | ||
704 | hw->eint->hw = hw->soc->eint_hw; | ||
705 | hw->eint->pctl = hw; | ||
706 | hw->eint->gpio_xlate = &mtk_eint_xt; | ||
707 | |||
708 | return mtk_eint_do_init(hw->eint); | ||
709 | } | ||
710 | |||
711 | int mtk_moore_pinctrl_probe(struct platform_device *pdev, | 587 | int mtk_moore_pinctrl_probe(struct platform_device *pdev, |
712 | const struct mtk_pin_soc *soc) | 588 | const struct mtk_pin_soc *soc) |
713 | { | 589 | { |
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 7d5f570d7211..e8a2066a4d15 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | |||
@@ -9,8 +9,11 @@ | |||
9 | #include <linux/device.h> | 9 | #include <linux/device.h> |
10 | #include <linux/err.h> | 10 | #include <linux/err.h> |
11 | #include <linux/gpio.h> | 11 | #include <linux/gpio.h> |
12 | #include <linux/platform_device.h> | ||
12 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/of_irq.h> | ||
13 | 15 | ||
16 | #include "mtk-eint.h" | ||
14 | #include "pinctrl-mtk-common-v2.h" | 17 | #include "pinctrl-mtk-common-v2.h" |
15 | 18 | ||
16 | /** | 19 | /** |
@@ -207,6 +210,138 @@ int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, | |||
207 | return 0; | 210 | return 0; |
208 | } | 211 | } |
209 | 212 | ||
213 | static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n) | ||
214 | { | ||
215 | const struct mtk_pin_desc *desc; | ||
216 | int i = 0; | ||
217 | |||
218 | desc = (const struct mtk_pin_desc *)hw->soc->pins; | ||
219 | |||
220 | while (i < hw->soc->npins) { | ||
221 | if (desc[i].eint.eint_n == eint_n) | ||
222 | return desc[i].number; | ||
223 | i++; | ||
224 | } | ||
225 | |||
226 | return EINT_NA; | ||
227 | } | ||
228 | |||
229 | static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n, | ||
230 | unsigned int *gpio_n, | ||
231 | struct gpio_chip **gpio_chip) | ||
232 | { | ||
233 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
234 | const struct mtk_pin_desc *desc; | ||
235 | |||
236 | desc = (const struct mtk_pin_desc *)hw->soc->pins; | ||
237 | *gpio_chip = &hw->chip; | ||
238 | |||
239 | /* Be greedy to guess first gpio_n is equal to eint_n */ | ||
240 | if (desc[eint_n].eint.eint_n == eint_n) | ||
241 | *gpio_n = eint_n; | ||
242 | else | ||
243 | *gpio_n = mtk_xt_find_eint_num(hw, eint_n); | ||
244 | |||
245 | return *gpio_n == EINT_NA ? -EINVAL : 0; | ||
246 | } | ||
247 | |||
248 | static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n) | ||
249 | { | ||
250 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
251 | const struct mtk_pin_desc *desc; | ||
252 | struct gpio_chip *gpio_chip; | ||
253 | unsigned int gpio_n; | ||
254 | int value, err; | ||
255 | |||
256 | err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); | ||
257 | if (err) | ||
258 | return err; | ||
259 | |||
260 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n]; | ||
261 | |||
262 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); | ||
263 | if (err) | ||
264 | return err; | ||
265 | |||
266 | return !!value; | ||
267 | } | ||
268 | |||
269 | static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n) | ||
270 | { | ||
271 | struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; | ||
272 | const struct mtk_pin_desc *desc; | ||
273 | struct gpio_chip *gpio_chip; | ||
274 | unsigned int gpio_n; | ||
275 | int err; | ||
276 | |||
277 | err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); | ||
278 | if (err) | ||
279 | return err; | ||
280 | |||
281 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n]; | ||
282 | |||
283 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, | ||
284 | desc->eint.eint_m); | ||
285 | if (err) | ||
286 | return err; | ||
287 | |||
288 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT); | ||
289 | if (err) | ||
290 | return err; | ||
291 | |||
292 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE); | ||
293 | if (err) | ||
294 | return err; | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static const struct mtk_eint_xt mtk_eint_xt = { | ||
300 | .get_gpio_n = mtk_xt_get_gpio_n, | ||
301 | .get_gpio_state = mtk_xt_get_gpio_state, | ||
302 | .set_gpio_as_eint = mtk_xt_set_gpio_as_eint, | ||
303 | }; | ||
304 | |||
305 | int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev) | ||
306 | { | ||
307 | struct device_node *np = pdev->dev.of_node; | ||
308 | struct resource *res; | ||
309 | |||
310 | if (!IS_ENABLED(CONFIG_EINT_MTK)) | ||
311 | return 0; | ||
312 | |||
313 | if (!of_property_read_bool(np, "interrupt-controller")) | ||
314 | return -ENODEV; | ||
315 | |||
316 | hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL); | ||
317 | if (!hw->eint) | ||
318 | return -ENOMEM; | ||
319 | |||
320 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint"); | ||
321 | if (!res) { | ||
322 | dev_err(&pdev->dev, "Unable to get eint resource\n"); | ||
323 | return -ENODEV; | ||
324 | } | ||
325 | |||
326 | hw->eint->base = devm_ioremap_resource(&pdev->dev, res); | ||
327 | if (IS_ERR(hw->eint->base)) | ||
328 | return PTR_ERR(hw->eint->base); | ||
329 | |||
330 | hw->eint->irq = irq_of_parse_and_map(np, 0); | ||
331 | if (!hw->eint->irq) | ||
332 | return -EINVAL; | ||
333 | |||
334 | if (!hw->soc->eint_hw) | ||
335 | return -ENODEV; | ||
336 | |||
337 | hw->eint->dev = &pdev->dev; | ||
338 | hw->eint->hw = hw->soc->eint_hw; | ||
339 | hw->eint->pctl = hw; | ||
340 | hw->eint->gpio_xlate = &mtk_eint_xt; | ||
341 | |||
342 | return mtk_eint_do_init(hw->eint); | ||
343 | } | ||
344 | |||
210 | /* Revision 0 */ | 345 | /* Revision 0 */ |
211 | int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw, | 346 | int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw, |
212 | const struct mtk_pin_desc *desc) | 347 | const struct mtk_pin_desc *desc) |
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index 05b9b391afea..e0d4e68b7cdd 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | |||
@@ -245,6 +245,8 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, | |||
245 | int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, | 245 | int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, |
246 | int field, int *value); | 246 | int field, int *value); |
247 | 247 | ||
248 | int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev); | ||
249 | |||
248 | int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw, | 250 | int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw, |
249 | const struct mtk_pin_desc *desc); | 251 | const struct mtk_pin_desc *desc); |
250 | int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw, | 252 | int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw, |