1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2009 Wind River Systems, Inc. 4 * Tom Rix <Tom.Rix@windriver.com> 5 * 6 * This work is derived from the linux 2.6.27 kernel source 7 * To fetch, use the kernel repository 8 * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 9 * Use the v2.6.27 tag. 10 * 11 * Below is the original's header including its copyright 12 * 13 * linux/arch/arm/plat-omap/gpio.c 14 * 15 * Support functions for OMAP GPIO 16 * 17 * Copyright (C) 2003-2005 Nokia Corporation 18 * Written by Juha Yrjölä <juha.yrjola@nokia.com> 19 */ 20 #include <common.h> 21 #include <dm.h> 22 #include <fdtdec.h> 23 #include <asm/gpio.h> 24 #include <asm/io.h> 25 #include <linux/errno.h> 26 #include <malloc.h> 27 28 DECLARE_GLOBAL_DATA_PTR; 29 30 #define OMAP_GPIO_DIR_OUT 0 31 #define OMAP_GPIO_DIR_IN 1 32 33 #ifdef CONFIG_DM_GPIO 34 35 #define GPIO_PER_BANK 32 36 37 struct gpio_bank { 38 /* TODO(sjg@chromium.org): Can we use a struct here? */ 39 void *base; /* address of registers in physical memory */ 40 }; 41 42 #endif 43 44 static inline int get_gpio_index(int gpio) 45 { 46 return gpio & 0x1f; 47 } 48 49 int gpio_is_valid(int gpio) 50 { 51 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO); 52 } 53 54 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, 55 int is_input) 56 { 57 void *reg = bank->base; 58 u32 l; 59 60 reg += OMAP_GPIO_OE; 61 62 l = __raw_readl(reg); 63 if (is_input) 64 l |= 1 << gpio; 65 else 66 l &= ~(1 << gpio); 67 __raw_writel(l, reg); 68 } 69 70 /** 71 * Get the direction of the GPIO by reading the GPIO_OE register 72 * corresponding to the specified bank. 73 */ 74 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) 75 { 76 void *reg = bank->base; 77 u32 v; 78 79 reg += OMAP_GPIO_OE; 80 81 v = __raw_readl(reg); 82 83 if (v & (1 << gpio)) 84 return OMAP_GPIO_DIR_IN; 85 else 86 return OMAP_GPIO_DIR_OUT; 87 } 88 89 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, 90 int enable) 91 { 92 void *reg = bank->base; 93 u32 l = 0; 94 95 if (enable) 96 reg += OMAP_GPIO_SETDATAOUT; 97 else 98 reg += OMAP_GPIO_CLEARDATAOUT; 99 100 l = 1 << gpio; 101 __raw_writel(l, reg); 102 } 103 104 static int _get_gpio_value(const struct gpio_bank *bank, int gpio) 105 { 106 void *reg = bank->base; 107 int input; 108 109 input = _get_gpio_direction(bank, gpio); 110 switch (input) { 111 case OMAP_GPIO_DIR_IN: 112 reg += OMAP_GPIO_DATAIN; 113 break; 114 case OMAP_GPIO_DIR_OUT: 115 reg += OMAP_GPIO_DATAOUT; 116 break; 117 default: 118 return -1; 119 } 120 121 return (__raw_readl(reg) & (1 << gpio)) != 0; 122 } 123 124 #ifndef CONFIG_DM_GPIO 125 126 static inline const struct gpio_bank *get_gpio_bank(int gpio) 127 { 128 return &omap_gpio_bank[gpio >> 5]; 129 } 130 131 static int check_gpio(int gpio) 132 { 133 if (!gpio_is_valid(gpio)) { 134 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); 135 return -1; 136 } 137 return 0; 138 } 139 140 /** 141 * Set value of the specified gpio 142 */ 143 int gpio_set_value(unsigned gpio, int value) 144 { 145 const struct gpio_bank *bank; 146 147 if (check_gpio(gpio) < 0) 148 return -1; 149 bank = get_gpio_bank(gpio); 150 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 151 152 return 0; 153 } 154 155 /** 156 * Get value of the specified gpio 157 */ 158 int gpio_get_value(unsigned gpio) 159 { 160 const struct gpio_bank *bank; 161 162 if (check_gpio(gpio) < 0) 163 return -1; 164 bank = get_gpio_bank(gpio); 165 166 return _get_gpio_value(bank, get_gpio_index(gpio)); 167 } 168 169 /** 170 * Set gpio direction as input 171 */ 172 int gpio_direction_input(unsigned gpio) 173 { 174 const struct gpio_bank *bank; 175 176 if (check_gpio(gpio) < 0) 177 return -1; 178 179 bank = get_gpio_bank(gpio); 180 _set_gpio_direction(bank, get_gpio_index(gpio), 1); 181 182 return 0; 183 } 184 185 /** 186 * Set gpio direction as output 187 */ 188 int gpio_direction_output(unsigned gpio, int value) 189 { 190 const struct gpio_bank *bank; 191 192 if (check_gpio(gpio) < 0) 193 return -1; 194 195 bank = get_gpio_bank(gpio); 196 _set_gpio_dataout(bank, get_gpio_index(gpio), value); 197 _set_gpio_direction(bank, get_gpio_index(gpio), 0); 198 199 return 0; 200 } 201 202 /** 203 * Request a gpio before using it. 204 * 205 * NOTE: Argument 'label' is unused. 206 */ 207 int gpio_request(unsigned gpio, const char *label) 208 { 209 if (check_gpio(gpio) < 0) 210 return -1; 211 212 return 0; 213 } 214 215 /** 216 * Reset and free the gpio after using it. 217 */ 218 int gpio_free(unsigned gpio) 219 { 220 return 0; 221 } 222 223 #else /* new driver model interface CONFIG_DM_GPIO */ 224 225 /* set GPIO pin 'gpio' as an input */ 226 static int omap_gpio_direction_input(struct udevice *dev, unsigned offset) 227 { 228 struct gpio_bank *bank = dev_get_priv(dev); 229 230 /* Configure GPIO direction as input. */ 231 _set_gpio_direction(bank, offset, 1); 232 233 return 0; 234 } 235 236 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 237 static int omap_gpio_direction_output(struct udevice *dev, unsigned offset, 238 int value) 239 { 240 struct gpio_bank *bank = dev_get_priv(dev); 241 242 _set_gpio_dataout(bank, offset, value); 243 _set_gpio_direction(bank, offset, 0); 244 245 return 0; 246 } 247 248 /* read GPIO IN value of pin 'gpio' */ 249 static int omap_gpio_get_value(struct udevice *dev, unsigned offset) 250 { 251 struct gpio_bank *bank = dev_get_priv(dev); 252 253 return _get_gpio_value(bank, offset); 254 } 255 256 /* write GPIO OUT value to pin 'gpio' */ 257 static int omap_gpio_set_value(struct udevice *dev, unsigned offset, 258 int value) 259 { 260 struct gpio_bank *bank = dev_get_priv(dev); 261 262 _set_gpio_dataout(bank, offset, value); 263 264 return 0; 265 } 266 267 static int omap_gpio_get_function(struct udevice *dev, unsigned offset) 268 { 269 struct gpio_bank *bank = dev_get_priv(dev); 270 271 /* GPIOF_FUNC is not implemented yet */ 272 if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT) 273 return GPIOF_OUTPUT; 274 else 275 return GPIOF_INPUT; 276 } 277 278 static const struct dm_gpio_ops gpio_omap_ops = { 279 .direction_input = omap_gpio_direction_input, 280 .direction_output = omap_gpio_direction_output, 281 .get_value = omap_gpio_get_value, 282 .set_value = omap_gpio_set_value, 283 .get_function = omap_gpio_get_function, 284 }; 285 286 static int omap_gpio_probe(struct udevice *dev) 287 { 288 struct gpio_bank *bank = dev_get_priv(dev); 289 struct omap_gpio_platdata *plat = dev_get_platdata(dev); 290 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 291 int banknum; 292 char name[18], *str; 293 294 banknum = plat->bank_index; 295 sprintf(name, "GPIO%d_", banknum + 1); 296 str = strdup(name); 297 if (!str) 298 return -ENOMEM; 299 uc_priv->bank_name = str; 300 uc_priv->gpio_count = GPIO_PER_BANK; 301 bank->base = (void *)plat->base; 302 return 0; 303 } 304 305 static int omap_gpio_bind(struct udevice *dev) 306 { 307 struct omap_gpio_platdata *plat = dev_get_platdata(dev); 308 fdt_addr_t base_addr; 309 310 if (plat) 311 return 0; 312 313 base_addr = devfdt_get_addr(dev); 314 if (base_addr == FDT_ADDR_T_NONE) 315 return -EINVAL; 316 317 /* 318 * TODO: 319 * When every board is converted to driver model and DT is 320 * supported, this can be done by auto-alloc feature, but 321 * not using calloc to alloc memory for platdata. 322 * 323 * For example am33xx_gpio uses platform data rather than device tree. 324 * 325 * NOTE: DO NOT COPY this code if you are using device tree. 326 */ 327 plat = calloc(1, sizeof(*plat)); 328 if (!plat) 329 return -ENOMEM; 330 331 plat->base = base_addr; 332 plat->port_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL); 333 dev->platdata = plat; 334 335 return 0; 336 } 337 338 static const struct udevice_id omap_gpio_ids[] = { 339 { .compatible = "ti,omap3-gpio" }, 340 { .compatible = "ti,omap4-gpio" }, 341 { .compatible = "ti,am4372-gpio" }, 342 { } 343 }; 344 345 U_BOOT_DRIVER(gpio_omap) = { 346 .name = "gpio_omap", 347 .id = UCLASS_GPIO, 348 .ops = &gpio_omap_ops, 349 .of_match = omap_gpio_ids, 350 .bind = omap_gpio_bind, 351 .probe = omap_gpio_probe, 352 .priv_auto_alloc_size = sizeof(struct gpio_bank), 353 .flags = DM_FLAG_PRE_RELOC, 354 }; 355 356 #endif /* CONFIG_DM_GPIO */ 357