Parcourir la source

Merge tag 'JH7110_515_SDK_v5.7.0' into vf2-devel

Andy Hu il y a 9 mois
Parent
commit
a987443e92

+ 8 - 4
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";

+ 15 - 0
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";
 };
 

+ 223 - 9
drivers/usb/cdns3/cdns3-starfive.c

@@ -6,50 +6,263 @@
  * Author:	yanhong <yanhong.wang@starfivetech.com>
  */
 
+#include <asm/io.h>
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <linux/usb/otg.h>
 #include <reset.h>
+#include <regmap.h>
+#include <syscon.h>
 
 #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<<PCIE_CKREF_SRC_SHIFT));
+		regmap_update_bits(data->stg_map, data->stg_offset_196,
+			PCIE_CLK_SEL_MASK, (0<<PCIE_CLK_SEL_SHIFT));
+		regmap_update_bits(data->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;
 }

+ 6 - 4
drivers/usb/cdns3/gadget.c

@@ -1569,15 +1569,17 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
 	case USB_ENDPOINT_XFER_INT:
 		ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT);
 
-		if ((priv_dev->dev_ver == DEV_VER_V2 && !priv_ep->dir) ||
-		    priv_dev->dev_ver > DEV_VER_V2)
+		if ((priv_dev->gadget.speed >= USB_SPEED_SUPER) &&
+			((priv_dev->dev_ver == DEV_VER_V2  && !priv_ep->dir) ||
+			priv_dev->dev_ver > DEV_VER_V2))
 			ep_cfg |= EP_CFG_TDL_CHK;
 		break;
 	case USB_ENDPOINT_XFER_BULK:
 		ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK);
 
-		if ((priv_dev->dev_ver == DEV_VER_V2  && !priv_ep->dir) ||
-		    priv_dev->dev_ver > DEV_VER_V2)
+		if ((priv_dev->gadget.speed >= USB_SPEED_SUPER) &&
+			((priv_dev->dev_ver == DEV_VER_V2  && !priv_ep->dir) ||
+			priv_dev->dev_ver > DEV_VER_V2))
 			ep_cfg |= EP_CFG_TDL_CHK;
 		break;
 	default: