brintos

brintos / linux-shallow public Read only

0
0
Text · 25.6 KiB · d16ece9 Raw
1012 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.4 */5 6#include <linux/gpio/driver.h>7#include <linux/module.h>8#include <linux/of.h>9#include <linux/of_irq.h>10#include <linux/platform_device.h>11#include <linux/regmap.h>12#include <linux/seq_file.h>13#include <linux/slab.h>14#include <linux/types.h>15 16#include <linux/pinctrl/pinconf-generic.h>17#include <linux/pinctrl/pinconf.h>18#include <linux/pinctrl/pinmux.h>19 20#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>21 22#include "../core.h"23#include "../pinctrl-utils.h"24 25#define PMIC_MPP_ADDRESS_RANGE			0x10026 27/*28 * Pull Up Values - it indicates whether a pull-up should be29 * applied for bidirectional mode only. The hardware ignores the30 * configuration when operating in other modes.31 */32#define PMIC_MPP_PULL_UP_0P6KOHM		033#define PMIC_MPP_PULL_UP_10KOHM			134#define PMIC_MPP_PULL_UP_30KOHM			235#define PMIC_MPP_PULL_UP_OPEN			336 37/* type registers base address bases */38#define PMIC_MPP_REG_TYPE			0x439#define PMIC_MPP_REG_SUBTYPE			0x540 41/* mpp peripheral type and subtype values */42#define PMIC_MPP_TYPE				0x1143#define PMIC_MPP_SUBTYPE_4CH_NO_ANA_OUT		0x344#define PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT	0x445#define PMIC_MPP_SUBTYPE_4CH_NO_SINK		0x546#define PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK	0x647#define PMIC_MPP_SUBTYPE_4CH_FULL_FUNC		0x748#define PMIC_MPP_SUBTYPE_8CH_FULL_FUNC		0xf49 50#define PMIC_MPP_REG_RT_STS			0x1051#define PMIC_MPP_REG_RT_STS_VAL_MASK		0x152 53/* control register base address bases */54#define PMIC_MPP_REG_MODE_CTL			0x4055#define PMIC_MPP_REG_DIG_VIN_CTL		0x4156#define PMIC_MPP_REG_DIG_PULL_CTL		0x4257#define PMIC_MPP_REG_DIG_IN_CTL			0x4358#define PMIC_MPP_REG_EN_CTL			0x4659#define PMIC_MPP_REG_AOUT_CTL			0x4860#define PMIC_MPP_REG_AIN_CTL			0x4a61#define PMIC_MPP_REG_SINK_CTL			0x4c62 63/* PMIC_MPP_REG_MODE_CTL */64#define PMIC_MPP_REG_MODE_VALUE_MASK		0x165#define PMIC_MPP_REG_MODE_FUNCTION_SHIFT	166#define PMIC_MPP_REG_MODE_FUNCTION_MASK		0x767#define PMIC_MPP_REG_MODE_DIR_SHIFT		468#define PMIC_MPP_REG_MODE_DIR_MASK		0x769 70/* PMIC_MPP_REG_DIG_VIN_CTL */71#define PMIC_MPP_REG_VIN_SHIFT			072#define PMIC_MPP_REG_VIN_MASK			0x773 74/* PMIC_MPP_REG_DIG_PULL_CTL */75#define PMIC_MPP_REG_PULL_SHIFT			076#define PMIC_MPP_REG_PULL_MASK			0x777 78/* PMIC_MPP_REG_EN_CTL */79#define PMIC_MPP_REG_MASTER_EN_SHIFT		780 81/* PMIC_MPP_REG_AIN_CTL */82#define PMIC_MPP_REG_AIN_ROUTE_SHIFT		083#define PMIC_MPP_REG_AIN_ROUTE_MASK		0x784 85#define PMIC_MPP_MODE_DIGITAL_INPUT		086#define PMIC_MPP_MODE_DIGITAL_OUTPUT		187#define PMIC_MPP_MODE_DIGITAL_BIDIR		288#define PMIC_MPP_MODE_ANALOG_BIDIR		389#define PMIC_MPP_MODE_ANALOG_INPUT		490#define PMIC_MPP_MODE_ANALOG_OUTPUT		591#define PMIC_MPP_MODE_CURRENT_SINK		692 93#define PMIC_MPP_SELECTOR_NORMAL		094#define PMIC_MPP_SELECTOR_PAIRED		195#define PMIC_MPP_SELECTOR_DTEST_FIRST		496 97#define PMIC_MPP_PHYSICAL_OFFSET		198 99/* Qualcomm specific pin configurations */100#define PMIC_MPP_CONF_AMUX_ROUTE		(PIN_CONFIG_END + 1)101#define PMIC_MPP_CONF_ANALOG_LEVEL		(PIN_CONFIG_END + 2)102#define PMIC_MPP_CONF_DTEST_SELECTOR		(PIN_CONFIG_END + 3)103#define PMIC_MPP_CONF_PAIRED			(PIN_CONFIG_END + 4)104 105/**106 * struct pmic_mpp_pad - keep current MPP settings107 * @base: Address base in SPMI device.108 * @is_enabled: Set to false when MPP should be put in high Z state.109 * @out_value: Cached pin output value.110 * @output_enabled: Set to true if MPP output logic is enabled.111 * @input_enabled: Set to true if MPP input buffer logic is enabled.112 * @paired: Pin operates in paired mode113 * @has_pullup: Pin has support to configure pullup114 * @num_sources: Number of power-sources supported by this MPP.115 * @power_source: Current power-source used.116 * @amux_input: Set the source for analog input.117 * @aout_level: Analog output level118 * @pullup: Pullup resistor value. Valid in Bidirectional mode only.119 * @function: See pmic_mpp_functions[].120 * @drive_strength: Amount of current in sink mode121 * @dtest: DTEST route selector122 */123struct pmic_mpp_pad {124	u16		base;125	bool		is_enabled;126	bool		out_value;127	bool		output_enabled;128	bool		input_enabled;129	bool		paired;130	bool		has_pullup;131	unsigned int	num_sources;132	unsigned int	power_source;133	unsigned int	amux_input;134	unsigned int	aout_level;135	unsigned int	pullup;136	unsigned int	function;137	unsigned int	drive_strength;138	unsigned int	dtest;139};140 141struct pmic_mpp_state {142	struct device	*dev;143	struct regmap	*map;144	struct pinctrl_dev *ctrl;145	struct gpio_chip chip;146};147 148static const struct pinconf_generic_params pmic_mpp_bindings[] = {149	{"qcom,amux-route",	PMIC_MPP_CONF_AMUX_ROUTE,	0},150	{"qcom,analog-level",	PMIC_MPP_CONF_ANALOG_LEVEL,	0},151	{"qcom,dtest",		PMIC_MPP_CONF_DTEST_SELECTOR,	0},152	{"qcom,paired",		PMIC_MPP_CONF_PAIRED,		0},153};154 155#ifdef CONFIG_DEBUG_FS156static const struct pin_config_item pmic_conf_items[] = {157	PCONFDUMP(PMIC_MPP_CONF_AMUX_ROUTE, "analog mux", NULL, true),158	PCONFDUMP(PMIC_MPP_CONF_ANALOG_LEVEL, "analog level", NULL, true),159	PCONFDUMP(PMIC_MPP_CONF_DTEST_SELECTOR, "dtest", NULL, true),160	PCONFDUMP(PMIC_MPP_CONF_PAIRED, "paired", NULL, false),161};162#endif163 164static const char *const pmic_mpp_groups[] = {165	"mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",166};167 168#define PMIC_MPP_DIGITAL	0169#define PMIC_MPP_ANALOG		1170#define PMIC_MPP_SINK		2171 172static const char *const pmic_mpp_functions[] = {173	"digital", "analog", "sink"174};175 176static int pmic_mpp_read(struct pmic_mpp_state *state,177			 struct pmic_mpp_pad *pad, unsigned int addr)178{179	unsigned int val;180	int ret;181 182	ret = regmap_read(state->map, pad->base + addr, &val);183	if (ret < 0)184		dev_err(state->dev, "read 0x%x failed\n", addr);185	else186		ret = val;187 188	return ret;189}190 191static int pmic_mpp_write(struct pmic_mpp_state *state,192			  struct pmic_mpp_pad *pad, unsigned int addr,193			  unsigned int val)194{195	int ret;196 197	ret = regmap_write(state->map, pad->base + addr, val);198	if (ret < 0)199		dev_err(state->dev, "write 0x%x failed\n", addr);200 201	return ret;202}203 204static int pmic_mpp_get_groups_count(struct pinctrl_dev *pctldev)205{206	/* Every PIN is a group */207	return pctldev->desc->npins;208}209 210static const char *pmic_mpp_get_group_name(struct pinctrl_dev *pctldev,211					   unsigned pin)212{213	return pctldev->desc->pins[pin].name;214}215 216static int pmic_mpp_get_group_pins(struct pinctrl_dev *pctldev,217				   unsigned pin,218				   const unsigned **pins, unsigned *num_pins)219{220	*pins = &pctldev->desc->pins[pin].number;221	*num_pins = 1;222	return 0;223}224 225static const struct pinctrl_ops pmic_mpp_pinctrl_ops = {226	.get_groups_count	= pmic_mpp_get_groups_count,227	.get_group_name		= pmic_mpp_get_group_name,228	.get_group_pins		= pmic_mpp_get_group_pins,229	.dt_node_to_map		= pinconf_generic_dt_node_to_map_group,230	.dt_free_map		= pinctrl_utils_free_map,231};232 233static int pmic_mpp_get_functions_count(struct pinctrl_dev *pctldev)234{235	return ARRAY_SIZE(pmic_mpp_functions);236}237 238static const char *pmic_mpp_get_function_name(struct pinctrl_dev *pctldev,239					      unsigned function)240{241	return pmic_mpp_functions[function];242}243 244static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev,245					unsigned function,246					const char *const **groups,247					unsigned *const num_qgroups)248{249	*groups = pmic_mpp_groups;250	*num_qgroups = pctldev->desc->npins;251	return 0;252}253 254static int pmic_mpp_write_mode_ctl(struct pmic_mpp_state *state,255				   struct pmic_mpp_pad *pad)256{257	unsigned int mode;258	unsigned int sel;259	unsigned int val;260	unsigned int en;261 262	switch (pad->function) {263	case PMIC_MPP_ANALOG:264		if (pad->input_enabled && pad->output_enabled)265			mode = PMIC_MPP_MODE_ANALOG_BIDIR;266		else if (pad->input_enabled)267			mode = PMIC_MPP_MODE_ANALOG_INPUT;268		else269			mode = PMIC_MPP_MODE_ANALOG_OUTPUT;270		break;271	case PMIC_MPP_DIGITAL:272		if (pad->input_enabled && pad->output_enabled)273			mode = PMIC_MPP_MODE_DIGITAL_BIDIR;274		else if (pad->input_enabled)275			mode = PMIC_MPP_MODE_DIGITAL_INPUT;276		else277			mode = PMIC_MPP_MODE_DIGITAL_OUTPUT;278		break;279	case PMIC_MPP_SINK:280	default:281		mode = PMIC_MPP_MODE_CURRENT_SINK;282		break;283	}284 285	if (pad->dtest)286		sel = PMIC_MPP_SELECTOR_DTEST_FIRST + pad->dtest - 1;287	else if (pad->paired)288		sel = PMIC_MPP_SELECTOR_PAIRED;289	else290		sel = PMIC_MPP_SELECTOR_NORMAL;291 292	en = !!pad->out_value;293 294	val = mode << PMIC_MPP_REG_MODE_DIR_SHIFT |295	      sel << PMIC_MPP_REG_MODE_FUNCTION_SHIFT |296	      en;297 298	return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val);299}300 301static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,302				unsigned pin)303{304	struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);305	struct pmic_mpp_pad *pad;306	unsigned int val;307	int ret;308 309	pad = pctldev->desc->pins[pin].drv_data;310 311	pad->function = function;312 313	ret = pmic_mpp_write_mode_ctl(state, pad);314	if (ret < 0)315		return ret;316 317	val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;318 319	return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);320}321 322static const struct pinmux_ops pmic_mpp_pinmux_ops = {323	.get_functions_count	= pmic_mpp_get_functions_count,324	.get_function_name	= pmic_mpp_get_function_name,325	.get_function_groups	= pmic_mpp_get_function_groups,326	.set_mux		= pmic_mpp_set_mux,327};328 329static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,330			       unsigned int pin, unsigned long *config)331{332	unsigned param = pinconf_to_config_param(*config);333	struct pmic_mpp_pad *pad;334	unsigned arg = 0;335 336	pad = pctldev->desc->pins[pin].drv_data;337 338	switch (param) {339	case PIN_CONFIG_BIAS_DISABLE:340		if (pad->pullup != PMIC_MPP_PULL_UP_OPEN)341			return -EINVAL;342		arg = 1;343		break;344	case PIN_CONFIG_BIAS_PULL_UP:345		switch (pad->pullup) {346		case PMIC_MPP_PULL_UP_0P6KOHM:347			arg = 600;348			break;349		case PMIC_MPP_PULL_UP_10KOHM:350			arg = 10000;351			break;352		case PMIC_MPP_PULL_UP_30KOHM:353			arg = 30000;354			break;355		default:356			return -EINVAL;357		}358		break;359	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:360		if (pad->is_enabled)361			return -EINVAL;362		arg = 1;363		break;364	case PIN_CONFIG_POWER_SOURCE:365		arg = pad->power_source;366		break;367	case PIN_CONFIG_INPUT_ENABLE:368		if (!pad->input_enabled)369			return -EINVAL;370		arg = 1;371		break;372	case PIN_CONFIG_OUTPUT:373		arg = pad->out_value;374		break;375	case PMIC_MPP_CONF_DTEST_SELECTOR:376		arg = pad->dtest;377		break;378	case PMIC_MPP_CONF_AMUX_ROUTE:379		arg = pad->amux_input;380		break;381	case PMIC_MPP_CONF_PAIRED:382		if (!pad->paired)383			return -EINVAL;384		arg = 1;385		break;386	case PIN_CONFIG_DRIVE_STRENGTH:387		arg = pad->drive_strength;388		break;389	case PMIC_MPP_CONF_ANALOG_LEVEL:390		arg = pad->aout_level;391		break;392	default:393		return -EINVAL;394	}395 396	/* Convert register value to pinconf value */397	*config = pinconf_to_config_packed(param, arg);398	return 0;399}400 401static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,402			       unsigned long *configs, unsigned nconfs)403{404	struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);405	struct pmic_mpp_pad *pad;406	unsigned param, arg;407	unsigned int val;408	int i, ret;409 410	pad = pctldev->desc->pins[pin].drv_data;411 412	/* Make it possible to enable the pin, by not setting high impedance */413	pad->is_enabled = true;414 415	for (i = 0; i < nconfs; i++) {416		param = pinconf_to_config_param(configs[i]);417		arg = pinconf_to_config_argument(configs[i]);418 419		switch (param) {420		case PIN_CONFIG_BIAS_DISABLE:421			pad->pullup = PMIC_MPP_PULL_UP_OPEN;422			break;423		case PIN_CONFIG_BIAS_PULL_UP:424			switch (arg) {425			case 600:426				pad->pullup = PMIC_MPP_PULL_UP_0P6KOHM;427				break;428			case 10000:429				pad->pullup = PMIC_MPP_PULL_UP_10KOHM;430				break;431			case 30000:432				pad->pullup = PMIC_MPP_PULL_UP_30KOHM;433				break;434			default:435				return -EINVAL;436			}437			break;438		case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:439			pad->is_enabled = false;440			break;441		case PIN_CONFIG_POWER_SOURCE:442			if (arg >= pad->num_sources)443				return -EINVAL;444			pad->power_source = arg;445			break;446		case PIN_CONFIG_INPUT_ENABLE:447			pad->input_enabled = arg ? true : false;448			break;449		case PIN_CONFIG_OUTPUT:450			pad->output_enabled = true;451			pad->out_value = arg;452			break;453		case PMIC_MPP_CONF_DTEST_SELECTOR:454			pad->dtest = arg;455			break;456		case PIN_CONFIG_DRIVE_STRENGTH:457			pad->drive_strength = arg;458			break;459		case PMIC_MPP_CONF_AMUX_ROUTE:460			if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4)461				return -EINVAL;462			pad->amux_input = arg;463			break;464		case PMIC_MPP_CONF_ANALOG_LEVEL:465			pad->aout_level = arg;466			break;467		case PMIC_MPP_CONF_PAIRED:468			pad->paired = !!arg;469			break;470		default:471			return -EINVAL;472		}473	}474 475	val = pad->power_source << PMIC_MPP_REG_VIN_SHIFT;476 477	ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_VIN_CTL, val);478	if (ret < 0)479		return ret;480 481	if (pad->has_pullup) {482		val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT;483 484		ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL,485				     val);486		if (ret < 0)487			return ret;488	}489 490	val = pad->amux_input & PMIC_MPP_REG_AIN_ROUTE_MASK;491 492	ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AIN_CTL, val);493	if (ret < 0)494		return ret;495 496	ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AOUT_CTL, pad->aout_level);497	if (ret < 0)498		return ret;499 500	ret = pmic_mpp_write_mode_ctl(state, pad);501	if (ret < 0)502		return ret;503 504	ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_SINK_CTL, pad->drive_strength);505	if (ret < 0)506		return ret;507 508	val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;509 510	return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);511}512 513static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,514				     struct seq_file *s, unsigned pin)515{516	struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);517	struct pmic_mpp_pad *pad;518	int ret;519 520	static const char *const biases[] = {521		"0.6kOhm", "10kOhm", "30kOhm", "Disabled"522	};523 524	pad = pctldev->desc->pins[pin].drv_data;525 526	seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET);527 528	if (!pad->is_enabled) {529		seq_puts(s, " ---");530	} else {531 532		if (pad->input_enabled) {533			ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);534			if (ret < 0)535				return;536 537			ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;538			pad->out_value = ret;539		}540 541		seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");542		seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);543		seq_printf(s, " vin-%d", pad->power_source);544		seq_printf(s, " %d", pad->aout_level);545		if (pad->has_pullup)546			seq_printf(s, " %-8s", biases[pad->pullup]);547		seq_printf(s, " %-4s", pad->out_value ? "high" : "low");548		if (pad->dtest)549			seq_printf(s, " dtest%d", pad->dtest);550		if (pad->paired)551			seq_puts(s, " paired");552	}553}554 555static const struct pinconf_ops pmic_mpp_pinconf_ops = {556	.is_generic = true,557	.pin_config_group_get		= pmic_mpp_config_get,558	.pin_config_group_set		= pmic_mpp_config_set,559	.pin_config_group_dbg_show	= pmic_mpp_config_dbg_show,560};561 562static int pmic_mpp_direction_input(struct gpio_chip *chip, unsigned pin)563{564	struct pmic_mpp_state *state = gpiochip_get_data(chip);565	unsigned long config;566 567	config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);568 569	return pmic_mpp_config_set(state->ctrl, pin, &config, 1);570}571 572static int pmic_mpp_direction_output(struct gpio_chip *chip,573				     unsigned pin, int val)574{575	struct pmic_mpp_state *state = gpiochip_get_data(chip);576	unsigned long config;577 578	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);579 580	return pmic_mpp_config_set(state->ctrl, pin, &config, 1);581}582 583static int pmic_mpp_get(struct gpio_chip *chip, unsigned pin)584{585	struct pmic_mpp_state *state = gpiochip_get_data(chip);586	struct pmic_mpp_pad *pad;587	int ret;588 589	pad = state->ctrl->desc->pins[pin].drv_data;590 591	if (pad->input_enabled) {592		ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);593		if (ret < 0)594			return ret;595 596		pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK;597	}598 599	return !!pad->out_value;600}601 602static void pmic_mpp_set(struct gpio_chip *chip, unsigned pin, int value)603{604	struct pmic_mpp_state *state = gpiochip_get_data(chip);605	unsigned long config;606 607	config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);608 609	pmic_mpp_config_set(state->ctrl, pin, &config, 1);610}611 612static int pmic_mpp_of_xlate(struct gpio_chip *chip,613			     const struct of_phandle_args *gpio_desc,614			     u32 *flags)615{616	if (chip->of_gpio_n_cells < 2)617		return -EINVAL;618 619	if (flags)620		*flags = gpio_desc->args[1];621 622	return gpio_desc->args[0] - PMIC_MPP_PHYSICAL_OFFSET;623}624 625static void pmic_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)626{627	struct pmic_mpp_state *state = gpiochip_get_data(chip);628	unsigned i;629 630	for (i = 0; i < chip->ngpio; i++) {631		pmic_mpp_config_dbg_show(state->ctrl, s, i);632		seq_puts(s, "\n");633	}634}635 636static const struct gpio_chip pmic_mpp_gpio_template = {637	.direction_input	= pmic_mpp_direction_input,638	.direction_output	= pmic_mpp_direction_output,639	.get			= pmic_mpp_get,640	.set			= pmic_mpp_set,641	.request		= gpiochip_generic_request,642	.free			= gpiochip_generic_free,643	.of_xlate		= pmic_mpp_of_xlate,644	.dbg_show		= pmic_mpp_dbg_show,645};646 647static int pmic_mpp_populate(struct pmic_mpp_state *state,648			     struct pmic_mpp_pad *pad)649{650	int type, subtype, val, dir;651	unsigned int sel;652 653	type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE);654	if (type < 0)655		return type;656 657	if (type != PMIC_MPP_TYPE) {658		dev_err(state->dev, "incorrect block type 0x%x at 0x%x\n",659			type, pad->base);660		return -ENODEV;661	}662 663	subtype = pmic_mpp_read(state, pad, PMIC_MPP_REG_SUBTYPE);664	if (subtype < 0)665		return subtype;666 667	switch (subtype) {668	case PMIC_MPP_SUBTYPE_4CH_NO_ANA_OUT:669	case PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT:670	case PMIC_MPP_SUBTYPE_4CH_NO_SINK:671	case PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK:672	case PMIC_MPP_SUBTYPE_4CH_FULL_FUNC:673		pad->num_sources = 4;674		break;675	case PMIC_MPP_SUBTYPE_8CH_FULL_FUNC:676		pad->num_sources = 8;677		break;678	default:679		dev_err(state->dev, "unknown MPP type 0x%x at 0x%x\n",680			subtype, pad->base);681		return -ENODEV;682	}683 684	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_MODE_CTL);685	if (val < 0)686		return val;687 688	pad->out_value = val & PMIC_MPP_REG_MODE_VALUE_MASK;689 690	dir = val >> PMIC_MPP_REG_MODE_DIR_SHIFT;691	dir &= PMIC_MPP_REG_MODE_DIR_MASK;692 693	switch (dir) {694	case PMIC_MPP_MODE_DIGITAL_INPUT:695		pad->input_enabled = true;696		pad->output_enabled = false;697		pad->function = PMIC_MPP_DIGITAL;698		break;699	case PMIC_MPP_MODE_DIGITAL_OUTPUT:700		pad->input_enabled = false;701		pad->output_enabled = true;702		pad->function = PMIC_MPP_DIGITAL;703		break;704	case PMIC_MPP_MODE_DIGITAL_BIDIR:705		pad->input_enabled = true;706		pad->output_enabled = true;707		pad->function = PMIC_MPP_DIGITAL;708		break;709	case PMIC_MPP_MODE_ANALOG_BIDIR:710		pad->input_enabled = true;711		pad->output_enabled = true;712		pad->function = PMIC_MPP_ANALOG;713		break;714	case PMIC_MPP_MODE_ANALOG_INPUT:715		pad->input_enabled = true;716		pad->output_enabled = false;717		pad->function = PMIC_MPP_ANALOG;718		break;719	case PMIC_MPP_MODE_ANALOG_OUTPUT:720		pad->input_enabled = false;721		pad->output_enabled = true;722		pad->function = PMIC_MPP_ANALOG;723		break;724	case PMIC_MPP_MODE_CURRENT_SINK:725		pad->input_enabled = false;726		pad->output_enabled = true;727		pad->function = PMIC_MPP_SINK;728		break;729	default:730		dev_err(state->dev, "unknown MPP direction\n");731		return -ENODEV;732	}733 734	sel = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;735	sel &= PMIC_MPP_REG_MODE_FUNCTION_MASK;736 737	if (sel >= PMIC_MPP_SELECTOR_DTEST_FIRST)738		pad->dtest = sel + 1;739	else if (sel == PMIC_MPP_SELECTOR_PAIRED)740		pad->paired = true;741 742	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL);743	if (val < 0)744		return val;745 746	pad->power_source = val >> PMIC_MPP_REG_VIN_SHIFT;747	pad->power_source &= PMIC_MPP_REG_VIN_MASK;748 749	if (subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT &&750	    subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK) {751		val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL);752		if (val < 0)753			return val;754 755		pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT;756		pad->pullup &= PMIC_MPP_REG_PULL_MASK;757		pad->has_pullup = true;758	}759 760	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AIN_CTL);761	if (val < 0)762		return val;763 764	pad->amux_input = val >> PMIC_MPP_REG_AIN_ROUTE_SHIFT;765	pad->amux_input &= PMIC_MPP_REG_AIN_ROUTE_MASK;766 767	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_SINK_CTL);768	if (val < 0)769		return val;770 771	pad->drive_strength = val;772 773	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AOUT_CTL);774	if (val < 0)775		return val;776 777	pad->aout_level = val;778 779	val = pmic_mpp_read(state, pad, PMIC_MPP_REG_EN_CTL);780	if (val < 0)781		return val;782 783	pad->is_enabled = !!val;784 785	return 0;786}787 788static int pmic_mpp_domain_translate(struct irq_domain *domain,789				      struct irq_fwspec *fwspec,790				      unsigned long *hwirq,791				      unsigned int *type)792{793	struct pmic_mpp_state *state = container_of(domain->host_data,794						     struct pmic_mpp_state,795						     chip);796 797	if (fwspec->param_count != 2 ||798	    fwspec->param[0] < 1 || fwspec->param[0] > state->chip.ngpio)799		return -EINVAL;800 801	*hwirq = fwspec->param[0] - PMIC_MPP_PHYSICAL_OFFSET;802	*type = fwspec->param[1];803 804	return 0;805}806 807static unsigned int pmic_mpp_child_offset_to_irq(struct gpio_chip *chip,808						  unsigned int offset)809{810	return offset + PMIC_MPP_PHYSICAL_OFFSET;811}812 813static int pmic_mpp_child_to_parent_hwirq(struct gpio_chip *chip,814					   unsigned int child_hwirq,815					   unsigned int child_type,816					   unsigned int *parent_hwirq,817					   unsigned int *parent_type)818{819	*parent_hwirq = child_hwirq + 0xc0;820	*parent_type = child_type;821 822	return 0;823}824 825static void pmic_mpp_irq_mask(struct irq_data *d)826{827	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);828 829	irq_chip_mask_parent(d);830	gpiochip_disable_irq(gc, irqd_to_hwirq(d));831}832 833static void pmic_mpp_irq_unmask(struct irq_data *d)834{835	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);836 837	gpiochip_enable_irq(gc, irqd_to_hwirq(d));838	irq_chip_unmask_parent(d);839}840 841static const struct irq_chip pmic_mpp_irq_chip = {842	.name = "spmi-mpp",843	.irq_ack = irq_chip_ack_parent,844	.irq_mask = pmic_mpp_irq_mask,845	.irq_unmask = pmic_mpp_irq_unmask,846	.irq_set_type = irq_chip_set_type_parent,847	.irq_set_wake = irq_chip_set_wake_parent,848	.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,849	GPIOCHIP_IRQ_RESOURCE_HELPERS,850};851 852static int pmic_mpp_probe(struct platform_device *pdev)853{854	struct irq_domain *parent_domain;855	struct device_node *parent_node;856	struct device *dev = &pdev->dev;857	struct pinctrl_pin_desc *pindesc;858	struct pinctrl_desc *pctrldesc;859	struct pmic_mpp_pad *pad, *pads;860	struct pmic_mpp_state *state;861	struct gpio_irq_chip *girq;862	int ret, npins, i;863	u32 reg;864 865	ret = of_property_read_u32(dev->of_node, "reg", &reg);866	if (ret < 0) {867		dev_err(dev, "missing base address");868		return ret;869	}870 871	npins = (uintptr_t) device_get_match_data(&pdev->dev);872 873	BUG_ON(npins > ARRAY_SIZE(pmic_mpp_groups));874 875	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);876	if (!state)877		return -ENOMEM;878 879	platform_set_drvdata(pdev, state);880 881	state->dev = &pdev->dev;882	state->map = dev_get_regmap(dev->parent, NULL);883 884	pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);885	if (!pindesc)886		return -ENOMEM;887 888	pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);889	if (!pads)890		return -ENOMEM;891 892	pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);893	if (!pctrldesc)894		return -ENOMEM;895 896	pctrldesc->pctlops = &pmic_mpp_pinctrl_ops;897	pctrldesc->pmxops = &pmic_mpp_pinmux_ops;898	pctrldesc->confops = &pmic_mpp_pinconf_ops;899	pctrldesc->owner = THIS_MODULE;900	pctrldesc->name = dev_name(dev);901	pctrldesc->pins = pindesc;902	pctrldesc->npins = npins;903 904	pctrldesc->num_custom_params = ARRAY_SIZE(pmic_mpp_bindings);905	pctrldesc->custom_params = pmic_mpp_bindings;906#ifdef CONFIG_DEBUG_FS907	pctrldesc->custom_conf_items = pmic_conf_items;908#endif909 910	for (i = 0; i < npins; i++, pindesc++) {911		pad = &pads[i];912		pindesc->drv_data = pad;913		pindesc->number = i;914		pindesc->name = pmic_mpp_groups[i];915 916		pad->base = reg + i * PMIC_MPP_ADDRESS_RANGE;917 918		ret = pmic_mpp_populate(state, pad);919		if (ret < 0)920			return ret;921	}922 923	state->chip = pmic_mpp_gpio_template;924	state->chip.parent = dev;925	state->chip.base = -1;926	state->chip.ngpio = npins;927	state->chip.label = dev_name(dev);928	state->chip.of_gpio_n_cells = 2;929	state->chip.can_sleep = false;930 931	state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);932	if (IS_ERR(state->ctrl))933		return PTR_ERR(state->ctrl);934 935	parent_node = of_irq_find_parent(state->dev->of_node);936	if (!parent_node)937		return -ENXIO;938 939	parent_domain = irq_find_host(parent_node);940	of_node_put(parent_node);941	if (!parent_domain)942		return -ENXIO;943 944	girq = &state->chip.irq;945	gpio_irq_chip_set_chip(girq, &pmic_mpp_irq_chip);946	girq->default_type = IRQ_TYPE_NONE;947	girq->handler = handle_level_irq;948	girq->fwnode = dev_fwnode(state->dev);949	girq->parent_domain = parent_domain;950	girq->child_to_parent_hwirq = pmic_mpp_child_to_parent_hwirq;951	girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell;952	girq->child_offset_to_irq = pmic_mpp_child_offset_to_irq;953	girq->child_irq_domain_ops.translate = pmic_mpp_domain_translate;954 955	ret = gpiochip_add_data(&state->chip, state);956	if (ret) {957		dev_err(state->dev, "can't add gpio chip\n");958		return ret;959	}960 961	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);962	if (ret) {963		dev_err(dev, "failed to add pin range\n");964		goto err_range;965	}966 967	return 0;968 969err_range:970	gpiochip_remove(&state->chip);971	return ret;972}973 974static void pmic_mpp_remove(struct platform_device *pdev)975{976	struct pmic_mpp_state *state = platform_get_drvdata(pdev);977 978	gpiochip_remove(&state->chip);979}980 981static const struct of_device_id pmic_mpp_of_match[] = {982	{ .compatible = "qcom,pm8019-mpp", .data = (void *) 6 },983	{ .compatible = "qcom,pm8226-mpp", .data = (void *) 8 },984	{ .compatible = "qcom,pm8841-mpp", .data = (void *) 4 },985	{ .compatible = "qcom,pm8916-mpp", .data = (void *) 4 },986	{ .compatible = "qcom,pm8941-mpp", .data = (void *) 8 },987	{ .compatible = "qcom,pm8950-mpp", .data = (void *) 4 },988	{ .compatible = "qcom,pmi8950-mpp", .data = (void *) 4 },989	{ .compatible = "qcom,pm8994-mpp", .data = (void *) 8 },990	{ .compatible = "qcom,pma8084-mpp", .data = (void *) 8 },991	{ .compatible = "qcom,pmi8994-mpp", .data = (void *) 4 },992	{ },993};994 995MODULE_DEVICE_TABLE(of, pmic_mpp_of_match);996 997static struct platform_driver pmic_mpp_driver = {998	.driver = {999		   .name = "qcom-spmi-mpp",1000		   .of_match_table = pmic_mpp_of_match,1001	},1002	.probe	= pmic_mpp_probe,1003	.remove_new = pmic_mpp_remove,1004};1005 1006module_platform_driver(pmic_mpp_driver);1007 1008MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");1009MODULE_DESCRIPTION("Qualcomm SPMI PMIC MPP pin control driver");1010MODULE_ALIAS("platform:qcom-spmi-mpp");1011MODULE_LICENSE("GPL v2");1012