brintos

brintos / linux-shallow public Read only

0
0
Text · 16.3 KiB · 628b60c Raw
605 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// CS42L43 Pinctrl and GPIO driver4//5// Copyright (c) 2023 Cirrus Logic, Inc. and6//                    Cirrus Logic International Semiconductor Ltd.7 8#include <linux/array_size.h>9#include <linux/bits.h>10#include <linux/build_bug.h>11#include <linux/err.h>12#include <linux/gpio/driver.h>13#include <linux/mfd/cs42l43.h>14#include <linux/mfd/cs42l43-regs.h>15#include <linux/module.h>16#include <linux/of.h>17#include <linux/platform_device.h>18#include <linux/pm_runtime.h>19#include <linux/regmap.h>20#include <linux/string_choices.h>21 22#include <linux/pinctrl/consumer.h>23#include <linux/pinctrl/pinctrl.h>24#include <linux/pinctrl/pinconf.h>25#include <linux/pinctrl/pinconf-generic.h>26#include <linux/pinctrl/pinmux.h>27 28#include "../pinctrl-utils.h"29 30#define CS42L43_NUM_GPIOS 331 32struct cs42l43_pin {33	struct gpio_chip gpio_chip;34 35	struct device *dev;36	struct regmap *regmap;37	bool shutters_locked;38};39 40struct cs42l43_pin_data {41	unsigned int reg;42	unsigned int shift;43	unsigned int mask;44};45 46#define CS42L43_PIN(_number, _name, _reg, _field) { \47	.number = _number, .name = _name, \48	.drv_data = &((struct cs42l43_pin_data){ \49		.reg = CS42L43_##_reg, \50		.shift = CS42L43_##_field##_DRV_SHIFT, \51		.mask = CS42L43_##_field##_DRV_MASK, \52	}), \53}54 55static const struct pinctrl_pin_desc cs42l43_pin_pins[] = {56	CS42L43_PIN(0,	"gpio1",	DRV_CTRL4,	GPIO1),57	CS42L43_PIN(1,	"gpio2",	DRV_CTRL4,	GPIO2),58	CS42L43_PIN(2,	"gpio3",	DRV_CTRL4,	GPIO3),59	CS42L43_PIN(3,	"asp_dout",	DRV_CTRL1,	ASP_DOUT),60	CS42L43_PIN(4,	"asp_fsync",	DRV_CTRL1,	ASP_FSYNC),61	CS42L43_PIN(5,	"asp_bclk",	DRV_CTRL1,	ASP_BCLK),62	CS42L43_PIN(6,	"pdmout2_clk",	DRV_CTRL3,	PDMOUT2_CLK),63	CS42L43_PIN(7,	"pdmout2_data",	DRV_CTRL3,	PDMOUT2_DATA),64	CS42L43_PIN(8,	"pdmout1_clk",	DRV_CTRL3,	PDMOUT1_CLK),65	CS42L43_PIN(9,	"pdmout1_data",	DRV_CTRL3,	PDMOUT1_DATA),66	CS42L43_PIN(10,	"i2c_sda",	DRV_CTRL3,	I2C_SDA),67	CS42L43_PIN(11,	"i2c_scl",	DRV_CTRL_5,	I2C_SCL),68	CS42L43_PIN(12,	"spi_miso",	DRV_CTRL3,	SPI_MISO),69	CS42L43_PIN(13,	"spi_sck",	DRV_CTRL_5,	SPI_SCK),70	CS42L43_PIN(14,	"spi_ssb",	DRV_CTRL_5,	SPI_SSB),71};72 73static const unsigned int cs42l43_pin_gpio1_pins[] = { 0 };74static const unsigned int cs42l43_pin_gpio2_pins[] = { 1 };75static const unsigned int cs42l43_pin_gpio3_pins[] = { 2 };76static const unsigned int cs42l43_pin_asp_pins[] = { 3, 4, 5 };77static const unsigned int cs42l43_pin_pdmout2_pins[] = { 6, 7 };78static const unsigned int cs42l43_pin_pdmout1_pins[] = { 8, 9 };79static const unsigned int cs42l43_pin_i2c_pins[] = { 10, 11 };80static const unsigned int cs42l43_pin_spi_pins[] = { 12, 13, 14 };81 82#define CS42L43_PINGROUP(_name) \83	PINCTRL_PINGROUP(#_name, cs42l43_pin_##_name##_pins, \84			 ARRAY_SIZE(cs42l43_pin_##_name##_pins))85 86static const struct pingroup cs42l43_pin_groups[] = {87	CS42L43_PINGROUP(gpio1),88	CS42L43_PINGROUP(gpio2),89	CS42L43_PINGROUP(gpio3),90	CS42L43_PINGROUP(asp),91	CS42L43_PINGROUP(pdmout2),92	CS42L43_PINGROUP(pdmout1),93	CS42L43_PINGROUP(i2c),94	CS42L43_PINGROUP(spi),95};96 97static int cs42l43_pin_get_groups_count(struct pinctrl_dev *pctldev)98{99	return ARRAY_SIZE(cs42l43_pin_groups);100}101 102static const char *cs42l43_pin_get_group_name(struct pinctrl_dev *pctldev,103					      unsigned int group_idx)104{105	return cs42l43_pin_groups[group_idx].name;106}107 108static int cs42l43_pin_get_group_pins(struct pinctrl_dev *pctldev,109				      unsigned int group_idx,110				      const unsigned int **pins,111				      unsigned int *num_pins)112{113	*pins = cs42l43_pin_groups[group_idx].pins;114	*num_pins = cs42l43_pin_groups[group_idx].npins;115 116	return 0;117}118 119static const struct pinctrl_ops cs42l43_pin_group_ops = {120	.get_groups_count = cs42l43_pin_get_groups_count,121	.get_group_name = cs42l43_pin_get_group_name,122	.get_group_pins = cs42l43_pin_get_group_pins,123#if IS_ENABLED(CONFIG_OF)124	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,125	.dt_free_map = pinconf_generic_dt_free_map,126#endif127};128 129enum cs42l43_pin_funcs {130	CS42L43_FUNC_GPIO,131	CS42L43_FUNC_SPDIF,132	CS42L43_FUNC_IRQ,133	CS42L43_FUNC_MIC_SHT,134	CS42L43_FUNC_SPK_SHT,135	CS42L43_FUNC_MAX136};137 138static const char * const cs42l43_pin_funcs[] = {139	"gpio", "spdif", "irq", "mic-shutter", "spk-shutter",140};141 142static const char * const cs42l43_pin_gpio_groups[] = { "gpio1", "gpio3" };143static const char * const cs42l43_pin_spdif_groups[] = { "gpio3" };144static const char * const cs42l43_pin_irq_groups[] = { "gpio1" };145static const char * const cs42l43_pin_shutter_groups[] = { "gpio1", "gpio2", "gpio3" };146 147static const struct pinfunction cs42l43_pin_func_groups[] = {148	PINCTRL_PINFUNCTION("gpio", cs42l43_pin_gpio_groups,149			    ARRAY_SIZE(cs42l43_pin_gpio_groups)),150	PINCTRL_PINFUNCTION("spdif", cs42l43_pin_spdif_groups,151			    ARRAY_SIZE(cs42l43_pin_spdif_groups)),152	PINCTRL_PINFUNCTION("irq",  cs42l43_pin_irq_groups,153			    ARRAY_SIZE(cs42l43_pin_irq_groups)),154	PINCTRL_PINFUNCTION("mic-shutter", cs42l43_pin_shutter_groups,155			    ARRAY_SIZE(cs42l43_pin_shutter_groups)),156	PINCTRL_PINFUNCTION("spk-shutter", cs42l43_pin_shutter_groups,157			    ARRAY_SIZE(cs42l43_pin_shutter_groups)),158};159 160static_assert(ARRAY_SIZE(cs42l43_pin_funcs) == CS42L43_FUNC_MAX);161static_assert(ARRAY_SIZE(cs42l43_pin_func_groups) == CS42L43_FUNC_MAX);162 163static int cs42l43_pin_get_func_count(struct pinctrl_dev *pctldev)164{165	return ARRAY_SIZE(cs42l43_pin_funcs);166}167 168static const char *cs42l43_pin_get_func_name(struct pinctrl_dev *pctldev,169					     unsigned int func_idx)170{171	return cs42l43_pin_funcs[func_idx];172}173 174static int cs42l43_pin_get_func_groups(struct pinctrl_dev *pctldev,175				       unsigned int func_idx,176				       const char * const **groups,177				       unsigned int * const num_groups)178{179	*groups = cs42l43_pin_func_groups[func_idx].groups;180	*num_groups = cs42l43_pin_func_groups[func_idx].ngroups;181 182	return 0;183}184 185static int cs42l43_pin_set_mux(struct pinctrl_dev *pctldev,186			       unsigned int func_idx, unsigned int group_idx)187{188	struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);189	unsigned int reg, mask, val;190 191	dev_dbg(priv->dev, "Setting %s to %s\n",192		cs42l43_pin_groups[group_idx].name, cs42l43_pin_funcs[func_idx]);193 194	switch (func_idx) {195	case CS42L43_FUNC_MIC_SHT:196		reg = CS42L43_SHUTTER_CONTROL;197		mask = CS42L43_MIC_SHUTTER_CFG_MASK;198		val = 0x2 << (group_idx + CS42L43_MIC_SHUTTER_CFG_SHIFT);199		break;200	case CS42L43_FUNC_SPK_SHT:201		reg = CS42L43_SHUTTER_CONTROL;202		mask = CS42L43_SPK_SHUTTER_CFG_MASK;203		val = 0x2 << (group_idx + CS42L43_SPK_SHUTTER_CFG_SHIFT);204		break;205	default:206		reg = CS42L43_GPIO_FN_SEL;207		mask = BIT(group_idx + CS42L43_GPIO1_FN_SEL_SHIFT);208		val = (func_idx == CS42L43_FUNC_GPIO) ?209				(0x1 << (group_idx + CS42L43_GPIO1_FN_SEL_SHIFT)) : 0;210		break;211	}212 213	if (priv->shutters_locked && reg == CS42L43_SHUTTER_CONTROL) {214		dev_err(priv->dev, "Shutter configuration not available\n");215		return -EPERM;216	}217 218	return regmap_update_bits(priv->regmap, reg, mask, val);219}220 221static int cs42l43_gpio_set_direction(struct pinctrl_dev *pctldev,222				      struct pinctrl_gpio_range *range,223				      unsigned int offset, bool input)224{225	struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);226	unsigned int shift = offset + CS42L43_GPIO1_DIR_SHIFT;227	int ret;228 229	dev_dbg(priv->dev, "Setting gpio%d to %s\n",230		offset + 1, input ? "input" : "output");231 232	ret = pm_runtime_resume_and_get(priv->dev);233	if (ret) {234		dev_err(priv->dev, "Failed to resume for direction: %d\n", ret);235		return ret;236	}237 238	ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1,239				 BIT(shift), !!input << shift);240	if (ret)241		dev_err(priv->dev, "Failed to set gpio%d direction: %d\n",242			offset + 1, ret);243 244	pm_runtime_put(priv->dev);245 246	return ret;247}248 249static int cs42l43_gpio_request_enable(struct pinctrl_dev *pctldev,250				       struct pinctrl_gpio_range *range,251				       unsigned int offset)252{253	return cs42l43_pin_set_mux(pctldev, 0, offset);254}255 256static void cs42l43_gpio_disable_free(struct pinctrl_dev *pctldev,257				      struct pinctrl_gpio_range *range,258				      unsigned int offset)259{260	cs42l43_gpio_set_direction(pctldev, range, offset, true);261}262 263static const struct pinmux_ops cs42l43_pin_mux_ops = {264	.get_functions_count	= cs42l43_pin_get_func_count,265	.get_function_name	= cs42l43_pin_get_func_name,266	.get_function_groups	= cs42l43_pin_get_func_groups,267 268	.set_mux		= cs42l43_pin_set_mux,269 270	.gpio_request_enable	= cs42l43_gpio_request_enable,271	.gpio_disable_free	= cs42l43_gpio_disable_free,272	.gpio_set_direction	= cs42l43_gpio_set_direction,273 274	.strict			= true,275};276 277static const unsigned int cs42l43_pin_drv_str_ma[] = { 1, 2, 4, 8, 9, 10, 12, 16 };278 279static int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin)280{281	const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;282	unsigned int val;283	int ret;284 285	ret = regmap_read(priv->regmap, pdat->reg, &val);286	if (ret)287		return ret;288 289	return cs42l43_pin_drv_str_ma[(val & pdat->mask) >> pdat->shift];290}291 292static int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin,293				   unsigned int ma)294{295	const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data;296	int i;297 298	for (i = 0; i < ARRAY_SIZE(cs42l43_pin_drv_str_ma); i++) {299		if (ma == cs42l43_pin_drv_str_ma[i]) {300			if ((i << pdat->shift) > pdat->mask)301				goto err;302 303			dev_dbg(priv->dev, "Set drive strength for %s to %d mA\n",304				cs42l43_pin_pins[pin].name, ma);305 306			return regmap_update_bits(priv->regmap, pdat->reg,307						  pdat->mask, i << pdat->shift);308		}309	}310 311err:312	dev_err(priv->dev, "Invalid drive strength for %s: %d mA\n",313		cs42l43_pin_pins[pin].name, ma);314	return -EINVAL;315}316 317static int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)318{319	unsigned int val;320	int ret;321 322	if (pin >= CS42L43_NUM_GPIOS)323		return -ENOTSUPP;324 325	ret = regmap_read(priv->regmap, CS42L43_GPIO_CTRL2, &val);326	if (ret)327		return ret;328 329	if (val & (CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin))330		return 0;331 332	return 85; // Debounce is roughly 85uS333}334 335static int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin,336			      unsigned int us)337{338	if (pin >= CS42L43_NUM_GPIOS)339		return -ENOTSUPP;340 341	dev_dbg(priv->dev, "Set debounce %s for %s\n",342		str_on_off(us), cs42l43_pin_pins[pin].name);343 344	return regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL2,345				  CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin,346				  !!us << pin);347}348 349static int cs42l43_pin_config_get(struct pinctrl_dev *pctldev,350				  unsigned int pin, unsigned long *config)351{352	struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);353	unsigned int param = pinconf_to_config_param(*config);354	int ret;355 356	switch (param) {357	case PIN_CONFIG_DRIVE_STRENGTH:358		ret = cs42l43_pin_get_drv_str(priv, pin);359		if (ret < 0)360			return ret;361		break;362	case PIN_CONFIG_INPUT_DEBOUNCE:363		ret = cs42l43_pin_get_db(priv, pin);364		if (ret < 0)365			return ret;366		break;367	default:368		return -ENOTSUPP;369	}370 371	*config = pinconf_to_config_packed(param, ret);372 373	return 0;374}375 376static int cs42l43_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,377				  unsigned long *configs, unsigned int num_configs)378{379	struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev);380	unsigned int val;381	int ret;382 383	while (num_configs) {384		val = pinconf_to_config_argument(*configs);385 386		switch (pinconf_to_config_param(*configs)) {387		case PIN_CONFIG_DRIVE_STRENGTH:388			ret = cs42l43_pin_set_drv_str(priv, pin, val);389			if (ret)390				return ret;391			break;392		case PIN_CONFIG_INPUT_DEBOUNCE:393			ret = cs42l43_pin_set_db(priv, pin, val);394			if (ret)395				return ret;396			break;397		default:398			return -ENOTSUPP;399		}400 401		configs++;402		num_configs--;403	}404 405	return 0;406}407 408static int cs42l43_pin_config_group_get(struct pinctrl_dev *pctldev,409					unsigned int selector, unsigned long *config)410{411	int i, ret;412 413	for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) {414		ret = cs42l43_pin_config_get(pctldev,415					     cs42l43_pin_groups[selector].pins[i],416					     config);417		if (ret)418			return ret;419	}420 421	return 0;422}423 424static int cs42l43_pin_config_group_set(struct pinctrl_dev *pctldev,425					unsigned int selector,426					unsigned long *configs,427					unsigned int num_configs)428{429	int i, ret;430 431	for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) {432		ret = cs42l43_pin_config_set(pctldev,433					     cs42l43_pin_groups[selector].pins[i],434					     configs, num_configs);435		if (ret)436			return ret;437	}438 439	return 0;440}441 442static const struct pinconf_ops cs42l43_pin_conf_ops = {443	.is_generic		= true,444 445	.pin_config_get		= cs42l43_pin_config_get,446	.pin_config_set		= cs42l43_pin_config_set,447	.pin_config_group_get	= cs42l43_pin_config_group_get,448	.pin_config_group_set	= cs42l43_pin_config_group_set,449};450 451static struct pinctrl_desc cs42l43_pin_desc = {452	.name		= "cs42l43-pinctrl",453	.owner		= THIS_MODULE,454 455	.pins		= cs42l43_pin_pins,456	.npins		= ARRAY_SIZE(cs42l43_pin_pins),457 458	.pctlops	= &cs42l43_pin_group_ops,459	.pmxops		= &cs42l43_pin_mux_ops,460	.confops	= &cs42l43_pin_conf_ops,461};462 463static int cs42l43_gpio_get(struct gpio_chip *chip, unsigned int offset)464{465	struct cs42l43_pin *priv = gpiochip_get_data(chip);466	unsigned int val;467	int ret;468 469	ret = pm_runtime_resume_and_get(priv->dev);470	if (ret) {471		dev_err(priv->dev, "Failed to resume for get: %d\n", ret);472		return ret;473	}474 475	ret = regmap_read(priv->regmap, CS42L43_GPIO_STS, &val);476	if (ret)477		dev_err(priv->dev, "Failed to get gpio%d: %d\n", offset + 1, ret);478	else479		ret = !!(val & BIT(offset + CS42L43_GPIO1_STS_SHIFT));480 481	pm_runtime_put(priv->dev);482 483	return ret;484}485 486static void cs42l43_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)487{488	struct cs42l43_pin *priv = gpiochip_get_data(chip);489	unsigned int shift = offset + CS42L43_GPIO1_LVL_SHIFT;490	int ret;491 492	dev_dbg(priv->dev, "Setting gpio%d to %s\n",493		offset + 1, str_high_low(value));494 495	ret = pm_runtime_resume_and_get(priv->dev);496	if (ret) {497		dev_err(priv->dev, "Failed to resume for set: %d\n", ret);498		return;499	}500 501	ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1,502				 BIT(shift), value << shift);503	if (ret)504		dev_err(priv->dev, "Failed to set gpio%d: %d\n", offset + 1, ret);505 506	pm_runtime_put(priv->dev);507}508 509static int cs42l43_gpio_direction_out(struct gpio_chip *chip,510				      unsigned int offset, int value)511{512	cs42l43_gpio_set(chip, offset, value);513 514	return pinctrl_gpio_direction_output(chip, offset);515}516 517static int cs42l43_gpio_add_pin_ranges(struct gpio_chip *chip)518{519	struct cs42l43_pin *priv = gpiochip_get_data(chip);520	int ret;521 522	ret = gpiochip_add_pin_range(&priv->gpio_chip, priv->gpio_chip.label,523				     0, 0, CS42L43_NUM_GPIOS);524	if (ret)525		dev_err(priv->dev, "Failed to add GPIO pin range: %d\n", ret);526 527	return ret;528}529 530static int cs42l43_pin_probe(struct platform_device *pdev)531{532	struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent);533	struct cs42l43_pin *priv;534	struct pinctrl_dev *pctldev;535	struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev);536	int ret;537 538	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);539	if (!priv)540		return -ENOMEM;541 542	priv->dev = &pdev->dev;543	priv->regmap = cs42l43->regmap;544 545	priv->shutters_locked = cs42l43->hw_lock;546 547	priv->gpio_chip.request = gpiochip_generic_request;548	priv->gpio_chip.free = gpiochip_generic_free;549	priv->gpio_chip.direction_input = pinctrl_gpio_direction_input;550	priv->gpio_chip.direction_output = cs42l43_gpio_direction_out;551	priv->gpio_chip.add_pin_ranges = cs42l43_gpio_add_pin_ranges;552	priv->gpio_chip.get = cs42l43_gpio_get;553	priv->gpio_chip.set = cs42l43_gpio_set;554	priv->gpio_chip.label = dev_name(priv->dev);555	priv->gpio_chip.parent = priv->dev;556	priv->gpio_chip.can_sleep = true;557	priv->gpio_chip.base = -1;558	priv->gpio_chip.ngpio = CS42L43_NUM_GPIOS;559 560	if (is_of_node(fwnode)) {561		fwnode = fwnode_get_named_child_node(fwnode, "pinctrl");562 563		if (fwnode && !fwnode->dev)564			fwnode->dev = priv->dev;565	}566 567	priv->gpio_chip.fwnode = fwnode;568 569	device_set_node(priv->dev, fwnode);570 571	devm_pm_runtime_enable(priv->dev);572	pm_runtime_idle(priv->dev);573 574	pctldev = devm_pinctrl_register(priv->dev, &cs42l43_pin_desc, priv);575	if (IS_ERR(pctldev))576		return dev_err_probe(priv->dev, PTR_ERR(pctldev),577				     "Failed to register pinctrl\n");578 579	ret = devm_gpiochip_add_data(priv->dev, &priv->gpio_chip, priv);580	if (ret)581		return dev_err_probe(priv->dev, ret,582				     "Failed to register gpiochip\n");583 584	return 0;585}586 587static const struct platform_device_id cs42l43_pin_id_table[] = {588	{ "cs42l43-pinctrl", },589	{}590};591MODULE_DEVICE_TABLE(platform, cs42l43_pin_id_table);592 593static struct platform_driver cs42l43_pin_driver = {594	.driver = {595		.name	= "cs42l43-pinctrl",596	},597	.probe		= cs42l43_pin_probe,598	.id_table	= cs42l43_pin_id_table,599};600module_platform_driver(cs42l43_pin_driver);601 602MODULE_DESCRIPTION("CS42L43 Pinctrl Driver");603MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");604MODULE_LICENSE("GPL");605