162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Meson G12A USB2 PHY driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
662306a36Sopenharmony_ci * Copyright (C) 2017 Amlogic, Inc. All rights reserved
762306a36Sopenharmony_ci * Copyright (C) 2019 BayLibre, SAS
862306a36Sopenharmony_ci * Author: Neil Armstrong <narmstrong@baylibre.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/bitfield.h>
1262306a36Sopenharmony_ci#include <linux/bitops.h>
1362306a36Sopenharmony_ci#include <linux/clk.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/io.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/of.h>
1862306a36Sopenharmony_ci#include <linux/regmap.h>
1962306a36Sopenharmony_ci#include <linux/reset.h>
2062306a36Sopenharmony_ci#include <linux/phy/phy.h>
2162306a36Sopenharmony_ci#include <linux/platform_device.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define PHY_CTRL_R0						0x0
2462306a36Sopenharmony_ci#define PHY_CTRL_R1						0x4
2562306a36Sopenharmony_ci#define PHY_CTRL_R2						0x8
2662306a36Sopenharmony_ci#define PHY_CTRL_R3						0xc
2762306a36Sopenharmony_ci	#define PHY_CTRL_R3_SQUELCH_REF				GENMASK(1, 0)
2862306a36Sopenharmony_ci	#define PHY_CTRL_R3_HSDIC_REF				GENMASK(3, 2)
2962306a36Sopenharmony_ci	#define PHY_CTRL_R3_DISC_THRESH				GENMASK(7, 4)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define PHY_CTRL_R4						0x10
3262306a36Sopenharmony_ci	#define PHY_CTRL_R4_CALIB_CODE_7_0			GENMASK(7, 0)
3362306a36Sopenharmony_ci	#define PHY_CTRL_R4_CALIB_CODE_15_8			GENMASK(15, 8)
3462306a36Sopenharmony_ci	#define PHY_CTRL_R4_CALIB_CODE_23_16			GENMASK(23, 16)
3562306a36Sopenharmony_ci	#define PHY_CTRL_R4_I_C2L_CAL_EN			BIT(24)
3662306a36Sopenharmony_ci	#define PHY_CTRL_R4_I_C2L_CAL_RESET_N			BIT(25)
3762306a36Sopenharmony_ci	#define PHY_CTRL_R4_I_C2L_CAL_DONE			BIT(26)
3862306a36Sopenharmony_ci	#define PHY_CTRL_R4_TEST_BYPASS_MODE_EN			BIT(27)
3962306a36Sopenharmony_ci	#define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0			GENMASK(29, 28)
4062306a36Sopenharmony_ci	#define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2			GENMASK(31, 30)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define PHY_CTRL_R5						0x14
4362306a36Sopenharmony_ci#define PHY_CTRL_R6						0x18
4462306a36Sopenharmony_ci#define PHY_CTRL_R7						0x1c
4562306a36Sopenharmony_ci#define PHY_CTRL_R8						0x20
4662306a36Sopenharmony_ci#define PHY_CTRL_R9						0x24
4762306a36Sopenharmony_ci#define PHY_CTRL_R10						0x28
4862306a36Sopenharmony_ci#define PHY_CTRL_R11						0x2c
4962306a36Sopenharmony_ci#define PHY_CTRL_R12						0x30
5062306a36Sopenharmony_ci#define PHY_CTRL_R13						0x34
5162306a36Sopenharmony_ci	#define PHY_CTRL_R13_CUSTOM_PATTERN_19			GENMASK(7, 0)
5262306a36Sopenharmony_ci	#define PHY_CTRL_R13_LOAD_STAT				BIT(14)
5362306a36Sopenharmony_ci	#define PHY_CTRL_R13_UPDATE_PMA_SIGNALS			BIT(15)
5462306a36Sopenharmony_ci	#define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET		GENMASK(20, 16)
5562306a36Sopenharmony_ci	#define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT		BIT(21)
5662306a36Sopenharmony_ci	#define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL		BIT(22)
5762306a36Sopenharmony_ci	#define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN		BIT(23)
5862306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_HS_EN			BIT(24)
5962306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_FS_EN			BIT(25)
6062306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_LS_EN			BIT(26)
6162306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_HS_OE			BIT(27)
6262306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_FS_OE			BIT(28)
6362306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_HS_RX_EN			BIT(29)
6462306a36Sopenharmony_ci	#define PHY_CTRL_R13_I_C2L_FSLS_RX_EN			BIT(30)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define PHY_CTRL_R14						0x38
6762306a36Sopenharmony_ci	#define PHY_CTRL_R14_I_RDP_EN				BIT(0)
6862306a36Sopenharmony_ci	#define PHY_CTRL_R14_I_RPU_SW1_EN			BIT(1)
6962306a36Sopenharmony_ci	#define PHY_CTRL_R14_I_RPU_SW2_EN			GENMASK(3, 2)
7062306a36Sopenharmony_ci	#define PHY_CTRL_R14_PG_RSTN				BIT(4)
7162306a36Sopenharmony_ci	#define PHY_CTRL_R14_I_C2L_DATA_16_8			BIT(5)
7262306a36Sopenharmony_ci	#define PHY_CTRL_R14_I_C2L_ASSERT_SINGLE_EN_ZERO	BIT(6)
7362306a36Sopenharmony_ci	#define PHY_CTRL_R14_BYPASS_CTRL_7_0			GENMASK(15, 8)
7462306a36Sopenharmony_ci	#define PHY_CTRL_R14_BYPASS_CTRL_15_8			GENMASK(23, 16)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define PHY_CTRL_R15						0x3c
7762306a36Sopenharmony_ci#define PHY_CTRL_R16						0x40
7862306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_M				GENMASK(8, 0)
7962306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_N				GENMASK(14, 10)
8062306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_TDC_MODE			BIT(20)
8162306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_SDM_EN			BIT(21)
8262306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_LOAD				BIT(22)
8362306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_DCO_SDM_EN			BIT(23)
8462306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_LOCK_LONG			GENMASK(25, 24)
8562306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_LOCK_F			BIT(26)
8662306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_FAST_LOCK			BIT(27)
8762306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_EN				BIT(28)
8862306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_RESET				BIT(29)
8962306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_LOCK				BIT(30)
9062306a36Sopenharmony_ci	#define PHY_CTRL_R16_MPLL_LOCK_DIG			BIT(31)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define PHY_CTRL_R17						0x44
9362306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_FRAC_IN			GENMASK(13, 0)
9462306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_FIX_EN			BIT(16)
9562306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_LAMBDA1			GENMASK(19, 17)
9662306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_LAMBDA0			GENMASK(22, 20)
9762306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_FILTER_MODE			BIT(23)
9862306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_FILTER_PVT2			GENMASK(27, 24)
9962306a36Sopenharmony_ci	#define PHY_CTRL_R17_MPLL_FILTER_PVT1			GENMASK(31, 28)
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define PHY_CTRL_R18						0x48
10262306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_LKW_SEL			GENMASK(1, 0)
10362306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_LK_W				GENMASK(5, 2)
10462306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_LK_S				GENMASK(11, 6)
10562306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_DCO_M_EN			BIT(12)
10662306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_DCO_CLK_SEL			BIT(13)
10762306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_PFD_GAIN			GENMASK(15, 14)
10862306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_ROU				GENMASK(18, 16)
10962306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_DATA_SEL			GENMASK(21, 19)
11062306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_BIAS_ADJ			GENMASK(23, 22)
11162306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_BB_MODE			GENMASK(25, 24)
11262306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_ALPHA				GENMASK(28, 26)
11362306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_ADJ_LDO			GENMASK(30, 29)
11462306a36Sopenharmony_ci	#define PHY_CTRL_R18_MPLL_ACG_RANGE			BIT(31)
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci#define PHY_CTRL_R19						0x4c
11762306a36Sopenharmony_ci#define PHY_CTRL_R20						0x50
11862306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_IDDET_EN			BIT(0)
11962306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0		GENMASK(3, 1)
12062306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_OTG_VBUSDET_EN		BIT(4)
12162306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_AMON_EN			BIT(5)
12262306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_CAL_CODE_R5			BIT(6)
12362306a36Sopenharmony_ci	#define PHY_CTRL_R20_BYPASS_OTG_DET			BIT(7)
12462306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_DMON_EN			BIT(8)
12562306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_DMON_SEL_3_0			GENMASK(12, 9)
12662306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_EDGE_DRV_EN			BIT(13)
12762306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0		GENMASK(15, 14)
12862306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_BGR_ADJ_4_0			GENMASK(20, 16)
12962306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_BGR_START			BIT(21)
13062306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_BGR_VREF_4_0			GENMASK(28, 24)
13162306a36Sopenharmony_ci	#define PHY_CTRL_R20_USB2_BGR_DBG_1_0			GENMASK(30, 29)
13262306a36Sopenharmony_ci	#define PHY_CTRL_R20_BYPASS_CAL_DONE_R5			BIT(31)
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#define PHY_CTRL_R21						0x54
13562306a36Sopenharmony_ci	#define PHY_CTRL_R21_USB2_BGR_FORCE			BIT(0)
13662306a36Sopenharmony_ci	#define PHY_CTRL_R21_USB2_CAL_ACK_EN			BIT(1)
13762306a36Sopenharmony_ci	#define PHY_CTRL_R21_USB2_OTG_ACA_EN			BIT(2)
13862306a36Sopenharmony_ci	#define PHY_CTRL_R21_USB2_TX_STRG_PD			BIT(3)
13962306a36Sopenharmony_ci	#define PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0		GENMASK(5, 4)
14062306a36Sopenharmony_ci	#define PHY_CTRL_R21_BYPASS_UTMI_CNTR			GENMASK(15, 6)
14162306a36Sopenharmony_ci	#define PHY_CTRL_R21_BYPASS_UTMI_REG			GENMASK(25, 20)
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#define PHY_CTRL_R22						0x58
14462306a36Sopenharmony_ci#define PHY_CTRL_R23						0x5c
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci#define RESET_COMPLETE_TIME					1000
14762306a36Sopenharmony_ci#define PLL_RESET_COMPLETE_TIME					100
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cienum meson_soc_id {
15062306a36Sopenharmony_ci	MESON_SOC_G12A  = 0,
15162306a36Sopenharmony_ci	MESON_SOC_A1,
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistruct phy_meson_g12a_usb2_priv {
15562306a36Sopenharmony_ci	struct device		*dev;
15662306a36Sopenharmony_ci	struct regmap		*regmap;
15762306a36Sopenharmony_ci	struct clk		*clk;
15862306a36Sopenharmony_ci	struct reset_control	*reset;
15962306a36Sopenharmony_ci	int                     soc_id;
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic const struct regmap_config phy_meson_g12a_usb2_regmap_conf = {
16362306a36Sopenharmony_ci	.reg_bits = 8,
16462306a36Sopenharmony_ci	.val_bits = 32,
16562306a36Sopenharmony_ci	.reg_stride = 4,
16662306a36Sopenharmony_ci	.max_register = PHY_CTRL_R23,
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic int phy_meson_g12a_usb2_init(struct phy *phy)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);
17262306a36Sopenharmony_ci	int ret;
17362306a36Sopenharmony_ci	unsigned int value;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	ret = clk_prepare_enable(priv->clk);
17662306a36Sopenharmony_ci	if (ret)
17762306a36Sopenharmony_ci		return ret;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	ret = reset_control_reset(priv->reset);
18062306a36Sopenharmony_ci	if (ret) {
18162306a36Sopenharmony_ci		clk_disable_unprepare(priv->clk);
18262306a36Sopenharmony_ci		return ret;
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	udelay(RESET_COMPLETE_TIME);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* usb2_otg_aca_en == 0 */
18862306a36Sopenharmony_ci	regmap_update_bits(priv->regmap, PHY_CTRL_R21,
18962306a36Sopenharmony_ci			   PHY_CTRL_R21_USB2_OTG_ACA_EN, 0);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	/* PLL Setup : 24MHz * 20 / 1 = 480MHz */
19262306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R16,
19362306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |
19462306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |
19562306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_LOAD |
19662306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |
19762306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_FAST_LOCK |
19862306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_EN |
19962306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_RESET);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R17,
20262306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R17_MPLL_FRAC_IN, 0) |
20362306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA1, 7) |
20462306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA0, 7) |
20562306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
20662306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
20962306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
21062306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
21162306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
21262306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_ROU, 7) |
21362306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_DATA_SEL, 3) |
21462306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_BIAS_ADJ, 1) |
21562306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_BB_MODE, 0) |
21662306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_ALPHA, 3) |
21762306a36Sopenharmony_ci		FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
21862306a36Sopenharmony_ci		PHY_CTRL_R18_MPLL_ACG_RANGE;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (priv->soc_id == MESON_SOC_A1)
22162306a36Sopenharmony_ci		value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R18, value);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	udelay(PLL_RESET_COMPLETE_TIME);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/* UnReset PLL */
22862306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R16,
22962306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |
23062306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |
23162306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_LOAD |
23262306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |
23362306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_FAST_LOCK |
23462306a36Sopenharmony_ci		     PHY_CTRL_R16_MPLL_EN);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/* PHY Tuning */
23762306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R20,
23862306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0, 4) |
23962306a36Sopenharmony_ci		     PHY_CTRL_R20_USB2_OTG_VBUSDET_EN |
24062306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_DMON_SEL_3_0, 15) |
24162306a36Sopenharmony_ci		     PHY_CTRL_R20_USB2_EDGE_DRV_EN |
24262306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0, 3) |
24362306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_BGR_ADJ_4_0, 0) |
24462306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
24562306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (priv->soc_id == MESON_SOC_G12A)
24862306a36Sopenharmony_ci		regmap_write(priv->regmap, PHY_CTRL_R4,
24962306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
25062306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
25162306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
25262306a36Sopenharmony_ci			     PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
25362306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
25462306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
25562306a36Sopenharmony_ci	else if (priv->soc_id == MESON_SOC_A1) {
25662306a36Sopenharmony_ci		regmap_write(priv->regmap, PHY_CTRL_R21,
25762306a36Sopenharmony_ci			     PHY_CTRL_R21_USB2_CAL_ACK_EN |
25862306a36Sopenharmony_ci			     PHY_CTRL_R21_USB2_TX_STRG_PD |
25962306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		/* Analog Settings */
26262306a36Sopenharmony_ci		regmap_write(priv->regmap, PHY_CTRL_R13,
26362306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	/* Tuning Disconnect Threshold */
26762306a36Sopenharmony_ci	regmap_write(priv->regmap, PHY_CTRL_R3,
26862306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R3_SQUELCH_REF, 0) |
26962306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R3_HSDIC_REF, 1) |
27062306a36Sopenharmony_ci		     FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	if (priv->soc_id == MESON_SOC_G12A) {
27362306a36Sopenharmony_ci		/* Analog Settings */
27462306a36Sopenharmony_ci		regmap_write(priv->regmap, PHY_CTRL_R14, 0);
27562306a36Sopenharmony_ci		regmap_write(priv->regmap, PHY_CTRL_R13,
27662306a36Sopenharmony_ci			     PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
27762306a36Sopenharmony_ci			     FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	return 0;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic int phy_meson_g12a_usb2_exit(struct phy *phy)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	struct phy_meson_g12a_usb2_priv *priv = phy_get_drvdata(phy);
28662306a36Sopenharmony_ci	int ret;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	ret = reset_control_reset(priv->reset);
28962306a36Sopenharmony_ci	if (!ret)
29062306a36Sopenharmony_ci		clk_disable_unprepare(priv->clk);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	return ret;
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/* set_mode is not needed, mode setting is handled via the UTMI bus */
29662306a36Sopenharmony_cistatic const struct phy_ops phy_meson_g12a_usb2_ops = {
29762306a36Sopenharmony_ci	.init		= phy_meson_g12a_usb2_init,
29862306a36Sopenharmony_ci	.exit		= phy_meson_g12a_usb2_exit,
29962306a36Sopenharmony_ci	.owner		= THIS_MODULE,
30062306a36Sopenharmony_ci};
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic int phy_meson_g12a_usb2_probe(struct platform_device *pdev)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
30562306a36Sopenharmony_ci	struct phy_provider *phy_provider;
30662306a36Sopenharmony_ci	struct phy_meson_g12a_usb2_priv *priv;
30762306a36Sopenharmony_ci	struct phy *phy;
30862306a36Sopenharmony_ci	void __iomem *base;
30962306a36Sopenharmony_ci	int ret;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
31262306a36Sopenharmony_ci	if (!priv)
31362306a36Sopenharmony_ci		return -ENOMEM;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	priv->dev = dev;
31662306a36Sopenharmony_ci	platform_set_drvdata(pdev, priv);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	base = devm_platform_ioremap_resource(pdev, 0);
31962306a36Sopenharmony_ci	if (IS_ERR(base))
32062306a36Sopenharmony_ci		return PTR_ERR(base);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	priv->soc_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	priv->regmap = devm_regmap_init_mmio(dev, base,
32562306a36Sopenharmony_ci					     &phy_meson_g12a_usb2_regmap_conf);
32662306a36Sopenharmony_ci	if (IS_ERR(priv->regmap))
32762306a36Sopenharmony_ci		return PTR_ERR(priv->regmap);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	priv->clk = devm_clk_get(dev, "xtal");
33062306a36Sopenharmony_ci	if (IS_ERR(priv->clk))
33162306a36Sopenharmony_ci		return PTR_ERR(priv->clk);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	priv->reset = devm_reset_control_get(dev, "phy");
33462306a36Sopenharmony_ci	if (IS_ERR(priv->reset))
33562306a36Sopenharmony_ci		return PTR_ERR(priv->reset);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	ret = reset_control_deassert(priv->reset);
33862306a36Sopenharmony_ci	if (ret)
33962306a36Sopenharmony_ci		return ret;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	phy = devm_phy_create(dev, NULL, &phy_meson_g12a_usb2_ops);
34262306a36Sopenharmony_ci	if (IS_ERR(phy)) {
34362306a36Sopenharmony_ci		ret = PTR_ERR(phy);
34462306a36Sopenharmony_ci		if (ret != -EPROBE_DEFER)
34562306a36Sopenharmony_ci			dev_err(dev, "failed to create PHY\n");
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci		return ret;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	phy_set_bus_width(phy, 8);
35162306a36Sopenharmony_ci	phy_set_drvdata(phy, priv);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	return PTR_ERR_OR_ZERO(phy_provider);
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic const struct of_device_id phy_meson_g12a_usb2_of_match[] = {
35962306a36Sopenharmony_ci	{
36062306a36Sopenharmony_ci		.compatible = "amlogic,g12a-usb2-phy",
36162306a36Sopenharmony_ci		.data = (void *)MESON_SOC_G12A,
36262306a36Sopenharmony_ci	},
36362306a36Sopenharmony_ci	{
36462306a36Sopenharmony_ci		.compatible = "amlogic,a1-usb2-phy",
36562306a36Sopenharmony_ci		.data = (void *)MESON_SOC_A1,
36662306a36Sopenharmony_ci	},
36762306a36Sopenharmony_ci	{ /* Sentinel */ }
36862306a36Sopenharmony_ci};
36962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, phy_meson_g12a_usb2_of_match);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic struct platform_driver phy_meson_g12a_usb2_driver = {
37262306a36Sopenharmony_ci	.probe	= phy_meson_g12a_usb2_probe,
37362306a36Sopenharmony_ci	.driver	= {
37462306a36Sopenharmony_ci		.name		= "phy-meson-g12a-usb2",
37562306a36Sopenharmony_ci		.of_match_table	= phy_meson_g12a_usb2_of_match,
37662306a36Sopenharmony_ci	},
37762306a36Sopenharmony_ci};
37862306a36Sopenharmony_cimodule_platform_driver(phy_meson_g12a_usb2_driver);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ciMODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
38162306a36Sopenharmony_ciMODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
38262306a36Sopenharmony_ciMODULE_DESCRIPTION("Meson G12A USB2 PHY driver");
38362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
384