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 [3] = GPIO4_BASE_ADDR, 45 #endif 46 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 47 [4] = GPIO5_BASE_ADDR, 48 #ifndef CONFIG_MX6UL 49 [5] = GPIO6_BASE_ADDR, 50 #endif 51 #endif 52 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 53 #ifndef CONFIG_MX6UL 54 [6] = GPIO7_BASE_ADDR, 55 #endif 56 #endif 57 }; 58 59 static int mxc_gpio_direction(unsigned int gpio, 60 enum mxc_gpio_direction direction) 61 { 62 unsigned int port = GPIO_TO_PORT(gpio); 63 struct gpio_regs *regs; 64 u32 l; 65 66 if (port >= ARRAY_SIZE(gpio_ports)) 67 return -1; 68 69 gpio &= 0x1f; 70 71 regs = (struct gpio_regs *)gpio_ports[port]; 72 73 l = readl(®s->gpio_dir); 74 75 switch (direction) { 76 case MXC_GPIO_DIRECTION_OUT: 77 l |= 1 << gpio; 78 break; 79 case MXC_GPIO_DIRECTION_IN: 80 l &= ~(1 << gpio); 81 } 82 writel(l, ®s->gpio_dir); 83 84 return 0; 85 } 86 87 int gpio_set_value(unsigned gpio, int value) 88 { 89 unsigned int port = GPIO_TO_PORT(gpio); 90 struct gpio_regs *regs; 91 u32 l; 92 93 if (port >= ARRAY_SIZE(gpio_ports)) 94 return -1; 95 96 gpio &= 0x1f; 97 98 regs = (struct gpio_regs *)gpio_ports[port]; 99 100 l = readl(®s->gpio_dr); 101 if (value) 102 l |= 1 << gpio; 103 else 104 l &= ~(1 << gpio); 105 writel(l, ®s->gpio_dr); 106 107 return 0; 108 } 109 110 int gpio_get_value(unsigned gpio) 111 { 112 unsigned int port = GPIO_TO_PORT(gpio); 113 struct gpio_regs *regs; 114 u32 val; 115 116 if (port >= ARRAY_SIZE(gpio_ports)) 117 return -1; 118 119 gpio &= 0x1f; 120 121 regs = (struct gpio_regs *)gpio_ports[port]; 122 123 val = (readl(®s->gpio_psr) >> gpio) & 0x01; 124 125 return val; 126 } 127 128 int gpio_request(unsigned gpio, const char *label) 129 { 130 unsigned int port = GPIO_TO_PORT(gpio); 131 if (port >= ARRAY_SIZE(gpio_ports)) 132 return -1; 133 return 0; 134 } 135 136 int gpio_free(unsigned gpio) 137 { 138 return 0; 139 } 140 141 int gpio_direction_input(unsigned gpio) 142 { 143 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); 144 } 145 146 int gpio_direction_output(unsigned gpio, int value) 147 { 148 int ret = gpio_set_value(gpio, value); 149 150 if (ret < 0) 151 return ret; 152 153 return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); 154 } 155 #endif 156 157 #ifdef CONFIG_DM_GPIO 158 #include <fdtdec.h> 159 DECLARE_GLOBAL_DATA_PTR; 160 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 = dev_get_addr(dev); 304 if (addr == FDT_ADDR_T_NONE) 305 return -ENODEV; 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 plat = calloc(1, sizeof(*plat)); 314 if (!plat) 315 return -ENOMEM; 316 317 plat->regs = (struct gpio_regs *)addr; 318 plat->bank_index = dev->req_seq; 319 dev->platdata = plat; 320 321 return 0; 322 } 323 324 static const struct udevice_id mxc_gpio_ids[] = { 325 { .compatible = "fsl,imx35-gpio" }, 326 { } 327 }; 328 329 U_BOOT_DRIVER(gpio_mxc) = { 330 .name = "gpio_mxc", 331 .id = UCLASS_GPIO, 332 .ops = &gpio_mxc_ops, 333 .probe = mxc_gpio_probe, 334 .priv_auto_alloc_size = sizeof(struct mxc_bank_info), 335 .of_match = mxc_gpio_ids, 336 .bind = mxc_gpio_bind, 337 }; 338 339 #if !CONFIG_IS_ENABLED(OF_CONTROL) 340 static const struct mxc_gpio_plat mxc_plat[] = { 341 { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, 342 { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, 343 { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, 344 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 345 defined(CONFIG_MX53) || defined(CONFIG_MX6) 346 { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, 347 #endif 348 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 349 { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, 350 { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, 351 #endif 352 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 353 { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, 354 #endif 355 }; 356 357 U_BOOT_DEVICES(mxc_gpios) = { 358 { "gpio_mxc", &mxc_plat[0] }, 359 { "gpio_mxc", &mxc_plat[1] }, 360 { "gpio_mxc", &mxc_plat[2] }, 361 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ 362 defined(CONFIG_MX53) || defined(CONFIG_MX6) 363 { "gpio_mxc", &mxc_plat[3] }, 364 #endif 365 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) 366 { "gpio_mxc", &mxc_plat[4] }, 367 { "gpio_mxc", &mxc_plat[5] }, 368 #endif 369 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) 370 { "gpio_mxc", &mxc_plat[6] }, 371 #endif 372 }; 373 #endif 374 #endif 375