File Index
Files and directories
Sign in
FILE

pinctrl-brcmstb.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pinctrl/bcm/pinctrl-brcmstb.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Driver for Broadcom brcmstb GPIO units (pinctrl only)
  4 *
  5 * Copyright (C) 2024-2025 Ivan T. Ivanov, Andrea della Porta
  6 * Copyright (C) 2021-3 Raspberry Pi Ltd.
  7 * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
  8 *
  9 * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by:
 10 * pinctrl-nomadik.c, please see original file for copyright information
 11 * pinctrl-tegra.c, please see original file for copyright information
 12 */
 13
 14#include <linux/device.h>
 15#include <linux/err.h>
 16#include <linux/init.h>
 17#include <linux/io.h>
 18#include <linux/of.h>
 19#include <linux/pinctrl/pinconf.h>
 20#include <linux/pinctrl/pinctrl.h>
 21#include <linux/pinctrl/pinmux.h>
 22#include <linux/pinctrl/pinconf-generic.h>
 23#include <linux/seq_file.h>
 24#include <linux/slab.h>
 25#include <linux/spinlock.h>
 26#include <linux/cleanup.h>
 27
 28#include "pinctrl-brcmstb.h"
 29
 30#define BRCMSTB_PULL_NONE	0
 31#define BRCMSTB_PULL_DOWN	1
 32#define BRCMSTB_PULL_UP		2
 33#define BRCMSTB_PULL_MASK	0x3
 34
 35#define BIT_TO_REG(b)		(((b) >> 5) << 2)
 36#define BIT_TO_SHIFT(b)		((b) & 0x1f)
 37
 38struct brcmstb_pinctrl {
 39	struct device *dev;
 40	void __iomem *base;
 41	struct pinctrl_dev *pctl_dev;
 42	struct pinctrl_desc pctl_desc;
 43	const struct pin_regs *pin_regs;
 44	const struct brcmstb_pin_funcs *pin_funcs;
 45	const char * const *func_names;
 46	unsigned int func_count;
 47	unsigned int func_gpio;
 48	const char *const *gpio_groups;
 49	struct pinctrl_gpio_range gpio_range;
 50	/* Protect FSEL registers */
 51	spinlock_t fsel_lock;
 52};
 53
 54static unsigned int brcmstb_pinctrl_fsel_get(struct brcmstb_pinctrl *pc,
 55					     unsigned int pin)
 56{
 57	u32 bit = pc->pin_regs[pin].mux_bit;
 58	unsigned int func;
 59	int fsel;
 60	u32 val;
 61
 62	if (!bit)
 63		return pc->func_gpio;
 64
 65	bit &= ~MUX_BIT_VALID;
 66
 67	val = readl(pc->base + BIT_TO_REG(bit));
 68	fsel = (val >> BIT_TO_SHIFT(bit)) & pc->pin_funcs[pin].func_mask;
 69	func = pc->pin_funcs[pin].funcs[fsel];
 70
 71	if (func >= pc->func_count)
 72		func = fsel;
 73
 74	dev_dbg(pc->dev, "get %04x: %08x (%u => %s)\n",
 75		BIT_TO_REG(bit), val, pin,
 76		pc->func_names[func]);
 77
 78	return func;
 79}
 80
 81static int brcmstb_pinctrl_fsel_set(struct brcmstb_pinctrl *pc,
 82				    unsigned int pin, unsigned int func)
 83{
 84	u32 bit = pc->pin_regs[pin].mux_bit, val, fsel_mask;
 85	const u8 *pin_funcs;
 86	int fsel;
 87	int cur;
 88	int i;
 89
 90	if (!bit || func >= pc->func_count)
 91		return -EINVAL;
 92
 93	bit &= ~MUX_BIT_VALID;
 94
 95	fsel = pc->pin_funcs[pin].n_funcs + 1;
 96	fsel_mask = pc->pin_funcs[pin].func_mask;
 97
 98	if (func >= fsel) {
 99		/* Convert to an fsel number */
100		pin_funcs = pc->pin_funcs[pin].funcs;
101		for (i = 1; i < fsel; i++) {
102			if (pin_funcs[i - 1] == func) {
103				fsel = i;
104				break;
105			}
106		}
107	} else {
108		fsel = func;
109	}
110
111	if (fsel >= pc->pin_funcs[pin].n_funcs + 1)
112		return -EINVAL;
113
114	guard(spinlock_irqsave)(&pc->fsel_lock);
115
116	val = readl(pc->base + BIT_TO_REG(bit));
117	cur = (val >> BIT_TO_SHIFT(bit)) & fsel_mask;
118
119	dev_dbg(pc->dev, "read %04x: %08x (%u => %s)\n",
120		BIT_TO_REG(bit), val, pin,
121		pc->func_names[cur]);
122
123	if (cur != fsel) {
124		val &= ~(fsel_mask << BIT_TO_SHIFT(bit));
125		val |= fsel << BIT_TO_SHIFT(bit);
126
127		dev_dbg(pc->dev, "write %04x: %08x (%u <= %s)\n",
128			BIT_TO_REG(bit), val, pin,
129			pc->func_names[fsel]);
130		writel(val, pc->base + BIT_TO_REG(bit));
131	}
132
133	return 0;
134}
135
136static int brcmstb_pctl_get_groups_count(struct pinctrl_dev *pctldev)
137{
138	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
139
140	return pc->pctl_desc.npins;
141}
142
143static const char *brcmstb_pctl_get_group_name(struct pinctrl_dev *pctldev,
144					       unsigned int selector)
145{
146	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
147
148	return pc->gpio_groups[selector];
149}
150
151static int brcmstb_pctl_get_group_pins(struct pinctrl_dev *pctldev,
152				       unsigned int selector,
153				       const unsigned int **pins,
154				       unsigned int *num_pins)
155{
156	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
157
158	*pins = &pc->pctl_desc.pins[selector].number;
159	*num_pins = 1;
160
161	return 0;
162}
163
164static void brcmstb_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
165				      struct seq_file *s, unsigned int offset)
166{
167	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
168	unsigned int fsel = brcmstb_pinctrl_fsel_get(pc, offset);
169	const char *fname = pc->func_names[fsel];
170
171	seq_printf(s, "function %s", fname);
172}
173
174static void brcmstb_pctl_dt_free_map(struct pinctrl_dev *pctldev,
175				     struct pinctrl_map *maps,
176				     unsigned int num_maps)
177{
178	int i;
179
180	for (i = 0; i < num_maps; i++)
181		if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
182			kfree(maps[i].data.configs.configs);
183
184	kfree(maps);
185}
186
187static const struct pinctrl_ops brcmstb_pctl_ops = {
188	.get_groups_count = brcmstb_pctl_get_groups_count,
189	.get_group_name = brcmstb_pctl_get_group_name,
190	.get_group_pins = brcmstb_pctl_get_group_pins,
191	.pin_dbg_show = brcmstb_pctl_pin_dbg_show,
192	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
193	.dt_free_map = brcmstb_pctl_dt_free_map,
194};
195
196static int brcmstb_pmx_free(struct pinctrl_dev *pctldev, unsigned int offset)
197{
198	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
199
200	/* disable by setting to GPIO */
201	return brcmstb_pinctrl_fsel_set(pc, offset, pc->func_gpio);
202}
203
204static int brcmstb_pmx_get_functions_count(struct pinctrl_dev *pctldev)
205{
206	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
207
208	return pc->func_count;
209}
210
211static const char *brcmstb_pmx_get_function_name(struct pinctrl_dev *pctldev,
212						 unsigned int selector)
213{
214	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
215
216	return (selector < pc->func_count) ? pc->func_names[selector] : NULL;
217}
218
219static int brcmstb_pmx_get_function_groups(struct pinctrl_dev *pctldev,
220					   unsigned int selector,
221					   const char *const **groups,
222					   unsigned *const num_groups)
223{
224	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
225
226	*groups = pc->gpio_groups;
227	*num_groups = pc->pctl_desc.npins;
228
229	return 0;
230}
231
232static int brcmstb_pmx_set(struct pinctrl_dev *pctldev,
233			   unsigned int func_selector,
234			   unsigned int group_selector)
235{
236	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
237	const struct pinctrl_desc *pctldesc = &pc->pctl_desc;
238	const struct pinctrl_pin_desc *pindesc;
239
240	if (group_selector >= pctldesc->npins)
241		return -EINVAL;
242
243	pindesc = &pctldesc->pins[group_selector];
244	return brcmstb_pinctrl_fsel_set(pc, pindesc->number, func_selector);
245}
246
247static int brcmstb_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
248					   struct pinctrl_gpio_range *range,
249					   unsigned int pin)
250{
251	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
252
253	return brcmstb_pinctrl_fsel_set(pc, pin, pc->func_gpio);
254}
255
256static void brcmstb_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
257					  struct pinctrl_gpio_range *range,
258					  unsigned int offset)
259{
260	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
261
262	/* disable by setting to GPIO */
263	(void)brcmstb_pinctrl_fsel_set(pc, offset, pc->func_gpio);
264}
265
266static bool brcmstb_pmx_function_is_gpio(struct pinctrl_dev *pctldev,
267					 unsigned int selector)
268{
269	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
270
271	return pc->func_gpio == selector;
272}
273
274static const struct pinmux_ops brcmstb_pmx_ops = {
275	.free = brcmstb_pmx_free,
276	.get_functions_count = brcmstb_pmx_get_functions_count,
277	.get_function_name = brcmstb_pmx_get_function_name,
278	.get_function_groups = brcmstb_pmx_get_function_groups,
279	.set_mux = brcmstb_pmx_set,
280	.gpio_request_enable = brcmstb_pmx_gpio_request_enable,
281	.gpio_disable_free = brcmstb_pmx_gpio_disable_free,
282	.function_is_gpio = brcmstb_pmx_function_is_gpio,
283	.strict = true,
284};
285
286static unsigned int brcmstb_pull_config_get(struct brcmstb_pinctrl *pc,
287					    unsigned int pin)
288{
289	u32 bit = pc->pin_regs[pin].pad_bit, val;
290
291	if (bit == PAD_BIT_INVALID)
292		return BRCMSTB_PULL_NONE;
293
294	val = readl(pc->base + BIT_TO_REG(bit));
295	return (val >> BIT_TO_SHIFT(bit)) & BRCMSTB_PULL_MASK;
296}
297
298static int brcmstb_pull_config_set(struct brcmstb_pinctrl *pc,
299				   unsigned int pin, unsigned int arg)
300{
301	u32 bit = pc->pin_regs[pin].pad_bit, val;
302
303	if (bit == PAD_BIT_INVALID) {
304		dev_warn(pc->dev, "Can't set pulls for %s\n",
305			 pc->gpio_groups[pin]);
306		return -EINVAL;
307	}
308
309	guard(spinlock_irqsave)(&pc->fsel_lock);
310
311	val = readl(pc->base + BIT_TO_REG(bit));
312	val &= ~(BRCMSTB_PULL_MASK << BIT_TO_SHIFT(bit));
313	val |= (arg << BIT_TO_SHIFT(bit));
314	writel(val, pc->base + BIT_TO_REG(bit));
315
316	return 0;
317}
318
319static int brcmstb_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
320			       unsigned long *config)
321{
322	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
323	enum pin_config_param param = pinconf_to_config_param(*config);
324	u32 arg;
325
326	switch (param) {
327	case PIN_CONFIG_BIAS_DISABLE:
328		arg = (brcmstb_pull_config_get(pc, pin) == BRCMSTB_PULL_NONE);
329		break;
330	case PIN_CONFIG_BIAS_PULL_DOWN:
331		arg = (brcmstb_pull_config_get(pc, pin) == BRCMSTB_PULL_DOWN);
332		break;
333	case PIN_CONFIG_BIAS_PULL_UP:
334		arg = (brcmstb_pull_config_get(pc, pin) == BRCMSTB_PULL_UP);
335		break;
336	default:
337		return -ENOTSUPP;
338	}
339
340	*config = pinconf_to_config_packed(param, arg);
341
342	return 0;
343}
344
345static int brcmstb_pinconf_set(struct pinctrl_dev *pctldev,
346			       unsigned int pin, unsigned long *configs,
347			       unsigned int num_configs)
348{
349	struct brcmstb_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
350	int ret = 0;
351	u32 param;
352	int i;
353
354	for (i = 0; i < num_configs; i++) {
355		param = pinconf_to_config_param(configs[i]);
356
357		switch (param) {
358		case PIN_CONFIG_BIAS_DISABLE:
359			ret = brcmstb_pull_config_set(pc, pin, BRCMSTB_PULL_NONE);
360			break;
361		case PIN_CONFIG_BIAS_PULL_DOWN:
362			ret = brcmstb_pull_config_set(pc, pin, BRCMSTB_PULL_DOWN);
363			break;
364		case PIN_CONFIG_BIAS_PULL_UP:
365			ret = brcmstb_pull_config_set(pc, pin, BRCMSTB_PULL_UP);
366			break;
367		default:
368			return -ENOTSUPP;
369		}
370	}
371
372	return ret;
373}
374
375static const struct pinconf_ops brcmstb_pinconf_ops = {
376	.is_generic = true,
377	.pin_config_get = brcmstb_pinconf_get,
378	.pin_config_set = brcmstb_pinconf_set,
379};
380
381int brcmstb_pinctrl_probe(struct platform_device *pdev)
382{
383	struct device *dev = &pdev->dev;
384	struct device_node *np = dev->of_node;
385	const struct brcmstb_pdata *pdata;
386	struct brcmstb_pinctrl *pc;
387	const char **names;
388	int num_pins, i;
389
390	pdata = of_device_get_match_data(dev);
391
392	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
393	if (!pc)
394		return -ENOMEM;
395
396	platform_set_drvdata(pdev, pc);
397	pc->dev = dev;
398	spin_lock_init(&pc->fsel_lock);
399
400	pc->base = devm_of_iomap(dev, np, 0, NULL);
401	if (IS_ERR(pc->base))
402		return dev_err_probe(&pdev->dev, PTR_ERR(pc->base),
403				     "Could not get IO memory\n");
404
405	pc->pctl_desc = *pdata->pctl_desc;
406	pc->pctl_desc.pctlops = &brcmstb_pctl_ops;
407	pc->pctl_desc.pmxops = &brcmstb_pmx_ops;
408	pc->pctl_desc.confops = &brcmstb_pinconf_ops;
409	pc->pctl_desc.owner = THIS_MODULE;
410	num_pins = pc->pctl_desc.npins;
411	names = devm_kmalloc_array(dev, num_pins, sizeof(const char *),
412				   GFP_KERNEL);
413	if (!names)
414		return -ENOMEM;
415
416	for (i = 0; i < num_pins; i++)
417		names[i] = pc->pctl_desc.pins[i].name;
418
419	pc->gpio_groups = names;
420	pc->pin_regs = pdata->pin_regs;
421	pc->pin_funcs = pdata->pin_funcs;
422	pc->func_count = pdata->func_count;
423	pc->func_names = pdata->func_names;
424
425	pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
426	if (IS_ERR(pc->pctl_dev))
427		return dev_err_probe(&pdev->dev, PTR_ERR(pc->pctl_dev),
428				     "Failed to register pinctrl device\n");
429
430	pc->gpio_range = *pdata->gpio_range;
431	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
432
433	return 0;
434}
435EXPORT_SYMBOL(brcmstb_pinctrl_probe);
436
437MODULE_AUTHOR("Phil Elwell");
438MODULE_AUTHOR("Jonathan Bell");
439MODULE_AUTHOR("Ivan T. Ivanov");
440MODULE_AUTHOR("Andrea della Porta");
441MODULE_DESCRIPTION("Broadcom brcmstb pinctrl driver");
442MODULE_LICENSE("GPL");
~/ Read-only file preview.