xref: /linux/drivers/phy/amlogic/phy-meson8b-usb2.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
13c910ecbSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20b56e9a7SVivek Gautam /*
34a3449d1SMartin Blumenstingl  * Meson8, Meson8b and GXBB USB2 PHY driver
40b56e9a7SVivek Gautam  *
50b56e9a7SVivek Gautam  * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
60b56e9a7SVivek Gautam  */
70b56e9a7SVivek Gautam 
80b56e9a7SVivek Gautam #include <linux/clk.h>
90b56e9a7SVivek Gautam #include <linux/delay.h>
100b56e9a7SVivek Gautam #include <linux/io.h>
11*7559e757SRob Herring #include <linux/mod_devicetable.h>
120b56e9a7SVivek Gautam #include <linux/module.h>
136b99262fSMartin Blumenstingl #include <linux/property.h>
14de143a40SMartin Blumenstingl #include <linux/regmap.h>
150b56e9a7SVivek Gautam #include <linux/reset.h>
160b56e9a7SVivek Gautam #include <linux/phy/phy.h>
170b56e9a7SVivek Gautam #include <linux/platform_device.h>
180b56e9a7SVivek Gautam #include <linux/usb/of.h>
190b56e9a7SVivek Gautam 
200b56e9a7SVivek Gautam #define REG_CONFIG					0x00
210b56e9a7SVivek Gautam 	#define REG_CONFIG_CLK_EN			BIT(0)
220b56e9a7SVivek Gautam 	#define REG_CONFIG_CLK_SEL_MASK			GENMASK(3, 1)
230b56e9a7SVivek Gautam 	#define REG_CONFIG_CLK_DIV_MASK			GENMASK(10, 4)
240b56e9a7SVivek Gautam 	#define REG_CONFIG_CLK_32k_ALTSEL		BIT(15)
250b56e9a7SVivek Gautam 	#define REG_CONFIG_TEST_TRIG			BIT(31)
260b56e9a7SVivek Gautam 
270b56e9a7SVivek Gautam #define REG_CTRL					0x04
280b56e9a7SVivek Gautam 	#define REG_CTRL_SOFT_PRST			BIT(0)
290b56e9a7SVivek Gautam 	#define REG_CTRL_SOFT_HRESET			BIT(1)
300b56e9a7SVivek Gautam 	#define REG_CTRL_SS_SCALEDOWN_MODE_MASK		GENMASK(3, 2)
310b56e9a7SVivek Gautam 	#define REG_CTRL_CLK_DET_RST			BIT(4)
320b56e9a7SVivek Gautam 	#define REG_CTRL_INTR_SEL			BIT(5)
330b56e9a7SVivek Gautam 	#define REG_CTRL_CLK_DETECTED			BIT(8)
340b56e9a7SVivek Gautam 	#define REG_CTRL_SOF_SENT_RCVD_TGL		BIT(9)
350b56e9a7SVivek Gautam 	#define REG_CTRL_SOF_TOGGLE_OUT			BIT(10)
360b56e9a7SVivek Gautam 	#define REG_CTRL_POWER_ON_RESET			BIT(15)
370b56e9a7SVivek Gautam 	#define REG_CTRL_SLEEPM				BIT(16)
380b56e9a7SVivek Gautam 	#define REG_CTRL_TX_BITSTUFF_ENN_H		BIT(17)
390b56e9a7SVivek Gautam 	#define REG_CTRL_TX_BITSTUFF_ENN		BIT(18)
400b56e9a7SVivek Gautam 	#define REG_CTRL_COMMON_ON			BIT(19)
410b56e9a7SVivek Gautam 	#define REG_CTRL_REF_CLK_SEL_MASK		GENMASK(21, 20)
420b56e9a7SVivek Gautam 	#define REG_CTRL_REF_CLK_SEL_SHIFT		20
430b56e9a7SVivek Gautam 	#define REG_CTRL_FSEL_MASK			GENMASK(24, 22)
440b56e9a7SVivek Gautam 	#define REG_CTRL_FSEL_SHIFT			22
450b56e9a7SVivek Gautam 	#define REG_CTRL_PORT_RESET			BIT(25)
460b56e9a7SVivek Gautam 	#define REG_CTRL_THREAD_ID_MASK			GENMASK(31, 26)
470b56e9a7SVivek Gautam 
480b56e9a7SVivek Gautam #define REG_ENDP_INTR					0x08
490b56e9a7SVivek Gautam 
500b56e9a7SVivek Gautam /* bits [31:26], [24:21] and [15:3] seem to be read-only */
510b56e9a7SVivek Gautam #define REG_ADP_BC					0x0c
520b56e9a7SVivek Gautam 	#define REG_ADP_BC_VBUS_VLD_EXT_SEL		BIT(0)
530b56e9a7SVivek Gautam 	#define REG_ADP_BC_VBUS_VLD_EXT			BIT(1)
540b56e9a7SVivek Gautam 	#define REG_ADP_BC_OTG_DISABLE			BIT(2)
550b56e9a7SVivek Gautam 	#define REG_ADP_BC_ID_PULLUP			BIT(3)
560b56e9a7SVivek Gautam 	#define REG_ADP_BC_DRV_VBUS			BIT(4)
570b56e9a7SVivek Gautam 	#define REG_ADP_BC_ADP_PRB_EN			BIT(5)
580b56e9a7SVivek Gautam 	#define REG_ADP_BC_ADP_DISCHARGE		BIT(6)
590b56e9a7SVivek Gautam 	#define REG_ADP_BC_ADP_CHARGE			BIT(7)
600b56e9a7SVivek Gautam 	#define REG_ADP_BC_SESS_END			BIT(8)
610b56e9a7SVivek Gautam 	#define REG_ADP_BC_DEVICE_SESS_VLD		BIT(9)
620b56e9a7SVivek Gautam 	#define REG_ADP_BC_B_VALID			BIT(10)
630b56e9a7SVivek Gautam 	#define REG_ADP_BC_A_VALID			BIT(11)
640b56e9a7SVivek Gautam 	#define REG_ADP_BC_ID_DIG			BIT(12)
650b56e9a7SVivek Gautam 	#define REG_ADP_BC_VBUS_VALID			BIT(13)
660b56e9a7SVivek Gautam 	#define REG_ADP_BC_ADP_PROBE			BIT(14)
670b56e9a7SVivek Gautam 	#define REG_ADP_BC_ADP_SENSE			BIT(15)
680b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_ENABLE			BIT(16)
690b56e9a7SVivek Gautam 	#define REG_ADP_BC_DCD_ENABLE			BIT(17)
700b56e9a7SVivek Gautam 	#define REG_ADP_BC_VDAT_DET_EN_B		BIT(18)
710b56e9a7SVivek Gautam 	#define REG_ADP_BC_VDAT_SRC_EN_B		BIT(19)
720b56e9a7SVivek Gautam 	#define REG_ADP_BC_CHARGE_SEL			BIT(20)
730b56e9a7SVivek Gautam 	#define REG_ADP_BC_CHARGE_DETECT		BIT(21)
740b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_PIN_RANGE_C		BIT(22)
750b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_PIN_RANGE_B		BIT(23)
760b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_PIN_RANGE_A		BIT(24)
770b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_PIN_GND			BIT(25)
780b56e9a7SVivek Gautam 	#define REG_ADP_BC_ACA_PIN_FLOAT		BIT(26)
790b56e9a7SVivek Gautam 
800b56e9a7SVivek Gautam #define REG_DBG_UART					0x10
817cafc017SMartin Blumenstingl 	#define REG_DBG_UART_BYPASS_SEL			BIT(0)
827cafc017SMartin Blumenstingl 	#define REG_DBG_UART_BYPASS_DM_EN		BIT(1)
837cafc017SMartin Blumenstingl 	#define REG_DBG_UART_BYPASS_DP_EN		BIT(2)
847cafc017SMartin Blumenstingl 	#define REG_DBG_UART_BYPASS_DM_DATA		BIT(3)
857cafc017SMartin Blumenstingl 	#define REG_DBG_UART_BYPASS_DP_DATA		BIT(4)
867cafc017SMartin Blumenstingl 	#define REG_DBG_UART_FSV_MINUS			BIT(5)
877cafc017SMartin Blumenstingl 	#define REG_DBG_UART_FSV_PLUS			BIT(6)
887cafc017SMartin Blumenstingl 	#define REG_DBG_UART_FSV_BURN_IN_TEST		BIT(7)
897cafc017SMartin Blumenstingl 	#define REG_DBG_UART_LOOPBACK_EN_B		BIT(8)
907cafc017SMartin Blumenstingl 	#define REG_DBG_UART_SET_IDDQ			BIT(9)
917cafc017SMartin Blumenstingl 	#define REG_DBG_UART_ATE_RESET			BIT(10)
920b56e9a7SVivek Gautam 
930b56e9a7SVivek Gautam #define REG_TEST					0x14
940b56e9a7SVivek Gautam 	#define REG_TEST_DATA_IN_MASK			GENMASK(3, 0)
950b56e9a7SVivek Gautam 	#define REG_TEST_EN_MASK			GENMASK(7, 4)
960b56e9a7SVivek Gautam 	#define REG_TEST_ADDR_MASK			GENMASK(11, 8)
970b56e9a7SVivek Gautam 	#define REG_TEST_DATA_OUT_SEL			BIT(12)
980b56e9a7SVivek Gautam 	#define REG_TEST_CLK				BIT(13)
990b56e9a7SVivek Gautam 	#define REG_TEST_VA_TEST_EN_B_MASK		GENMASK(15, 14)
1000b56e9a7SVivek Gautam 	#define REG_TEST_DATA_OUT_MASK			GENMASK(19, 16)
1010b56e9a7SVivek Gautam 	#define REG_TEST_DISABLE_ID_PULLUP		BIT(20)
1020b56e9a7SVivek Gautam 
1030b56e9a7SVivek Gautam #define REG_TUNE					0x18
1040b56e9a7SVivek Gautam 	#define REG_TUNE_TX_RES_TUNE_MASK		GENMASK(1, 0)
1050b56e9a7SVivek Gautam 	#define REG_TUNE_TX_HSXV_TUNE_MASK		GENMASK(3, 2)
1060b56e9a7SVivek Gautam 	#define REG_TUNE_TX_VREF_TUNE_MASK		GENMASK(7, 4)
1070b56e9a7SVivek Gautam 	#define REG_TUNE_TX_RISE_TUNE_MASK		GENMASK(9, 8)
1080b56e9a7SVivek Gautam 	#define REG_TUNE_TX_PREEMP_PULSE_TUNE		BIT(10)
1090b56e9a7SVivek Gautam 	#define REG_TUNE_TX_PREEMP_AMP_TUNE_MASK	GENMASK(12, 11)
1100b56e9a7SVivek Gautam 	#define REG_TUNE_TX_FSLS_TUNE_MASK		GENMASK(16, 13)
1110b56e9a7SVivek Gautam 	#define REG_TUNE_SQRX_TUNE_MASK			GENMASK(19, 17)
1120b56e9a7SVivek Gautam 	#define REG_TUNE_OTG_TUNE			GENMASK(22, 20)
1130b56e9a7SVivek Gautam 	#define REG_TUNE_COMP_DIS_TUNE			GENMASK(25, 23)
1140b56e9a7SVivek Gautam 	#define REG_TUNE_HOST_DM_PULLDOWN		BIT(26)
1150b56e9a7SVivek Gautam 	#define REG_TUNE_HOST_DP_PULLDOWN		BIT(27)
1160b56e9a7SVivek Gautam 
1170b56e9a7SVivek Gautam #define RESET_COMPLETE_TIME				500
1180b56e9a7SVivek Gautam #define ACA_ENABLE_COMPLETE_TIME			50
1190b56e9a7SVivek Gautam 
1206b99262fSMartin Blumenstingl struct phy_meson8b_usb2_match_data {
1216b99262fSMartin Blumenstingl 	bool			host_enable_aca;
1226b99262fSMartin Blumenstingl };
1236b99262fSMartin Blumenstingl 
1240b56e9a7SVivek Gautam struct phy_meson8b_usb2_priv {
125de143a40SMartin Blumenstingl 	struct regmap					*regmap;
1260b56e9a7SVivek Gautam 	enum usb_dr_mode				dr_mode;
1270b56e9a7SVivek Gautam 	struct clk					*clk_usb_general;
1280b56e9a7SVivek Gautam 	struct clk					*clk_usb;
1290b56e9a7SVivek Gautam 	struct reset_control				*reset;
1306b99262fSMartin Blumenstingl 	const struct phy_meson8b_usb2_match_data	*match;
1310b56e9a7SVivek Gautam };
1320b56e9a7SVivek Gautam 
133de143a40SMartin Blumenstingl static const struct regmap_config phy_meson8b_usb2_regmap_conf = {
134de143a40SMartin Blumenstingl 	.reg_bits = 8,
135de143a40SMartin Blumenstingl 	.val_bits = 32,
136de143a40SMartin Blumenstingl 	.reg_stride = 4,
137de143a40SMartin Blumenstingl 	.max_register = REG_TUNE,
138de143a40SMartin Blumenstingl };
1390b56e9a7SVivek Gautam 
phy_meson8b_usb2_power_on(struct phy * phy)1400b56e9a7SVivek Gautam static int phy_meson8b_usb2_power_on(struct phy *phy)
1410b56e9a7SVivek Gautam {
1420b56e9a7SVivek Gautam 	struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
143de143a40SMartin Blumenstingl 	u32 reg;
1440b56e9a7SVivek Gautam 	int ret;
1450b56e9a7SVivek Gautam 
1460b56e9a7SVivek Gautam 	if (!IS_ERR_OR_NULL(priv->reset)) {
1470b56e9a7SVivek Gautam 		ret = reset_control_reset(priv->reset);
1480b56e9a7SVivek Gautam 		if (ret) {
1490b56e9a7SVivek Gautam 			dev_err(&phy->dev, "Failed to trigger USB reset\n");
1500b56e9a7SVivek Gautam 			return ret;
1510b56e9a7SVivek Gautam 		}
1520b56e9a7SVivek Gautam 	}
1530b56e9a7SVivek Gautam 
1540b56e9a7SVivek Gautam 	ret = clk_prepare_enable(priv->clk_usb_general);
1550b56e9a7SVivek Gautam 	if (ret) {
1560b56e9a7SVivek Gautam 		dev_err(&phy->dev, "Failed to enable USB general clock\n");
1576f1dedf0SAmjad Ouled-Ameur 		reset_control_rearm(priv->reset);
1580b56e9a7SVivek Gautam 		return ret;
1590b56e9a7SVivek Gautam 	}
1600b56e9a7SVivek Gautam 
1610b56e9a7SVivek Gautam 	ret = clk_prepare_enable(priv->clk_usb);
1620b56e9a7SVivek Gautam 	if (ret) {
1630b56e9a7SVivek Gautam 		dev_err(&phy->dev, "Failed to enable USB DDR clock\n");
1640b56e9a7SVivek Gautam 		clk_disable_unprepare(priv->clk_usb_general);
1656f1dedf0SAmjad Ouled-Ameur 		reset_control_rearm(priv->reset);
1660b56e9a7SVivek Gautam 		return ret;
1670b56e9a7SVivek Gautam 	}
1680b56e9a7SVivek Gautam 
169de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL,
1700b56e9a7SVivek Gautam 			   REG_CONFIG_CLK_32k_ALTSEL);
1710b56e9a7SVivek Gautam 
172de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK,
1730b56e9a7SVivek Gautam 			   0x2 << REG_CTRL_REF_CLK_SEL_SHIFT);
1740b56e9a7SVivek Gautam 
175de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_FSEL_MASK,
1760b56e9a7SVivek Gautam 			   0x5 << REG_CTRL_FSEL_SHIFT);
1770b56e9a7SVivek Gautam 
1780b56e9a7SVivek Gautam 	/* reset the PHY */
179de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
1800b56e9a7SVivek Gautam 			   REG_CTRL_POWER_ON_RESET);
1810b56e9a7SVivek Gautam 	udelay(RESET_COMPLETE_TIME);
182de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0);
1830b56e9a7SVivek Gautam 	udelay(RESET_COMPLETE_TIME);
1840b56e9a7SVivek Gautam 
185de143a40SMartin Blumenstingl 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT,
1860b56e9a7SVivek Gautam 			   REG_CTRL_SOF_TOGGLE_OUT);
1870b56e9a7SVivek Gautam 
1887cafc017SMartin Blumenstingl 	if (priv->dr_mode == USB_DR_MODE_HOST) {
1897cafc017SMartin Blumenstingl 		regmap_update_bits(priv->regmap, REG_DBG_UART,
1907cafc017SMartin Blumenstingl 				   REG_DBG_UART_SET_IDDQ, 0);
1917cafc017SMartin Blumenstingl 
1927cafc017SMartin Blumenstingl 		if (priv->match->host_enable_aca) {
193de143a40SMartin Blumenstingl 			regmap_update_bits(priv->regmap, REG_ADP_BC,
1940b56e9a7SVivek Gautam 					   REG_ADP_BC_ACA_ENABLE,
1950b56e9a7SVivek Gautam 					   REG_ADP_BC_ACA_ENABLE);
1960b56e9a7SVivek Gautam 
1970b56e9a7SVivek Gautam 			udelay(ACA_ENABLE_COMPLETE_TIME);
1980b56e9a7SVivek Gautam 
199de143a40SMartin Blumenstingl 			regmap_read(priv->regmap, REG_ADP_BC, &reg);
200de143a40SMartin Blumenstingl 			if (reg & REG_ADP_BC_ACA_PIN_FLOAT) {
2010b56e9a7SVivek Gautam 				dev_warn(&phy->dev, "USB ID detect failed!\n");
2020b56e9a7SVivek Gautam 				clk_disable_unprepare(priv->clk_usb);
2030b56e9a7SVivek Gautam 				clk_disable_unprepare(priv->clk_usb_general);
2046f1dedf0SAmjad Ouled-Ameur 				reset_control_rearm(priv->reset);
2050b56e9a7SVivek Gautam 				return -EINVAL;
2060b56e9a7SVivek Gautam 			}
2070b56e9a7SVivek Gautam 		}
2087cafc017SMartin Blumenstingl 	}
2090b56e9a7SVivek Gautam 
2100b56e9a7SVivek Gautam 	return 0;
2110b56e9a7SVivek Gautam }
2120b56e9a7SVivek Gautam 
phy_meson8b_usb2_power_off(struct phy * phy)2130b56e9a7SVivek Gautam static int phy_meson8b_usb2_power_off(struct phy *phy)
2140b56e9a7SVivek Gautam {
2150b56e9a7SVivek Gautam 	struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy);
2160b56e9a7SVivek Gautam 
2177cafc017SMartin Blumenstingl 	if (priv->dr_mode == USB_DR_MODE_HOST)
2187cafc017SMartin Blumenstingl 		regmap_update_bits(priv->regmap, REG_DBG_UART,
2197cafc017SMartin Blumenstingl 				   REG_DBG_UART_SET_IDDQ,
2207cafc017SMartin Blumenstingl 				   REG_DBG_UART_SET_IDDQ);
2217cafc017SMartin Blumenstingl 
2220b56e9a7SVivek Gautam 	clk_disable_unprepare(priv->clk_usb);
2230b56e9a7SVivek Gautam 	clk_disable_unprepare(priv->clk_usb_general);
2246f1dedf0SAmjad Ouled-Ameur 	reset_control_rearm(priv->reset);
2250b56e9a7SVivek Gautam 
226e1f31c93SAnand Moon 	/* power off the PHY by putting it into reset mode */
227e1f31c93SAnand Moon 	regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET,
228e1f31c93SAnand Moon 			   REG_CTRL_POWER_ON_RESET);
229e1f31c93SAnand Moon 
2300b56e9a7SVivek Gautam 	return 0;
2310b56e9a7SVivek Gautam }
2320b56e9a7SVivek Gautam 
2330b56e9a7SVivek Gautam static const struct phy_ops phy_meson8b_usb2_ops = {
2340b56e9a7SVivek Gautam 	.power_on	= phy_meson8b_usb2_power_on,
2350b56e9a7SVivek Gautam 	.power_off	= phy_meson8b_usb2_power_off,
2360b56e9a7SVivek Gautam 	.owner		= THIS_MODULE,
2370b56e9a7SVivek Gautam };
2380b56e9a7SVivek Gautam 
phy_meson8b_usb2_probe(struct platform_device * pdev)2390b56e9a7SVivek Gautam static int phy_meson8b_usb2_probe(struct platform_device *pdev)
2400b56e9a7SVivek Gautam {
2410b56e9a7SVivek Gautam 	struct phy_meson8b_usb2_priv *priv;
2420b56e9a7SVivek Gautam 	struct phy *phy;
2430b56e9a7SVivek Gautam 	struct phy_provider *phy_provider;
244de143a40SMartin Blumenstingl 	void __iomem *base;
2450b56e9a7SVivek Gautam 
2460b56e9a7SVivek Gautam 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
2470b56e9a7SVivek Gautam 	if (!priv)
2480b56e9a7SVivek Gautam 		return -ENOMEM;
2490b56e9a7SVivek Gautam 
250de143a40SMartin Blumenstingl 	base = devm_platform_ioremap_resource(pdev, 0);
251de143a40SMartin Blumenstingl 	if (IS_ERR(base))
252de143a40SMartin Blumenstingl 		return PTR_ERR(base);
253de143a40SMartin Blumenstingl 
2546b99262fSMartin Blumenstingl 	priv->match = device_get_match_data(&pdev->dev);
2556b99262fSMartin Blumenstingl 	if (!priv->match)
2566b99262fSMartin Blumenstingl 		return -ENODEV;
2576b99262fSMartin Blumenstingl 
258de143a40SMartin Blumenstingl 	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
259de143a40SMartin Blumenstingl 					     &phy_meson8b_usb2_regmap_conf);
260de143a40SMartin Blumenstingl 	if (IS_ERR(priv->regmap))
261de143a40SMartin Blumenstingl 		return PTR_ERR(priv->regmap);
2620b56e9a7SVivek Gautam 
2630b56e9a7SVivek Gautam 	priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general");
2640b56e9a7SVivek Gautam 	if (IS_ERR(priv->clk_usb_general))
2650b56e9a7SVivek Gautam 		return PTR_ERR(priv->clk_usb_general);
2660b56e9a7SVivek Gautam 
2670b56e9a7SVivek Gautam 	priv->clk_usb = devm_clk_get(&pdev->dev, "usb");
2680b56e9a7SVivek Gautam 	if (IS_ERR(priv->clk_usb))
2690b56e9a7SVivek Gautam 		return PTR_ERR(priv->clk_usb);
2700b56e9a7SVivek Gautam 
2710b56e9a7SVivek Gautam 	priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
2726466ba18SAmjad Ouled-Ameur 	if (IS_ERR(priv->reset))
2736466ba18SAmjad Ouled-Ameur 		return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset),
2746466ba18SAmjad Ouled-Ameur 				     "Failed to get the reset line");
2750b56e9a7SVivek Gautam 
2760b56e9a7SVivek Gautam 	priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1);
2770b56e9a7SVivek Gautam 	if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
2780b56e9a7SVivek Gautam 		dev_err(&pdev->dev,
2790b56e9a7SVivek Gautam 			"missing dual role configuration of the controller\n");
2800b56e9a7SVivek Gautam 		return -EINVAL;
2810b56e9a7SVivek Gautam 	}
2820b56e9a7SVivek Gautam 
2830b56e9a7SVivek Gautam 	phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops);
2840b56e9a7SVivek Gautam 	if (IS_ERR(phy)) {
285c7c40243SAnand Moon 		return dev_err_probe(&pdev->dev, PTR_ERR(phy),
286c7c40243SAnand Moon 				     "failed to create PHY\n");
2870b56e9a7SVivek Gautam 	}
2880b56e9a7SVivek Gautam 
2890b56e9a7SVivek Gautam 	phy_set_drvdata(phy, priv);
2900b56e9a7SVivek Gautam 
2910b56e9a7SVivek Gautam 	phy_provider =
2920b56e9a7SVivek Gautam 		devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
2930b56e9a7SVivek Gautam 
2940b56e9a7SVivek Gautam 	return PTR_ERR_OR_ZERO(phy_provider);
2950b56e9a7SVivek Gautam }
2960b56e9a7SVivek Gautam 
2976b99262fSMartin Blumenstingl static const struct phy_meson8b_usb2_match_data phy_meson8_usb2_match_data = {
2986b99262fSMartin Blumenstingl 	.host_enable_aca = false,
2996b99262fSMartin Blumenstingl };
3006b99262fSMartin Blumenstingl 
3016b99262fSMartin Blumenstingl static const struct phy_meson8b_usb2_match_data phy_meson8b_usb2_match_data = {
3026b99262fSMartin Blumenstingl 	.host_enable_aca = true,
3036b99262fSMartin Blumenstingl };
3046b99262fSMartin Blumenstingl 
3050b56e9a7SVivek Gautam static const struct of_device_id phy_meson8b_usb2_of_match[] = {
3066b99262fSMartin Blumenstingl 	{
3076b99262fSMartin Blumenstingl 		.compatible = "amlogic,meson8-usb2-phy",
3086b99262fSMartin Blumenstingl 		.data = &phy_meson8_usb2_match_data
3096b99262fSMartin Blumenstingl 	},
3106b99262fSMartin Blumenstingl 	{
3116b99262fSMartin Blumenstingl 		.compatible = "amlogic,meson8b-usb2-phy",
3126b99262fSMartin Blumenstingl 		.data = &phy_meson8b_usb2_match_data
3136b99262fSMartin Blumenstingl 	},
3146b99262fSMartin Blumenstingl 	{
315f004be59SMartin Blumenstingl 		.compatible = "amlogic,meson8m2-usb2-phy",
316f004be59SMartin Blumenstingl 		.data = &phy_meson8b_usb2_match_data
317f004be59SMartin Blumenstingl 	},
318f004be59SMartin Blumenstingl 	{
3196b99262fSMartin Blumenstingl 		.compatible = "amlogic,meson-gxbb-usb2-phy",
3206b99262fSMartin Blumenstingl 		.data = &phy_meson8b_usb2_match_data
3216b99262fSMartin Blumenstingl 	},
3226b99262fSMartin Blumenstingl 	{ /* sentinel */ }
3230b56e9a7SVivek Gautam };
3240b56e9a7SVivek Gautam MODULE_DEVICE_TABLE(of, phy_meson8b_usb2_of_match);
3250b56e9a7SVivek Gautam 
3260b56e9a7SVivek Gautam static struct platform_driver phy_meson8b_usb2_driver = {
3270b56e9a7SVivek Gautam 	.probe	= phy_meson8b_usb2_probe,
3280b56e9a7SVivek Gautam 	.driver	= {
3290b56e9a7SVivek Gautam 		.name		= "phy-meson-usb2",
3300b56e9a7SVivek Gautam 		.of_match_table	= phy_meson8b_usb2_of_match,
3310b56e9a7SVivek Gautam 	},
3320b56e9a7SVivek Gautam };
3330b56e9a7SVivek Gautam module_platform_driver(phy_meson8b_usb2_driver);
3340b56e9a7SVivek Gautam 
3350b56e9a7SVivek Gautam MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
336f004be59SMartin Blumenstingl MODULE_DESCRIPTION("Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY driver");
3370b56e9a7SVivek Gautam MODULE_LICENSE("GPL");
338