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