1// SPDX-License-Identifier: GPL-2.0 2/* 3 * RZ/G2L Pin Function Controller 4 * 5 * Copyright (C) 2021-2023 Renesas Electronics Corp. 6 */ 7 8#include <asm-generic/gpio.h> 9#include <asm/io.h> 10#include <dm/device.h> 11#include <dm/device_compat.h> 12#include <renesas/rzg2l-pfc.h> 13 14static void rzg2l_gpio_set(const struct rzg2l_pfc_data *data, u32 port, u8 pin, 15 bool value) 16{ 17 if (value) 18 setbits_8(data->base + P(port), BIT(pin)); 19 else 20 clrbits_8(data->base + P(port), BIT(pin)); 21} 22 23static int rzg2l_gpio_get_value(struct udevice *dev, unsigned int offset) 24{ 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); 29 u16 pm_state; 30 31 pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK; 32 switch (pm_state) { 33 case PM_INPUT: 34 return !!(readb(data->base + PIN(port)) & BIT(pin)); 35 case PM_OUTPUT: 36 case PM_OUTPUT_IEN: 37 return !!(readb(data->base + P(port)) & BIT(pin)); 38 default: /* PM_HIGH_Z */ 39 return 0; 40 } 41} 42 43static int rzg2l_gpio_set_value(struct udevice *dev, unsigned int offset, 44 int value) 45{ 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); 50 51 rzg2l_gpio_set(data, port, pin, (bool)value); 52 return 0; 53} 54 55static void rzg2l_gpio_set_direction(const struct rzg2l_pfc_data *data, 56 u32 port, u8 pin, bool output) 57{ 58 clrsetbits_le16(data->base + PM(port), PM_MASK << (pin * 2), 59 (output ? PM_OUTPUT : PM_INPUT) << (pin * 2)); 60} 61 62static int rzg2l_gpio_direction_input(struct udevice *dev, unsigned int offset) 63{ 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); 68 69 rzg2l_gpio_set_direction(data, port, pin, false); 70 return 0; 71} 72 73static int rzg2l_gpio_direction_output(struct udevice *dev, unsigned int offset, 74 int value) 75{ 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); 80 81 rzg2l_gpio_set(data, port, pin, (bool)value); 82 rzg2l_gpio_set_direction(data, port, pin, true); 83 return 0; 84} 85 86static int rzg2l_gpio_request(struct udevice *dev, unsigned int offset, 87 const char *label) 88{ 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); 93 94 if (!rzg2l_port_validate(data, port, pin)) { 95 dev_err(dev, "Invalid GPIO %u:%u\n", port, pin); 96 return -EINVAL; 97 } 98 99 /* Select GPIO mode in PMC Register */ 100 clrbits_8(data->base + PMC(port), BIT(pin)); 101 102 return 0; 103} 104 105static int rzg2l_gpio_get_function(struct udevice *dev, unsigned int offset) 106{ 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); 111 u16 pm_state; 112 u8 pmc_state; 113 114 if (!rzg2l_port_validate(data, port, pin)) { 115 /* This offset does not correspond to a valid GPIO pin. */ 116 return -ENOENT; 117 } 118 119 /* Check if the pin is in GPIO or function mode. */ 120 pmc_state = readb(data->base + PMC(port)) & BIT(pin); 121 if (pmc_state) 122 return GPIOF_FUNC; 123 124 /* Check the pin direction. */ 125 pm_state = (readw(data->base + PM(port)) >> (pin * 2)) & PM_MASK; 126 switch (pm_state) { 127 case PM_INPUT: 128 return GPIOF_INPUT; 129 case PM_OUTPUT: 130 case PM_OUTPUT_IEN: 131 return GPIOF_OUTPUT; 132 default: /* PM_HIGH_Z */ 133 return GPIOF_UNUSED; 134 } 135} 136 137static 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, 144}; 145 146static int rzg2l_gpio_probe(struct udevice *dev) 147{ 148 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 149 struct ofnode_phandle_args args; 150 int ret; 151 152 uc_priv->bank_name = "rzg2l-pfc-gpio"; 153 ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges", 154 NULL, 3, 0, &args); 155 if (ret < 0) { 156 dev_err(dev, "Failed to parse gpio-ranges: %d\n", ret); 157 return -EINVAL; 158 } 159 160 uc_priv->gpio_count = args.args[2]; 161 return rzg2l_pfc_enable(dev); 162} 163 164U_BOOT_DRIVER(rzg2l_pfc_gpio) = { 165 .name = "rzg2l-pfc-gpio", 166 .id = UCLASS_GPIO, 167 .ops = &rzg2l_gpio_ops, 168 .probe = rzg2l_gpio_probe, 169}; 170