[PATCH 2/4] usb: ohci-at91: Enable OHCI functionality and register into DM
Marek Vasut
marex at denx.de
Tue Jan 3 00:26:10 CET 2023
On 12/23/22 13:34, Sergiu Moga wrote:
[...]
> diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
> index 9b955c1bd6..9ae55c6e5d 100644
> --- a/drivers/usb/host/ohci-at91.c
> +++ b/drivers/usb/host/ohci-at91.c
> @@ -5,6 +5,9 @@
> */
>
> #include <common.h>
> +
> +#if !(CONFIG_IS_ENABLED(DM_USB))
> +
> #include <asm/arch/clk.h>
>
> int usb_cpu_init(void)
> @@ -62,3 +65,183 @@ int usb_cpu_init_fail(void)
> {
> return usb_cpu_stop();
> }
Would it be possible to just remove the non-DM functionality ?
> +#elif CONFIG_IS_ENABLED(DM_GPIO)
I think you want plain '#else' here, and then make the driver select
DM_GPIO in case DM_USB is enabled in Kconfig entry.
> +#include <clk.h>
> +#include <dm.h>
> +#include <asm/gpio.h>
> +#include <usb.h>
> +#include "ohci.h"
> +
> +#define AT91_MAX_USBH_PORTS 3
>
> +#define at91_for_each_port(index) \
> + for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
> +
> +struct at91_usbh_data {
> + enum usb_init_type init_type;
> + struct gpio_desc vbus_pin[AT91_MAX_USBH_PORTS];
drivers/usb/host/ehci-generic.c: ret =
device_get_supply_regulator(dev, "vbus-supply",
I wonder if we can instead use regulator for vbus-supply here too ?
> + u8 ports; /* number of ports on root hub */
> +};
> +
> +struct ohci_at91_priv {
> + struct clk *iclk;
> + struct clk *fclk;
> + struct clk *hclk;
Have a look at clk.*bulk functions in U-Boot , then you can do
clk_get_bulk() / clk_enable_bulk() etc. below.
> + bool clocked;
> +};
> +
> +static void at91_start_clock(struct ohci_at91_priv *ohci_at91)
> +{
> + if (ohci_at91->clocked)
> + return;
> +
> + clk_set_rate(ohci_at91->fclk, 48000000);
> + clk_prepare_enable(ohci_at91->hclk);
> + clk_prepare_enable(ohci_at91->iclk);
> + clk_prepare_enable(ohci_at91->fclk);
E.g. here you can use clk_enable_bulk() .
> + ohci_at91->clocked = true;
Why is this here, are you suffering from clock inbalance ? You
shouldn't, so remove this and the if (ohci_at91->clocked) test above.
> +}
> +
> +static void at91_stop_clock(struct ohci_at91_priv *ohci_at91)
> +{
> + if (!ohci_at91->clocked)
Is this really needed ?
> + return;
> +
> + clk_disable_unprepare(ohci_at91->fclk);
> + clk_disable_unprepare(ohci_at91->iclk);
> + clk_disable_unprepare(ohci_at91->hclk);
> + ohci_at91->clocked = false;
> +}
> +
> +static void ohci_at91_set_power(struct at91_usbh_data *pdata, int port,
> + bool enable)
> +{
> + if (!dm_gpio_is_valid(&pdata->vbus_pin[port]))
> + return;
This could be regulator instead.
> + if (enable)
> + dm_gpio_set_dir_flags(&pdata->vbus_pin[port],
> + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> + else
> + dm_gpio_set_dir_flags(&pdata->vbus_pin[port], 0);
> +}
> +
> +static void at91_start_hc(struct udevice *dev)
> +{
> + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
> +
> + at91_start_clock(ohci_at91);
> +}
> +
> +static void at91_stop_hc(struct udevice *dev)
> +{
> + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
> +
> + at91_stop_clock(ohci_at91);
> +}
> +
> +static int ohci_atmel_deregister(struct udevice *dev)
> +{
> + struct at91_usbh_data *pdata = dev_get_plat(dev);
> + int i;
> +
> + at91_stop_hc(dev);
> +
> + at91_for_each_port(i) {
> + if (i >= pdata->ports)
You can just wrap this test into the at91_for_each_port() macro , just
use "index < min(AT91_MAX_USBH_PORTS, pdata->ports)" or so.
> + break;
> +
> + ohci_at91_set_power(pdata, i, false);
> + }
> +
> + return ohci_deregister(dev);
> +}
> +
> +static int ohci_atmel_child_pre_probe(struct udevice *dev)
> +{
> + struct udevice *ohci_controller = dev_get_parent(dev);
> + struct at91_usbh_data *pdata = dev_get_plat(ohci_controller);
> + int i;
> +
> + at91_for_each_port(i) {
> + if (i >= pdata->ports)
> + break;
> +
> + ohci_at91_set_power(pdata, i, true);
> + }
> +
> + return 0;
> +}
> +
> +static int ohci_atmel_probe(struct udevice *dev)
> +{
> + struct at91_usbh_data *pdata = dev_get_plat(dev);
> + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev);
> + int i;
> + int ret;
> + u32 ports;
> + struct ohci_regs *regs = (struct ohci_regs *)dev_read_addr(dev);
> +
> + if (!dev_read_u32(dev, "num-ports", &ports))
> + pdata->ports = ports;
dev_read_u32_default() ?
> + at91_for_each_port(i) {
> + if (i >= pdata->ports)
> + break;
> +
> + gpio_request_by_name(dev, "atmel,vbus-gpio", i,
> + &pdata->vbus_pin[i], GPIOD_IS_OUT |
> + GPIOD_IS_OUT_ACTIVE);
> + }
> +
> + ohci_at91->iclk = devm_clk_get(dev, "ohci_clk");
> + if (IS_ERR(ohci_at91->iclk)) {
> + ret = PTR_ERR(ohci_at91->iclk);
> + goto fail;
> + }
> +
> + ohci_at91->fclk = devm_clk_get(dev, "uhpck");
> + if (IS_ERR(ohci_at91->fclk)) {
> + ret = PTR_ERR(ohci_at91->fclk);
> + goto fail;
> + }
> +
> + ohci_at91->hclk = devm_clk_get(dev, "hclk");
> + if (IS_ERR(ohci_at91->hclk)) {
> + ret = PTR_ERR(ohci_at91->hclk);
clk_get_bulk() would simplify this.
[...]
More information about the U-Boot
mailing list