Changes in uspace/drv/bus/usb/ehci/res.c [99e8fb7b:615abda] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/res.c
r99e8fb7b r615abda 46 46 47 47 #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" 60 49 61 50 #define USBLEGSUP_OFFSET 0 … … 67 56 #define WAIT_STEP 10 68 57 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 interrupts110 *111 * @param[in] device Device asking for interrupts112 * @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 }126 127 58 /** Implements BIOS hands-off routine as described in EHCI spec 128 59 * … … 131 62 * @return Error code. 132 63 */ 133 static int disable_extended_caps( ddf_dev_t *device, unsigned eecp)64 static int disable_extended_caps(async_sess_t *parent_sess, unsigned eecp) 134 65 { 135 66 /* nothing to do */ … … 137 68 return EOK; 138 69 139 async_sess_t *parent_sess = devman_parent_device_connect(140 EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);141 if (!parent_sess)142 return ENOMEM;143 144 70 /* Read the first EEC. i.e. Legacy Support register */ 145 71 uint32_t usblegsup; 146 int r c= pci_config_space_read_32(parent_sess,72 int ret = pci_config_space_read_32(parent_sess, 147 73 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 74 if (ret != EOK) { 75 usb_log_error("Failed to read USBLEGSUP: %s.\n", str_error(ret)); 76 return ret; 77 } 154 78 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 155 79 … … 157 81 * byte. (OS Control semaphore)*/ 158 82 usb_log_debug("Requesting OS control.\n"); 159 r c= pci_config_space_write_8(parent_sess,83 ret = pci_config_space_write_8(parent_sess, 160 84 eecp + USBLEGSUP_OFFSET + 3, 1); 161 if (r c!= EOK) {85 if (ret != EOK) { 162 86 usb_log_error("Failed to request OS EHCI control: %s.\n", 163 str_error(r c));164 goto error;87 str_error(ret)); 88 return ret; 165 89 } 166 90 167 91 size_t wait = 0; 168 92 /* Wait for BIOS to release control. */ 169 r c= pci_config_space_read_32(93 ret = pci_config_space_read_32( 170 94 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)) { 95 while ((ret == EOK) && (wait < DEFAULT_WAIT) 96 && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 178 97 async_usleep(WAIT_STEP); 179 r c= pci_config_space_read_32(parent_sess,98 ret = pci_config_space_read_32(parent_sess, 180 99 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 }186 100 wait += WAIT_STEP; 187 101 } … … 189 103 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) { 190 104 usb_log_info("BIOS released control after %zu usec.\n", wait); 191 async_hangup(parent_sess);192 105 return EOK; 193 106 } … … 196 109 usb_log_warning( "BIOS failed to release control after " 197 110 "%zu usecs, force it.\n", wait); 198 r c= pci_config_space_write_32(parent_sess,111 ret = pci_config_space_write_32(parent_sess, 199 112 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL); 200 if (r c!= EOK) {201 usb_log_error("Failed to force OS control: "202 "%s.\n", str_error(rc));203 goto error;113 if (ret != EOK) { 114 usb_log_error("Failed to force OS control: %s.\n", 115 str_error(ret)); 116 return ret; 204 117 } 205 118 … … 213 126 /* Read the second EEC Legacy Support and Control register */ 214 127 uint32_t usblegctlsts; 215 r c= pci_config_space_read_32(parent_sess,128 ret = pci_config_space_read_32(parent_sess, 216 129 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 217 if (r c!= EOK) {130 if (ret != EOK) { 218 131 usb_log_error("Failed to get USBLEGCTLSTS: %s.\n", 219 str_error(r c));220 goto error;132 str_error(ret)); 133 return ret; 221 134 } 222 223 135 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts); 224 136 /* … … 227 139 * interfering. NOTE: Three upper bits are WC 228 140 */ 229 r c= pci_config_space_write_32(parent_sess,141 ret = pci_config_space_write_32(parent_sess, 230 142 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000); 231 if (rc != EOK) { 232 usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc); 233 goto error; 143 if (ret != EOK) { 144 usb_log_error("Failed to zero USBLEGCTLSTS: %s\n", 145 str_error(ret)); 146 return ret; 234 147 } 235 148 236 149 udelay(10); 237 rc = pci_config_space_read_32(parent_sess, 150 /* read again to amke sure it's zeroed */ 151 ret = pci_config_space_read_32(parent_sess, 238 152 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 239 if (r c!= EOK) {153 if (ret != EOK) { 240 154 usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n", 241 str_error(r c));242 goto error;155 str_error(ret)); 156 return ret; 243 157 } 244 245 158 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n", 246 159 usblegctlsts); … … 248 161 249 162 /* Read again Legacy Support register */ 250 r c= pci_config_space_read_32(parent_sess,163 ret = pci_config_space_read_32(parent_sess, 251 164 eecp + USBLEGSUP_OFFSET, &usblegsup); 252 if (r c!= EOK) {165 if (ret != EOK) { 253 166 usb_log_error("Failed to read USBLEGSUP: %s.\n", 254 str_error(rc)); 255 goto error; 256 } 257 167 str_error(ret)); 168 return ret; 169 } 258 170 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 259 async_hangup(parent_sess); 260 return EOK; 261 error: 262 async_hangup(parent_sess); 263 return rc; 171 return ret; 264 172 } 265 173 266 int disable_legacy(ddf_dev_t *device , addr_range_t *reg_range)174 int disable_legacy(ddf_dev_t *device) 267 175 { 268 176 assert(device); 177 178 async_sess_t *parent_sess = devman_parent_device_connect( 179 EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING); 180 if (!parent_sess) 181 return ENOMEM; 182 269 183 usb_log_debug("Disabling EHCI legacy support.\n"); 184 185 hw_res_list_parsed_t res; 186 hw_res_list_parsed_init(&res); 187 int ret = hw_res_get_list_parsed(parent_sess, &res, 0); 188 if (ret != EOK) { 189 usb_log_error("Failed to get resource list: %s\n", 190 str_error(ret)); 191 goto clean; 192 } 193 194 if (res.mem_ranges.count < 1) { 195 usb_log_error("Incorrect mem range count: %zu", 196 res.mem_ranges.count); 197 ret = EINVAL; 198 goto clean; 199 } 270 200 271 201 /* Map EHCI registers */ 272 202 void *regs = NULL; 273 int rc = pio_enable_range(reg_range, ®s);274 if (r c!= EOK) {203 ret = pio_enable_range(&res.mem_ranges.ranges[0], ®s); 204 if (ret != EOK) { 275 205 usb_log_error("Failed to map registers %p: %s.\n", 276 RNGABSPTR( *reg_range), str_error(rc));277 return rc;206 RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret)); 207 goto clean; 278 208 } 279 209 280 210 usb_log_debug2("Registers mapped at: %p.\n", regs); 281 211 282 const uint32_t hcc_params = 283 *(uint32_t*)(regs + HCC_PARAMS_OFFSET); 212 ehci_caps_regs_t *ehci_caps = regs; 213 214 const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams); 284 215 usb_log_debug("Value of hcc params register: %x.\n", hcc_params); 285 216 … … 287 218 * position of EEC registers (points to PCI config space) */ 288 219 const uint32_t eecp = 289 (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;220 (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK; 290 221 usb_log_debug("Value of EECP: %x.\n", eecp); 291 222 292 r c = disable_extended_caps(device, eecp);293 if (r c!= EOK) {223 ret = disable_extended_caps(parent_sess, eecp); 224 if (ret != EOK) { 294 225 usb_log_error("Failed to disable extended capabilities: %s.\n", 295 str_error(rc)); 296 return rc; 297 } 298 299 /* 300 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT IF NEEDED 301 */ 302 303 /* Get size of capability registers in memory space. */ 304 const unsigned operation_offset = *(uint8_t*)regs; 305 usb_log_debug("USBCMD offset: %d.\n", operation_offset); 306 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; 323 /* Wait until hc is halted */ 324 while ((*usbsts & USBSTS_HALTED) == 0); 325 usb_log_info("EHCI turned off.\n"); 326 } else { 327 usb_log_info("EHCI was not running.\n"); 328 } 329 usb_log_debug("Registers: \n" 330 "\t USBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)\n" 331 "\t USBSTS(%p): %x(0x00001000 = HC halted)\n" 332 "\t USBINT(%p): %x(0x0 = no interrupts).\n" 333 "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n", 334 usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf); 335 336 return rc; 226 str_error(ret)); 227 goto clean; 228 } 229 clean: 230 //TODO unmap registers 231 hw_res_list_parsed_clean(&res); 232 async_hangup(parent_sess); 233 return ret; 337 234 } 338 235
Note:
See TracChangeset
for help on using the changeset viewer.