462 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * DPHY TX driver for the StarFive JH7110 SoC4 *5 * Copyright (C) 2023 StarFive Technology Co., Ltd.6 * Author: Keith Zhao <keith.zhao@starfivetech.com>7 * Author: Shengyang Chen <shengyang.chen@starfivetech.com>8 */9 10#include <linux/bitfield.h>11#include <linux/clk.h>12#include <linux/io.h>13#include <linux/iopoll.h>14#include <linux/mfd/syscon.h>15#include <linux/module.h>16#include <linux/of.h>17#include <linux/of_device.h>18#include <linux/phy/phy.h>19#include <linux/phy/phy-mipi-dphy.h>20#include <linux/platform_device.h>21#include <linux/pm_runtime.h>22#include <linux/reset.h>23 24#define STF_DPHY_APBIFSAIF_SYSCFG(x) (x)25 26#define STF_DPHY_AON_POWER_READY_N_ACTIVE 027#define STF_DPHY_AON_POWER_READY_N BIT(0)28#define STF_DPHY_CFG_L0_SWAP_SEL GENMASK(14, 12)29#define STF_DPHY_CFG_L1_SWAP_SEL GENMASK(17, 15)30#define STF_DPHY_CFG_L2_SWAP_SEL GENMASK(20, 18)31#define STF_DPHY_CFG_L3_SWAP_SEL GENMASK(23, 21)32#define STF_DPHY_CFG_L4_SWAP_SEL GENMASK(26, 24)33#define STF_DPHY_RGS_CDTX_PLL_UNLOCK BIT(18)34#define STF_DPHY_RG_CDTX_L0N_HSTX_RES GENMASK(23, 19)35#define STF_DPHY_RG_CDTX_L0P_HSTX_RES GENMASK(28, 24)36 37#define STF_DPHY_RG_CDTX_L1P_HSTX_RES GENMASK(9, 5)38#define STF_DPHY_RG_CDTX_L2N_HSTX_RES GENMASK(14, 10)39#define STF_DPHY_RG_CDTX_L2P_HSTX_RES GENMASK(19, 15)40#define STF_DPHY_RG_CDTX_L3N_HSTX_RES GENMASK(24, 20)41#define STF_DPHY_RG_CDTX_L3P_HSTX_RES GENMASK(29, 25)42 43#define STF_DPHY_RG_CDTX_L4N_HSTX_RES GENMASK(4, 0)44#define STF_DPHY_RG_CDTX_L4P_HSTX_RES GENMASK(9, 5)45#define STF_DPHY_RG_CDTX_PLL_FBK_FRA GENMASK(23, 0)46 47#define STF_DPHY_RG_CDTX_PLL_FBK_INT GENMASK(8, 0)48#define STF_DPHY_RG_CDTX_PLL_FM_EN BIT(9)49#define STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN BIT(10)50#define STF_DPHY_RG_CDTX_PLL_PRE_DIV GENMASK(12, 11)51 52#define STF_DPHY_RG_CDTX_PLL_SSC_EN BIT(18)53 54#define STF_DPHY_RG_CLANE_HS_CLK_POST_TIME GENMASK(7, 0)55#define STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME GENMASK(15, 8)56#define STF_DPHY_RG_CLANE_HS_PRE_TIME GENMASK(23, 16)57#define STF_DPHY_RG_CLANE_HS_TRAIL_TIME GENMASK(31, 24)58 59#define STF_DPHY_RG_CLANE_HS_ZERO_TIME GENMASK(7, 0)60#define STF_DPHY_RG_DLANE_HS_PRE_TIME GENMASK(15, 8)61#define STF_DPHY_RG_DLANE_HS_TRAIL_TIME GENMASK(23, 16)62#define STF_DPHY_RG_DLANE_HS_ZERO_TIME GENMASK(31, 24)63 64#define STF_DPHY_RG_EXTD_CYCLE_SEL GENMASK(2, 0)65#define STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME GENMASK(31, 0)66 67#define STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL GENMASK(2, 1)68#define STF_DPHY_SCFG_PPI_C_READY_SEL GENMASK(4, 3)69 70#define STF_DPHY_REFCLK_IN_SEL GENMASK(28, 26)71#define STF_DPHY_RESETB BIT(29)72 73#define STF_DPHY_REFCLK_12M 174#define STF_DPHY_BITRATE_ALIGN 1000000075 76#define STF_MAP_LANES_NUM 577 78#define STF_DPHY_LSHIFT_16(x) (FIELD_PREP(GENMASK(23, 16), (x)))79#define STF_DPHY_LSHIFT_8(x) (FIELD_PREP(GENMASK(15, 8), (x)))80 81#define STF_DPHY_HW_DELAY_US 20082#define STF_DPHY_HW_TIMEOUT_US 500083 84struct stf_dphy_config {85 unsigned long bitrate;86 u32 pll_fbk_int;87 u32 pll_fbk_fra_val;88 u32 extd_cycle_sel;89 u32 dlane_hs_pre_time;90 u32 dlane_hs_zero_time;91 u32 dlane_hs_trail_time;92 u32 clane_hs_pre_time;93 u32 clane_hs_zero_time;94 u32 clane_hs_trail_time;95 u32 clane_hs_clk_pre_time;96 u32 clane_hs_clk_post_time;97};98 99static const struct stf_dphy_config reg_configs[] = {100 {160000000, 0x6a, 0xaa, 0x3, 0xa, 0x17, 0x11, 0x5, 0x2b, 0xd, 0x7, 0x3d},101 {170000000, 0x71, 0x55, 0x3, 0xb, 0x18, 0x11, 0x5, 0x2e, 0xd, 0x7, 0x3d},102 {180000000, 0x78, 0x0, 0x3, 0xb, 0x19, 0x12, 0x6, 0x30, 0xe, 0x7, 0x3e},103 {190000000, 0x7e, 0xaa, 0x3, 0xc, 0x1a, 0x12, 0x6, 0x33, 0xe, 0x7, 0x3e},104 {200000000, 0x85, 0x55, 0x3, 0xc, 0x1b, 0x13, 0x7, 0x35, 0xf, 0x7, 0x3f},105 {320000000, 0x6a, 0xaa, 0x2, 0x8, 0x14, 0xf, 0x5, 0x2b, 0xd, 0x3, 0x23},106 {330000000, 0x6e, 0x0, 0x2, 0x8, 0x15, 0xf, 0x5, 0x2d, 0xd, 0x3, 0x23},107 {340000000, 0x71, 0x55, 0x2, 0x9, 0x15, 0xf, 0x5, 0x2e, 0xd, 0x3, 0x23},108 {350000000, 0x74, 0xaa, 0x2, 0x9, 0x15, 0x10, 0x6, 0x2f, 0xe, 0x3, 0x24},109 {360000000, 0x78, 0x0, 0x2, 0x9, 0x16, 0x10, 0x6, 0x30, 0xe, 0x3, 0x24},110 {370000000, 0x7b, 0x55, 0x2, 0x9, 0x17, 0x10, 0x6, 0x32, 0xe, 0x3, 0x24},111 {380000000, 0x7e, 0xaa, 0x2, 0xa, 0x17, 0x10, 0x6, 0x33, 0xe, 0x3, 0x24},112 {390000000, 0x82, 0x0, 0x2, 0xa, 0x17, 0x11, 0x6, 0x35, 0xf, 0x3, 0x25},113 {400000000, 0x85, 0x55, 0x2, 0xa, 0x18, 0x11, 0x7, 0x35, 0xf, 0x3, 0x25},114 {410000000, 0x88, 0xaa, 0x2, 0xa, 0x19, 0x11, 0x7, 0x37, 0xf, 0x3, 0x25},115 {420000000, 0x8c, 0x0, 0x2, 0xa, 0x19, 0x12, 0x7, 0x38, 0x10, 0x3, 0x26},116 {430000000, 0x8f, 0x55, 0x2, 0xb, 0x19, 0x12, 0x7, 0x39, 0x10, 0x3, 0x26},117 {440000000, 0x92, 0xaa, 0x2, 0xb, 0x1a, 0x12, 0x7, 0x3b, 0x10, 0x3, 0x26},118 {450000000, 0x96, 0x0, 0x2, 0xb, 0x1b, 0x12, 0x8, 0x3c, 0x10, 0x3, 0x26},119 {460000000, 0x99, 0x55, 0x2, 0xb, 0x1b, 0x13, 0x8, 0x3d, 0x11, 0x3, 0x27},120 {470000000, 0x9c, 0xaa, 0x2, 0xc, 0x1b, 0x13, 0x8, 0x3e, 0x11, 0x3, 0x27},121 {480000000, 0xa0, 0x27, 0x2, 0xc, 0x1c, 0x13, 0x8, 0x40, 0x11, 0x3, 0x27},122 {490000000, 0xa3, 0x55, 0x2, 0xc, 0x1d, 0x14, 0x8, 0x42, 0x12, 0x3, 0x28},123 {500000000, 0xa6, 0xaa, 0x2, 0xc, 0x1d, 0x14, 0x9, 0x42, 0x12, 0x3, 0x28},124 {510000000, 0xaa, 0x0, 0x2, 0xc, 0x1e, 0x14, 0x9, 0x44, 0x12, 0x3, 0x28},125 {520000000, 0xad, 0x55, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x45, 0x13, 0x3, 0x29},126 {530000000, 0xb0, 0xaa, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x47, 0x13, 0x3, 0x29},127 {540000000, 0xb4, 0x0, 0x2, 0xd, 0x1f, 0x15, 0x9, 0x48, 0x13, 0x3, 0x29},128 {550000000, 0xb7, 0x55, 0x2, 0xd, 0x20, 0x16, 0x9, 0x4a, 0x14, 0x3, 0x2a},129 {560000000, 0xba, 0xaa, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4a, 0x14, 0x3, 0x2a},130 {570000000, 0xbe, 0x0, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4c, 0x14, 0x3, 0x2a},131 {580000000, 0xc1, 0x55, 0x2, 0xe, 0x21, 0x16, 0xa, 0x4d, 0x14, 0x3, 0x2a},132 {590000000, 0xc4, 0xaa, 0x2, 0xe, 0x22, 0x17, 0xa, 0x4f, 0x15, 0x3, 0x2b},133 {600000000, 0xc8, 0x0, 0x2, 0xe, 0x23, 0x17, 0xa, 0x50, 0x15, 0x3, 0x2b},134 {610000000, 0xcb, 0x55, 0x2, 0xf, 0x22, 0x17, 0xb, 0x50, 0x15, 0x3, 0x2b},135 {620000000, 0xce, 0xaa, 0x2, 0xf, 0x23, 0x18, 0xb, 0x52, 0x16, 0x3, 0x2c},136 {630000000, 0x69, 0x0, 0x1, 0x7, 0x12, 0xd, 0x5, 0x2a, 0xc, 0x1, 0x15},137 {640000000, 0x6a, 0xaa, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2b, 0xd, 0x1, 0x16},138 {650000000, 0x6c, 0x55, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2c, 0xd, 0x1, 0x16},139 {660000000, 0x6e, 0x0, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},140 {670000000, 0x6f, 0xaa, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},141 {680000000, 0x71, 0x55, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2e, 0xd, 0x1, 0x16},142 {690000000, 0x73, 0x0, 0x1, 0x8, 0x14, 0xe, 0x6, 0x2e, 0xd, 0x1, 0x16},143 {700000000, 0x74, 0xaa, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x16},144 {710000000, 0x76, 0x55, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x17},145 {720000000, 0x78, 0x0, 0x1, 0x8, 0x15, 0xf, 0x6, 0x30, 0xe, 0x1, 0x17},146 {730000000, 0x79, 0xaa, 0x1, 0x8, 0x15, 0xf, 0x6, 0x31, 0xe, 0x1, 0x17},147 {740000000, 0x7b, 0x55, 0x1, 0x8, 0x15, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},148 {750000000, 0x7d, 0x0, 0x1, 0x8, 0x16, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},149 {760000000, 0x7e, 0xaa, 0x1, 0x9, 0x15, 0xf, 0x6, 0x33, 0xe, 0x1, 0x17},150 {770000000, 0x80, 0x55, 0x1, 0x9, 0x15, 0x10, 0x6, 0x34, 0xf, 0x1, 0x18},151 {780000000, 0x82, 0x0, 0x1, 0x9, 0x16, 0x10, 0x6, 0x35, 0xf, 0x1, 0x18,},152 {790000000, 0x83, 0xaa, 0x1, 0x9, 0x16, 0x10, 0x7, 0x34, 0xf, 0x1, 0x18},153 {800000000, 0x85, 0x55, 0x1, 0x9, 0x17, 0x10, 0x7, 0x35, 0xf, 0x1, 0x18},154 {810000000, 0x87, 0x0, 0x1, 0x9, 0x17, 0x10, 0x7, 0x36, 0xf, 0x1, 0x18},155 {820000000, 0x88, 0xaa, 0x1, 0x9, 0x17, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},156 {830000000, 0x8a, 0x55, 0x1, 0x9, 0x18, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},157 {840000000, 0x8c, 0x0, 0x1, 0x9, 0x18, 0x11, 0x7, 0x38, 0x10, 0x1, 0x19},158 {850000000, 0x8d, 0xaa, 0x1, 0xa, 0x17, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},159 {860000000, 0x8f, 0x55, 0x1, 0xa, 0x18, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},160 {870000000, 0x91, 0x0, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3a, 0x10, 0x1, 0x19},161 {880000000, 0x92, 0xaa, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3b, 0x10, 0x1, 0x19},162 {890000000, 0x94, 0x55, 0x1, 0xa, 0x19, 0x11, 0x7, 0x3c, 0x10, 0x1, 0x19},163 {900000000, 0x96, 0x0, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x10, 0x1, 0x19},164 {910000000, 0x97, 0xaa, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x11, 0x1, 0x1a},165 {920000000, 0x99, 0x55, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3d, 0x11, 0x1, 0x1a},166 {930000000, 0x9b, 0x0, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},167 {940000000, 0x9c, 0xaa, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},168 {950000000, 0x9e, 0x55, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3f, 0x11, 0x1, 0x1a},169 {960000000, 0xa0, 0x0, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x40, 0x11, 0x1, 0x1a},170 {970000000, 0xa1, 0xaa, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x41, 0x12, 0x1, 0x1b},171 {980000000, 0xa3, 0x55, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},172 {990000000, 0xa5, 0x0, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},173 {1000000000, 0xa6, 0xaa, 0x1, 0xb, 0x1c, 0x13, 0x9, 0x42, 0x12, 0x1, 0x1b},174};175 176struct stf_dphy_info {177 /**178 * @maps:179 *180 * Physical lanes and logic lanes mapping table.181 *182 * The default order is:183 * [data lane 0, data lane 1, data lane 2, date lane 3, clk lane]184 */185 u8 maps[STF_MAP_LANES_NUM];186};187 188struct stf_dphy {189 struct device *dev;190 void __iomem *topsys;191 struct clk *txesc_clk;192 struct reset_control *sys_rst;193 194 struct phy_configure_opts_mipi_dphy config;195 196 struct phy *phy;197 const struct stf_dphy_info *info;198};199 200static u32 stf_dphy_get_config_index(u32 bitrate)201{202 u32 i;203 204 for (i = 0; i < ARRAY_SIZE(reg_configs); i++) {205 if (reg_configs[i].bitrate == bitrate)206 return i;207 }208 209 return 0;210}211 212static void stf_dphy_hw_reset(struct stf_dphy *dphy, int assert)213{214 int rc;215 u32 status = 0;216 217 writel(FIELD_PREP(STF_DPHY_RESETB, assert),218 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));219 220 if (assert) {221 rc = readl_poll_timeout_atomic(dphy->topsys +222 STF_DPHY_APBIFSAIF_SYSCFG(8),223 status,224 !(FIELD_GET(STF_DPHY_RGS_CDTX_PLL_UNLOCK, status)),225 STF_DPHY_HW_DELAY_US, STF_DPHY_HW_TIMEOUT_US);226 if (rc)227 dev_err(dphy->dev, "MIPI dphy-tx # PLL Locked\n");228 }229}230 231static int stf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)232{233 struct stf_dphy *dphy = phy_get_drvdata(phy);234 const struct stf_dphy_info *info = dphy->info;235 const struct stf_dphy_config *p = reg_configs;236 unsigned long alignment = STF_DPHY_BITRATE_ALIGN;237 u32 bitrate = opts->mipi_dphy.hs_clk_rate;238 u32 tmp;239 u32 i;240 241 if (bitrate % alignment)242 bitrate += alignment - (bitrate % alignment);243 244 i = stf_dphy_get_config_index(bitrate);245 246 tmp = readl(dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));247 tmp &= ~STF_DPHY_REFCLK_IN_SEL;248 tmp |= FIELD_PREP(STF_DPHY_REFCLK_IN_SEL, STF_DPHY_REFCLK_12M);249 writel(tmp, dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));250 251 writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |252 FIELD_PREP(STF_DPHY_RG_CDTX_L0P_HSTX_RES, 0x10),253 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(8));254 255 writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |256 FIELD_PREP(STF_DPHY_RG_CDTX_L2N_HSTX_RES, 0x10) |257 FIELD_PREP(STF_DPHY_RG_CDTX_L3N_HSTX_RES, 0x10) |258 FIELD_PREP(STF_DPHY_RG_CDTX_L1P_HSTX_RES, 0x10) |259 FIELD_PREP(STF_DPHY_RG_CDTX_L2P_HSTX_RES, 0x10) |260 FIELD_PREP(STF_DPHY_RG_CDTX_L3P_HSTX_RES, 0x10),261 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(12));262 263 writel(FIELD_PREP(STF_DPHY_RG_CDTX_L4N_HSTX_RES, 0x10) |264 FIELD_PREP(STF_DPHY_RG_CDTX_L4P_HSTX_RES, 0x10),265 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(16));266 267 /* Lane setting */268 writel(FIELD_PREP(STF_DPHY_AON_POWER_READY_N,269 STF_DPHY_AON_POWER_READY_N_ACTIVE) |270 FIELD_PREP(STF_DPHY_CFG_L0_SWAP_SEL, info->maps[0]) |271 FIELD_PREP(STF_DPHY_CFG_L1_SWAP_SEL, info->maps[1]) |272 FIELD_PREP(STF_DPHY_CFG_L2_SWAP_SEL, info->maps[2]) |273 FIELD_PREP(STF_DPHY_CFG_L3_SWAP_SEL, info->maps[3]) |274 FIELD_PREP(STF_DPHY_CFG_L4_SWAP_SEL, info->maps[4]),275 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(0));276 277 /* PLL setting */278 writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_SSC_EN, 0x0),279 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(28));280 281 writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN, 0x1) |282 FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FM_EN, 0x1) |283 FIELD_PREP(STF_DPHY_RG_CDTX_PLL_PRE_DIV, 0x0) |284 FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_INT, p[i].pll_fbk_int),285 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(24));286 287 writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_FRA,288 STF_DPHY_LSHIFT_16(p[i].pll_fbk_fra_val) |289 STF_DPHY_LSHIFT_8(p[i].pll_fbk_fra_val) |290 p[i].pll_fbk_fra_val),291 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(20));292 293 writel(FIELD_PREP(STF_DPHY_RG_EXTD_CYCLE_SEL, p[i].extd_cycle_sel),294 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(40));295 296 writel(FIELD_PREP(STF_DPHY_RG_DLANE_HS_PRE_TIME, p[i].dlane_hs_pre_time) |297 FIELD_PREP(STF_DPHY_RG_DLANE_HS_ZERO_TIME, p[i].dlane_hs_zero_time) |298 FIELD_PREP(STF_DPHY_RG_DLANE_HS_TRAIL_TIME, p[i].dlane_hs_trail_time) |299 FIELD_PREP(STF_DPHY_RG_CLANE_HS_ZERO_TIME, p[i].clane_hs_zero_time),300 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(36));301 302 writel(FIELD_PREP(STF_DPHY_RG_CLANE_HS_PRE_TIME, p[i].clane_hs_pre_time) |303 FIELD_PREP(STF_DPHY_RG_CLANE_HS_TRAIL_TIME, p[i].clane_hs_trail_time) |304 FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME, p[i].clane_hs_clk_pre_time) |305 FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_POST_TIME, p[i].clane_hs_clk_post_time),306 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(32));307 308 return 0;309}310 311static int stf_dphy_init(struct phy *phy)312{313 struct stf_dphy *dphy = phy_get_drvdata(phy);314 int ret;315 316 stf_dphy_hw_reset(dphy, 1);317 318 writel(FIELD_PREP(STF_DPHY_SCFG_PPI_C_READY_SEL, 0) |319 FIELD_PREP(STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL, 0),320 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(48));321 322 writel(FIELD_PREP(STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME, 0x30),323 dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(44));324 325 ret = clk_prepare_enable(dphy->txesc_clk);326 if (ret) {327 dev_err(dphy->dev, "Failed to prepare/enable txesc_clk\n");328 return ret;329 }330 331 ret = reset_control_deassert(dphy->sys_rst);332 if (ret) {333 dev_err(dphy->dev, "Failed to deassert sys_rst\n");334 return ret;335 }336 337 return 0;338}339 340static int stf_dphy_exit(struct phy *phy)341{342 struct stf_dphy *dphy = phy_get_drvdata(phy);343 int ret;344 345 ret = reset_control_assert(dphy->sys_rst);346 if (ret) {347 dev_err(dphy->dev, "Failed to assert sys_rst\n");348 return ret;349 }350 351 clk_disable_unprepare(dphy->txesc_clk);352 353 stf_dphy_hw_reset(dphy, 0);354 355 return 0;356}357 358static int stf_dphy_power_on(struct phy *phy)359{360 struct stf_dphy *dphy = phy_get_drvdata(phy);361 362 return pm_runtime_resume_and_get(dphy->dev);363}364 365static int stf_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,366 union phy_configure_opts *opts)367{368 if (mode != PHY_MODE_MIPI_DPHY)369 return -EINVAL;370 371 return 0;372}373 374static int stf_dphy_power_off(struct phy *phy)375{376 struct stf_dphy *dphy = phy_get_drvdata(phy);377 378 return pm_runtime_put_sync(dphy->dev);379}380 381static const struct phy_ops stf_dphy_ops = {382 .power_on = stf_dphy_power_on,383 .power_off = stf_dphy_power_off,384 .init = stf_dphy_init,385 .exit = stf_dphy_exit,386 .configure = stf_dphy_configure,387 .validate = stf_dphy_validate,388 .owner = THIS_MODULE,389};390 391static int stf_dphy_probe(struct platform_device *pdev)392{393 struct phy_provider *phy_provider;394 struct stf_dphy *dphy;395 396 dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);397 if (!dphy)398 return -ENOMEM;399 400 dphy->info = of_device_get_match_data(&pdev->dev);401 402 dphy->dev = &pdev->dev;403 dev_set_drvdata(&pdev->dev, dphy);404 405 dphy->topsys = devm_platform_ioremap_resource(pdev, 0);406 if (IS_ERR(dphy->topsys))407 return PTR_ERR(dphy->topsys);408 409 pm_runtime_enable(&pdev->dev);410 411 dphy->txesc_clk = devm_clk_get(&pdev->dev, "txesc");412 if (IS_ERR(dphy->txesc_clk))413 return dev_err_probe(&pdev->dev, PTR_ERR(dphy->txesc_clk),414 "Failed to get txesc clock\n");415 416 dphy->sys_rst = devm_reset_control_get_exclusive(&pdev->dev, "sys");417 if (IS_ERR(dphy->sys_rst))418 return dev_err_probe(&pdev->dev, PTR_ERR(dphy->sys_rst),419 "Failed to get sys reset\n");420 421 dphy->phy = devm_phy_create(&pdev->dev, NULL, &stf_dphy_ops);422 if (IS_ERR(dphy->phy))423 return dev_err_probe(&pdev->dev, PTR_ERR(dphy->phy),424 "Failed to create phy\n");425 426 phy_set_drvdata(dphy->phy, dphy);427 428 phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);429 if (IS_ERR(phy_provider))430 return dev_err_probe(&pdev->dev, PTR_ERR(phy_provider),431 "Failed to register phy\n");432 433 return 0;434}435 436static const struct stf_dphy_info starfive_dphy_info = {437 .maps = {0, 1, 2, 3, 4},438};439 440static const struct of_device_id stf_dphy_dt_ids[] = {441 {442 .compatible = "starfive,jh7110-dphy-tx",443 .data = &starfive_dphy_info,444 },445 { /* sentinel */ },446};447MODULE_DEVICE_TABLE(of, stf_dphy_dt_ids);448 449static struct platform_driver stf_dphy_driver = {450 .driver = {451 .name = "starfive-dphy-tx",452 .of_match_table = stf_dphy_dt_ids,453 },454 .probe = stf_dphy_probe,455};456module_platform_driver(stf_dphy_driver);457 458MODULE_AUTHOR("Keith Zhao <keith.zhao@starfivetech.com>");459MODULE_AUTHOR("Shengyang Chen <shengyang.chen@starfivetech.com>");460MODULE_DESCRIPTION("StarFive JH7110 DPHY TX driver");461MODULE_LICENSE("GPL");462