3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
6 * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
8 * SPDX-License-Identifier: GPL-2.0+
14 #include <asm/arch/imx-regs.h>
18 enum mxc_gpio_direction
{
19 MXC_GPIO_DIRECTION_IN
,
20 MXC_GPIO_DIRECTION_OUT
,
23 #define GPIO_PER_BANK 32
25 struct mxc_gpio_plat
{
26 struct gpio_regs
*regs
;
29 struct mxc_bank_info
{
30 struct gpio_regs
*regs
;
33 #ifndef CONFIG_DM_GPIO
34 #define GPIO_TO_PORT(n) (n / 32)
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
,
45 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
46 [4] = GPIO5_BASE_ADDR
,
47 [5] = GPIO6_BASE_ADDR
,
49 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
50 [6] = GPIO7_BASE_ADDR
,
54 static int mxc_gpio_direction(unsigned int gpio
,
55 enum mxc_gpio_direction direction
)
57 unsigned int port
= GPIO_TO_PORT(gpio
);
58 struct gpio_regs
*regs
;
61 if (port
>= ARRAY_SIZE(gpio_ports
))
66 regs
= (struct gpio_regs
*)gpio_ports
[port
];
68 l
= readl(®s
->gpio_dir
);
71 case MXC_GPIO_DIRECTION_OUT
:
74 case MXC_GPIO_DIRECTION_IN
:
77 writel(l
, ®s
->gpio_dir
);
82 int gpio_set_value(unsigned gpio
, int value
)
84 unsigned int port
= GPIO_TO_PORT(gpio
);
85 struct gpio_regs
*regs
;
88 if (port
>= ARRAY_SIZE(gpio_ports
))
93 regs
= (struct gpio_regs
*)gpio_ports
[port
];
95 l
= readl(®s
->gpio_dr
);
100 writel(l
, ®s
->gpio_dr
);
105 int gpio_get_value(unsigned gpio
)
107 unsigned int port
= GPIO_TO_PORT(gpio
);
108 struct gpio_regs
*regs
;
111 if (port
>= ARRAY_SIZE(gpio_ports
))
116 regs
= (struct gpio_regs
*)gpio_ports
[port
];
118 val
= (readl(®s
->gpio_psr
) >> gpio
) & 0x01;
123 int gpio_request(unsigned gpio
, const char *label
)
125 unsigned int port
= GPIO_TO_PORT(gpio
);
126 if (port
>= ARRAY_SIZE(gpio_ports
))
131 int gpio_free(unsigned gpio
)
136 int gpio_direction_input(unsigned gpio
)
138 return mxc_gpio_direction(gpio
, MXC_GPIO_DIRECTION_IN
);
141 int gpio_direction_output(unsigned gpio
, int value
)
143 int ret
= gpio_set_value(gpio
, value
);
148 return mxc_gpio_direction(gpio
, MXC_GPIO_DIRECTION_OUT
);
152 #ifdef CONFIG_DM_GPIO
153 static int mxc_gpio_is_output(struct gpio_regs
*regs
, int offset
)
157 val
= readl(®s
->gpio_dir
);
159 return val
& (1 << offset
) ? 1 : 0;
162 static void mxc_gpio_bank_direction(struct gpio_regs
*regs
, int offset
,
163 enum mxc_gpio_direction direction
)
167 l
= readl(®s
->gpio_dir
);
170 case MXC_GPIO_DIRECTION_OUT
:
173 case MXC_GPIO_DIRECTION_IN
:
176 writel(l
, ®s
->gpio_dir
);
179 static void mxc_gpio_bank_set_value(struct gpio_regs
*regs
, int offset
,
184 l
= readl(®s
->gpio_dr
);
189 writel(l
, ®s
->gpio_dr
);
192 static int mxc_gpio_bank_get_value(struct gpio_regs
*regs
, int offset
)
194 return (readl(®s
->gpio_psr
) >> offset
) & 0x01;
197 /* set GPIO pin 'gpio' as an input */
198 static int mxc_gpio_direction_input(struct udevice
*dev
, unsigned offset
)
200 struct mxc_bank_info
*bank
= dev_get_priv(dev
);
202 /* Configure GPIO direction as input. */
203 mxc_gpio_bank_direction(bank
->regs
, offset
, MXC_GPIO_DIRECTION_IN
);
208 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
209 static int mxc_gpio_direction_output(struct udevice
*dev
, unsigned offset
,
212 struct mxc_bank_info
*bank
= dev_get_priv(dev
);
214 /* Configure GPIO output value. */
215 mxc_gpio_bank_set_value(bank
->regs
, offset
, value
);
217 /* Configure GPIO direction as output. */
218 mxc_gpio_bank_direction(bank
->regs
, offset
, MXC_GPIO_DIRECTION_OUT
);
223 /* read GPIO IN value of pin 'gpio' */
224 static int mxc_gpio_get_value(struct udevice
*dev
, unsigned offset
)
226 struct mxc_bank_info
*bank
= dev_get_priv(dev
);
228 return mxc_gpio_bank_get_value(bank
->regs
, offset
);
231 /* write GPIO OUT value to pin 'gpio' */
232 static int mxc_gpio_set_value(struct udevice
*dev
, unsigned offset
,
235 struct mxc_bank_info
*bank
= dev_get_priv(dev
);
237 mxc_gpio_bank_set_value(bank
->regs
, offset
, value
);
242 static int mxc_gpio_get_function(struct udevice
*dev
, unsigned offset
)
244 struct mxc_bank_info
*bank
= dev_get_priv(dev
);
246 /* GPIOF_FUNC is not implemented yet */
247 if (mxc_gpio_is_output(bank
->regs
, offset
))
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
,
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
},
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
},
273 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
274 { (struct gpio_regs
*)GPIO7_BASE_ADDR
},
278 static int mxc_gpio_probe(struct udevice
*dev
)
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
;
286 banknum
= plat
- mxc_plat
;
287 sprintf(name
, "GPIO%d_", banknum
+ 1);
291 uc_priv
->bank_name
= str
;
292 uc_priv
->gpio_count
= GPIO_PER_BANK
;
293 bank
->regs
= plat
->regs
;
298 U_BOOT_DRIVER(gpio_mxc
) = {
301 .ops
= &gpio_mxc_ops
,
302 .probe
= mxc_gpio_probe
,
303 .priv_auto_alloc_size
= sizeof(struct mxc_bank_info
),
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] },
314 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
315 { "gpio_mxc", &mxc_plat
[4] },
316 { "gpio_mxc", &mxc_plat
[5] },
318 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
319 { "gpio_mxc", &mxc_plat
[6] },