linux/drivers/thunderbolt/lc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Thunderbolt link controller support
   4 *
   5 * Copyright (C) 2019, Intel Corporation
   6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
   7 */
   8
   9#include "tb.h"
  10
  11/**
  12 * tb_lc_read_uuid() - Read switch UUID from link controller common register
  13 * @sw: Switch whose UUID is read
  14 * @uuid: UUID is placed here
  15 */
  16int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid)
  17{
  18        if (!sw->cap_lc)
  19                return -EINVAL;
  20        return tb_sw_read(sw, uuid, TB_CFG_SWITCH, sw->cap_lc + TB_LC_FUSE, 4);
  21}
  22
  23static int read_lc_desc(struct tb_switch *sw, u32 *desc)
  24{
  25        if (!sw->cap_lc)
  26                return -EINVAL;
  27        return tb_sw_read(sw, desc, TB_CFG_SWITCH, sw->cap_lc + TB_LC_DESC, 1);
  28}
  29
  30static int find_port_lc_cap(struct tb_port *port)
  31{
  32        struct tb_switch *sw = port->sw;
  33        int start, phys, ret, size;
  34        u32 desc;
  35
  36        ret = read_lc_desc(sw, &desc);
  37        if (ret)
  38                return ret;
  39
  40        /* Start of port LC registers */
  41        start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT;
  42        size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT;
  43        phys = tb_phy_port_from_link(port->port);
  44
  45        return sw->cap_lc + start + phys * size;
  46}
  47
  48static int tb_lc_configure_lane(struct tb_port *port, bool configure)
  49{
  50        bool upstream = tb_is_upstream_port(port);
  51        struct tb_switch *sw = port->sw;
  52        u32 ctrl, lane;
  53        int cap, ret;
  54
  55        if (sw->generation < 2)
  56                return 0;
  57
  58        cap = find_port_lc_cap(port);
  59        if (cap < 0)
  60                return cap;
  61
  62        ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
  63        if (ret)
  64                return ret;
  65
  66        /* Resolve correct lane */
  67        if (port->port % 2)
  68                lane = TB_LC_SX_CTRL_L1C;
  69        else
  70                lane = TB_LC_SX_CTRL_L2C;
  71
  72        if (configure) {
  73                ctrl |= lane;
  74                if (upstream)
  75                        ctrl |= TB_LC_SX_CTRL_UPSTREAM;
  76        } else {
  77                ctrl &= ~lane;
  78                if (upstream)
  79                        ctrl &= ~TB_LC_SX_CTRL_UPSTREAM;
  80        }
  81
  82        return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1);
  83}
  84
  85/**
  86 * tb_lc_configure_link() - Let LC know about configured link
  87 * @sw: Switch that is being added
  88 *
  89 * Informs LC of both parent switch and @sw that there is established
  90 * link between the two.
  91 */
  92int tb_lc_configure_link(struct tb_switch *sw)
  93{
  94        struct tb_port *up, *down;
  95        int ret;
  96
  97        if (!tb_route(sw) || tb_switch_is_icm(sw))
  98                return 0;
  99
 100        up = tb_upstream_port(sw);
 101        down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
 102
 103        /* Configure parent link toward this switch */
 104        ret = tb_lc_configure_lane(down, true);
 105        if (ret)
 106                return ret;
 107
 108        /* Configure upstream link from this switch to the parent */
 109        ret = tb_lc_configure_lane(up, true);
 110        if (ret)
 111                tb_lc_configure_lane(down, false);
 112
 113        return ret;
 114}
 115
 116/**
 117 * tb_lc_unconfigure_link() - Let LC know about unconfigured link
 118 * @sw: Switch to unconfigure
 119 *
 120 * Informs LC of both parent switch and @sw that the link between the
 121 * two does not exist anymore.
 122 */
 123void tb_lc_unconfigure_link(struct tb_switch *sw)
 124{
 125        struct tb_port *up, *down;
 126
 127        if (sw->is_unplugged || !tb_route(sw) || tb_switch_is_icm(sw))
 128                return;
 129
 130        up = tb_upstream_port(sw);
 131        down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent));
 132
 133        tb_lc_configure_lane(up, false);
 134        tb_lc_configure_lane(down, false);
 135}
 136
 137/**
 138 * tb_lc_set_sleep() - Inform LC that the switch is going to sleep
 139 * @sw: Switch to set sleep
 140 *
 141 * Let the switch link controllers know that the switch is going to
 142 * sleep.
 143 */
 144int tb_lc_set_sleep(struct tb_switch *sw)
 145{
 146        int start, size, nlc, ret, i;
 147        u32 desc;
 148
 149        if (sw->generation < 2)
 150                return 0;
 151
 152        ret = read_lc_desc(sw, &desc);
 153        if (ret)
 154                return ret;
 155
 156        /* Figure out number of link controllers */
 157        nlc = desc & TB_LC_DESC_NLC_MASK;
 158        start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT;
 159        size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT;
 160
 161        /* For each link controller set sleep bit */
 162        for (i = 0; i < nlc; i++) {
 163                unsigned int offset = sw->cap_lc + start + i * size;
 164                u32 ctrl;
 165
 166                ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH,
 167                                 offset + TB_LC_SX_CTRL, 1);
 168                if (ret)
 169                        return ret;
 170
 171                ctrl |= TB_LC_SX_CTRL_SLP;
 172                ret = tb_sw_write(sw, &ctrl, TB_CFG_SWITCH,
 173                                  offset + TB_LC_SX_CTRL, 1);
 174                if (ret)
 175                        return ret;
 176        }
 177
 178        return 0;
 179}
 180
 181/**
 182 * tb_lc_lane_bonding_possible() - Is lane bonding possible towards switch
 183 * @sw: Switch to check
 184 *
 185 * Checks whether conditions for lane bonding from parent to @sw are
 186 * possible.
 187 */
 188bool tb_lc_lane_bonding_possible(struct tb_switch *sw)
 189{
 190        struct tb_port *up;
 191        int cap, ret;
 192        u32 val;
 193
 194        if (sw->generation < 2)
 195                return false;
 196
 197        up = tb_upstream_port(sw);
 198        cap = find_port_lc_cap(up);
 199        if (cap < 0)
 200                return false;
 201
 202        ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_PORT_ATTR, 1);
 203        if (ret)
 204                return false;
 205
 206        return !!(val & TB_LC_PORT_ATTR_BE);
 207}
 208
 209static int tb_lc_dp_sink_from_port(const struct tb_switch *sw,
 210                                   struct tb_port *in)
 211{
 212        struct tb_port *port;
 213
 214        /* The first DP IN port is sink 0 and second is sink 1 */
 215        tb_switch_for_each_port(sw, port) {
 216                if (tb_port_is_dpin(port))
 217                        return in != port;
 218        }
 219
 220        return -EINVAL;
 221}
 222
 223static int tb_lc_dp_sink_available(struct tb_switch *sw, int sink)
 224{
 225        u32 val, alloc;
 226        int ret;
 227
 228        ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
 229                         sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
 230        if (ret)
 231                return ret;
 232
 233        /*
 234         * Sink is available for CM/SW to use if the allocation valie is
 235         * either 0 or 1.
 236         */
 237        if (!sink) {
 238                alloc = val & TB_LC_SNK_ALLOCATION_SNK0_MASK;
 239                if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK0_CM)
 240                        return 0;
 241        } else {
 242                alloc = (val & TB_LC_SNK_ALLOCATION_SNK1_MASK) >>
 243                        TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
 244                if (!alloc || alloc == TB_LC_SNK_ALLOCATION_SNK1_CM)
 245                        return 0;
 246        }
 247
 248        return -EBUSY;
 249}
 250
 251/**
 252 * tb_lc_dp_sink_query() - Is DP sink available for DP IN port
 253 * @sw: Switch whose DP sink is queried
 254 * @in: DP IN port to check
 255 *
 256 * Queries through LC SNK_ALLOCATION registers whether DP sink is available
 257 * for the given DP IN port or not.
 258 */
 259bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in)
 260{
 261        int sink;
 262
 263        /*
 264         * For older generations sink is always available as there is no
 265         * allocation mechanism.
 266         */
 267        if (sw->generation < 3)
 268                return true;
 269
 270        sink = tb_lc_dp_sink_from_port(sw, in);
 271        if (sink < 0)
 272                return false;
 273
 274        return !tb_lc_dp_sink_available(sw, sink);
 275}
 276
 277/**
 278 * tb_lc_dp_sink_alloc() - Allocate DP sink
 279 * @sw: Switch whose DP sink is allocated
 280 * @in: DP IN port the DP sink is allocated for
 281 *
 282 * Allocate DP sink for @in via LC SNK_ALLOCATION registers. If the
 283 * resource is available and allocation is successful returns %0. In all
 284 * other cases returs negative errno. In particular %-EBUSY is returned if
 285 * the resource was not available.
 286 */
 287int tb_lc_dp_sink_alloc(struct tb_switch *sw, struct tb_port *in)
 288{
 289        int ret, sink;
 290        u32 val;
 291
 292        if (sw->generation < 3)
 293                return 0;
 294
 295        sink = tb_lc_dp_sink_from_port(sw, in);
 296        if (sink < 0)
 297                return sink;
 298
 299        ret = tb_lc_dp_sink_available(sw, sink);
 300        if (ret)
 301                return ret;
 302
 303        ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
 304                         sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
 305        if (ret)
 306                return ret;
 307
 308        if (!sink) {
 309                val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
 310                val |= TB_LC_SNK_ALLOCATION_SNK0_CM;
 311        } else {
 312                val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
 313                val |= TB_LC_SNK_ALLOCATION_SNK1_CM <<
 314                        TB_LC_SNK_ALLOCATION_SNK1_SHIFT;
 315        }
 316
 317        ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
 318                          sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
 319
 320        if (ret)
 321                return ret;
 322
 323        tb_port_dbg(in, "sink %d allocated\n", sink);
 324        return 0;
 325}
 326
 327/**
 328 * tb_lc_dp_sink_dealloc() - De-allocate DP sink
 329 * @sw: Switch whose DP sink is de-allocated
 330 * @in: DP IN port whose DP sink is de-allocated
 331 *
 332 * De-allocate DP sink from @in using LC SNK_ALLOCATION registers.
 333 */
 334int tb_lc_dp_sink_dealloc(struct tb_switch *sw, struct tb_port *in)
 335{
 336        int ret, sink;
 337        u32 val;
 338
 339        if (sw->generation < 3)
 340                return 0;
 341
 342        sink = tb_lc_dp_sink_from_port(sw, in);
 343        if (sink < 0)
 344                return sink;
 345
 346        /* Needs to be owned by CM/SW */
 347        ret = tb_lc_dp_sink_available(sw, sink);
 348        if (ret)
 349                return ret;
 350
 351        ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
 352                         sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
 353        if (ret)
 354                return ret;
 355
 356        if (!sink)
 357                val &= ~TB_LC_SNK_ALLOCATION_SNK0_MASK;
 358        else
 359                val &= ~TB_LC_SNK_ALLOCATION_SNK1_MASK;
 360
 361        ret = tb_sw_write(sw, &val, TB_CFG_SWITCH,
 362                          sw->cap_lc + TB_LC_SNK_ALLOCATION, 1);
 363        if (ret)
 364                return ret;
 365
 366        tb_port_dbg(in, "sink %d de-allocated\n", sink);
 367        return 0;
 368}
 369