source: mainline/uspace/drv/bus/usb/ehci/res.c@ 3f932a7e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3f932a7e was e0a5d4c, checked in by Ondřej Hlavatý <aearsis@…>, 7 years ago

usb: update copyrights

The data was generated by a script, guided manually. If you feel your
name is missing somewhere, please add it!

The semi-automated process was roughly:

1) Changes per file and author (limited to our team) were counted
2) Trivial numbers were thrown away
3) Authors were sorted by lines added to file
4) All previous copyrights were replaced by the newly generated one
5) Hunks changing only year were discarded

It seems that a lot of my copyrights were added. It is due to me being
both sticking my nose everywhere and lazy to update the copyright right
away :)

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * Copyright (c) 2018 Ondrej Hlavaty
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @addtogroup drvusbehci
32 * @{
33 */
34/**
35 * @file
36 * PCI related functions needed by the EHCI driver.
37 */
38
39#include <errno.h>
40#include <str_error.h>
41#include <assert.h>
42#include <ddf/driver.h>
43#include <ddi.h>
44#include <usb/debug.h>
45#include <device/hw_res_parsed.h>
46#include <pci_dev_iface.h>
47
48#include "hc.h"
49#include "res.h"
50#include "ehci_regs.h"
51
52#define USBLEGSUP_OFFSET 0
53#define USBLEGSUP_BIOS_CONTROL (1 << 16)
54#define USBLEGSUP_OS_CONTROL (1 << 24)
55#define USBLEGCTLSTS_OFFSET 4
56
57#define DEFAULT_WAIT 1000
58#define WAIT_STEP 10
59
60/** Implements BIOS hands-off routine as described in EHCI spec
61 *
62 * @param device EHCI device
63 * @param eecp Value of EHCI Extended Capabilities pointer.
64 * @return Error code.
65 */
66static errno_t disable_extended_caps(async_sess_t *parent_sess, unsigned eecp)
67{
68 /* nothing to do */
69 if (eecp == 0)
70 return EOK;
71
72 /* Read the first EEC. i.e. Legacy Support register */
73 uint32_t usblegsup;
74 errno_t ret = pci_config_space_read_32(parent_sess,
75 eecp + USBLEGSUP_OFFSET, &usblegsup);
76 if (ret != EOK) {
77 usb_log_error("Failed to read USBLEGSUP: %s.", str_error(ret));
78 return ret;
79 }
80 usb_log_debug2("USBLEGSUP: %" PRIx32 ".", usblegsup);
81
82 /* Request control from firmware/BIOS by writing 1 to highest
83 * byte. (OS Control semaphore)*/
84 usb_log_debug("Requesting OS control.");
85 ret = pci_config_space_write_8(parent_sess,
86 eecp + USBLEGSUP_OFFSET + 3, 1);
87 if (ret != EOK) {
88 usb_log_error("Failed to request OS EHCI control: %s.",
89 str_error(ret));
90 return ret;
91 }
92
93 size_t wait = 0;
94 /* Wait for BIOS to release control. */
95 ret = pci_config_space_read_32(
96 parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup);
97 while ((ret == EOK) && (wait < DEFAULT_WAIT)
98 && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
99 async_usleep(WAIT_STEP);
100 ret = pci_config_space_read_32(parent_sess,
101 eecp + USBLEGSUP_OFFSET, &usblegsup);
102 wait += WAIT_STEP;
103 }
104
105 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
106 usb_log_info("BIOS released control after %zu usec.", wait);
107 return EOK;
108 }
109
110 /* BIOS failed to hand over control, this should not happen. */
111 usb_log_warning( "BIOS failed to release control after "
112 "%zu usecs, force it.", wait);
113 ret = pci_config_space_write_32(parent_sess,
114 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL);
115 if (ret != EOK) {
116 usb_log_error("Failed to force OS control: %s.",
117 str_error(ret));
118 return ret;
119 }
120
121 /*
122 * Check capability type here, value of 01h identifies the capability
123 * as Legacy Support. This extended capability requires one additional
124 * 32-bit register for control/status information and this register is
125 * located at offset EECP+04h
126 */
127 if ((usblegsup & 0xff) == 1) {
128 /* Read the second EEC Legacy Support and Control register */
129 uint32_t usblegctlsts;
130 ret = pci_config_space_read_32(parent_sess,
131 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
132 if (ret != EOK) {
133 usb_log_error("Failed to get USBLEGCTLSTS: %s.",
134 str_error(ret));
135 return ret;
136 }
137 usb_log_debug2("USBLEGCTLSTS: %" PRIx32 ".", usblegctlsts);
138 /*
139 * Zero SMI enables in legacy control register.
140 * It should prevent pre-OS code from
141 * interfering. NOTE: Three upper bits are WC
142 */
143 ret = pci_config_space_write_32(parent_sess,
144 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000);
145 if (ret != EOK) {
146 usb_log_error("Failed to zero USBLEGCTLSTS: %s",
147 str_error(ret));
148 return ret;
149 }
150
151 udelay(10);
152 /* read again to amke sure it's zeroed */
153 ret = pci_config_space_read_32(parent_sess,
154 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
155 if (ret != EOK) {
156 usb_log_error("Failed to get USBLEGCTLSTS 2: %s.",
157 str_error(ret));
158 return ret;
159 }
160 usb_log_debug2("Zeroed USBLEGCTLSTS: %" PRIx32 ".",
161 usblegctlsts);
162 }
163
164 /* Read again Legacy Support register */
165 ret = pci_config_space_read_32(parent_sess,
166 eecp + USBLEGSUP_OFFSET, &usblegsup);
167 if (ret != EOK) {
168 usb_log_error("Failed to read USBLEGSUP: %s.",
169 str_error(ret));
170 return ret;
171 }
172 usb_log_debug2("USBLEGSUP: %" PRIx32 ".", usblegsup);
173 return ret;
174}
175
176errno_t disable_legacy(hc_device_t *hcd)
177{
178 hc_t *hc = hcd_to_hc(hcd);
179
180 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev);
181 if (parent_sess == NULL)
182 return ENOMEM;
183
184 usb_log_debug("Disabling EHCI legacy support.");
185
186 const uint32_t hcc_params = EHCI_RD(hc->caps->hccparams);
187 usb_log_debug2("Value of hcc params register: %x.", hcc_params);
188
189 /* Read value of EHCI Extended Capabilities Pointer
190 * position of EEC registers (points to PCI config space) */
191 const uint32_t eecp =
192 (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK;
193 usb_log_debug2("Value of EECP: %x.", eecp);
194
195 int ret = disable_extended_caps(parent_sess, eecp);
196 if (ret != EOK) {
197 usb_log_error("Failed to disable extended capabilities: %s.",
198 str_error(ret));
199 goto clean;
200 }
201clean:
202 async_hangup(parent_sess);
203 return ret;
204}
205
206/**
207 * @}
208 */
Note: See TracBrowser for help on using the repository browser.