brintos

brintos / linux-shallow public Read only

0
0
Text · 22.9 KiB · fbd0fcd Raw
915 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Copyright (C) 2015-2017 Socionext Inc.4//   Author: Masahiro Yamada <yamada.masahiro@socionext.com>5 6#include <linux/list.h>7#include <linux/mfd/syscon.h>8#include <linux/of.h>9#include <linux/platform_device.h>10#include <linux/regmap.h>11#include <linux/seq_file.h>12 13#include <linux/pinctrl/pinconf-generic.h>14#include <linux/pinctrl/pinconf.h>15#include <linux/pinctrl/pinctrl.h>16#include <linux/pinctrl/pinmux.h>17 18#include "../core.h"19#include "../pinctrl-utils.h"20#include "pinctrl-uniphier.h"21 22#define UNIPHIER_PINCTRL_PINMUX_BASE	0x100023#define UNIPHIER_PINCTRL_LOAD_PINMUX	0x170024#define UNIPHIER_PINCTRL_DRVCTRL_BASE	0x180025#define UNIPHIER_PINCTRL_DRV2CTRL_BASE	0x190026#define UNIPHIER_PINCTRL_DRV3CTRL_BASE	0x198027#define UNIPHIER_PINCTRL_PUPDCTRL_BASE	0x1a0028#define UNIPHIER_PINCTRL_IECTRL_BASE	0x1d0029 30struct uniphier_pinctrl_reg_region {31	struct list_head node;32	unsigned int base;33	unsigned int nregs;34	u32 vals[] __counted_by(nregs);35};36 37struct uniphier_pinctrl_priv {38	struct pinctrl_desc pctldesc;39	struct pinctrl_dev *pctldev;40	struct regmap *regmap;41	const struct uniphier_pinctrl_socdata *socdata;42	struct list_head reg_regions;43};44 45static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev)46{47	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);48 49	return priv->socdata->groups_count;50}51 52static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev,53						unsigned selector)54{55	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);56 57	return priv->socdata->groups[selector].name;58}59 60static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,61					unsigned selector,62					const unsigned **pins,63					unsigned *num_pins)64{65	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);66 67	*pins = priv->socdata->groups[selector].pins;68	*num_pins = priv->socdata->groups[selector].num_pins;69 70	return 0;71}72 73#ifdef CONFIG_DEBUG_FS74static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,75				       struct seq_file *s, unsigned offset)76{77	const struct pin_desc *desc = pin_desc_get(pctldev, offset);78	const char *pull_dir, *drv_type;79 80	switch (uniphier_pin_get_pull_dir(desc->drv_data)) {81	case UNIPHIER_PIN_PULL_UP:82		pull_dir = "UP";83		break;84	case UNIPHIER_PIN_PULL_DOWN:85		pull_dir = "DOWN";86		break;87	case UNIPHIER_PIN_PULL_UP_FIXED:88		pull_dir = "UP(FIXED)";89		break;90	case UNIPHIER_PIN_PULL_DOWN_FIXED:91		pull_dir = "DOWN(FIXED)";92		break;93	case UNIPHIER_PIN_PULL_NONE:94		pull_dir = "NONE";95		break;96	default:97		BUG();98	}99 100	switch (uniphier_pin_get_drv_type(desc->drv_data)) {101	case UNIPHIER_PIN_DRV_1BIT:102		drv_type = "4/8(mA)";103		break;104	case UNIPHIER_PIN_DRV_2BIT:105		drv_type = "8/12/16/20(mA)";106		break;107	case UNIPHIER_PIN_DRV_3BIT:108		drv_type = "4/5/7/9/11/12/14/16(mA)";109		break;110	case UNIPHIER_PIN_DRV_FIXED4:111		drv_type = "4(mA)";112		break;113	case UNIPHIER_PIN_DRV_FIXED5:114		drv_type = "5(mA)";115		break;116	case UNIPHIER_PIN_DRV_FIXED8:117		drv_type = "8(mA)";118		break;119	case UNIPHIER_PIN_DRV_NONE:120		drv_type = "NONE";121		break;122	default:123		BUG();124	}125 126	seq_printf(s, " PULL_DIR=%s  DRV_TYPE=%s", pull_dir, drv_type);127}128#endif129 130static const struct pinctrl_ops uniphier_pctlops = {131	.get_groups_count = uniphier_pctl_get_groups_count,132	.get_group_name = uniphier_pctl_get_group_name,133	.get_group_pins = uniphier_pctl_get_group_pins,134#ifdef CONFIG_DEBUG_FS135	.pin_dbg_show = uniphier_pctl_pin_dbg_show,136#endif137	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,138	.dt_free_map = pinctrl_utils_free_map,139};140 141static const unsigned int uniphier_conf_drv_strengths_1bit[] = {4, 8};142static const unsigned int uniphier_conf_drv_strengths_2bit[] = {8, 12, 16, 20};143static const unsigned int uniphier_conf_drv_strengths_3bit[] = {4, 5, 7, 9, 11,144								12, 14, 16};145static const unsigned int uniphier_conf_drv_strengths_fixed4[] = {4};146static const unsigned int uniphier_conf_drv_strengths_fixed5[] = {5};147static const unsigned int uniphier_conf_drv_strengths_fixed8[] = {8};148 149static int uniphier_conf_get_drvctrl_data(struct pinctrl_dev *pctldev,150					  unsigned int pin, unsigned int *reg,151					  unsigned int *shift,152					  unsigned int *mask,153					  const unsigned int **strengths)154{155	const struct pin_desc *desc = pin_desc_get(pctldev, pin);156	enum uniphier_pin_drv_type type =157				uniphier_pin_get_drv_type(desc->drv_data);158	unsigned int base = 0;159	unsigned int stride = 0;160	unsigned int width = 0;161	unsigned int drvctrl;162 163	switch (type) {164	case UNIPHIER_PIN_DRV_1BIT:165		*strengths = uniphier_conf_drv_strengths_1bit;166		base = UNIPHIER_PINCTRL_DRVCTRL_BASE;167		stride = 1;168		width = 1;169		break;170	case UNIPHIER_PIN_DRV_2BIT:171		*strengths = uniphier_conf_drv_strengths_2bit;172		base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;173		stride = 2;174		width = 2;175		break;176	case UNIPHIER_PIN_DRV_3BIT:177		*strengths = uniphier_conf_drv_strengths_3bit;178		base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;179		stride = 4;180		width = 3;181		break;182	case UNIPHIER_PIN_DRV_FIXED4:183		*strengths = uniphier_conf_drv_strengths_fixed4;184		break;185	case UNIPHIER_PIN_DRV_FIXED5:186		*strengths = uniphier_conf_drv_strengths_fixed5;187		break;188	case UNIPHIER_PIN_DRV_FIXED8:189		*strengths = uniphier_conf_drv_strengths_fixed8;190		break;191	default:192		/* drive strength control is not supported for this pin */193		return -EINVAL;194	}195 196	drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);197	drvctrl *= stride;198 199	*reg = base + drvctrl / 32 * 4;200	*shift = drvctrl % 32;201	*mask = (1U << width) - 1;202 203	return 0;204}205 206static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,207				      unsigned int pin,208				      enum pin_config_param param)209{210	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);211	const struct pin_desc *desc = pin_desc_get(pctldev, pin);212	enum uniphier_pin_pull_dir pull_dir =213				uniphier_pin_get_pull_dir(desc->drv_data);214	unsigned int pupdctrl, reg, shift, val;215	unsigned int expected = 1;216	int ret;217 218	switch (param) {219	case PIN_CONFIG_BIAS_DISABLE:220		if (pull_dir == UNIPHIER_PIN_PULL_NONE)221			return 0;222		if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||223		    pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)224			return -EINVAL;225		expected = 0;226		break;227	case PIN_CONFIG_BIAS_PULL_UP:228		if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED)229			return 0;230		if (pull_dir != UNIPHIER_PIN_PULL_UP)231			return -EINVAL;232		break;233	case PIN_CONFIG_BIAS_PULL_DOWN:234		if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)235			return 0;236		if (pull_dir != UNIPHIER_PIN_PULL_DOWN)237			return -EINVAL;238		break;239	default:240		BUG();241	}242 243	pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);244 245	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;246	shift = pupdctrl % 32;247 248	ret = regmap_read(priv->regmap, reg, &val);249	if (ret)250		return ret;251 252	val = (val >> shift) & 1;253 254	return (val == expected) ? 0 : -EINVAL;255}256 257static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,258				       unsigned int pin, u32 *strength)259{260	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);261	unsigned int reg, shift, mask, val;262	const unsigned int *strengths;263	int ret;264 265	ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,266					     &mask, &strengths);267	if (ret)268		return ret;269 270	if (mask) {271		ret = regmap_read(priv->regmap, reg, &val);272		if (ret)273			return ret;274	} else {275		val = 0;276	}277 278	*strength = strengths[(val >> shift) & mask];279 280	return 0;281}282 283static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,284					      unsigned int pin)285{286	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);287	const struct pin_desc *desc = pin_desc_get(pctldev, pin);288	unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);289	unsigned int reg, mask, val;290	int ret;291 292	if (iectrl == UNIPHIER_PIN_IECTRL_NONE)293		/* This pin is always input-enabled. */294		return 0;295 296	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)297		iectrl = pin;298 299	reg = UNIPHIER_PINCTRL_IECTRL_BASE + iectrl / 32 * 4;300	mask = BIT(iectrl % 32);301 302	ret = regmap_read(priv->regmap, reg, &val);303	if (ret)304		return ret;305 306	return val & mask ? 0 : -EINVAL;307}308 309static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,310					unsigned pin,311					unsigned long *configs)312{313	enum pin_config_param param = pinconf_to_config_param(*configs);314	bool has_arg = false;315	u32 arg;316	int ret;317 318	switch (param) {319	case PIN_CONFIG_BIAS_DISABLE:320	case PIN_CONFIG_BIAS_PULL_UP:321	case PIN_CONFIG_BIAS_PULL_DOWN:322		ret = uniphier_conf_pin_bias_get(pctldev, pin, param);323		break;324	case PIN_CONFIG_DRIVE_STRENGTH:325		ret = uniphier_conf_pin_drive_get(pctldev, pin, &arg);326		has_arg = true;327		break;328	case PIN_CONFIG_INPUT_ENABLE:329		ret = uniphier_conf_pin_input_enable_get(pctldev, pin);330		break;331	default:332		/* unsupported parameter */333		ret = -EINVAL;334		break;335	}336 337	if (ret == 0 && has_arg)338		*configs = pinconf_to_config_packed(param, arg);339 340	return ret;341}342 343static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,344				      unsigned int pin,345				      enum pin_config_param param, u32 arg)346{347	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);348	const struct pin_desc *desc = pin_desc_get(pctldev, pin);349	enum uniphier_pin_pull_dir pull_dir =350				uniphier_pin_get_pull_dir(desc->drv_data);351	unsigned int pupdctrl, reg, shift;352	unsigned int val = 1;353 354	switch (param) {355	case PIN_CONFIG_BIAS_DISABLE:356		if (pull_dir == UNIPHIER_PIN_PULL_NONE)357			return 0;358		if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||359		    pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {360			dev_err(pctldev->dev,361				"can not disable pull register for pin %s\n",362				desc->name);363			return -EINVAL;364		}365		val = 0;366		break;367	case PIN_CONFIG_BIAS_PULL_UP:368		if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0)369			return 0;370		if (pull_dir != UNIPHIER_PIN_PULL_UP) {371			dev_err(pctldev->dev,372				"pull-up is unsupported for pin %s\n",373				desc->name);374			return -EINVAL;375		}376		if (arg == 0) {377			dev_err(pctldev->dev, "pull-up can not be total\n");378			return -EINVAL;379		}380		break;381	case PIN_CONFIG_BIAS_PULL_DOWN:382		if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0)383			return 0;384		if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {385			dev_err(pctldev->dev,386				"pull-down is unsupported for pin %s\n",387				desc->name);388			return -EINVAL;389		}390		if (arg == 0) {391			dev_err(pctldev->dev, "pull-down can not be total\n");392			return -EINVAL;393		}394		break;395	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:396		if (pull_dir == UNIPHIER_PIN_PULL_NONE) {397			dev_err(pctldev->dev,398				"pull-up/down is unsupported for pin %s\n",399				desc->name);400			return -EINVAL;401		}402 403		if (arg == 0)404			return 0; /* configuration ingored */405		break;406	default:407		BUG();408	}409 410	pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);411 412	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;413	shift = pupdctrl % 32;414 415	return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);416}417 418static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,419				       unsigned int pin, u32 strength)420{421	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);422	const struct pin_desc *desc = pin_desc_get(pctldev, pin);423	unsigned int reg, shift, mask, val;424	const unsigned int *strengths;425	int ret;426 427	ret = uniphier_conf_get_drvctrl_data(pctldev, pin, &reg, &shift,428					     &mask, &strengths);429	if (ret) {430		dev_err(pctldev->dev, "cannot set drive strength for pin %s\n",431			desc->name);432		return ret;433	}434 435	for (val = 0; val <= mask; val++) {436		if (strengths[val] > strength)437			break;438	}439 440	if (val == 0) {441		dev_err(pctldev->dev,442			"unsupported drive strength %u mA for pin %s\n",443			strength, desc->name);444		return -EINVAL;445	}446 447	if (!mask)448		return 0;449 450	val--;451 452	return regmap_update_bits(priv->regmap, reg,453				  mask << shift, val << shift);454}455 456static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,457					  unsigned int pin, u32 enable)458{459	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);460	const struct pin_desc *desc = pin_desc_get(pctldev, pin);461	unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);462	unsigned int reg, mask;463 464	/*465	 * Multiple pins share one input enable, per-pin disabling is466	 * impossible.467	 */468	if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) &&469	    !enable)470		return -EINVAL;471 472	/* UNIPHIER_PIN_IECTRL_NONE means the pin is always input-enabled */473	if (iectrl == UNIPHIER_PIN_IECTRL_NONE)474		return enable ? 0 : -EINVAL;475 476	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)477		iectrl = pin;478 479	reg = UNIPHIER_PINCTRL_IECTRL_BASE + iectrl / 32 * 4;480	mask = BIT(iectrl % 32);481 482	return regmap_update_bits(priv->regmap, reg, mask, enable ? mask : 0);483}484 485static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,486					unsigned pin,487					unsigned long *configs,488					unsigned num_configs)489{490	int i, ret;491 492	for (i = 0; i < num_configs; i++) {493		enum pin_config_param param =494					pinconf_to_config_param(configs[i]);495		u32 arg = pinconf_to_config_argument(configs[i]);496 497		switch (param) {498		case PIN_CONFIG_BIAS_DISABLE:499		case PIN_CONFIG_BIAS_PULL_UP:500		case PIN_CONFIG_BIAS_PULL_DOWN:501		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:502			ret = uniphier_conf_pin_bias_set(pctldev, pin,503							 param, arg);504			break;505		case PIN_CONFIG_DRIVE_STRENGTH:506			ret = uniphier_conf_pin_drive_set(pctldev, pin, arg);507			break;508		case PIN_CONFIG_INPUT_ENABLE:509			ret = uniphier_conf_pin_input_enable(pctldev, pin, arg);510			break;511		default:512			dev_err(pctldev->dev,513				"unsupported configuration parameter %u\n",514				param);515			return -EINVAL;516		}517 518		if (ret)519			return ret;520	}521 522	return 0;523}524 525static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev,526					      unsigned selector,527					      unsigned long *configs,528					      unsigned num_configs)529{530	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);531	const unsigned *pins = priv->socdata->groups[selector].pins;532	unsigned num_pins = priv->socdata->groups[selector].num_pins;533	int i, ret;534 535	for (i = 0; i < num_pins; i++) {536		ret = uniphier_conf_pin_config_set(pctldev, pins[i],537						   configs, num_configs);538		if (ret)539			return ret;540	}541 542	return 0;543}544 545static const struct pinconf_ops uniphier_confops = {546	.is_generic = true,547	.pin_config_get = uniphier_conf_pin_config_get,548	.pin_config_set = uniphier_conf_pin_config_set,549	.pin_config_group_set = uniphier_conf_pin_config_group_set,550};551 552static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev)553{554	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);555 556	return priv->socdata->functions_count;557}558 559static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev,560						  unsigned selector)561{562	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);563 564	return priv->socdata->functions[selector].name;565}566 567static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,568					    unsigned selector,569					    const char * const **groups,570					    unsigned *num_groups)571{572	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);573 574	*groups = priv->socdata->functions[selector].groups;575	*num_groups = priv->socdata->functions[selector].num_groups;576 577	return 0;578}579 580static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,581				    int muxval)582{583	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);584	unsigned int mux_bits, reg_stride, reg, reg_end, shift, mask;585	bool load_pinctrl;586	int ret;587 588	/* some pins need input-enabling */589	ret = uniphier_conf_pin_input_enable(pctldev, pin, 1);590	if (ret)591		return ret;592 593	if (muxval < 0)594		return 0;	/* dedicated pin; nothing to do for pin-mux */595 596	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {597		/*598		 *  Mode     reg_offset     bit_position599		 *  Normal    4 * n        shift+3:shift600		 *  Debug     4 * n        shift+7:shift+4601		 */602		mux_bits = 4;603		reg_stride = 8;604		load_pinctrl = true;605	} else {606		/*607		 *  Mode     reg_offset     bit_position608		 *  Normal    8 * n        shift+3:shift609		 *  Debug     8 * n + 4    shift+3:shift610		 */611		mux_bits = 8;612		reg_stride = 4;613		load_pinctrl = false;614	}615 616	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;617	reg_end = reg + reg_stride;618	shift = pin * mux_bits % 32;619	mask = (1U << mux_bits) - 1;620 621	/*622	 * If reg_stride is greater than 4, the MSB of each pinsel shall be623	 * stored in the offset+4.624	 */625	for (; reg < reg_end; reg += 4) {626		ret = regmap_update_bits(priv->regmap, reg,627					 mask << shift, muxval << shift);628		if (ret)629			return ret;630		muxval >>= mux_bits;631	}632 633	if (load_pinctrl) {634		ret = regmap_write(priv->regmap,635				   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);636		if (ret)637			return ret;638	}639 640	return 0;641}642 643static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,644				unsigned func_selector,645				unsigned group_selector)646{647	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);648	const struct uniphier_pinctrl_group *grp =649					&priv->socdata->groups[group_selector];650	int i;651	int ret;652 653	for (i = 0; i < grp->num_pins; i++) {654		ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],655					       grp->muxvals[i]);656		if (ret)657			return ret;658	}659 660	return 0;661}662 663static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,664					    struct pinctrl_gpio_range *range,665					    unsigned offset)666{667	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);668	unsigned int gpio_offset;669	int muxval, i;670 671	if (range->pins) {672		for (i = 0; i < range->npins; i++)673			if (range->pins[i] == offset)674				break;675 676		if (WARN_ON(i == range->npins))677			return -EINVAL;678 679		gpio_offset = i;680	} else {681		gpio_offset = offset - range->pin_base;682	}683 684	gpio_offset += range->id;685 686	muxval = priv->socdata->get_gpio_muxval(offset, gpio_offset);687 688	return uniphier_pmx_set_one_mux(pctldev, offset, muxval);689}690 691static const struct pinmux_ops uniphier_pmxops = {692	.get_functions_count = uniphier_pmx_get_functions_count,693	.get_function_name = uniphier_pmx_get_function_name,694	.get_function_groups = uniphier_pmx_get_function_groups,695	.set_mux = uniphier_pmx_set_mux,696	.gpio_request_enable = uniphier_pmx_gpio_request_enable,697	.strict = true,698};699 700#ifdef CONFIG_PM_SLEEP701static int uniphier_pinctrl_suspend(struct device *dev)702{703	struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev);704	struct uniphier_pinctrl_reg_region *r;705	int ret;706 707	list_for_each_entry(r, &priv->reg_regions, node) {708		ret = regmap_bulk_read(priv->regmap, r->base, r->vals,709				       r->nregs);710		if (ret)711			return ret;712	}713 714	return 0;715}716 717static int uniphier_pinctrl_resume(struct device *dev)718{719	struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev);720	struct uniphier_pinctrl_reg_region *r;721	int ret;722 723	list_for_each_entry(r, &priv->reg_regions, node) {724		ret = regmap_bulk_write(priv->regmap, r->base, r->vals,725					r->nregs);726		if (ret)727			return ret;728	}729 730	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {731		ret = regmap_write(priv->regmap,732				   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);733		if (ret)734			return ret;735	}736 737	return 0;738}739 740static int uniphier_pinctrl_add_reg_region(struct device *dev,741					   struct uniphier_pinctrl_priv *priv,742					   unsigned int base,743					   unsigned int count,744					   unsigned int width)745{746	struct uniphier_pinctrl_reg_region *region;747	unsigned int nregs;748 749	if (!count)750		return 0;751 752	nregs = DIV_ROUND_UP(count * width, 32);753 754	region = devm_kzalloc(dev, struct_size(region, vals, nregs),755			      GFP_KERNEL);756	if (!region)757		return -ENOMEM;758 759	region->base = base;760	region->nregs = nregs;761 762	list_add_tail(&region->node, &priv->reg_regions);763 764	return 0;765}766#endif767 768static int uniphier_pinctrl_pm_init(struct device *dev,769				    struct uniphier_pinctrl_priv *priv)770{771#ifdef CONFIG_PM_SLEEP772	const struct uniphier_pinctrl_socdata *socdata = priv->socdata;773	unsigned int num_drvctrl = 0;774	unsigned int num_drv2ctrl = 0;775	unsigned int num_drv3ctrl = 0;776	unsigned int num_pupdctrl = 0;777	unsigned int num_iectrl = 0;778	unsigned int iectrl, drvctrl, pupdctrl;779	enum uniphier_pin_drv_type drv_type;780	enum uniphier_pin_pull_dir pull_dir;781	int i, ret;782 783	for (i = 0; i < socdata->npins; i++) {784		void *drv_data = socdata->pins[i].drv_data;785 786		drvctrl = uniphier_pin_get_drvctrl(drv_data);787		drv_type = uniphier_pin_get_drv_type(drv_data);788		pupdctrl = uniphier_pin_get_pupdctrl(drv_data);789		pull_dir = uniphier_pin_get_pull_dir(drv_data);790		iectrl = uniphier_pin_get_iectrl(drv_data);791 792		switch (drv_type) {793		case UNIPHIER_PIN_DRV_1BIT:794			num_drvctrl = max(num_drvctrl, drvctrl + 1);795			break;796		case UNIPHIER_PIN_DRV_2BIT:797			num_drv2ctrl = max(num_drv2ctrl, drvctrl + 1);798			break;799		case UNIPHIER_PIN_DRV_3BIT:800			num_drv3ctrl = max(num_drv3ctrl, drvctrl + 1);801			break;802		default:803			break;804		}805 806		if (pull_dir == UNIPHIER_PIN_PULL_UP ||807		    pull_dir == UNIPHIER_PIN_PULL_DOWN)808			num_pupdctrl = max(num_pupdctrl, pupdctrl + 1);809 810		if (iectrl != UNIPHIER_PIN_IECTRL_NONE) {811			if (socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)812				iectrl = i;813			num_iectrl = max(num_iectrl, iectrl + 1);814		}815	}816 817	INIT_LIST_HEAD(&priv->reg_regions);818 819	ret = uniphier_pinctrl_add_reg_region(dev, priv,820					      UNIPHIER_PINCTRL_PINMUX_BASE,821					      socdata->npins, 8);822	if (ret)823		return ret;824 825	ret = uniphier_pinctrl_add_reg_region(dev, priv,826					      UNIPHIER_PINCTRL_DRVCTRL_BASE,827					      num_drvctrl, 1);828	if (ret)829		return ret;830 831	ret = uniphier_pinctrl_add_reg_region(dev, priv,832					      UNIPHIER_PINCTRL_DRV2CTRL_BASE,833					      num_drv2ctrl, 2);834	if (ret)835		return ret;836 837	ret = uniphier_pinctrl_add_reg_region(dev, priv,838					      UNIPHIER_PINCTRL_DRV3CTRL_BASE,839					      num_drv3ctrl, 3);840	if (ret)841		return ret;842 843	ret = uniphier_pinctrl_add_reg_region(dev, priv,844					      UNIPHIER_PINCTRL_PUPDCTRL_BASE,845					      num_pupdctrl, 1);846	if (ret)847		return ret;848 849	ret = uniphier_pinctrl_add_reg_region(dev, priv,850					      UNIPHIER_PINCTRL_IECTRL_BASE,851					      num_iectrl, 1);852	if (ret)853		return ret;854#endif855	return 0;856}857 858const struct dev_pm_ops uniphier_pinctrl_pm_ops = {859	SET_LATE_SYSTEM_SLEEP_PM_OPS(uniphier_pinctrl_suspend,860				     uniphier_pinctrl_resume)861};862 863int uniphier_pinctrl_probe(struct platform_device *pdev,864			   const struct uniphier_pinctrl_socdata *socdata)865{866	struct device *dev = &pdev->dev;867	struct uniphier_pinctrl_priv *priv;868	struct device_node *parent;869	int ret;870 871	if (!socdata ||872	    !socdata->pins || !socdata->npins ||873	    !socdata->groups || !socdata->groups_count ||874	    !socdata->functions || !socdata->functions_count) {875		dev_err(dev, "pinctrl socdata lacks necessary members\n");876		return -EINVAL;877	}878 879	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);880	if (!priv)881		return -ENOMEM;882 883	parent = of_get_parent(dev->of_node);884	priv->regmap = syscon_node_to_regmap(parent);885	of_node_put(parent);886 887	if (IS_ERR(priv->regmap)) {888		dev_err(dev, "failed to get regmap\n");889		return PTR_ERR(priv->regmap);890	}891 892	priv->socdata = socdata;893	priv->pctldesc.name = dev->driver->name;894	priv->pctldesc.pins = socdata->pins;895	priv->pctldesc.npins = socdata->npins;896	priv->pctldesc.pctlops = &uniphier_pctlops;897	priv->pctldesc.pmxops = &uniphier_pmxops;898	priv->pctldesc.confops = &uniphier_confops;899	priv->pctldesc.owner = dev->driver->owner;900 901	ret = uniphier_pinctrl_pm_init(dev, priv);902	if (ret)903		return ret;904 905	priv->pctldev = devm_pinctrl_register(dev, &priv->pctldesc, priv);906	if (IS_ERR(priv->pctldev)) {907		dev_err(dev, "failed to register UniPhier pinctrl driver\n");908		return PTR_ERR(priv->pctldev);909	}910 911	platform_set_drvdata(pdev, priv);912 913	return 0;914}915