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