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