1256 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2014 STMicroelectronics4 *5 * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).6 *7 * Author: Alexandre Torgue <alexandre.torgue@st.com>8 */9 10#include <linux/platform_device.h>11#include <linux/io.h>12#include <linux/iopoll.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/of_platform.h>17#include <linux/of_address.h>18#include <linux/clk.h>19#include <linux/phy/phy.h>20#include <linux/delay.h>21#include <linux/mfd/syscon.h>22#include <linux/regmap.h>23#include <linux/reset.h>24 25#include <dt-bindings/phy/phy.h>26 27/* MiPHY registers */28#define MIPHY_CONF_RESET 0x0029#define RST_APPLI_SW BIT(0)30#define RST_CONF_SW BIT(1)31#define RST_MACRO_SW BIT(2)32 33#define MIPHY_RESET 0x0134#define RST_PLL_SW BIT(0)35#define RST_COMP_SW BIT(2)36 37#define MIPHY_STATUS_1 0x0238#define PHY_RDY BIT(0)39#define HFC_RDY BIT(1)40#define HFC_PLL BIT(2)41 42#define MIPHY_CONTROL 0x0443#define TERM_EN_SW BIT(2)44#define DIS_LINK_RST BIT(3)45#define AUTO_RST_RX BIT(4)46#define PX_RX_POL BIT(5)47 48#define MIPHY_BOUNDARY_SEL 0x0a49#define TX_SEL BIT(6)50#define SSC_SEL BIT(4)51#define GENSEL_SEL BIT(0)52 53#define MIPHY_BOUNDARY_1 0x0b54#define MIPHY_BOUNDARY_2 0x0c55#define SSC_EN_SW BIT(2)56 57#define MIPHY_PLL_CLKREF_FREQ 0x0d58#define MIPHY_SPEED 0x0e59#define TX_SPDSEL_80DEC 060#define TX_SPDSEL_40DEC 161#define TX_SPDSEL_20DEC 262#define RX_SPDSEL_80DEC 063#define RX_SPDSEL_40DEC (1 << 2)64#define RX_SPDSEL_20DEC (2 << 2)65 66#define MIPHY_CONF 0x0f67#define MIPHY_CTRL_TEST_SEL 0x2068#define MIPHY_CTRL_TEST_1 0x2169#define MIPHY_CTRL_TEST_2 0x2270#define MIPHY_CTRL_TEST_3 0x2371#define MIPHY_CTRL_TEST_4 0x2472#define MIPHY_FEEDBACK_TEST 0x2573#define MIPHY_DEBUG_BUS 0x2674#define MIPHY_DEBUG_STATUS_MSB 0x2775#define MIPHY_DEBUG_STATUS_LSB 0x2876#define MIPHY_PWR_RAIL_1 0x2977#define MIPHY_PWR_RAIL_2 0x2a78#define MIPHY_SYNCHAR_CONTROL 0x3079 80#define MIPHY_COMP_FSM_1 0x3a81#define COMP_START BIT(6)82 83#define MIPHY_COMP_FSM_6 0x3f84#define COMP_DONE BIT(7)85 86#define MIPHY_COMP_POSTP 0x4287#define MIPHY_TX_CTRL_1 0x4988#define TX_REG_STEP_0V 089#define TX_REG_STEP_P_25MV 190#define TX_REG_STEP_P_50MV 291#define TX_REG_STEP_N_25MV 792#define TX_REG_STEP_N_50MV 693#define TX_REG_STEP_N_75MV 594 95#define MIPHY_TX_CTRL_2 0x4a96#define TX_SLEW_SW_40_PS 097#define TX_SLEW_SW_80_PS 198#define TX_SLEW_SW_120_PS 299 100#define MIPHY_TX_CTRL_3 0x4b101#define MIPHY_TX_CAL_MAN 0x4e102#define TX_SLEW_CAL_MAN_EN BIT(0)103 104#define MIPHY_TST_BIAS_BOOST_2 0x62105#define MIPHY_BIAS_BOOST_1 0x63106#define MIPHY_BIAS_BOOST_2 0x64107#define MIPHY_RX_DESBUFF_FDB_2 0x67108#define MIPHY_RX_DESBUFF_FDB_3 0x68109#define MIPHY_SIGDET_COMPENS1 0x69110#define MIPHY_SIGDET_COMPENS2 0x6a111#define MIPHY_JITTER_PERIOD 0x6b112#define MIPHY_JITTER_AMPLITUDE_1 0x6c113#define MIPHY_JITTER_AMPLITUDE_2 0x6d114#define MIPHY_JITTER_AMPLITUDE_3 0x6e115#define MIPHY_RX_K_GAIN 0x78116#define MIPHY_RX_BUFFER_CTRL 0x7a117#define VGA_GAIN BIT(0)118#define EQ_DC_GAIN BIT(2)119#define EQ_BOOST_GAIN BIT(3)120 121#define MIPHY_RX_VGA_GAIN 0x7b122#define MIPHY_RX_EQU_GAIN_1 0x7f123#define MIPHY_RX_EQU_GAIN_2 0x80124#define MIPHY_RX_EQU_GAIN_3 0x81125#define MIPHY_RX_CAL_CTRL_1 0x97126#define MIPHY_RX_CAL_CTRL_2 0x98127 128#define MIPHY_RX_CAL_OFFSET_CTRL 0x99129#define CAL_OFFSET_VGA_64 (0x03 << 0)130#define CAL_OFFSET_THRESHOLD_64 (0x03 << 2)131#define VGA_OFFSET_POLARITY BIT(4)132#define OFFSET_COMPENSATION_EN BIT(6)133 134#define MIPHY_RX_CAL_VGA_STEP 0x9a135#define MIPHY_RX_CAL_EYE_MIN 0x9d136#define MIPHY_RX_CAL_OPT_LENGTH 0x9f137#define MIPHY_RX_LOCK_CTRL_1 0xc1138#define MIPHY_RX_LOCK_SETTINGS_OPT 0xc2139#define MIPHY_RX_LOCK_STEP 0xc4140 141#define MIPHY_RX_SIGDET_SLEEP_OA 0xc9142#define MIPHY_RX_SIGDET_SLEEP_SEL 0xca143#define MIPHY_RX_SIGDET_WAIT_SEL 0xcb144#define MIPHY_RX_SIGDET_DATA_SEL 0xcc145#define EN_ULTRA_LOW_POWER BIT(0)146#define EN_FIRST_HALF BIT(1)147#define EN_SECOND_HALF BIT(2)148#define EN_DIGIT_SIGNAL_CHECK BIT(3)149 150#define MIPHY_RX_POWER_CTRL_1 0xcd151#define MIPHY_RX_POWER_CTRL_2 0xce152#define MIPHY_PLL_CALSET_CTRL 0xd3153#define MIPHY_PLL_CALSET_1 0xd4154#define MIPHY_PLL_CALSET_2 0xd5155#define MIPHY_PLL_CALSET_3 0xd6156#define MIPHY_PLL_CALSET_4 0xd7157#define MIPHY_PLL_SBR_1 0xe3158#define SET_NEW_CHANGE BIT(1)159 160#define MIPHY_PLL_SBR_2 0xe4161#define MIPHY_PLL_SBR_3 0xe5162#define MIPHY_PLL_SBR_4 0xe6163#define MIPHY_PLL_COMMON_MISC_2 0xe9164#define START_ACT_FILT BIT(6)165 166#define MIPHY_PLL_SPAREIN 0xeb167 168/*169 * On STiH407 the glue logic can be different among MiPHY devices; for example:170 * MiPHY0: OSC_FORCE_EXT means:171 * 0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1172 * MiPHY1: OSC_FORCE_EXT means:173 * 1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1174 * Some devices have not the possibility to check if the osc is ready.175 */176#define MIPHY_OSC_FORCE_EXT BIT(3)177#define MIPHY_OSC_RDY BIT(5)178 179#define MIPHY_CTRL_MASK 0x0f180#define MIPHY_CTRL_DEFAULT 0181#define MIPHY_CTRL_SYNC_D_EN BIT(2)182 183/* SATA / PCIe defines */184#define SATA_CTRL_MASK 0x07185#define PCIE_CTRL_MASK 0xff186#define SATA_CTRL_SELECT_SATA 1187#define SATA_CTRL_SELECT_PCIE 0188#define SYSCFG_PCIE_PCIE_VAL 0x80189#define SATA_SPDMODE 1190 191#define MIPHY_SATA_BANK_NB 3192#define MIPHY_PCIE_BANK_NB 2193 194enum {195 SYSCFG_CTRL,196 SYSCFG_STATUS,197 SYSCFG_PCI,198 SYSCFG_SATA,199 SYSCFG_REG_MAX,200};201 202struct miphy28lp_phy {203 struct phy *phy;204 struct miphy28lp_dev *phydev;205 void __iomem *base;206 void __iomem *pipebase;207 208 bool osc_force_ext;209 bool osc_rdy;210 bool px_rx_pol_inv;211 bool ssc;212 bool tx_impedance;213 214 struct reset_control *miphy_rst;215 216 u32 sata_gen;217 218 /* Sysconfig registers offsets needed to configure the device */219 u32 syscfg_reg[SYSCFG_REG_MAX];220 u8 type;221};222 223struct miphy28lp_dev {224 struct device *dev;225 struct regmap *regmap;226 struct mutex miphy_mutex;227 struct miphy28lp_phy **phys;228 int nphys;229};230 231enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };232 233static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };234 235struct pll_ratio {236 int clk_ref;237 int calset_1;238 int calset_2;239 int calset_3;240 int calset_4;241 int cal_ctrl;242};243 244static struct pll_ratio sata_pll_ratio = {245 .clk_ref = 0x1e,246 .calset_1 = 0xc8,247 .calset_2 = 0x00,248 .calset_3 = 0x00,249 .calset_4 = 0x00,250 .cal_ctrl = 0x00,251};252 253static struct pll_ratio pcie_pll_ratio = {254 .clk_ref = 0x1e,255 .calset_1 = 0xa6,256 .calset_2 = 0xaa,257 .calset_3 = 0xaa,258 .calset_4 = 0x00,259 .cal_ctrl = 0x00,260};261 262static struct pll_ratio usb3_pll_ratio = {263 .clk_ref = 0x1e,264 .calset_1 = 0xa6,265 .calset_2 = 0xaa,266 .calset_3 = 0xaa,267 .calset_4 = 0x04,268 .cal_ctrl = 0x00,269};270 271struct miphy28lp_pll_gen {272 int bank;273 int speed;274 int bias_boost_1;275 int bias_boost_2;276 int tx_ctrl_1;277 int tx_ctrl_2;278 int tx_ctrl_3;279 int rx_k_gain;280 int rx_vga_gain;281 int rx_equ_gain_1;282 int rx_equ_gain_2;283 int rx_equ_gain_3;284 int rx_buff_ctrl;285};286 287static struct miphy28lp_pll_gen sata_pll_gen[] = {288 {289 .bank = 0x00,290 .speed = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,291 .bias_boost_1 = 0x00,292 .bias_boost_2 = 0xae,293 .tx_ctrl_2 = 0x53,294 .tx_ctrl_3 = 0x00,295 .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,296 .rx_vga_gain = 0x00,297 .rx_equ_gain_1 = 0x7d,298 .rx_equ_gain_2 = 0x56,299 .rx_equ_gain_3 = 0x00,300 },301 {302 .bank = 0x01,303 .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,304 .bias_boost_1 = 0x00,305 .bias_boost_2 = 0xae,306 .tx_ctrl_2 = 0x72,307 .tx_ctrl_3 = 0x20,308 .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,309 .rx_vga_gain = 0x00,310 .rx_equ_gain_1 = 0x7d,311 .rx_equ_gain_2 = 0x56,312 .rx_equ_gain_3 = 0x00,313 },314 {315 .bank = 0x02,316 .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,317 .bias_boost_1 = 0x00,318 .bias_boost_2 = 0xae,319 .tx_ctrl_2 = 0xc0,320 .tx_ctrl_3 = 0x20,321 .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,322 .rx_vga_gain = 0x00,323 .rx_equ_gain_1 = 0x7d,324 .rx_equ_gain_2 = 0x56,325 .rx_equ_gain_3 = 0x00,326 },327};328 329static struct miphy28lp_pll_gen pcie_pll_gen[] = {330 {331 .bank = 0x00,332 .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,333 .bias_boost_1 = 0x00,334 .bias_boost_2 = 0xa5,335 .tx_ctrl_1 = TX_REG_STEP_N_25MV,336 .tx_ctrl_2 = 0x71,337 .tx_ctrl_3 = 0x60,338 .rx_k_gain = 0x98,339 .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,340 .rx_vga_gain = 0x00,341 .rx_equ_gain_1 = 0x79,342 .rx_equ_gain_2 = 0x56,343 },344 {345 .bank = 0x01,346 .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,347 .bias_boost_1 = 0x00,348 .bias_boost_2 = 0xa5,349 .tx_ctrl_1 = TX_REG_STEP_N_25MV,350 .tx_ctrl_2 = 0x70,351 .tx_ctrl_3 = 0x60,352 .rx_k_gain = 0xcc,353 .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,354 .rx_vga_gain = 0x00,355 .rx_equ_gain_1 = 0x78,356 .rx_equ_gain_2 = 0x07,357 },358};359 360static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)361{362 void __iomem *base = miphy_phy->base;363 u8 val;364 365 /* Putting Macro in reset */366 writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);367 368 val = RST_APPLI_SW | RST_CONF_SW;369 writeb_relaxed(val, base + MIPHY_CONF_RESET);370 371 writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);372 373 /* Bringing the MIPHY-CPU registers out of reset */374 if (miphy_phy->type == PHY_TYPE_PCIE) {375 val = AUTO_RST_RX | TERM_EN_SW;376 writeb_relaxed(val, base + MIPHY_CONTROL);377 } else {378 val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;379 writeb_relaxed(val, base + MIPHY_CONTROL);380 }381}382 383static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,384 struct pll_ratio *pll_ratio)385{386 void __iomem *base = miphy_phy->base;387 u8 val;388 389 /* Applying PLL Settings */390 writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);391 writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);392 393 /* PLL Ratio */394 writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);395 writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);396 writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);397 writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);398 writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);399 400 writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);401 402 val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;403 writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);404 405 val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;406 407 if (miphy_phy->type != PHY_TYPE_SATA)408 val |= OFFSET_COMPENSATION_EN;409 410 writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);411 412 if (miphy_phy->type == PHY_TYPE_USB3) {413 writeb_relaxed(0x00, base + MIPHY_CONF);414 writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);415 writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);416 writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);417 writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);418 419 val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;420 writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);421 }422 423}424 425static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)426{427 void __iomem *base = miphy_phy->base;428 int i;429 430 for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {431 struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];432 433 /* Banked settings */434 writeb_relaxed(gen->bank, base + MIPHY_CONF);435 writeb_relaxed(gen->speed, base + MIPHY_SPEED);436 writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);437 writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);438 439 /* TX buffer Settings */440 writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);441 writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);442 443 /* RX Buffer Settings */444 writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);445 writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);446 writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);447 writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);448 writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);449 }450}451 452static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)453{454 void __iomem *base = miphy_phy->base;455 int i;456 457 for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {458 struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];459 460 /* Banked settings */461 writeb_relaxed(gen->bank, base + MIPHY_CONF);462 writeb_relaxed(gen->speed, base + MIPHY_SPEED);463 writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);464 writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);465 466 /* TX buffer Settings */467 writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);468 writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);469 writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);470 471 writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);472 473 /* RX Buffer Settings */474 writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);475 writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);476 writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);477 writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);478 }479}480 481static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)482{483 u8 val;484 485 /* Waiting for Compensation to complete */486 return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6,487 val, val & COMP_DONE, 1, 5 * USEC_PER_SEC);488}489 490 491static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,492 struct pll_ratio *pll_ratio)493{494 void __iomem *base = miphy_phy->base;495 496 /* Poll for HFC ready after reset release */497 /* Compensation measurement */498 writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);499 500 writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);501 writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);502 writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);503 504 if (miphy_phy->type == PHY_TYPE_PCIE)505 writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);506 507 writeb_relaxed(0x00, base + MIPHY_RESET);508 writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);509 writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);510 511 /* TX compensation offset to re-center TX impedance */512 writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);513 514 if (miphy_phy->type == PHY_TYPE_PCIE)515 return miphy28lp_wait_compensation(miphy_phy);516 517 return 0;518}519 520static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)521{522 void __iomem *base = miphy_phy->base;523 u8 val;524 525 /* MIPHY Reset */526 writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);527 writeb_relaxed(0x00, base + MIPHY_CONF_RESET);528 writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);529 530 val = RST_COMP_SW | RST_PLL_SW;531 writeb_relaxed(val, base + MIPHY_RESET);532 533 writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);534 writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);535 writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);536 writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);537 writeb_relaxed(0x00, base + MIPHY_RESET);538 writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);539 writeb_relaxed(0x00, base + MIPHY_CONF);540 writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);541 writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);542 writeb_relaxed(0x00, base + MIPHY_CONF);543 writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);544 writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);545 writeb_relaxed(0x00, base + MIPHY_CONF);546}547 548static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)549{550 void __iomem *base = miphy_phy->base;551 u8 val;552 553 /* Compensate Tx impedance to avoid out of range values */554 /*555 * Enable the SSC on PLL for all banks556 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp557 */558 val = readb_relaxed(base + MIPHY_BOUNDARY_2);559 val |= SSC_EN_SW;560 writeb_relaxed(val, base + MIPHY_BOUNDARY_2);561 562 val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);563 val |= SSC_SEL;564 writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);565 566 for (val = 0; val < MIPHY_SATA_BANK_NB; val++) {567 writeb_relaxed(val, base + MIPHY_CONF);568 569 /* Add value to each reference clock cycle */570 /* and define the period length of the SSC */571 writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);572 writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3);573 writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4);574 575 /* Clear any previous request */576 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);577 578 /* requests the PLL to take in account new parameters */579 writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);580 581 /* To be sure there is no other pending requests */582 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);583 }584}585 586static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)587{588 void __iomem *base = miphy_phy->base;589 u8 val;590 591 /* Compensate Tx impedance to avoid out of range values */592 /*593 * Enable the SSC on PLL for all banks594 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp595 */596 val = readb_relaxed(base + MIPHY_BOUNDARY_2);597 val |= SSC_EN_SW;598 writeb_relaxed(val, base + MIPHY_BOUNDARY_2);599 600 val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);601 val |= SSC_SEL;602 writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);603 604 for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) {605 writeb_relaxed(val, base + MIPHY_CONF);606 607 /* Validate Step component */608 writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3);609 writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);610 611 /* Validate Period component */612 writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);613 writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);614 615 /* Clear any previous request */616 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);617 618 /* requests the PLL to take in account new parameters */619 writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);620 621 /* To be sure there is no other pending requests */622 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);623 }624}625 626static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy)627{628 /* Compensate Tx impedance to avoid out of range values */629 writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP);630}631 632static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)633{634 void __iomem *base = miphy_phy->base;635 int err;636 u8 val;637 638 /* Putting Macro in reset */639 miphy28lp_set_reset(miphy_phy);640 641 /* PLL calibration */642 miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);643 644 /* Banked settings Gen1/Gen2/Gen3 */645 miphy28lp_sata_config_gen(miphy_phy);646 647 /* Power control */648 /* Input bridge enable, manual input bridge control */649 writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);650 651 /* Macro out of reset */652 writeb_relaxed(0x00, base + MIPHY_CONF_RESET);653 654 /* Poll for HFC ready after reset release */655 /* Compensation measurement */656 err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);657 if (err)658 return err;659 660 if (miphy_phy->px_rx_pol_inv) {661 /* Invert Rx polarity */662 val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);663 val |= PX_RX_POL;664 writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);665 }666 667 if (miphy_phy->ssc)668 miphy_sata_tune_ssc(miphy_phy);669 670 if (miphy_phy->tx_impedance)671 miphy_tune_tx_impedance(miphy_phy);672 673 return 0;674}675 676static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)677{678 void __iomem *base = miphy_phy->base;679 int err;680 681 /* Putting Macro in reset */682 miphy28lp_set_reset(miphy_phy);683 684 /* PLL calibration */685 miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);686 687 /* Banked settings Gen1/Gen2 */688 miphy28lp_pcie_config_gen(miphy_phy);689 690 /* Power control */691 /* Input bridge enable, manual input bridge control */692 writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);693 694 /* Macro out of reset */695 writeb_relaxed(0x00, base + MIPHY_CONF_RESET);696 697 /* Poll for HFC ready after reset release */698 /* Compensation measurement */699 err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);700 if (err)701 return err;702 703 if (miphy_phy->ssc)704 miphy_pcie_tune_ssc(miphy_phy);705 706 if (miphy_phy->tx_impedance)707 miphy_tune_tx_impedance(miphy_phy);708 709 return 0;710}711 712 713static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)714{715 void __iomem *base = miphy_phy->base;716 u8 val;717 718 /* Putting Macro in reset */719 miphy28lp_set_reset(miphy_phy);720 721 /* PLL calibration */722 miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);723 724 /* Writing The Speed Rate */725 writeb_relaxed(0x00, base + MIPHY_CONF);726 727 val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;728 writeb_relaxed(val, base + MIPHY_SPEED);729 730 /* RX Channel compensation and calibration */731 writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);732 writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);733 writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);734 735 val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |736 CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;737 writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);738 writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);739 writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);740 741 val = EQ_DC_GAIN | VGA_GAIN;742 writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);743 writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);744 writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);745 746 /* TX compensation offset to re-center TX impedance */747 writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);748 749 /* Enable GENSEL_SEL and SSC */750 /* TX_SEL=0 swing preemp forced by pipe registres */751 val = SSC_SEL | GENSEL_SEL;752 writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);753 754 /* MIPHY Bias boost */755 writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);756 writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);757 758 /* SSC modulation */759 writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);760 761 /* MIPHY TX control */762 writeb_relaxed(0x00, base + MIPHY_CONF);763 764 /* Validate Step component */765 writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);766 writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);767 768 /* Validate Period component */769 writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);770 writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);771 772 /* Clear any previous request */773 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);774 775 /* requests the PLL to take in account new parameters */776 writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);777 778 /* To be sure there is no other pending requests */779 writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);780 781 /* Rx PI controller settings */782 writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);783 784 /* MIPHY RX input bridge control */785 /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */786 writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);787 writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);788 writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);789 790 /* MIPHY Reset for usb3 */791 miphy28_usb3_miphy_reset(miphy_phy);792}793 794static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)795{796 u8 mask = HFC_PLL | HFC_RDY;797 u8 val;798 799 /*800 * For PCIe and USB3 check only that PLL and HFC are ready801 * For SATA check also that phy is ready!802 */803 if (miphy_phy->type == PHY_TYPE_SATA)804 mask |= PHY_RDY;805 806 return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1,807 val, (val & mask) == mask, 1,808 5 * USEC_PER_SEC);809}810 811static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)812{813 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;814 u32 val;815 816 if (!miphy_phy->osc_rdy)817 return 0;818 819 if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])820 return -EINVAL;821 822 return regmap_read_poll_timeout(miphy_dev->regmap,823 miphy_phy->syscfg_reg[SYSCFG_STATUS],824 val, val & MIPHY_OSC_RDY, 1,825 5 * USEC_PER_SEC);826}827 828static int miphy28lp_get_resource_byname(struct device_node *child,829 char *rname, struct resource *res)830{831 int index;832 833 index = of_property_match_string(child, "reg-names", rname);834 if (index < 0)835 return -ENODEV;836 837 return of_address_to_resource(child, index, res);838}839 840static int miphy28lp_get_one_addr(struct device *dev,841 struct device_node *child, char *rname,842 void __iomem **base)843{844 struct resource res;845 int ret;846 847 ret = miphy28lp_get_resource_byname(child, rname, &res);848 if (!ret) {849 *base = devm_ioremap(dev, res.start, resource_size(&res));850 if (!*base) {851 dev_err(dev, "failed to ioremap %s address region\n"852 , rname);853 return -ENOENT;854 }855 }856 857 return 0;858}859 860/* MiPHY reset and sysconf setup */861static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)862{863 int err;864 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;865 866 if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])867 return -EINVAL;868 869 err = reset_control_assert(miphy_phy->miphy_rst);870 if (err) {871 dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");872 return err;873 }874 875 if (miphy_phy->osc_force_ext)876 miphy_val |= MIPHY_OSC_FORCE_EXT;877 878 regmap_update_bits(miphy_dev->regmap,879 miphy_phy->syscfg_reg[SYSCFG_CTRL],880 MIPHY_CTRL_MASK, miphy_val);881 882 err = reset_control_deassert(miphy_phy->miphy_rst);883 if (err) {884 dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");885 return err;886 }887 888 return miphy_osc_is_ready(miphy_phy);889}890 891static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)892{893 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;894 int err, sata_conf = SATA_CTRL_SELECT_SATA;895 896 if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||897 (!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||898 (!miphy_phy->base))899 return -EINVAL;900 901 dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);902 903 /* Configure the glue-logic */904 sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);905 906 regmap_update_bits(miphy_dev->regmap,907 miphy_phy->syscfg_reg[SYSCFG_SATA],908 SATA_CTRL_MASK, sata_conf);909 910 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],911 PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);912 913 /* MiPHY path and clocking init */914 err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);915 916 if (err) {917 dev_err(miphy_dev->dev, "SATA phy setup failed\n");918 return err;919 }920 921 /* initialize miphy */922 miphy28lp_configure_sata(miphy_phy);923 924 return miphy_is_ready(miphy_phy);925}926 927static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)928{929 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;930 int err;931 932 if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||933 (!miphy_phy->syscfg_reg[SYSCFG_PCI])934 || (!miphy_phy->base) || (!miphy_phy->pipebase))935 return -EINVAL;936 937 dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);938 939 /* Configure the glue-logic */940 regmap_update_bits(miphy_dev->regmap,941 miphy_phy->syscfg_reg[SYSCFG_SATA],942 SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);943 944 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],945 PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);946 947 /* MiPHY path and clocking init */948 err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);949 950 if (err) {951 dev_err(miphy_dev->dev, "PCIe phy setup failed\n");952 return err;953 }954 955 /* initialize miphy */956 err = miphy28lp_configure_pcie(miphy_phy);957 if (err)958 return err;959 960 /* PIPE Wrapper Configuration */961 writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */962 writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */963 writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */964 writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */965 writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */966 writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */967 968 /* Wait for phy_ready */969 return miphy_is_ready(miphy_phy);970}971 972static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)973{974 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;975 int err;976 977 if ((!miphy_phy->base) || (!miphy_phy->pipebase))978 return -EINVAL;979 980 dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);981 982 /* MiPHY path and clocking init */983 err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);984 if (err) {985 dev_err(miphy_dev->dev, "USB3 phy setup failed\n");986 return err;987 }988 989 /* initialize miphy */990 miphy28lp_configure_usb3(miphy_phy);991 992 /* PIPE Wrapper Configuration */993 writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);994 writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);995 writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);996 writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);997 writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);998 writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);999 1000 /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */1001 writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);1002 writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);1003 writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);1004 writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);1005 writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);1006 writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);1007 writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);1008 writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);1009 1010 return miphy_is_ready(miphy_phy);1011}1012 1013static int miphy28lp_init(struct phy *phy)1014{1015 struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);1016 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1017 int ret;1018 1019 mutex_lock(&miphy_dev->miphy_mutex);1020 1021 switch (miphy_phy->type) {1022 1023 case PHY_TYPE_SATA:1024 ret = miphy28lp_init_sata(miphy_phy);1025 break;1026 case PHY_TYPE_PCIE:1027 ret = miphy28lp_init_pcie(miphy_phy);1028 break;1029 case PHY_TYPE_USB3:1030 ret = miphy28lp_init_usb3(miphy_phy);1031 break;1032 default:1033 ret = -EINVAL;1034 break;1035 }1036 1037 mutex_unlock(&miphy_dev->miphy_mutex);1038 1039 return ret;1040}1041 1042static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)1043{1044 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1045 struct device_node *phynode = miphy_phy->phy->dev.of_node;1046 int err;1047 1048 if ((miphy_phy->type != PHY_TYPE_SATA) &&1049 (miphy_phy->type != PHY_TYPE_PCIE) &&1050 (miphy_phy->type != PHY_TYPE_USB3)) {1051 return -EINVAL;1052 }1053 1054 err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,1055 PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],1056 &miphy_phy->base);1057 if (err)1058 return err;1059 1060 if ((miphy_phy->type == PHY_TYPE_PCIE) ||1061 (miphy_phy->type == PHY_TYPE_USB3)) {1062 err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",1063 &miphy_phy->pipebase);1064 if (err)1065 return err;1066 }1067 1068 return 0;1069}1070 1071static struct phy *miphy28lp_xlate(struct device *dev,1072 const struct of_phandle_args *args)1073{1074 struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);1075 struct miphy28lp_phy *miphy_phy = NULL;1076 struct device_node *phynode = args->np;1077 int ret, index = 0;1078 1079 if (args->args_count != 1) {1080 dev_err(dev, "Invalid number of cells in 'phy' property\n");1081 return ERR_PTR(-EINVAL);1082 }1083 1084 for (index = 0; index < miphy_dev->nphys; index++)1085 if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {1086 miphy_phy = miphy_dev->phys[index];1087 break;1088 }1089 1090 if (!miphy_phy) {1091 dev_err(dev, "Failed to find appropriate phy\n");1092 return ERR_PTR(-EINVAL);1093 }1094 1095 miphy_phy->type = args->args[0];1096 1097 ret = miphy28lp_get_addr(miphy_phy);1098 if (ret < 0)1099 return ERR_PTR(ret);1100 1101 return miphy_phy->phy;1102}1103 1104static const struct phy_ops miphy28lp_ops = {1105 .init = miphy28lp_init,1106 .owner = THIS_MODULE,1107};1108 1109static int miphy28lp_probe_resets(struct device_node *node,1110 struct miphy28lp_phy *miphy_phy)1111{1112 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;1113 int err;1114 1115 miphy_phy->miphy_rst =1116 of_reset_control_get_shared(node, "miphy-sw-rst");1117 1118 if (IS_ERR(miphy_phy->miphy_rst)) {1119 dev_err(miphy_dev->dev,1120 "miphy soft reset control not defined\n");1121 return PTR_ERR(miphy_phy->miphy_rst);1122 }1123 1124 err = reset_control_deassert(miphy_phy->miphy_rst);1125 if (err) {1126 dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");1127 return err;1128 }1129 1130 return 0;1131}1132 1133static int miphy28lp_of_probe(struct device_node *np,1134 struct miphy28lp_phy *miphy_phy)1135{1136 int i;1137 u32 ctrlreg;1138 1139 miphy_phy->osc_force_ext =1140 of_property_read_bool(np, "st,osc-force-ext");1141 1142 miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");1143 1144 miphy_phy->px_rx_pol_inv =1145 of_property_read_bool(np, "st,px_rx_pol_inv");1146 1147 miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");1148 1149 miphy_phy->tx_impedance =1150 of_property_read_bool(np, "st,tx-impedance-comp");1151 1152 of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);1153 if (!miphy_phy->sata_gen)1154 miphy_phy->sata_gen = SATA_GEN1;1155 1156 for (i = 0; i < SYSCFG_REG_MAX; i++) {1157 if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))1158 miphy_phy->syscfg_reg[i] = ctrlreg;1159 }1160 1161 return 0;1162}1163 1164static int miphy28lp_probe(struct platform_device *pdev)1165{1166 struct device_node *child, *np = pdev->dev.of_node;1167 struct miphy28lp_dev *miphy_dev;1168 struct phy_provider *provider;1169 struct phy *phy;1170 int ret, port = 0;1171 1172 miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);1173 if (!miphy_dev)1174 return -ENOMEM;1175 1176 miphy_dev->nphys = of_get_child_count(np);1177 miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys,1178 sizeof(*miphy_dev->phys), GFP_KERNEL);1179 if (!miphy_dev->phys)1180 return -ENOMEM;1181 1182 miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");1183 if (IS_ERR(miphy_dev->regmap)) {1184 dev_err(miphy_dev->dev, "No syscfg phandle specified\n");1185 return PTR_ERR(miphy_dev->regmap);1186 }1187 1188 miphy_dev->dev = &pdev->dev;1189 1190 dev_set_drvdata(&pdev->dev, miphy_dev);1191 1192 mutex_init(&miphy_dev->miphy_mutex);1193 1194 for_each_child_of_node(np, child) {1195 struct miphy28lp_phy *miphy_phy;1196 1197 miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),1198 GFP_KERNEL);1199 if (!miphy_phy) {1200 ret = -ENOMEM;1201 goto put_child;1202 }1203 1204 miphy_dev->phys[port] = miphy_phy;1205 1206 phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);1207 if (IS_ERR(phy)) {1208 dev_err(&pdev->dev, "failed to create PHY\n");1209 ret = PTR_ERR(phy);1210 goto put_child;1211 }1212 1213 miphy_dev->phys[port]->phy = phy;1214 miphy_dev->phys[port]->phydev = miphy_dev;1215 1216 ret = miphy28lp_of_probe(child, miphy_phy);1217 if (ret)1218 goto put_child;1219 1220 ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);1221 if (ret)1222 goto put_child;1223 1224 phy_set_drvdata(phy, miphy_dev->phys[port]);1225 port++;1226 1227 }1228 1229 provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);1230 return PTR_ERR_OR_ZERO(provider);1231put_child:1232 of_node_put(child);1233 return ret;1234}1235 1236static const struct of_device_id miphy28lp_of_match[] = {1237 {.compatible = "st,miphy28lp-phy", },1238 {},1239};1240 1241MODULE_DEVICE_TABLE(of, miphy28lp_of_match);1242 1243static struct platform_driver miphy28lp_driver = {1244 .probe = miphy28lp_probe,1245 .driver = {1246 .name = "miphy28lp-phy",1247 .of_match_table = miphy28lp_of_match,1248 }1249};1250 1251module_platform_driver(miphy28lp_driver);1252 1253MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");1254MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");1255MODULE_LICENSE("GPL v2");1256