Lines Matching +full:interrupt +full:- +full:endpoint
1 /* usb_dc_kinetis.c - Kinetis USBFSOTG usb device driver */
6 * SPDX-License-Identifier: Apache-2.0
44 * Buffer Descriptor (BD) entry provides endpoint buffer control
45 * information for USBFS controller. Every endpoint direction requires
75 * four BD entries per endpoint and 512 bytes of memory.
138 * endpoint address and the odd bit.
152 SIM->SOPT1 |= SIM_SOPT1_USBREGEN_MASK; in kinetis_usb_init()
155 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; in kinetis_usb_init()
158 USB0->CTL = 0; in kinetis_usb_init()
160 USB0->CTL |= USB_CTL_USBENSOFEN_MASK; in kinetis_usb_init()
162 if ((USB0->PERID != USBFSOTG_PERID) || in kinetis_usb_init()
163 (USB0->REV != USBFSOTG_REV)) { in kinetis_usb_init()
164 return -1; in kinetis_usb_init()
167 USB0->BDTPAGE1 = (uint8_t)(((uint32_t)bdt) >> 8); in kinetis_usb_init()
168 USB0->BDTPAGE2 = (uint8_t)(((uint32_t)bdt) >> 16); in kinetis_usb_init()
169 USB0->BDTPAGE3 = (uint8_t)(((uint32_t)bdt) >> 24); in kinetis_usb_init()
171 /* clear interrupt flags */ in kinetis_usb_init()
172 USB0->ISTAT = 0xFF; in kinetis_usb_init()
174 /* enable reset interrupt */ in kinetis_usb_init()
175 USB0->INTEN = USB_INTEN_USBRSTEN_MASK; in kinetis_usb_init()
177 USB0->USBCTRL = USB_USBCTRL_PDE_MASK; in kinetis_usb_init()
189 USB0->ENDPOINT[i].ENDPT = 0; in usb_dc_reset()
194 USB0->CTL |= USB_CTL_ODDRST_MASK; in usb_dc_reset()
195 USB0->CTL &= ~USB_CTL_ODDRST_MASK; in usb_dc_reset()
197 /* Clear interrupt status flags */ in usb_dc_reset()
198 USB0->ISTAT = 0xFF; in usb_dc_reset()
200 USB0->ERRSTAT = 0xFF; in usb_dc_reset()
201 /* Enable all error interrupt sources */ in usb_dc_reset()
202 USB0->ERREN = 0xFF; in usb_dc_reset()
204 USB0->ADDR = 0x00; in usb_dc_reset()
206 USB0->INTEN = (USB_INTEN_USBRSTEN_MASK | in usb_dc_reset()
235 /* non-OTG device mode, enable DP Pullup */ in usb_dc_attach()
236 USB0->CONTROL = USB_CONTROL_DPPULLUPNONOTG_MASK; in usb_dc_attach()
245 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; in usb_dc_detach()
246 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; in usb_dc_detach()
256 return -EINVAL; in usb_dc_set_address()
272 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr); in usb_dc_ep_check_cap()
274 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_check_cap()
275 LOG_ERR("endpoint index/address out of range"); in usb_dc_ep_check_cap()
276 return -EINVAL; in usb_dc_ep_check_cap()
279 switch (cfg->ep_type) { in usb_dc_ep_check_cap()
281 if (cfg->ep_mps > USB_MAX_CTRL_MPS) { in usb_dc_ep_check_cap()
282 return -EINVAL; in usb_dc_ep_check_cap()
286 if (cfg->ep_mps > USB_MAX_FS_BULK_MPS) { in usb_dc_ep_check_cap()
287 return -EINVAL; in usb_dc_ep_check_cap()
291 if (cfg->ep_mps > USB_MAX_FS_INT_MPS) { in usb_dc_ep_check_cap()
292 return -EINVAL; in usb_dc_ep_check_cap()
296 if (cfg->ep_mps > USB_MAX_FS_ISO_MPS) { in usb_dc_ep_check_cap()
297 return -EINVAL; in usb_dc_ep_check_cap()
301 LOG_ERR("Unknown endpoint type!"); in usb_dc_ep_check_cap()
302 return -EINVAL; in usb_dc_ep_check_cap()
306 if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_IN) { in usb_dc_ep_check_cap()
307 LOG_INF("pre-selected as IN endpoint"); in usb_dc_ep_check_cap()
308 return -1; in usb_dc_ep_check_cap()
311 if (USB_EP_GET_DIR(cfg->ep_addr) != USB_EP_DIR_OUT) { in usb_dc_ep_check_cap()
312 LOG_INF("pre-selected as OUT endpoint"); in usb_dc_ep_check_cap()
313 return -1; in usb_dc_ep_check_cap()
322 uint8_t ep_idx = USB_EP_GET_IDX(cfg->ep_addr); in usb_dc_ep_configure()
329 return -EINVAL; in usb_dc_ep_configure()
332 idx_even = get_bdt_idx(cfg->ep_addr, 0); in usb_dc_ep_configure()
333 idx_odd = get_bdt_idx(cfg->ep_addr, 1); in usb_dc_ep_configure()
338 LOG_WRN("endpoint already configured"); in usb_dc_ep_configure()
339 return -EALREADY; in usb_dc_ep_configure()
342 LOG_DBG("ep %x, mps %d, type %d", cfg->ep_addr, cfg->ep_mps, in usb_dc_ep_configure()
343 cfg->ep_type); in usb_dc_ep_configure()
345 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) { in usb_dc_ep_configure()
346 block = &(ep_ctrl->mblock_out); in usb_dc_ep_configure()
348 block = &(ep_ctrl->mblock_in); in usb_dc_ep_configure()
352 k_heap_free(&ep_buf_pool, block->data); in usb_dc_ep_configure()
355 USB0->ENDPOINT[ep_idx].ENDPT = 0; in usb_dc_ep_configure()
359 block->data = k_heap_alloc(&ep_buf_pool, cfg->ep_mps * 2U, K_NO_WAIT); in usb_dc_ep_configure()
360 if (block->data != NULL) { in usb_dc_ep_configure()
361 (void)memset(block->data, 0, cfg->ep_mps * 2U); in usb_dc_ep_configure()
363 LOG_ERR("Memory allocation time-out"); in usb_dc_ep_configure()
364 return -ENOMEM; in usb_dc_ep_configure()
367 bdt[idx_even].buf_addr = (uint32_t)block->data; in usb_dc_ep_configure()
368 LOG_INF("idx_even %x", (uint32_t)block->data); in usb_dc_ep_configure()
369 bdt[idx_odd].buf_addr = (uint32_t)((uint8_t *)block->data + cfg->ep_mps); in usb_dc_ep_configure()
370 LOG_INF("idx_odd %x", (uint32_t)((uint8_t *)block->data + cfg->ep_mps)); in usb_dc_ep_configure()
372 if (cfg->ep_addr & USB_EP_DIR_IN) { in usb_dc_ep_configure()
373 dev_data.ep_ctrl[ep_idx].mps_in = cfg->ep_mps; in usb_dc_ep_configure()
375 dev_data.ep_ctrl[ep_idx].mps_out = cfg->ep_mps; in usb_dc_ep_configure()
378 bdt[idx_even].set.bc = cfg->ep_mps; in usb_dc_ep_configure()
379 bdt[idx_odd].set.bc = cfg->ep_mps; in usb_dc_ep_configure()
384 switch (cfg->ep_type) { in usb_dc_ep_configure()
386 LOG_DBG("configure control endpoint"); in usb_dc_ep_configure()
387 USB0->ENDPOINT[ep_idx].ENDPT |= (USB_ENDPT_EPHSHK_MASK | in usb_dc_ep_configure()
393 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPHSHK_MASK; in usb_dc_ep_configure()
394 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) { in usb_dc_ep_configure()
395 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK; in usb_dc_ep_configure()
397 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK; in usb_dc_ep_configure()
401 if (USB_EP_DIR_IS_OUT(cfg->ep_addr)) { in usb_dc_ep_configure()
402 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPRXEN_MASK; in usb_dc_ep_configure()
404 USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPTXEN_MASK; in usb_dc_ep_configure()
408 return -EINVAL; in usb_dc_ep_configure()
419 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_set_stall()
420 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_set_stall()
421 return -EINVAL; in usb_dc_ep_set_stall()
446 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_clear_stall()
447 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_clear_stall()
448 return -EINVAL; in usb_dc_ep_clear_stall()
452 USB0->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; in usb_dc_ep_clear_stall()
471 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; in usb_dc_ep_clear_stall()
481 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_is_stalled()
482 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_is_stalled()
483 return -EINVAL; in usb_dc_ep_is_stalled()
488 return -EINVAL; in usb_dc_ep_is_stalled()
519 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_enable()
520 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_enable()
521 return -EINVAL; in usb_dc_ep_enable()
529 LOG_WRN("endpoint 0x%x already enabled", ep); in usb_dc_ep_enable()
530 return -EALREADY; in usb_dc_ep_enable()
560 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_disable()
561 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_disable()
562 return -EINVAL; in usb_dc_ep_disable()
585 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_flush()
586 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_flush()
587 return -EINVAL; in usb_dc_ep_flush()
604 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_write()
605 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_write()
606 return -EINVAL; in usb_dc_ep_write()
614 LOG_ERR("Wrong endpoint direction"); in usb_dc_ep_write()
615 return -EINVAL; in usb_dc_ep_write()
619 LOG_WRN("endpoint is stalled"); in usb_dc_ep_write()
620 return -EBUSY; in usb_dc_ep_write()
669 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_read_wait()
670 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_read_wait()
671 return -EINVAL; in usb_dc_ep_read_wait()
674 /* select the index of active endpoint buffer */ in usb_dc_ep_read_wait()
679 LOG_ERR("Wrong endpoint direction"); in usb_dc_ep_read_wait()
680 return -EINVAL; in usb_dc_ep_read_wait()
684 LOG_WRN("endpoint is stalled"); in usb_dc_ep_read_wait()
685 return -EBUSY; in usb_dc_ep_read_wait()
691 return -EINVAL; in usb_dc_ep_read_wait()
695 LOG_ERR("Endpoint is occupied by the controller"); in usb_dc_ep_read_wait()
696 return -EBUSY; in usb_dc_ep_read_wait()
739 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_read_continue()
740 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_read_continue()
741 return -EINVAL; in usb_dc_ep_read_continue()
747 LOG_ERR("Wrong endpoint direction"); in usb_dc_ep_read_continue()
748 return -EINVAL; in usb_dc_ep_read_continue()
757 /* select the index of the next endpoint buffer */ in usb_dc_ep_read_continue()
774 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; in usb_dc_ep_read_continue()
799 return -EINVAL; in usb_dc_ep_read()
811 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_set_callback()
812 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_set_callback()
813 return -EINVAL; in usb_dc_ep_set_callback()
817 return -EINVAL; in usb_dc_ep_set_callback()
841 if (ep_idx > (NUM_OF_EP_MAX - 1)) { in usb_dc_ep_mps()
842 LOG_ERR("Wrong endpoint index/address"); in usb_dc_ep_mps()
843 return -EINVAL; in usb_dc_ep_mps()
857 /* Reconfigure control endpoint 0 after a reset */ in reenable_control_endpoints()
865 /* Enable both endpoint directions */ in reenable_control_endpoints()
872 uint8_t istatus = USB0->ISTAT; in usb_kinetis_isr_handler()
873 uint8_t status = USB0->STAT; in usb_kinetis_isr_handler()
879 USB0->ADDR = (uint8_t)0; in usb_kinetis_isr_handler()
883 * therefore, we must re-enable the default control 0 endpoint in usb_kinetis_isr_handler()
886 USB0->CTL |= USB_CTL_ODDRST_MASK; in usb_kinetis_isr_handler()
887 USB0->CTL &= ~USB_CTL_ODDRST_MASK; in usb_kinetis_isr_handler()
896 USB0->ERRSTAT = 0xFF; in usb_kinetis_isr_handler()
930 * Set/Reset here the toggle bits for control endpoint in usb_kinetis_isr_handler()
949 USB0->ADDR = dev_data.address & 0x7f; in usb_kinetis_isr_handler()
962 /* Enable resume interrupt */ in usb_kinetis_isr_handler()
963 USB0->INTEN |= USB_INTEN_RESUMEEN_MASK; in usb_kinetis_isr_handler()
971 /* Disable resume interrupt */ in usb_kinetis_isr_handler()
972 USB0->INTEN &= ~USB_INTEN_RESUMEEN_MASK; in usb_kinetis_isr_handler()
979 /* Clear interrupt status bits */ in usb_kinetis_isr_handler()
980 USB0->ISTAT = istatus; in usb_kinetis_isr_handler()
984 * This thread is only used to not run the USB device stack and endpoint