1 /* 2 * Copyright (C) 2009 3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4 * 5 * Copyright (C) 2011 6 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 #include <common.h> 11 #include <errno.h> 12 #include <dm.h> 13 #include <malloc.h> 14 #include <asm/arch/imx-regs.h> 15 #include <asm/gpio.h> 16 #include <asm/io.h> 17 18 enum mxc_gpio_direction { 19 MXC_GPIO_DIRECTION_IN, 20 MXC_GPIO_DIRECTION_OUT, 21 }; 22 23 #define GPIO_PER_BANK 32 24 25 struct mxc_gpio_plat { 26 int bank_index; 27 struct gpio_regs *regs; 28 }; 29 30 struct mxc_bank_info { 31 struct gpio_regs *regs; 32 }; 33 34 #ifndef CONFIG_DM_GPIO 35 #define GPIO_TO_PORT(n) (n / 32) 36 37 /* GPIO port description */ 38 static unsigned long gpio_ports[] = { 39 [0] = GPIO1_BASE_ADDR, 40 [1] = GPIO2_BASE_ADDR, 41 [2] = GPIO3_BASE_ADDR, 42 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 43 defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 44 defined(CONFIG_MX7) || defined(CONFIG_MX8M) 45 [3] = GPIO4_BASE_ADDR, 46 #endif 47 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 48 defined(CONFIG_MX7) || defined(CONFIG_MX8M) 49 [4] = GPIO5_BASE_ADDR, 50 #if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX8M)) 51 [5] = GPIO6_BASE_ADDR, 52 #endif 53 #endif 54 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) || defined(CONFIG_MX7) 55 #if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)) 56 [6] = GPIO7_BASE_ADDR, 57 #endif 58 #endif 59 }; 60 61 static int mxc_gpio_direction(unsigned int gpio, 62 enum mxc_gpio_direction direction) 63 { 64 unsigned int port = GPIO_TO_PORT(gpio); 65 struct gpio_regs *regs; 66 u32 l; 67 68 if (port >= ARRAY_SIZE(gpio_ports)) 69 return -1; 70 71 gpio &= 0x1f; 72 73 regs = (struct gpio_regs *)gpio_ports[port]; 74 75 l = readl(®s->gpio_dir); 76 77 switch (direction) { 78 case MXC_GPIO_DIRECTION_OUT: 79 l |= 1 << gpio; 80 break; 81 case MXC_GPIO_DIRECTION_IN: 82 l &= ~(1 << gpio); 83 } 84 writel(l, ®s->gpio_dir); 85 86 return 0; 87 } 88 89 int gpio_set_value(unsigned gpio, int value) 90 { 91 unsigned int port = GPIO_TO_PORT(gpio); 92 struct gpio_regs *regs; 93 u32 l; 94 95 if (port >= ARRAY_SIZE(gpio_ports)) 96 return -1; 97 98 gpio &= 0x1f; 99 100 regs = (struct gpio_regs *)gpio_ports[port]; 101 102 l = readl(®s->gpio_dr); 103 if (value) 104 l |= 1 << gpio; 105 else 106 l &= ~(1 << gpio); 107 writel(l, ®s->gpio_dr); 108 109 return 0; 110 } 111 112 int gpio_get_value(unsigned gpio) 113 { 114 unsigned int port = GPIO_TO_PORT(gpio); 115 struct gpio_regs *regs; 116 u32 val; 117 118 if (port >= ARRAY_SIZE(gpio_ports)) 119 return -1; 120 121 gpio &= 0x1f; 122 123 regs = (struct gpio_regs *)gpio_ports[port]; 124 125 val = (readl(®s->gpio_psr) >> gpio) & 0x01; 126 127 return val; 128 } 129 130 int gpio_request(unsigned gpio, const char *label) 131 { 132 unsigned int port = GPIO_TO_PORT(gpio); 133 if (port >= ARRAY_SIZE(gpio_ports)) 134 return -1; 135 return 0; 136 } 137 138 int gpio_free(unsigned gpio) 139 { 140 return 0; 141 } 142 143 int gpio_direction_input(unsigned gpio) 144 { 145 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); 146 } 147 148 int gpio_direction_output(unsigned gpio, int value) 149 { 150 int ret = gpio_set_value(gpio, value); 151 152 if (ret < 0) 153 return ret; 154 155 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); 156 } 157 #endif 158 159 #ifdef CONFIG_DM_GPIO 160 #include <fdtdec.h> 161 DECLARE_GLOBAL_DATA_PTR; 162 163 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset) 164 { 165 u32 val; 166 167 val = readl(®s->gpio_dir); 168 169 return val & (1 << offset) ? 1 : 0; 170 } 171 172 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset, 173 enum mxc_gpio_direction direction) 174 { 175 u32 l; 176 177 l = readl(®s->gpio_dir); 178 179 switch (direction) { 180 case MXC_GPIO_DIRECTION_OUT: 181 l |= 1 << offset; 182 break; 183 case MXC_GPIO_DIRECTION_IN: 184 l &= ~(1 << offset); 185 } 186 writel(l, ®s->gpio_dir); 187 } 188 189 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset, 190 int value) 191 { 192 u32 l; 193 194 l = readl(®s->gpio_dr); 195 if (value) 196 l |= 1 << offset; 197 else 198 l &= ~(1 << offset); 199 writel(l, ®s->gpio_dr); 200 } 201 202 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset) 203 { 204 return (readl(®s->gpio_psr) >> offset) & 0x01; 205 } 206 207 /* set GPIO pin 'gpio' as an input */ 208 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset) 209 { 210 struct mxc_bank_info *bank = dev_get_priv(dev); 211 212 /* Configure GPIO direction as input. */ 213 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN); 214 215 return 0; 216 } 217 218 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 219 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset, 220 int value) 221 { 222 struct mxc_bank_info *bank = dev_get_priv(dev); 223 224 /* Configure GPIO output value. */ 225 mxc_gpio_bank_set_value(bank->regs, offset, value); 226 227 /* Configure GPIO direction as output. */ 228 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT); 229 230 return 0; 231 } 232 233 /* read GPIO IN value of pin 'gpio' */ 234 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset) 235 { 236 struct mxc_bank_info *bank = dev_get_priv(dev); 237 238 return mxc_gpio_bank_get_value(bank->regs, offset); 239 } 240 241 /* write GPIO OUT value to pin 'gpio' */ 242 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset, 243 int value) 244 { 245 struct mxc_bank_info *bank = dev_get_priv(dev); 246 247 mxc_gpio_bank_set_value(bank->regs, offset, value); 248 249 return 0; 250 } 251 252 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset) 253 { 254 struct mxc_bank_info *bank = dev_get_priv(dev); 255 256 /* GPIOF_FUNC is not implemented yet */ 257 if (mxc_gpio_is_output(bank->regs, offset)) 258 return GPIOF_OUTPUT; 259 else 260 return GPIOF_INPUT; 261 } 262 263 static const struct dm_gpio_ops gpio_mxc_ops = { 264 .direction_input = mxc_gpio_direction_input, 265 .direction_output = mxc_gpio_direction_output, 266 .get_value = mxc_gpio_get_value, 267 .set_value = mxc_gpio_set_value, 268 .get_function = mxc_gpio_get_function, 269 }; 270 271 static int mxc_gpio_probe(struct udevice *dev) 272 { 273 struct mxc_bank_info *bank = dev_get_priv(dev); 274 struct mxc_gpio_plat *plat = dev_get_platdata(dev); 275 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 276 int banknum; 277 char name[18], *str; 278 279 banknum = plat->bank_index; 280 sprintf(name, "GPIO%d_", banknum + 1); 281 str = strdup(name); 282 if (!str) 283 return -ENOMEM; 284 uc_priv->bank_name = str; 285 uc_priv->gpio_count = GPIO_PER_BANK; 286 bank->regs = plat->regs; 287 288 return 0; 289 } 290 291 static int mxc_gpio_bind(struct udevice *dev) 292 { 293 struct mxc_gpio_plat *plat = dev->platdata; 294 fdt_addr_t addr; 295 296 /* 297 * If platdata already exsits, directly return. 298 * Actually only when DT is not supported, platdata 299 * is statically initialized in U_BOOT_DEVICES.Here 300 * will return. 301 */ 302 if (plat) 303 return 0; 304 305 addr = devfdt_get_addr(dev); 306 if (addr == FDT_ADDR_T_NONE) 307 return -EINVAL; 308 309 /* 310 * TODO: 311 * When every board is converted to driver model and DT is supported, 312 * this can be done by auto-alloc feature, but not using calloc 313 * to alloc memory for platdata. 314 * 315 * For example mxc_plat below uses platform data rather than device 316 * tree. 317 * 318 * NOTE: DO NOT COPY this code if you are using device tree. 319 */ 320 plat = calloc(1, sizeof(*plat)); 321 if (!plat) 322 return -ENOMEM; 323 324 plat->regs = (struct gpio_regs *)addr; 325 plat->bank_index = dev->req_seq; 326 dev->platdata = plat; 327 328 return 0; 329 } 330 331 static const struct udevice_id mxc_gpio_ids[] = { 332 { .compatible = "fsl,imx35-gpio" }, 333 { } 334 }; 335 336 U_BOOT_DRIVER(gpio_mxc) = { 337 .name = "gpio_mxc", 338 .id = UCLASS_GPIO, 339 .ops = &gpio_mxc_ops, 340 .probe = mxc_gpio_probe, 341 .priv_auto_alloc_size = sizeof(struct mxc_bank_info), 342 .of_match = mxc_gpio_ids, 343 .bind = mxc_gpio_bind, 344 }; 345 346 #if !CONFIG_IS_ENABLED(OF_CONTROL) 347 static const struct mxc_gpio_plat mxc_plat[] = { 348 { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, 349 { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, 350 { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, 351 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 352 defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 353 defined(CONFIG_MX8M) 354 { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, 355 #endif 356 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 357 defined(CONFIG_MX8M) 358 { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, 359 #ifndef CONFIG_MX8M 360 { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, 361 #endif 362 #endif 363 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 364 { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, 365 #endif 366 }; 367 368 U_BOOT_DEVICES(mxc_gpios) = { 369 { "gpio_mxc", &mxc_plat[0] }, 370 { "gpio_mxc", &mxc_plat[1] }, 371 { "gpio_mxc", &mxc_plat[2] }, 372 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 373 defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 374 defined(CONFIG_MX8M) 375 { "gpio_mxc", &mxc_plat[3] }, 376 #endif 377 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 378 defined(CONFIG_MX8M) 379 { "gpio_mxc", &mxc_plat[4] }, 380 #ifndef CONFIG_MX8M 381 { "gpio_mxc", &mxc_plat[5] }, 382 #endif 383 #endif 384 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 385 { "gpio_mxc", &mxc_plat[6] }, 386 #endif 387 }; 388 #endif 389 #endif 390