Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: uhc: implement UHC shim driver for NXP KHCI and EHCI controller #77973

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

MarkWangChinese
Copy link
Contributor

Enablet the NXP MCUX UHC drivers.
Add uhc support for frdm_k22f, rt1060, lpc55s69 and lpc55s28. frdm_k22f supports the KHCI controller, rt1060 supports the EHCI controller, lpc55s69 and lpc55s28 support the OHCI and IP3516HS controller.

@zephyrbot zephyrbot added area: ARM ARM (32-bit) Architecture area: Architectures area: USB Universal Serial Bus platform: NXP NXP platform: NXP Drivers NXP Semiconductors, drivers labels Sep 4, 2024
@zephyrbot
Copy link
Collaborator

zephyrbot commented Sep 4, 2024

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
hal_nxp zephyrproject-rtos/hal_nxp@b5f6470 (master) zephyrproject-rtos/hal_nxp#496 zephyrproject-rtos/hal_nxp#496/files

DNM label due to: 1 project with PR revision

Note: This message is automatically posted and updated by the Manifest GitHub Action.

@PetervdPerk-NXP
Copy link
Collaborator

Any plans to enable 1170 and 1180 as well?
Since they share almost the same EHCI controller.

@MarkWangChinese
Copy link
Contributor Author

Any plans to enable 1170 and 1180 as well? Since they share almost the same EHCI controller.

After this basic NXP UHC controller driver merges, I think next step is implementing the host stack. Because the host stack is not ready, so supporting more platforms does not make much sense.

@jfischer-no jfischer-no added this to the v4.0.0 milestone Sep 5, 2024
*
* @return the device's address.
*/
uint8_t usbh_udev_get_address(void *usb_device);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why void *usb_device? Shouldn't it simply be struct usb_device *usb_device?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is called from context that can't see struct usb_device. For example: the uhc files that can't see struct usb_device.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just treat it as opaque pointer then. Having void * here is bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the struct uhc_transfer, it is void *udev. So I use the void *. Could you please give reference codes how to treat it as opaque pointer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would need a change in the struct uhc_transfer then. Opaque pointers in C are simply achieved by having incomplete struct definition. So in this case it would be struct usb_device; above struct uhc_transfer { and then the void *udev; can be changed to struct usb_device *udev;. Similar could be done with the transfer completion callback. I somehow completely missed this during the uhc review.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @tmon-nordic, I changed it, please help to review again.

tmon-nordic
tmon-nordic previously approved these changes Sep 10, 2024
@@ -89,6 +89,9 @@ struct usbh_class_data {
int (*resumed)(struct usbh_contex *const uhs_ctx);
};

/* declare usb_device */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't really make anything clearer, I'd remove it.

@jfischer-no jfischer-no changed the title Feature/enable mcux uhc drivers: uhc: implement UHC shim driver for NXP KHCI and EHCI controller Sep 10, 2024
bool "NXP MCUX USB EHCI Host controller driver"
default y
depends on DT_HAS_NXP_UHC_EHCI_ENABLED
select EVENTS
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is k_event used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NXP hal controller drivers use the k_event. Hal controller drivers depend on the event of modules\hal\nxp\mcux\mcux-sdk\components\osa\fsl_os_abstraction_zephyr, and the fsl_os_abstraction_zephyr depend on k_event.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hal driver must not use anything from Zephyr RTOS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MCUX usb host hal controller driver is like the UHC of Zephyr. In the hal driver, one task function is provided, the upper layer can use the task function to create one task to handle the controller interrupts. Then the OS event is used to handle interrupts in this task function.

NXP MCUX USB Host Controller Driver for ohci.

config HEAP_MEM_POOL_ADD_SIZE_UHC_MCUX
int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally hidden?

Comment on lines 50 to 52
}
return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an empty line above return if it is not a single line within a block, please fix it everywhere.

Comment on lines 109 to 116
case kUSB_HostGetDeviceHubNumber: /* device hub address */
case kUSB_HostGetDevicePortNumber: /* device port no */
case kUSB_HostGetDeviceHSHubNumber: /* device high-speed hub address */
case kUSB_HostGetDeviceHSHubPort: /* device high-speed hub port no */
case kUSB_HostGetHubThinkTime: /* device hub think time */
*infoValue = 0;
break;
case kUSB_HostGetDeviceLevel: /* device level */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please cleanup from redundant comments.

break;

default:
/*no action*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please cleanup from redundant comments.

for (uint8_t i = 0; i < USB_HOST_CONFIG_MAX_PIPES; i++) {
uint8_t mcux_ep = ep;

if (mcux_ep == 0x80) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (mcux_ep == USB_CONTROL_EP_IN) {

mcux_ep_handle = uhc_mcux_get_hal_ep(priv, udev, ep);

/* Initialize mcux endpoint pipe */
if (mcux_ep_handle == NULL) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	if (mcux_ep_handle != NULL) {
		return mcux_ep_handle;
	}

