1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2013 - 2018 Xilinx, Michal Simek 4 */ 5 6 #include <common.h> 7 #include <errno.h> 8 #include <malloc.h> 9 #include <linux/list.h> 10 #include <asm/io.h> 11 #include <asm/gpio.h> 12 #include <dm.h> 13 #include <dt-bindings/gpio/gpio.h> 14 15 #define XILINX_GPIO_MAX_BANK 2 16 17 /* Gpio simple map */ 18 struct gpio_regs { 19 u32 gpiodata; 20 u32 gpiodir; 21 }; 22 23 struct xilinx_gpio_platdata { 24 struct gpio_regs *regs; 25 int bank_max[XILINX_GPIO_MAX_BANK]; 26 int bank_input[XILINX_GPIO_MAX_BANK]; 27 int bank_output[XILINX_GPIO_MAX_BANK]; 28 }; 29 30 static int xilinx_gpio_get_bank_pin(unsigned offset, u32 *bank_num, 31 u32 *bank_pin_num, struct udevice *dev) 32 { 33 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 34 u32 bank, max_pins; 35 /* the first gpio is 0 not 1 */ 36 u32 pin_num = offset; 37 38 for (bank = 0; bank < XILINX_GPIO_MAX_BANK; bank++) { 39 max_pins = platdata->bank_max[bank]; 40 if (pin_num < max_pins) { 41 debug("%s: found at bank 0x%x pin 0x%x\n", __func__, 42 bank, pin_num); 43 *bank_num = bank; 44 *bank_pin_num = pin_num; 45 return 0; 46 } 47 pin_num -= max_pins; 48 } 49 50 return -EINVAL; 51 } 52 53 static int xilinx_gpio_set_value(struct udevice *dev, unsigned offset, 54 int value) 55 { 56 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 57 int val, ret; 58 u32 bank, pin; 59 60 ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev); 61 if (ret) 62 return ret; 63 64 debug("%s: regs: %lx, value: %x, gpio: %x, bank %x, pin %x\n", 65 __func__, (ulong)platdata->regs, value, offset, bank, pin); 66 67 if (value) { 68 val = readl(&platdata->regs->gpiodata + bank * 2); 69 val = val | (1 << pin); 70 writel(val, &platdata->regs->gpiodata + bank * 2); 71 } else { 72 val = readl(&platdata->regs->gpiodata + bank * 2); 73 val = val & ~(1 << pin); 74 writel(val, &platdata->regs->gpiodata + bank * 2); 75 } 76 77 return val; 78 }; 79 80 static int xilinx_gpio_get_value(struct udevice *dev, unsigned offset) 81 { 82 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 83 int val, ret; 84 u32 bank, pin; 85 86 ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev); 87 if (ret) 88 return ret; 89 90 debug("%s: regs: %lx, gpio: %x, bank %x, pin %x\n", __func__, 91 (ulong)platdata->regs, offset, bank, pin); 92 93 val = readl(&platdata->regs->gpiodata + bank * 2); 94 val = !!(val & (1 << pin)); 95 96 return val; 97 }; 98 99 static int xilinx_gpio_get_function(struct udevice *dev, unsigned offset) 100 { 101 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 102 int val, ret; 103 u32 bank, pin; 104 105 ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev); 106 if (ret) 107 return ret; 108 109 /* Check if all pins are inputs */ 110 if (platdata->bank_input[bank]) 111 return GPIOF_INPUT; 112 113 /* Check if all pins are outputs */ 114 if (platdata->bank_output[bank]) 115 return GPIOF_OUTPUT; 116 117 /* FIXME test on dual */ 118 val = readl(&platdata->regs->gpiodir + bank * 2); 119 val = !(val & (1 << pin)); 120 121 /* input is 1 in reg but GPIOF_INPUT is 0 */ 122 /* output is 0 in reg but GPIOF_OUTPUT is 1 */ 123 124 return val; 125 } 126 127 static int xilinx_gpio_direction_output(struct udevice *dev, unsigned offset, 128 int value) 129 { 130 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 131 int val, ret; 132 u32 bank, pin; 133 134 ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev); 135 if (ret) 136 return ret; 137 138 /* can't change it if all is input by default */ 139 if (platdata->bank_input[bank]) 140 return -EINVAL; 141 142 xilinx_gpio_set_value(dev, offset, value); 143 144 if (!platdata->bank_output[bank]) { 145 val = readl(&platdata->regs->gpiodir + bank * 2); 146 val = val & ~(1 << pin); 147 writel(val, &platdata->regs->gpiodir + bank * 2); 148 } 149 150 return 0; 151 } 152 153 static int xilinx_gpio_direction_input(struct udevice *dev, unsigned offset) 154 { 155 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 156 int val, ret; 157 u32 bank, pin; 158 159 ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev); 160 if (ret) 161 return ret; 162 163 /* Already input */ 164 if (platdata->bank_input[bank]) 165 return 0; 166 167 /* can't change it if all is output by default */ 168 if (platdata->bank_output[bank]) 169 return -EINVAL; 170 171 val = readl(&platdata->regs->gpiodir + bank * 2); 172 val = val | (1 << pin); 173 writel(val, &platdata->regs->gpiodir + bank * 2); 174 175 return 0; 176 } 177 178 static int xilinx_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, 179 struct ofnode_phandle_args *args) 180 { 181 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 182 183 desc->offset = args->args[0]; 184 185 debug("%s: argc: %x, [0]: %x, [1]: %x, [2]: %x\n", __func__, 186 args->args_count, args->args[0], args->args[1], args->args[2]); 187 188 /* 189 * The second cell is channel offset: 190 * 0 is first channel, 8 is second channel 191 * 192 * U-Boot driver just combine channels together that's why simply 193 * add amount of pins in second channel if present. 194 */ 195 if (args->args[1]) { 196 if (!platdata->bank_max[1]) { 197 printf("%s: %s has no second channel\n", 198 __func__, dev->name); 199 return -EINVAL; 200 } 201 202 desc->offset += platdata->bank_max[0]; 203 } 204 205 /* The third cell is optional */ 206 if (args->args_count > 2) 207 desc->flags = (args->args[2] & 208 GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0); 209 210 debug("%s: offset %x, flags %lx\n", 211 __func__, desc->offset, desc->flags); 212 return 0; 213 } 214 215 static const struct dm_gpio_ops xilinx_gpio_ops = { 216 .direction_input = xilinx_gpio_direction_input, 217 .direction_output = xilinx_gpio_direction_output, 218 .get_value = xilinx_gpio_get_value, 219 .set_value = xilinx_gpio_set_value, 220 .get_function = xilinx_gpio_get_function, 221 .xlate = xilinx_gpio_xlate, 222 }; 223 224 static int xilinx_gpio_probe(struct udevice *dev) 225 { 226 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 227 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 228 229 uc_priv->bank_name = dev->name; 230 231 uc_priv->gpio_count = platdata->bank_max[0] + platdata->bank_max[1]; 232 233 return 0; 234 } 235 236 static int xilinx_gpio_ofdata_to_platdata(struct udevice *dev) 237 { 238 struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev); 239 int is_dual; 240 241 platdata->regs = (struct gpio_regs *)dev_read_addr(dev); 242 243 platdata->bank_max[0] = dev_read_u32_default(dev, 244 "xlnx,gpio-width", 0); 245 platdata->bank_input[0] = dev_read_u32_default(dev, 246 "xlnx,all-inputs", 0); 247 platdata->bank_output[0] = dev_read_u32_default(dev, 248 "xlnx,all-outputs", 0); 249 250 is_dual = dev_read_u32_default(dev, "xlnx,is-dual", 0); 251 if (is_dual) { 252 platdata->bank_max[1] = dev_read_u32_default(dev, 253 "xlnx,gpio2-width", 0); 254 platdata->bank_input[1] = dev_read_u32_default(dev, 255 "xlnx,all-inputs-2", 0); 256 platdata->bank_output[1] = dev_read_u32_default(dev, 257 "xlnx,all-outputs-2", 0); 258 } 259 260 return 0; 261 } 262 263 static const struct udevice_id xilinx_gpio_ids[] = { 264 { .compatible = "xlnx,xps-gpio-1.00.a",}, 265 { } 266 }; 267 268 U_BOOT_DRIVER(xilinx_gpio) = { 269 .name = "xlnx_gpio", 270 .id = UCLASS_GPIO, 271 .ops = &xilinx_gpio_ops, 272 .of_match = xilinx_gpio_ids, 273 .ofdata_to_platdata = xilinx_gpio_ofdata_to_platdata, 274 .probe = xilinx_gpio_probe, 275 .platdata_auto_alloc_size = sizeof(struct xilinx_gpio_platdata), 276 }; 277