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