uboot/arch/arm/mach-tegra/xusb-padctl-common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
   4 */
   5
   6#define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
   7
   8#include <common.h>
   9#include <errno.h>
  10#include <log.h>
  11
  12#include "xusb-padctl-common.h"
  13
  14#include <asm/arch/clock.h>
  15
  16int 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
  24int 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
  32int 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
  40int 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
  48struct 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
  63static const struct tegra_xusb_padctl_lane *
  64tegra_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
  75static int
  76tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
  77                                 struct tegra_xusb_padctl_group *group,
  78                                 ofnode node)
  79{
  80        unsigned int i;
  81        int len, ret;
  82
  83        group->name = ofnode_get_name(node);
  84
  85        len = ofnode_read_string_count(node, "nvidia,lanes");
  86        if (len < 0) {
  87                pr_err("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                ret = ofnode_read_string_index(node, "nvidia,lanes", i,
  95                                               &group->pins[i]);
  96                if (ret) {
  97                        pr_err("failed to read string from \"nvidia,lanes\" property");
  98                        return -EINVAL;
  99                }
 100        }
 101
 102        group->num_pins = len;
 103
 104        ret = ofnode_read_string_index(node, "nvidia,function", 0,
 105                                       &group->func);
 106        if (ret) {
 107                pr_err("failed to parse \"nvidia,func\" property");
 108                return -EINVAL;
 109        }
 110
 111        group->iddq = ofnode_read_u32_default(node, "nvidia,iddq", -1);
 112
 113        return 0;
 114}
 115
 116static int tegra_xusb_padctl_find_function(struct tegra_xusb_padctl *padctl,
 117                                           const char *name)
 118{
 119        unsigned int i;
 120
 121        for (i = 0; i < padctl->socdata->num_functions; i++)
 122                if (strcmp(name, padctl->socdata->functions[i]) == 0)
 123                        return i;
 124
 125        return -ENOENT;
 126}
 127
 128static int
 129tegra_xusb_padctl_lane_find_function(struct tegra_xusb_padctl *padctl,
 130                                     const struct tegra_xusb_padctl_lane *lane,
 131                                     const char *name)
 132{
 133        unsigned int i;
 134        int func;
 135
 136        func = tegra_xusb_padctl_find_function(padctl, name);
 137        if (func < 0)
 138                return func;
 139
 140        for (i = 0; i < lane->num_funcs; i++)
 141                if (lane->funcs[i] == func)
 142                        return i;
 143
 144        return -ENOENT;
 145}
 146
 147static int
 148tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl,
 149                              const struct tegra_xusb_padctl_group *group)
 150{
 151        unsigned int i;
 152
 153        for (i = 0; i < group->num_pins; i++) {
 154                const struct tegra_xusb_padctl_lane *lane;
 155                unsigned int func;
 156                u32 value;
 157
 158                lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]);
 159                if (!lane) {
 160                        pr_err("no lane for pin %s", group->pins[i]);
 161                        continue;
 162                }
 163
 164                func = tegra_xusb_padctl_lane_find_function(padctl, lane,
 165                                                            group->func);
 166                if (func < 0) {
 167                        pr_err("function %s invalid for lane %s: %d",
 168                              group->func, lane->name, func);
 169                        continue;
 170                }
 171
 172                value = padctl_readl(padctl, lane->offset);
 173
 174                /* set pin function */
 175                value &= ~(lane->mask << lane->shift);
 176                value |= func << lane->shift;
 177
 178                /*
 179                 * Set IDDQ if supported on the lane and specified in the
 180                 * configuration.
 181                 */
 182                if (lane->iddq > 0 && group->iddq >= 0) {
 183                        if (group->iddq != 0)
 184                                value &= ~(1 << lane->iddq);
 185                        else
 186                                value |= 1 << lane->iddq;
 187                }
 188
 189                padctl_writel(padctl, value, lane->offset);
 190        }
 191
 192        return 0;
 193}
 194
 195static int
 196tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl,
 197                               struct tegra_xusb_padctl_config *config)
 198{
 199        unsigned int i;
 200
 201        for (i = 0; i < config->num_groups; i++) {
 202                const struct tegra_xusb_padctl_group *group;
 203                int err;
 204
 205                group = &config->groups[i];
 206
 207                err = tegra_xusb_padctl_group_apply(padctl, group);
 208                if (err < 0) {
 209                        pr_err("failed to apply group %s: %d",
 210                              group->name, err);
 211                        continue;
 212                }
 213        }
 214
 215        return 0;
 216}
 217
 218static int
 219tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
 220                                  struct tegra_xusb_padctl_config *config,
 221                                  ofnode node)
 222{
 223        ofnode subnode;
 224
 225        config->name = ofnode_get_name(node);
 226
 227        ofnode_for_each_subnode(subnode, node) {
 228                struct tegra_xusb_padctl_group *group;
 229                int err;
 230
 231                group = &config->groups[config->num_groups];
 232
 233                err = tegra_xusb_padctl_group_parse_dt(padctl, group, subnode);
 234                if (err < 0) {
 235                        pr_err("failed to parse group %s", group->name);
 236                        return err;
 237                }
 238
 239                config->num_groups++;
 240        }
 241
 242        return 0;
 243}
 244
 245static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
 246                                      ofnode node)
 247{
 248        ofnode subnode;
 249        int err;
 250
 251        err = ofnode_read_resource(node, 0, &padctl->regs);
 252        if (err < 0) {
 253                pr_err("registers not found");
 254                return err;
 255        }
 256
 257        ofnode_for_each_subnode(subnode, node) {
 258                struct tegra_xusb_padctl_config *config = &padctl->config;
 259
 260                debug("%s: subnode=%s\n", __func__, ofnode_get_name(subnode));
 261                err = tegra_xusb_padctl_config_parse_dt(padctl, config,
 262                                                        subnode);
 263                if (err < 0) {
 264                        pr_err("failed to parse entry %s: %d",
 265                              config->name, err);
 266                        continue;
 267                }
 268        }
 269        debug("%s: done\n", __func__);
 270
 271        return 0;
 272}
 273
 274struct tegra_xusb_padctl padctl;
 275
 276int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count,
 277                             const struct tegra_xusb_padctl_soc *socdata)
 278{
 279        unsigned int i;
 280        int err;
 281
 282        debug("%s: count=%d\n", __func__, count);
 283        for (i = 0; i < count; i++) {
 284                debug("%s: i=%d, node=%p\n", __func__, i, nodes[i].np);
 285                if (!ofnode_is_available(nodes[i]))
 286                        continue;
 287
 288                padctl.socdata = socdata;
 289
 290                err = tegra_xusb_padctl_parse_dt(&padctl, nodes[i]);
 291                if (err < 0) {
 292                        pr_err("failed to parse DT: %d", err);
 293                        continue;
 294                }
 295
 296                /* deassert XUSB padctl reset */
 297                reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
 298
 299                err = tegra_xusb_padctl_config_apply(&padctl, &padctl.config);
 300                if (err < 0) {
 301                        pr_err("failed to apply pinmux: %d", err);
 302                        continue;
 303                }
 304
 305                /* only a single instance is supported */
 306                break;
 307        }
 308        debug("%s: done\n", __func__);
 309
 310        return 0;
 311}
 312