/* * Copyright (C) 2015-2016 Wills Wang * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; enum periph_id { PERIPH_ID_UART0, PERIPH_ID_SPI0, PERIPH_ID_NONE = -1, }; struct ar933x_pinctrl_priv { void __iomem *regs; }; static void pinctrl_ar933x_spi_config(struct ar933x_pinctrl_priv *priv, int cs) { switch (cs) { case 0: clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, AR933X_GPIO(4), AR933X_GPIO(3) | AR933X_GPIO(5) | AR933X_GPIO(2)); setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, AR933X_GPIO_FUNC_SPI_EN | AR933X_GPIO_FUNC_RES_TRUE); break; } } static void pinctrl_ar933x_uart_config(struct ar933x_pinctrl_priv *priv, int uart_id) { switch (uart_id) { case PERIPH_ID_UART0: clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, AR933X_GPIO(9), AR933X_GPIO(10)); setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, AR933X_GPIO_FUNC_UART_EN | AR933X_GPIO_FUNC_RES_TRUE); break; } } static int ar933x_pinctrl_request(struct udevice *dev, int func, int flags) { struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); debug("%s: func=%x, flags=%x\n", __func__, func, flags); switch (func) { case PERIPH_ID_SPI0: pinctrl_ar933x_spi_config(priv, flags); break; case PERIPH_ID_UART0: pinctrl_ar933x_uart_config(priv, func); break; default: return -EINVAL; } return 0; } static int ar933x_pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph) { u32 cell[2]; int ret; ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset, "interrupts", cell, ARRAY_SIZE(cell)); if (ret < 0) return -EINVAL; switch (cell[0]) { case 128: return PERIPH_ID_UART0; case 129: return PERIPH_ID_SPI0; } return -ENOENT; } static int ar933x_pinctrl_set_state_simple(struct udevice *dev, struct udevice *periph) { int func; func = ar933x_pinctrl_get_periph_id(dev, periph); if (func < 0) return func; return ar933x_pinctrl_request(dev, func, 0); } static struct pinctrl_ops ar933x_pinctrl_ops = { .set_state_simple = ar933x_pinctrl_set_state_simple, .request = ar933x_pinctrl_request, .get_periph_id = ar933x_pinctrl_get_periph_id, }; static int ar933x_pinctrl_probe(struct udevice *dev) { struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); fdt_addr_t addr; addr = dev_get_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; priv->regs = map_physmem(addr, AR71XX_GPIO_SIZE, MAP_NOCACHE); return 0; } static const struct udevice_id ar933x_pinctrl_ids[] = { { .compatible = "qca,ar933x-pinctrl" }, { } }; U_BOOT_DRIVER(pinctrl_ar933x) = { .name = "pinctrl_ar933x", .id = UCLASS_PINCTRL, .of_match = ar933x_pinctrl_ids, .priv_auto_alloc_size = sizeof(struct ar933x_pinctrl_priv), .ops = &ar933x_pinctrl_ops, .probe = ar933x_pinctrl_probe, };