1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2016 Freescale Semiconductor, Inc.
5 * RGPIO2P driver for the Freescale i.MX7ULP.
14 #include <dm/device-internal.h>
17 enum imx_rgpio2p_direction {
18 IMX_RGPIO2P_DIRECTION_IN,
19 IMX_RGPIO2P_DIRECTION_OUT,
22 #define GPIO_PER_BANK 32
24 struct imx_rgpio2p_soc_data {
28 #define IMX8ULP_GPIO_BASE_OFF 0x40
30 struct imx_rgpio2p_data {
31 struct gpio_regs *regs;
34 struct imx_rgpio2p_plat {
36 struct gpio_regs *regs;
39 static int imx_rgpio2p_is_output(struct gpio_regs *regs, int offset)
43 val = readl(®s->gpio_pddr);
45 return val & (1 << offset) ? 1 : 0;
48 static int imx_rgpio2p_bank_get_direction(struct gpio_regs *regs, int offset)
50 if ((readl(®s->gpio_pddr) >> offset) & 0x01)
51 return IMX_RGPIO2P_DIRECTION_OUT;
53 return IMX_RGPIO2P_DIRECTION_IN;
56 static void imx_rgpio2p_bank_direction(struct gpio_regs *regs, int offset,
57 enum imx_rgpio2p_direction direction)
61 l = readl(®s->gpio_pddr);
64 case IMX_RGPIO2P_DIRECTION_OUT:
67 case IMX_RGPIO2P_DIRECTION_IN:
70 writel(l, ®s->gpio_pddr);
73 static void imx_rgpio2p_bank_set_value(struct gpio_regs *regs, int offset,
77 writel((1 << offset), ®s->gpio_psor);
79 writel((1 << offset), ®s->gpio_pcor);
82 static int imx_rgpio2p_bank_get_value(struct gpio_regs *regs, int offset)
84 if (imx_rgpio2p_bank_get_direction(regs, offset) ==
85 IMX_RGPIO2P_DIRECTION_IN)
86 return (readl(®s->gpio_pdir) >> offset) & 0x01;
88 return (readl(®s->gpio_pdor) >> offset) & 0x01;
91 static int imx_rgpio2p_direction_input(struct udevice *dev, unsigned offset)
93 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
95 /* Configure GPIO direction as input. */
96 imx_rgpio2p_bank_direction(bank->regs, offset, IMX_RGPIO2P_DIRECTION_IN);
101 static int imx_rgpio2p_direction_output(struct udevice *dev, unsigned offset,
104 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
106 /* Configure GPIO output value. */
107 imx_rgpio2p_bank_set_value(bank->regs, offset, value);
109 /* Configure GPIO direction as output. */
110 imx_rgpio2p_bank_direction(bank->regs, offset, IMX_RGPIO2P_DIRECTION_OUT);
115 static int imx_rgpio2p_get_value(struct udevice *dev, unsigned offset)
117 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
119 return imx_rgpio2p_bank_get_value(bank->regs, offset);
122 static int imx_rgpio2p_set_value(struct udevice *dev, unsigned offset,
125 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
127 imx_rgpio2p_bank_set_value(bank->regs, offset, value);
132 static int imx_rgpio2p_get_function(struct udevice *dev, unsigned offset)
134 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
136 /* GPIOF_FUNC is not implemented yet */
137 if (imx_rgpio2p_is_output(bank->regs, offset))
143 static const struct dm_gpio_ops imx_rgpio2p_ops = {
144 .direction_input = imx_rgpio2p_direction_input,
145 .direction_output = imx_rgpio2p_direction_output,
146 .get_value = imx_rgpio2p_get_value,
147 .set_value = imx_rgpio2p_set_value,
148 .get_function = imx_rgpio2p_get_function,
151 static int imx_rgpio2p_probe(struct udevice *dev)
153 struct imx_rgpio2p_data *bank = dev_get_priv(dev);
154 struct imx_rgpio2p_plat *plat = dev_get_plat(dev);
155 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
159 banknum = plat->bank_index;
160 sprintf(name, "GPIO%d_", banknum + 1);
164 uc_priv->bank_name = str;
165 uc_priv->gpio_count = GPIO_PER_BANK;
166 bank->regs = plat->regs;
171 static int imx_rgpio2p_bind(struct udevice *dev)
173 struct imx_rgpio2p_plat *plat = dev_get_plat(dev);
174 struct imx_rgpio2p_soc_data *data =
175 (struct imx_rgpio2p_soc_data *)dev_get_driver_data(dev);
176 bool dual_base = data->have_dual_base;
180 * If plat already exsits, directly return.
181 * Actually only when DT is not supported, plat
182 * is statically initialized in U_BOOT_DRVINFOS.Here
189 * Handle legacy compatible combinations which used two reg values
190 * for the i.MX8ULP and i.MX93.
192 if (device_is_compatible(dev, "fsl,imx7ulp-gpio") &&
193 (device_is_compatible(dev, "fsl,imx93-gpio") ||
194 (device_is_compatible(dev, "fsl,imx8ulp-gpio"))))
198 addr = devfdt_get_addr_index(dev, 1);
199 if (addr == FDT_ADDR_T_NONE)
202 addr = devfdt_get_addr_index(dev, 0);
203 if (addr == FDT_ADDR_T_NONE)
206 addr += IMX8ULP_GPIO_BASE_OFF;
211 * When every board is converted to driver model and DT is supported,
212 * this can be done by auto-alloc feature, but not using calloc
213 * to alloc memory for plat.
215 * For example imx_rgpio2p_plat uses platform data rather than device
218 * NOTE: DO NOT COPY this code if you are using device tree.
220 plat = calloc(1, sizeof(*plat));
224 plat->regs = (struct gpio_regs *)addr;
225 plat->bank_index = dev_seq(dev);
226 dev_set_plat(dev, plat);
231 static struct imx_rgpio2p_soc_data imx7ulp_data = {
232 .have_dual_base = true,
235 static struct imx_rgpio2p_soc_data imx8ulp_data = {
236 .have_dual_base = false,
239 static const struct udevice_id imx_rgpio2p_ids[] = {
240 { .compatible = "fsl,imx7ulp-gpio", .data = (ulong)&imx7ulp_data },
241 { .compatible = "fsl,imx8ulp-gpio", .data = (ulong)&imx8ulp_data },
245 U_BOOT_DRIVER(imx_rgpio2p) = {
246 .name = "imx_rgpio2p",
248 .ops = &imx_rgpio2p_ops,
249 .probe = imx_rgpio2p_probe,
250 .priv_auto = sizeof(struct imx_rgpio2p_plat),
251 .of_match = imx_rgpio2p_ids,
252 .bind = imx_rgpio2p_bind,
255 #if !CONFIG_IS_ENABLED(OF_CONTROL)
256 static const struct imx_rgpio2p_plat imx_plat[] = {
257 { 0, (struct gpio_regs *)RGPIO2P_GPIO1_BASE_ADDR },
258 { 1, (struct gpio_regs *)RGPIO2P_GPIO2_BASE_ADDR },
259 { 2, (struct gpio_regs *)RGPIO2P_GPIO3_BASE_ADDR },
260 { 3, (struct gpio_regs *)RGPIO2P_GPIO4_BASE_ADDR },
261 { 4, (struct gpio_regs *)RGPIO2P_GPIO5_BASE_ADDR },
262 { 5, (struct gpio_regs *)RGPIO2P_GPIO6_BASE_ADDR },
265 U_BOOT_DRVINFOS(imx_rgpio2ps) = {
266 { "imx_rgpio2p", &imx_plat[0] },
267 { "imx_rgpio2p", &imx_plat[1] },
268 { "imx_rgpio2p", &imx_plat[2] },
269 { "imx_rgpio2p", &imx_plat[3] },
270 { "imx_rgpio2p", &imx_plat[4] },
271 { "imx_rgpio2p", &imx_plat[5] },