Changeset 816335c in mainline for uspace/drv/bus/usb/xhci/hc.c


Ignore:
Timestamp:
2017-10-04T10:06:10Z (7 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c68c713c
Parents:
5c5c9407
Message:

xhci: port speed detected properly

The correct way to determine protocol supported on a port is to look at the Port Speed value in the port register, and use it as an index to the speeds defined in extended capabilities. Now we support non-contiguous ranges of ports, USB 3.1, and the detection would work even for non-USB protocols.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/hc.c

    r5c5c9407 r816335c  
    4848 */
    4949#define PSI_TO_BPS(psie, psim) (((uint64_t) psim) << (10 * psie))
    50 #define PORT_SPEED(psie, psim) { \
     50#define PORT_SPEED(mjr, psie, psim) { \
     51        .name = "USB ", \
     52        .major = mjr, \
     53        .minor = 0, \
    5154        .rx_bps = PSI_TO_BPS(psie, psim), \
    5255        .tx_bps = PSI_TO_BPS(psie, psim) \
    5356}
    54 static const xhci_port_speed_t ps_default_full  = PORT_SPEED(2, 12);
    55 static const xhci_port_speed_t ps_default_low   = PORT_SPEED(1, 1500);
    56 static const xhci_port_speed_t ps_default_high  = PORT_SPEED(2, 480);
    57 static const xhci_port_speed_t ps_default_super = PORT_SPEED(3, 5);
     57static const xhci_port_speed_t ps_default_full  = PORT_SPEED(2, 2, 12);
     58static const xhci_port_speed_t ps_default_low   = PORT_SPEED(2, 1, 1500);
     59static const xhci_port_speed_t ps_default_high  = PORT_SPEED(2, 2, 480);
     60static const xhci_port_speed_t ps_default_super = PORT_SPEED(3, 3, 5);
    5861
    5962/**
     
    6265static int hc_parse_ec(xhci_hc_t *hc)
    6366{
    64         unsigned psic, major;
     67        unsigned psic, major, minor;
     68        xhci_sp_name_t name;
     69
     70        xhci_port_speed_t *speeds = hc->rh.speeds;
    6571
    6672        for (xhci_extcap_t *ec = hc->xecp; ec; ec = xhci_extcap_next(ec)) {
     
    7480                        psic = XHCI_REG_RD(ec, XHCI_EC_SP_PSIC);
    7581                        major = XHCI_REG_RD(ec, XHCI_EC_SP_MAJOR);
     82                        minor = XHCI_REG_RD(ec, XHCI_EC_SP_MINOR);
     83                        name.packed = host2uint32_t_le(XHCI_REG_RD(ec, XHCI_EC_SP_NAME));
     84
     85                        if (name.packed != xhci_name_usb.packed) {
     86                                /**
     87                                 * The detection of such protocol would work,
     88                                 * but the rest of the implementation is made
     89                                 * for the USB protocol only.
     90                                 */
     91                                usb_log_error("Unknown protocol %.4s.", name.str);
     92                                return ENOTSUP;
     93                        }
    7694
    7795                        // "Implied" speed
    7896                        if (psic == 0) {
    79                                 /*
    80                                  * According to section 7.2.2.1.2, only USB 2.0
    81                                  * and USB 3.0 can have psic == 0. So we
    82                                  * blindly assume the name == "USB " and minor
    83                                  * == 0.
    84                                  */
    85 
    86                                 unsigned ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF);
    87                                 unsigned ports_to = ports_from
    88                                         + XHCI_REG_RD(ec, XHCI_EC_SP_CP_COUNT) - 1;
     97                                assert(minor == 0);
    8998
    9099                                if (major == 2) {
    91                                         hc->speeds[1] = ps_default_full;
    92                                         hc->speeds[2] = ps_default_low;
    93                                         hc->speeds[3] = ps_default_high;
    94                                         hc->rh.usb2_port_start = ports_from;
    95                                         hc->rh.usb2_port_end = ports_to;
     100                                        speeds[1] = ps_default_full;
     101                                        speeds[2] = ps_default_low;
     102                                        speeds[3] = ps_default_high;
    96103                                } else if (major == 3) {
    97                                         hc->speeds[4] = ps_default_super;
    98                                         hc->rh.usb3_port_start = ports_from;
    99                                         hc->rh.usb3_port_end = ports_to;
     104                                        speeds[4] = ps_default_super;
    100105                                } else {
    101106                                        return EINVAL;
    102107                                }
    103108
    104                                 usb_log_debug2("Implied speed of USB %u set up.", major);
     109                                usb_log_debug2("Implied speed of USB %u.0 set up.", major);
    105110                        } else {
    106111                                for (unsigned i = 0; i < psic; i++) {
     
    111116                                        unsigned psim = XHCI_REG_RD(psi, XHCI_PSI_PSIM);
    112117
     118                                        speeds[psiv].major = major;
     119                                        speeds[psiv].minor = minor;
     120                                        str_ncpy(speeds[psiv].name, 4, name.str, 4);
     121
    113122                                        uint64_t bps = PSI_TO_BPS(psie, psim);
    114123
    115124                                        if (sim == XHCI_PSI_PLT_SYMM || sim == XHCI_PSI_PLT_RX)
    116                                                 hc->speeds[psiv].rx_bps = bps;
     125                                                speeds[psiv].rx_bps = bps;
    117126                                        if (sim == XHCI_PSI_PLT_SYMM || sim == XHCI_PSI_PLT_TX) {
    118                                                 hc->speeds[psiv].tx_bps = bps;
    119                                                 usb_log_debug2("Speed %u set up for bps %" PRIu64 " / %" PRIu64 ".", psiv, hc->speeds[psiv].rx_bps, hc->speeds[psiv].tx_bps);
     127                                                speeds[psiv].tx_bps = bps;
     128                                                usb_log_debug2("Speed %u set up for bps %" PRIu64 " / %" PRIu64 ".", psiv, speeds[psiv].rx_bps, speeds[psiv].tx_bps);
    120129                                        }
    121130                                }
     
    202211                goto err_scratch;
    203212
    204         if ((err = xhci_rh_init(&hc->rh, hc->op_regs)))
     213        if ((err = xhci_rh_init(&hc->rh, hc)))
    205214                goto err_cmd;
    206215
Note: See TracChangeset for help on using the changeset viewer.