diff options
Diffstat (limited to 'drivers/pinctrl/samsung')
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-exynos-arm64.c | 73 | ||||
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-exynos.c | 7 | ||||
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-samsung.c | 89 | ||||
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-samsung.h | 1 |
4 files changed, 148 insertions, 22 deletions
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c index 2e490e7696f4..d291819c2f77 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c @@ -585,13 +585,11 @@ static const struct samsung_pin_ctrl exynos850_pin_ctrl[] __initconst = { /* pin-controller instance 0 ALIVE data */ .pin_banks = exynos850_pin_banks0, .nr_banks = ARRAY_SIZE(exynos850_pin_banks0), - .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, }, { /* pin-controller instance 1 CMGP data */ .pin_banks = exynos850_pin_banks1, .nr_banks = ARRAY_SIZE(exynos850_pin_banks1), - .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, }, { /* pin-controller instance 2 AUD data */ @@ -727,3 +725,74 @@ const struct samsung_pinctrl_of_match_data exynosautov9_of_data __initconst = { .ctrl = exynosautov9_pin_ctrl, .num_ctrl = ARRAY_SIZE(exynosautov9_pin_ctrl), }; + +/* + * Pinctrl driver data for Tesla FSD SoC. FSD SoC includes three + * gpio/pin-mux/pinconfig controllers. + */ + +/* pin banks of FSD pin-controller 0 (FSYS) */ +static const struct samsung_pin_bank_data fsd_pin_banks0[] __initconst = { + EXYNOS850_PIN_BANK_EINTG(7, 0x00, "gpf0", 0x00), + EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gpf1", 0x04), + EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gpf6", 0x08), + EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpf4", 0x0c), + EXYNOS850_PIN_BANK_EINTG(6, 0x80, "gpf5", 0x10), +}; + +/* pin banks of FSD pin-controller 1 (PERIC) */ +static const struct samsung_pin_bank_data fsd_pin_banks1[] __initconst = { + EXYNOS850_PIN_BANK_EINTG(4, 0x000, "gpc8", 0x00), + EXYNOS850_PIN_BANK_EINTG(7, 0x020, "gpf2", 0x04), + EXYNOS850_PIN_BANK_EINTG(8, 0x040, "gpf3", 0x08), + EXYNOS850_PIN_BANK_EINTG(8, 0x060, "gpd0", 0x0c), + EXYNOS850_PIN_BANK_EINTG(8, 0x080, "gpb0", 0x10), + EXYNOS850_PIN_BANK_EINTG(8, 0x0a0, "gpb1", 0x14), + EXYNOS850_PIN_BANK_EINTG(8, 0x0c0, "gpb4", 0x18), + EXYNOS850_PIN_BANK_EINTG(4, 0x0e0, "gpb5", 0x1c), + EXYNOS850_PIN_BANK_EINTG(8, 0x100, "gpb6", 0x20), + EXYNOS850_PIN_BANK_EINTG(8, 0x120, "gpb7", 0x24), + EXYNOS850_PIN_BANK_EINTG(5, 0x140, "gpd1", 0x28), + EXYNOS850_PIN_BANK_EINTG(5, 0x160, "gpd2", 0x2c), + EXYNOS850_PIN_BANK_EINTG(7, 0x180, "gpd3", 0x30), + EXYNOS850_PIN_BANK_EINTG(8, 0x1a0, "gpg0", 0x34), + EXYNOS850_PIN_BANK_EINTG(8, 0x1c0, "gpg1", 0x38), + EXYNOS850_PIN_BANK_EINTG(8, 0x1e0, "gpg2", 0x3c), + EXYNOS850_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40), + EXYNOS850_PIN_BANK_EINTG(8, 0x220, "gpg4", 0x44), + EXYNOS850_PIN_BANK_EINTG(8, 0x240, "gpg5", 0x48), + EXYNOS850_PIN_BANK_EINTG(8, 0x260, "gpg6", 0x4c), + EXYNOS850_PIN_BANK_EINTG(8, 0x280, "gpg7", 0x50), +}; + +/* pin banks of FSD pin-controller 2 (PMU) */ +static const struct samsung_pin_bank_data fsd_pin_banks2[] __initconst = { + EXYNOS850_PIN_BANK_EINTN(3, 0x00, "gpq0"), +}; + +const struct samsung_pin_ctrl fsd_pin_ctrl[] __initconst = { + { + /* pin-controller instance 0 FSYS0 data */ + .pin_banks = fsd_pin_banks0, + .nr_banks = ARRAY_SIZE(fsd_pin_banks0), + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 1 PERIC data */ + .pin_banks = fsd_pin_banks1, + .nr_banks = ARRAY_SIZE(fsd_pin_banks1), + .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 2 PMU data */ + .pin_banks = fsd_pin_banks2, + .nr_banks = ARRAY_SIZE(fsd_pin_banks2), + }, +}; + +const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = { + .ctrl = fsd_pin_ctrl, + .num_ctrl = ARRAY_SIZE(fsd_pin_ctrl), +}; diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index 0489c899b401..c1c4ffbae6e2 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -344,7 +344,8 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq); - pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq); + pr_info("wake %s for irq %u (%s-%lu)\n", on ? "enabled" : "disabled", + irqd->irq, bank->name, irqd->hwirq); if (!on) *our_chip->eint_wake_mask_value |= bit; @@ -465,6 +466,10 @@ static const struct of_device_id exynos_wkup_irq_ids[] = { .data = &exynos4210_wkup_irq_chip }, { .compatible = "samsung,exynos7-wakeup-eint", .data = &exynos7_wkup_irq_chip }, + { .compatible = "samsung,exynos850-wakeup-eint", + .data = &exynos7_wkup_irq_chip }, + { .compatible = "samsung,exynosautov9-wakeup-eint", + .data = &exynos7_wkup_irq_chip }, { } }; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 0f6e9305fec5..f610beab23a0 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1002,13 +1002,66 @@ samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev) return &(of_data->ctrl[id]); } +static void samsung_banks_of_node_put(struct samsung_pinctrl_drv_data *d) +{ + struct samsung_pin_bank *bank; + unsigned int i; + + bank = d->pin_banks; + for (i = 0; i < d->nr_banks; ++i, ++bank) + of_node_put(bank->of_node); +} + +/* + * Iterate over all driver pin banks to find one matching the name of node, + * skipping optional "-gpio" node suffix. When found, assign node to the bank. + */ +static void samsung_banks_of_node_get(struct device *dev, + struct samsung_pinctrl_drv_data *d, + struct device_node *node) +{ + const char *suffix = "-gpio-bank"; + struct samsung_pin_bank *bank; + struct device_node *child; + /* Pin bank names are up to 4 characters */ + char node_name[20]; + unsigned int i; + size_t len; + + bank = d->pin_banks; + for (i = 0; i < d->nr_banks; ++i, ++bank) { + strscpy(node_name, bank->name, sizeof(node_name)); + len = strlcat(node_name, suffix, sizeof(node_name)); + if (len >= sizeof(node_name)) { + dev_err(dev, "Too long pin bank name '%s', ignoring\n", + bank->name); + continue; + } + + for_each_child_of_node(node, child) { + if (!of_find_property(child, "gpio-controller", NULL)) + continue; + if (of_node_name_eq(child, node_name)) + break; + else if (of_node_name_eq(child, bank->name)) + break; + } + + if (child) + bank->of_node = child; + else + dev_warn(dev, "Missing node for bank %s - invalid DTB\n", + bank->name); + /* child reference dropped in samsung_drop_banks_of_node() */ + } +} + /* retrieve the soc specific data */ static const struct samsung_pin_ctrl * samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - struct device_node *np; const struct samsung_pin_bank_data *bdata; const struct samsung_pin_ctrl *ctrl; struct samsung_pin_bank *bank; @@ -1072,17 +1125,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, */ d->virt_base = virt_base[0]; - for_each_child_of_node(node, np) { - if (!of_find_property(np, "gpio-controller", NULL)) - continue; - bank = d->pin_banks; - for (i = 0; i < d->nr_banks; ++i, ++bank) { - if (of_node_name_eq(np, bank->name)) { - bank->of_node = np; - break; - } - } - } + samsung_banks_of_node_get(&pdev->dev, d, node); d->pin_base = pin_base; pin_base += d->nr_pins; @@ -1117,19 +1160,19 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) if (ctrl->retention_data) { drvdata->retention_ctrl = ctrl->retention_data->init(drvdata, ctrl->retention_data); - if (IS_ERR(drvdata->retention_ctrl)) - return PTR_ERR(drvdata->retention_ctrl); + if (IS_ERR(drvdata->retention_ctrl)) { + ret = PTR_ERR(drvdata->retention_ctrl); + goto err_put_banks; + } } ret = samsung_pinctrl_register(pdev, drvdata); if (ret) - return ret; + goto err_put_banks; ret = samsung_gpiolib_register(pdev, drvdata); - if (ret) { - samsung_pinctrl_unregister(pdev, drvdata); - return ret; - } + if (ret) + goto err_unregister; if (ctrl->eint_gpio_init) ctrl->eint_gpio_init(drvdata); @@ -1139,6 +1182,12 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drvdata); return 0; + +err_unregister: + samsung_pinctrl_unregister(pdev, drvdata); +err_put_banks: + samsung_banks_of_node_put(drvdata); + return ret; } /* @@ -1271,6 +1320,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { .data = &exynos850_of_data }, { .compatible = "samsung,exynosautov9-pinctrl", .data = &exynosautov9_of_data }, + { .compatible = "tesla,fsd-pinctrl", + .data = &fsd_of_data }, #endif #ifdef CONFIG_PINCTRL_S3C64XX { .compatible = "samsung,s3c64xx-pinctrl", diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 1f8d30ba05af..5b32d3f30fcd 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -342,6 +342,7 @@ extern const struct samsung_pinctrl_of_match_data exynos7_of_data; extern const struct samsung_pinctrl_of_match_data exynos7885_of_data; extern const struct samsung_pinctrl_of_match_data exynos850_of_data; extern const struct samsung_pinctrl_of_match_data exynosautov9_of_data; +extern const struct samsung_pinctrl_of_match_data fsd_of_data; extern const struct samsung_pinctrl_of_match_data s3c64xx_of_data; extern const struct samsung_pinctrl_of_match_data s3c2412_of_data; extern const struct samsung_pinctrl_of_match_data s3c2416_of_data; |