drivers/pinctrl/bcm/pinctrl-brcmstb.c

Source file repositories/reference/linux-study-clean/drivers/pinctrl/bcm/pinctrl-brcmstb.c

File Facts

System
Linux kernel
Corpus path
drivers/pinctrl/bcm/pinctrl-brcmstb.c
Extension
.c
Size
11722 bytes
Lines
443
Domain
Driver Families
Bucket
drivers/pinctrl
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct brcmstb_pinctrl {
	struct device *dev;
	void __iomem *base;
	struct pinctrl_dev *pctl_dev;
	struct pinctrl_desc pctl_desc;
	const struct pin_regs *pin_regs;
	const struct brcmstb_pin_funcs *pin_funcs;
	const char * const *func_names;
	unsigned int func_count;
	unsigned int func_gpio;
	const char *const *gpio_groups;
	struct pinctrl_gpio_range gpio_range;
	/* Protect FSEL registers */
	spinlock_t fsel_lock;
};

static unsigned int brcmstb_pinctrl_fsel_get(struct brcmstb_pinctrl *pc,
					     unsigned int pin)
{
	u32 bit = pc->pin_regs[pin].mux_bit;
	unsigned int func;
	int fsel;
	u32 val;

	if (!bit)
		return pc->func_gpio;

	bit &= ~MUX_BIT_VALID;

	val = readl(pc->base + BIT_TO_REG(bit));
	fsel = (val >> BIT_TO_SHIFT(bit)) & pc->pin_funcs[pin].func_mask;
	func = pc->pin_funcs[pin].funcs[fsel];

	if (func >= pc->func_count)
		func = fsel;

	dev_dbg(pc->dev, "get %04x: %08x (%u => %s)\n",
		BIT_TO_REG(bit), val, pin,
		pc->func_names[func]);

	return func;
}

static int brcmstb_pinctrl_fsel_set(struct brcmstb_pinctrl *pc,
				    unsigned int pin, unsigned int func)
{
	u32 bit = pc->pin_regs[pin].mux_bit, val, fsel_mask;
	const u8 *pin_funcs;
	int fsel;
	int cur;
	int i;

	if (!bit || func >= pc->func_count)
		return -EINVAL;

	bit &= ~MUX_BIT_VALID;

	fsel = pc->pin_funcs[pin].n_funcs + 1;
	fsel_mask = pc->pin_funcs[pin].func_mask;

	if (func >= fsel) {
		/* Convert to an fsel number */
		pin_funcs = pc->pin_funcs[pin].funcs;
		for (i = 1; i < fsel; i++) {
			if (pin_funcs[i - 1] == func) {
				fsel = i;
				break;
			}
		}
	} else {
		fsel = func;
	}

	if (fsel >= pc->pin_funcs[pin].n_funcs + 1)
		return -EINVAL;

	guard(spinlock_irqsave)(&pc->fsel_lock);

	val = readl(pc->base + BIT_TO_REG(bit));
	cur = (val >> BIT_TO_SHIFT(bit)) & fsel_mask;

	dev_dbg(pc->dev, "read %04x: %08x (%u => %s)\n",
		BIT_TO_REG(bit), val, pin,
		pc->func_names[cur]);

	if (cur != fsel) {
		val &= ~(fsel_mask << BIT_TO_SHIFT(bit));
		val |= fsel << BIT_TO_SHIFT(bit);

		dev_dbg(pc->dev, "write %04x: %08x (%u <= %s)\n",

Annotation

Implementation Notes