1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2016 Allwinnertech Co., Ltd. 4 * Copyright (C) 2017-2018 Bootlin 5 * 6 * Maxime Ripard <maxime.ripard@free-electrons.com> 7 */ 8 9 #include <linux/bitops.h> 10 #include <linux/clk.h> 11 #include <linux/module.h> 12 #include <linux/of_address.h> 13 #include <linux/platform_device.h> 14 #include <linux/regmap.h> 15 #include <linux/reset.h> 16 17 #include <linux/phy/phy.h> 18 #include <linux/phy/phy-mipi-dphy.h> 19 20 #define SUN6I_DPHY_GCTL_REG 0x00 21 #define SUN6I_DPHY_GCTL_LANE_NUM(n) ((((n) - 1) & 3) << 4) 22 #define SUN6I_DPHY_GCTL_EN BIT(0) 23 24 #define SUN6I_DPHY_TX_CTL_REG 0x04 25 #define SUN6I_DPHY_TX_CTL_HS_TX_CLK_CONT BIT(28) 26 27 #define SUN6I_DPHY_RX_CTL_REG 0x08 28 #define SUN6I_DPHY_RX_CTL_EN_DBC BIT(31) 29 #define SUN6I_DPHY_RX_CTL_RX_CLK_FORCE BIT(24) 30 #define SUN6I_DPHY_RX_CTL_RX_D3_FORCE BIT(23) 31 #define SUN6I_DPHY_RX_CTL_RX_D2_FORCE BIT(22) 32 #define SUN6I_DPHY_RX_CTL_RX_D1_FORCE BIT(21) 33 #define SUN6I_DPHY_RX_CTL_RX_D0_FORCE BIT(20) 34 35 #define SUN6I_DPHY_TX_TIME0_REG 0x10 36 #define SUN6I_DPHY_TX_TIME0_HS_TRAIL(n) (((n) & 0xff) << 24) 37 #define SUN6I_DPHY_TX_TIME0_HS_PREPARE(n) (((n) & 0xff) << 16) 38 #define SUN6I_DPHY_TX_TIME0_LP_CLK_DIV(n) ((n) & 0xff) 39 40 #define SUN6I_DPHY_TX_TIME1_REG 0x14 41 #define SUN6I_DPHY_TX_TIME1_CLK_POST(n) (((n) & 0xff) << 24) 42 #define SUN6I_DPHY_TX_TIME1_CLK_PRE(n) (((n) & 0xff) << 16) 43 #define SUN6I_DPHY_TX_TIME1_CLK_ZERO(n) (((n) & 0xff) << 8) 44 #define SUN6I_DPHY_TX_TIME1_CLK_PREPARE(n) ((n) & 0xff) 45 46 #define SUN6I_DPHY_TX_TIME2_REG 0x18 47 #define SUN6I_DPHY_TX_TIME2_CLK_TRAIL(n) ((n) & 0xff) 48 49 #define SUN6I_DPHY_TX_TIME3_REG 0x1c 50 51 #define SUN6I_DPHY_TX_TIME4_REG 0x20 52 #define SUN6I_DPHY_TX_TIME4_HS_TX_ANA1(n) (((n) & 0xff) << 8) 53 #define SUN6I_DPHY_TX_TIME4_HS_TX_ANA0(n) ((n) & 0xff) 54 55 #define SUN6I_DPHY_RX_TIME0_REG 0x30 56 #define SUN6I_DPHY_RX_TIME0_HS_RX_SYNC(n) (((n) & 0xff) << 24) 57 #define SUN6I_DPHY_RX_TIME0_HS_RX_CLK_MISS(n) (((n) & 0xff) << 16) 58 #define SUN6I_DPHY_RX_TIME0_LP_RX(n) (((n) & 0xff) << 8) 59 60 #define SUN6I_DPHY_RX_TIME1_REG 0x34 61 #define SUN6I_DPHY_RX_TIME1_RX_DLY(n) (((n) & 0xfff) << 20) 62 #define SUN6I_DPHY_RX_TIME1_LP_RX_ULPS_WP(n) ((n) & 0xfffff) 63 64 #define SUN6I_DPHY_RX_TIME2_REG 0x38 65 #define SUN6I_DPHY_RX_TIME2_HS_RX_ANA1(n) (((n) & 0xff) << 8) 66 #define SUN6I_DPHY_RX_TIME2_HS_RX_ANA0(n) ((n) & 0xff) 67 68 #define SUN6I_DPHY_RX_TIME3_REG 0x40 69 #define SUN6I_DPHY_RX_TIME3_LPRST_DLY(n) (((n) & 0xffff) << 16) 70 71 #define SUN6I_DPHY_ANA0_REG 0x4c 72 #define SUN6I_DPHY_ANA0_REG_PWS BIT(31) 73 #define SUN6I_DPHY_ANA0_REG_PWEND BIT(30) 74 #define SUN6I_DPHY_ANA0_REG_PWENC BIT(29) 75 #define SUN6I_DPHY_ANA0_REG_DMPC BIT(28) 76 #define SUN6I_DPHY_ANA0_REG_DMPD(n) (((n) & 0xf) << 24) 77 #define SUN6I_DPHY_ANA0_REG_SRXDT(n) (((n) & 0xf) << 20) 78 #define SUN6I_DPHY_ANA0_REG_SRXCK(n) (((n) & 0xf) << 16) 79 #define SUN6I_DPHY_ANA0_REG_SDIV2 BIT(15) 80 #define SUN6I_DPHY_ANA0_REG_SLV(n) (((n) & 7) << 12) 81 #define SUN6I_DPHY_ANA0_REG_DEN(n) (((n) & 0xf) << 8) 82 #define SUN6I_DPHY_ANA0_REG_PLR(n) (((n) & 0xf) << 4) 83 #define SUN6I_DPHY_ANA0_REG_SFB(n) (((n) & 3) << 2) 84 #define SUN6I_DPHY_ANA0_REG_RSD BIT(1) 85 #define SUN6I_DPHY_ANA0_REG_SELSCK BIT(0) 86 87 #define SUN6I_DPHY_ANA1_REG 0x50 88 #define SUN6I_DPHY_ANA1_REG_VTTMODE BIT(31) 89 #define SUN6I_DPHY_ANA1_REG_CSMPS(n) (((n) & 3) << 28) 90 #define SUN6I_DPHY_ANA1_REG_SVTT(n) (((n) & 0xf) << 24) 91 92 #define SUN6I_DPHY_ANA2_REG 0x54 93 #define SUN6I_DPHY_ANA2_EN_P2S_CPU(n) (((n) & 0xf) << 24) 94 #define SUN6I_DPHY_ANA2_EN_P2S_CPU_MASK GENMASK(27, 24) 95 #define SUN6I_DPHY_ANA2_EN_CK_CPU BIT(4) 96 #define SUN6I_DPHY_ANA2_REG_ENIB BIT(1) 97 98 #define SUN6I_DPHY_ANA3_REG 0x58 99 #define SUN6I_DPHY_ANA3_EN_VTTD(n) (((n) & 0xf) << 28) 100 #define SUN6I_DPHY_ANA3_EN_VTTD_MASK GENMASK(31, 28) 101 #define SUN6I_DPHY_ANA3_EN_VTTC BIT(27) 102 #define SUN6I_DPHY_ANA3_EN_DIV BIT(26) 103 #define SUN6I_DPHY_ANA3_EN_LDOC BIT(25) 104 #define SUN6I_DPHY_ANA3_EN_LDOD BIT(24) 105 #define SUN6I_DPHY_ANA3_EN_LDOR BIT(18) 106 107 #define SUN6I_DPHY_ANA4_REG 0x5c 108 #define SUN6I_DPHY_ANA4_REG_EN_MIPI BIT(31) 109 #define SUN6I_DPHY_ANA4_REG_EN_COMTEST BIT(30) 110 #define SUN6I_DPHY_ANA4_REG_COMTEST(n) (((n) & 3) << 28) 111 #define SUN6I_DPHY_ANA4_REG_IB(n) (((n) & 3) << 25) 112 #define SUN6I_DPHY_ANA4_REG_DMPLVC BIT(24) 113 #define SUN6I_DPHY_ANA4_REG_DMPLVD(n) (((n) & 0xf) << 20) 114 #define SUN6I_DPHY_ANA4_REG_VTT_SET(n) (((n) & 0x7) << 17) 115 #define SUN6I_DPHY_ANA4_REG_CKDV(n) (((n) & 0x1f) << 12) 116 #define SUN6I_DPHY_ANA4_REG_TMSC(n) (((n) & 3) << 10) 117 #define SUN6I_DPHY_ANA4_REG_TMSD(n) (((n) & 3) << 8) 118 #define SUN6I_DPHY_ANA4_REG_TXDNSC(n) (((n) & 3) << 6) 119 #define SUN6I_DPHY_ANA4_REG_TXDNSD(n) (((n) & 3) << 4) 120 #define SUN6I_DPHY_ANA4_REG_TXPUSC(n) (((n) & 3) << 2) 121 #define SUN6I_DPHY_ANA4_REG_TXPUSD(n) ((n) & 3) 122 123 #define SUN6I_DPHY_DBG5_REG 0xf4 124 125 #define SUN50I_DPHY_TX_SLEW_REG0 0xf8 126 #define SUN50I_DPHY_TX_SLEW_REG1 0xfc 127 #define SUN50I_DPHY_TX_SLEW_REG2 0x100 128 129 #define SUN50I_DPHY_PLL_REG0 0x104 130 #define SUN50I_DPHY_PLL_REG0_CP36_EN BIT(23) 131 #define SUN50I_DPHY_PLL_REG0_LDO_EN BIT(22) 132 #define SUN50I_DPHY_PLL_REG0_EN_LVS BIT(21) 133 #define SUN50I_DPHY_PLL_REG0_PLL_EN BIT(20) 134 #define SUN50I_DPHY_PLL_REG0_P(n) (((n) & 0xf) << 16) 135 #define SUN50I_DPHY_PLL_REG0_N(n) (((n) & 0xff) << 8) 136 #define SUN50I_DPHY_PLL_REG0_NDET BIT(7) 137 #define SUN50I_DPHY_PLL_REG0_TDIV BIT(6) 138 #define SUN50I_DPHY_PLL_REG0_M0(n) (((n) & 3) << 4) 139 #define SUN50I_DPHY_PLL_REG0_M1(n) ((n) & 0xf) 140 141 #define SUN50I_DPHY_PLL_REG1 0x108 142 #define SUN50I_DPHY_PLL_REG1_UNLOCK_MDSEL(n) (((n) & 3) << 14) 143 #define SUN50I_DPHY_PLL_REG1_LOCKMDSEL BIT(13) 144 #define SUN50I_DPHY_PLL_REG1_LOCKDET_EN BIT(12) 145 #define SUN50I_DPHY_PLL_REG1_VSETA(n) (((n) & 0x7) << 9) 146 #define SUN50I_DPHY_PLL_REG1_VSETD(n) (((n) & 0x7) << 6) 147 #define SUN50I_DPHY_PLL_REG1_LPF_SW BIT(5) 148 #define SUN50I_DPHY_PLL_REG1_ICP_SEL(n) (((n) & 3) << 3) 149 #define SUN50I_DPHY_PLL_REG1_ATEST_SEL(n) (((n) & 3) << 1) 150 #define SUN50I_DPHY_PLL_REG1_TEST_EN BIT(0) 151 152 #define SUN50I_DPHY_PLL_REG2 0x10c 153 #define SUN50I_DPHY_PLL_REG2_SDM_EN BIT(31) 154 #define SUN50I_DPHY_PLL_REG2_FF_EN BIT(30) 155 #define SUN50I_DPHY_PLL_REG2_SS_EN BIT(29) 156 #define SUN50I_DPHY_PLL_REG2_SS_FRAC(n) (((n) & 0x1ff) << 20) 157 #define SUN50I_DPHY_PLL_REG2_SS_INT(n) (((n) & 0xff) << 12) 158 #define SUN50I_DPHY_PLL_REG2_FRAC(n) ((n) & 0xfff) 159 160 #define SUN50I_COMBO_PHY_REG0 0x110 161 #define SUN50I_COMBO_PHY_REG0_EN_TEST_COMBOLDO BIT(5) 162 #define SUN50I_COMBO_PHY_REG0_EN_TEST_0P8 BIT(4) 163 #define SUN50I_COMBO_PHY_REG0_EN_MIPI BIT(3) 164 #define SUN50I_COMBO_PHY_REG0_EN_LVDS BIT(2) 165 #define SUN50I_COMBO_PHY_REG0_EN_COMBOLDO BIT(1) 166 #define SUN50I_COMBO_PHY_REG0_EN_CP BIT(0) 167 168 #define SUN50I_COMBO_PHY_REG1 0x114 169 #define SUN50I_COMBO_PHY_REG2_REG_VREF1P6(n) (((n) & 0x7) << 4) 170 #define SUN50I_COMBO_PHY_REG2_REG_VREF0P8(n) ((n) & 0x7) 171 172 #define SUN50I_COMBO_PHY_REG2 0x118 173 #define SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(n) ((n) & 0xff) 174 175 enum sun6i_dphy_direction { 176 SUN6I_DPHY_DIRECTION_TX, 177 SUN6I_DPHY_DIRECTION_RX, 178 }; 179 180 struct sun6i_dphy; 181 182 struct sun6i_dphy_variant { 183 void (*tx_power_on)(struct sun6i_dphy *dphy); 184 bool rx_supported; 185 }; 186 187 struct sun6i_dphy { 188 struct clk *bus_clk; 189 struct clk *mod_clk; 190 struct regmap *regs; 191 struct reset_control *reset; 192 193 struct phy *phy; 194 struct phy_configure_opts_mipi_dphy config; 195 196 const struct sun6i_dphy_variant *variant; 197 enum sun6i_dphy_direction direction; 198 }; 199 200 static int sun6i_dphy_init(struct phy *phy) 201 { 202 struct sun6i_dphy *dphy = phy_get_drvdata(phy); 203 204 reset_control_deassert(dphy->reset); 205 clk_prepare_enable(dphy->mod_clk); 206 clk_set_rate_exclusive(dphy->mod_clk, 150000000); 207 208 return 0; 209 } 210 211 static int sun6i_dphy_configure(struct phy *phy, union phy_configure_opts *opts) 212 { 213 struct sun6i_dphy *dphy = phy_get_drvdata(phy); 214 int ret; 215 216 ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy); 217 if (ret) 218 return ret; 219 220 memcpy(&dphy->config, opts, sizeof(dphy->config)); 221 222 return 0; 223 } 224 225 static void sun6i_a31_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy) 226 { 227 u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0); 228 229 regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, 230 SUN6I_DPHY_ANA0_REG_PWS | 231 SUN6I_DPHY_ANA0_REG_DMPC | 232 SUN6I_DPHY_ANA0_REG_SLV(7) | 233 SUN6I_DPHY_ANA0_REG_DMPD(lanes_mask) | 234 SUN6I_DPHY_ANA0_REG_DEN(lanes_mask)); 235 236 regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG, 237 SUN6I_DPHY_ANA1_REG_CSMPS(1) | 238 SUN6I_DPHY_ANA1_REG_SVTT(7)); 239 240 regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, 241 SUN6I_DPHY_ANA4_REG_CKDV(1) | 242 SUN6I_DPHY_ANA4_REG_TMSC(1) | 243 SUN6I_DPHY_ANA4_REG_TMSD(1) | 244 SUN6I_DPHY_ANA4_REG_TXDNSC(1) | 245 SUN6I_DPHY_ANA4_REG_TXDNSD(1) | 246 SUN6I_DPHY_ANA4_REG_TXPUSC(1) | 247 SUN6I_DPHY_ANA4_REG_TXPUSD(1) | 248 SUN6I_DPHY_ANA4_REG_DMPLVC | 249 SUN6I_DPHY_ANA4_REG_DMPLVD(lanes_mask)); 250 251 regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG, 252 SUN6I_DPHY_ANA2_REG_ENIB); 253 udelay(5); 254 255 regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, 256 SUN6I_DPHY_ANA3_EN_LDOR | 257 SUN6I_DPHY_ANA3_EN_LDOC | 258 SUN6I_DPHY_ANA3_EN_LDOD); 259 udelay(1); 260 } 261 262 static void sun50i_a100_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy) 263 { 264 unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate; 265 unsigned int div, n; 266 267 regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, 268 SUN6I_DPHY_ANA4_REG_IB(2) | 269 SUN6I_DPHY_ANA4_REG_DMPLVD(4) | 270 SUN6I_DPHY_ANA4_REG_VTT_SET(3) | 271 SUN6I_DPHY_ANA4_REG_CKDV(3) | 272 SUN6I_DPHY_ANA4_REG_TMSD(1) | 273 SUN6I_DPHY_ANA4_REG_TMSC(1) | 274 SUN6I_DPHY_ANA4_REG_TXPUSD(2) | 275 SUN6I_DPHY_ANA4_REG_TXPUSC(3) | 276 SUN6I_DPHY_ANA4_REG_TXDNSD(2) | 277 SUN6I_DPHY_ANA4_REG_TXDNSC(3)); 278 279 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG, 280 SUN6I_DPHY_ANA2_EN_CK_CPU, 281 SUN6I_DPHY_ANA2_EN_CK_CPU); 282 283 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG, 284 SUN6I_DPHY_ANA2_REG_ENIB, 285 SUN6I_DPHY_ANA2_REG_ENIB); 286 287 regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, 288 SUN6I_DPHY_ANA3_EN_LDOR | 289 SUN6I_DPHY_ANA3_EN_LDOC | 290 SUN6I_DPHY_ANA3_EN_LDOD); 291 292 regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, 293 SUN6I_DPHY_ANA0_REG_PLR(4) | 294 SUN6I_DPHY_ANA0_REG_SFB(1)); 295 296 regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG0, 297 SUN50I_COMBO_PHY_REG0_EN_CP); 298 299 /* Choose a divider to limit the VCO frequency to around 2 GHz. */ 300 div = 16 >> order_base_2(DIV_ROUND_UP(mipi_symbol_rate, 264000000)); 301 n = mipi_symbol_rate * div / 24000000; 302 303 regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG0, 304 SUN50I_DPHY_PLL_REG0_CP36_EN | 305 SUN50I_DPHY_PLL_REG0_LDO_EN | 306 SUN50I_DPHY_PLL_REG0_EN_LVS | 307 SUN50I_DPHY_PLL_REG0_PLL_EN | 308 SUN50I_DPHY_PLL_REG0_NDET | 309 SUN50I_DPHY_PLL_REG0_P((div - 1) % 8) | 310 SUN50I_DPHY_PLL_REG0_N(n) | 311 SUN50I_DPHY_PLL_REG0_M0((div - 1) / 8) | 312 SUN50I_DPHY_PLL_REG0_M1(2)); 313 314 /* Disable sigma-delta modulation. */ 315 regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG2, 0); 316 317 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA4_REG, 318 SUN6I_DPHY_ANA4_REG_EN_MIPI, 319 SUN6I_DPHY_ANA4_REG_EN_MIPI); 320 321 regmap_update_bits(dphy->regs, SUN50I_COMBO_PHY_REG0, 322 SUN50I_COMBO_PHY_REG0_EN_MIPI | 323 SUN50I_COMBO_PHY_REG0_EN_COMBOLDO, 324 SUN50I_COMBO_PHY_REG0_EN_MIPI | 325 SUN50I_COMBO_PHY_REG0_EN_COMBOLDO); 326 327 regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG2, 328 SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(20)); 329 udelay(1); 330 } 331 332 static int sun6i_dphy_tx_power_on(struct sun6i_dphy *dphy) 333 { 334 u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0); 335 336 regmap_write(dphy->regs, SUN6I_DPHY_TX_CTL_REG, 337 SUN6I_DPHY_TX_CTL_HS_TX_CLK_CONT); 338 339 regmap_write(dphy->regs, SUN6I_DPHY_TX_TIME0_REG, 340 SUN6I_DPHY_TX_TIME0_LP_CLK_DIV(14) | 341 SUN6I_DPHY_TX_TIME0_HS_PREPARE(6) | 342 SUN6I_DPHY_TX_TIME0_HS_TRAIL(10)); 343 344 regmap_write(dphy->regs, SUN6I_DPHY_TX_TIME1_REG, 345 SUN6I_DPHY_TX_TIME1_CLK_PREPARE(7) | 346 SUN6I_DPHY_TX_TIME1_CLK_ZERO(50) | 347 SUN6I_DPHY_TX_TIME1_CLK_PRE(3) | 348 SUN6I_DPHY_TX_TIME1_CLK_POST(10)); 349 350 regmap_write(dphy->regs, SUN6I_DPHY_TX_TIME2_REG, 351 SUN6I_DPHY_TX_TIME2_CLK_TRAIL(30)); 352 353 regmap_write(dphy->regs, SUN6I_DPHY_TX_TIME3_REG, 0); 354 355 regmap_write(dphy->regs, SUN6I_DPHY_TX_TIME4_REG, 356 SUN6I_DPHY_TX_TIME4_HS_TX_ANA0(3) | 357 SUN6I_DPHY_TX_TIME4_HS_TX_ANA1(3)); 358 359 dphy->variant->tx_power_on(dphy); 360 361 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA3_REG, 362 SUN6I_DPHY_ANA3_EN_VTTC | 363 SUN6I_DPHY_ANA3_EN_VTTD_MASK, 364 SUN6I_DPHY_ANA3_EN_VTTC | 365 SUN6I_DPHY_ANA3_EN_VTTD(lanes_mask)); 366 udelay(1); 367 368 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA3_REG, 369 SUN6I_DPHY_ANA3_EN_DIV, 370 SUN6I_DPHY_ANA3_EN_DIV); 371 udelay(1); 372 373 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG, 374 SUN6I_DPHY_ANA2_EN_CK_CPU, 375 SUN6I_DPHY_ANA2_EN_CK_CPU); 376 udelay(1); 377 378 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA1_REG, 379 SUN6I_DPHY_ANA1_REG_VTTMODE, 380 SUN6I_DPHY_ANA1_REG_VTTMODE); 381 382 regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG, 383 SUN6I_DPHY_ANA2_EN_P2S_CPU_MASK, 384 SUN6I_DPHY_ANA2_EN_P2S_CPU(lanes_mask)); 385 386 regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG, 387 SUN6I_DPHY_GCTL_LANE_NUM(dphy->config.lanes) | 388 SUN6I_DPHY_GCTL_EN); 389 390 return 0; 391 } 392 393 static int sun6i_dphy_rx_power_on(struct sun6i_dphy *dphy) 394 { 395 /* Physical clock rate is actually half of symbol rate with DDR. */ 396 unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate; 397 unsigned long dphy_clk_rate; 398 unsigned int rx_dly; 399 unsigned int lprst_dly; 400 u32 value; 401 402 dphy_clk_rate = clk_get_rate(dphy->mod_clk); 403 if (!dphy_clk_rate) 404 return -EINVAL; 405 406 /* Hardcoded timing parameters from the Allwinner BSP. */ 407 regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME0_REG, 408 SUN6I_DPHY_RX_TIME0_HS_RX_SYNC(255) | 409 SUN6I_DPHY_RX_TIME0_HS_RX_CLK_MISS(255) | 410 SUN6I_DPHY_RX_TIME0_LP_RX(255)); 411 412 /* 413 * Formula from the Allwinner BSP, with hardcoded coefficients 414 * (probably internal divider/multiplier). 415 */ 416 rx_dly = 8 * (unsigned int)(dphy_clk_rate / (mipi_symbol_rate / 8)); 417 418 /* 419 * The Allwinner BSP has an alternative formula for LP_RX_ULPS_WP: 420 * lp_ulps_wp_cnt = lp_ulps_wp_ms * lp_clk / 1000 421 * but does not use it and hardcodes 255 instead. 422 */ 423 regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME1_REG, 424 SUN6I_DPHY_RX_TIME1_RX_DLY(rx_dly) | 425 SUN6I_DPHY_RX_TIME1_LP_RX_ULPS_WP(255)); 426 427 /* HS_RX_ANA0 value is hardcoded in the Allwinner BSP. */ 428 regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME2_REG, 429 SUN6I_DPHY_RX_TIME2_HS_RX_ANA0(4)); 430 431 /* 432 * Formula from the Allwinner BSP, with hardcoded coefficients 433 * (probably internal divider/multiplier). 434 */ 435 lprst_dly = 4 * (unsigned int)(dphy_clk_rate / (mipi_symbol_rate / 2)); 436 437 regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME3_REG, 438 SUN6I_DPHY_RX_TIME3_LPRST_DLY(lprst_dly)); 439 440 /* Analog parameters are hardcoded in the Allwinner BSP. */ 441 regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, 442 SUN6I_DPHY_ANA0_REG_PWS | 443 SUN6I_DPHY_ANA0_REG_SLV(7) | 444 SUN6I_DPHY_ANA0_REG_SFB(2)); 445 446 regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG, 447 SUN6I_DPHY_ANA1_REG_SVTT(4)); 448 449 regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, 450 SUN6I_DPHY_ANA4_REG_DMPLVC | 451 SUN6I_DPHY_ANA4_REG_DMPLVD(1)); 452 453 regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG, 454 SUN6I_DPHY_ANA2_REG_ENIB); 455 456 regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, 457 SUN6I_DPHY_ANA3_EN_LDOR | 458 SUN6I_DPHY_ANA3_EN_LDOC | 459 SUN6I_DPHY_ANA3_EN_LDOD); 460 461 /* 462 * Delay comes from the Allwinner BSP, likely for internal regulator 463 * ramp-up. 464 */ 465 udelay(3); 466 467 value = SUN6I_DPHY_RX_CTL_EN_DBC | SUN6I_DPHY_RX_CTL_RX_CLK_FORCE; 468 469 /* 470 * Rx data lane force-enable bits are used as regular RX enable by the 471 * Allwinner BSP. 472 */ 473 if (dphy->config.lanes >= 1) 474 value |= SUN6I_DPHY_RX_CTL_RX_D0_FORCE; 475 if (dphy->config.lanes >= 2) 476 value |= SUN6I_DPHY_RX_CTL_RX_D1_FORCE; 477 if (dphy->config.lanes >= 3) 478 value |= SUN6I_DPHY_RX_CTL_RX_D2_FORCE; 479 if (dphy->config.lanes == 4) 480 value |= SUN6I_DPHY_RX_CTL_RX_D3_FORCE; 481 482 regmap_write(dphy->regs, SUN6I_DPHY_RX_CTL_REG, value); 483 484 regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG, 485 SUN6I_DPHY_GCTL_LANE_NUM(dphy->config.lanes) | 486 SUN6I_DPHY_GCTL_EN); 487 488 return 0; 489 } 490 491 static int sun6i_dphy_power_on(struct phy *phy) 492 { 493 struct sun6i_dphy *dphy = phy_get_drvdata(phy); 494 495 switch (dphy->direction) { 496 case SUN6I_DPHY_DIRECTION_TX: 497 return sun6i_dphy_tx_power_on(dphy); 498 case SUN6I_DPHY_DIRECTION_RX: 499 return sun6i_dphy_rx_power_on(dphy); 500 default: 501 return -EINVAL; 502 } 503 } 504 505 static int sun6i_dphy_power_off(struct phy *phy) 506 { 507 struct sun6i_dphy *dphy = phy_get_drvdata(phy); 508 509 regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG, 0); 510 511 regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, 0); 512 regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG, 0); 513 regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG, 0); 514 regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, 0); 515 regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, 0); 516 517 return 0; 518 } 519 520 static int sun6i_dphy_exit(struct phy *phy) 521 { 522 struct sun6i_dphy *dphy = phy_get_drvdata(phy); 523 524 clk_rate_exclusive_put(dphy->mod_clk); 525 clk_disable_unprepare(dphy->mod_clk); 526 reset_control_assert(dphy->reset); 527 528 return 0; 529 } 530 531 532 static const struct phy_ops sun6i_dphy_ops = { 533 .configure = sun6i_dphy_configure, 534 .power_on = sun6i_dphy_power_on, 535 .power_off = sun6i_dphy_power_off, 536 .init = sun6i_dphy_init, 537 .exit = sun6i_dphy_exit, 538 }; 539 540 static const struct regmap_config sun6i_dphy_regmap_config = { 541 .reg_bits = 32, 542 .val_bits = 32, 543 .reg_stride = 4, 544 .max_register = SUN50I_COMBO_PHY_REG2, 545 .name = "mipi-dphy", 546 }; 547 548 static int sun6i_dphy_probe(struct platform_device *pdev) 549 { 550 struct phy_provider *phy_provider; 551 struct sun6i_dphy *dphy; 552 const char *direction; 553 void __iomem *regs; 554 int ret; 555 556 dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL); 557 if (!dphy) 558 return -ENOMEM; 559 560 dphy->variant = device_get_match_data(&pdev->dev); 561 if (!dphy->variant) 562 return -EINVAL; 563 564 regs = devm_platform_ioremap_resource(pdev, 0); 565 if (IS_ERR(regs)) { 566 dev_err(&pdev->dev, "Couldn't map the DPHY encoder registers\n"); 567 return PTR_ERR(regs); 568 } 569 570 dphy->regs = devm_regmap_init_mmio_clk(&pdev->dev, "bus", 571 regs, &sun6i_dphy_regmap_config); 572 if (IS_ERR(dphy->regs)) { 573 dev_err(&pdev->dev, "Couldn't create the DPHY encoder regmap\n"); 574 return PTR_ERR(dphy->regs); 575 } 576 577 dphy->reset = devm_reset_control_get_shared(&pdev->dev, NULL); 578 if (IS_ERR(dphy->reset)) { 579 dev_err(&pdev->dev, "Couldn't get our reset line\n"); 580 return PTR_ERR(dphy->reset); 581 } 582 583 dphy->mod_clk = devm_clk_get(&pdev->dev, "mod"); 584 if (IS_ERR(dphy->mod_clk)) { 585 dev_err(&pdev->dev, "Couldn't get the DPHY mod clock\n"); 586 return PTR_ERR(dphy->mod_clk); 587 } 588 589 dphy->phy = devm_phy_create(&pdev->dev, NULL, &sun6i_dphy_ops); 590 if (IS_ERR(dphy->phy)) { 591 dev_err(&pdev->dev, "failed to create PHY\n"); 592 return PTR_ERR(dphy->phy); 593 } 594 595 dphy->direction = SUN6I_DPHY_DIRECTION_TX; 596 597 ret = of_property_read_string(pdev->dev.of_node, "allwinner,direction", 598 &direction); 599 600 if (!ret && !strncmp(direction, "rx", 2)) { 601 if (!dphy->variant->rx_supported) { 602 dev_err(&pdev->dev, "RX not supported on this variant\n"); 603 return -EOPNOTSUPP; 604 } 605 606 dphy->direction = SUN6I_DPHY_DIRECTION_RX; 607 } 608 609 phy_set_drvdata(dphy->phy, dphy); 610 phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); 611 612 return PTR_ERR_OR_ZERO(phy_provider); 613 } 614 615 static const struct sun6i_dphy_variant sun6i_a31_mipi_dphy_variant = { 616 .tx_power_on = sun6i_a31_mipi_dphy_tx_power_on, 617 .rx_supported = true, 618 }; 619 620 static const struct sun6i_dphy_variant sun50i_a100_mipi_dphy_variant = { 621 .tx_power_on = sun50i_a100_mipi_dphy_tx_power_on, 622 }; 623 624 static const struct of_device_id sun6i_dphy_of_table[] = { 625 { 626 .compatible = "allwinner,sun6i-a31-mipi-dphy", 627 .data = &sun6i_a31_mipi_dphy_variant, 628 }, 629 { 630 .compatible = "allwinner,sun50i-a100-mipi-dphy", 631 .data = &sun50i_a100_mipi_dphy_variant, 632 }, 633 { } 634 }; 635 MODULE_DEVICE_TABLE(of, sun6i_dphy_of_table); 636 637 static struct platform_driver sun6i_dphy_platform_driver = { 638 .probe = sun6i_dphy_probe, 639 .driver = { 640 .name = "sun6i-mipi-dphy", 641 .of_match_table = sun6i_dphy_of_table, 642 }, 643 }; 644 module_platform_driver(sun6i_dphy_platform_driver); 645 646 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin>"); 647 MODULE_DESCRIPTION("Allwinner A31 MIPI D-PHY Driver"); 648 MODULE_LICENSE("GPL"); 649