18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Salvo PHY is a 28nm PHY, it is a legacy PHY, and only
48c2ecf20Sopenharmony_ci * for USB3 and USB2.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (c) 2019-2020 NXP
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/clk.h>
108c2ecf20Sopenharmony_ci#include <linux/io.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/phy/phy.h>
138c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
148c2ecf20Sopenharmony_ci#include <linux/delay.h>
158c2ecf20Sopenharmony_ci#include <linux/of.h>
168c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* PHY register definition */
198c2ecf20Sopenharmony_ci#define PHY_PMA_CMN_CTRL1			0xC800
208c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_HSCLK_SEL		0x01e0
218c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR	0x0084
228c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR	0x0085
238c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_INTDIV	                0x0094
248c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_FRACDIV		0x0095
258c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_HIGH_THR		0x0096
268c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_SS_CTRL1		0x0098
278c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_SS_CTRL2		0x0099
288c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PLL0_DSM_DIAG		0x0097
298c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_OVRD		0x01c2
308c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD		0x01c0
318c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD		0x01c1
328c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE          0x01C5
338c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_CP_TUNE           0x01C6
348c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_LF_PROG           0x01C7
358c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_DIAG_PLL0_TEST_MODE		0x01c4
368c2ecf20Sopenharmony_ci#define TB_ADDR_CMN_PSM_CLK_CTRL		0x0061
378c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR	0x40ea
388c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_RCTRL	                0x4001
398c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_A0		        0x4100
408c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_A1		        0x4101
418c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_A2		        0x4102
428c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_A3		        0x4103
438c2ecf20Sopenharmony_ci#define TB_ADDR_TX_DIAG_ECTRL_OVRD		0x41f5
448c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_CAL		        0x4106
458c2ecf20Sopenharmony_ci#define TB_ADDR_TX_PSC_RDY		        0x4107
468c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_A0	                0x8000
478c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_A1	                0x8001
488c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_A2	                0x8002
498c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_A3	                0x8003
508c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_CAL	                0x8006
518c2ecf20Sopenharmony_ci#define TB_ADDR_RX_PSC_RDY	                0x8007
528c2ecf20Sopenharmony_ci#define TB_ADDR_TX_TXCC_MGNLS_MULT_000		0x4058
538c2ecf20Sopenharmony_ci#define TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY	0x41e7
548c2ecf20Sopenharmony_ci#define TB_ADDR_RX_SLC_CU_ITER_TMR		0x80e3
558c2ecf20Sopenharmony_ci#define TB_ADDR_RX_SIGDET_HL_FILT_TMR		0x8090
568c2ecf20Sopenharmony_ci#define TB_ADDR_RX_SAMP_DAC_CTRL		0x8058
578c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_SIGDET_TUNE		0x81dc
588c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_LFPSDET_TUNE2		0x81df
598c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_BS_TM	                0x81f5
608c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_DFE_CTRL1		0x81d3
618c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_ILL_IQE_TRIM4		0x81c7
628c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_ILL_E_TRIM0		0x81c2
638c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_ILL_IQ_TRIM0		0x81c1
648c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_ILL_IQE_TRIM6		0x81c9
658c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_RXFE_TM3		0x81f8
668c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_RXFE_TM4		0x81f9
678c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_LFPSDET_TUNE		0x81dd
688c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_DFE_CTRL3		0x81d5
698c2ecf20Sopenharmony_ci#define TB_ADDR_RX_DIAG_SC2C_DELAY		0x81e1
708c2ecf20Sopenharmony_ci#define TB_ADDR_RX_REE_VGA_GAIN_NODFE		0x81bf
718c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_CAL_TMR		0x4002
728c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A0BYP_TMR		0x4004
738c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A0IN_TMR		0x4003
748c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A1IN_TMR		0x4005
758c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A2IN_TMR		0x4006
768c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A3IN_TMR		0x4007
778c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A4IN_TMR		0x4008
788c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A5IN_TMR		0x4009
798c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A0OUT_TMR		0x400a
808c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A1OUT_TMR		0x400b
818c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A2OUT_TMR		0x400c
828c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A3OUT_TMR		0x400d
838c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A4OUT_TMR		0x400e
848c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_PSM_A5OUT_TMR		0x400f
858c2ecf20Sopenharmony_ci#define TB_ADDR_TX_RCVDET_EN_TMR	        0x4122
868c2ecf20Sopenharmony_ci#define TB_ADDR_TX_RCVDET_ST_TMR	        0x4123
878c2ecf20Sopenharmony_ci#define TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR	0x40f2
888c2ecf20Sopenharmony_ci#define TB_ADDR_TX_RCVDETSC_CTRL	        0x4124
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/* TB_ADDR_TX_RCVDETSC_CTRL */
918c2ecf20Sopenharmony_ci#define RXDET_IN_P3_32KHZ			BIT(0)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistruct cdns_reg_pairs {
948c2ecf20Sopenharmony_ci	u16 val;
958c2ecf20Sopenharmony_ci	u32 off;
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistruct cdns_salvo_data {
998c2ecf20Sopenharmony_ci	u8 reg_offset_shift;
1008c2ecf20Sopenharmony_ci	const struct cdns_reg_pairs *init_sequence_val;
1018c2ecf20Sopenharmony_ci	u8 init_sequence_length;
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistruct cdns_salvo_phy {
1058c2ecf20Sopenharmony_ci	struct phy *phy;
1068c2ecf20Sopenharmony_ci	struct clk *clk;
1078c2ecf20Sopenharmony_ci	void __iomem *base;
1088c2ecf20Sopenharmony_ci	struct cdns_salvo_data *data;
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic const struct of_device_id cdns_salvo_phy_of_match[];
1128c2ecf20Sopenharmony_cistatic u16 cdns_salvo_read(struct cdns_salvo_phy *salvo_phy, u32 reg)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	return (u16)readl(salvo_phy->base +
1158c2ecf20Sopenharmony_ci		reg * (1 << salvo_phy->data->reg_offset_shift));
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy,
1198c2ecf20Sopenharmony_ci			     u32 reg, u16 val)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	writel(val, salvo_phy->base +
1228c2ecf20Sopenharmony_ci		reg * (1 << salvo_phy->data->reg_offset_shift));
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci/*
1268c2ecf20Sopenharmony_ci * Below bringup sequence pair are from Cadence PHY's User Guide
1278c2ecf20Sopenharmony_ci * and NXP platform tuning results.
1288c2ecf20Sopenharmony_ci */
1298c2ecf20Sopenharmony_cistatic const struct cdns_reg_pairs cdns_nxp_sequence_pair[] = {
1308c2ecf20Sopenharmony_ci	{0x0830, PHY_PMA_CMN_CTRL1},
1318c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_CMN_DIAG_HSCLK_SEL},
1328c2ecf20Sopenharmony_ci	{0x00f0, TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR},
1338c2ecf20Sopenharmony_ci	{0x0018, TB_ADDR_CMN_PLL0_VCOCAL_ITER_TMR},
1348c2ecf20Sopenharmony_ci	{0x00d0, TB_ADDR_CMN_PLL0_INTDIV},
1358c2ecf20Sopenharmony_ci	{0x4aaa, TB_ADDR_CMN_PLL0_FRACDIV},
1368c2ecf20Sopenharmony_ci	{0x0034, TB_ADDR_CMN_PLL0_HIGH_THR},
1378c2ecf20Sopenharmony_ci	{0x01ee, TB_ADDR_CMN_PLL0_SS_CTRL1},
1388c2ecf20Sopenharmony_ci	{0x7f03, TB_ADDR_CMN_PLL0_SS_CTRL2},
1398c2ecf20Sopenharmony_ci	{0x0020, TB_ADDR_CMN_PLL0_DSM_DIAG},
1408c2ecf20Sopenharmony_ci	{0x0000, TB_ADDR_CMN_DIAG_PLL0_OVRD},
1418c2ecf20Sopenharmony_ci	{0x0000, TB_ADDR_CMN_DIAG_PLL0_FBH_OVRD},
1428c2ecf20Sopenharmony_ci	{0x0000, TB_ADDR_CMN_DIAG_PLL0_FBL_OVRD},
1438c2ecf20Sopenharmony_ci	{0x0007, TB_ADDR_CMN_DIAG_PLL0_V2I_TUNE},
1448c2ecf20Sopenharmony_ci	{0x0027, TB_ADDR_CMN_DIAG_PLL0_CP_TUNE},
1458c2ecf20Sopenharmony_ci	{0x0008, TB_ADDR_CMN_DIAG_PLL0_LF_PROG},
1468c2ecf20Sopenharmony_ci	{0x0022, TB_ADDR_CMN_DIAG_PLL0_TEST_MODE},
1478c2ecf20Sopenharmony_ci	{0x000a, TB_ADDR_CMN_PSM_CLK_CTRL},
1488c2ecf20Sopenharmony_ci	{0x0139, TB_ADDR_XCVR_DIAG_RX_LANE_CAL_RST_TMR},
1498c2ecf20Sopenharmony_ci	{0xbefc, TB_ADDR_XCVR_PSM_RCTRL},
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	{0x7799, TB_ADDR_TX_PSC_A0},
1528c2ecf20Sopenharmony_ci	{0x7798, TB_ADDR_TX_PSC_A1},
1538c2ecf20Sopenharmony_ci	{0x509b, TB_ADDR_TX_PSC_A2},
1548c2ecf20Sopenharmony_ci	{0x0003, TB_ADDR_TX_DIAG_ECTRL_OVRD},
1558c2ecf20Sopenharmony_ci	{0x509b, TB_ADDR_TX_PSC_A3},
1568c2ecf20Sopenharmony_ci	{0x2090, TB_ADDR_TX_PSC_CAL},
1578c2ecf20Sopenharmony_ci	{0x2090, TB_ADDR_TX_PSC_RDY},
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	{0xA6FD, TB_ADDR_RX_PSC_A0},
1608c2ecf20Sopenharmony_ci	{0xA6FD, TB_ADDR_RX_PSC_A1},
1618c2ecf20Sopenharmony_ci	{0xA410, TB_ADDR_RX_PSC_A2},
1628c2ecf20Sopenharmony_ci	{0x2410, TB_ADDR_RX_PSC_A3},
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	{0x23FF, TB_ADDR_RX_PSC_CAL},
1658c2ecf20Sopenharmony_ci	{0x2010, TB_ADDR_RX_PSC_RDY},
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	{0x0020, TB_ADDR_TX_TXCC_MGNLS_MULT_000},
1688c2ecf20Sopenharmony_ci	{0x00ff, TB_ADDR_TX_DIAG_BGREF_PREDRV_DELAY},
1698c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_RX_SLC_CU_ITER_TMR},
1708c2ecf20Sopenharmony_ci	{0x0013, TB_ADDR_RX_SIGDET_HL_FILT_TMR},
1718c2ecf20Sopenharmony_ci	{0x0000, TB_ADDR_RX_SAMP_DAC_CTRL},
1728c2ecf20Sopenharmony_ci	{0x1004, TB_ADDR_RX_DIAG_SIGDET_TUNE},
1738c2ecf20Sopenharmony_ci	{0x4041, TB_ADDR_RX_DIAG_LFPSDET_TUNE2},
1748c2ecf20Sopenharmony_ci	{0x0480, TB_ADDR_RX_DIAG_BS_TM},
1758c2ecf20Sopenharmony_ci	{0x8006, TB_ADDR_RX_DIAG_DFE_CTRL1},
1768c2ecf20Sopenharmony_ci	{0x003f, TB_ADDR_RX_DIAG_ILL_IQE_TRIM4},
1778c2ecf20Sopenharmony_ci	{0x543f, TB_ADDR_RX_DIAG_ILL_E_TRIM0},
1788c2ecf20Sopenharmony_ci	{0x543f, TB_ADDR_RX_DIAG_ILL_IQ_TRIM0},
1798c2ecf20Sopenharmony_ci	{0x0000, TB_ADDR_RX_DIAG_ILL_IQE_TRIM6},
1808c2ecf20Sopenharmony_ci	{0x8000, TB_ADDR_RX_DIAG_RXFE_TM3},
1818c2ecf20Sopenharmony_ci	{0x0003, TB_ADDR_RX_DIAG_RXFE_TM4},
1828c2ecf20Sopenharmony_ci	{0x2408, TB_ADDR_RX_DIAG_LFPSDET_TUNE},
1838c2ecf20Sopenharmony_ci	{0x05ca, TB_ADDR_RX_DIAG_DFE_CTRL3},
1848c2ecf20Sopenharmony_ci	{0x0258, TB_ADDR_RX_DIAG_SC2C_DELAY},
1858c2ecf20Sopenharmony_ci	{0x1fff, TB_ADDR_RX_REE_VGA_GAIN_NODFE},
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	{0x02c6, TB_ADDR_XCVR_PSM_CAL_TMR},
1888c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A0BYP_TMR},
1898c2ecf20Sopenharmony_ci	{0x02c6, TB_ADDR_XCVR_PSM_A0IN_TMR},
1908c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_XCVR_PSM_A1IN_TMR},
1918c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_XCVR_PSM_A2IN_TMR},
1928c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_XCVR_PSM_A3IN_TMR},
1938c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_XCVR_PSM_A4IN_TMR},
1948c2ecf20Sopenharmony_ci	{0x0010, TB_ADDR_XCVR_PSM_A5IN_TMR},
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A0OUT_TMR},
1978c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A1OUT_TMR},
1988c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A2OUT_TMR},
1998c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A3OUT_TMR},
2008c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A4OUT_TMR},
2018c2ecf20Sopenharmony_ci	{0x0002, TB_ADDR_XCVR_PSM_A5OUT_TMR},
2028c2ecf20Sopenharmony_ci	/* Change rx detect parameter */
2038c2ecf20Sopenharmony_ci	{0x0960, TB_ADDR_TX_RCVDET_EN_TMR},
2048c2ecf20Sopenharmony_ci	{0x01e0, TB_ADDR_TX_RCVDET_ST_TMR},
2058c2ecf20Sopenharmony_ci	{0x0090, TB_ADDR_XCVR_DIAG_LANE_FCM_EN_MGN_TMR},
2068c2ecf20Sopenharmony_ci};
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic int cdns_salvo_phy_init(struct phy *phy)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
2118c2ecf20Sopenharmony_ci	struct cdns_salvo_data *data = salvo_phy->data;
2128c2ecf20Sopenharmony_ci	int ret, i;
2138c2ecf20Sopenharmony_ci	u16 value;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(salvo_phy->clk);
2168c2ecf20Sopenharmony_ci	if (ret)
2178c2ecf20Sopenharmony_ci		return ret;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	for (i = 0; i < data->init_sequence_length; i++) {
2208c2ecf20Sopenharmony_ci		const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val);
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/* RXDET_IN_P3_32KHZ, Receiver detect slow clock enable */
2268c2ecf20Sopenharmony_ci	value = cdns_salvo_read(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL);
2278c2ecf20Sopenharmony_ci	value |= RXDET_IN_P3_32KHZ;
2288c2ecf20Sopenharmony_ci	cdns_salvo_write(salvo_phy, TB_ADDR_TX_RCVDETSC_CTRL,
2298c2ecf20Sopenharmony_ci			 RXDET_IN_P3_32KHZ);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	udelay(10);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	clk_disable_unprepare(salvo_phy->clk);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	return ret;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic int cdns_salvo_phy_power_on(struct phy *phy)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	return clk_prepare_enable(salvo_phy->clk);
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic int cdns_salvo_phy_power_off(struct phy *phy)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct cdns_salvo_phy *salvo_phy = phy_get_drvdata(phy);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	clk_disable_unprepare(salvo_phy->clk);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic const struct phy_ops cdns_salvo_phy_ops = {
2558c2ecf20Sopenharmony_ci	.init		= cdns_salvo_phy_init,
2568c2ecf20Sopenharmony_ci	.power_on	= cdns_salvo_phy_power_on,
2578c2ecf20Sopenharmony_ci	.power_off	= cdns_salvo_phy_power_off,
2588c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
2598c2ecf20Sopenharmony_ci};
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic int cdns_salvo_phy_probe(struct platform_device *pdev)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct phy_provider *phy_provider;
2648c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
2658c2ecf20Sopenharmony_ci	struct cdns_salvo_phy *salvo_phy;
2668c2ecf20Sopenharmony_ci	struct resource *res;
2678c2ecf20Sopenharmony_ci	const struct of_device_id *match;
2688c2ecf20Sopenharmony_ci	struct cdns_salvo_data *data;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	match = of_match_device(cdns_salvo_phy_of_match, dev);
2718c2ecf20Sopenharmony_ci	if (!match)
2728c2ecf20Sopenharmony_ci		return -EINVAL;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	data = (struct cdns_salvo_data *)match->data;
2758c2ecf20Sopenharmony_ci	salvo_phy = devm_kzalloc(dev, sizeof(*salvo_phy), GFP_KERNEL);
2768c2ecf20Sopenharmony_ci	if (!salvo_phy)
2778c2ecf20Sopenharmony_ci		return -ENOMEM;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	salvo_phy->data = data;
2808c2ecf20Sopenharmony_ci	salvo_phy->clk = devm_clk_get_optional(dev, "salvo_phy_clk");
2818c2ecf20Sopenharmony_ci	if (IS_ERR(salvo_phy->clk))
2828c2ecf20Sopenharmony_ci		return PTR_ERR(salvo_phy->clk);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2858c2ecf20Sopenharmony_ci	salvo_phy->base = devm_ioremap_resource(dev, res);
2868c2ecf20Sopenharmony_ci	if (IS_ERR(salvo_phy->base))
2878c2ecf20Sopenharmony_ci		return PTR_ERR(salvo_phy->base);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	salvo_phy->phy = devm_phy_create(dev, NULL, &cdns_salvo_phy_ops);
2908c2ecf20Sopenharmony_ci	if (IS_ERR(salvo_phy->phy))
2918c2ecf20Sopenharmony_ci		return PTR_ERR(salvo_phy->phy);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	phy_set_drvdata(salvo_phy->phy, salvo_phy);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
2968c2ecf20Sopenharmony_ci	return PTR_ERR_OR_ZERO(phy_provider);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic const struct cdns_salvo_data cdns_nxp_salvo_data = {
3008c2ecf20Sopenharmony_ci	2,
3018c2ecf20Sopenharmony_ci	cdns_nxp_sequence_pair,
3028c2ecf20Sopenharmony_ci	ARRAY_SIZE(cdns_nxp_sequence_pair),
3038c2ecf20Sopenharmony_ci};
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic const struct of_device_id cdns_salvo_phy_of_match[] = {
3068c2ecf20Sopenharmony_ci	{
3078c2ecf20Sopenharmony_ci		.compatible = "nxp,salvo-phy",
3088c2ecf20Sopenharmony_ci		.data = &cdns_nxp_salvo_data,
3098c2ecf20Sopenharmony_ci	},
3108c2ecf20Sopenharmony_ci	{}
3118c2ecf20Sopenharmony_ci};
3128c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, cdns_salvo_phy_of_match);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic struct platform_driver cdns_salvo_phy_driver = {
3158c2ecf20Sopenharmony_ci	.probe	= cdns_salvo_phy_probe,
3168c2ecf20Sopenharmony_ci	.driver = {
3178c2ecf20Sopenharmony_ci		.name	= "cdns-salvo-phy",
3188c2ecf20Sopenharmony_ci		.of_match_table	= cdns_salvo_phy_of_match,
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci};
3218c2ecf20Sopenharmony_cimodule_platform_driver(cdns_salvo_phy_driver);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ciMODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
3248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
3258c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Cadence SALVO PHY Driver");
326