141d32cfcSBaolin Wang /* 241d32cfcSBaolin Wang * Spreadtrum pin controller driver 341d32cfcSBaolin Wang * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com 441d32cfcSBaolin Wang * 541d32cfcSBaolin Wang * This program is free software; you can redistribute it and/or 641d32cfcSBaolin Wang * modify it under the terms of the GNU General Public License 741d32cfcSBaolin Wang * version 2 as published by the Free Software Foundation. 841d32cfcSBaolin Wang * 941d32cfcSBaolin Wang * This program is distributed in the hope that it will be useful, but 1041d32cfcSBaolin Wang * WITHOUT ANY WARRANTY; without even the implied warranty of 1141d32cfcSBaolin Wang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1241d32cfcSBaolin Wang * General Public License for more details. 1341d32cfcSBaolin Wang */ 1441d32cfcSBaolin Wang 1541d32cfcSBaolin Wang #include <linux/debugfs.h> 1641d32cfcSBaolin Wang #include <linux/err.h> 1741d32cfcSBaolin Wang #include <linux/init.h> 1841d32cfcSBaolin Wang #include <linux/io.h> 1941d32cfcSBaolin Wang #include <linux/kernel.h> 2041d32cfcSBaolin Wang #include <linux/module.h> 2141d32cfcSBaolin Wang #include <linux/of.h> 2241d32cfcSBaolin Wang #include <linux/of_device.h> 2341d32cfcSBaolin Wang #include <linux/platform_device.h> 2441d32cfcSBaolin Wang #include <linux/pinctrl/machine.h> 2541d32cfcSBaolin Wang #include <linux/pinctrl/pinconf.h> 2641d32cfcSBaolin Wang #include <linux/pinctrl/pinconf-generic.h> 2741d32cfcSBaolin Wang #include <linux/pinctrl/pinctrl.h> 2841d32cfcSBaolin Wang #include <linux/pinctrl/pinmux.h> 2941d32cfcSBaolin Wang #include <linux/slab.h> 3041d32cfcSBaolin Wang 3141d32cfcSBaolin Wang #include "../core.h" 3241d32cfcSBaolin Wang #include "../pinmux.h" 3341d32cfcSBaolin Wang #include "../pinconf.h" 3441d32cfcSBaolin Wang #include "../pinctrl-utils.h" 3541d32cfcSBaolin Wang #include "pinctrl-sprd.h" 3641d32cfcSBaolin Wang 3741d32cfcSBaolin Wang #define PINCTRL_BIT_MASK(width) (~(~0UL << (width))) 3841d32cfcSBaolin Wang #define PINCTRL_REG_OFFSET 0x20 3941d32cfcSBaolin Wang #define PINCTRL_REG_MISC_OFFSET 0x4020 4041d32cfcSBaolin Wang #define PINCTRL_REG_LEN 0x4 4141d32cfcSBaolin Wang 4241d32cfcSBaolin Wang #define PIN_FUNC_MASK (BIT(4) | BIT(5)) 4341d32cfcSBaolin Wang #define PIN_FUNC_SEL_1 ~PIN_FUNC_MASK 4441d32cfcSBaolin Wang #define PIN_FUNC_SEL_2 BIT(4) 4541d32cfcSBaolin Wang #define PIN_FUNC_SEL_3 BIT(5) 4641d32cfcSBaolin Wang #define PIN_FUNC_SEL_4 PIN_FUNC_MASK 4741d32cfcSBaolin Wang 4841d32cfcSBaolin Wang #define AP_SLEEP_MODE BIT(13) 4941d32cfcSBaolin Wang #define PUBCP_SLEEP_MODE BIT(14) 5041d32cfcSBaolin Wang #define TGLDSP_SLEEP_MODE BIT(15) 5141d32cfcSBaolin Wang #define AGDSP_SLEEP_MODE BIT(16) 5241d32cfcSBaolin Wang #define SLEEP_MODE_MASK GENMASK(3, 0) 5341d32cfcSBaolin Wang #define SLEEP_MODE_SHIFT 13 5441d32cfcSBaolin Wang 5541d32cfcSBaolin Wang #define SLEEP_INPUT BIT(1) 5641d32cfcSBaolin Wang #define SLEEP_INPUT_MASK 0x1 5741d32cfcSBaolin Wang #define SLEEP_INPUT_SHIFT 1 5841d32cfcSBaolin Wang 5941d32cfcSBaolin Wang #define SLEEP_OUTPUT BIT(0) 6041d32cfcSBaolin Wang #define SLEEP_OUTPUT_MASK 0x1 6141d32cfcSBaolin Wang #define SLEEP_OUTPUT_SHIFT 0 6241d32cfcSBaolin Wang 6341d32cfcSBaolin Wang #define DRIVE_STRENGTH_MASK GENMASK(3, 0) 6441d32cfcSBaolin Wang #define DRIVE_STRENGTH_SHIFT 19 6541d32cfcSBaolin Wang 6641d32cfcSBaolin Wang #define SLEEP_PULL_DOWN BIT(2) 6741d32cfcSBaolin Wang #define SLEEP_PULL_DOWN_MASK 0x1 6841d32cfcSBaolin Wang #define SLEEP_PULL_DOWN_SHIFT 2 6941d32cfcSBaolin Wang 7041d32cfcSBaolin Wang #define PULL_DOWN BIT(6) 7141d32cfcSBaolin Wang #define PULL_DOWN_MASK 0x1 7241d32cfcSBaolin Wang #define PULL_DOWN_SHIFT 6 7341d32cfcSBaolin Wang 7441d32cfcSBaolin Wang #define SLEEP_PULL_UP BIT(3) 7541d32cfcSBaolin Wang #define SLEEP_PULL_UP_MASK 0x1 7641d32cfcSBaolin Wang #define SLEEP_PULL_UP_SHIFT 3 7741d32cfcSBaolin Wang 7841d32cfcSBaolin Wang #define PULL_UP_20K (BIT(12) | BIT(7)) 7941d32cfcSBaolin Wang #define PULL_UP_4_7K BIT(12) 8041d32cfcSBaolin Wang #define PULL_UP_MASK 0x21 8141d32cfcSBaolin Wang #define PULL_UP_SHIFT 7 8241d32cfcSBaolin Wang 8341d32cfcSBaolin Wang #define INPUT_SCHMITT BIT(11) 8441d32cfcSBaolin Wang #define INPUT_SCHMITT_MASK 0x1 8541d32cfcSBaolin Wang #define INPUT_SCHMITT_SHIFT 11 8641d32cfcSBaolin Wang 8741d32cfcSBaolin Wang enum pin_sleep_mode { 8841d32cfcSBaolin Wang AP_SLEEP = BIT(0), 8941d32cfcSBaolin Wang PUBCP_SLEEP = BIT(1), 9041d32cfcSBaolin Wang TGLDSP_SLEEP = BIT(2), 9141d32cfcSBaolin Wang AGDSP_SLEEP = BIT(3), 9241d32cfcSBaolin Wang }; 9341d32cfcSBaolin Wang 9441d32cfcSBaolin Wang enum pin_func_sel { 9541d32cfcSBaolin Wang PIN_FUNC_1, 9641d32cfcSBaolin Wang PIN_FUNC_2, 9741d32cfcSBaolin Wang PIN_FUNC_3, 9841d32cfcSBaolin Wang PIN_FUNC_4, 9941d32cfcSBaolin Wang PIN_FUNC_MAX, 10041d32cfcSBaolin Wang }; 10141d32cfcSBaolin Wang 10241d32cfcSBaolin Wang /** 10341d32cfcSBaolin Wang * struct sprd_pin: represent one pin's description 10441d32cfcSBaolin Wang * @name: pin name 10541d32cfcSBaolin Wang * @number: pin number 10641d32cfcSBaolin Wang * @type: pin type, can be GLOBAL_CTRL_PIN/COMMON_PIN/MISC_PIN 10741d32cfcSBaolin Wang * @reg: pin register address 10841d32cfcSBaolin Wang * @bit_offset: bit offset in pin register 10941d32cfcSBaolin Wang * @bit_width: bit width in pin register 11041d32cfcSBaolin Wang */ 11141d32cfcSBaolin Wang struct sprd_pin { 11241d32cfcSBaolin Wang const char *name; 11341d32cfcSBaolin Wang unsigned int number; 11441d32cfcSBaolin Wang enum pin_type type; 11541d32cfcSBaolin Wang unsigned long reg; 11641d32cfcSBaolin Wang unsigned long bit_offset; 11741d32cfcSBaolin Wang unsigned long bit_width; 11841d32cfcSBaolin Wang }; 11941d32cfcSBaolin Wang 12041d32cfcSBaolin Wang /** 12141d32cfcSBaolin Wang * struct sprd_pin_group: represent one group's description 12241d32cfcSBaolin Wang * @name: group name 12341d32cfcSBaolin Wang * @npins: pin numbers of this group 12441d32cfcSBaolin Wang * @pins: pointer to pins array 12541d32cfcSBaolin Wang */ 12641d32cfcSBaolin Wang struct sprd_pin_group { 12741d32cfcSBaolin Wang const char *name; 12841d32cfcSBaolin Wang unsigned int npins; 12941d32cfcSBaolin Wang unsigned int *pins; 13041d32cfcSBaolin Wang }; 13141d32cfcSBaolin Wang 13241d32cfcSBaolin Wang /** 13341d32cfcSBaolin Wang * struct sprd_pinctrl_soc_info: represent the SoC's pins description 13441d32cfcSBaolin Wang * @groups: pointer to groups of pins 13541d32cfcSBaolin Wang * @ngroups: group numbers of the whole SoC 13641d32cfcSBaolin Wang * @pins: pointer to pins description 13741d32cfcSBaolin Wang * @npins: pin numbers of the whole SoC 13841d32cfcSBaolin Wang * @grp_names: pointer to group names array 13941d32cfcSBaolin Wang */ 14041d32cfcSBaolin Wang struct sprd_pinctrl_soc_info { 14141d32cfcSBaolin Wang struct sprd_pin_group *groups; 14241d32cfcSBaolin Wang unsigned int ngroups; 14341d32cfcSBaolin Wang struct sprd_pin *pins; 14441d32cfcSBaolin Wang unsigned int npins; 14541d32cfcSBaolin Wang const char **grp_names; 14641d32cfcSBaolin Wang }; 14741d32cfcSBaolin Wang 14841d32cfcSBaolin Wang /** 14941d32cfcSBaolin Wang * struct sprd_pinctrl: represent the pin controller device 15041d32cfcSBaolin Wang * @dev: pointer to the device structure 15141d32cfcSBaolin Wang * @pctl: pointer to the pinctrl handle 15241d32cfcSBaolin Wang * @base: base address of the controller 15341d32cfcSBaolin Wang * @info: pointer to SoC's pins description information 15441d32cfcSBaolin Wang */ 15541d32cfcSBaolin Wang struct sprd_pinctrl { 15641d32cfcSBaolin Wang struct device *dev; 15741d32cfcSBaolin Wang struct pinctrl_dev *pctl; 15841d32cfcSBaolin Wang void __iomem *base; 15941d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info; 16041d32cfcSBaolin Wang }; 16141d32cfcSBaolin Wang 16241d32cfcSBaolin Wang enum sprd_pinconf_params { 16341d32cfcSBaolin Wang SPRD_PIN_CONFIG_CONTROL = PIN_CONFIG_END + 1, 16441d32cfcSBaolin Wang SPRD_PIN_CONFIG_SLEEP_MODE = PIN_CONFIG_END + 2, 16541d32cfcSBaolin Wang }; 16641d32cfcSBaolin Wang 16741d32cfcSBaolin Wang static int sprd_pinctrl_get_id_by_name(struct sprd_pinctrl *sprd_pctl, 16841d32cfcSBaolin Wang const char *name) 16941d32cfcSBaolin Wang { 17041d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = sprd_pctl->info; 17141d32cfcSBaolin Wang int i; 17241d32cfcSBaolin Wang 17341d32cfcSBaolin Wang for (i = 0; i < info->npins; i++) { 17441d32cfcSBaolin Wang if (!strcmp(info->pins[i].name, name)) 17541d32cfcSBaolin Wang return info->pins[i].number; 17641d32cfcSBaolin Wang } 17741d32cfcSBaolin Wang 17841d32cfcSBaolin Wang return -ENODEV; 17941d32cfcSBaolin Wang } 18041d32cfcSBaolin Wang 18141d32cfcSBaolin Wang static struct sprd_pin * 18241d32cfcSBaolin Wang sprd_pinctrl_get_pin_by_id(struct sprd_pinctrl *sprd_pctl, unsigned int id) 18341d32cfcSBaolin Wang { 18441d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = sprd_pctl->info; 18541d32cfcSBaolin Wang struct sprd_pin *pin = NULL; 18641d32cfcSBaolin Wang int i; 18741d32cfcSBaolin Wang 18841d32cfcSBaolin Wang for (i = 0; i < info->npins; i++) { 18941d32cfcSBaolin Wang if (info->pins[i].number == id) { 19041d32cfcSBaolin Wang pin = &info->pins[i]; 19141d32cfcSBaolin Wang break; 19241d32cfcSBaolin Wang } 19341d32cfcSBaolin Wang } 19441d32cfcSBaolin Wang 19541d32cfcSBaolin Wang return pin; 19641d32cfcSBaolin Wang } 19741d32cfcSBaolin Wang 19841d32cfcSBaolin Wang static const struct sprd_pin_group * 19941d32cfcSBaolin Wang sprd_pinctrl_find_group_by_name(struct sprd_pinctrl *sprd_pctl, 20041d32cfcSBaolin Wang const char *name) 20141d32cfcSBaolin Wang { 20241d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = sprd_pctl->info; 20341d32cfcSBaolin Wang const struct sprd_pin_group *grp = NULL; 20441d32cfcSBaolin Wang int i; 20541d32cfcSBaolin Wang 20641d32cfcSBaolin Wang for (i = 0; i < info->ngroups; i++) { 20741d32cfcSBaolin Wang if (!strcmp(info->groups[i].name, name)) { 20841d32cfcSBaolin Wang grp = &info->groups[i]; 20941d32cfcSBaolin Wang break; 21041d32cfcSBaolin Wang } 21141d32cfcSBaolin Wang } 21241d32cfcSBaolin Wang 21341d32cfcSBaolin Wang return grp; 21441d32cfcSBaolin Wang } 21541d32cfcSBaolin Wang 21641d32cfcSBaolin Wang static int sprd_pctrl_group_count(struct pinctrl_dev *pctldev) 21741d32cfcSBaolin Wang { 21841d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 21941d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 22041d32cfcSBaolin Wang 22141d32cfcSBaolin Wang return info->ngroups; 22241d32cfcSBaolin Wang } 22341d32cfcSBaolin Wang 22441d32cfcSBaolin Wang static const char *sprd_pctrl_group_name(struct pinctrl_dev *pctldev, 22541d32cfcSBaolin Wang unsigned int selector) 22641d32cfcSBaolin Wang { 22741d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 22841d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 22941d32cfcSBaolin Wang 23041d32cfcSBaolin Wang return info->groups[selector].name; 23141d32cfcSBaolin Wang } 23241d32cfcSBaolin Wang 23341d32cfcSBaolin Wang static int sprd_pctrl_group_pins(struct pinctrl_dev *pctldev, 23441d32cfcSBaolin Wang unsigned int selector, 23541d32cfcSBaolin Wang const unsigned int **pins, 23641d32cfcSBaolin Wang unsigned int *npins) 23741d32cfcSBaolin Wang { 23841d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 23941d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 24041d32cfcSBaolin Wang 24141d32cfcSBaolin Wang if (selector >= info->ngroups) 24241d32cfcSBaolin Wang return -EINVAL; 24341d32cfcSBaolin Wang 24441d32cfcSBaolin Wang *pins = info->groups[selector].pins; 24541d32cfcSBaolin Wang *npins = info->groups[selector].npins; 24641d32cfcSBaolin Wang 24741d32cfcSBaolin Wang return 0; 24841d32cfcSBaolin Wang } 24941d32cfcSBaolin Wang 25041d32cfcSBaolin Wang static int sprd_dt_node_to_map(struct pinctrl_dev *pctldev, 25141d32cfcSBaolin Wang struct device_node *np, 25241d32cfcSBaolin Wang struct pinctrl_map **map, 25341d32cfcSBaolin Wang unsigned int *num_maps) 25441d32cfcSBaolin Wang { 25541d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 25641d32cfcSBaolin Wang const struct sprd_pin_group *grp; 25741d32cfcSBaolin Wang unsigned long *configs = NULL; 25841d32cfcSBaolin Wang unsigned int num_configs = 0; 25941d32cfcSBaolin Wang unsigned int reserved_maps = 0; 26041d32cfcSBaolin Wang unsigned int reserve = 0; 26141d32cfcSBaolin Wang const char *function; 26241d32cfcSBaolin Wang enum pinctrl_map_type type; 26341d32cfcSBaolin Wang int ret; 26441d32cfcSBaolin Wang 26541d32cfcSBaolin Wang grp = sprd_pinctrl_find_group_by_name(pctl, np->name); 26641d32cfcSBaolin Wang if (!grp) { 26741d32cfcSBaolin Wang dev_err(pctl->dev, "unable to find group for node %s\n", 26841d32cfcSBaolin Wang of_node_full_name(np)); 26941d32cfcSBaolin Wang return -EINVAL; 27041d32cfcSBaolin Wang } 27141d32cfcSBaolin Wang 27241d32cfcSBaolin Wang ret = of_property_count_strings(np, "pins"); 27341d32cfcSBaolin Wang if (ret < 0) 27441d32cfcSBaolin Wang return ret; 27541d32cfcSBaolin Wang 27641d32cfcSBaolin Wang if (ret == 1) 27741d32cfcSBaolin Wang type = PIN_MAP_TYPE_CONFIGS_PIN; 27841d32cfcSBaolin Wang else 27941d32cfcSBaolin Wang type = PIN_MAP_TYPE_CONFIGS_GROUP; 28041d32cfcSBaolin Wang 28141d32cfcSBaolin Wang ret = of_property_read_string(np, "function", &function); 28241d32cfcSBaolin Wang if (ret < 0) { 28341d32cfcSBaolin Wang if (ret != -EINVAL) 28441d32cfcSBaolin Wang dev_err(pctl->dev, 28541d32cfcSBaolin Wang "%s: could not parse property function\n", 28641d32cfcSBaolin Wang of_node_full_name(np)); 28741d32cfcSBaolin Wang function = NULL; 28841d32cfcSBaolin Wang } 28941d32cfcSBaolin Wang 29041d32cfcSBaolin Wang ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, 29141d32cfcSBaolin Wang &num_configs); 29241d32cfcSBaolin Wang if (ret < 0) { 29341d32cfcSBaolin Wang dev_err(pctl->dev, "%s: could not parse node property\n", 29441d32cfcSBaolin Wang of_node_full_name(np)); 29541d32cfcSBaolin Wang return ret; 29641d32cfcSBaolin Wang } 29741d32cfcSBaolin Wang 29841d32cfcSBaolin Wang *map = NULL; 29941d32cfcSBaolin Wang *num_maps = 0; 30041d32cfcSBaolin Wang 30141d32cfcSBaolin Wang if (function != NULL) 30241d32cfcSBaolin Wang reserve++; 30341d32cfcSBaolin Wang if (num_configs) 30441d32cfcSBaolin Wang reserve++; 30541d32cfcSBaolin Wang 30641d32cfcSBaolin Wang ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, 30741d32cfcSBaolin Wang num_maps, reserve); 30841d32cfcSBaolin Wang if (ret < 0) 30941d32cfcSBaolin Wang goto out; 31041d32cfcSBaolin Wang 31141d32cfcSBaolin Wang if (function) { 31241d32cfcSBaolin Wang ret = pinctrl_utils_add_map_mux(pctldev, map, 31341d32cfcSBaolin Wang &reserved_maps, num_maps, 31441d32cfcSBaolin Wang grp->name, function); 31541d32cfcSBaolin Wang if (ret < 0) 31641d32cfcSBaolin Wang goto out; 31741d32cfcSBaolin Wang } 31841d32cfcSBaolin Wang 31941d32cfcSBaolin Wang if (num_configs) { 32041d32cfcSBaolin Wang const char *group_or_pin; 32141d32cfcSBaolin Wang unsigned int pin_id; 32241d32cfcSBaolin Wang 32341d32cfcSBaolin Wang if (type == PIN_MAP_TYPE_CONFIGS_PIN) { 32441d32cfcSBaolin Wang pin_id = grp->pins[0]; 32541d32cfcSBaolin Wang group_or_pin = pin_get_name(pctldev, pin_id); 32641d32cfcSBaolin Wang } else { 32741d32cfcSBaolin Wang group_or_pin = grp->name; 32841d32cfcSBaolin Wang } 32941d32cfcSBaolin Wang 33041d32cfcSBaolin Wang ret = pinctrl_utils_add_map_configs(pctldev, map, 33141d32cfcSBaolin Wang &reserved_maps, num_maps, 33241d32cfcSBaolin Wang group_or_pin, configs, 33341d32cfcSBaolin Wang num_configs, type); 33441d32cfcSBaolin Wang } 33541d32cfcSBaolin Wang 33641d32cfcSBaolin Wang out: 33741d32cfcSBaolin Wang kfree(configs); 33841d32cfcSBaolin Wang return ret; 33941d32cfcSBaolin Wang } 34041d32cfcSBaolin Wang 34141d32cfcSBaolin Wang static void sprd_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 34241d32cfcSBaolin Wang unsigned int offset) 34341d32cfcSBaolin Wang { 34441d32cfcSBaolin Wang seq_printf(s, "%s", dev_name(pctldev->dev)); 34541d32cfcSBaolin Wang } 34641d32cfcSBaolin Wang 34741d32cfcSBaolin Wang static const struct pinctrl_ops sprd_pctrl_ops = { 34841d32cfcSBaolin Wang .get_groups_count = sprd_pctrl_group_count, 34941d32cfcSBaolin Wang .get_group_name = sprd_pctrl_group_name, 35041d32cfcSBaolin Wang .get_group_pins = sprd_pctrl_group_pins, 35141d32cfcSBaolin Wang .pin_dbg_show = sprd_pctrl_dbg_show, 35241d32cfcSBaolin Wang .dt_node_to_map = sprd_dt_node_to_map, 35341d32cfcSBaolin Wang .dt_free_map = pinctrl_utils_free_map, 35441d32cfcSBaolin Wang }; 35541d32cfcSBaolin Wang 356045b5792SColin Ian King static int sprd_pmx_get_function_count(struct pinctrl_dev *pctldev) 35741d32cfcSBaolin Wang { 35841d32cfcSBaolin Wang return PIN_FUNC_MAX; 35941d32cfcSBaolin Wang } 36041d32cfcSBaolin Wang 361045b5792SColin Ian King static const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev, 36241d32cfcSBaolin Wang unsigned int selector) 36341d32cfcSBaolin Wang { 36441d32cfcSBaolin Wang switch (selector) { 36541d32cfcSBaolin Wang case PIN_FUNC_1: 36641d32cfcSBaolin Wang return "func1"; 36741d32cfcSBaolin Wang case PIN_FUNC_2: 36841d32cfcSBaolin Wang return "func2"; 36941d32cfcSBaolin Wang case PIN_FUNC_3: 37041d32cfcSBaolin Wang return "func3"; 37141d32cfcSBaolin Wang case PIN_FUNC_4: 37241d32cfcSBaolin Wang return "func4"; 37341d32cfcSBaolin Wang default: 37441d32cfcSBaolin Wang return "null"; 37541d32cfcSBaolin Wang } 37641d32cfcSBaolin Wang } 37741d32cfcSBaolin Wang 378045b5792SColin Ian King static int sprd_pmx_get_function_groups(struct pinctrl_dev *pctldev, 37941d32cfcSBaolin Wang unsigned int selector, 38041d32cfcSBaolin Wang const char * const **groups, 38141d32cfcSBaolin Wang unsigned int * const num_groups) 38241d32cfcSBaolin Wang { 38341d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 38441d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 38541d32cfcSBaolin Wang 38641d32cfcSBaolin Wang *groups = info->grp_names; 38741d32cfcSBaolin Wang *num_groups = info->ngroups; 38841d32cfcSBaolin Wang 38941d32cfcSBaolin Wang return 0; 39041d32cfcSBaolin Wang } 39141d32cfcSBaolin Wang 39241d32cfcSBaolin Wang static int sprd_pmx_set_mux(struct pinctrl_dev *pctldev, 39341d32cfcSBaolin Wang unsigned int func_selector, 39441d32cfcSBaolin Wang unsigned int group_selector) 39541d32cfcSBaolin Wang { 39641d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 39741d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 39841d32cfcSBaolin Wang struct sprd_pin_group *grp = &info->groups[group_selector]; 39941d32cfcSBaolin Wang unsigned int i, grp_pins = grp->npins; 40041d32cfcSBaolin Wang unsigned long reg; 40141d32cfcSBaolin Wang unsigned int val = 0; 40241d32cfcSBaolin Wang 4034ce504c4SDan Carpenter if (group_selector >= info->ngroups) 40441d32cfcSBaolin Wang return -EINVAL; 40541d32cfcSBaolin Wang 40641d32cfcSBaolin Wang switch (func_selector) { 40741d32cfcSBaolin Wang case PIN_FUNC_1: 40841d32cfcSBaolin Wang val &= PIN_FUNC_SEL_1; 40941d32cfcSBaolin Wang break; 41041d32cfcSBaolin Wang case PIN_FUNC_2: 41141d32cfcSBaolin Wang val |= PIN_FUNC_SEL_2; 41241d32cfcSBaolin Wang break; 41341d32cfcSBaolin Wang case PIN_FUNC_3: 41441d32cfcSBaolin Wang val |= PIN_FUNC_SEL_3; 41541d32cfcSBaolin Wang break; 41641d32cfcSBaolin Wang case PIN_FUNC_4: 41741d32cfcSBaolin Wang val |= PIN_FUNC_SEL_4; 41841d32cfcSBaolin Wang break; 41941d32cfcSBaolin Wang default: 42041d32cfcSBaolin Wang break; 42141d32cfcSBaolin Wang } 42241d32cfcSBaolin Wang 42341d32cfcSBaolin Wang for (i = 0; i < grp_pins; i++) { 42441d32cfcSBaolin Wang unsigned int pin_id = grp->pins[i]; 42541d32cfcSBaolin Wang struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(pctl, pin_id); 42641d32cfcSBaolin Wang 42741d32cfcSBaolin Wang if (!pin || pin->type != COMMON_PIN) 42841d32cfcSBaolin Wang continue; 42941d32cfcSBaolin Wang 43041d32cfcSBaolin Wang reg = readl((void __iomem *)pin->reg); 43141d32cfcSBaolin Wang reg &= ~PIN_FUNC_MASK; 43241d32cfcSBaolin Wang reg |= val; 43341d32cfcSBaolin Wang writel(reg, (void __iomem *)pin->reg); 43441d32cfcSBaolin Wang } 43541d32cfcSBaolin Wang 43641d32cfcSBaolin Wang return 0; 43741d32cfcSBaolin Wang } 43841d32cfcSBaolin Wang 43941d32cfcSBaolin Wang static const struct pinmux_ops sprd_pmx_ops = { 44041d32cfcSBaolin Wang .get_functions_count = sprd_pmx_get_function_count, 44141d32cfcSBaolin Wang .get_function_name = sprd_pmx_get_function_name, 44241d32cfcSBaolin Wang .get_function_groups = sprd_pmx_get_function_groups, 44341d32cfcSBaolin Wang .set_mux = sprd_pmx_set_mux, 44441d32cfcSBaolin Wang }; 44541d32cfcSBaolin Wang 44641d32cfcSBaolin Wang static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, 44741d32cfcSBaolin Wang unsigned long *config) 44841d32cfcSBaolin Wang { 44941d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 45041d32cfcSBaolin Wang struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(pctl, pin_id); 45141d32cfcSBaolin Wang unsigned int param = pinconf_to_config_param(*config); 45241d32cfcSBaolin Wang unsigned int reg, arg; 45341d32cfcSBaolin Wang 45441d32cfcSBaolin Wang if (!pin) 45541d32cfcSBaolin Wang return -EINVAL; 45641d32cfcSBaolin Wang 45741d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN) { 45841d32cfcSBaolin Wang reg = (readl((void __iomem *)pin->reg) >> 45941d32cfcSBaolin Wang pin->bit_offset) & PINCTRL_BIT_MASK(pin->bit_width); 46041d32cfcSBaolin Wang } else { 46141d32cfcSBaolin Wang reg = readl((void __iomem *)pin->reg); 46241d32cfcSBaolin Wang } 46341d32cfcSBaolin Wang 46441d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN && 46541d32cfcSBaolin Wang param == SPRD_PIN_CONFIG_CONTROL) { 46641d32cfcSBaolin Wang arg = reg; 46741d32cfcSBaolin Wang } else if (pin->type == COMMON_PIN) { 46841d32cfcSBaolin Wang switch (param) { 46941d32cfcSBaolin Wang case SPRD_PIN_CONFIG_SLEEP_MODE: 47041d32cfcSBaolin Wang arg = (reg >> SLEEP_MODE_SHIFT) & SLEEP_MODE_MASK; 47141d32cfcSBaolin Wang break; 47241d32cfcSBaolin Wang case PIN_CONFIG_INPUT_ENABLE: 47341d32cfcSBaolin Wang arg = (reg >> SLEEP_INPUT_SHIFT) & SLEEP_INPUT_MASK; 47441d32cfcSBaolin Wang break; 47541d32cfcSBaolin Wang case PIN_CONFIG_OUTPUT: 47641d32cfcSBaolin Wang arg = reg & SLEEP_OUTPUT_MASK; 47741d32cfcSBaolin Wang break; 47841d32cfcSBaolin Wang case PIN_CONFIG_SLEEP_HARDWARE_STATE: 47941d32cfcSBaolin Wang arg = 0; 48041d32cfcSBaolin Wang break; 48141d32cfcSBaolin Wang default: 48241d32cfcSBaolin Wang return -ENOTSUPP; 48341d32cfcSBaolin Wang } 48441d32cfcSBaolin Wang } else if (pin->type == MISC_PIN) { 48541d32cfcSBaolin Wang switch (param) { 48641d32cfcSBaolin Wang case PIN_CONFIG_DRIVE_STRENGTH: 48741d32cfcSBaolin Wang arg = (reg >> DRIVE_STRENGTH_SHIFT) & 48841d32cfcSBaolin Wang DRIVE_STRENGTH_MASK; 48941d32cfcSBaolin Wang break; 49041d32cfcSBaolin Wang case PIN_CONFIG_BIAS_PULL_DOWN: 49141d32cfcSBaolin Wang /* combine sleep pull down and pull down config */ 49241d32cfcSBaolin Wang arg = ((reg >> SLEEP_PULL_DOWN_SHIFT) & 49341d32cfcSBaolin Wang SLEEP_PULL_DOWN_MASK) << 16; 49441d32cfcSBaolin Wang arg |= (reg >> PULL_DOWN_SHIFT) & PULL_DOWN_MASK; 49541d32cfcSBaolin Wang break; 49641d32cfcSBaolin Wang case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 49741d32cfcSBaolin Wang arg = (reg >> INPUT_SCHMITT_SHIFT) & INPUT_SCHMITT_MASK; 49841d32cfcSBaolin Wang break; 49941d32cfcSBaolin Wang case PIN_CONFIG_BIAS_PULL_UP: 50041d32cfcSBaolin Wang /* combine sleep pull up and pull up config */ 50141d32cfcSBaolin Wang arg = ((reg >> SLEEP_PULL_UP_SHIFT) & 50241d32cfcSBaolin Wang SLEEP_PULL_UP_MASK) << 16; 50341d32cfcSBaolin Wang arg |= (reg >> PULL_UP_SHIFT) & PULL_UP_MASK; 50441d32cfcSBaolin Wang break; 50541d32cfcSBaolin Wang case PIN_CONFIG_SLEEP_HARDWARE_STATE: 50641d32cfcSBaolin Wang arg = 0; 50741d32cfcSBaolin Wang break; 50841d32cfcSBaolin Wang default: 50941d32cfcSBaolin Wang return -ENOTSUPP; 51041d32cfcSBaolin Wang } 51141d32cfcSBaolin Wang } else { 51241d32cfcSBaolin Wang return -ENOTSUPP; 51341d32cfcSBaolin Wang } 51441d32cfcSBaolin Wang 51541d32cfcSBaolin Wang *config = pinconf_to_config_packed(param, arg); 51641d32cfcSBaolin Wang return 0; 51741d32cfcSBaolin Wang } 51841d32cfcSBaolin Wang 51941d32cfcSBaolin Wang static unsigned int sprd_pinconf_drive(unsigned int mA) 52041d32cfcSBaolin Wang { 52141d32cfcSBaolin Wang unsigned int val = 0; 52241d32cfcSBaolin Wang 52341d32cfcSBaolin Wang switch (mA) { 52441d32cfcSBaolin Wang case 2: 52541d32cfcSBaolin Wang break; 52641d32cfcSBaolin Wang case 4: 52741d32cfcSBaolin Wang val |= BIT(19); 52841d32cfcSBaolin Wang break; 52941d32cfcSBaolin Wang case 6: 53041d32cfcSBaolin Wang val |= BIT(20); 53141d32cfcSBaolin Wang break; 53241d32cfcSBaolin Wang case 8: 53341d32cfcSBaolin Wang val |= BIT(19) | BIT(20); 53441d32cfcSBaolin Wang break; 53541d32cfcSBaolin Wang case 10: 53641d32cfcSBaolin Wang val |= BIT(21); 53741d32cfcSBaolin Wang break; 53841d32cfcSBaolin Wang case 12: 53941d32cfcSBaolin Wang val |= BIT(21) | BIT(19); 54041d32cfcSBaolin Wang break; 54141d32cfcSBaolin Wang case 14: 54241d32cfcSBaolin Wang val |= BIT(21) | BIT(20); 54341d32cfcSBaolin Wang break; 54441d32cfcSBaolin Wang case 16: 54541d32cfcSBaolin Wang val |= BIT(19) | BIT(20) | BIT(21); 54641d32cfcSBaolin Wang break; 54741d32cfcSBaolin Wang case 20: 54841d32cfcSBaolin Wang val |= BIT(22); 54941d32cfcSBaolin Wang break; 55041d32cfcSBaolin Wang case 21: 55141d32cfcSBaolin Wang val |= BIT(22) | BIT(19); 55241d32cfcSBaolin Wang break; 55341d32cfcSBaolin Wang case 24: 55441d32cfcSBaolin Wang val |= BIT(22) | BIT(20); 55541d32cfcSBaolin Wang break; 55641d32cfcSBaolin Wang case 25: 55741d32cfcSBaolin Wang val |= BIT(22) | BIT(20) | BIT(19); 55841d32cfcSBaolin Wang break; 55941d32cfcSBaolin Wang case 27: 56041d32cfcSBaolin Wang val |= BIT(22) | BIT(21); 56141d32cfcSBaolin Wang break; 56241d32cfcSBaolin Wang case 29: 56341d32cfcSBaolin Wang val |= BIT(22) | BIT(21) | BIT(19); 56441d32cfcSBaolin Wang break; 56541d32cfcSBaolin Wang case 31: 56641d32cfcSBaolin Wang val |= BIT(22) | BIT(21) | BIT(20); 56741d32cfcSBaolin Wang break; 56841d32cfcSBaolin Wang case 33: 56941d32cfcSBaolin Wang val |= BIT(22) | BIT(21) | BIT(20) | BIT(19); 57041d32cfcSBaolin Wang break; 57141d32cfcSBaolin Wang default: 57241d32cfcSBaolin Wang break; 57341d32cfcSBaolin Wang } 57441d32cfcSBaolin Wang 57541d32cfcSBaolin Wang return val; 57641d32cfcSBaolin Wang } 57741d32cfcSBaolin Wang 57841d32cfcSBaolin Wang static bool sprd_pinctrl_check_sleep_config(unsigned long *configs, 57941d32cfcSBaolin Wang unsigned int num_configs) 58041d32cfcSBaolin Wang { 58141d32cfcSBaolin Wang unsigned int param; 58241d32cfcSBaolin Wang int i; 58341d32cfcSBaolin Wang 58441d32cfcSBaolin Wang for (i = 0; i < num_configs; i++) { 58541d32cfcSBaolin Wang param = pinconf_to_config_param(configs[i]); 58641d32cfcSBaolin Wang if (param == PIN_CONFIG_SLEEP_HARDWARE_STATE) 58741d32cfcSBaolin Wang return true; 58841d32cfcSBaolin Wang } 58941d32cfcSBaolin Wang 59041d32cfcSBaolin Wang return false; 59141d32cfcSBaolin Wang } 59241d32cfcSBaolin Wang 59341d32cfcSBaolin Wang static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, 59441d32cfcSBaolin Wang unsigned long *configs, unsigned int num_configs) 59541d32cfcSBaolin Wang { 59641d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 59741d32cfcSBaolin Wang struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(pctl, pin_id); 59841d32cfcSBaolin Wang bool is_sleep_config; 59941d32cfcSBaolin Wang unsigned long reg; 60041d32cfcSBaolin Wang int i; 60141d32cfcSBaolin Wang 60241d32cfcSBaolin Wang if (!pin) 60341d32cfcSBaolin Wang return -EINVAL; 60441d32cfcSBaolin Wang 60541d32cfcSBaolin Wang is_sleep_config = sprd_pinctrl_check_sleep_config(configs, num_configs); 60641d32cfcSBaolin Wang 60741d32cfcSBaolin Wang for (i = 0; i < num_configs; i++) { 60841d32cfcSBaolin Wang unsigned int param, arg, shift, mask, val; 60941d32cfcSBaolin Wang 61041d32cfcSBaolin Wang param = pinconf_to_config_param(configs[i]); 61141d32cfcSBaolin Wang arg = pinconf_to_config_argument(configs[i]); 61241d32cfcSBaolin Wang 61341d32cfcSBaolin Wang val = 0; 61441d32cfcSBaolin Wang shift = 0; 61541d32cfcSBaolin Wang mask = 0; 61641d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN && 61741d32cfcSBaolin Wang param == SPRD_PIN_CONFIG_CONTROL) { 61841d32cfcSBaolin Wang val = arg; 61941d32cfcSBaolin Wang } else if (pin->type == COMMON_PIN) { 62041d32cfcSBaolin Wang switch (param) { 62141d32cfcSBaolin Wang case SPRD_PIN_CONFIG_SLEEP_MODE: 62241d32cfcSBaolin Wang if (arg & AP_SLEEP) 62341d32cfcSBaolin Wang val |= AP_SLEEP_MODE; 62441d32cfcSBaolin Wang if (arg & PUBCP_SLEEP) 62541d32cfcSBaolin Wang val |= PUBCP_SLEEP_MODE; 62641d32cfcSBaolin Wang if (arg & TGLDSP_SLEEP) 62741d32cfcSBaolin Wang val |= TGLDSP_SLEEP_MODE; 62841d32cfcSBaolin Wang if (arg & AGDSP_SLEEP) 62941d32cfcSBaolin Wang val |= AGDSP_SLEEP_MODE; 63041d32cfcSBaolin Wang 63141d32cfcSBaolin Wang mask = SLEEP_MODE_MASK; 63241d32cfcSBaolin Wang shift = SLEEP_MODE_SHIFT; 63341d32cfcSBaolin Wang break; 63441d32cfcSBaolin Wang case PIN_CONFIG_INPUT_ENABLE: 63541d32cfcSBaolin Wang if (is_sleep_config == true) { 63641d32cfcSBaolin Wang if (arg > 0) 63741d32cfcSBaolin Wang val |= SLEEP_INPUT; 63841d32cfcSBaolin Wang else 63941d32cfcSBaolin Wang val &= ~SLEEP_INPUT; 64041d32cfcSBaolin Wang 64141d32cfcSBaolin Wang mask = SLEEP_INPUT_MASK; 64241d32cfcSBaolin Wang shift = SLEEP_INPUT_SHIFT; 64341d32cfcSBaolin Wang } 64441d32cfcSBaolin Wang break; 64541d32cfcSBaolin Wang case PIN_CONFIG_OUTPUT: 64641d32cfcSBaolin Wang if (is_sleep_config == true) { 64741d32cfcSBaolin Wang val |= SLEEP_OUTPUT; 64841d32cfcSBaolin Wang mask = SLEEP_OUTPUT_MASK; 64941d32cfcSBaolin Wang shift = SLEEP_OUTPUT_SHIFT; 65041d32cfcSBaolin Wang } 65141d32cfcSBaolin Wang break; 65241d32cfcSBaolin Wang case PIN_CONFIG_SLEEP_HARDWARE_STATE: 65341d32cfcSBaolin Wang continue; 65441d32cfcSBaolin Wang default: 65541d32cfcSBaolin Wang return -ENOTSUPP; 65641d32cfcSBaolin Wang } 65741d32cfcSBaolin Wang } else if (pin->type == MISC_PIN) { 65841d32cfcSBaolin Wang switch (param) { 65941d32cfcSBaolin Wang case PIN_CONFIG_DRIVE_STRENGTH: 66041d32cfcSBaolin Wang if (arg < 2 || arg > 60) 66141d32cfcSBaolin Wang return -EINVAL; 66241d32cfcSBaolin Wang 66341d32cfcSBaolin Wang val = sprd_pinconf_drive(arg); 66441d32cfcSBaolin Wang mask = DRIVE_STRENGTH_MASK; 66541d32cfcSBaolin Wang shift = DRIVE_STRENGTH_SHIFT; 66641d32cfcSBaolin Wang break; 66741d32cfcSBaolin Wang case PIN_CONFIG_BIAS_PULL_DOWN: 66841d32cfcSBaolin Wang if (is_sleep_config == true) { 66941d32cfcSBaolin Wang val |= SLEEP_PULL_DOWN; 67041d32cfcSBaolin Wang mask = SLEEP_PULL_DOWN_MASK; 67141d32cfcSBaolin Wang shift = SLEEP_PULL_DOWN_SHIFT; 67241d32cfcSBaolin Wang } else { 67341d32cfcSBaolin Wang val |= PULL_DOWN; 67441d32cfcSBaolin Wang mask = PULL_DOWN_MASK; 67541d32cfcSBaolin Wang shift = PULL_DOWN_SHIFT; 67641d32cfcSBaolin Wang } 67741d32cfcSBaolin Wang break; 67841d32cfcSBaolin Wang case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 67941d32cfcSBaolin Wang if (arg > 0) 68041d32cfcSBaolin Wang val |= INPUT_SCHMITT; 68141d32cfcSBaolin Wang else 68241d32cfcSBaolin Wang val &= ~INPUT_SCHMITT; 68341d32cfcSBaolin Wang 68441d32cfcSBaolin Wang mask = INPUT_SCHMITT_MASK; 68541d32cfcSBaolin Wang shift = INPUT_SCHMITT_SHIFT; 68641d32cfcSBaolin Wang break; 68741d32cfcSBaolin Wang case PIN_CONFIG_BIAS_PULL_UP: 68841d32cfcSBaolin Wang if (is_sleep_config == true) { 68941d32cfcSBaolin Wang val |= SLEEP_PULL_UP; 69041d32cfcSBaolin Wang mask = SLEEP_PULL_UP_MASK; 69141d32cfcSBaolin Wang shift = SLEEP_PULL_UP_SHIFT; 69241d32cfcSBaolin Wang } else { 69341d32cfcSBaolin Wang if (arg == 20000) 69441d32cfcSBaolin Wang val |= PULL_UP_20K; 69541d32cfcSBaolin Wang else if (arg == 4700) 69641d32cfcSBaolin Wang val |= PULL_UP_4_7K; 69741d32cfcSBaolin Wang 69841d32cfcSBaolin Wang mask = PULL_UP_MASK; 69941d32cfcSBaolin Wang shift = PULL_UP_SHIFT; 70041d32cfcSBaolin Wang } 70141d32cfcSBaolin Wang break; 70241d32cfcSBaolin Wang case PIN_CONFIG_SLEEP_HARDWARE_STATE: 70341d32cfcSBaolin Wang continue; 70441d32cfcSBaolin Wang default: 70541d32cfcSBaolin Wang return -ENOTSUPP; 70641d32cfcSBaolin Wang } 70741d32cfcSBaolin Wang } else { 70841d32cfcSBaolin Wang return -ENOTSUPP; 70941d32cfcSBaolin Wang } 71041d32cfcSBaolin Wang 71141d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN) { 71241d32cfcSBaolin Wang reg = readl((void __iomem *)pin->reg); 71341d32cfcSBaolin Wang reg &= ~(PINCTRL_BIT_MASK(pin->bit_width) 71441d32cfcSBaolin Wang << pin->bit_offset); 71541d32cfcSBaolin Wang reg |= (val & PINCTRL_BIT_MASK(pin->bit_width)) 71641d32cfcSBaolin Wang << pin->bit_offset; 71741d32cfcSBaolin Wang writel(reg, (void __iomem *)pin->reg); 71841d32cfcSBaolin Wang } else { 71941d32cfcSBaolin Wang reg = readl((void __iomem *)pin->reg); 72041d32cfcSBaolin Wang reg &= ~(mask << shift); 72141d32cfcSBaolin Wang reg |= val; 72241d32cfcSBaolin Wang writel(reg, (void __iomem *)pin->reg); 72341d32cfcSBaolin Wang } 72441d32cfcSBaolin Wang } 72541d32cfcSBaolin Wang 72641d32cfcSBaolin Wang return 0; 72741d32cfcSBaolin Wang } 72841d32cfcSBaolin Wang 72941d32cfcSBaolin Wang static int sprd_pinconf_group_get(struct pinctrl_dev *pctldev, 73041d32cfcSBaolin Wang unsigned int selector, unsigned long *config) 73141d32cfcSBaolin Wang { 73241d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 73341d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 73441d32cfcSBaolin Wang struct sprd_pin_group *grp; 73541d32cfcSBaolin Wang unsigned int pin_id; 73641d32cfcSBaolin Wang 7374ce504c4SDan Carpenter if (selector >= info->ngroups) 73841d32cfcSBaolin Wang return -EINVAL; 73941d32cfcSBaolin Wang 74041d32cfcSBaolin Wang grp = &info->groups[selector]; 74141d32cfcSBaolin Wang pin_id = grp->pins[0]; 74241d32cfcSBaolin Wang 74341d32cfcSBaolin Wang return sprd_pinconf_get(pctldev, pin_id, config); 74441d32cfcSBaolin Wang } 74541d32cfcSBaolin Wang 74641d32cfcSBaolin Wang static int sprd_pinconf_group_set(struct pinctrl_dev *pctldev, 74741d32cfcSBaolin Wang unsigned int selector, 74841d32cfcSBaolin Wang unsigned long *configs, 74941d32cfcSBaolin Wang unsigned int num_configs) 75041d32cfcSBaolin Wang { 75141d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 75241d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 75341d32cfcSBaolin Wang struct sprd_pin_group *grp; 75441d32cfcSBaolin Wang int ret, i; 75541d32cfcSBaolin Wang 7564ce504c4SDan Carpenter if (selector >= info->ngroups) 75741d32cfcSBaolin Wang return -EINVAL; 75841d32cfcSBaolin Wang 75941d32cfcSBaolin Wang grp = &info->groups[selector]; 76041d32cfcSBaolin Wang 76141d32cfcSBaolin Wang for (i = 0; i < grp->npins; i++) { 76241d32cfcSBaolin Wang unsigned int pin_id = grp->pins[i]; 76341d32cfcSBaolin Wang 76441d32cfcSBaolin Wang ret = sprd_pinconf_set(pctldev, pin_id, configs, num_configs); 76541d32cfcSBaolin Wang if (ret) 76641d32cfcSBaolin Wang return ret; 76741d32cfcSBaolin Wang } 76841d32cfcSBaolin Wang 76941d32cfcSBaolin Wang return 0; 77041d32cfcSBaolin Wang } 77141d32cfcSBaolin Wang 77241d32cfcSBaolin Wang static int sprd_pinconf_get_config(struct pinctrl_dev *pctldev, 77341d32cfcSBaolin Wang unsigned int pin_id, 77441d32cfcSBaolin Wang unsigned long *config) 77541d32cfcSBaolin Wang { 77641d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 77741d32cfcSBaolin Wang struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(pctl, pin_id); 77841d32cfcSBaolin Wang 77941d32cfcSBaolin Wang if (!pin) 78041d32cfcSBaolin Wang return -EINVAL; 78141d32cfcSBaolin Wang 78241d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN) { 78341d32cfcSBaolin Wang *config = (readl((void __iomem *)pin->reg) >> 78441d32cfcSBaolin Wang pin->bit_offset) & PINCTRL_BIT_MASK(pin->bit_width); 78541d32cfcSBaolin Wang } else { 78641d32cfcSBaolin Wang *config = readl((void __iomem *)pin->reg); 78741d32cfcSBaolin Wang } 78841d32cfcSBaolin Wang 78941d32cfcSBaolin Wang return 0; 79041d32cfcSBaolin Wang } 79141d32cfcSBaolin Wang 79241d32cfcSBaolin Wang static void sprd_pinconf_dbg_show(struct pinctrl_dev *pctldev, 79341d32cfcSBaolin Wang struct seq_file *s, unsigned int pin_id) 79441d32cfcSBaolin Wang { 79541d32cfcSBaolin Wang unsigned long config; 79641d32cfcSBaolin Wang int ret; 79741d32cfcSBaolin Wang 79841d32cfcSBaolin Wang ret = sprd_pinconf_get_config(pctldev, pin_id, &config); 79941d32cfcSBaolin Wang if (ret) 80041d32cfcSBaolin Wang return; 80141d32cfcSBaolin Wang 80241d32cfcSBaolin Wang seq_printf(s, "0x%lx", config); 80341d32cfcSBaolin Wang } 80441d32cfcSBaolin Wang 80541d32cfcSBaolin Wang static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, 80641d32cfcSBaolin Wang struct seq_file *s, 80741d32cfcSBaolin Wang unsigned int selector) 80841d32cfcSBaolin Wang { 80941d32cfcSBaolin Wang struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); 81041d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = pctl->info; 81141d32cfcSBaolin Wang struct sprd_pin_group *grp; 81241d32cfcSBaolin Wang unsigned long config; 81341d32cfcSBaolin Wang const char *name; 81441d32cfcSBaolin Wang int i, ret; 81541d32cfcSBaolin Wang 8164ce504c4SDan Carpenter if (selector >= info->ngroups) 81741d32cfcSBaolin Wang return; 81841d32cfcSBaolin Wang 81941d32cfcSBaolin Wang grp = &info->groups[selector]; 82041d32cfcSBaolin Wang 8219d2fc7c3SMarkus Elfring seq_putc(s, '\n'); 82241d32cfcSBaolin Wang for (i = 0; i < grp->npins; i++, config++) { 82341d32cfcSBaolin Wang unsigned int pin_id = grp->pins[i]; 82441d32cfcSBaolin Wang 82541d32cfcSBaolin Wang name = pin_get_name(pctldev, pin_id); 82641d32cfcSBaolin Wang ret = sprd_pinconf_get_config(pctldev, pin_id, &config); 82741d32cfcSBaolin Wang if (ret) 82841d32cfcSBaolin Wang return; 82941d32cfcSBaolin Wang 83041d32cfcSBaolin Wang seq_printf(s, "%s: 0x%lx ", name, config); 83141d32cfcSBaolin Wang } 83241d32cfcSBaolin Wang } 83341d32cfcSBaolin Wang 83441d32cfcSBaolin Wang static const struct pinconf_ops sprd_pinconf_ops = { 83541d32cfcSBaolin Wang .is_generic = true, 83641d32cfcSBaolin Wang .pin_config_get = sprd_pinconf_get, 83741d32cfcSBaolin Wang .pin_config_set = sprd_pinconf_set, 83841d32cfcSBaolin Wang .pin_config_group_get = sprd_pinconf_group_get, 83941d32cfcSBaolin Wang .pin_config_group_set = sprd_pinconf_group_set, 84041d32cfcSBaolin Wang .pin_config_dbg_show = sprd_pinconf_dbg_show, 84141d32cfcSBaolin Wang .pin_config_group_dbg_show = sprd_pinconf_group_dbg_show, 84241d32cfcSBaolin Wang }; 84341d32cfcSBaolin Wang 84441d32cfcSBaolin Wang static const struct pinconf_generic_params sprd_dt_params[] = { 84541d32cfcSBaolin Wang {"sprd,control", SPRD_PIN_CONFIG_CONTROL, 0}, 84641d32cfcSBaolin Wang {"sprd,sleep-mode", SPRD_PIN_CONFIG_SLEEP_MODE, 0}, 84741d32cfcSBaolin Wang }; 84841d32cfcSBaolin Wang 84941d32cfcSBaolin Wang #ifdef CONFIG_DEBUG_FS 85041d32cfcSBaolin Wang static const struct pin_config_item sprd_conf_items[] = { 85141d32cfcSBaolin Wang PCONFDUMP(SPRD_PIN_CONFIG_CONTROL, "global control", NULL, true), 85241d32cfcSBaolin Wang PCONFDUMP(SPRD_PIN_CONFIG_SLEEP_MODE, "sleep mode", NULL, true), 85341d32cfcSBaolin Wang }; 85441d32cfcSBaolin Wang #endif 85541d32cfcSBaolin Wang 85641d32cfcSBaolin Wang static struct pinctrl_desc sprd_pinctrl_desc = { 85741d32cfcSBaolin Wang .pctlops = &sprd_pctrl_ops, 85841d32cfcSBaolin Wang .pmxops = &sprd_pmx_ops, 85941d32cfcSBaolin Wang .confops = &sprd_pinconf_ops, 86041d32cfcSBaolin Wang .num_custom_params = ARRAY_SIZE(sprd_dt_params), 86141d32cfcSBaolin Wang .custom_params = sprd_dt_params, 86241d32cfcSBaolin Wang #ifdef CONFIG_DEBUG_FS 86341d32cfcSBaolin Wang .custom_conf_items = sprd_conf_items, 86441d32cfcSBaolin Wang #endif 86541d32cfcSBaolin Wang .owner = THIS_MODULE, 86641d32cfcSBaolin Wang }; 86741d32cfcSBaolin Wang 86841d32cfcSBaolin Wang static int sprd_pinctrl_parse_groups(struct device_node *np, 86941d32cfcSBaolin Wang struct sprd_pinctrl *sprd_pctl, 87041d32cfcSBaolin Wang struct sprd_pin_group *grp) 87141d32cfcSBaolin Wang { 87241d32cfcSBaolin Wang struct property *prop; 87341d32cfcSBaolin Wang const char *pin_name; 87441d32cfcSBaolin Wang int ret, i = 0; 87541d32cfcSBaolin Wang 87641d32cfcSBaolin Wang ret = of_property_count_strings(np, "pins"); 87741d32cfcSBaolin Wang if (ret < 0) 87841d32cfcSBaolin Wang return ret; 87941d32cfcSBaolin Wang 88041d32cfcSBaolin Wang grp->name = np->name; 88141d32cfcSBaolin Wang grp->npins = ret; 882a86854d0SKees Cook grp->pins = devm_kcalloc(sprd_pctl->dev, 883a86854d0SKees Cook grp->npins, sizeof(unsigned int), 884a86854d0SKees Cook GFP_KERNEL); 88541d32cfcSBaolin Wang if (!grp->pins) 88641d32cfcSBaolin Wang return -ENOMEM; 88741d32cfcSBaolin Wang 88841d32cfcSBaolin Wang of_property_for_each_string(np, "pins", prop, pin_name) { 88941d32cfcSBaolin Wang ret = sprd_pinctrl_get_id_by_name(sprd_pctl, pin_name); 89041d32cfcSBaolin Wang if (ret >= 0) 89141d32cfcSBaolin Wang grp->pins[i++] = ret; 89241d32cfcSBaolin Wang } 89341d32cfcSBaolin Wang 89441d32cfcSBaolin Wang for (i = 0; i < grp->npins; i++) { 89541d32cfcSBaolin Wang dev_dbg(sprd_pctl->dev, 89641d32cfcSBaolin Wang "Group[%s] contains [%d] pins: id = %d\n", 89741d32cfcSBaolin Wang grp->name, grp->npins, grp->pins[i]); 89841d32cfcSBaolin Wang } 89941d32cfcSBaolin Wang 90041d32cfcSBaolin Wang return 0; 90141d32cfcSBaolin Wang } 90241d32cfcSBaolin Wang 90341d32cfcSBaolin Wang static unsigned int sprd_pinctrl_get_groups(struct device_node *np) 90441d32cfcSBaolin Wang { 90541d32cfcSBaolin Wang struct device_node *child; 90641d32cfcSBaolin Wang unsigned int group_cnt, cnt; 90741d32cfcSBaolin Wang 90841d32cfcSBaolin Wang group_cnt = of_get_child_count(np); 90941d32cfcSBaolin Wang 91041d32cfcSBaolin Wang for_each_child_of_node(np, child) { 91141d32cfcSBaolin Wang cnt = of_get_child_count(child); 91241d32cfcSBaolin Wang if (cnt > 0) 91341d32cfcSBaolin Wang group_cnt += cnt; 91441d32cfcSBaolin Wang } 91541d32cfcSBaolin Wang 91641d32cfcSBaolin Wang return group_cnt; 91741d32cfcSBaolin Wang } 91841d32cfcSBaolin Wang 91941d32cfcSBaolin Wang static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) 92041d32cfcSBaolin Wang { 92141d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = sprd_pctl->info; 92241d32cfcSBaolin Wang struct device_node *np = sprd_pctl->dev->of_node; 92341d32cfcSBaolin Wang struct device_node *child, *sub_child; 92441d32cfcSBaolin Wang struct sprd_pin_group *grp; 92541d32cfcSBaolin Wang const char **temp; 92641d32cfcSBaolin Wang int ret; 92741d32cfcSBaolin Wang 92841d32cfcSBaolin Wang if (!np) 92941d32cfcSBaolin Wang return -ENODEV; 93041d32cfcSBaolin Wang 93141d32cfcSBaolin Wang info->ngroups = sprd_pinctrl_get_groups(np); 93241d32cfcSBaolin Wang if (!info->ngroups) 93341d32cfcSBaolin Wang return 0; 93441d32cfcSBaolin Wang 935a86854d0SKees Cook info->groups = devm_kcalloc(sprd_pctl->dev, 936a86854d0SKees Cook info->ngroups, 93741d32cfcSBaolin Wang sizeof(struct sprd_pin_group), 93841d32cfcSBaolin Wang GFP_KERNEL); 93941d32cfcSBaolin Wang if (!info->groups) 94041d32cfcSBaolin Wang return -ENOMEM; 94141d32cfcSBaolin Wang 942a86854d0SKees Cook info->grp_names = devm_kcalloc(sprd_pctl->dev, 943a86854d0SKees Cook info->ngroups, sizeof(char *), 94441d32cfcSBaolin Wang GFP_KERNEL); 94541d32cfcSBaolin Wang if (!info->grp_names) 94641d32cfcSBaolin Wang return -ENOMEM; 94741d32cfcSBaolin Wang 94841d32cfcSBaolin Wang temp = info->grp_names; 94941d32cfcSBaolin Wang grp = info->groups; 95041d32cfcSBaolin Wang 95141d32cfcSBaolin Wang for_each_child_of_node(np, child) { 95241d32cfcSBaolin Wang ret = sprd_pinctrl_parse_groups(child, sprd_pctl, grp); 95341d32cfcSBaolin Wang if (ret) 95441d32cfcSBaolin Wang return ret; 95541d32cfcSBaolin Wang 95641d32cfcSBaolin Wang *temp++ = grp->name; 95741d32cfcSBaolin Wang grp++; 95841d32cfcSBaolin Wang 95941d32cfcSBaolin Wang if (of_get_child_count(child) > 0) { 96041d32cfcSBaolin Wang for_each_child_of_node(child, sub_child) { 96141d32cfcSBaolin Wang ret = sprd_pinctrl_parse_groups(sub_child, 96241d32cfcSBaolin Wang sprd_pctl, grp); 96341d32cfcSBaolin Wang if (ret) 96441d32cfcSBaolin Wang return ret; 96541d32cfcSBaolin Wang 96641d32cfcSBaolin Wang *temp++ = grp->name; 96741d32cfcSBaolin Wang grp++; 96841d32cfcSBaolin Wang } 96941d32cfcSBaolin Wang } 97041d32cfcSBaolin Wang } 97141d32cfcSBaolin Wang 97241d32cfcSBaolin Wang return 0; 97341d32cfcSBaolin Wang } 97441d32cfcSBaolin Wang 97541d32cfcSBaolin Wang static int sprd_pinctrl_add_pins(struct sprd_pinctrl *sprd_pctl, 97641d32cfcSBaolin Wang struct sprd_pins_info *sprd_soc_pin_info, 97741d32cfcSBaolin Wang int pins_cnt) 97841d32cfcSBaolin Wang { 97941d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *info = sprd_pctl->info; 98041d32cfcSBaolin Wang unsigned int ctrl_pin = 0, com_pin = 0; 98141d32cfcSBaolin Wang struct sprd_pin *pin; 98241d32cfcSBaolin Wang int i; 98341d32cfcSBaolin Wang 98441d32cfcSBaolin Wang info->npins = pins_cnt; 985a86854d0SKees Cook info->pins = devm_kcalloc(sprd_pctl->dev, 986a86854d0SKees Cook info->npins, sizeof(struct sprd_pin), 98741d32cfcSBaolin Wang GFP_KERNEL); 98841d32cfcSBaolin Wang if (!info->pins) 98941d32cfcSBaolin Wang return -ENOMEM; 99041d32cfcSBaolin Wang 99141d32cfcSBaolin Wang for (i = 0, pin = info->pins; i < info->npins; i++, pin++) { 99241d32cfcSBaolin Wang unsigned int reg; 99341d32cfcSBaolin Wang 99441d32cfcSBaolin Wang pin->name = sprd_soc_pin_info[i].name; 99541d32cfcSBaolin Wang pin->type = sprd_soc_pin_info[i].type; 99641d32cfcSBaolin Wang pin->number = sprd_soc_pin_info[i].num; 99741d32cfcSBaolin Wang reg = sprd_soc_pin_info[i].reg; 99841d32cfcSBaolin Wang if (pin->type == GLOBAL_CTRL_PIN) { 99941d32cfcSBaolin Wang pin->reg = (unsigned long)sprd_pctl->base + 100041d32cfcSBaolin Wang PINCTRL_REG_LEN * reg; 100141d32cfcSBaolin Wang pin->bit_offset = sprd_soc_pin_info[i].bit_offset; 100241d32cfcSBaolin Wang pin->bit_width = sprd_soc_pin_info[i].bit_width; 100341d32cfcSBaolin Wang ctrl_pin++; 100441d32cfcSBaolin Wang } else if (pin->type == COMMON_PIN) { 100541d32cfcSBaolin Wang pin->reg = (unsigned long)sprd_pctl->base + 100641d32cfcSBaolin Wang PINCTRL_REG_OFFSET + PINCTRL_REG_LEN * 100741d32cfcSBaolin Wang (i - ctrl_pin); 100841d32cfcSBaolin Wang com_pin++; 100941d32cfcSBaolin Wang } else if (pin->type == MISC_PIN) { 101041d32cfcSBaolin Wang pin->reg = (unsigned long)sprd_pctl->base + 101141d32cfcSBaolin Wang PINCTRL_REG_MISC_OFFSET + PINCTRL_REG_LEN * 101241d32cfcSBaolin Wang (i - ctrl_pin - com_pin); 101341d32cfcSBaolin Wang } 101441d32cfcSBaolin Wang } 101541d32cfcSBaolin Wang 101641d32cfcSBaolin Wang for (i = 0, pin = info->pins; i < info->npins; pin++, i++) { 101741d32cfcSBaolin Wang dev_dbg(sprd_pctl->dev, "pin name[%s-%d], type = %d, " 101841d32cfcSBaolin Wang "bit offset = %ld, bit width = %ld, reg = 0x%lx\n", 101941d32cfcSBaolin Wang pin->name, pin->number, pin->type, 102041d32cfcSBaolin Wang pin->bit_offset, pin->bit_width, pin->reg); 102141d32cfcSBaolin Wang } 102241d32cfcSBaolin Wang 102341d32cfcSBaolin Wang return 0; 102441d32cfcSBaolin Wang } 102541d32cfcSBaolin Wang 102641d32cfcSBaolin Wang int sprd_pinctrl_core_probe(struct platform_device *pdev, 102741d32cfcSBaolin Wang struct sprd_pins_info *sprd_soc_pin_info, 102841d32cfcSBaolin Wang int pins_cnt) 102941d32cfcSBaolin Wang { 103041d32cfcSBaolin Wang struct sprd_pinctrl *sprd_pctl; 103141d32cfcSBaolin Wang struct sprd_pinctrl_soc_info *pinctrl_info; 103241d32cfcSBaolin Wang struct pinctrl_pin_desc *pin_desc; 103341d32cfcSBaolin Wang struct resource *res; 103441d32cfcSBaolin Wang int ret, i; 103541d32cfcSBaolin Wang 103641d32cfcSBaolin Wang sprd_pctl = devm_kzalloc(&pdev->dev, sizeof(struct sprd_pinctrl), 103741d32cfcSBaolin Wang GFP_KERNEL); 103841d32cfcSBaolin Wang if (!sprd_pctl) 103941d32cfcSBaolin Wang return -ENOMEM; 104041d32cfcSBaolin Wang 104141d32cfcSBaolin Wang res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 104241d32cfcSBaolin Wang sprd_pctl->base = devm_ioremap_resource(&pdev->dev, res); 104341d32cfcSBaolin Wang if (IS_ERR(sprd_pctl->base)) 104441d32cfcSBaolin Wang return PTR_ERR(sprd_pctl->base); 104541d32cfcSBaolin Wang 104641d32cfcSBaolin Wang pinctrl_info = devm_kzalloc(&pdev->dev, 104741d32cfcSBaolin Wang sizeof(struct sprd_pinctrl_soc_info), 104841d32cfcSBaolin Wang GFP_KERNEL); 104941d32cfcSBaolin Wang if (!pinctrl_info) 105041d32cfcSBaolin Wang return -ENOMEM; 105141d32cfcSBaolin Wang 105241d32cfcSBaolin Wang sprd_pctl->info = pinctrl_info; 105341d32cfcSBaolin Wang sprd_pctl->dev = &pdev->dev; 105441d32cfcSBaolin Wang platform_set_drvdata(pdev, sprd_pctl); 105541d32cfcSBaolin Wang 105641d32cfcSBaolin Wang ret = sprd_pinctrl_add_pins(sprd_pctl, sprd_soc_pin_info, pins_cnt); 105741d32cfcSBaolin Wang if (ret) { 105841d32cfcSBaolin Wang dev_err(&pdev->dev, "fail to add pins information\n"); 105941d32cfcSBaolin Wang return ret; 106041d32cfcSBaolin Wang } 106141d32cfcSBaolin Wang 1062*63e037bcSBaolin Wang ret = sprd_pinctrl_parse_dt(sprd_pctl); 1063*63e037bcSBaolin Wang if (ret) { 1064*63e037bcSBaolin Wang dev_err(&pdev->dev, "fail to parse dt properties\n"); 1065*63e037bcSBaolin Wang return ret; 1066*63e037bcSBaolin Wang } 1067*63e037bcSBaolin Wang 1068a86854d0SKees Cook pin_desc = devm_kcalloc(&pdev->dev, 1069a86854d0SKees Cook pinctrl_info->npins, 107041d32cfcSBaolin Wang sizeof(struct pinctrl_pin_desc), 107141d32cfcSBaolin Wang GFP_KERNEL); 107241d32cfcSBaolin Wang if (!pin_desc) 107341d32cfcSBaolin Wang return -ENOMEM; 107441d32cfcSBaolin Wang 107541d32cfcSBaolin Wang for (i = 0; i < pinctrl_info->npins; i++) { 107641d32cfcSBaolin Wang pin_desc[i].number = pinctrl_info->pins[i].number; 107741d32cfcSBaolin Wang pin_desc[i].name = pinctrl_info->pins[i].name; 107841d32cfcSBaolin Wang pin_desc[i].drv_data = pinctrl_info; 107941d32cfcSBaolin Wang } 108041d32cfcSBaolin Wang 108141d32cfcSBaolin Wang sprd_pinctrl_desc.pins = pin_desc; 108241d32cfcSBaolin Wang sprd_pinctrl_desc.name = dev_name(&pdev->dev); 108341d32cfcSBaolin Wang sprd_pinctrl_desc.npins = pinctrl_info->npins; 108441d32cfcSBaolin Wang 108541d32cfcSBaolin Wang sprd_pctl->pctl = pinctrl_register(&sprd_pinctrl_desc, 108641d32cfcSBaolin Wang &pdev->dev, (void *)sprd_pctl); 108741d32cfcSBaolin Wang if (IS_ERR(sprd_pctl->pctl)) { 108841d32cfcSBaolin Wang dev_err(&pdev->dev, "could not register pinctrl driver\n"); 108941d32cfcSBaolin Wang return PTR_ERR(sprd_pctl->pctl); 109041d32cfcSBaolin Wang } 109141d32cfcSBaolin Wang 109241d32cfcSBaolin Wang return 0; 109341d32cfcSBaolin Wang } 109441d32cfcSBaolin Wang 109541d32cfcSBaolin Wang int sprd_pinctrl_remove(struct platform_device *pdev) 109641d32cfcSBaolin Wang { 109741d32cfcSBaolin Wang struct sprd_pinctrl *sprd_pctl = platform_get_drvdata(pdev); 109841d32cfcSBaolin Wang 109941d32cfcSBaolin Wang pinctrl_unregister(sprd_pctl->pctl); 110041d32cfcSBaolin Wang return 0; 110141d32cfcSBaolin Wang } 110241d32cfcSBaolin Wang 110341d32cfcSBaolin Wang void sprd_pinctrl_shutdown(struct platform_device *pdev) 110441d32cfcSBaolin Wang { 110541470c37SDan Carpenter struct pinctrl *pinctl; 110641d32cfcSBaolin Wang struct pinctrl_state *state; 110741d32cfcSBaolin Wang 110841470c37SDan Carpenter pinctl = devm_pinctrl_get(&pdev->dev); 110941470c37SDan Carpenter if (IS_ERR(pinctl)) 111041470c37SDan Carpenter return; 111141d32cfcSBaolin Wang state = pinctrl_lookup_state(pinctl, "shutdown"); 111241470c37SDan Carpenter if (IS_ERR(state)) 111341470c37SDan Carpenter return; 111441d32cfcSBaolin Wang pinctrl_select_state(pinctl, state); 111541d32cfcSBaolin Wang } 111641d32cfcSBaolin Wang 111741d32cfcSBaolin Wang MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); 111841d32cfcSBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); 111941d32cfcSBaolin Wang MODULE_LICENSE("GPL v2"); 1120