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