brintos

brintos / linux-shallow public Read only

0
0
Text · 15.1 KiB · 2440604 Raw
597 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Realtek DHC pin controller driver4 *5 * Copyright (c) 2023 Realtek Semiconductor Corp.6 */7 8#include <linux/bitops.h>9#include <linux/io.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/of_address.h>13#include <linux/pinctrl/machine.h>14#include <linux/pinctrl/pinconf.h>15#include <linux/pinctrl/pinconf-generic.h>16#include <linux/pinctrl/pinctrl.h>17#include <linux/pinctrl/pinmux.h>18#include <linux/platform_device.h>19#include <linux/seq_file.h>20#include <linux/regmap.h>21#include <linux/slab.h>22#include "../core.h"23#include "../pinctrl-utils.h"24#include "pinctrl-rtd.h"25 26struct rtd_pinctrl {27	struct device *dev;28	struct pinctrl_dev *pcdev;29	void __iomem *base;30	struct pinctrl_desc desc;31	const struct rtd_pinctrl_desc *info;32	struct regmap *regmap_pinctrl;33};34 35/* custom pinconf parameters */36#define RTD_DRIVE_STRENGH_P (PIN_CONFIG_END + 1)37#define RTD_DRIVE_STRENGH_N (PIN_CONFIG_END + 2)38#define RTD_DUTY_CYCLE (PIN_CONFIG_END + 3)39 40static const struct pinconf_generic_params rtd_custom_bindings[] = {41	{"realtek,drive-strength-p", RTD_DRIVE_STRENGH_P, 0},42	{"realtek,drive-strength-n", RTD_DRIVE_STRENGH_N, 0},43	{"realtek,duty-cycle", RTD_DUTY_CYCLE, 0},44};45 46static int rtd_pinctrl_get_groups_count(struct pinctrl_dev *pcdev)47{48	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);49 50	return data->info->num_groups;51}52 53static const char *rtd_pinctrl_get_group_name(struct pinctrl_dev *pcdev,54					      unsigned int selector)55{56	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);57 58	return data->info->groups[selector].name;59}60 61static int rtd_pinctrl_get_group_pins(struct pinctrl_dev *pcdev,62				      unsigned int selector,63				      const unsigned int **pins,64				      unsigned int *num_pins)65{66	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);67 68	*pins = data->info->groups[selector].pins;69	*num_pins = data->info->groups[selector].num_pins;70 71	return 0;72}73 74static void rtd_pinctrl_dbg_show(struct pinctrl_dev *pcdev,75				 struct seq_file *s,76				 unsigned int offset)77{78	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);79	const struct rtd_pin_desc *mux = &data->info->muxes[offset];80	const struct rtd_pin_mux_desc *func;81	u32 val;82	u32 mask;83	u32 pin_val;84	int is_map;85 86	if (!mux->name) {87		seq_puts(s, "[not defined]");88		return;89	}90	val = readl_relaxed(data->base + mux->mux_offset);91	mask = mux->mux_mask;92	pin_val = val & mask;93 94	is_map = 0;95	func = &mux->functions[0];96	seq_puts(s, "function: ");97	while (func->name) {98		if (func->mux_value == pin_val) {99			is_map = 1;100			seq_printf(s, "[%s] ", func->name);101		} else {102			seq_printf(s, "%s ", func->name);103		}104		func++;105	}106	if (!is_map)107		seq_puts(s, "[not defined]");108}109 110static const struct pinctrl_ops rtd_pinctrl_ops = {111	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,112	.dt_free_map = pinctrl_utils_free_map,113	.get_groups_count = rtd_pinctrl_get_groups_count,114	.get_group_name = rtd_pinctrl_get_group_name,115	.get_group_pins = rtd_pinctrl_get_group_pins,116	.pin_dbg_show = rtd_pinctrl_dbg_show,117};118 119static int rtd_pinctrl_get_functions_count(struct pinctrl_dev *pcdev)120{121	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);122 123	return data->info->num_functions;124}125 126static const char *rtd_pinctrl_get_function_name(struct pinctrl_dev *pcdev,127						 unsigned int selector)128{129	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);130 131	return data->info->functions[selector].name;132}133 134static int rtd_pinctrl_get_function_groups(struct pinctrl_dev *pcdev,135					   unsigned int selector,136					   const char * const **groups,137					   unsigned int * const num_groups)138{139	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);140 141	*groups = data->info->functions[selector].groups;142	*num_groups = data->info->functions[selector].num_groups;143 144	return 0;145}146 147static const struct rtd_pin_desc *rtd_pinctrl_find_mux(struct rtd_pinctrl *data, unsigned int pin)148{149	if (data->info->muxes[pin].name)150		return &data->info->muxes[pin];151 152	return NULL;153}154 155static int rtd_pinctrl_set_one_mux(struct pinctrl_dev *pcdev,156				   unsigned int pin, const char *func_name)157{158	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);159	const struct rtd_pin_desc *mux;160	int ret = 0;161	int i;162 163	mux = rtd_pinctrl_find_mux(data, pin);164	if (!mux)165		return 0;166 167	if (!mux->functions) {168		if (!mux->name)169			dev_err(pcdev->dev, "NULL pin has no functions\n");170		else171			dev_err(pcdev->dev, "No functions available for pin %s\n", mux->name);172		return -ENOTSUPP;173	}174 175	for (i = 0; mux->functions[i].name; i++) {176		if (strcmp(mux->functions[i].name, func_name) != 0)177			continue;178		ret = regmap_update_bits(data->regmap_pinctrl, mux->mux_offset, mux->mux_mask,179					mux->functions[i].mux_value);180		return ret;181	}182 183	if (!mux->name) {184		dev_err(pcdev->dev, "NULL pin provided for function %s\n", func_name);185		return -EINVAL;186	}187 188	dev_err(pcdev->dev, "No function %s available for pin %s\n", func_name, mux->name);189 190	return -EINVAL;191}192 193static int rtd_pinctrl_set_mux(struct pinctrl_dev *pcdev,194			       unsigned int function, unsigned int group)195{196	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);197	const unsigned int *pins;198	unsigned int num_pins;199	const char *func_name;200	const char *group_name;201	int i, ret;202 203	func_name = data->info->functions[function].name;204	group_name = data->info->groups[group].name;205 206	ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins);207	if (ret) {208		dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name);209		return ret;210	}211 212	for (i = 0; i < num_pins; i++) {213		ret = rtd_pinctrl_set_one_mux(pcdev, pins[i], func_name);214		if (ret)215			return ret;216	}217 218	return 0;219}220 221static int rtd_pinctrl_gpio_request_enable(struct pinctrl_dev *pcdev,222					   struct pinctrl_gpio_range *range,223					   unsigned int offset)224{225	return rtd_pinctrl_set_one_mux(pcdev, offset, "gpio");226}227 228static const struct pinmux_ops rtd_pinmux_ops = {229	.get_functions_count = rtd_pinctrl_get_functions_count,230	.get_function_name = rtd_pinctrl_get_function_name,231	.get_function_groups = rtd_pinctrl_get_function_groups,232	.set_mux = rtd_pinctrl_set_mux,233	.gpio_request_enable = rtd_pinctrl_gpio_request_enable,234};235 236static const struct pinctrl_pin_desc237	*rtd_pinctrl_get_pin_by_number(struct rtd_pinctrl *data, int number)238{239	int i;240 241	for (i = 0; i < data->info->num_pins; i++) {242		if (data->info->pins[i].number == number)243			return &data->info->pins[i];244	}245 246	return NULL;247}248 249static const struct rtd_pin_config_desc250	*rtd_pinctrl_find_config(struct rtd_pinctrl *data, unsigned int pin)251{252	if (data->info->configs[pin].name)253		return &data->info->configs[pin];254 255	return NULL;256}257 258static const struct rtd_pin_sconfig_desc *rtd_pinctrl_find_sconfig(struct rtd_pinctrl *data,259								   unsigned int pin)260{261	int i;262	const struct pinctrl_pin_desc *pin_desc;263	const char *pin_name;264 265	pin_desc = rtd_pinctrl_get_pin_by_number(data, pin);266	if (!pin_desc)267		return NULL;268 269	pin_name = pin_desc->name;270 271	for (i = 0; i < data->info->num_sconfigs; i++) {272		if (strcmp(data->info->sconfigs[i].name, pin_name) == 0)273			return &data->info->sconfigs[i];274	}275 276	return NULL;277}278 279static int rtd_pconf_parse_conf(struct rtd_pinctrl *data,280				unsigned int pinnr,281				enum pin_config_param param,282				enum pin_config_param arg)283{284	const struct rtd_pin_config_desc *config_desc;285	const struct rtd_pin_sconfig_desc *sconfig_desc;286	u8 set_val = 0;287	u16 strength;288	u32 val;289	u32 mask;290	u32 pulsel_off, pulen_off, smt_off, curr_off, pow_off, reg_off, p_off, n_off;291	const char *name = data->info->pins[pinnr].name;292	int ret = 0;293 294	config_desc = rtd_pinctrl_find_config(data, pinnr);295	if (!config_desc) {296		dev_err(data->dev, "Not support pin config for pin: %s\n", name);297		return -ENOTSUPP;298	}299	switch ((u32)param) {300	case PIN_CONFIG_INPUT_SCHMITT:301	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:302		if (config_desc->smt_offset == NA) {303			dev_err(data->dev, "Not support input schmitt for pin: %s\n", name);304			return -ENOTSUPP;305		}306		smt_off = config_desc->base_bit + config_desc->smt_offset;307		reg_off = config_desc->reg_offset;308		set_val = arg;309 310		mask = BIT(smt_off);311		val = set_val ? BIT(smt_off) : 0;312		break;313 314	case PIN_CONFIG_DRIVE_PUSH_PULL:315		if (config_desc->pud_en_offset == NA) {316			dev_err(data->dev, "Not support push pull for pin: %s\n", name);317			return -ENOTSUPP;318		}319		pulen_off = config_desc->base_bit + config_desc->pud_en_offset;320		reg_off = config_desc->reg_offset;321 322		mask =  BIT(pulen_off);323		val = 0;324		break;325 326	case PIN_CONFIG_BIAS_DISABLE:327		if (config_desc->pud_en_offset == NA) {328			dev_err(data->dev, "Not support bias disable for pin: %s\n", name);329			return -ENOTSUPP;330		}331		pulen_off = config_desc->base_bit + config_desc->pud_en_offset;332		reg_off = config_desc->reg_offset;333 334		mask =  BIT(pulen_off);335		val = 0;336		break;337 338	case PIN_CONFIG_BIAS_PULL_UP:339		if (config_desc->pud_en_offset == NA) {340			dev_err(data->dev, "Not support bias pull up for pin:%s\n", name);341			return -ENOTSUPP;342		}343		pulen_off = config_desc->base_bit + config_desc->pud_en_offset;344		pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset;345		reg_off = config_desc->reg_offset;346 347		mask = BIT(pulen_off) | BIT(pulsel_off);348		val = mask;349		break;350 351	case PIN_CONFIG_BIAS_PULL_DOWN:352		if (config_desc->pud_en_offset == NA) {353			dev_err(data->dev, "Not support bias pull down for pin: %s\n", name);354			return -ENOTSUPP;355		}356		pulen_off = config_desc->base_bit + config_desc->pud_en_offset;357		pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset;358		reg_off = config_desc->reg_offset;359 360		mask = BIT(pulen_off) | BIT(pulsel_off);361		val = BIT(pulen_off);362		break;363 364	case PIN_CONFIG_DRIVE_STRENGTH:365		curr_off = config_desc->base_bit + config_desc->curr_offset;366		reg_off = config_desc->reg_offset;367		strength = arg;368		val = 0;369		switch (config_desc->curr_type) {370		case PADDRI_4_8:371			if (strength == 4)372				val = 0;373			else if (strength == 8)374				val = BIT(curr_off);375			else376				return -EINVAL;377			break;378		case PADDRI_2_4:379			if (strength == 2)380				val = 0;381			else if (strength == 4)382				val = BIT(curr_off);383			else384				return -EINVAL;385			break;386		case NA:387			dev_err(data->dev, "Not support drive strength for pin: %s\n", name);388			return -ENOTSUPP;389		default:390			return -EINVAL;391		}392		mask = BIT(curr_off);393		break;394 395	case PIN_CONFIG_POWER_SOURCE:396		if (config_desc->power_offset == NA) {397			dev_err(data->dev, "Not support power source for pin: %s\n", name);398			return -ENOTSUPP;399		}400		reg_off = config_desc->reg_offset;401		pow_off = config_desc->base_bit + config_desc->power_offset;402		if (pow_off >= 32) {403			reg_off += 0x4;404			pow_off -= 32;405		}406		set_val = arg;407		mask = BIT(pow_off);408		val = set_val ? mask : 0;409		break;410 411	case RTD_DRIVE_STRENGH_P:412		sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);413		if (!sconfig_desc) {414			dev_err(data->dev, "Not support P driving for pin: %s\n", name);415			return -ENOTSUPP;416		}417		set_val = arg;418		reg_off = sconfig_desc->reg_offset;419		p_off = sconfig_desc->pdrive_offset;420		if (p_off >= 32) {421			reg_off += 0x4;422			p_off -= 32;423		}424		mask = GENMASK(p_off + sconfig_desc->pdrive_maskbits - 1, p_off);425		val = set_val << p_off;426		break;427 428	case RTD_DRIVE_STRENGH_N:429		sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);430		if (!sconfig_desc) {431			dev_err(data->dev, "Not support N driving for pin: %s\n", name);432			return -ENOTSUPP;433		}434		set_val = arg;435		reg_off = sconfig_desc->reg_offset;436		n_off = sconfig_desc->ndrive_offset;437		if (n_off >= 32) {438			reg_off += 0x4;439			n_off -= 32;440		}441		mask = GENMASK(n_off + sconfig_desc->ndrive_maskbits - 1, n_off);442		val = set_val << n_off;443		break;444 445	case RTD_DUTY_CYCLE:446		sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);447		if (!sconfig_desc || sconfig_desc->dcycle_offset == NA) {448			dev_err(data->dev, "Not support duty cycle for pin: %s\n", name);449			return -ENOTSUPP;450		}451		set_val = arg;452		reg_off = config_desc->reg_offset;453		mask = GENMASK(sconfig_desc->dcycle_offset +454		sconfig_desc->dcycle_maskbits - 1, sconfig_desc->dcycle_offset);455		val = set_val << sconfig_desc->dcycle_offset;456		break;457 458	default:459		dev_err(data->dev, "unsupported pinconf: %d\n", (u32)param);460		return -EINVAL;461	}462 463	ret = regmap_update_bits(data->regmap_pinctrl, reg_off, mask, val);464	if (ret)465		dev_err(data->dev, "could not update pinconf(%d) for pin(%s)\n", (u32)param, name);466 467	return ret;468}469 470static int rtd_pin_config_get(struct pinctrl_dev *pcdev, unsigned int pinnr,471			      unsigned long *config)472{473	unsigned int param = pinconf_to_config_param(*config);474	unsigned int arg = 0;475 476	switch (param) {477	default:478		return -ENOTSUPP;479	}480 481	*config = pinconf_to_config_packed(param, arg);482	return 0;483}484 485static int rtd_pin_config_set(struct pinctrl_dev *pcdev, unsigned int pinnr,486			      unsigned long *configs, unsigned int num_configs)487{488	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);489	int i;490	int ret = 0;491 492	for (i = 0; i < num_configs; i++) {493		ret = rtd_pconf_parse_conf(data, pinnr,494					   pinconf_to_config_param(configs[i]),495					   pinconf_to_config_argument(configs[i]));496		if (ret < 0)497			return ret;498	}499 500	return 0;501}502 503static int rtd_pin_config_group_set(struct pinctrl_dev *pcdev, unsigned int group,504				    unsigned long *configs, unsigned int num_configs)505{506	struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);507	const unsigned int *pins;508	unsigned int num_pins;509	const char *group_name;510	int i, ret;511 512	group_name = data->info->groups[group].name;513 514	ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins);515	if (ret) {516		dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name);517		return ret;518	}519 520	for (i = 0; i < num_pins; i++) {521		ret = rtd_pin_config_set(pcdev, pins[i], configs, num_configs);522		if (ret)523			return ret;524	}525 526	return 0;527}528 529static const struct pinconf_ops rtd_pinconf_ops = {530	.is_generic = true,531	.pin_config_get = rtd_pin_config_get,532	.pin_config_set = rtd_pin_config_set,533	.pin_config_group_set = rtd_pin_config_group_set,534};535 536static const struct regmap_config rtd_pinctrl_regmap_config = {537	.reg_bits = 32,538	.val_bits = 32,539	.reg_stride = 4,540	.use_relaxed_mmio = true,541};542 543int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc)544{545	struct rtd_pinctrl *data;546	int ret;547 548	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);549	if (!data)550		return -ENOMEM;551 552	data->base = of_iomap(pdev->dev.of_node, 0);553	if (!data->base)554		return -ENOMEM;555 556	data->dev = &pdev->dev;557	data->info = desc;558	data->desc.name = dev_name(&pdev->dev);559	data->desc.pins = data->info->pins;560	data->desc.npins = data->info->num_pins;561	data->desc.pctlops = &rtd_pinctrl_ops;562	data->desc.pmxops = &rtd_pinmux_ops;563	data->desc.confops = &rtd_pinconf_ops;564	data->desc.custom_params = rtd_custom_bindings;565	data->desc.num_custom_params = ARRAY_SIZE(rtd_custom_bindings);566	data->desc.owner = THIS_MODULE;567	data->regmap_pinctrl = devm_regmap_init_mmio(data->dev, data->base,568						     &rtd_pinctrl_regmap_config);569 570	if (IS_ERR(data->regmap_pinctrl)) {571		dev_err(data->dev, "failed to init regmap: %ld\n",572			PTR_ERR(data->regmap_pinctrl));573		ret = PTR_ERR(data->regmap_pinctrl);574		goto unmap;575	}576 577	data->pcdev = pinctrl_register(&data->desc, &pdev->dev, data);578	if (IS_ERR(data->pcdev)) {579		ret = PTR_ERR(data->pcdev);580		goto unmap;581	}582 583	platform_set_drvdata(pdev, data);584 585	dev_dbg(&pdev->dev, "probed\n");586 587	return 0;588 589unmap:590	iounmap(data->base);591	return ret;592}593EXPORT_SYMBOL(rtd_pinctrl_probe);594 595MODULE_DESCRIPTION("Realtek DHC SoC pinctrl driver");596MODULE_LICENSE("GPL v2");597