1 // SPDX-License-Identifier: GPL-2.0
3 * RZ/G2L Pin Function Controller
5 * Copyright (C) 2021-2023 Renesas Electronics Corp.
8 #include <asm-generic/gpio.h>
10 #include <dm/device.h>
11 #include <dm/device_compat.h>
12 #include <renesas/rzg2l-pfc.h>
14 static void rzg2l_gpio_set(const struct rzg2l_pfc_data *data, u32 port, u8 pin,
18 setbits_8(data->base + P(port), BIT(pin));
20 clrbits_8(data->base + P(port), BIT(pin));
23 static int rzg2l_gpio_get_value(struct udevice *dev, unsigned int offset)
25 const struct rzg2l_pfc_data *data =
26 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
27 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
28 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
31 pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK;
34 return !!(readb(data->base + PIN(port)) & BIT(pin));
37 return !!(readb(data->base + P(port)) & BIT(pin));
38 default: /* PM_HIGH_Z */
43 static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset,
46 const struct rzg2l_pfc_data *data =
47 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
48 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
49 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
51 rzg2l_gpio_set(data, port, pin, (bool)value);
55 static void rzg2l_gpio_set_direction(const struct rzg2l_pfc_data *data,
56 u32 port, u8 pin, bool output)
58 clrsetbits_le16(data->base + PM(port), PM_MASK << (pin * 2),
59 (output ? PM_OUTPUT : PM_INPUT) << (pin * 2));
62 static int rzg2l_gpio_direction_input(struct udevice *dev, unsigned int offset)
64 const struct rzg2l_pfc_data *data =
65 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
66 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
67 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
69 rzg2l_gpio_set_direction(data, port, pin, false);
73 static int rzg2l_gpio_direction_output(struct udevice *dev, unsigned int offset,
76 const struct rzg2l_pfc_data *data =
77 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
78 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
79 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
81 rzg2l_gpio_set(data, port, pin, (bool)value);
82 rzg2l_gpio_set_direction(data, port, pin, true);
86 static int rzg2l_gpio_request(struct udevice *dev, unsigned int offset,
89 const struct rzg2l_pfc_data *data =
90 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
91 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
92 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
94 if (!rzg2l_port_validate(data, port, pin)) {
95 dev_err(dev, "Invalid GPIO %u:%u\n", port, pin);
99 /* Select GPIO mode in PMC Register */
100 clrbits_8(data->base + PMC(port), BIT(pin));
105 static int rzg2l_gpio_get_function(struct udevice *dev, unsigned int offset)
107 const struct rzg2l_pfc_data *data =
108 (const struct rzg2l_pfc_data *)dev_get_driver_data(dev);
109 const u32 port = RZG2L_PINMUX_TO_PORT(offset);
110 const u8 pin = RZG2L_PINMUX_TO_PIN(offset);
114 if (!rzg2l_port_validate(data, port, pin)) {
115 /* This offset does not correspond to a valid GPIO pin. */
119 /* Check if the pin is in GPIO or function mode. */
120 pmc_state = readb(data->base + PMC(port)) & BIT(pin);
124 /* Check the pin direction. */
125 pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK;
132 default: /* PM_HIGH_Z */
137 static const struct dm_gpio_ops rzg2l_gpio_ops = {
138 .direction_input = rzg2l_gpio_direction_input,
139 .direction_output = rzg2l_gpio_direction_output,
140 .get_value = rzg2l_gpio_get_value,
141 .set_value = rzg2l_gpio_set_value,
142 .request = rzg2l_gpio_request,
143 .get_function = rzg2l_gpio_get_function,
146 static int rzg2l_gpio_probe(struct udevice *dev)
148 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
149 struct ofnode_phandle_args args;
152 uc_priv->bank_name = "rzg2l-pfc-gpio";
153 ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges",
156 dev_err(dev, "Failed to parse gpio-ranges: %d\n", ret);
160 uc_priv->gpio_count = args.args[2];
161 return rzg2l_pfc_enable(dev);
164 U_BOOT_DRIVER(rzg2l_pfc_gpio) = {
165 .name = "rzg2l-pfc-gpio",
167 .ops = &rzg2l_gpio_ops,
168 .probe = rzg2l_gpio_probe,