xref: /openbmc/u-boot/drivers/phy/meson-gxl-usb3.c (revision d35812368a590ebe1a5c92199a1a57ce3e80722e)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * Meson GXL USB3 PHY driver
4   *
5   * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
6   * Copyright (C) 2018 BayLibre, SAS
7   * Author: Neil Armstrong <narmstron@baylibre.com>
8   */
9  
10  #include <common.h>
11  #include <asm/io.h>
12  #include <bitfield.h>
13  #include <dm.h>
14  #include <errno.h>
15  #include <generic-phy.h>
16  #include <regmap.h>
17  #include <clk.h>
18  
19  #include <linux/bitops.h>
20  #include <linux/compat.h>
21  #include <linux/bitfield.h>
22  
23  #define USB_R0							0x00
24  	#define USB_R0_P30_FSEL_MASK				GENMASK(5, 0)
25  	#define USB_R0_P30_PHY_RESET				BIT(6)
26  	#define USB_R0_P30_TEST_POWERDOWN_HSP			BIT(7)
27  	#define USB_R0_P30_TEST_POWERDOWN_SSP			BIT(8)
28  	#define USB_R0_P30_ACJT_LEVEL_MASK			GENMASK(13, 9)
29  	#define USB_R0_P30_TX_BOOST_LEVEL_MASK			GENMASK(16, 14)
30  	#define USB_R0_P30_LANE0_TX2RX_LOOPBACK			BIT(17)
31  	#define USB_R0_P30_LANE0_EXT_PCLK_REQ			BIT(18)
32  	#define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK		GENMASK(28, 19)
33  	#define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK		GENMASK(30, 29)
34  	#define USB_R0_U2D_ACT					BIT(31)
35  
36  #define USB_R1							0x04
37  	#define USB_R1_U3H_BIGENDIAN_GS				BIT(0)
38  	#define USB_R1_U3H_PME_ENABLE				BIT(1)
39  	#define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK		GENMASK(6, 2)
40  	#define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK		GENMASK(11, 7)
41  	#define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK		GENMASK(15, 12)
42  	#define USB_R1_U3H_HOST_U3_PORT_DISABLE			BIT(16)
43  	#define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT	BIT(17)
44  	#define USB_R1_U3H_HOST_MSI_ENABLE			BIT(18)
45  	#define USB_R1_U3H_FLADJ_30MHZ_REG_MASK			GENMASK(24, 19)
46  	#define USB_R1_P30_PCS_TX_SWING_FULL_MASK		GENMASK(31, 25)
47  
48  #define USB_R2							0x08
49  	#define USB_R2_P30_CR_DATA_IN_MASK			GENMASK(15, 0)
50  	#define USB_R2_P30_CR_READ				BIT(16)
51  	#define USB_R2_P30_CR_WRITE				BIT(17)
52  	#define USB_R2_P30_CR_CAP_ADDR				BIT(18)
53  	#define USB_R2_P30_CR_CAP_DATA				BIT(19)
54  	#define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK		GENMASK(25, 20)
55  	#define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK		GENMASK(31, 26)
56  
57  #define USB_R3							0x0c
58  	#define USB_R3_P30_SSC_ENABLE				BIT(0)
59  	#define USB_R3_P30_SSC_RANGE_MASK			GENMASK(3, 1)
60  	#define USB_R3_P30_SSC_REF_CLK_SEL_MASK			GENMASK(12, 4)
61  	#define USB_R3_P30_REF_SSP_EN				BIT(13)
62  	#define USB_R3_P30_LOS_BIAS_MASK			GENMASK(18, 16)
63  	#define USB_R3_P30_LOS_LEVEL_MASK			GENMASK(23, 19)
64  	#define USB_R3_P30_MPLL_MULTIPLIER_MASK			GENMASK(30, 24)
65  
66  #define USB_R4							0x10
67  	#define USB_R4_P21_PORT_RESET_0				BIT(0)
68  	#define USB_R4_P21_SLEEP_M0				BIT(1)
69  	#define USB_R4_MEM_PD_MASK				GENMASK(3, 2)
70  	#define USB_R4_P21_ONLY					BIT(4)
71  
72  #define USB_R5							0x14
73  	#define USB_R5_ID_DIG_SYNC				BIT(0)
74  	#define USB_R5_ID_DIG_REG				BIT(1)
75  	#define USB_R5_ID_DIG_CFG_MASK				GENMASK(3, 2)
76  	#define USB_R5_ID_DIG_EN_0				BIT(4)
77  	#define USB_R5_ID_DIG_EN_1				BIT(5)
78  	#define USB_R5_ID_DIG_CURR				BIT(6)
79  	#define USB_R5_ID_DIG_IRQ				BIT(7)
80  	#define USB_R5_ID_DIG_TH_MASK				GENMASK(15, 8)
81  	#define USB_R5_ID_DIG_CNT_MASK				GENMASK(23, 16)
82  
83  /* read-only register */
84  #define USB_R6							0x18
85  	#define USB_R6_P30_CR_DATA_OUT_MASK			GENMASK(15, 0)
86  	#define USB_R6_P30_CR_ACK				BIT(16)
87  
88  struct phy_meson_gxl_usb3_priv {
89  	struct regmap		*regmap;
90  #if CONFIG_IS_ENABLED(CLK)
91  	struct clk		clk;
92  #endif
93  };
94  
95  static int
phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv * priv)96  phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv)
97  {
98  	uint val;
99  
100  	regmap_read(priv->regmap, USB_R0, &val);
101  	val &= ~USB_R0_U2D_ACT;
102  	regmap_write(priv->regmap, USB_R0, val);
103  
104  	regmap_read(priv->regmap, USB_R4, &val);
105  	val &= ~USB_R4_P21_SLEEP_M0;
106  	regmap_write(priv->regmap, USB_R4, val);
107  
108  	return 0;
109  }
110  
phy_meson_gxl_usb3_power_on(struct phy * phy)111  static int phy_meson_gxl_usb3_power_on(struct phy *phy)
112  {
113  	struct udevice *dev = phy->dev;
114  	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
115  	uint val;
116  
117  	regmap_read(priv->regmap, USB_R5, &val);
118  	val |= USB_R5_ID_DIG_EN_0;
119  	val |= USB_R5_ID_DIG_EN_1;
120  	val &= ~USB_R5_ID_DIG_TH_MASK;
121  	val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff);
122  	regmap_write(priv->regmap, USB_R5, val);
123  
124  	return phy_meson_gxl_usb3_set_host_mode(priv);
125  }
126  
phy_meson_gxl_usb3_power_off(struct phy * phy)127  static int phy_meson_gxl_usb3_power_off(struct phy *phy)
128  {
129  	struct udevice *dev = phy->dev;
130  	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
131  	uint val;
132  
133  	regmap_read(priv->regmap, USB_R5, &val);
134  	val &= ~USB_R5_ID_DIG_EN_0;
135  	val &= ~USB_R5_ID_DIG_EN_1;
136  	regmap_write(priv->regmap, USB_R5, val);
137  
138  	return 0;
139  }
140  
phy_meson_gxl_usb3_init(struct phy * phy)141  static int phy_meson_gxl_usb3_init(struct phy *phy)
142  {
143  	struct udevice *dev = phy->dev;
144  	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
145  	uint val;
146  
147  	regmap_read(priv->regmap, USB_R1, &val);
148  	val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK;
149  	val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20);
150  	regmap_write(priv->regmap, USB_R1, val);
151  
152  	return 0;
153  }
154  
155  struct phy_ops meson_gxl_usb3_phy_ops = {
156  	.init = phy_meson_gxl_usb3_init,
157  	.power_on = phy_meson_gxl_usb3_power_on,
158  	.power_off = phy_meson_gxl_usb3_power_off,
159  };
160  
meson_gxl_usb3_phy_probe(struct udevice * dev)161  int meson_gxl_usb3_phy_probe(struct udevice *dev)
162  {
163  	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
164  	int ret;
165  
166  	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
167  	if (ret)
168  		return ret;
169  
170  #if CONFIG_IS_ENABLED(CLK)
171  	ret = clk_get_by_index(dev, 0, &priv->clk);
172  	if (ret < 0)
173  		return ret;
174  
175  	ret = clk_enable(&priv->clk);
176  	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
177  		pr_err("failed to enable PHY clock\n");
178  		clk_free(&priv->clk);
179  		return ret;
180  	}
181  #endif
182  
183  	return 0;
184  }
185  
186  static const struct udevice_id meson_gxl_usb3_phy_ids[] = {
187  	{ .compatible = "amlogic,meson-gxl-usb3-phy" },
188  	{ }
189  };
190  
191  U_BOOT_DRIVER(meson_gxl_usb3_phy) = {
192  	.name = "meson_gxl_usb3_phy",
193  	.id = UCLASS_PHY,
194  	.of_match = meson_gxl_usb3_phy_ids,
195  	.probe = meson_gxl_usb3_phy_probe,
196  	.ops = &meson_gxl_usb3_phy_ops,
197  	.priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv),
198  };
199