usb: dwc3: Add dwc3 glue driver for am62

Add glue code for TI AM62 to the dwc3 driver; Most code adopted from
TI vendor u-boot code.

Signed-off-by: Sjoerd Simons <sjoerd@collabora.com>
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Signed-off-by: Ravi Gunasekaran <r-gunasekaran@ti.com>
This commit is contained in:
Sjoerd Simons 2023-04-14 11:34:43 +05:30 committed by Praneeth Bajjuri
parent 828cd56f3f
commit db5ee9d822
3 changed files with 142 additions and 0 deletions

View File

@ -37,6 +37,20 @@ config SPL_USB_DWC3_GENERIC
Select this for Xilinx ZynqMP and similar Platforms. Select this for Xilinx ZynqMP and similar Platforms.
This wrapper supports Host and Peripheral operation modes. This wrapper supports Host and Peripheral operation modes.
config SPL_USB_DWC3_AM62
bool "TI AM62 USB wrapper"
depends on SPL_DM_USB && SPL_USB_DWC3_GENERIC
help
Select this for TI AM62 Platforms.
This wrapper supports Host and Peripheral operation modes.
config USB_DWC3_AM62
bool "TI AM62 USB wrapper"
depends on DM_USB && USB_DWC3_GENERIC
help
Select this for TI AM62 Platforms.
This wrapper supports Host and Peripheral operation modes.
config USB_DWC3_MESON_G12A config USB_DWC3_MESON_G12A
bool "Amlogic Meson G12A USB wrapper" bool "Amlogic Meson G12A USB wrapper"
depends on DM_USB && USB_DWC3 && ARCH_MESON depends on DM_USB && USB_DWC3 && ARCH_MESON

View File

@ -6,6 +6,7 @@ dwc3-y := core.o
obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o
obj-$(CONFIG_$(SPL_)USB_DWC3_AM62) += dwc3-am62.o
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o
obj-$(CONFIG_USB_DWC3_MESON_GXL) += dwc3-meson-gxl.o obj-$(CONFIG_USB_DWC3_MESON_GXL) += dwc3-meson-gxl.o

View File

@ -0,0 +1,127 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI AM62 specific glue layer for DWC3
*/
#include <common.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/io.h>
#include "dwc3-generic.h"
void dwc3_ti_am62_glue_configure(struct udevice *dev, int index,
enum usb_dr_mode mode)
{
#define USBSS_MODE_CONTROL 0x1c
#define USBSS_PHY_CONFIG 0x8
#define USBSS_PHY_VBUS_SEL_MASK GENMASK(2, 1)
#define USBSS_PHY_VBUS_SEL_SHIFT 1
#define USBSS_MODE_VALID BIT(0)
#define PHY_PLL_REFCLK_MASK GENMASK(3, 0)
static const int dwc3_ti_am62_rate_table[] = { /* in KHZ */
9600,
10000,
12000,
19200,
20000,
24000,
25000,
26000,
38400,
40000,
58000,
50000,
52000,
};
struct clk usb2_refclk;
int rate_code, i, ret;
unsigned long rate;
u32 reg;
void *usbss;
bool vbus_divider;
struct regmap *syscon;
struct ofnode_phandle_args args;
usbss = dev_remap_addr_index(dev, 0);
if (IS_ERR(usbss)) {
dev_err(dev, "can't map IOMEM resource\n");
return;
}
ret = clk_get_by_name(dev, "ref", &usb2_refclk);
if (ret) {
dev_err(dev, "can't get usb2_refclk\n");
return;
}
/* Calcuate the rate code */
rate = clk_get_rate(&usb2_refclk);
rate /= 1000; /* To KHz */
for (i = 0; i < ARRAY_SIZE(dwc3_ti_am62_rate_table); i++) {
if (dwc3_ti_am62_rate_table[i] == rate)
break;
}
if (i == ARRAY_SIZE(dwc3_ti_am62_rate_table)) {
dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
return;
}
rate_code = i;
/* Read the syscon property */
syscon = syscon_regmap_lookup_by_phandle(dev, "ti,syscon-phy-pll-refclk");
if (IS_ERR(syscon)) {
dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
return;
}
ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "ti,syscon-phy-pll-refclk", NULL, 1,
0, &args);
if (ret)
return;
/* Program PHY PLL refclk by reading syscon property */
ret = regmap_update_bits(syscon, args.args[0], PHY_PLL_REFCLK_MASK, rate_code);
if (ret) {
dev_err(dev, "failed to set phy pll reference clock rate\n");
return;
}
/* VBUS divider select */
reg = readl(usbss + USBSS_PHY_CONFIG);
vbus_divider = dev_read_bool(dev, "ti,vbus-divider");
if (vbus_divider)
reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
writel(reg, usbss + USBSS_PHY_CONFIG);
/* Set mode valid */
reg = readl(usbss + USBSS_MODE_CONTROL);
reg |= USBSS_MODE_VALID;
writel(reg, usbss + USBSS_MODE_CONTROL);
}
struct dwc3_glue_ops ti_am62_ops = {
.glue_configure = dwc3_ti_am62_glue_configure,
};
static const struct udevice_id dwc3_am62_match[] = {
{ .compatible = "ti,am62-usb", .data = (ulong)&ti_am62_ops },
{ /* sentinel */ }
};
U_BOOT_DRIVER(dwc3_am62_wrapper) = {
.name = "dwc3-am62",
.id = UCLASS_SIMPLE_BUS,
.of_match = dwc3_am62_match,
.bind = dwc3_glue_bind,
.probe = dwc3_glue_probe,
.remove = dwc3_glue_remove,
.plat_auto = sizeof(struct dwc3_glue_data),
};