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