From f752ceaff9b81a6d4a2fc99ce04dbe8c978f824a Mon Sep 17 00:00:00 2001 From: Anant Goel Date: Wed, 14 Oct 2020 10:55:25 -0700 Subject: [PATCH] drivers: pinctrl: Add custom GPIO to PDC pin mapping list support Add feature support where a user can provide a custom list of TLMM GPIOs associated with PDC pins for direct connect interrupt support. This feature is needed because the TLMM GPIO PDC map is fixed per target which is restrictive for a usecase where a custom list of direct connect interrupts for GPIOs is needed. Change-Id: Idc6e07a3405c7900445f25e60d08570f7b350fcc Signed-off-by: Anant Goel --- drivers/pinctrl/qcom/pinctrl-sdmshrike.c | 49 ++++++++++++++++++++++- drivers/pinctrl/qcom/pinctrl-sm6150.c | 47 ++++++++++++++++++++++ drivers/pinctrl/qcom/pinctrl-sm8150.c | 51 +++++++++++++++++++++++- 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-sdmshrike.c b/drivers/pinctrl/qcom/pinctrl-sdmshrike.c index 836ee39fec1d..160fa890a903 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdmshrike.c +++ b/drivers/pinctrl/qcom/pinctrl-sdmshrike.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include @@ -2270,8 +2270,55 @@ static struct msm_pinctrl_soc_data sdmshrike_pinctrl = { .dir_conn = sdmshrike_dir_conn, }; +static int sdmshrike_pinctrl_gpio_irq_map_probe(struct platform_device *pdev) +{ + int ret, n, gpio_irq_map_count; + struct device_node *np = pdev->dev.of_node; + struct msm_gpio_wakeirq_map *gpio_irq_map; + + n = of_property_count_elems_of_size(np, "qcom,gpio-irq-map", + sizeof(u32)); + if (n <= 0 || n % 2) + return -EINVAL; + + gpio_irq_map_count = n / 2; + gpio_irq_map = devm_kcalloc(&pdev->dev, gpio_irq_map_count, + sizeof(*gpio_irq_map), GFP_KERNEL); + if (!gpio_irq_map) + return -ENOMEM; + + for (n = 0; n < gpio_irq_map_count; n++) { + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 0, + &gpio_irq_map[n].gpio); + if (ret) + return ret; + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 1, + &gpio_irq_map[n].wakeirq); + if (ret) + return ret; + } + + sdmshrike_pinctrl.wakeirq_map = gpio_irq_map; + sdmshrike_pinctrl.nwakeirq_map = gpio_irq_map_count; + + return 0; +} + static int sdmshrike_pinctrl_probe(struct platform_device *pdev) { + int len, ret; + + if (of_find_property(pdev->dev.of_node, "qcom,gpio-irq-map", &len)) { + ret = sdmshrike_pinctrl_gpio_irq_map_probe(pdev); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse GPIO IRQ map\n"); + return ret; + } + } + return msm_pinctrl_probe(pdev, &sdmshrike_pinctrl); } diff --git a/drivers/pinctrl/qcom/pinctrl-sm6150.c b/drivers/pinctrl/qcom/pinctrl-sm6150.c index dd52c006f175..580eaeb0ee76 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6150.c @@ -1614,8 +1614,55 @@ static struct msm_pinctrl_soc_data sm6150_pinctrl = { #endif }; +static int sm6150_pinctrl_gpio_irq_map_probe(struct platform_device *pdev) +{ + int ret, n, gpio_irq_map_count; + struct device_node *np = pdev->dev.of_node; + struct msm_gpio_wakeirq_map *gpio_irq_map; + + n = of_property_count_elems_of_size(np, "qcom,gpio-irq-map", + sizeof(u32)); + if (n <= 0 || n % 2) + return -EINVAL; + + gpio_irq_map_count = n / 2; + gpio_irq_map = devm_kcalloc(&pdev->dev, gpio_irq_map_count, + sizeof(*gpio_irq_map), GFP_KERNEL); + if (!gpio_irq_map) + return -ENOMEM; + + for (n = 0; n < gpio_irq_map_count; n++) { + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 0, + &gpio_irq_map[n].gpio); + if (ret) + return ret; + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 1, + &gpio_irq_map[n].wakeirq); + if (ret) + return ret; + } + + sm6150_pinctrl.wakeirq_map = gpio_irq_map; + sm6150_pinctrl.nwakeirq_map = gpio_irq_map_count; + + return 0; +} + static int sm6150_pinctrl_probe(struct platform_device *pdev) { + int len, ret; + + if (of_find_property(pdev->dev.of_node, "qcom,gpio-irq-map", &len)) { + ret = sm6150_pinctrl_gpio_irq_map_probe(pdev); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse GPIO IRQ map\n"); + return ret; + } + } + return msm_pinctrl_probe(pdev, &sm6150_pinctrl); } diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index a1844ad2bb6b..e491640373d0 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. +// Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. #include #include @@ -1532,7 +1532,7 @@ static struct msm_dir_conn sm8150_dir_conn[] = { {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0} }; -static const struct msm_pinctrl_soc_data sm8150_pinctrl = { +static struct msm_pinctrl_soc_data sm8150_pinctrl = { .pins = sm8150_pins, .npins = ARRAY_SIZE(sm8150_pins), .functions = sm8150_functions, @@ -1547,8 +1547,55 @@ static const struct msm_pinctrl_soc_data sm8150_pinctrl = { .dir_conn = sm8150_dir_conn, }; +static int sm8150_pinctrl_gpio_irq_map_probe(struct platform_device *pdev) +{ + int ret, n, gpio_irq_map_count; + struct device_node *np = pdev->dev.of_node; + struct msm_gpio_wakeirq_map *gpio_irq_map; + + n = of_property_count_elems_of_size(np, "qcom,gpio-irq-map", + sizeof(u32)); + if (n <= 0 || n % 2) + return -EINVAL; + + gpio_irq_map_count = n / 2; + gpio_irq_map = devm_kcalloc(&pdev->dev, gpio_irq_map_count, + sizeof(*gpio_irq_map), GFP_KERNEL); + if (!gpio_irq_map) + return -ENOMEM; + + for (n = 0; n < gpio_irq_map_count; n++) { + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 0, + &gpio_irq_map[n].gpio); + if (ret) + return ret; + ret = of_property_read_u32_index(np, "qcom,gpio-irq-map", + n * 2 + 1, + &gpio_irq_map[n].wakeirq); + if (ret) + return ret; + } + + sm8150_pinctrl.wakeirq_map = gpio_irq_map; + sm8150_pinctrl.nwakeirq_map = gpio_irq_map_count; + + return 0; +} + static int sm8150_pinctrl_probe(struct platform_device *pdev) { + int len, ret; + + if (of_find_property(pdev->dev.of_node, "qcom,gpio-irq-map", &len)) { + ret = sm8150_pinctrl_gpio_irq_map_probe(pdev); + if (ret) { + dev_err(&pdev->dev, + "Unable to parse GPIO IRQ map\n"); + return ret; + } + } + return msm_pinctrl_probe(pdev, &sm8150_pinctrl); }