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