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