1 /* 2 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #define pr_fmt(fmt) "tegra-xusb-padctl: " fmt 8 9 #include <common.h> 10 #include <errno.h> 11 12 #include "xusb-padctl-common.h" 13 14 #include <asm/arch/clock.h> 15 16 int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy) 17 { 18 if (phy && phy->ops && phy->ops->prepare) 19 return phy->ops->prepare(phy); 20 21 return phy ? -ENOSYS : -EINVAL; 22 } 23 24 int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy) 25 { 26 if (phy && phy->ops && phy->ops->enable) 27 return phy->ops->enable(phy); 28 29 return phy ? -ENOSYS : -EINVAL; 30 } 31 32 int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy) 33 { 34 if (phy && phy->ops && phy->ops->disable) 35 return phy->ops->disable(phy); 36 37 return phy ? -ENOSYS : -EINVAL; 38 } 39 40 int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy) 41 { 42 if (phy && phy->ops && phy->ops->unprepare) 43 return phy->ops->unprepare(phy); 44 45 return phy ? -ENOSYS : -EINVAL; 46 } 47 48 struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type) 49 { 50 struct tegra_xusb_phy *phy; 51 int i; 52 53 for (i = 0; i < padctl.socdata->num_phys; i++) { 54 phy = &padctl.socdata->phys[i]; 55 if (phy->type != type) 56 continue; 57 return phy; 58 } 59 60 return NULL; 61 } 62 63 static const struct tegra_xusb_padctl_lane * 64 tegra_xusb_padctl_find_lane(struct tegra_xusb_padctl *padctl, const char *name) 65 { 66 unsigned int i; 67 68 for (i = 0; i < padctl->socdata->num_lanes; i++) 69 if (strcmp(name, padctl->socdata->lanes[i].name) == 0) 70 return &padctl->socdata->lanes[i]; 71 72 return NULL; 73 } 74 75 static int 76 tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl, 77 struct tegra_xusb_padctl_group *group, 78 const void *fdt, int node) 79 { 80 unsigned int i; 81 int len; 82 83 group->name = fdt_get_name(fdt, node, &len); 84 85 len = fdt_stringlist_count(fdt, node, "nvidia,lanes"); 86 if (len < 0) { 87 error("failed to parse \"nvidia,lanes\" property"); 88 return -EINVAL; 89 } 90 91 group->num_pins = len; 92 93 for (i = 0; i < group->num_pins; i++) { 94 group->pins[i] = fdt_stringlist_get(fdt, node, "nvidia,lanes", 95 i, NULL); 96 if (!group->pins[i]) { 97 error("failed to read string from \"nvidia,lanes\" property"); 98 return -EINVAL; 99 } 100 } 101 102 group->num_pins = len; 103 104 group->func = fdt_stringlist_get(fdt, node, "nvidia,function", 0, NULL); 105 if (!group->func) { 106 error("failed to parse \"nvidia,func\" property"); 107 return -EINVAL; 108 } 109 110 group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1); 111 112 return 0; 113 } 114 115 static int tegra_xusb_padctl_find_function(struct tegra_xusb_padctl *padctl, 116 const char *name) 117 { 118 unsigned int i; 119 120 for (i = 0; i < padctl->socdata->num_functions; i++) 121 if (strcmp(name, padctl->socdata->functions[i]) == 0) 122 return i; 123 124 return -ENOENT; 125 } 126 127 static int 128 tegra_xusb_padctl_lane_find_function(struct tegra_xusb_padctl *padctl, 129 const struct tegra_xusb_padctl_lane *lane, 130 const char *name) 131 { 132 unsigned int i; 133 int func; 134 135 func = tegra_xusb_padctl_find_function(padctl, name); 136 if (func < 0) 137 return func; 138 139 for (i = 0; i < lane->num_funcs; i++) 140 if (lane->funcs[i] == func) 141 return i; 142 143 return -ENOENT; 144 } 145 146 static int 147 tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl, 148 const struct tegra_xusb_padctl_group *group) 149 { 150 unsigned int i; 151 152 for (i = 0; i < group->num_pins; i++) { 153 const struct tegra_xusb_padctl_lane *lane; 154 unsigned int func; 155 u32 value; 156 157 lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]); 158 if (!lane) { 159 error("no lane for pin %s", group->pins[i]); 160 continue; 161 } 162 163 func = tegra_xusb_padctl_lane_find_function(padctl, lane, 164 group->func); 165 if (func < 0) { 166 error("function %s invalid for lane %s: %d", 167 group->func, lane->name, func); 168 continue; 169 } 170 171 value = padctl_readl(padctl, lane->offset); 172 173 /* set pin function */ 174 value &= ~(lane->mask << lane->shift); 175 value |= func << lane->shift; 176 177 /* 178 * Set IDDQ if supported on the lane and specified in the 179 * configuration. 180 */ 181 if (lane->iddq > 0 && group->iddq >= 0) { 182 if (group->iddq != 0) 183 value &= ~(1 << lane->iddq); 184 else 185 value |= 1 << lane->iddq; 186 } 187 188 padctl_writel(padctl, value, lane->offset); 189 } 190 191 return 0; 192 } 193 194 static int 195 tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl, 196 struct tegra_xusb_padctl_config *config) 197 { 198 unsigned int i; 199 200 for (i = 0; i < config->num_groups; i++) { 201 const struct tegra_xusb_padctl_group *group; 202 int err; 203 204 group = &config->groups[i]; 205 206 err = tegra_xusb_padctl_group_apply(padctl, group); 207 if (err < 0) { 208 error("failed to apply group %s: %d", 209 group->name, err); 210 continue; 211 } 212 } 213 214 return 0; 215 } 216 217 static int 218 tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl, 219 struct tegra_xusb_padctl_config *config, 220 const void *fdt, int node) 221 { 222 int subnode; 223 224 config->name = fdt_get_name(fdt, node, NULL); 225 226 fdt_for_each_subnode(subnode, fdt, node) { 227 struct tegra_xusb_padctl_group *group; 228 int err; 229 230 group = &config->groups[config->num_groups]; 231 232 err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt, 233 subnode); 234 if (err < 0) { 235 error("failed to parse group %s", group->name); 236 return err; 237 } 238 239 config->num_groups++; 240 } 241 242 return 0; 243 } 244 245 static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl, 246 const void *fdt, int node) 247 { 248 int subnode, err; 249 250 err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs); 251 if (err < 0) { 252 error("registers not found"); 253 return err; 254 } 255 256 fdt_for_each_subnode(subnode, fdt, node) { 257 struct tegra_xusb_padctl_config *config = &padctl->config; 258 259 err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt, 260 subnode); 261 if (err < 0) { 262 error("failed to parse entry %s: %d", 263 config->name, err); 264 continue; 265 } 266 } 267 268 return 0; 269 } 270 271 struct tegra_xusb_padctl padctl; 272 273 int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count, 274 const struct tegra_xusb_padctl_soc *socdata) 275 { 276 unsigned int i; 277 int err; 278 279 for (i = 0; i < count; i++) { 280 if (!fdtdec_get_is_enabled(fdt, nodes[i])) 281 continue; 282 283 padctl.socdata = socdata; 284 285 err = tegra_xusb_padctl_parse_dt(&padctl, fdt, nodes[i]); 286 if (err < 0) { 287 error("failed to parse DT: %d", err); 288 continue; 289 } 290 291 /* deassert XUSB padctl reset */ 292 reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0); 293 294 err = tegra_xusb_padctl_config_apply(&padctl, &padctl.config); 295 if (err < 0) { 296 error("failed to apply pinmux: %d", err); 297 continue; 298 } 299 300 /* only a single instance is supported */ 301 break; 302 } 303 304 return 0; 305 } 306