diff options
Diffstat (limited to 'drivers/pinctrl/sprd/pinctrl-sprd.c')
| -rw-r--r-- | drivers/pinctrl/sprd/pinctrl-sprd.c | 110 |
1 files changed, 61 insertions, 49 deletions
diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c index 7d9a44bd0047..16cf9d15f247 100644 --- a/drivers/pinctrl/sprd/pinctrl-sprd.c +++ b/drivers/pinctrl/sprd/pinctrl-sprd.c @@ -1,15 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Spreadtrum pin controller driver * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. */ #include <linux/debugfs.h> @@ -19,14 +11,16 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/seq_file.h> +#include <linux/slab.h> + +#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/machine.h> -#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> -#include <linux/slab.h> #include "../core.h" #include "../pinmux.h" @@ -49,7 +43,8 @@ #define PUBCP_SLEEP_MODE BIT(14) #define TGLDSP_SLEEP_MODE BIT(15) #define AGDSP_SLEEP_MODE BIT(16) -#define SLEEP_MODE_MASK GENMASK(3, 0) +#define CM4_SLEEP_MODE BIT(17) +#define SLEEP_MODE_MASK GENMASK(5, 0) #define SLEEP_MODE_SHIFT 13 #define SLEEP_INPUT BIT(1) @@ -75,8 +70,8 @@ #define SLEEP_PULL_UP_MASK 0x1 #define SLEEP_PULL_UP_SHIFT 3 -#define PULL_UP_20K (BIT(12) | BIT(7)) -#define PULL_UP_4_7K BIT(12) +#define PULL_UP_4_7K (BIT(12) | BIT(7)) +#define PULL_UP_20K BIT(7) #define PULL_UP_MASK 0x21 #define PULL_UP_SHIFT 7 @@ -89,6 +84,7 @@ enum pin_sleep_mode { PUBCP_SLEEP = BIT(1), TGLDSP_SLEEP = BIT(2), AGDSP_SLEEP = BIT(3), + CM4_SLEEP = BIT(4), }; enum pin_func_sel { @@ -262,8 +258,7 @@ static int sprd_dt_node_to_map(struct pinctrl_dev *pctldev, grp = sprd_pinctrl_find_group_by_name(pctl, np->name); if (!grp) { - dev_err(pctl->dev, "unable to find group for node %s\n", - of_node_full_name(np)); + dev_err(pctl->dev, "unable to find group for node %pOF\n", np); return -EINVAL; } @@ -280,16 +275,14 @@ static int sprd_dt_node_to_map(struct pinctrl_dev *pctldev, if (ret < 0) { if (ret != -EINVAL) dev_err(pctl->dev, - "%s: could not parse property function\n", - of_node_full_name(np)); + "%pOF: could not parse property function\n", np); function = NULL; } ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); if (ret < 0) { - dev_err(pctl->dev, "%s: could not parse node property\n", - of_node_full_name(np)); + dev_err(pctl->dev, "%pOF: could not parse node property\n", np); return ret; } @@ -462,7 +455,7 @@ static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, if (pin->type == GLOBAL_CTRL_PIN && param == SPRD_PIN_CONFIG_CONTROL) { arg = reg; - } else if (pin->type == COMMON_PIN) { + } else if (pin->type == COMMON_PIN || pin->type == MISC_PIN) { switch (param) { case SPRD_PIN_CONFIG_SLEEP_MODE: arg = (reg >> SLEEP_MODE_SHIFT) & SLEEP_MODE_MASK; @@ -470,17 +463,15 @@ static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, case PIN_CONFIG_INPUT_ENABLE: arg = (reg >> SLEEP_INPUT_SHIFT) & SLEEP_INPUT_MASK; break; - case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_OUTPUT_ENABLE: arg = reg & SLEEP_OUTPUT_MASK; break; - case PIN_CONFIG_SLEEP_HARDWARE_STATE: - arg = 0; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + if ((reg & SLEEP_OUTPUT) || (reg & SLEEP_INPUT)) + return -EINVAL; + + arg = 1; break; - default: - return -ENOTSUPP; - } - } else if (pin->type == MISC_PIN) { - switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: arg = (reg >> DRIVE_STRENGTH_SHIFT) & DRIVE_STRENGTH_MASK; @@ -500,6 +491,13 @@ static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, SLEEP_PULL_UP_MASK) << 16; arg |= (reg >> PULL_UP_SHIFT) & PULL_UP_MASK; break; + case PIN_CONFIG_BIAS_DISABLE: + if ((reg & (SLEEP_PULL_DOWN | SLEEP_PULL_UP)) || + (reg & (PULL_DOWN | PULL_UP_4_7K | PULL_UP_20K))) + return -EINVAL; + + arg = 1; + break; case PIN_CONFIG_SLEEP_HARDWARE_STATE: arg = 0; break; @@ -614,7 +612,7 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, if (pin->type == GLOBAL_CTRL_PIN && param == SPRD_PIN_CONFIG_CONTROL) { val = arg; - } else if (pin->type == COMMON_PIN) { + } else if (pin->type == COMMON_PIN || pin->type == MISC_PIN) { switch (param) { case SPRD_PIN_CONFIG_SLEEP_MODE: if (arg & AP_SLEEP) @@ -625,6 +623,8 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, val |= TGLDSP_SLEEP_MODE; if (arg & AGDSP_SLEEP) val |= AGDSP_SLEEP_MODE; + if (arg & CM4_SLEEP) + val |= CM4_SLEEP_MODE; mask = SLEEP_MODE_MASK; shift = SLEEP_MODE_SHIFT; @@ -640,20 +640,23 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, shift = SLEEP_INPUT_SHIFT; } break; - case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_OUTPUT_ENABLE: if (is_sleep_config == true) { - val |= SLEEP_OUTPUT; + if (arg > 0) + val |= SLEEP_OUTPUT; + else + val &= ~SLEEP_OUTPUT; + mask = SLEEP_OUTPUT_MASK; shift = SLEEP_OUTPUT_SHIFT; } break; - case PIN_CONFIG_SLEEP_HARDWARE_STATE: - continue; - default: - return -ENOTSUPP; - } - } else if (pin->type == MISC_PIN) { - switch (param) { + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + if (is_sleep_config == true) { + val = shift = 0; + mask = SLEEP_OUTPUT | SLEEP_INPUT; + } + break; case PIN_CONFIG_DRIVE_STRENGTH: if (arg < 2 || arg > 60) return -EINVAL; @@ -683,7 +686,7 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, shift = INPUT_SCHMITT_SHIFT; break; case PIN_CONFIG_BIAS_PULL_UP: - if (is_sleep_config == true) { + if (is_sleep_config) { val |= SLEEP_PULL_UP; mask = SLEEP_PULL_UP_MASK; shift = SLEEP_PULL_UP_SHIFT; @@ -697,6 +700,16 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, shift = PULL_UP_SHIFT; } break; + case PIN_CONFIG_BIAS_DISABLE: + if (is_sleep_config == true) { + val = shift = 0; + mask = SLEEP_PULL_DOWN | SLEEP_PULL_UP; + } else { + val = shift = 0; + mask = PULL_DOWN | PULL_UP_20K | + PULL_UP_4_7K; + } + break; case PIN_CONFIG_SLEEP_HARDWARE_STATE: continue; default: @@ -918,7 +931,6 @@ static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) { struct sprd_pinctrl_soc_info *info = sprd_pctl->info; struct device_node *np = sprd_pctl->dev->of_node; - struct device_node *child, *sub_child; struct sprd_pin_group *grp; const char **temp; int ret; @@ -946,7 +958,7 @@ static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) temp = info->grp_names; grp = info->groups; - for_each_child_of_node(np, child) { + for_each_child_of_node_scoped(np, child) { ret = sprd_pinctrl_parse_groups(child, sprd_pctl, grp); if (ret) return ret; @@ -955,7 +967,7 @@ static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) grp++; if (of_get_child_count(child) > 0) { - for_each_child_of_node(child, sub_child) { + for_each_child_of_node_scoped(child, sub_child) { ret = sprd_pinctrl_parse_groups(sub_child, sprd_pctl, grp); if (ret) @@ -1028,7 +1040,6 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, struct sprd_pinctrl *sprd_pctl; struct sprd_pinctrl_soc_info *pinctrl_info; struct pinctrl_pin_desc *pin_desc; - struct resource *res; int ret, i; sprd_pctl = devm_kzalloc(&pdev->dev, sizeof(struct sprd_pinctrl), @@ -1036,8 +1047,7 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, if (!sprd_pctl) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sprd_pctl->base = devm_ioremap_resource(&pdev->dev, res); + sprd_pctl->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sprd_pctl->base)) return PTR_ERR(sprd_pctl->base); @@ -1089,14 +1099,15 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_core_probe); -int sprd_pinctrl_remove(struct platform_device *pdev) +void sprd_pinctrl_remove(struct platform_device *pdev) { struct sprd_pinctrl *sprd_pctl = platform_get_drvdata(pdev); pinctrl_unregister(sprd_pctl->pctl); - return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_remove); void sprd_pinctrl_shutdown(struct platform_device *pdev) { @@ -1111,6 +1122,7 @@ void sprd_pinctrl_shutdown(struct platform_device *pdev) return; pinctrl_select_state(pinctl, state); } +EXPORT_SYMBOL_GPL(sprd_pinctrl_shutdown); MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); |
