brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · 2932d7a Raw
1105 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Pinctrl for Cirrus Logic Madera codecs4 *5 * Copyright (C) 2016-2018 Cirrus Logic6 */7 8#include <linux/err.h>9#include <linux/module.h>10#include <linux/platform_device.h>11#include <linux/property.h>12#include <linux/regmap.h>13#include <linux/seq_file.h>14#include <linux/slab.h>15 16#include <linux/pinctrl/machine.h>17#include <linux/pinctrl/pinconf-generic.h>18#include <linux/pinctrl/pinconf.h>19#include <linux/pinctrl/pinctrl.h>20#include <linux/pinctrl/pinmux.h>21 22#include <linux/mfd/madera/core.h>23#include <linux/mfd/madera/registers.h>24 25#include "../pinctrl-utils.h"26 27#include "pinctrl-madera.h"28 29/*30 * Use pin GPIO names for consistency31 * NOTE: IDs are zero-indexed for coding convenience32 */33static const struct pinctrl_pin_desc madera_pins[] = {34	PINCTRL_PIN(0, "gpio1"),35	PINCTRL_PIN(1, "gpio2"),36	PINCTRL_PIN(2, "gpio3"),37	PINCTRL_PIN(3, "gpio4"),38	PINCTRL_PIN(4, "gpio5"),39	PINCTRL_PIN(5, "gpio6"),40	PINCTRL_PIN(6, "gpio7"),41	PINCTRL_PIN(7, "gpio8"),42	PINCTRL_PIN(8, "gpio9"),43	PINCTRL_PIN(9, "gpio10"),44	PINCTRL_PIN(10, "gpio11"),45	PINCTRL_PIN(11, "gpio12"),46	PINCTRL_PIN(12, "gpio13"),47	PINCTRL_PIN(13, "gpio14"),48	PINCTRL_PIN(14, "gpio15"),49	PINCTRL_PIN(15, "gpio16"),50	PINCTRL_PIN(16, "gpio17"),51	PINCTRL_PIN(17, "gpio18"),52	PINCTRL_PIN(18, "gpio19"),53	PINCTRL_PIN(19, "gpio20"),54	PINCTRL_PIN(20, "gpio21"),55	PINCTRL_PIN(21, "gpio22"),56	PINCTRL_PIN(22, "gpio23"),57	PINCTRL_PIN(23, "gpio24"),58	PINCTRL_PIN(24, "gpio25"),59	PINCTRL_PIN(25, "gpio26"),60	PINCTRL_PIN(26, "gpio27"),61	PINCTRL_PIN(27, "gpio28"),62	PINCTRL_PIN(28, "gpio29"),63	PINCTRL_PIN(29, "gpio30"),64	PINCTRL_PIN(30, "gpio31"),65	PINCTRL_PIN(31, "gpio32"),66	PINCTRL_PIN(32, "gpio33"),67	PINCTRL_PIN(33, "gpio34"),68	PINCTRL_PIN(34, "gpio35"),69	PINCTRL_PIN(35, "gpio36"),70	PINCTRL_PIN(36, "gpio37"),71	PINCTRL_PIN(37, "gpio38"),72	PINCTRL_PIN(38, "gpio39"),73	PINCTRL_PIN(39, "gpio40"),74};75 76/*77 * All single-pin functions can be mapped to any GPIO, however pinmux applies78 * functions to pin groups and only those groups declared as supporting that79 * function. To make this work we must put each pin in its own dummy group so80 * that the functions can be described as applying to all pins.81 * Since these do not correspond to anything in the actual hardware - they are82 * merely an adaptation to pinctrl's view of the world - we use the same name83 * as the pin to avoid confusion when comparing with datasheet instructions84 */85static const char * const madera_pin_single_group_names[] = {86	"gpio1",  "gpio2",  "gpio3",  "gpio4",  "gpio5",  "gpio6",  "gpio7",87	"gpio8",  "gpio9",  "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",88	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",89	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",90	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",91	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40",92};93 94/* set of pin numbers for single-pin groups, zero-indexed */95static const unsigned int madera_pin_single_group_pins[] = {96	  0,  1,  2,  3,  4,  5,  6,97	  7,  8,  9, 10, 11, 12, 13,98	 14, 15, 16, 17, 18, 19, 20,99	 21, 22, 23, 24, 25, 26, 27,100	 28, 29, 30, 31, 32, 33, 34,101	 35, 36, 37, 38, 39,102};103 104static const char * const madera_aif1_group_names[] = { "aif1" };105static const char * const madera_aif2_group_names[] = { "aif2" };106static const char * const madera_aif3_group_names[] = { "aif3" };107static const char * const madera_aif4_group_names[] = { "aif4" };108static const char * const madera_mif1_group_names[] = { "mif1" };109static const char * const madera_mif2_group_names[] = { "mif2" };110static const char * const madera_mif3_group_names[] = { "mif3" };111static const char * const madera_dmic3_group_names[] = { "dmic3" };112static const char * const madera_dmic4_group_names[] = { "dmic4" };113static const char * const madera_dmic5_group_names[] = { "dmic5" };114static const char * const madera_dmic6_group_names[] = { "dmic6" };115static const char * const madera_spk1_group_names[] = { "pdmspk1" };116static const char * const madera_spk2_group_names[] = { "pdmspk2" };117 118/*119 * alt-functions always apply to a single pin group, other functions always120 * apply to all pins121 */122static const struct {123	const char *name;124	const char * const *group_names;125	u32 func;126} madera_mux_funcs[] = {127	{128		.name = "aif1",129		.group_names = madera_aif1_group_names,130		.func = 0x000131	},132	{133		.name = "aif2",134		.group_names = madera_aif2_group_names,135		.func = 0x000136	},137	{138		.name = "aif3",139		.group_names = madera_aif3_group_names,140		.func = 0x000141	},142	{143		.name = "aif4",144		.group_names = madera_aif4_group_names,145		.func = 0x000146	},147	{148		.name = "mif1",149		.group_names = madera_mif1_group_names,150		.func = 0x000151	},152	{153		.name = "mif2",154		.group_names = madera_mif2_group_names,155		.func = 0x000156	},157	{158		.name = "mif3",159		.group_names = madera_mif3_group_names,160		.func = 0x000161	},162	{163		.name = "dmic3",164		.group_names = madera_dmic3_group_names,165		.func = 0x000166	},167	{168		.name = "dmic4",169		.group_names = madera_dmic4_group_names,170		.func = 0x000171	},172	{173		.name = "dmic5",174		.group_names = madera_dmic5_group_names,175		.func = 0x000176	},177	{178		.name = "dmic6",179		.group_names = madera_dmic6_group_names,180		.func = 0x000181	},182	{183		.name = "pdmspk1",184		.group_names = madera_spk1_group_names,185		.func = 0x000186	},187	{188		.name = "pdmspk2",189		.group_names = madera_spk2_group_names,190		.func = 0x000191	},192	{193		.name = "io",194		.group_names = madera_pin_single_group_names,195		.func = 0x001196	},197	{198		.name = "dsp-gpio",199		.group_names = madera_pin_single_group_names,200		.func = 0x002201	},202	{203		.name = "irq1",204		.group_names = madera_pin_single_group_names,205		.func = 0x003206	},207	{208		.name = "irq2",209		.group_names = madera_pin_single_group_names,210		.func = 0x004211	},212	{213		.name = "fll1-clk",214		.group_names = madera_pin_single_group_names,215		.func = 0x010216	},217	{218		.name = "fll2-clk",219		.group_names = madera_pin_single_group_names,220		.func = 0x011221	},222	{223		.name = "fll3-clk",224		.group_names = madera_pin_single_group_names,225		.func = 0x012226	},227	{228		.name = "fllao-clk",229		.group_names = madera_pin_single_group_names,230		.func = 0x013231	},232	{233		.name = "fll1-lock",234		.group_names = madera_pin_single_group_names,235		.func = 0x018236	},237	{238		.name = "fll2-lock",239		.group_names = madera_pin_single_group_names,240		.func = 0x019241	},242	{243		.name = "fll3-lock",244		.group_names = madera_pin_single_group_names,245		.func = 0x01a246	},247	{248		.name = "fllao-lock",249		.group_names = madera_pin_single_group_names,250		.func = 0x01b251	},252	{253		.name = "opclk",254		.group_names = madera_pin_single_group_names,255		.func = 0x040256	},257	{258		.name = "opclk-async",259		.group_names = madera_pin_single_group_names,260		.func = 0x041261	},262	{263		.name = "pwm1",264		.group_names = madera_pin_single_group_names,265		.func = 0x048266	},267	{268		.name = "pwm2",269		.group_names = madera_pin_single_group_names,270		.func = 0x049271	},272	{273		.name = "spdif",274		.group_names = madera_pin_single_group_names,275		.func = 0x04c276	},277	{278		.name = "asrc1-in1-lock",279		.group_names = madera_pin_single_group_names,280		.func = 0x088281	},282	{283		.name = "asrc1-in2-lock",284		.group_names = madera_pin_single_group_names,285		.func = 0x089286	},287	{288		.name = "asrc2-in1-lock",289		.group_names = madera_pin_single_group_names,290		.func = 0x08a291	},292	{293		.name = "asrc2-in2-lock",294		.group_names = madera_pin_single_group_names,295		.func = 0x08b296	},297	{298		.name = "spkl-short-circuit",299		.group_names = madera_pin_single_group_names,300		.func = 0x0b6301	},302	{303		.name = "spkr-short-circuit",304		.group_names = madera_pin_single_group_names,305		.func = 0x0b7306	},307	{308		.name = "spk-shutdown",309		.group_names = madera_pin_single_group_names,310		.func = 0x0e0311	},312	{313		.name = "spk-overheat-shutdown",314		.group_names = madera_pin_single_group_names,315		.func = 0x0e1316	},317	{318		.name = "spk-overheat-warn",319		.group_names = madera_pin_single_group_names,320		.func = 0x0e2321	},322	{323		.name = "timer1-sts",324		.group_names = madera_pin_single_group_names,325		.func = 0x140326	},327	{328		.name = "timer2-sts",329		.group_names = madera_pin_single_group_names,330		.func = 0x141331	},332	{333		.name = "timer3-sts",334		.group_names = madera_pin_single_group_names,335		.func = 0x142336	},337	{338		.name = "timer4-sts",339		.group_names = madera_pin_single_group_names,340		.func = 0x143341	},342	{343		.name = "timer5-sts",344		.group_names = madera_pin_single_group_names,345		.func = 0x144346	},347	{348		.name = "timer6-sts",349		.group_names = madera_pin_single_group_names,350		.func = 0x145351	},352	{353		.name = "timer7-sts",354		.group_names = madera_pin_single_group_names,355		.func = 0x146356	},357	{358		.name = "timer8-sts",359		.group_names = madera_pin_single_group_names,360		.func = 0x147361	},362	{363		.name = "log1-fifo-ne",364		.group_names = madera_pin_single_group_names,365		.func = 0x150366	},367	{368		.name = "log2-fifo-ne",369		.group_names = madera_pin_single_group_names,370		.func = 0x151371	},372	{373		.name = "log3-fifo-ne",374		.group_names = madera_pin_single_group_names,375		.func = 0x152376	},377	{378		.name = "log4-fifo-ne",379		.group_names = madera_pin_single_group_names,380		.func = 0x153381	},382	{383		.name = "log5-fifo-ne",384		.group_names = madera_pin_single_group_names,385		.func = 0x154386	},387	{388		.name = "log6-fifo-ne",389		.group_names = madera_pin_single_group_names,390		.func = 0x155391	},392	{393		.name = "log7-fifo-ne",394		.group_names = madera_pin_single_group_names,395		.func = 0x156396	},397	{398		.name = "log8-fifo-ne",399		.group_names = madera_pin_single_group_names,400		.func = 0x157401	},402	{403		.name = "aux-pdm-clk",404		.group_names = madera_pin_single_group_names,405		.func = 0x280406	},407	{408		.name = "aux-pdm-dat",409		.group_names = madera_pin_single_group_names,410		.func = 0x281411	},412};413 414static u16 madera_pin_make_drv_str(struct madera_pin_private *priv,415				      unsigned int milliamps)416{417	switch (milliamps) {418	case 4:419		return 0;420	case 8:421		return 2 << MADERA_GP1_DRV_STR_SHIFT;422	default:423		break;424	}425 426	dev_warn(priv->dev, "%u mA not a valid drive strength", milliamps);427 428	return 0;429}430 431static unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv,432					      u16 regval)433{434	regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT;435 436	switch (regval) {437	case 0:438		return 4;439	case 2:440		return 8;441	default:442		return 0;443	}444}445 446static int madera_get_groups_count(struct pinctrl_dev *pctldev)447{448	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);449 450	/* Number of alt function groups plus number of single-pin groups */451	return priv->chip->n_pin_groups + priv->chip->n_pins;452}453 454static const char *madera_get_group_name(struct pinctrl_dev *pctldev,455					 unsigned int selector)456{457	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);458 459	if (selector < priv->chip->n_pin_groups)460		return priv->chip->pin_groups[selector].name;461 462	selector -= priv->chip->n_pin_groups;463	return madera_pin_single_group_names[selector];464}465 466static int madera_get_group_pins(struct pinctrl_dev *pctldev,467				 unsigned int selector,468				 const unsigned int **pins,469				 unsigned int *num_pins)470{471	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);472 473	if (selector < priv->chip->n_pin_groups) {474		*pins = priv->chip->pin_groups[selector].pins;475		*num_pins = priv->chip->pin_groups[selector].n_pins;476	} else {477		/* return the dummy group for a single pin */478		selector -= priv->chip->n_pin_groups;479		*pins = &madera_pin_single_group_pins[selector];480		*num_pins = 1;481	}482	return 0;483}484 485static void madera_pin_dbg_show_fn(struct madera_pin_private *priv,486				   struct seq_file *s,487				   unsigned int pin, unsigned int fn)488{489	const struct madera_pin_chip *chip = priv->chip;490	int i, g_pin;491 492	if (fn != 0) {493		for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) {494			if (madera_mux_funcs[i].func == fn) {495				seq_printf(s, " FN=%s",496					   madera_mux_funcs[i].name);497				return;498			}499		}500		return;	/* ignore unknown function values */501	}502 503	/* alt function */504	for (i = 0; i < chip->n_pin_groups; ++i) {505		for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) {506			if (chip->pin_groups[i].pins[g_pin] == pin) {507				seq_printf(s, " FN=%s",508					   chip->pin_groups[i].name);509				return;510			}511		}512	}513}514 515static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,516					       struct seq_file *s,517					       unsigned int pin)518{519	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);520	unsigned int conf[2];521	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);522	unsigned int fn;523	int ret;524 525	ret = regmap_read(priv->madera->regmap, reg, &conf[0]);526	if (ret)527		return;528 529	ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);530	if (ret)531		return;532 533	seq_printf(s, "%04x:%04x", conf[0], conf[1]);534 535	fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT;536	madera_pin_dbg_show_fn(priv, s, pin, fn);537 538	/* State of direction bit is only relevant if function==1 */539	if (fn == 1) {540		if (conf[1] & MADERA_GP1_DIR_MASK)541			seq_puts(s, " IN");542		else543			seq_puts(s, " OUT");544	}545 546	if (conf[1] & MADERA_GP1_PU_MASK)547		seq_puts(s, " PU");548 549	if (conf[1] & MADERA_GP1_PD_MASK)550		seq_puts(s, " PD");551 552	if (conf[0] & MADERA_GP1_DB_MASK)553		seq_puts(s, " DB");554 555	if (conf[0] & MADERA_GP1_OP_CFG_MASK)556		seq_puts(s, " OD");557	else558		seq_puts(s, " CMOS");559 560	seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));561 562	if (conf[0] & MADERA_GP1_IP_CFG_MASK)563		seq_puts(s, " SCHMITT");564}565 566static const struct pinctrl_ops madera_pin_group_ops = {567	.get_groups_count = madera_get_groups_count,568	.get_group_name = madera_get_group_name,569	.get_group_pins = madera_get_group_pins,570#if IS_ENABLED(CONFIG_OF)571	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,572	.dt_free_map = pinctrl_utils_free_map,573#endif574#if IS_ENABLED(CONFIG_DEBUG_FS)575	.pin_dbg_show = madera_pin_dbg_show,576#endif577};578 579static int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev)580{581	return ARRAY_SIZE(madera_mux_funcs);582}583 584static const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev,585					    unsigned int selector)586{587	return madera_mux_funcs[selector].name;588}589 590static int madera_mux_get_groups(struct pinctrl_dev *pctldev,591				 unsigned int selector,592				 const char * const **groups,593				 unsigned int * const num_groups)594{595	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);596 597	*groups = madera_mux_funcs[selector].group_names;598 599	if (madera_mux_funcs[selector].func == 0) {600		/* alt func always maps to a single group */601		*num_groups = 1;602	} else {603		/* other funcs map to all available gpio pins */604		*num_groups = priv->chip->n_pins;605	}606 607	return 0;608}609 610static int madera_mux_set_mux(struct pinctrl_dev *pctldev,611			      unsigned int selector,612			      unsigned int group)613{614	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);615	struct madera *madera = priv->madera;616	const struct madera_pin_groups *pin_group = priv->chip->pin_groups;617	unsigned int n_chip_groups = priv->chip->n_pin_groups;618	const char *func_name = madera_mux_funcs[selector].name;619	unsigned int reg;620	int i, ret = 0;621 622	dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",623		__func__, selector, func_name, group,624		madera_get_group_name(pctldev, group));625 626	if (madera_mux_funcs[selector].func == 0) {627		/* alt func pin assignments are codec-specific */628		for (i = 0; i < n_chip_groups; ++i) {629			if (strcmp(func_name, pin_group->name) == 0)630				break;631 632			++pin_group;633		}634 635		if (i == n_chip_groups)636			return -EINVAL;637 638		for (i = 0; i < pin_group->n_pins; ++i) {639			reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]);640 641			dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n",642				__func__, reg);643 644			ret = regmap_update_bits(madera->regmap, reg,645						 MADERA_GP1_FN_MASK, 0);646			if (ret)647				break;648 649		}650	} else {651		/*652		 * for other funcs the group will be the gpio number and will653		 * be offset by the number of chip-specific functions at the654		 * start of the group list655		 */656		group -= n_chip_groups;657		reg = MADERA_GPIO1_CTRL_1 + (2 * group);658 659		dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n",660			__func__, reg, madera_mux_funcs[selector].func);661 662		ret = regmap_update_bits(madera->regmap,663					 reg,664					 MADERA_GP1_FN_MASK,665					 madera_mux_funcs[selector].func);666	}667 668	if (ret)669		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);670 671	return ret;672}673 674static int madera_gpio_set_direction(struct pinctrl_dev *pctldev,675				     struct pinctrl_gpio_range *range,676				     unsigned int offset,677				     bool input)678{679	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);680	struct madera *madera = priv->madera;681	unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset);682	unsigned int val;683	int ret;684 685	if (input)686		val = MADERA_GP1_DIR;687	else688		val = 0;689 690	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_DIR_MASK, val);691	if (ret)692		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);693 694	return ret;695}696 697static int madera_gpio_request_enable(struct pinctrl_dev *pctldev,698				      struct pinctrl_gpio_range *range,699				      unsigned int offset)700{701	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);702	struct madera *madera = priv->madera;703	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);704	int ret;705 706	/* put the pin into GPIO mode */707	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);708	if (ret)709		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);710 711	return ret;712}713 714static void madera_gpio_disable_free(struct pinctrl_dev *pctldev,715				     struct pinctrl_gpio_range *range,716				     unsigned int offset)717{718	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);719	struct madera *madera = priv->madera;720	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);721	int ret;722 723	/* disable GPIO by setting to GPIO IN */724	madera_gpio_set_direction(pctldev, range, offset, true);725 726	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);727	if (ret)728		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);729}730 731static const struct pinmux_ops madera_pin_mux_ops = {732	.get_functions_count = madera_mux_get_funcs_count,733	.get_function_name = madera_mux_get_func_name,734	.get_function_groups = madera_mux_get_groups,735	.set_mux = madera_mux_set_mux,736	.gpio_request_enable = madera_gpio_request_enable,737	.gpio_disable_free = madera_gpio_disable_free,738	.gpio_set_direction = madera_gpio_set_direction,739	.strict = true, /* GPIO and other functions are exclusive */740};741 742static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,743			       unsigned long *config)744{745	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);746	unsigned int param = pinconf_to_config_param(*config);747	unsigned int result = 0;748	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);749	unsigned int conf[2];750	int ret;751 752	ret = regmap_read(priv->madera->regmap, reg, &conf[0]);753	if (!ret)754		ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);755 756	if (ret) {757		dev_err(priv->dev, "Failed to read GP%d conf (%d)\n",758			pin + 1, ret);759		return ret;760	}761 762	switch (param) {763	case PIN_CONFIG_BIAS_BUS_HOLD:764		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;765		if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD))766			result = 1;767		break;768	case PIN_CONFIG_BIAS_DISABLE:769		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;770		if (!conf[1])771			result = 1;772		break;773	case PIN_CONFIG_BIAS_PULL_DOWN:774		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;775		if (conf[1] == MADERA_GP1_PD_MASK)776			result = 1;777		break;778	case PIN_CONFIG_BIAS_PULL_UP:779		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;780		if (conf[1] == MADERA_GP1_PU_MASK)781			result = 1;782		break;783	case PIN_CONFIG_DRIVE_OPEN_DRAIN:784		if (conf[0] & MADERA_GP1_OP_CFG_MASK)785			result = 1;786		break;787	case PIN_CONFIG_DRIVE_PUSH_PULL:788		if (!(conf[0] & MADERA_GP1_OP_CFG_MASK))789			result = 1;790		break;791	case PIN_CONFIG_DRIVE_STRENGTH:792		result = madera_pin_unmake_drv_str(priv, conf[1]);793		break;794	case PIN_CONFIG_INPUT_DEBOUNCE:795		if (conf[0] & MADERA_GP1_DB_MASK)796			result = 1;797		break;798	case PIN_CONFIG_INPUT_ENABLE:799		if (conf[0] & MADERA_GP1_DIR_MASK)800			result = 1;801		break;802	case PIN_CONFIG_INPUT_SCHMITT:803	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:804		if (conf[0] & MADERA_GP1_IP_CFG_MASK)805			result = 1;806		break;807	case PIN_CONFIG_OUTPUT:808		if ((conf[1] & MADERA_GP1_DIR_MASK) &&809		    (conf[0] & MADERA_GP1_LVL_MASK))810			result = 1;811		break;812	default:813		return -ENOTSUPP;814	}815 816	*config = pinconf_to_config_packed(param, result);817 818	return 0;819}820 821static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,822			       unsigned long *configs, unsigned int num_configs)823{824	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);825	u16 conf[2] = {0, 0};826	u16 mask[2] = {0, 0};827	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);828	unsigned int val;829	int ret;830 831	while (num_configs) {832		dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);833 834		switch (pinconf_to_config_param(*configs)) {835		case PIN_CONFIG_BIAS_BUS_HOLD:836			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;837			conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;838			break;839		case PIN_CONFIG_BIAS_DISABLE:840			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;841			conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);842			break;843		case PIN_CONFIG_BIAS_PULL_DOWN:844			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;845			conf[1] |= MADERA_GP1_PD;846			conf[1] &= ~MADERA_GP1_PU;847			break;848		case PIN_CONFIG_BIAS_PULL_UP:849			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;850			conf[1] |= MADERA_GP1_PU;851			conf[1] &= ~MADERA_GP1_PD;852			break;853		case PIN_CONFIG_DRIVE_OPEN_DRAIN:854			mask[0] |= MADERA_GP1_OP_CFG_MASK;855			conf[0] |= MADERA_GP1_OP_CFG;856			break;857		case PIN_CONFIG_DRIVE_PUSH_PULL:858			mask[0] |= MADERA_GP1_OP_CFG_MASK;859			conf[0] &= ~MADERA_GP1_OP_CFG;860			break;861		case PIN_CONFIG_DRIVE_STRENGTH:862			val = pinconf_to_config_argument(*configs);863			mask[1] |= MADERA_GP1_DRV_STR_MASK;864			conf[1] &= ~MADERA_GP1_DRV_STR_MASK;865			conf[1] |= madera_pin_make_drv_str(priv, val);866			break;867		case PIN_CONFIG_INPUT_DEBOUNCE:868			mask[0] |= MADERA_GP1_DB_MASK;869 870			/*871			 * we can't configure debounce time per-pin so value872			 * is just a flag873			 */874			val = pinconf_to_config_argument(*configs);875			if (val)876				conf[0] |= MADERA_GP1_DB;877			else878				conf[0] &= ~MADERA_GP1_DB;879			break;880		case PIN_CONFIG_INPUT_ENABLE:881			val = pinconf_to_config_argument(*configs);882			mask[1] |= MADERA_GP1_DIR_MASK;883			if (val)884				conf[1] |= MADERA_GP1_DIR;885			else886				conf[1] &= ~MADERA_GP1_DIR;887			break;888		case PIN_CONFIG_INPUT_SCHMITT:889			val = pinconf_to_config_argument(*configs);890			mask[0] |= MADERA_GP1_IP_CFG;891			if (val)892				conf[0] |= MADERA_GP1_IP_CFG;893			else894				conf[0] &= ~MADERA_GP1_IP_CFG;895 896			mask[1] |= MADERA_GP1_DIR_MASK;897			conf[1] |= MADERA_GP1_DIR;898			break;899		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:900			mask[0] |= MADERA_GP1_IP_CFG;901			conf[0] |= MADERA_GP1_IP_CFG;902			mask[1] |= MADERA_GP1_DIR_MASK;903			conf[1] |= MADERA_GP1_DIR;904			break;905		case PIN_CONFIG_OUTPUT:906			val = pinconf_to_config_argument(*configs);907			mask[0] |= MADERA_GP1_LVL_MASK;908			if (val)909				conf[0] |= MADERA_GP1_LVL;910			else911				conf[0] &= ~MADERA_GP1_LVL;912 913			mask[1] |= MADERA_GP1_DIR_MASK;914			conf[1] &= ~MADERA_GP1_DIR;915			break;916		default:917			return -ENOTSUPP;918		}919 920		++configs;921		--num_configs;922	}923 924	dev_dbg(priv->dev,925		"%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",926		__func__, pin + 1, reg, conf[0], reg + 1, conf[1]);927 928	ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);929	if (ret)930		goto err;931 932	++reg;933	ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);934	if (ret)935		goto err;936 937	return 0;938 939err:940	dev_err(priv->dev,941		"Failed to write GPIO%d conf (%d) reg 0x%x\n",942		pin + 1, ret, reg);943 944	return ret;945}946 947static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,948				     unsigned int selector,949				     unsigned long *configs,950				     unsigned int num_configs)951{952	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);953	const struct madera_pin_groups *pin_group;954	unsigned int n_groups = priv->chip->n_pin_groups;955	int i, ret;956 957	dev_dbg(priv->dev, "%s setting group %s\n", __func__,958		madera_get_group_name(pctldev, selector));959 960	if (selector >= n_groups) {961		/* group is a single pin, convert to pin number and set */962		return madera_pin_conf_set(pctldev,963					   selector - n_groups,964					   configs,965					   num_configs);966	} else {967		pin_group = &priv->chip->pin_groups[selector];968 969		for (i = 0; i < pin_group->n_pins; ++i) {970			ret = madera_pin_conf_set(pctldev,971						  pin_group->pins[i],972						  configs,973						  num_configs);974			if (ret)975				return ret;976		}977	}978 979	return 0;980}981 982static const struct pinconf_ops madera_pin_conf_ops = {983	.is_generic = true,984	.pin_config_get = madera_pin_conf_get,985	.pin_config_set = madera_pin_conf_set,986	.pin_config_group_set = madera_pin_conf_group_set,987};988 989static struct pinctrl_desc madera_pin_desc = {990	.name = "madera-pinctrl",991	.pins = madera_pins,992	.pctlops = &madera_pin_group_ops,993	.pmxops = &madera_pin_mux_ops,994	.confops = &madera_pin_conf_ops,995	.owner = THIS_MODULE,996};997 998static int madera_pin_probe(struct platform_device *pdev)999{1000	struct madera *madera = dev_get_drvdata(pdev->dev.parent);1001	const struct madera_pdata *pdata = &madera->pdata;1002	struct madera_pin_private *priv;1003	int ret;1004 1005	BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) !=1006		     ARRAY_SIZE(madera_pin_single_group_pins));1007 1008	dev_dbg(&pdev->dev, "%s\n", __func__);1009 1010	device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));1011 1012	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);1013	if (!priv)1014		return -ENOMEM;1015 1016	priv->dev = &pdev->dev;1017	priv->madera = madera;1018 1019	switch (madera->type) {1020	case CS47L15:1021		if (IS_ENABLED(CONFIG_PINCTRL_CS47L15))1022			priv->chip = &cs47l15_pin_chip;1023		break;1024	case CS47L35:1025		if (IS_ENABLED(CONFIG_PINCTRL_CS47L35))1026			priv->chip = &cs47l35_pin_chip;1027		break;1028	case CS47L85:1029	case WM1840:1030		if (IS_ENABLED(CONFIG_PINCTRL_CS47L85))1031			priv->chip = &cs47l85_pin_chip;1032		break;1033	case CS47L90:1034	case CS47L91:1035		if (IS_ENABLED(CONFIG_PINCTRL_CS47L90))1036			priv->chip = &cs47l90_pin_chip;1037		break;1038	case CS42L92:1039	case CS47L92:1040	case CS47L93:1041		if (IS_ENABLED(CONFIG_PINCTRL_CS47L92))1042			priv->chip = &cs47l92_pin_chip;1043		break;1044	default:1045		break;1046	}1047 1048	if (!priv->chip)1049		return -ENODEV;1050 1051	madera_pin_desc.npins = priv->chip->n_pins;1052 1053	ret = devm_pinctrl_register_and_init(&pdev->dev,1054					     &madera_pin_desc,1055					     priv,1056					     &priv->pctl);1057	if (ret) {1058		dev_err(priv->dev, "Failed pinctrl register (%d)\n", ret);1059		return ret;1060	}1061 1062	/* if the configuration is provided through pdata, apply it */1063	if (pdata->gpio_configs) {1064		ret = pinctrl_register_mappings(pdata->gpio_configs,1065						pdata->n_gpio_configs);1066		if (ret)1067			return dev_err_probe(priv->dev, ret,1068						"Failed to register pdata mappings\n");1069	}1070 1071	ret = pinctrl_enable(priv->pctl);1072	if (ret) {1073		dev_err(priv->dev, "Failed to enable pinctrl (%d)\n", ret);1074		return ret;1075	}1076 1077	platform_set_drvdata(pdev, priv);1078 1079	dev_dbg(priv->dev, "pinctrl probed ok\n");1080 1081	return 0;1082}1083 1084static void madera_pin_remove(struct platform_device *pdev)1085{1086	struct madera_pin_private *priv = platform_get_drvdata(pdev);1087 1088	if (priv->madera->pdata.gpio_configs)1089		pinctrl_unregister_mappings(priv->madera->pdata.gpio_configs);1090}1091 1092static struct platform_driver madera_pin_driver = {1093	.probe = madera_pin_probe,1094	.remove_new = madera_pin_remove,1095	.driver = {1096		.name = "madera-pinctrl",1097	},1098};1099 1100module_platform_driver(madera_pin_driver);1101 1102MODULE_DESCRIPTION("Madera pinctrl driver");1103MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");1104MODULE_LICENSE("GPL v2");1105