Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/res.c

    r99e8fb7b rfddffb2  
    4646
    4747#include "res.h"
    48 
    49 #define HCC_PARAMS_OFFSET 0x8
    50 #define HCC_PARAMS_EECP_MASK 0xff
    51 #define HCC_PARAMS_EECP_OFFSET 8
    52 
    53 #define CMD_OFFSET 0x0
    54 #define STS_OFFSET 0x4
    55 #define INT_OFFSET 0x8
    56 #define CFG_OFFSET 0x40
    57 
    58 #define USBCMD_RUN 1
    59 #define USBSTS_HALTED (1 << 12)
     48#include "ehci_regs.h"
    6049
    6150#define USBLEGSUP_OFFSET 0
     
    6655#define DEFAULT_WAIT 1000
    6756#define WAIT_STEP 10
    68 
    69 
    70 /** Get address of registers and IRQ for given device.
    71  *
    72  * @param[in] dev Device asking for the addresses.
    73  * @param[out] mem_regs_p Pointer to the register range.
    74  * @param[out] irq_no IRQ assigned to the device.
    75  * @return Error code.
    76  */
    77 int get_my_registers(ddf_dev_t *dev,
    78     addr_range_t *mem_regs_p, int *irq_no)
    79 {
    80         assert(dev);
    81        
    82         async_sess_t *parent_sess = devman_parent_device_connect(
    83             EXCHANGE_SERIALIZE, ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
    84         if (!parent_sess)
    85                 return ENOMEM;
    86        
    87         hw_res_list_parsed_t hw_res;
    88         hw_res_list_parsed_init(&hw_res);
    89         const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
    90         async_hangup(parent_sess);
    91         if (ret != EOK) {
    92                 return ret;
    93         }
    94 
    95         if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {
    96                 hw_res_list_parsed_clean(&hw_res);
    97                 return ENOENT;
    98         }
    99 
    100         if (mem_regs_p)
    101                 *mem_regs_p = hw_res.mem_ranges.ranges[0];
    102         if (irq_no)
    103                 *irq_no = hw_res.irqs.irqs[0];
    104 
    105         hw_res_list_parsed_clean(&hw_res);
    106         return EOK;
    107 }
    108 
    109 /** Calls the PCI driver with a request to enable interrupts
    110  *
    111  * @param[in] device Device asking for interrupts
    112  * @return Error code.
    113  */
    114 int enable_interrupts(ddf_dev_t *device)
    115 {
    116         async_sess_t *parent_sess = devman_parent_device_connect(
    117             EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
    118         if (!parent_sess)
    119                 return ENOMEM;
    120        
    121         const bool enabled = hw_res_enable_interrupt(parent_sess);
    122         async_hangup(parent_sess);
    123        
    124         return enabled ? EOK : EIO;
    125 }
    12657
    12758/** Implements BIOS hands-off routine as described in EHCI spec
     
    14273                return ENOMEM;
    14374
     75#define CHECK_RET_HANGUP_RETURN(ret, message...) \
     76        if (ret != EOK) { \
     77                usb_log_error(message); \
     78                async_hangup(parent_sess); \
     79                return ret; \
     80        } else (void)0
     81
    14482        /* Read the first EEC. i.e. Legacy Support register */
    14583        uint32_t usblegsup;
    146         int rc = pci_config_space_read_32(parent_sess,
     84        int ret = pci_config_space_read_32(parent_sess,
    14785            eecp + USBLEGSUP_OFFSET, &usblegsup);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed to read USBLEGSUP: %s.\n",
    150                     str_error(rc));
    151                 goto error;
    152         }
    153 
     86        CHECK_RET_HANGUP_RETURN(ret,
     87            "Failed to read USBLEGSUP: %s.\n", str_error(ret));
    15488        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    15589
     
    15791         * byte. (OS Control semaphore)*/
    15892        usb_log_debug("Requesting OS control.\n");
    159         rc = pci_config_space_write_8(parent_sess,
     93        ret = pci_config_space_write_8(parent_sess,
    16094            eecp + USBLEGSUP_OFFSET + 3, 1);
    161         if (rc != EOK) {
    162                 usb_log_error("Failed to request OS EHCI control: %s.\n",
    163                     str_error(rc));
    164                 goto error;
    165         }
     95        CHECK_RET_HANGUP_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
     96            str_error(ret));
    16697
    16798        size_t wait = 0;
    16899        /* Wait for BIOS to release control. */
    169         rc = pci_config_space_read_32(
     100        ret = pci_config_space_read_32(
    170101            parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup);
    171         if (rc != EOK) {
    172                 usb_log_error("Failed reading PCI config space: %s.\n",
    173                     str_error(rc));
    174                 goto error;
    175         }
    176 
    177         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     102        while ((ret == EOK) && (wait < DEFAULT_WAIT)
     103            && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
    178104                async_usleep(WAIT_STEP);
    179                 rc = pci_config_space_read_32(parent_sess,
     105                ret = pci_config_space_read_32(parent_sess,
    180106                    eecp + USBLEGSUP_OFFSET, &usblegsup);
    181                 if (rc != EOK) {
    182                         usb_log_error("Failed reading PCI config space: %s.\n",
    183                             str_error(rc));
    184                         goto error;
    185                 }
    186107                wait += WAIT_STEP;
    187108        }
     
    196117        usb_log_warning( "BIOS failed to release control after "
    197118            "%zu usecs, force it.\n", wait);
    198         rc = pci_config_space_write_32(parent_sess,
     119        ret = pci_config_space_write_32(parent_sess,
    199120            eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
    200         if (rc != EOK) {
    201                 usb_log_error("Failed to force OS control: "
    202                     "%s.\n", str_error(rc));
    203                 goto error;
    204         }
    205 
     121        CHECK_RET_HANGUP_RETURN(ret, "Failed to force OS control: "
     122            "%s.\n", str_error(ret));
    206123        /*
    207124         * Check capability type here, value of 01h identifies the capability
     
    213130                /* Read the second EEC Legacy Support and Control register */
    214131                uint32_t usblegctlsts;
    215                 rc = pci_config_space_read_32(parent_sess,
     132                ret = pci_config_space_read_32(parent_sess,
    216133                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    217                 if (rc != EOK) {
    218                         usb_log_error("Failed to get USBLEGCTLSTS: %s.\n",
    219                             str_error(rc));
    220                         goto error;
    221                 }
    222 
     134                CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS: %s.\n",
     135                    str_error(ret));
    223136                usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts);
    224137                /*
     
    227140                 * interfering. NOTE: Three upper bits are WC
    228141                 */
    229                 rc = pci_config_space_write_32(parent_sess,
     142                ret = pci_config_space_write_32(parent_sess,
    230143                    eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
    231                 if (rc != EOK) {
    232                         usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc);
    233                         goto error;
    234                 }
    235 
     144                CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    236145                udelay(10);
    237                 rc = pci_config_space_read_32(parent_sess,
     146                ret = pci_config_space_read_32(parent_sess,
    238147                    eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    239                 if (rc != EOK) {
    240                         usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n",
    241                             str_error(rc));
    242                         goto error;
    243                 }
    244 
     148                CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS 2: %s.\n",
     149                    str_error(ret));
    245150                usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
    246151                    usblegctlsts);
     
    248153
    249154        /* Read again Legacy Support register */
    250         rc = pci_config_space_read_32(parent_sess,
     155        ret = pci_config_space_read_32(parent_sess,
    251156            eecp + USBLEGSUP_OFFSET, &usblegsup);
    252         if (rc != EOK) {
    253                 usb_log_error("Failed to read USBLEGSUP: %s.\n",
    254                     str_error(rc));
    255                 goto error;
    256         }
    257 
     157        CHECK_RET_HANGUP_RETURN(ret, "Failed to read USBLEGSUP: %s.\n",
     158            str_error(ret));
    258159        usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
    259160        async_hangup(parent_sess);
    260161        return EOK;
    261 error:
    262         async_hangup(parent_sess);
    263         return rc;
     162#undef CHECK_RET_HANGUP_RETURN
    264163}
    265164
     
    271170        /* Map EHCI registers */
    272171        void *regs = NULL;
    273         int rc = pio_enable_range(reg_range, &regs);
    274         if (rc != EOK) {
     172        int ret = pio_enable_range(reg_range, &regs);
     173        if (ret != EOK) {
    275174                usb_log_error("Failed to map registers %p: %s.\n",
    276                     RNGABSPTR(*reg_range), str_error(rc));
    277                 return rc;
     175                    RNGABSPTR(*reg_range), str_error(ret));
     176                return ret;
    278177        }
    279178
    280179        usb_log_debug2("Registers mapped at: %p.\n", regs);
    281180
    282         const uint32_t hcc_params =
    283             *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
     181        ehci_caps_regs_t *ehci_caps = regs;
     182
     183        const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams);
    284184        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    285185
     
    287187         * position of EEC registers (points to PCI config space) */
    288188        const uint32_t eecp =
    289             (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
     189            (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK;
    290190        usb_log_debug("Value of EECP: %x.\n", eecp);
    291191
    292         rc = disable_extended_caps(device, eecp);
    293         if (rc != EOK) {
     192        ret = disable_extended_caps(device, eecp);
     193        if (ret != EOK) {
    294194                usb_log_error("Failed to disable extended capabilities: %s.\n",
    295                     str_error(rc));
    296                 return rc;
    297         }
     195                    str_error(ret));
     196                return ret;
     197        }
     198
    298199
    299200        /*
     
    302203
    303204        /* Get size of capability registers in memory space. */
    304         const unsigned operation_offset = *(uint8_t*)regs;
     205        const unsigned operation_offset = EHCI_RD8(ehci_caps->caplength);
    305206        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    306207
    307         /* Zero USBCMD register. */
    308         volatile uint32_t *usbcmd =
    309             (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
    310         volatile uint32_t *usbsts =
    311             (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
    312         volatile uint32_t *usbconf =
    313             (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
    314         volatile uint32_t *usbint =
    315             (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
    316         usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    317         if (*usbcmd & USBCMD_RUN) {
    318                 *usbsts = 0x3f; /* ack all interrupts */
    319                 *usbint = 0; /* disable all interrupts */
    320                 *usbconf = 0; /* release control of RH ports */
    321 
    322                 *usbcmd = 0;
     208        ehci_regs_t *ehci_regs = regs + operation_offset;
     209
     210        usb_log_debug("USBCMD value: %x.\n", EHCI_RD(ehci_regs->usbcmd));
     211        if (EHCI_RD(ehci_regs->usbcmd) & USB_CMD_RUN_FLAG) {
     212                EHCI_WR(ehci_regs->usbintr, 0); /* disable all interrupts */
     213                EHCI_WR(ehci_regs->usbsts, 0x3f); /* ack all interrupts */
     214                EHCI_WR(ehci_regs->configflag, 0); /* release RH ports */
     215                EHCI_WR(ehci_regs->usbcmd, 0);
    323216                /* Wait until hc is halted */
    324                 while ((*usbsts & USBSTS_HALTED) == 0);
     217                while ((EHCI_RD(ehci_regs->usbsts) & USB_STS_HC_HALTED_FLAG) == 0);
    325218                usb_log_info("EHCI turned off.\n");
    326219        } else {
     
    332225            "\t USBINT(%p): %x(0x0 = no interrupts).\n"
    333226            "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n",
    334             usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf);
    335 
    336         return rc;
     227            &ehci_regs->usbcmd, EHCI_RD(ehci_regs->usbcmd),
     228            &ehci_regs->usbsts, EHCI_RD(ehci_regs->usbsts),
     229            &ehci_regs->usbintr, EHCI_RD(ehci_regs->usbintr),
     230            &ehci_regs->configflag, EHCI_RD(ehci_regs->configflag));
     231
     232        return ret;
    337233}
    338234
Note: See TracChangeset for help on using the changeset viewer.