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, ®);
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