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 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset) 162 { 163 u32 val; 164 165 val = readl(®s->gpio_dir); 166 167 return val & (1 << offset) ? 1 : 0; 168 } 169 170 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset, 171 enum mxc_gpio_direction direction) 172 { 173 u32 l; 174 175 l = readl(®s->gpio_dir); 176 177 switch (direction) { 178 case MXC_GPIO_DIRECTION_OUT: 179 l |= 1 << offset; 180 break; 181 case MXC_GPIO_DIRECTION_IN: 182 l &= ~(1 << offset); 183 } 184 writel(l, ®s->gpio_dir); 185 } 186 187 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset, 188 int value) 189 { 190 u32 l; 191 192 l = readl(®s->gpio_dr); 193 if (value) 194 l |= 1 << offset; 195 else 196 l &= ~(1 << offset); 197 writel(l, ®s->gpio_dr); 198 } 199 200 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset) 201 { 202 return (readl(®s->gpio_psr) >> offset) & 0x01; 203 } 204 205 /* set GPIO pin 'gpio' as an input */ 206 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset) 207 { 208 struct mxc_bank_info *bank = dev_get_priv(dev); 209 210 /* Configure GPIO direction as input. */ 211 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN); 212 213 return 0; 214 } 215 216 /* set GPIO pin 'gpio' as an output, with polarity 'value' */ 217 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset, 218 int value) 219 { 220 struct mxc_bank_info *bank = dev_get_priv(dev); 221 222 /* Configure GPIO output value. */ 223 mxc_gpio_bank_set_value(bank->regs, offset, value); 224 225 /* Configure GPIO direction as output. */ 226 mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT); 227 228 return 0; 229 } 230 231 /* read GPIO IN value of pin 'gpio' */ 232 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset) 233 { 234 struct mxc_bank_info *bank = dev_get_priv(dev); 235 236 return mxc_gpio_bank_get_value(bank->regs, offset); 237 } 238 239 /* write GPIO OUT value to pin 'gpio' */ 240 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset, 241 int value) 242 { 243 struct mxc_bank_info *bank = dev_get_priv(dev); 244 245 mxc_gpio_bank_set_value(bank->regs, offset, value); 246 247 return 0; 248 } 249 250 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset) 251 { 252 struct mxc_bank_info *bank = dev_get_priv(dev); 253 254 /* GPIOF_FUNC is not implemented yet */ 255 if (mxc_gpio_is_output(bank->regs, offset)) 256 return GPIOF_OUTPUT; 257 else 258 return GPIOF_INPUT; 259 } 260 261 static const struct dm_gpio_ops gpio_mxc_ops = { 262 .direction_input = mxc_gpio_direction_input, 263 .direction_output = mxc_gpio_direction_output, 264 .get_value = mxc_gpio_get_value, 265 .set_value = mxc_gpio_set_value, 266 .get_function = mxc_gpio_get_function, 267 }; 268 269 static int mxc_gpio_probe(struct udevice *dev) 270 { 271 struct mxc_bank_info *bank = dev_get_priv(dev); 272 struct mxc_gpio_plat *plat = dev_get_platdata(dev); 273 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 274 int banknum; 275 char name[18], *str; 276 277 banknum = plat->bank_index; 278 sprintf(name, "GPIO%d_", banknum + 1); 279 str = strdup(name); 280 if (!str) 281 return -ENOMEM; 282 uc_priv->bank_name = str; 283 uc_priv->gpio_count = GPIO_PER_BANK; 284 bank->regs = plat->regs; 285 286 return 0; 287 } 288 289 static int mxc_gpio_bind(struct udevice *dev) 290 { 291 struct mxc_gpio_plat *plat = dev->platdata; 292 fdt_addr_t addr; 293 294 /* 295 * If platdata already exsits, directly return. 296 * Actually only when DT is not supported, platdata 297 * is statically initialized in U_BOOT_DEVICES.Here 298 * will return. 299 */ 300 if (plat) 301 return 0; 302 303 addr = devfdt_get_addr(dev); 304 if (addr == FDT_ADDR_T_NONE) 305 return -EINVAL; 306 307 /* 308 * TODO: 309 * When every board is converted to driver model and DT is supported, 310 * this can be done by auto-alloc feature, but not using calloc 311 * to alloc memory for platdata. 312 * 313 * For example mxc_plat below uses platform data rather than device 314 * tree. 315 * 316 * NOTE: DO NOT COPY this code if you are using device tree. 317 */ 318 plat = calloc(1, sizeof(*plat)); 319 if (!plat) 320 return -ENOMEM; 321 322 plat->regs = (struct gpio_regs *)addr; 323 plat->bank_index = dev->req_seq; 324 dev->platdata = plat; 325 326 return 0; 327 } 328 329 static const struct udevice_id mxc_gpio_ids[] = { 330 { .compatible = "fsl,imx35-gpio" }, 331 { } 332 }; 333 334 U_BOOT_DRIVER(gpio_mxc) = { 335 .name = "gpio_mxc", 336 .id = UCLASS_GPIO, 337 .ops = &gpio_mxc_ops, 338 .probe = mxc_gpio_probe, 339 .priv_auto_alloc_size = sizeof(struct mxc_bank_info), 340 .of_match = mxc_gpio_ids, 341 .bind = mxc_gpio_bind, 342 }; 343 344 #if !CONFIG_IS_ENABLED(OF_CONTROL) 345 static const struct mxc_gpio_plat mxc_plat[] = { 346 { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, 347 { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, 348 { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, 349 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 350 defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 351 defined(CONFIG_MX8M) 352 { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, 353 #endif 354 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 355 defined(CONFIG_MX8M) 356 { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, 357 #ifndef CONFIG_MX8M 358 { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, 359 #endif 360 #endif 361 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 362 { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, 363 #endif 364 }; 365 366 U_BOOT_DEVICES(mxc_gpios) = { 367 { "gpio_mxc", &mxc_plat[0] }, 368 { "gpio_mxc", &mxc_plat[1] }, 369 { "gpio_mxc", &mxc_plat[2] }, 370 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 371 defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 372 defined(CONFIG_MX8M) 373 { "gpio_mxc", &mxc_plat[3] }, 374 #endif 375 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \ 376 defined(CONFIG_MX8M) 377 { "gpio_mxc", &mxc_plat[4] }, 378 #ifndef CONFIG_MX8M 379 { "gpio_mxc", &mxc_plat[5] }, 380 #endif 381 #endif 382 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 383 { "gpio_mxc", &mxc_plat[6] }, 384 #endif 385 }; 386 #endif 387 #endif 388