brintos

brintos / linux-shallow public Read only

0
0
Text · 16.5 KiB · 5b1c824 Raw
373 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2023, Linaro Limited4 */5 6#include <linux/clk.h>7#include <linux/ethtool.h>8#include <linux/module.h>9#include <linux/of.h>10#include <linux/phy/phy.h>11#include <linux/platform_device.h>12#include <linux/regmap.h>13 14#include "phy-qcom-qmp-pcs-sgmii.h"15#include "phy-qcom-qmp-qserdes-com-v5.h"16#include "phy-qcom-qmp-qserdes-txrx-v5.h"17 18#define QSERDES_QMP_PLL					0x019#define QSERDES_RX					0x60020#define QSERDES_TX					0x40021#define QSERDES_PCS					0xc0022 23#define QSERDES_COM_C_READY				BIT(0)24#define QSERDES_PCS_READY				BIT(0)25#define QSERDES_PCS_SGMIIPHY_READY			BIT(7)26#define QSERDES_COM_C_PLL_LOCKED			BIT(1)27 28struct qcom_dwmac_sgmii_phy_data {29	struct regmap *regmap;30	struct clk *refclk;31	int speed;32};33 34static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)35{36	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);37	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);38 39	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);40	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);41	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);42	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);43	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);44	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0A);45	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1A);46	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x82);47	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55);48	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55);49	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03);50	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24);51 52	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);53	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);54	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x04);55	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);56	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0A);57	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);58	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);59	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);60	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);61 62	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x05);63	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);64	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);65	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09);66	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);67	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);68	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);69	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);70 71	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);72	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);73	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);74	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);75	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);76	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);77	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);78	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);79	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x04);80	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);81	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);82	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);83	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);84	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);85	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);86	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);87	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);88	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);89	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);90	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);91	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);92	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);93	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x05);94	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0xE0);95	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);96	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);97	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x09);98	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB1);99	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);100	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);101	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);102	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);103	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);104	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);105	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);106	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);107	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);108	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);109	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);110 111	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);112	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);113	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);114	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);115	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);116	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x0C);117	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);118 119	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);120}121 122static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)123{124	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);125	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);126 127	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);128	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);129	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);130	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);131	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);132	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x1A);133	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x41);134	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x7A);135	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x00);136	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x20);137	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x01);138	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0xA1);139 140	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);141	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);142	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x03);143	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);144	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x05);145	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);146	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);147	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);148	regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);149 150	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x04);151	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);152	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);153	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x02);154	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);155	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);156	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);157	regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);158 159	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);160	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);161	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);162	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);163	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);164	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);165	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);166	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);167	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x00);168	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);169	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);170	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);171	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);172	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);173	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);174	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);175	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);176	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);177	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);178	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);179	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);180	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);181	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x18);182	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0x18);183	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);184	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);185	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x0C);186	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB8);187	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);188	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);189	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);190	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);191	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);192	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);193	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);194	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);195	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);196	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);197	regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);198 199	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);200	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);201	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);202	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);203	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);204	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x8C);205	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);206 207	regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);208}209 210static inline int211qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,212				 unsigned int bit)213{214	unsigned int val;215 216	return regmap_read_poll_timeout(regmap, reg, val,217					val & bit, 1500, 750000);218}219 220static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)221{222	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);223	struct device *dev = phy->dev.parent;224 225	switch (data->speed) {226	case SPEED_10:227	case SPEED_100:228	case SPEED_1000:229		qcom_dwmac_sgmii_phy_init_1g(data->regmap);230		break;231	case SPEED_2500:232		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);233		break;234	}235 236	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,237					     QSERDES_QMP_PLL + QSERDES_V5_COM_C_READY_STATUS,238					     QSERDES_COM_C_READY)) {239		dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");240		return -ETIMEDOUT;241	}242 243	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,244					     QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,245					     QSERDES_PCS_READY)) {246		dev_err(dev, "PCS_READY timed-out");247		return -ETIMEDOUT;248	}249 250	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,251					     QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,252					     QSERDES_PCS_SGMIIPHY_READY)) {253		dev_err(dev, "SGMIIPHY_READY timed-out");254		return -ETIMEDOUT;255	}256 257	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,258					     QSERDES_QMP_PLL + QSERDES_V5_COM_CMN_STATUS,259					     QSERDES_COM_C_PLL_LOCKED)) {260		dev_err(dev, "PLL Lock Status timed-out");261		return -ETIMEDOUT;262	}263 264	return 0;265}266 267static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)268{269	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);270 271	return clk_prepare_enable(data->refclk);272}273 274static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)275{276	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);277 278	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);279	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);280	udelay(100);281	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);282	regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);283 284	clk_disable_unprepare(data->refclk);285 286	return 0;287}288 289static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)290{291	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);292 293	if (speed != data->speed)294		data->speed = speed;295 296	return qcom_dwmac_sgmii_phy_calibrate(phy);297}298 299static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {300	.power_on	= qcom_dwmac_sgmii_phy_power_on,301	.power_off	= qcom_dwmac_sgmii_phy_power_off,302	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,303	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,304	.owner		= THIS_MODULE,305};306 307static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {308	.reg_bits		= 32,309	.val_bits		= 32,310	.reg_stride		= 4,311	.use_relaxed_mmio	= true,312	.disable_locking	= true,313};314 315static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)316{317	struct qcom_dwmac_sgmii_phy_data *data;318	struct device *dev = &pdev->dev;319	struct phy_provider *provider;320	void __iomem *base;321	struct phy *phy;322 323	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);324	if (!data)325		return -ENOMEM;326 327	data->speed = SPEED_10;328 329	base = devm_platform_ioremap_resource(pdev, 0);330	if (IS_ERR(base))331		return PTR_ERR(base);332 333	data->regmap = devm_regmap_init_mmio(dev, base,334					     &qcom_dwmac_sgmii_phy_regmap_cfg);335	if (IS_ERR(data->regmap))336		return PTR_ERR(data->regmap);337 338	phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);339	if (IS_ERR(phy))340		return PTR_ERR(phy);341 342	data->refclk = devm_clk_get(dev, "sgmi_ref");343	if (IS_ERR(data->refclk))344		return PTR_ERR(data->refclk);345 346	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);347	if (IS_ERR(provider))348		return PTR_ERR(provider);349 350	phy_set_drvdata(phy, data);351 352	return 0;353}354 355static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {356	{ .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },357	{ },358};359MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);360 361static struct platform_driver qcom_dwmac_sgmii_phy_driver = {362	.probe	= qcom_dwmac_sgmii_phy_probe,363	.driver = {364		.name	= "qcom-dwmac-sgmii-phy",365		.of_match_table	= qcom_dwmac_sgmii_phy_of_match,366	}367};368 369module_platform_driver(qcom_dwmac_sgmii_phy_driver);370 371MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");372MODULE_LICENSE("GPL");373