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