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