1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2010-2016, NVIDIA CORPORATION. 4 * (based on tegra_gpio.c) 5 */ 6 7#include <common.h> 8#include <dm.h> 9#include <malloc.h> 10#include <errno.h> 11#include <fdtdec.h> 12#include <asm/io.h> 13#include <asm/bitops.h> 14#include <asm/gpio.h> 15#include <dm/device-internal.h> 16#include <dt-bindings/gpio/gpio.h> 17#include "tegra186_gpio_priv.h" 18 19struct tegra186_gpio_port_data { 20 const char *name; 21 uint32_t offset; 22}; 23 24struct tegra186_gpio_ctlr_data { 25 const struct tegra186_gpio_port_data *ports; 26 uint32_t port_count; 27}; 28 29struct tegra186_gpio_plat { 30 const char *name; 31 uint32_t *regs; 32}; 33 34static uint32_t *tegra186_gpio_reg(struct udevice *dev, uint32_t reg, 35 uint32_t gpio) 36{ 37 struct tegra186_gpio_plat *plat = dev_get_plat(dev); 38 uint32_t index = (reg + (gpio * TEGRA186_GPIO_PER_GPIO_STRIDE)) / 4; 39 40 return &(plat->regs[index]); 41} 42 43static int tegra186_gpio_set_out(struct udevice *dev, unsigned offset, 44 bool output) 45{ 46 uint32_t *reg; 47 uint32_t rval; 48 49 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_CONTROL, offset); 50 rval = readl(reg); 51 if (output) 52 rval &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED; 53 else 54 rval |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED; 55 writel(rval, reg); 56 57 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset); 58 rval = readl(reg); 59 if (output) 60 rval |= TEGRA186_GPIO_ENABLE_CONFIG_OUT; 61 else 62 rval &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT; 63 rval |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE; 64 writel(rval, reg); 65 66 return 0; 67} 68 69static int tegra186_gpio_set_val(struct udevice *dev, unsigned offset, bool val) 70{ 71 uint32_t *reg; 72 uint32_t rval; 73 74 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE, offset); 75 rval = readl(reg); 76 if (val) 77 rval |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH; 78 else 79 rval &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH; 80 writel(rval, reg); 81 82 return 0; 83} 84 85static int tegra186_gpio_direction_input(struct udevice *dev, unsigned offset) 86{ 87 return tegra186_gpio_set_out(dev, offset, false); 88} 89 90static int tegra186_gpio_direction_output(struct udevice *dev, unsigned offset, 91 int value) 92{ 93 int ret; 94 95 ret = tegra186_gpio_set_val(dev, offset, value != 0); 96 if (ret) 97 return ret; 98 return tegra186_gpio_set_out(dev, offset, true); 99} 100 101static int tegra186_gpio_get_value(struct udevice *dev, unsigned offset) 102{ 103 uint32_t *reg; 104 uint32_t rval; 105 106 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset); 107 rval = readl(reg); 108 109 if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT) 110 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE, 111 offset); 112 else 113 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_INPUT, offset); 114 115 rval = readl(reg); 116 return !!rval; 117} 118 119static int tegra186_gpio_set_value(struct udevice *dev, unsigned offset, 120 int value) 121{ 122 return tegra186_gpio_set_val(dev, offset, value != 0); 123} 124 125static int tegra186_gpio_get_function(struct udevice *dev, unsigned offset) 126{ 127 uint32_t *reg; 128 uint32_t rval; 129 130 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset); 131 rval = readl(reg); 132 if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT) 133 return GPIOF_OUTPUT; 134 else 135 return GPIOF_INPUT; 136} 137 138static int tegra186_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, 139 struct ofnode_phandle_args *args) 140{ 141 int gpio, port, ret; 142 143 gpio = args->args[0]; 144 port = gpio / TEGRA186_GPIO_PER_GPIO_COUNT; 145 ret = device_get_child(dev, port, &desc->dev); 146 if (ret) 147 return ret; 148 desc->offset = gpio % TEGRA186_GPIO_PER_GPIO_COUNT; 149 desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; 150 151 return 0; 152} 153 154static const struct dm_gpio_ops tegra186_gpio_ops = { 155 .direction_input = tegra186_gpio_direction_input, 156 .direction_output = tegra186_gpio_direction_output, 157 .get_value = tegra186_gpio_get_value, 158 .set_value = tegra186_gpio_set_value, 159 .get_function = tegra186_gpio_get_function, 160 .xlate = tegra186_gpio_xlate, 161}; 162 163/** 164 * We have a top-level GPIO device with no actual GPIOs. It has a child device 165 * for each port within the controller. 166 */ 167static int tegra186_gpio_bind(struct udevice *parent) 168{ 169 struct tegra186_gpio_plat *parent_plat = dev_get_plat(parent); 170 struct tegra186_gpio_ctlr_data *ctlr_data = 171 (struct tegra186_gpio_ctlr_data *)dev_get_driver_data(parent); 172 uint32_t *regs; 173 int port, ret; 174 175 /* If this is a child device, there is nothing to do here */ 176 if (parent_plat) 177 return 0; 178 179 regs = dev_read_addr_name_ptr(parent, "gpio"); 180 if (!regs) 181 return -EINVAL; 182 183 for (port = 0; port < ctlr_data->port_count; port++) { 184 struct tegra186_gpio_plat *plat; 185 struct udevice *dev; 186 187 plat = calloc(1, sizeof(*plat)); 188 if (!plat) 189 return -ENOMEM; 190 plat->name = ctlr_data->ports[port].name; 191 plat->regs = &(regs[ctlr_data->ports[port].offset / 4]); 192 193 ret = device_bind(parent, parent->driver, plat->name, plat, 194 dev_ofnode(parent), &dev); 195 if (ret) 196 return ret; 197 } 198 199 return 0; 200} 201 202static int tegra186_gpio_probe(struct udevice *dev) 203{ 204 struct tegra186_gpio_plat *plat = dev_get_plat(dev); 205 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 206 207 /* Only child devices have ports */ 208 if (!plat) 209 return 0; 210 211 uc_priv->gpio_count = TEGRA186_GPIO_PER_GPIO_COUNT; 212 uc_priv->bank_name = plat->name; 213 214 return 0; 215} 216 217static const struct tegra186_gpio_port_data tegra186_gpio_main_ports[] = { 218 {"A", 0x2000}, 219 {"B", 0x3000}, 220 {"C", 0x3200}, 221 {"D", 0x3400}, 222 {"E", 0x2200}, 223 {"F", 0x2400}, 224 {"G", 0x4200}, 225 {"H", 0x1000}, 226 {"I", 0x0800}, 227 {"J", 0x5000}, 228 {"K", 0x5200}, 229 {"L", 0x1200}, 230 {"M", 0x5600}, 231 {"N", 0x0000}, 232 {"O", 0x0200}, 233 {"P", 0x4000}, 234 {"Q", 0x0400}, 235 {"R", 0x0a00}, 236 {"T", 0x0600}, 237 {"X", 0x1400}, 238 {"Y", 0x1600}, 239 {"BB", 0x2600}, 240 {"CC", 0x5400}, 241}; 242 243static const struct tegra186_gpio_ctlr_data tegra186_gpio_main_data = { 244 .ports = tegra186_gpio_main_ports, 245 .port_count = ARRAY_SIZE(tegra186_gpio_main_ports), 246}; 247 248static const struct tegra186_gpio_port_data tegra186_gpio_aon_ports[] = { 249 {"S", 0x0200}, 250 {"U", 0x0400}, 251 {"V", 0x0800}, 252 {"W", 0x0a00}, 253 {"Z", 0x0e00}, 254 {"AA", 0x0c00}, 255 {"EE", 0x0600}, 256 {"FF", 0x0000}, 257}; 258 259static const struct tegra186_gpio_ctlr_data tegra186_gpio_aon_data = { 260 .ports = tegra186_gpio_aon_ports, 261 .port_count = ARRAY_SIZE(tegra186_gpio_aon_ports), 262}; 263 264static const struct udevice_id tegra186_gpio_ids[] = { 265 { 266 .compatible = "nvidia,tegra186-gpio", 267 .data = (ulong)&tegra186_gpio_main_data, 268 }, 269 { 270 .compatible = "nvidia,tegra186-gpio-aon", 271 .data = (ulong)&tegra186_gpio_aon_data, 272 }, 273 { } 274}; 275 276U_BOOT_DRIVER(tegra186_gpio) = { 277 .name = "tegra186_gpio", 278 .id = UCLASS_GPIO, 279 .of_match = tegra186_gpio_ids, 280 .bind = tegra186_gpio_bind, 281 .probe = tegra186_gpio_probe, 282 .ops = &tegra186_gpio_ops, 283}; 284