mcux_ep_handle = uhc_mcux_get_hal_ep(priv, udev, ep);

/* Initialize mcux endpoint pipe */
if (mcux_ep_handle == NULL) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	if (mcux_ep_handle != NULL) {
		return mcux_ep_handle;
	}

@@ -89,6 +89,9 @@ struct usbh_class_data {
int (*resumed)(struct usbh_contex *const uhs_ctx);
};

/* declare usb_device */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please cleanup.

usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
uint32_t infoCode, uint32_t *infoValue)
{
const struct device *dev = usbh_udev_get_dev(deviceHandle);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Driver must not call anything from the higher layer. Each uhc_transfer has a device address, you have to use it somehow.

Copy link
Contributor Author

@MarkWangChinese MarkWangChinese Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of I add usbh_udev_get_dev and usbh_udev_get_address is to get device's information by controller driver. I think the device's related hub information (hub address, port num, first hs hub address, first hs hub port num) and speed are also needed by the controller driver to do the transfer. Will you plan to put all the information to every uhc_transfer?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless of whether this information is needed or not, you cannot include this header or use any higher-level API in the driver.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even the linux EHCI driver include the usb.h linux/usb.h> in linux/drivers/usb/host/ehci-hcd.c. Actually I don't understand why the simple helper API can't be called in lower level. Just want to figure out the style, do you mean that only callback is right from lower level to higher level? Anyway I have changed the codes to get device information based on the xfer. When developing the usb host stack, I think the codes may need to be updated to match host stack's design. For now, it should work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't understand why the simple helper API can't be called in lower level.

Because it is always a level violation, and it ends in a nightmare.

I think the device's related hub information (hub address, port num, first hs hub address, first hs hub port num) and speed are also needed by the controller driver to do the transfer. Will you plan to put all the information to every uhc_transfer?

Yes, but maybe rather a pointer to a device structure similar to struct urb. struct usb_device would have to be defined in uhc.h and replace addr in struct uhc_transfer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, Thanks for the explanation.

@CrushedB
Copy link

Any plans to enable 1170 and 1180 as well? Since they share almost the same EHCI controller.

After this basic NXP UHC controller driver merges, I think next step is implementing the host stack. Because the host stack is not ready, so supporting more platforms does not make much sense.

Hi @MarkWangChinese,
Thanks for this delivery.
Can you please elaborate on the missing host stack? What won't be supported after this delivery? (I would like to be able to host a USB thumb drive on the rx10xx board).

@DerekSnell
Copy link
Contributor

Hi @CrushedB ,

Can you please elaborate on the missing host stack? What won't be supported after this delivery? (I would like to be able to host a USB thumb drive on the rx10xx board).

Currently, Zephyr does not include a USB Host stack, only USB Device. This USB RFC tracks the plans and progress for adding a USB Host stack. Today, the USB Host Controller (UHC) driver API has be introduced for the low-level APIs. And this PR is porting the UHC APIs to the NXP USB hardware. But as the RFC shows, the USB Host stack for the high-level APIs still needs to be introduced. And the RFC shows the plans for the Host classes that will be supported.

If you have any further questions on the USB Host plans or progress, we encourage you to engage in the USB RFC. Best regards

@MarkWangChinese
Copy link
Contributor Author

Rebase the Zephyr main branch.
Hi @jfischer-no Could you please help to review again?
I have another query, I see you have one task item as "Introduction of USB host stack implementation (WIP @jfischer-no)" in #42066. When will you plan to give this introducation?

@tmon-nordic
Copy link
Contributor

Twister failures sounds like some hal issue with missing fsl_os_abstraction.h header. Please fix it.

It is based on SDK USB Host controller driver.
Support NXP EHCI, KHCI, OHCI and IP3516HS controllers.

Signed-off-by: Mark Wang <yichang.wang@nxp.com>
…5s28

add uhc related items to dts.
add clock initialization
add BM4 if CONFIG_USB_UHC_NXP_KHCI is enabled
add pin mux
update board related CMakeLists.txt
update west.yml to contain the hal_nxp pr

Signed-off-by: Mark Wang <yichang.wang@nxp.com>
add uhc related items to dts.

Signed-off-by: Mark Wang <yichang.wang@nxp.com>
@MarkWangChinese MarkWangChinese force-pushed the feature/enable_mcux_uhc branch from 9c0cd0c to 186641a Compare January 14, 2025 05:20
@MarkWangChinese
Copy link
Contributor Author

Twister failures sounds like some hal issue with missing fsl_os_abstraction.h header. Please fix it.

Fixed

@fabiobaltieri fabiobaltieri added DNM (manifest) This PR should not be merged (controlled by action-manifest) and removed DNM This PR should not be merged (Do Not Merge) labels Feb 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Architectures area: ARM ARM (32-bit) Architecture area: USB Universal Serial Bus DNM (manifest) This PR should not be merged (controlled by action-manifest) manifest manifest-hal_nxp platform: NXP Drivers NXP Semiconductors, drivers platform: NXP NXP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants