From 22d5e1fae2a1f70e84a63341cda47fa91b0853ea Mon Sep 17 00:00:00 2001 From: Yanhong Wang Date: Fri, 19 May 2023 17:06:09 +0800 Subject: usb: cdns3: starfive: Add usb driver to support for JH7110 Add usb driver to support for jh7110. Signed-off-by: Yanhong Wang Signed-off-by: Minda Chen --- drivers/usb/cdns3/cdns3-starfive.c | 232 +++++++++++++++++++++++++++++++++++-- 1 file changed, 223 insertions(+), 9 deletions(-) diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c index d51bf30b67..a7682c2fbf 100644 --- a/drivers/usb/cdns3/cdns3-starfive.c +++ b/drivers/usb/cdns3/cdns3-starfive.c @@ -6,50 +6,263 @@ * Author: yanhong */ +#include #include #include #include #include #include #include +#include +#include #include "core.h" +#define USB_STRAP_HOST (2 << 0x10) +#define USB_STRAP_DEVICE (4 << 0X10) +#define USB_STRAP_MASK 0x70000 + +#define USB_SUSPENDM_HOST (1 << 0x13) +#define USB_SUSPENDM_DEVICE (0 << 0x13) +#define USB_SUSPENDM_MASK 0x80000 + +#define USB_SUSPENDM_BYPS_SHIFT 0x14 +#define USB_SUSPENDM_BYPS_MASK 0x100000 +#define USB_REFCLK_MODE_SHIFT 0x17 +#define USB_REFCLK_MODE_MASK 0x800000 +#define USB_PLL_EN_SHIFT 0x16 +#define USB_PLL_EN_MASK 0x400000 +#define USB_PDRSTN_SPLIT_SHIFT 0x11 +#define USB_PDRSTN_SPLIT_MASK 0x20000 + +#define PCIE_CKREF_SRC_SHIFT 0x12 +#define PCIE_CKREF_SRC_MASK 0xC0000 +#define PCIE_CLK_SEL_SHIFT 0x14 +#define PCIE_CLK_SEL_MASK 0x300000 +#define PCIE_PHY_MODE_SHIFT 0x14 +#define PCIE_PHY_MODE_MASK 0x300000 +#define PCIE_USB3_BUS_WIDTH_SHIFT 0x2 +#define PCIE_USB3_BUS_WIDTH_MASK 0xC +#define PCIE_USB3_RATE_SHIFT 0x5 +#define PCIE_USB3_RATE_MASK 0x60 +#define PCIE_USB3_RX_STANDBY_SHIFT 0x7 +#define PCIE_USB3_RX_STANDBY_MASK 0x80 +#define PCIE_USB3_PHY_ENABLE_SHIFT 0x4 +#define PCIE_USB3_PHY_ENABLE_MASK 0x10 +#define PCIE_USB3_PHY_PLL_CTL_OFF (0x1f * 4) + +#define USB_125M_CLK_RATE 125000000 + +#define USB3_PHY_RES_INDEX 0 +#define USB2_PHY_RES_INDEX 1 +#define USB_LS_KEEPALIVE_OFF 0x4 +#define USB_LS_KEEPALIVE_ENABLE 4 + struct cdns_starfive { struct udevice *dev; struct clk_bulk clks; struct reset_ctl_bulk resets; + struct regmap *stg_map; + struct regmap *sys_map; + struct clk usb_125m_clk; + void __iomem *phy3_base; + void __iomem *phy2_base; + u32 sys_offset; + u32 stg_offset_4; + u32 stg_offset_196; + u32 stg_offset_328; + u32 stg_offset_500; + u32 usb2_only; + enum usb_dr_mode mode; }; -static int cdns_starfive_probe(struct udevice *dev) +static int cdns_mode_init(struct cdns_starfive *data) +{ + enum usb_dr_mode mode; + + /* Init usb 2.0 utmi phy */ + regmap_update_bits(data->stg_map, data->stg_offset_4, + USB_SUSPENDM_BYPS_MASK, BIT(USB_SUSPENDM_BYPS_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_4, + USB_PLL_EN_MASK, BIT(USB_PLL_EN_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_4, + USB_REFCLK_MODE_MASK, BIT(USB_REFCLK_MODE_SHIFT)); + + if (data->usb2_only) { + /* Disconnect usb 3.0 phy mode */ + regmap_update_bits(data->sys_map, data->sys_offset, + USB_PDRSTN_SPLIT_MASK, BIT(USB_PDRSTN_SPLIT_SHIFT)); + } else { + /* Config usb 3.0 pipe phy */ + regmap_update_bits(data->stg_map, data->stg_offset_196, + PCIE_CKREF_SRC_MASK, (0<stg_map, data->stg_offset_196, + PCIE_CLK_SEL_MASK, (0<stg_map, data->stg_offset_328, + PCIE_PHY_MODE_MASK, BIT(PCIE_PHY_MODE_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_500, + PCIE_USB3_BUS_WIDTH_MASK, (0 << PCIE_USB3_BUS_WIDTH_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_500, + PCIE_USB3_RATE_MASK, (0 << PCIE_USB3_RATE_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_500, + PCIE_USB3_RX_STANDBY_MASK, (0 << PCIE_USB3_RX_STANDBY_SHIFT)); + regmap_update_bits(data->stg_map, data->stg_offset_500, + PCIE_USB3_PHY_ENABLE_MASK, BIT(PCIE_USB3_PHY_ENABLE_SHIFT)); + + /* Connect usb 3.0 phy mode */ + regmap_update_bits(data->sys_map, data->sys_offset, + USB_PDRSTN_SPLIT_MASK, (0 << USB_PDRSTN_SPLIT_SHIFT)); + } + + mode = usb_get_dr_mode(dev_read_first_subnode(data->dev)); + data->mode = mode; + + switch (mode) { + case USB_DR_MODE_HOST: + regmap_update_bits(data->stg_map, + data->stg_offset_4, + USB_STRAP_MASK, + USB_STRAP_HOST); + regmap_update_bits(data->stg_map, + data->stg_offset_4, + USB_SUSPENDM_MASK, + USB_SUSPENDM_HOST); + break; + + case USB_DR_MODE_PERIPHERAL: + regmap_update_bits(data->stg_map, data->stg_offset_4, + USB_STRAP_MASK, USB_STRAP_DEVICE); + regmap_update_bits(data->stg_map, data->stg_offset_4, + USB_SUSPENDM_MASK, USB_SUSPENDM_DEVICE); + break; + + case USB_DR_MODE_UNKNOWN: + case USB_DR_MODE_OTG: + default: + break; + } + + return 0; +} + +static int cdns_clk_rst_init(struct cdns_starfive *data) { - struct cdns_starfive *data = dev_get_plat(dev); int ret; - data->dev = dev; + ret = clk_get_by_name(data->dev, "125m", &data->usb_125m_clk); + if (ret) + goto exit; - ret = clk_get_bulk(dev, &data->clks); + ret = clk_get_bulk(data->dev, &data->clks); if (ret) - goto err; + goto err_125m_clk; - ret = reset_get_bulk(dev, &data->resets); + ret = reset_get_bulk(data->dev, &data->resets); if (ret) goto err_clk; + /* Needs to set the USB_125M clock explicitly, + * since it's divided from pll0 clock, and the pll0 clock + * changes per the cpu frequency. + */ + ret = clk_set_rate(&data->usb_125m_clk, USB_125M_CLK_RATE); + if (!ret) + goto err_en_clk; + ret = clk_enable_bulk(&data->clks); if (ret) - goto err_reset; + goto err_en_clk; ret = reset_deassert_bulk(&data->resets); if (ret) goto err_reset; return 0; + err_reset: + clk_disable_bulk(&data->clks); +err_en_clk: reset_release_bulk(&data->resets); err_clk: clk_release_bulk(&data->clks); -err: +err_125m_clk: + clk_free(&data->usb_125m_clk); +exit: + return ret; +} + +static void cdns_starfive_set_phy(struct cdns_starfive *data) +{ + unsigned int val; + void __iomem *addr; + + if (data->mode != USB_DR_MODE_PERIPHERAL) { + /* Enable the LS speed keep-alive signal */ + addr = data->phy2_base + USB_LS_KEEPALIVE_OFF; + val = readl(addr); + val |= BIT(USB_LS_KEEPALIVE_ENABLE); + writel(val, addr); + } + + if (!data->usb2_only) { + addr = data->phy3_base + PCIE_USB3_PHY_PLL_CTL_OFF; + /* Configuare spread-spectrum mode: down-spread-spectrum */ + writel(BIT(4), addr); + } +} + +static int cdns_starfive_probe(struct udevice *dev) +{ + struct cdns_starfive *data = dev_get_plat(dev); + struct ofnode_phandle_args args; + int ret; + + data->dev = dev; + data->phy3_base = (void *)dev_read_addr_index(dev, USB3_PHY_RES_INDEX); + if (data->phy3_base == (void __iomem *)FDT_ADDR_T_NONE) { + dev_err(dev, "Missing phy 3.0 reg base\n"); + return -EINVAL; + } + + data->phy2_base = (void *)dev_read_addr_index(dev, USB2_PHY_RES_INDEX); + if (data->phy2_base == (void __iomem *)FDT_ADDR_T_NONE) { + dev_err(dev, "Missing phy 2.0 reg base"); + return -EINVAL; + } + + data->usb2_only = dev_read_bool(dev, "starfive,usb2-only"); + + ret = dev_read_phandle_with_args(dev, "starfive,stg-syscon", NULL, 4, 0, &args); + if (ret) + return ret; + + data->stg_map = syscon_node_to_regmap(args.node); + if (IS_ERR(data->stg_map)) + return PTR_ERR(data->stg_map); + + data->stg_offset_4 = args.args[0]; + data->stg_offset_196 = args.args[1]; + data->stg_offset_328 = args.args[2]; + data->stg_offset_500 = args.args[3]; + + ret = dev_read_phandle_with_args(dev, "starfive,sys-syscon", NULL, 1, 0, &args); + if (ret) + return ret; + + data->sys_map = syscon_node_to_regmap(args.node); + if (IS_ERR(data->sys_map)) + return PTR_ERR(data->sys_map); + data->sys_offset = args.args[0]; + + cdns_mode_init(data); + + ret = cdns_clk_rst_init(data); + if (ret < 0) { + pr_err("Failed to init usb clk reset: %d\n", ret); + return ret; + } + cdns_starfive_set_phy(data); + return ret; } @@ -58,7 +271,8 @@ static int cdns_starfive_remove(struct udevice *dev) struct cdns_starfive *data = dev_get_plat(dev); clk_release_bulk(&data->clks); -// reset_assert_bulk(&data->resets); + reset_assert_bulk(&data->resets); + clk_free(&data->usb_125m_clk); return 0; } -- cgit v1.2.3 From f64678cdc6e51d09c9a7de1a04c011a6be8eec27 Mon Sep 17 00:00:00 2001 From: Yanhong Wang Date: Fri, 19 May 2023 17:08:54 +0800 Subject: dts: starfive: devkits: Update usb device tree node Updated USB Device Tree Node to support USB Device functionality and is consistent with Kernel. Signed-off-by: Yanhong Wang Signed-off-by: Minda Chen --- arch/riscv/dts/jh7110.dtsi | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi index e353aeb25b..1022a08db5 100644 --- a/arch/riscv/dts/jh7110.dtsi +++ b/arch/riscv/dts/jh7110.dtsi @@ -354,21 +354,25 @@ usbdrd30: usbdrd{ compatible = "starfive,jh7110-cdns3"; + dma-coherent; #address-cells = <2>; #size-cells = <2>; - clocks = <&clkgen JH7110_USB0_CLK_APP_125>, + reg = <0x0 0x10210000 0x0 0x1000>, + <0x0 0x10200000 0x0 0x1000>; + clocks = <&clkgen JH7110_USB_125M>, + <&clkgen JH7110_USB0_CLK_APP_125>, <&clkgen JH7110_USB0_CLK_LPM>, <&clkgen JH7110_USB0_CLK_STB>, <&clkgen JH7110_USB0_CLK_USB_APB>, <&clkgen JH7110_USB0_CLK_AXI>, <&clkgen JH7110_USB0_CLK_UTMI_APB>; - clock-names = "app","lpm","stb","apb","axi","utmi"; + clock-names = "125m","app","lpm","stb","apb","axi","utmi"; resets = <&rstgen RSTN_U0_CDN_USB_PWRUP>, <&rstgen RSTN_U0_CDN_USB_APB>, <&rstgen RSTN_U0_CDN_USB_AXI>, <&rstgen RSTN_U0_CDN_USB_UTMI_APB>; reset-names = "pwrup","apb","axi","utmi"; - starfive,stg-syscon = <&stg_syscon 0x4>; + starfive,stg-syscon = <&stg_syscon 0x4 0xc4 0x148 0x1f4>; starfive,sys-syscon = <&sys_syscon 0x18>; status = "disabled"; @@ -378,7 +382,7 @@ <0x0 0x10110000 0x0 0x10000>, <0x0 0x10120000 0x0 0x10000>; reg-names = "otg", "xhci", "dev"; - interrupts = <108>, <109>, <110>; + interrupts = <100>, <108>, <110>; interrupt-names = "host", "peripheral", "otg"; phy-names = "cdns3,usb3-phy", "cnds3,usb2-phy"; maximum-speed = "super-speed"; -- cgit v1.2.3 From 37cf2331abec749f33deaefe30c31d266b62d076 Mon Sep 17 00:00:00 2001 From: Minda Chen Date: Fri, 25 Aug 2023 16:16:19 +0800 Subject: dts: usb: Add USB 3.0 clock dts. Add evb USB 3.0 clock dts. Signed-off-by: Minda Chen --- arch/riscv/dts/starfive_evb.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/riscv/dts/starfive_evb.dts b/arch/riscv/dts/starfive_evb.dts index 19b8e5f1e0..0ce86ad8bd 100644 --- a/arch/riscv/dts/starfive_evb.dts +++ b/arch/riscv/dts/starfive_evb.dts @@ -297,6 +297,21 @@ }; &usbdrd30 { + clocks = <&clkgen JH7110_USB_125M>, + <&clkgen JH7110_USB0_CLK_APP_125>, + <&clkgen JH7110_USB0_CLK_LPM>, + <&clkgen JH7110_USB0_CLK_STB>, + <&clkgen JH7110_USB0_CLK_USB_APB>, + <&clkgen JH7110_USB0_CLK_AXI>, + <&clkgen JH7110_USB0_CLK_UTMI_APB>, + <&clkgen JH7110_PCIE0_CLK_APB>; + clock-names = "125m","app","lpm","stb","apb","axi","utmi", "phy"; + resets = <&rstgen RSTN_U0_CDN_USB_PWRUP>, + <&rstgen RSTN_U0_CDN_USB_APB>, + <&rstgen RSTN_U0_CDN_USB_AXI>, + <&rstgen RSTN_U0_CDN_USB_UTMI_APB>, + <&rstgen RSTN_U0_PLDA_PCIE_APB>; + reset-names = "pwrup","apb","axi","utmi", "phy"; status = "okay"; }; -- cgit v1.2.3