18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014 STMicroelectronics 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407). 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Alexandre Torgue <alexandre.torgue@st.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 178c2ecf20Sopenharmony_ci#include <linux/of_address.h> 188c2ecf20Sopenharmony_ci#include <linux/clk.h> 198c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 228c2ecf20Sopenharmony_ci#include <linux/regmap.h> 238c2ecf20Sopenharmony_ci#include <linux/reset.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <dt-bindings/phy/phy.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* MiPHY registers */ 288c2ecf20Sopenharmony_ci#define MIPHY_CONF_RESET 0x00 298c2ecf20Sopenharmony_ci#define RST_APPLI_SW BIT(0) 308c2ecf20Sopenharmony_ci#define RST_CONF_SW BIT(1) 318c2ecf20Sopenharmony_ci#define RST_MACRO_SW BIT(2) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define MIPHY_RESET 0x01 348c2ecf20Sopenharmony_ci#define RST_PLL_SW BIT(0) 358c2ecf20Sopenharmony_ci#define RST_COMP_SW BIT(2) 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define MIPHY_STATUS_1 0x02 388c2ecf20Sopenharmony_ci#define PHY_RDY BIT(0) 398c2ecf20Sopenharmony_ci#define HFC_RDY BIT(1) 408c2ecf20Sopenharmony_ci#define HFC_PLL BIT(2) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define MIPHY_CONTROL 0x04 438c2ecf20Sopenharmony_ci#define TERM_EN_SW BIT(2) 448c2ecf20Sopenharmony_ci#define DIS_LINK_RST BIT(3) 458c2ecf20Sopenharmony_ci#define AUTO_RST_RX BIT(4) 468c2ecf20Sopenharmony_ci#define PX_RX_POL BIT(5) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define MIPHY_BOUNDARY_SEL 0x0a 498c2ecf20Sopenharmony_ci#define TX_SEL BIT(6) 508c2ecf20Sopenharmony_ci#define SSC_SEL BIT(4) 518c2ecf20Sopenharmony_ci#define GENSEL_SEL BIT(0) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define MIPHY_BOUNDARY_1 0x0b 548c2ecf20Sopenharmony_ci#define MIPHY_BOUNDARY_2 0x0c 558c2ecf20Sopenharmony_ci#define SSC_EN_SW BIT(2) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define MIPHY_PLL_CLKREF_FREQ 0x0d 588c2ecf20Sopenharmony_ci#define MIPHY_SPEED 0x0e 598c2ecf20Sopenharmony_ci#define TX_SPDSEL_80DEC 0 608c2ecf20Sopenharmony_ci#define TX_SPDSEL_40DEC 1 618c2ecf20Sopenharmony_ci#define TX_SPDSEL_20DEC 2 628c2ecf20Sopenharmony_ci#define RX_SPDSEL_80DEC 0 638c2ecf20Sopenharmony_ci#define RX_SPDSEL_40DEC (1 << 2) 648c2ecf20Sopenharmony_ci#define RX_SPDSEL_20DEC (2 << 2) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define MIPHY_CONF 0x0f 678c2ecf20Sopenharmony_ci#define MIPHY_CTRL_TEST_SEL 0x20 688c2ecf20Sopenharmony_ci#define MIPHY_CTRL_TEST_1 0x21 698c2ecf20Sopenharmony_ci#define MIPHY_CTRL_TEST_2 0x22 708c2ecf20Sopenharmony_ci#define MIPHY_CTRL_TEST_3 0x23 718c2ecf20Sopenharmony_ci#define MIPHY_CTRL_TEST_4 0x24 728c2ecf20Sopenharmony_ci#define MIPHY_FEEDBACK_TEST 0x25 738c2ecf20Sopenharmony_ci#define MIPHY_DEBUG_BUS 0x26 748c2ecf20Sopenharmony_ci#define MIPHY_DEBUG_STATUS_MSB 0x27 758c2ecf20Sopenharmony_ci#define MIPHY_DEBUG_STATUS_LSB 0x28 768c2ecf20Sopenharmony_ci#define MIPHY_PWR_RAIL_1 0x29 778c2ecf20Sopenharmony_ci#define MIPHY_PWR_RAIL_2 0x2a 788c2ecf20Sopenharmony_ci#define MIPHY_SYNCHAR_CONTROL 0x30 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define MIPHY_COMP_FSM_1 0x3a 818c2ecf20Sopenharmony_ci#define COMP_START BIT(6) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define MIPHY_COMP_FSM_6 0x3f 848c2ecf20Sopenharmony_ci#define COMP_DONE BIT(7) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define MIPHY_COMP_POSTP 0x42 878c2ecf20Sopenharmony_ci#define MIPHY_TX_CTRL_1 0x49 888c2ecf20Sopenharmony_ci#define TX_REG_STEP_0V 0 898c2ecf20Sopenharmony_ci#define TX_REG_STEP_P_25MV 1 908c2ecf20Sopenharmony_ci#define TX_REG_STEP_P_50MV 2 918c2ecf20Sopenharmony_ci#define TX_REG_STEP_N_25MV 7 928c2ecf20Sopenharmony_ci#define TX_REG_STEP_N_50MV 6 938c2ecf20Sopenharmony_ci#define TX_REG_STEP_N_75MV 5 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define MIPHY_TX_CTRL_2 0x4a 968c2ecf20Sopenharmony_ci#define TX_SLEW_SW_40_PS 0 978c2ecf20Sopenharmony_ci#define TX_SLEW_SW_80_PS 1 988c2ecf20Sopenharmony_ci#define TX_SLEW_SW_120_PS 2 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define MIPHY_TX_CTRL_3 0x4b 1018c2ecf20Sopenharmony_ci#define MIPHY_TX_CAL_MAN 0x4e 1028c2ecf20Sopenharmony_ci#define TX_SLEW_CAL_MAN_EN BIT(0) 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci#define MIPHY_TST_BIAS_BOOST_2 0x62 1058c2ecf20Sopenharmony_ci#define MIPHY_BIAS_BOOST_1 0x63 1068c2ecf20Sopenharmony_ci#define MIPHY_BIAS_BOOST_2 0x64 1078c2ecf20Sopenharmony_ci#define MIPHY_RX_DESBUFF_FDB_2 0x67 1088c2ecf20Sopenharmony_ci#define MIPHY_RX_DESBUFF_FDB_3 0x68 1098c2ecf20Sopenharmony_ci#define MIPHY_SIGDET_COMPENS1 0x69 1108c2ecf20Sopenharmony_ci#define MIPHY_SIGDET_COMPENS2 0x6a 1118c2ecf20Sopenharmony_ci#define MIPHY_JITTER_PERIOD 0x6b 1128c2ecf20Sopenharmony_ci#define MIPHY_JITTER_AMPLITUDE_1 0x6c 1138c2ecf20Sopenharmony_ci#define MIPHY_JITTER_AMPLITUDE_2 0x6d 1148c2ecf20Sopenharmony_ci#define MIPHY_JITTER_AMPLITUDE_3 0x6e 1158c2ecf20Sopenharmony_ci#define MIPHY_RX_K_GAIN 0x78 1168c2ecf20Sopenharmony_ci#define MIPHY_RX_BUFFER_CTRL 0x7a 1178c2ecf20Sopenharmony_ci#define VGA_GAIN BIT(0) 1188c2ecf20Sopenharmony_ci#define EQ_DC_GAIN BIT(2) 1198c2ecf20Sopenharmony_ci#define EQ_BOOST_GAIN BIT(3) 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#define MIPHY_RX_VGA_GAIN 0x7b 1228c2ecf20Sopenharmony_ci#define MIPHY_RX_EQU_GAIN_1 0x7f 1238c2ecf20Sopenharmony_ci#define MIPHY_RX_EQU_GAIN_2 0x80 1248c2ecf20Sopenharmony_ci#define MIPHY_RX_EQU_GAIN_3 0x81 1258c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_CTRL_1 0x97 1268c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_CTRL_2 0x98 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_OFFSET_CTRL 0x99 1298c2ecf20Sopenharmony_ci#define CAL_OFFSET_VGA_64 (0x03 << 0) 1308c2ecf20Sopenharmony_ci#define CAL_OFFSET_THRESHOLD_64 (0x03 << 2) 1318c2ecf20Sopenharmony_ci#define VGA_OFFSET_POLARITY BIT(4) 1328c2ecf20Sopenharmony_ci#define OFFSET_COMPENSATION_EN BIT(6) 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_VGA_STEP 0x9a 1358c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_EYE_MIN 0x9d 1368c2ecf20Sopenharmony_ci#define MIPHY_RX_CAL_OPT_LENGTH 0x9f 1378c2ecf20Sopenharmony_ci#define MIPHY_RX_LOCK_CTRL_1 0xc1 1388c2ecf20Sopenharmony_ci#define MIPHY_RX_LOCK_SETTINGS_OPT 0xc2 1398c2ecf20Sopenharmony_ci#define MIPHY_RX_LOCK_STEP 0xc4 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci#define MIPHY_RX_SIGDET_SLEEP_OA 0xc9 1428c2ecf20Sopenharmony_ci#define MIPHY_RX_SIGDET_SLEEP_SEL 0xca 1438c2ecf20Sopenharmony_ci#define MIPHY_RX_SIGDET_WAIT_SEL 0xcb 1448c2ecf20Sopenharmony_ci#define MIPHY_RX_SIGDET_DATA_SEL 0xcc 1458c2ecf20Sopenharmony_ci#define EN_ULTRA_LOW_POWER BIT(0) 1468c2ecf20Sopenharmony_ci#define EN_FIRST_HALF BIT(1) 1478c2ecf20Sopenharmony_ci#define EN_SECOND_HALF BIT(2) 1488c2ecf20Sopenharmony_ci#define EN_DIGIT_SIGNAL_CHECK BIT(3) 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define MIPHY_RX_POWER_CTRL_1 0xcd 1518c2ecf20Sopenharmony_ci#define MIPHY_RX_POWER_CTRL_2 0xce 1528c2ecf20Sopenharmony_ci#define MIPHY_PLL_CALSET_CTRL 0xd3 1538c2ecf20Sopenharmony_ci#define MIPHY_PLL_CALSET_1 0xd4 1548c2ecf20Sopenharmony_ci#define MIPHY_PLL_CALSET_2 0xd5 1558c2ecf20Sopenharmony_ci#define MIPHY_PLL_CALSET_3 0xd6 1568c2ecf20Sopenharmony_ci#define MIPHY_PLL_CALSET_4 0xd7 1578c2ecf20Sopenharmony_ci#define MIPHY_PLL_SBR_1 0xe3 1588c2ecf20Sopenharmony_ci#define SET_NEW_CHANGE BIT(1) 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#define MIPHY_PLL_SBR_2 0xe4 1618c2ecf20Sopenharmony_ci#define MIPHY_PLL_SBR_3 0xe5 1628c2ecf20Sopenharmony_ci#define MIPHY_PLL_SBR_4 0xe6 1638c2ecf20Sopenharmony_ci#define MIPHY_PLL_COMMON_MISC_2 0xe9 1648c2ecf20Sopenharmony_ci#define START_ACT_FILT BIT(6) 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci#define MIPHY_PLL_SPAREIN 0xeb 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* 1698c2ecf20Sopenharmony_ci * On STiH407 the glue logic can be different among MiPHY devices; for example: 1708c2ecf20Sopenharmony_ci * MiPHY0: OSC_FORCE_EXT means: 1718c2ecf20Sopenharmony_ci * 0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1 1728c2ecf20Sopenharmony_ci * MiPHY1: OSC_FORCE_EXT means: 1738c2ecf20Sopenharmony_ci * 1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1 1748c2ecf20Sopenharmony_ci * Some devices have not the possibility to check if the osc is ready. 1758c2ecf20Sopenharmony_ci */ 1768c2ecf20Sopenharmony_ci#define MIPHY_OSC_FORCE_EXT BIT(3) 1778c2ecf20Sopenharmony_ci#define MIPHY_OSC_RDY BIT(5) 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#define MIPHY_CTRL_MASK 0x0f 1808c2ecf20Sopenharmony_ci#define MIPHY_CTRL_DEFAULT 0 1818c2ecf20Sopenharmony_ci#define MIPHY_CTRL_SYNC_D_EN BIT(2) 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/* SATA / PCIe defines */ 1848c2ecf20Sopenharmony_ci#define SATA_CTRL_MASK 0x07 1858c2ecf20Sopenharmony_ci#define PCIE_CTRL_MASK 0xff 1868c2ecf20Sopenharmony_ci#define SATA_CTRL_SELECT_SATA 1 1878c2ecf20Sopenharmony_ci#define SATA_CTRL_SELECT_PCIE 0 1888c2ecf20Sopenharmony_ci#define SYSCFG_PCIE_PCIE_VAL 0x80 1898c2ecf20Sopenharmony_ci#define SATA_SPDMODE 1 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci#define MIPHY_SATA_BANK_NB 3 1928c2ecf20Sopenharmony_ci#define MIPHY_PCIE_BANK_NB 2 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cienum { 1958c2ecf20Sopenharmony_ci SYSCFG_CTRL, 1968c2ecf20Sopenharmony_ci SYSCFG_STATUS, 1978c2ecf20Sopenharmony_ci SYSCFG_PCI, 1988c2ecf20Sopenharmony_ci SYSCFG_SATA, 1998c2ecf20Sopenharmony_ci SYSCFG_REG_MAX, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistruct miphy28lp_phy { 2038c2ecf20Sopenharmony_ci struct phy *phy; 2048c2ecf20Sopenharmony_ci struct miphy28lp_dev *phydev; 2058c2ecf20Sopenharmony_ci void __iomem *base; 2068c2ecf20Sopenharmony_ci void __iomem *pipebase; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci bool osc_force_ext; 2098c2ecf20Sopenharmony_ci bool osc_rdy; 2108c2ecf20Sopenharmony_ci bool px_rx_pol_inv; 2118c2ecf20Sopenharmony_ci bool ssc; 2128c2ecf20Sopenharmony_ci bool tx_impedance; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci struct reset_control *miphy_rst; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci u32 sata_gen; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* Sysconfig registers offsets needed to configure the device */ 2198c2ecf20Sopenharmony_ci u32 syscfg_reg[SYSCFG_REG_MAX]; 2208c2ecf20Sopenharmony_ci u8 type; 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistruct miphy28lp_dev { 2248c2ecf20Sopenharmony_ci struct device *dev; 2258c2ecf20Sopenharmony_ci struct regmap *regmap; 2268c2ecf20Sopenharmony_ci struct mutex miphy_mutex; 2278c2ecf20Sopenharmony_ci struct miphy28lp_phy **phys; 2288c2ecf20Sopenharmony_ci int nphys; 2298c2ecf20Sopenharmony_ci}; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistruct miphy_initval { 2328c2ecf20Sopenharmony_ci u16 reg; 2338c2ecf20Sopenharmony_ci u16 val; 2348c2ecf20Sopenharmony_ci}; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cienum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 }; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" }; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistruct pll_ratio { 2418c2ecf20Sopenharmony_ci int clk_ref; 2428c2ecf20Sopenharmony_ci int calset_1; 2438c2ecf20Sopenharmony_ci int calset_2; 2448c2ecf20Sopenharmony_ci int calset_3; 2458c2ecf20Sopenharmony_ci int calset_4; 2468c2ecf20Sopenharmony_ci int cal_ctrl; 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic struct pll_ratio sata_pll_ratio = { 2508c2ecf20Sopenharmony_ci .clk_ref = 0x1e, 2518c2ecf20Sopenharmony_ci .calset_1 = 0xc8, 2528c2ecf20Sopenharmony_ci .calset_2 = 0x00, 2538c2ecf20Sopenharmony_ci .calset_3 = 0x00, 2548c2ecf20Sopenharmony_ci .calset_4 = 0x00, 2558c2ecf20Sopenharmony_ci .cal_ctrl = 0x00, 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic struct pll_ratio pcie_pll_ratio = { 2598c2ecf20Sopenharmony_ci .clk_ref = 0x1e, 2608c2ecf20Sopenharmony_ci .calset_1 = 0xa6, 2618c2ecf20Sopenharmony_ci .calset_2 = 0xaa, 2628c2ecf20Sopenharmony_ci .calset_3 = 0xaa, 2638c2ecf20Sopenharmony_ci .calset_4 = 0x00, 2648c2ecf20Sopenharmony_ci .cal_ctrl = 0x00, 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic struct pll_ratio usb3_pll_ratio = { 2688c2ecf20Sopenharmony_ci .clk_ref = 0x1e, 2698c2ecf20Sopenharmony_ci .calset_1 = 0xa6, 2708c2ecf20Sopenharmony_ci .calset_2 = 0xaa, 2718c2ecf20Sopenharmony_ci .calset_3 = 0xaa, 2728c2ecf20Sopenharmony_ci .calset_4 = 0x04, 2738c2ecf20Sopenharmony_ci .cal_ctrl = 0x00, 2748c2ecf20Sopenharmony_ci}; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistruct miphy28lp_pll_gen { 2778c2ecf20Sopenharmony_ci int bank; 2788c2ecf20Sopenharmony_ci int speed; 2798c2ecf20Sopenharmony_ci int bias_boost_1; 2808c2ecf20Sopenharmony_ci int bias_boost_2; 2818c2ecf20Sopenharmony_ci int tx_ctrl_1; 2828c2ecf20Sopenharmony_ci int tx_ctrl_2; 2838c2ecf20Sopenharmony_ci int tx_ctrl_3; 2848c2ecf20Sopenharmony_ci int rx_k_gain; 2858c2ecf20Sopenharmony_ci int rx_vga_gain; 2868c2ecf20Sopenharmony_ci int rx_equ_gain_1; 2878c2ecf20Sopenharmony_ci int rx_equ_gain_2; 2888c2ecf20Sopenharmony_ci int rx_equ_gain_3; 2898c2ecf20Sopenharmony_ci int rx_buff_ctrl; 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic struct miphy28lp_pll_gen sata_pll_gen[] = { 2938c2ecf20Sopenharmony_ci { 2948c2ecf20Sopenharmony_ci .bank = 0x00, 2958c2ecf20Sopenharmony_ci .speed = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC, 2968c2ecf20Sopenharmony_ci .bias_boost_1 = 0x00, 2978c2ecf20Sopenharmony_ci .bias_boost_2 = 0xae, 2988c2ecf20Sopenharmony_ci .tx_ctrl_2 = 0x53, 2998c2ecf20Sopenharmony_ci .tx_ctrl_3 = 0x00, 3008c2ecf20Sopenharmony_ci .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, 3018c2ecf20Sopenharmony_ci .rx_vga_gain = 0x00, 3028c2ecf20Sopenharmony_ci .rx_equ_gain_1 = 0x7d, 3038c2ecf20Sopenharmony_ci .rx_equ_gain_2 = 0x56, 3048c2ecf20Sopenharmony_ci .rx_equ_gain_3 = 0x00, 3058c2ecf20Sopenharmony_ci }, 3068c2ecf20Sopenharmony_ci { 3078c2ecf20Sopenharmony_ci .bank = 0x01, 3088c2ecf20Sopenharmony_ci .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC, 3098c2ecf20Sopenharmony_ci .bias_boost_1 = 0x00, 3108c2ecf20Sopenharmony_ci .bias_boost_2 = 0xae, 3118c2ecf20Sopenharmony_ci .tx_ctrl_2 = 0x72, 3128c2ecf20Sopenharmony_ci .tx_ctrl_3 = 0x20, 3138c2ecf20Sopenharmony_ci .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, 3148c2ecf20Sopenharmony_ci .rx_vga_gain = 0x00, 3158c2ecf20Sopenharmony_ci .rx_equ_gain_1 = 0x7d, 3168c2ecf20Sopenharmony_ci .rx_equ_gain_2 = 0x56, 3178c2ecf20Sopenharmony_ci .rx_equ_gain_3 = 0x00, 3188c2ecf20Sopenharmony_ci }, 3198c2ecf20Sopenharmony_ci { 3208c2ecf20Sopenharmony_ci .bank = 0x02, 3218c2ecf20Sopenharmony_ci .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC, 3228c2ecf20Sopenharmony_ci .bias_boost_1 = 0x00, 3238c2ecf20Sopenharmony_ci .bias_boost_2 = 0xae, 3248c2ecf20Sopenharmony_ci .tx_ctrl_2 = 0xc0, 3258c2ecf20Sopenharmony_ci .tx_ctrl_3 = 0x20, 3268c2ecf20Sopenharmony_ci .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, 3278c2ecf20Sopenharmony_ci .rx_vga_gain = 0x00, 3288c2ecf20Sopenharmony_ci .rx_equ_gain_1 = 0x7d, 3298c2ecf20Sopenharmony_ci .rx_equ_gain_2 = 0x56, 3308c2ecf20Sopenharmony_ci .rx_equ_gain_3 = 0x00, 3318c2ecf20Sopenharmony_ci }, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic struct miphy28lp_pll_gen pcie_pll_gen[] = { 3358c2ecf20Sopenharmony_ci { 3368c2ecf20Sopenharmony_ci .bank = 0x00, 3378c2ecf20Sopenharmony_ci .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC, 3388c2ecf20Sopenharmony_ci .bias_boost_1 = 0x00, 3398c2ecf20Sopenharmony_ci .bias_boost_2 = 0xa5, 3408c2ecf20Sopenharmony_ci .tx_ctrl_1 = TX_REG_STEP_N_25MV, 3418c2ecf20Sopenharmony_ci .tx_ctrl_2 = 0x71, 3428c2ecf20Sopenharmony_ci .tx_ctrl_3 = 0x60, 3438c2ecf20Sopenharmony_ci .rx_k_gain = 0x98, 3448c2ecf20Sopenharmony_ci .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, 3458c2ecf20Sopenharmony_ci .rx_vga_gain = 0x00, 3468c2ecf20Sopenharmony_ci .rx_equ_gain_1 = 0x79, 3478c2ecf20Sopenharmony_ci .rx_equ_gain_2 = 0x56, 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci { 3508c2ecf20Sopenharmony_ci .bank = 0x01, 3518c2ecf20Sopenharmony_ci .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC, 3528c2ecf20Sopenharmony_ci .bias_boost_1 = 0x00, 3538c2ecf20Sopenharmony_ci .bias_boost_2 = 0xa5, 3548c2ecf20Sopenharmony_ci .tx_ctrl_1 = TX_REG_STEP_N_25MV, 3558c2ecf20Sopenharmony_ci .tx_ctrl_2 = 0x70, 3568c2ecf20Sopenharmony_ci .tx_ctrl_3 = 0x60, 3578c2ecf20Sopenharmony_ci .rx_k_gain = 0xcc, 3588c2ecf20Sopenharmony_ci .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, 3598c2ecf20Sopenharmony_ci .rx_vga_gain = 0x00, 3608c2ecf20Sopenharmony_ci .rx_equ_gain_1 = 0x78, 3618c2ecf20Sopenharmony_ci .rx_equ_gain_2 = 0x07, 3628c2ecf20Sopenharmony_ci }, 3638c2ecf20Sopenharmony_ci}; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 3688c2ecf20Sopenharmony_ci u8 val; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* Putting Macro in reset */ 3718c2ecf20Sopenharmony_ci writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci val = RST_APPLI_SW | RST_CONF_SW; 3748c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_CONF_RESET); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* Bringing the MIPHY-CPU registers out of reset */ 3798c2ecf20Sopenharmony_ci if (miphy_phy->type == PHY_TYPE_PCIE) { 3808c2ecf20Sopenharmony_ci val = AUTO_RST_RX | TERM_EN_SW; 3818c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_CONTROL); 3828c2ecf20Sopenharmony_ci } else { 3838c2ecf20Sopenharmony_ci val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST; 3848c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_CONTROL); 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy, 3898c2ecf20Sopenharmony_ci struct pll_ratio *pll_ratio) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 3928c2ecf20Sopenharmony_ci u8 val; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* Applying PLL Settings */ 3958c2ecf20Sopenharmony_ci writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN); 3968c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* PLL Ratio */ 3998c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1); 4008c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2); 4018c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3); 4028c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4); 4038c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN; 4088c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_TX_CAL_MAN); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci if (miphy_phy->type != PHY_TYPE_SATA) 4138c2ecf20Sopenharmony_ci val |= OFFSET_COMPENSATION_EN; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (miphy_phy->type == PHY_TYPE_USB3) { 4188c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 4198c2ecf20Sopenharmony_ci writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP); 4208c2ecf20Sopenharmony_ci writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA); 4218c2ecf20Sopenharmony_ci writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL); 4228c2ecf20Sopenharmony_ci writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF; 4258c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL); 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 4338c2ecf20Sopenharmony_ci int i; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) { 4368c2ecf20Sopenharmony_ci struct miphy28lp_pll_gen *gen = &sata_pll_gen[i]; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* Banked settings */ 4398c2ecf20Sopenharmony_ci writeb_relaxed(gen->bank, base + MIPHY_CONF); 4408c2ecf20Sopenharmony_ci writeb_relaxed(gen->speed, base + MIPHY_SPEED); 4418c2ecf20Sopenharmony_ci writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1); 4428c2ecf20Sopenharmony_ci writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* TX buffer Settings */ 4458c2ecf20Sopenharmony_ci writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2); 4468c2ecf20Sopenharmony_ci writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci /* RX Buffer Settings */ 4498c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL); 4508c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN); 4518c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1); 4528c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2); 4538c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3); 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 4608c2ecf20Sopenharmony_ci int i; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) { 4638c2ecf20Sopenharmony_ci struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i]; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* Banked settings */ 4668c2ecf20Sopenharmony_ci writeb_relaxed(gen->bank, base + MIPHY_CONF); 4678c2ecf20Sopenharmony_ci writeb_relaxed(gen->speed, base + MIPHY_SPEED); 4688c2ecf20Sopenharmony_ci writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1); 4698c2ecf20Sopenharmony_ci writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* TX buffer Settings */ 4728c2ecf20Sopenharmony_ci writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1); 4738c2ecf20Sopenharmony_ci writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2); 4748c2ecf20Sopenharmony_ci writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* RX Buffer Settings */ 4798c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL); 4808c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN); 4818c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1); 4828c2ecf20Sopenharmony_ci writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2); 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci u8 val; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* Waiting for Compensation to complete */ 4918c2ecf20Sopenharmony_ci return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6, 4928c2ecf20Sopenharmony_ci val, val & COMP_DONE, 1, 5 * USEC_PER_SEC); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy, 4978c2ecf20Sopenharmony_ci struct pll_ratio *pll_ratio) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci /* Poll for HFC ready after reset release */ 5028c2ecf20Sopenharmony_ci /* Compensation measurement */ 5038c2ecf20Sopenharmony_ci writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2); 5068c2ecf20Sopenharmony_ci writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ); 5078c2ecf20Sopenharmony_ci writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (miphy_phy->type == PHY_TYPE_PCIE) 5108c2ecf20Sopenharmony_ci writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_RESET); 5138c2ecf20Sopenharmony_ci writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2); 5148c2ecf20Sopenharmony_ci writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci /* TX compensation offset to re-center TX impedance */ 5178c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_COMP_POSTP); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (miphy_phy->type == PHY_TYPE_PCIE) 5208c2ecf20Sopenharmony_ci return miphy28lp_wait_compensation(miphy_phy); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci return 0; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 5288c2ecf20Sopenharmony_ci u8 val; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* MIPHY Reset */ 5318c2ecf20Sopenharmony_ci writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); 5328c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF_RESET); 5338c2ecf20Sopenharmony_ci writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci val = RST_COMP_SW | RST_PLL_SW; 5368c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_RESET); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2); 5398c2ecf20Sopenharmony_ci writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ); 5408c2ecf20Sopenharmony_ci writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1); 5418c2ecf20Sopenharmony_ci writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET); 5428c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_RESET); 5438c2ecf20Sopenharmony_ci writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2); 5448c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 5458c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1); 5468c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2); 5478c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 5488c2ecf20Sopenharmony_ci writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); 5498c2ecf20Sopenharmony_ci writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS); 5508c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 5568c2ecf20Sopenharmony_ci u8 val; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* Compensate Tx impedance to avoid out of range values */ 5598c2ecf20Sopenharmony_ci /* 5608c2ecf20Sopenharmony_ci * Enable the SSC on PLL for all banks 5618c2ecf20Sopenharmony_ci * SSC Modulation @ 31 KHz and 4000 ppm modulation amp 5628c2ecf20Sopenharmony_ci */ 5638c2ecf20Sopenharmony_ci val = readb_relaxed(base + MIPHY_BOUNDARY_2); 5648c2ecf20Sopenharmony_ci val |= SSC_EN_SW; 5658c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_BOUNDARY_2); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci val = readb_relaxed(base + MIPHY_BOUNDARY_SEL); 5688c2ecf20Sopenharmony_ci val |= SSC_SEL; 5698c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci for (val = 0; val < MIPHY_SATA_BANK_NB; val++) { 5728c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_CONF); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci /* Add value to each reference clock cycle */ 5758c2ecf20Sopenharmony_ci /* and define the period length of the SSC */ 5768c2ecf20Sopenharmony_ci writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); 5778c2ecf20Sopenharmony_ci writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3); 5788c2ecf20Sopenharmony_ci writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* Clear any previous request */ 5818c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* requests the PLL to take in account new parameters */ 5848c2ecf20Sopenharmony_ci writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* To be sure there is no other pending requests */ 5878c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_cistatic void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 5948c2ecf20Sopenharmony_ci u8 val; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* Compensate Tx impedance to avoid out of range values */ 5978c2ecf20Sopenharmony_ci /* 5988c2ecf20Sopenharmony_ci * Enable the SSC on PLL for all banks 5998c2ecf20Sopenharmony_ci * SSC Modulation @ 31 KHz and 4000 ppm modulation amp 6008c2ecf20Sopenharmony_ci */ 6018c2ecf20Sopenharmony_ci val = readb_relaxed(base + MIPHY_BOUNDARY_2); 6028c2ecf20Sopenharmony_ci val |= SSC_EN_SW; 6038c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_BOUNDARY_2); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci val = readb_relaxed(base + MIPHY_BOUNDARY_SEL); 6068c2ecf20Sopenharmony_ci val |= SSC_SEL; 6078c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) { 6108c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_CONF); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* Validate Step component */ 6138c2ecf20Sopenharmony_ci writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3); 6148c2ecf20Sopenharmony_ci writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* Validate Period component */ 6178c2ecf20Sopenharmony_ci writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); 6188c2ecf20Sopenharmony_ci writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci /* Clear any previous request */ 6218c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* requests the PLL to take in account new parameters */ 6248c2ecf20Sopenharmony_ci writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* To be sure there is no other pending requests */ 6278c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci /* Compensate Tx impedance to avoid out of range values */ 6348c2ecf20Sopenharmony_ci writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP); 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 6408c2ecf20Sopenharmony_ci int err; 6418c2ecf20Sopenharmony_ci u8 val; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* Putting Macro in reset */ 6448c2ecf20Sopenharmony_ci miphy28lp_set_reset(miphy_phy); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci /* PLL calibration */ 6478c2ecf20Sopenharmony_ci miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* Banked settings Gen1/Gen2/Gen3 */ 6508c2ecf20Sopenharmony_ci miphy28lp_sata_config_gen(miphy_phy); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci /* Power control */ 6538c2ecf20Sopenharmony_ci /* Input bridge enable, manual input bridge control */ 6548c2ecf20Sopenharmony_ci writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /* Macro out of reset */ 6578c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF_RESET); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* Poll for HFC ready after reset release */ 6608c2ecf20Sopenharmony_ci /* Compensation measurement */ 6618c2ecf20Sopenharmony_ci err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio); 6628c2ecf20Sopenharmony_ci if (err) 6638c2ecf20Sopenharmony_ci return err; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (miphy_phy->px_rx_pol_inv) { 6668c2ecf20Sopenharmony_ci /* Invert Rx polarity */ 6678c2ecf20Sopenharmony_ci val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL); 6688c2ecf20Sopenharmony_ci val |= PX_RX_POL; 6698c2ecf20Sopenharmony_ci writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL); 6708c2ecf20Sopenharmony_ci } 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci if (miphy_phy->ssc) 6738c2ecf20Sopenharmony_ci miphy_sata_tune_ssc(miphy_phy); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (miphy_phy->tx_impedance) 6768c2ecf20Sopenharmony_ci miphy_tune_tx_impedance(miphy_phy); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci return 0; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 6848c2ecf20Sopenharmony_ci int err; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci /* Putting Macro in reset */ 6878c2ecf20Sopenharmony_ci miphy28lp_set_reset(miphy_phy); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* PLL calibration */ 6908c2ecf20Sopenharmony_ci miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* Banked settings Gen1/Gen2 */ 6938c2ecf20Sopenharmony_ci miphy28lp_pcie_config_gen(miphy_phy); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci /* Power control */ 6968c2ecf20Sopenharmony_ci /* Input bridge enable, manual input bridge control */ 6978c2ecf20Sopenharmony_ci writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci /* Macro out of reset */ 7008c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF_RESET); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci /* Poll for HFC ready after reset release */ 7038c2ecf20Sopenharmony_ci /* Compensation measurement */ 7048c2ecf20Sopenharmony_ci err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio); 7058c2ecf20Sopenharmony_ci if (err) 7068c2ecf20Sopenharmony_ci return err; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (miphy_phy->ssc) 7098c2ecf20Sopenharmony_ci miphy_pcie_tune_ssc(miphy_phy); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci if (miphy_phy->tx_impedance) 7128c2ecf20Sopenharmony_ci miphy_tune_tx_impedance(miphy_phy); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci return 0; 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_cistatic inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci void __iomem *base = miphy_phy->base; 7218c2ecf20Sopenharmony_ci u8 val; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci /* Putting Macro in reset */ 7248c2ecf20Sopenharmony_ci miphy28lp_set_reset(miphy_phy); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* PLL calibration */ 7278c2ecf20Sopenharmony_ci miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci /* Writing The Speed Rate */ 7308c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC; 7338c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_SPEED); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* RX Channel compensation and calibration */ 7368c2ecf20Sopenharmony_ci writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT); 7378c2ecf20Sopenharmony_ci writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1); 7388c2ecf20Sopenharmony_ci writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY | 7418c2ecf20Sopenharmony_ci CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64; 7428c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL); 7438c2ecf20Sopenharmony_ci writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP); 7448c2ecf20Sopenharmony_ci writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci val = EQ_DC_GAIN | VGA_GAIN; 7478c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL); 7488c2ecf20Sopenharmony_ci writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1); 7498c2ecf20Sopenharmony_ci writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* TX compensation offset to re-center TX impedance */ 7528c2ecf20Sopenharmony_ci writeb_relaxed(0x02, base + MIPHY_COMP_POSTP); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci /* Enable GENSEL_SEL and SSC */ 7558c2ecf20Sopenharmony_ci /* TX_SEL=0 swing preemp forced by pipe registres */ 7568c2ecf20Sopenharmony_ci val = SSC_SEL | GENSEL_SEL; 7578c2ecf20Sopenharmony_ci writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* MIPHY Bias boost */ 7608c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1); 7618c2ecf20Sopenharmony_ci writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* SSC modulation */ 7648c2ecf20Sopenharmony_ci writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci /* MIPHY TX control */ 7678c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_CONF); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* Validate Step component */ 7708c2ecf20Sopenharmony_ci writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3); 7718c2ecf20Sopenharmony_ci writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci /* Validate Period component */ 7748c2ecf20Sopenharmony_ci writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); 7758c2ecf20Sopenharmony_ci writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* Clear any previous request */ 7788c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci /* requests the PLL to take in account new parameters */ 7818c2ecf20Sopenharmony_ci writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* To be sure there is no other pending requests */ 7848c2ecf20Sopenharmony_ci writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci /* Rx PI controller settings */ 7878c2ecf20Sopenharmony_ci writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* MIPHY RX input bridge control */ 7908c2ecf20Sopenharmony_ci /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */ 7918c2ecf20Sopenharmony_ci writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); 7928c2ecf20Sopenharmony_ci writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1); 7938c2ecf20Sopenharmony_ci writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* MIPHY Reset for usb3 */ 7968c2ecf20Sopenharmony_ci miphy28_usb3_miphy_reset(miphy_phy); 7978c2ecf20Sopenharmony_ci} 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_cistatic inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy) 8008c2ecf20Sopenharmony_ci{ 8018c2ecf20Sopenharmony_ci u8 mask = HFC_PLL | HFC_RDY; 8028c2ecf20Sopenharmony_ci u8 val; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* 8058c2ecf20Sopenharmony_ci * For PCIe and USB3 check only that PLL and HFC are ready 8068c2ecf20Sopenharmony_ci * For SATA check also that phy is ready! 8078c2ecf20Sopenharmony_ci */ 8088c2ecf20Sopenharmony_ci if (miphy_phy->type == PHY_TYPE_SATA) 8098c2ecf20Sopenharmony_ci mask |= PHY_RDY; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1, 8128c2ecf20Sopenharmony_ci val, (val & mask) == mask, 1, 8138c2ecf20Sopenharmony_ci 5 * USEC_PER_SEC); 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_cistatic int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 8198c2ecf20Sopenharmony_ci u32 val; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci if (!miphy_phy->osc_rdy) 8228c2ecf20Sopenharmony_ci return 0; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci if (!miphy_phy->syscfg_reg[SYSCFG_STATUS]) 8258c2ecf20Sopenharmony_ci return -EINVAL; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci return regmap_read_poll_timeout(miphy_dev->regmap, 8288c2ecf20Sopenharmony_ci miphy_phy->syscfg_reg[SYSCFG_STATUS], 8298c2ecf20Sopenharmony_ci val, val & MIPHY_OSC_RDY, 1, 8308c2ecf20Sopenharmony_ci 5 * USEC_PER_SEC); 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic int miphy28lp_get_resource_byname(struct device_node *child, 8348c2ecf20Sopenharmony_ci char *rname, struct resource *res) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci int index; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci index = of_property_match_string(child, "reg-names", rname); 8398c2ecf20Sopenharmony_ci if (index < 0) 8408c2ecf20Sopenharmony_ci return -ENODEV; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci return of_address_to_resource(child, index, res); 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic int miphy28lp_get_one_addr(struct device *dev, 8468c2ecf20Sopenharmony_ci struct device_node *child, char *rname, 8478c2ecf20Sopenharmony_ci void __iomem **base) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci struct resource res; 8508c2ecf20Sopenharmony_ci int ret; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci ret = miphy28lp_get_resource_byname(child, rname, &res); 8538c2ecf20Sopenharmony_ci if (!ret) { 8548c2ecf20Sopenharmony_ci *base = devm_ioremap(dev, res.start, resource_size(&res)); 8558c2ecf20Sopenharmony_ci if (!*base) { 8568c2ecf20Sopenharmony_ci dev_err(dev, "failed to ioremap %s address region\n" 8578c2ecf20Sopenharmony_ci , rname); 8588c2ecf20Sopenharmony_ci return -ENOENT; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci/* MiPHY reset and sysconf setup */ 8668c2ecf20Sopenharmony_cistatic int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val) 8678c2ecf20Sopenharmony_ci{ 8688c2ecf20Sopenharmony_ci int err; 8698c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci if (!miphy_phy->syscfg_reg[SYSCFG_CTRL]) 8728c2ecf20Sopenharmony_ci return -EINVAL; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci err = reset_control_assert(miphy_phy->miphy_rst); 8758c2ecf20Sopenharmony_ci if (err) { 8768c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); 8778c2ecf20Sopenharmony_ci return err; 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci if (miphy_phy->osc_force_ext) 8818c2ecf20Sopenharmony_ci miphy_val |= MIPHY_OSC_FORCE_EXT; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci regmap_update_bits(miphy_dev->regmap, 8848c2ecf20Sopenharmony_ci miphy_phy->syscfg_reg[SYSCFG_CTRL], 8858c2ecf20Sopenharmony_ci MIPHY_CTRL_MASK, miphy_val); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci err = reset_control_deassert(miphy_phy->miphy_rst); 8888c2ecf20Sopenharmony_ci if (err) { 8898c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); 8908c2ecf20Sopenharmony_ci return err; 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci return miphy_osc_is_ready(miphy_phy); 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 8998c2ecf20Sopenharmony_ci int err, sata_conf = SATA_CTRL_SELECT_SATA; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || 9028c2ecf20Sopenharmony_ci (!miphy_phy->syscfg_reg[SYSCFG_PCI]) || 9038c2ecf20Sopenharmony_ci (!miphy_phy->base)) 9048c2ecf20Sopenharmony_ci return -EINVAL; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* Configure the glue-logic */ 9098c2ecf20Sopenharmony_ci sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci regmap_update_bits(miphy_dev->regmap, 9128c2ecf20Sopenharmony_ci miphy_phy->syscfg_reg[SYSCFG_SATA], 9138c2ecf20Sopenharmony_ci SATA_CTRL_MASK, sata_conf); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], 9168c2ecf20Sopenharmony_ci PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci /* MiPHY path and clocking init */ 9198c2ecf20Sopenharmony_ci err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (err) { 9228c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "SATA phy setup failed\n"); 9238c2ecf20Sopenharmony_ci return err; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci /* initialize miphy */ 9278c2ecf20Sopenharmony_ci miphy28lp_configure_sata(miphy_phy); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci return miphy_is_ready(miphy_phy); 9308c2ecf20Sopenharmony_ci} 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_cistatic int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy) 9338c2ecf20Sopenharmony_ci{ 9348c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 9358c2ecf20Sopenharmony_ci int err; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || 9388c2ecf20Sopenharmony_ci (!miphy_phy->syscfg_reg[SYSCFG_PCI]) 9398c2ecf20Sopenharmony_ci || (!miphy_phy->base) || (!miphy_phy->pipebase)) 9408c2ecf20Sopenharmony_ci return -EINVAL; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci /* Configure the glue-logic */ 9458c2ecf20Sopenharmony_ci regmap_update_bits(miphy_dev->regmap, 9468c2ecf20Sopenharmony_ci miphy_phy->syscfg_reg[SYSCFG_SATA], 9478c2ecf20Sopenharmony_ci SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], 9508c2ecf20Sopenharmony_ci PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* MiPHY path and clocking init */ 9538c2ecf20Sopenharmony_ci err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (err) { 9568c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "PCIe phy setup failed\n"); 9578c2ecf20Sopenharmony_ci return err; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* initialize miphy */ 9618c2ecf20Sopenharmony_ci err = miphy28lp_configure_pcie(miphy_phy); 9628c2ecf20Sopenharmony_ci if (err) 9638c2ecf20Sopenharmony_ci return err; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* PIPE Wrapper Configuration */ 9668c2ecf20Sopenharmony_ci writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */ 9678c2ecf20Sopenharmony_ci writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */ 9688c2ecf20Sopenharmony_ci writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */ 9698c2ecf20Sopenharmony_ci writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */ 9708c2ecf20Sopenharmony_ci writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */ 9718c2ecf20Sopenharmony_ci writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */ 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* Wait for phy_ready */ 9748c2ecf20Sopenharmony_ci return miphy_is_ready(miphy_phy); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 9808c2ecf20Sopenharmony_ci int err; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci if ((!miphy_phy->base) || (!miphy_phy->pipebase)) 9838c2ecf20Sopenharmony_ci return -EINVAL; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base); 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci /* MiPHY path and clocking init */ 9888c2ecf20Sopenharmony_ci err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN); 9898c2ecf20Sopenharmony_ci if (err) { 9908c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "USB3 phy setup failed\n"); 9918c2ecf20Sopenharmony_ci return err; 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* initialize miphy */ 9958c2ecf20Sopenharmony_ci miphy28lp_configure_usb3(miphy_phy); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci /* PIPE Wrapper Configuration */ 9988c2ecf20Sopenharmony_ci writeb_relaxed(0x68, miphy_phy->pipebase + 0x23); 9998c2ecf20Sopenharmony_ci writeb_relaxed(0x61, miphy_phy->pipebase + 0x24); 10008c2ecf20Sopenharmony_ci writeb_relaxed(0x68, miphy_phy->pipebase + 0x26); 10018c2ecf20Sopenharmony_ci writeb_relaxed(0x61, miphy_phy->pipebase + 0x27); 10028c2ecf20Sopenharmony_ci writeb_relaxed(0x18, miphy_phy->pipebase + 0x29); 10038c2ecf20Sopenharmony_ci writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */ 10068c2ecf20Sopenharmony_ci writeb_relaxed(0X67, miphy_phy->pipebase + 0x68); 10078c2ecf20Sopenharmony_ci writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69); 10088c2ecf20Sopenharmony_ci writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a); 10098c2ecf20Sopenharmony_ci writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b); 10108c2ecf20Sopenharmony_ci writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c); 10118c2ecf20Sopenharmony_ci writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d); 10128c2ecf20Sopenharmony_ci writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e); 10138c2ecf20Sopenharmony_ci writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci return miphy_is_ready(miphy_phy); 10168c2ecf20Sopenharmony_ci} 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_cistatic int miphy28lp_init(struct phy *phy) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy); 10218c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 10228c2ecf20Sopenharmony_ci int ret; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci mutex_lock(&miphy_dev->miphy_mutex); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci switch (miphy_phy->type) { 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci case PHY_TYPE_SATA: 10298c2ecf20Sopenharmony_ci ret = miphy28lp_init_sata(miphy_phy); 10308c2ecf20Sopenharmony_ci break; 10318c2ecf20Sopenharmony_ci case PHY_TYPE_PCIE: 10328c2ecf20Sopenharmony_ci ret = miphy28lp_init_pcie(miphy_phy); 10338c2ecf20Sopenharmony_ci break; 10348c2ecf20Sopenharmony_ci case PHY_TYPE_USB3: 10358c2ecf20Sopenharmony_ci ret = miphy28lp_init_usb3(miphy_phy); 10368c2ecf20Sopenharmony_ci break; 10378c2ecf20Sopenharmony_ci default: 10388c2ecf20Sopenharmony_ci ret = -EINVAL; 10398c2ecf20Sopenharmony_ci break; 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci mutex_unlock(&miphy_dev->miphy_mutex); 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci return ret; 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_cistatic int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 10508c2ecf20Sopenharmony_ci struct device_node *phynode = miphy_phy->phy->dev.of_node; 10518c2ecf20Sopenharmony_ci int err; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci if ((miphy_phy->type != PHY_TYPE_SATA) && 10548c2ecf20Sopenharmony_ci (miphy_phy->type != PHY_TYPE_PCIE) && 10558c2ecf20Sopenharmony_ci (miphy_phy->type != PHY_TYPE_USB3)) { 10568c2ecf20Sopenharmony_ci return -EINVAL; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, 10608c2ecf20Sopenharmony_ci PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA], 10618c2ecf20Sopenharmony_ci &miphy_phy->base); 10628c2ecf20Sopenharmony_ci if (err) 10638c2ecf20Sopenharmony_ci return err; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci if ((miphy_phy->type == PHY_TYPE_PCIE) || 10668c2ecf20Sopenharmony_ci (miphy_phy->type == PHY_TYPE_USB3)) { 10678c2ecf20Sopenharmony_ci err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew", 10688c2ecf20Sopenharmony_ci &miphy_phy->pipebase); 10698c2ecf20Sopenharmony_ci if (err) 10708c2ecf20Sopenharmony_ci return err; 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci return 0; 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_cistatic struct phy *miphy28lp_xlate(struct device *dev, 10778c2ecf20Sopenharmony_ci struct of_phandle_args *args) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev); 10808c2ecf20Sopenharmony_ci struct miphy28lp_phy *miphy_phy = NULL; 10818c2ecf20Sopenharmony_ci struct device_node *phynode = args->np; 10828c2ecf20Sopenharmony_ci int ret, index = 0; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (args->args_count != 1) { 10858c2ecf20Sopenharmony_ci dev_err(dev, "Invalid number of cells in 'phy' property\n"); 10868c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci for (index = 0; index < miphy_dev->nphys; index++) 10908c2ecf20Sopenharmony_ci if (phynode == miphy_dev->phys[index]->phy->dev.of_node) { 10918c2ecf20Sopenharmony_ci miphy_phy = miphy_dev->phys[index]; 10928c2ecf20Sopenharmony_ci break; 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci if (!miphy_phy) { 10968c2ecf20Sopenharmony_ci dev_err(dev, "Failed to find appropriate phy\n"); 10978c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci miphy_phy->type = args->args[0]; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci ret = miphy28lp_get_addr(miphy_phy); 11038c2ecf20Sopenharmony_ci if (ret < 0) 11048c2ecf20Sopenharmony_ci return ERR_PTR(ret); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci return miphy_phy->phy; 11078c2ecf20Sopenharmony_ci} 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_cistatic const struct phy_ops miphy28lp_ops = { 11108c2ecf20Sopenharmony_ci .init = miphy28lp_init, 11118c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 11128c2ecf20Sopenharmony_ci}; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_cistatic int miphy28lp_probe_resets(struct device_node *node, 11158c2ecf20Sopenharmony_ci struct miphy28lp_phy *miphy_phy) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 11188c2ecf20Sopenharmony_ci int err; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci miphy_phy->miphy_rst = 11218c2ecf20Sopenharmony_ci of_reset_control_get_shared(node, "miphy-sw-rst"); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci if (IS_ERR(miphy_phy->miphy_rst)) { 11248c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, 11258c2ecf20Sopenharmony_ci "miphy soft reset control not defined\n"); 11268c2ecf20Sopenharmony_ci return PTR_ERR(miphy_phy->miphy_rst); 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci err = reset_control_deassert(miphy_phy->miphy_rst); 11308c2ecf20Sopenharmony_ci if (err) { 11318c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); 11328c2ecf20Sopenharmony_ci return err; 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return 0; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistatic int miphy28lp_of_probe(struct device_node *np, 11398c2ecf20Sopenharmony_ci struct miphy28lp_phy *miphy_phy) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci int i; 11428c2ecf20Sopenharmony_ci u32 ctrlreg; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci miphy_phy->osc_force_ext = 11458c2ecf20Sopenharmony_ci of_property_read_bool(np, "st,osc-force-ext"); 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy"); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci miphy_phy->px_rx_pol_inv = 11508c2ecf20Sopenharmony_ci of_property_read_bool(np, "st,px_rx_pol_inv"); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on"); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci miphy_phy->tx_impedance = 11558c2ecf20Sopenharmony_ci of_property_read_bool(np, "st,tx-impedance-comp"); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen); 11588c2ecf20Sopenharmony_ci if (!miphy_phy->sata_gen) 11598c2ecf20Sopenharmony_ci miphy_phy->sata_gen = SATA_GEN1; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci for (i = 0; i < SYSCFG_REG_MAX; i++) { 11628c2ecf20Sopenharmony_ci if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg)) 11638c2ecf20Sopenharmony_ci miphy_phy->syscfg_reg[i] = ctrlreg; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci return 0; 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int miphy28lp_probe(struct platform_device *pdev) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci struct device_node *child, *np = pdev->dev.of_node; 11728c2ecf20Sopenharmony_ci struct miphy28lp_dev *miphy_dev; 11738c2ecf20Sopenharmony_ci struct phy_provider *provider; 11748c2ecf20Sopenharmony_ci struct phy *phy; 11758c2ecf20Sopenharmony_ci int ret, port = 0; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL); 11788c2ecf20Sopenharmony_ci if (!miphy_dev) 11798c2ecf20Sopenharmony_ci return -ENOMEM; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci miphy_dev->nphys = of_get_child_count(np); 11828c2ecf20Sopenharmony_ci miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys, 11838c2ecf20Sopenharmony_ci sizeof(*miphy_dev->phys), GFP_KERNEL); 11848c2ecf20Sopenharmony_ci if (!miphy_dev->phys) 11858c2ecf20Sopenharmony_ci return -ENOMEM; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); 11888c2ecf20Sopenharmony_ci if (IS_ERR(miphy_dev->regmap)) { 11898c2ecf20Sopenharmony_ci dev_err(miphy_dev->dev, "No syscfg phandle specified\n"); 11908c2ecf20Sopenharmony_ci return PTR_ERR(miphy_dev->regmap); 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci miphy_dev->dev = &pdev->dev; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci dev_set_drvdata(&pdev->dev, miphy_dev); 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci mutex_init(&miphy_dev->miphy_mutex); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci for_each_child_of_node(np, child) { 12008c2ecf20Sopenharmony_ci struct miphy28lp_phy *miphy_phy; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy), 12038c2ecf20Sopenharmony_ci GFP_KERNEL); 12048c2ecf20Sopenharmony_ci if (!miphy_phy) { 12058c2ecf20Sopenharmony_ci ret = -ENOMEM; 12068c2ecf20Sopenharmony_ci goto put_child; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci miphy_dev->phys[port] = miphy_phy; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops); 12128c2ecf20Sopenharmony_ci if (IS_ERR(phy)) { 12138c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to create PHY\n"); 12148c2ecf20Sopenharmony_ci ret = PTR_ERR(phy); 12158c2ecf20Sopenharmony_ci goto put_child; 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci miphy_dev->phys[port]->phy = phy; 12198c2ecf20Sopenharmony_ci miphy_dev->phys[port]->phydev = miphy_dev; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci ret = miphy28lp_of_probe(child, miphy_phy); 12228c2ecf20Sopenharmony_ci if (ret) 12238c2ecf20Sopenharmony_ci goto put_child; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]); 12268c2ecf20Sopenharmony_ci if (ret) 12278c2ecf20Sopenharmony_ci goto put_child; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci phy_set_drvdata(phy, miphy_dev->phys[port]); 12308c2ecf20Sopenharmony_ci port++; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate); 12358c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(provider); 12368c2ecf20Sopenharmony_ciput_child: 12378c2ecf20Sopenharmony_ci of_node_put(child); 12388c2ecf20Sopenharmony_ci return ret; 12398c2ecf20Sopenharmony_ci} 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic const struct of_device_id miphy28lp_of_match[] = { 12428c2ecf20Sopenharmony_ci {.compatible = "st,miphy28lp-phy", }, 12438c2ecf20Sopenharmony_ci {}, 12448c2ecf20Sopenharmony_ci}; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, miphy28lp_of_match); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_cistatic struct platform_driver miphy28lp_driver = { 12498c2ecf20Sopenharmony_ci .probe = miphy28lp_probe, 12508c2ecf20Sopenharmony_ci .driver = { 12518c2ecf20Sopenharmony_ci .name = "miphy28lp-phy", 12528c2ecf20Sopenharmony_ci .of_match_table = miphy28lp_of_match, 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci}; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_cimodule_platform_driver(miphy28lp_driver); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>"); 12598c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics miphy28lp driver"); 12608c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1261