blob: b2451fdda8ab31a917565cf2b7d78e2e68cf7436 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasut6b6440d2011-11-08 23:18:13 +00002/*
3 * Freescale i.MX28 GPIO control code
4 *
5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
6 * on behalf of DENX Software Engineering GmbH
Marek Vasut6b6440d2011-11-08 23:18:13 +00007 */
8
9#include <common.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +090010#include <linux/errno.h>
Marek Vasut6b6440d2011-11-08 23:18:13 +000011#include <asm/io.h>
12#include <asm/arch/iomux.h>
13#include <asm/arch/imx-regs.h>
14
15#if defined(CONFIG_MX23)
16#define PINCTRL_BANKS 3
17#define PINCTRL_DOUT(n) (0x0500 + ((n) * 0x10))
18#define PINCTRL_DIN(n) (0x0600 + ((n) * 0x10))
19#define PINCTRL_DOE(n) (0x0700 + ((n) * 0x10))
20#define PINCTRL_PIN2IRQ(n) (0x0800 + ((n) * 0x10))
21#define PINCTRL_IRQEN(n) (0x0900 + ((n) * 0x10))
22#define PINCTRL_IRQSTAT(n) (0x0c00 + ((n) * 0x10))
23#elif defined(CONFIG_MX28)
24#define PINCTRL_BANKS 5
25#define PINCTRL_DOUT(n) (0x0700 + ((n) * 0x10))
26#define PINCTRL_DIN(n) (0x0900 + ((n) * 0x10))
27#define PINCTRL_DOE(n) (0x0b00 + ((n) * 0x10))
28#define PINCTRL_PIN2IRQ(n) (0x1000 + ((n) * 0x10))
29#define PINCTRL_IRQEN(n) (0x1100 + ((n) * 0x10))
30#define PINCTRL_IRQSTAT(n) (0x1400 + ((n) * 0x10))
31#else
32#error "Please select CONFIG_MX23 or CONFIG_MX28"
33#endif
34
35#define GPIO_INT_FALL_EDGE 0x0
36#define GPIO_INT_LOW_LEV 0x1
37#define GPIO_INT_RISE_EDGE 0x2
38#define GPIO_INT_HIGH_LEV 0x3
39#define GPIO_INT_LEV_MASK (1 << 0)
40#define GPIO_INT_POL_MASK (1 << 1)
41
42void mxs_gpio_init(void)
43{
44 int i;
45
46 for (i = 0; i < PINCTRL_BANKS; i++) {
47 writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
48 writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
49 /* Use SCT address here to clear the IRQSTAT bits */
50 writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
51 }
52}
53
Lukasz Majewski397af352019-06-19 17:31:05 +020054#if !CONFIG_IS_ENABLED(DM_GPIO)
Joe Hershberger365d6072011-11-11 15:55:36 -060055int gpio_get_value(unsigned gpio)
Marek Vasut6b6440d2011-11-08 23:18:13 +000056{
Joe Hershberger365d6072011-11-11 15:55:36 -060057 uint32_t bank = PAD_BANK(gpio);
Marek Vasut6b6440d2011-11-08 23:18:13 +000058 uint32_t offset = PINCTRL_DIN(bank);
Otavio Salvadorddcf13b2012-08-05 09:05:30 +000059 struct mxs_register_32 *reg =
60 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
Marek Vasut6b6440d2011-11-08 23:18:13 +000061
Joe Hershberger365d6072011-11-11 15:55:36 -060062 return (readl(&reg->reg) >> PAD_PIN(gpio)) & 1;
Marek Vasut6b6440d2011-11-08 23:18:13 +000063}
64
Joe Hershberger365d6072011-11-11 15:55:36 -060065void gpio_set_value(unsigned gpio, int value)
Marek Vasut6b6440d2011-11-08 23:18:13 +000066{
Joe Hershberger365d6072011-11-11 15:55:36 -060067 uint32_t bank = PAD_BANK(gpio);
Marek Vasut6b6440d2011-11-08 23:18:13 +000068 uint32_t offset = PINCTRL_DOUT(bank);
Otavio Salvadorddcf13b2012-08-05 09:05:30 +000069 struct mxs_register_32 *reg =
70 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
Marek Vasut6b6440d2011-11-08 23:18:13 +000071
72 if (value)
Joe Hershberger365d6072011-11-11 15:55:36 -060073 writel(1 << PAD_PIN(gpio), &reg->reg_set);
Marek Vasut6b6440d2011-11-08 23:18:13 +000074 else
Joe Hershberger365d6072011-11-11 15:55:36 -060075 writel(1 << PAD_PIN(gpio), &reg->reg_clr);
Marek Vasut6b6440d2011-11-08 23:18:13 +000076}
77
Joe Hershberger365d6072011-11-11 15:55:36 -060078int gpio_direction_input(unsigned gpio)
Marek Vasut6b6440d2011-11-08 23:18:13 +000079{
Joe Hershberger365d6072011-11-11 15:55:36 -060080 uint32_t bank = PAD_BANK(gpio);
Marek Vasut6b6440d2011-11-08 23:18:13 +000081 uint32_t offset = PINCTRL_DOE(bank);
Otavio Salvadorddcf13b2012-08-05 09:05:30 +000082 struct mxs_register_32 *reg =
83 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
Marek Vasut6b6440d2011-11-08 23:18:13 +000084
Joe Hershberger365d6072011-11-11 15:55:36 -060085 writel(1 << PAD_PIN(gpio), &reg->reg_clr);
Marek Vasut6b6440d2011-11-08 23:18:13 +000086
87 return 0;
88}
89
Joe Hershberger365d6072011-11-11 15:55:36 -060090int gpio_direction_output(unsigned gpio, int value)
Marek Vasut6b6440d2011-11-08 23:18:13 +000091{
Joe Hershberger365d6072011-11-11 15:55:36 -060092 uint32_t bank = PAD_BANK(gpio);
Marek Vasut6b6440d2011-11-08 23:18:13 +000093 uint32_t offset = PINCTRL_DOE(bank);
Otavio Salvadorddcf13b2012-08-05 09:05:30 +000094 struct mxs_register_32 *reg =
95 (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
Marek Vasut6b6440d2011-11-08 23:18:13 +000096
Joe Hershberger365d6072011-11-11 15:55:36 -060097 gpio_set_value(gpio, value);
Marek Vasut6b6440d2011-11-08 23:18:13 +000098
Michael Heimpoldac135f62013-11-03 22:59:26 +010099 writel(1 << PAD_PIN(gpio), &reg->reg_set);
100
Marek Vasut6b6440d2011-11-08 23:18:13 +0000101 return 0;
102}
103
Joe Hershberger365d6072011-11-11 15:55:36 -0600104int gpio_request(unsigned gpio, const char *label)
Marek Vasut6b6440d2011-11-08 23:18:13 +0000105{
Joe Hershberger365d6072011-11-11 15:55:36 -0600106 if (PAD_BANK(gpio) >= PINCTRL_BANKS)
107 return -1;
Marek Vasut6b6440d2011-11-08 23:18:13 +0000108
109 return 0;
110}
111
Joe Hershberger365d6072011-11-11 15:55:36 -0600112int gpio_free(unsigned gpio)
Marek Vasut6b6440d2011-11-08 23:18:13 +0000113{
Joe Hershberger365d6072011-11-11 15:55:36 -0600114 return 0;
Marek Vasut6b6440d2011-11-08 23:18:13 +0000115}
Måns Rullgård88f91d12015-12-15 22:27:57 +0000116
117int name_to_gpio(const char *name)
118{
119 unsigned bank, pin;
120 char *end;
121
122 bank = simple_strtoul(name, &end, 10);
123
124 if (!*end || *end != ':')
125 return bank;
126
127 pin = simple_strtoul(end + 1, NULL, 10);
128
129 return (bank << MXS_PAD_BANK_SHIFT) | (pin << MXS_PAD_PIN_SHIFT);
130}
Lukasz Majewski397af352019-06-19 17:31:05 +0200131#else /* CONFIG_DM_GPIO */
132#include <dm.h>
133#include <asm/gpio.h>
134#include <asm/arch/gpio.h>
135#define MXS_MAX_GPIO_PER_BANK 32
136
137DECLARE_GLOBAL_DATA_PTR;
138/*
139 * According to i.MX28 Reference Manual:
140 * 'i.MX28 Applications Processor Reference Manual, Rev. 1, 2010'
141 * The i.MX28 has following number of GPIOs available:
142 * Bank 0: 0-28 -> 29 PINS
143 * Bank 1: 0-31 -> 32 PINS
144 * Bank 2: 0-27 -> 28 PINS
145 * Bank 3: 0-30 -> 31 PINS
146 * Bank 4: 0-20 -> 21 PINS
147 */
148
149struct mxs_gpio_priv {
150 unsigned int bank;
151};
152
153static int mxs_gpio_get_value(struct udevice *dev, unsigned offset)
154{
155 struct mxs_gpio_priv *priv = dev_get_priv(dev);
156 struct mxs_register_32 *reg =
157 (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
158 PINCTRL_DIN(priv->bank));
159
160 return (readl(&reg->reg) >> offset) & 1;
161}
162
163static int mxs_gpio_set_value(struct udevice *dev, unsigned offset,
164 int value)
165{
166 struct mxs_gpio_priv *priv = dev_get_priv(dev);
167 struct mxs_register_32 *reg =
168 (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
169 PINCTRL_DOUT(priv->bank));
170 if (value)
171 writel(BIT(offset), &reg->reg_set);
172 else
173 writel(BIT(offset), &reg->reg_clr);
174
175 return 0;
176}
177
178static int mxs_gpio_direction_input(struct udevice *dev, unsigned offset)
179{
180 struct mxs_gpio_priv *priv = dev_get_priv(dev);
181 struct mxs_register_32 *reg =
182 (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
183 PINCTRL_DOE(priv->bank));
184
185 writel(BIT(offset), &reg->reg_clr);
186
187 return 0;
188}
189
190static int mxs_gpio_direction_output(struct udevice *dev, unsigned offset,
191 int value)
192{
193 struct mxs_gpio_priv *priv = dev_get_priv(dev);
194 struct mxs_register_32 *reg =
195 (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
196 PINCTRL_DOE(priv->bank));
197
198 mxs_gpio_set_value(dev, offset, value);
199
200 writel(BIT(offset), &reg->reg_set);
201
202 return 0;
203}
204
205static int mxs_gpio_get_function(struct udevice *dev, unsigned offset)
206{
207 struct mxs_gpio_priv *priv = dev_get_priv(dev);
208 struct mxs_register_32 *reg =
209 (struct mxs_register_32 *)(MXS_PINCTRL_BASE +
210 PINCTRL_DOE(priv->bank));
211 bool is_output = !!(readl(&reg->reg) >> offset);
212
213 return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
214}
215
216static const struct dm_gpio_ops gpio_mxs_ops = {
217 .direction_input = mxs_gpio_direction_input,
218 .direction_output = mxs_gpio_direction_output,
219 .get_value = mxs_gpio_get_value,
220 .set_value = mxs_gpio_set_value,
221 .get_function = mxs_gpio_get_function,
222};
223
224static int mxs_gpio_probe(struct udevice *dev)
225{
226 struct mxs_gpio_priv *priv = dev_get_priv(dev);
227 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
228 struct fdtdec_phandle_args args;
229 int node = dev_of_offset(dev);
230 char name[16], *str;
231 fdt_addr_t addr;
232 int ret;
233
234 addr = devfdt_get_addr(dev);
235 if (addr == FDT_ADDR_T_NONE) {
236 printf("%s: No 'reg' property defined!\n", __func__);
237 return -EINVAL;
238 }
239
240 priv->bank = (unsigned int)addr;
241
242 snprintf(name, sizeof(name), "GPIO%d_", priv->bank);
243 str = strdup(name);
244 if (!str)
245 return -ENOMEM;
246
247 uc_priv->bank_name = str;
248
249 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node, "gpio-ranges",
250 NULL, 3, 0, &args);
251 if (ret)
252 printf("%s: 'gpio-ranges' not defined - using default!\n",
253 __func__);
254
255 uc_priv->gpio_count = ret == 0 ? args.args[2] : MXS_MAX_GPIO_PER_BANK;
256
257 debug("%s: %s: %d pins\n", __func__, uc_priv->bank_name,
258 uc_priv->gpio_count);
259
260 return 0;
261}
262
263static const struct udevice_id mxs_gpio_ids[] = {
264 { .compatible = "fsl,imx23-gpio" },
265 { .compatible = "fsl,imx28-gpio" },
266 { }
267};
268
269U_BOOT_DRIVER(gpio_mxs) = {
270 .name = "gpio_mxs",
271 .id = UCLASS_GPIO,
272 .ops = &gpio_mxs_ops,
273 .probe = mxs_gpio_probe,
274 .priv_auto_alloc_size = sizeof(struct mxs_gpio_priv),
275 .of_match = mxs_gpio_ids,
276};
277#endif /* CONFIG_DM_GPIO */