1 /* 2 * (C) Copyright 2009 Samsung Electronics 3 * Minkyu Kang <mk7.kang@samsung.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <fdtdec.h> 12 #include <malloc.h> 13 #include <asm/io.h> 14 #include <asm/gpio.h> 15 #include <dm/device-internal.h> 16 #include <dt-bindings/gpio/gpio.h> 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 #define S5P_GPIO_GET_PIN(x) (x % GPIO_PER_BANK) 21 22 #define CON_MASK(val) (0xf << ((val) << 2)) 23 #define CON_SFR(gpio, cfg) ((cfg) << ((gpio) << 2)) 24 #define CON_SFR_UNSHIFT(val, gpio) ((val) >> ((gpio) << 2)) 25 26 #define DAT_MASK(gpio) (0x1 << (gpio)) 27 #define DAT_SET(gpio) (0x1 << (gpio)) 28 29 #define PULL_MASK(gpio) (0x3 << ((gpio) << 1)) 30 #define PULL_MODE(gpio, pull) ((pull) << ((gpio) << 1)) 31 32 #define DRV_MASK(gpio) (0x3 << ((gpio) << 1)) 33 #define DRV_SET(gpio, mode) ((mode) << ((gpio) << 1)) 34 #define RATE_MASK(gpio) (0x1 << (gpio + 16)) 35 #define RATE_SET(gpio) (0x1 << (gpio + 16)) 36 37 /* Platform data for each bank */ 38 struct exynos_gpio_platdata { 39 struct s5p_gpio_bank *bank; 40 const char *bank_name; /* Name of port, e.g. 'gpa0" */ 41 }; 42 43 /* Information about each bank at run-time */ 44 struct exynos_bank_info { 45 struct s5p_gpio_bank *bank; 46 }; 47 48 static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio) 49 { 50 const struct gpio_info *data; 51 unsigned int upto; 52 int i, count; 53 54 data = get_gpio_data(); 55 count = get_bank_num(); 56 upto = 0; 57 58 for (i = 0; i < count; i++) { 59 debug("i=%d, upto=%d\n", i, upto); 60 if (gpio < data->max_gpio) { 61 struct s5p_gpio_bank *bank; 62 bank = (struct s5p_gpio_bank *)data->reg_addr; 63 bank += (gpio - upto) / GPIO_PER_BANK; 64 debug("gpio=%d, bank=%p\n", gpio, bank); 65 return bank; 66 } 67 68 upto = data->max_gpio; 69 data++; 70 } 71 72 return NULL; 73 } 74 75 static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) 76 { 77 unsigned int value; 78 79 value = readl(&bank->con); 80 value &= ~CON_MASK(gpio); 81 value |= CON_SFR(gpio, cfg); 82 writel(value, &bank->con); 83 } 84 85 static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) 86 { 87 unsigned int value; 88 89 value = readl(&bank->dat); 90 value &= ~DAT_MASK(gpio); 91 if (en) 92 value |= DAT_SET(gpio); 93 writel(value, &bank->dat); 94 } 95 96 #ifdef CONFIG_SPL_BUILD 97 /* Common GPIO API - SPL does not support driver model yet */ 98 int gpio_set_value(unsigned gpio, int value) 99 { 100 s5p_gpio_set_value(s5p_gpio_get_bank(gpio), 101 s5p_gpio_get_pin(gpio), value); 102 103 return 0; 104 } 105 #else 106 static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio) 107 { 108 unsigned int value; 109 110 value = readl(&bank->con); 111 value &= CON_MASK(gpio); 112 return CON_SFR_UNSHIFT(value, gpio); 113 } 114 115 static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) 116 { 117 unsigned int value; 118 119 value = readl(&bank->dat); 120 return !!(value & DAT_MASK(gpio)); 121 } 122 #endif /* CONFIG_SPL_BUILD */ 123 124 static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) 125 { 126 unsigned int value; 127 128 value = readl(&bank->pull); 129 value &= ~PULL_MASK(gpio); 130 131 switch (mode) { 132 case S5P_GPIO_PULL_DOWN: 133 case S5P_GPIO_PULL_UP: 134 value |= PULL_MODE(gpio, mode); 135 break; 136 default: 137 break; 138 } 139 140 writel(value, &bank->pull); 141 } 142 143 static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) 144 { 145 unsigned int value; 146 147 value = readl(&bank->drv); 148 value &= ~DRV_MASK(gpio); 149 150 switch (mode) { 151 case S5P_GPIO_DRV_1X: 152 case S5P_GPIO_DRV_2X: 153 case S5P_GPIO_DRV_3X: 154 case S5P_GPIO_DRV_4X: 155 value |= DRV_SET(gpio, mode); 156 break; 157 default: 158 return; 159 } 160 161 writel(value, &bank->drv); 162 } 163 164 static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) 165 { 166 unsigned int value; 167 168 value = readl(&bank->drv); 169 value &= ~RATE_MASK(gpio); 170 171 switch (mode) { 172 case S5P_GPIO_DRV_FAST: 173 case S5P_GPIO_DRV_SLOW: 174 value |= RATE_SET(gpio); 175 break; 176 default: 177 return; 178 } 179 180 writel(value, &bank->drv); 181 } 182 183 int s5p_gpio_get_pin(unsigned gpio) 184 { 185 return S5P_GPIO_GET_PIN(gpio); 186 } 187 188 /* Driver model interface */ 189 #ifndef CONFIG_SPL_BUILD 190 /* set GPIO pin 'gpio' as an input */ 191 static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset) 192 { 193 struct exynos_bank_info *state = dev_get_priv(dev); 194 195 /* Configure GPIO direction as input. */ 196 s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT); 197 198 return 0; 199 } 200 201 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 202 static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset, 203 int value) 204 { 205 struct exynos_bank_info *state = dev_get_priv(dev); 206 207 /* Configure GPIO output value. */ 208 s5p_gpio_set_value(state->bank, offset, value); 209 210 /* Configure GPIO direction as output. */ 211 s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT); 212 213 return 0; 214 } 215 216 /* read GPIO IN value of pin 'gpio' */ 217 static int exynos_gpio_get_value(struct udevice *dev, unsigned offset) 218 { 219 struct exynos_bank_info *state = dev_get_priv(dev); 220 221 return s5p_gpio_get_value(state->bank, offset); 222 } 223 224 /* write GPIO OUT value to pin 'gpio' */ 225 static int exynos_gpio_set_value(struct udevice *dev, unsigned offset, 226 int value) 227 { 228 struct exynos_bank_info *state = dev_get_priv(dev); 229 230 s5p_gpio_set_value(state->bank, offset, value); 231 232 return 0; 233 } 234 #endif /* nCONFIG_SPL_BUILD */ 235 236 /* 237 * There is no common GPIO API for pull, drv, pin, rate (yet). These 238 * functions are kept here to preserve function ordering for review. 239 */ 240 void gpio_set_pull(int gpio, int mode) 241 { 242 s5p_gpio_set_pull(s5p_gpio_get_bank(gpio), 243 s5p_gpio_get_pin(gpio), mode); 244 } 245 246 void gpio_set_drv(int gpio, int mode) 247 { 248 s5p_gpio_set_drv(s5p_gpio_get_bank(gpio), 249 s5p_gpio_get_pin(gpio), mode); 250 } 251 252 void gpio_cfg_pin(int gpio, int cfg) 253 { 254 s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio), 255 s5p_gpio_get_pin(gpio), cfg); 256 } 257 258 void gpio_set_rate(int gpio, int mode) 259 { 260 s5p_gpio_set_rate(s5p_gpio_get_bank(gpio), 261 s5p_gpio_get_pin(gpio), mode); 262 } 263 264 #ifndef CONFIG_SPL_BUILD 265 static int exynos_gpio_get_function(struct udevice *dev, unsigned offset) 266 { 267 struct exynos_bank_info *state = dev_get_priv(dev); 268 int cfg; 269 270 cfg = s5p_gpio_get_cfg_pin(state->bank, offset); 271 if (cfg == S5P_GPIO_OUTPUT) 272 return GPIOF_OUTPUT; 273 else if (cfg == S5P_GPIO_INPUT) 274 return GPIOF_INPUT; 275 else 276 return GPIOF_FUNC; 277 } 278 279 static int exynos_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, 280 struct fdtdec_phandle_args *args) 281 { 282 desc->offset = args->args[0]; 283 desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; 284 285 return 0; 286 } 287 288 static const struct dm_gpio_ops gpio_exynos_ops = { 289 .direction_input = exynos_gpio_direction_input, 290 .direction_output = exynos_gpio_direction_output, 291 .get_value = exynos_gpio_get_value, 292 .set_value = exynos_gpio_set_value, 293 .get_function = exynos_gpio_get_function, 294 .xlate = exynos_gpio_xlate, 295 }; 296 297 static int gpio_exynos_probe(struct udevice *dev) 298 { 299 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 300 struct exynos_bank_info *priv = dev->priv; 301 struct exynos_gpio_platdata *plat = dev->platdata; 302 303 /* Only child devices have ports */ 304 if (!plat) 305 return 0; 306 307 priv->bank = plat->bank; 308 309 uc_priv->gpio_count = GPIO_PER_BANK; 310 uc_priv->bank_name = plat->bank_name; 311 312 return 0; 313 } 314 315 /** 316 * We have a top-level GPIO device with no actual GPIOs. It has a child 317 * device for each Exynos GPIO bank. 318 */ 319 static int gpio_exynos_bind(struct udevice *parent) 320 { 321 struct exynos_gpio_platdata *plat = parent->platdata; 322 struct s5p_gpio_bank *bank, *base; 323 const void *blob = gd->fdt_blob; 324 int node; 325 326 /* If this is a child device, there is nothing to do here */ 327 if (plat) 328 return 0; 329 330 base = (struct s5p_gpio_bank *)dev_get_addr(parent); 331 for (node = fdt_first_subnode(blob, parent->of_offset), bank = base; 332 node > 0; 333 node = fdt_next_subnode(blob, node), bank++) { 334 struct exynos_gpio_platdata *plat; 335 struct udevice *dev; 336 fdt_addr_t reg; 337 int ret; 338 339 if (!fdtdec_get_bool(blob, node, "gpio-controller")) 340 continue; 341 plat = calloc(1, sizeof(*plat)); 342 if (!plat) 343 return -ENOMEM; 344 reg = fdtdec_get_addr(blob, node, "reg"); 345 if (reg != FDT_ADDR_T_NONE) 346 bank = (struct s5p_gpio_bank *)((ulong)base + reg); 347 plat->bank = bank; 348 plat->bank_name = fdt_get_name(blob, node, NULL); 349 debug("dev at %p: %s\n", bank, plat->bank_name); 350 351 ret = device_bind(parent, parent->driver, 352 plat->bank_name, plat, -1, &dev); 353 if (ret) 354 return ret; 355 dev->of_offset = node; 356 } 357 358 return 0; 359 } 360 361 static const struct udevice_id exynos_gpio_ids[] = { 362 { .compatible = "samsung,s5pc100-pinctrl" }, 363 { .compatible = "samsung,s5pc110-pinctrl" }, 364 { .compatible = "samsung,exynos4210-pinctrl" }, 365 { .compatible = "samsung,exynos4x12-pinctrl" }, 366 { .compatible = "samsung,exynos5250-pinctrl" }, 367 { .compatible = "samsung,exynos5420-pinctrl" }, 368 { } 369 }; 370 371 U_BOOT_DRIVER(gpio_exynos) = { 372 .name = "gpio_exynos", 373 .id = UCLASS_GPIO, 374 .of_match = exynos_gpio_ids, 375 .bind = gpio_exynos_bind, 376 .probe = gpio_exynos_probe, 377 .priv_auto_alloc_size = sizeof(struct exynos_bank_info), 378 .ops = &gpio_exynos_ops, 379 }; 380 #endif 381