1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015-2016 Wills Wang <wills.wang (at) live.com> 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <asm/io.h> 10 #include <dm/pinctrl.h> 11 #include <mach/ar71xx_regs.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 enum periph_id { 16 PERIPH_ID_UART0, 17 PERIPH_ID_SPI0, 18 PERIPH_ID_NONE = -1, 19 }; 20 21 struct qca953x_pinctrl_priv { 22 void __iomem *regs; 23 }; 24 25 static void pinctrl_qca953x_spi_config(struct qca953x_pinctrl_priv *priv, int cs) 26 { 27 switch (cs) { 28 case 0: 29 clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, 30 QCA953X_GPIO(5) | QCA953X_GPIO(6) | 31 QCA953X_GPIO(7), QCA953X_GPIO(8)); 32 33 clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC1, 34 QCA953X_GPIO_MUX_MASK(8) | 35 QCA953X_GPIO_MUX_MASK(16) | 36 QCA953X_GPIO_MUX_MASK(24), 37 (QCA953X_GPIO_OUT_MUX_SPI_CS0 << 8) | 38 (QCA953X_GPIO_OUT_MUX_SPI_CLK << 16) | 39 (QCA953X_GPIO_OUT_MUX_SPI_MOSI << 24)); 40 41 clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, 42 QCA953X_GPIO_MUX_MASK(0), 43 QCA953X_GPIO_IN_MUX_SPI_DATA_IN); 44 45 setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, 46 QCA953X_GPIO(8)); 47 break; 48 } 49 } 50 51 static void pinctrl_qca953x_uart_config(struct qca953x_pinctrl_priv *priv, int uart_id) 52 { 53 switch (uart_id) { 54 case PERIPH_ID_UART0: 55 clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, 56 QCA953X_GPIO(9), QCA953X_GPIO(10)); 57 58 clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC2, 59 QCA953X_GPIO_MUX_MASK(16), 60 QCA953X_GPIO_OUT_MUX_UART0_SOUT << 16); 61 62 clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, 63 QCA953X_GPIO_MUX_MASK(8), 64 QCA953X_GPIO_IN_MUX_UART0_SIN << 8); 65 66 setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, 67 QCA953X_GPIO(10)); 68 break; 69 } 70 } 71 72 static int qca953x_pinctrl_request(struct udevice *dev, int func, int flags) 73 { 74 struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); 75 76 debug("%s: func=%x, flags=%x\n", __func__, func, flags); 77 switch (func) { 78 case PERIPH_ID_SPI0: 79 pinctrl_qca953x_spi_config(priv, flags); 80 break; 81 case PERIPH_ID_UART0: 82 pinctrl_qca953x_uart_config(priv, func); 83 break; 84 default: 85 return -EINVAL; 86 } 87 88 return 0; 89 } 90 91 static int qca953x_pinctrl_get_periph_id(struct udevice *dev, 92 struct udevice *periph) 93 { 94 u32 cell[2]; 95 int ret; 96 97 ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(periph), 98 "interrupts", cell, ARRAY_SIZE(cell)); 99 if (ret < 0) 100 return -EINVAL; 101 102 switch (cell[0]) { 103 case 128: 104 return PERIPH_ID_UART0; 105 case 129: 106 return PERIPH_ID_SPI0; 107 } 108 return -ENOENT; 109 } 110 111 static int qca953x_pinctrl_set_state_simple(struct udevice *dev, 112 struct udevice *periph) 113 { 114 int func; 115 116 func = qca953x_pinctrl_get_periph_id(dev, periph); 117 if (func < 0) 118 return func; 119 return qca953x_pinctrl_request(dev, func, 0); 120 } 121 122 static struct pinctrl_ops qca953x_pinctrl_ops = { 123 .set_state_simple = qca953x_pinctrl_set_state_simple, 124 .request = qca953x_pinctrl_request, 125 .get_periph_id = qca953x_pinctrl_get_periph_id, 126 }; 127 128 static int qca953x_pinctrl_probe(struct udevice *dev) 129 { 130 struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); 131 fdt_addr_t addr; 132 133 addr = devfdt_get_addr(dev); 134 if (addr == FDT_ADDR_T_NONE) 135 return -EINVAL; 136 137 priv->regs = map_physmem(addr, 138 AR71XX_GPIO_SIZE, 139 MAP_NOCACHE); 140 return 0; 141 } 142 143 static const struct udevice_id qca953x_pinctrl_ids[] = { 144 { .compatible = "qca,qca953x-pinctrl" }, 145 { } 146 }; 147 148 U_BOOT_DRIVER(pinctrl_qca953x) = { 149 .name = "pinctrl_qca953x", 150 .id = UCLASS_PINCTRL, 151 .of_match = qca953x_pinctrl_ids, 152 .priv_auto_alloc_size = sizeof(struct qca953x_pinctrl_priv), 153 .ops = &qca953x_pinctrl_ops, 154 .probe = qca953x_pinctrl_probe, 155 }; 156