1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013--2024 Intel Corporation 4 */ 5 6 #include <linux/bitfield.h> 7 #include <linux/bits.h> 8 #include <linux/delay.h> 9 #include <linux/device.h> 10 #include <linux/iopoll.h> 11 #include <linux/math64.h> 12 13 #include "ipu6-bus.h" 14 #include "ipu6-isys.h" 15 #include "ipu6-platform-isys-csi2-reg.h" 16 17 #define IPU6_DWC_DPHY_BASE(i) (0x238038 + 0x34 * (i)) 18 #define IPU6_DWC_DPHY_RSTZ 0x00 19 #define IPU6_DWC_DPHY_SHUTDOWNZ 0x04 20 #define IPU6_DWC_DPHY_HSFREQRANGE 0x08 21 #define IPU6_DWC_DPHY_CFGCLKFREQRANGE 0x0c 22 #define IPU6_DWC_DPHY_TEST_IFC_ACCESS_MODE 0x10 23 #define IPU6_DWC_DPHY_TEST_IFC_REQ 0x14 24 #define IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION 0x18 25 #define IPU6_DWC_DPHY_DFT_CTRL0 0x28 26 #define IPU6_DWC_DPHY_DFT_CTRL1 0x2c 27 #define IPU6_DWC_DPHY_DFT_CTRL2 0x30 28 29 /* 30 * test IFC request definition: 31 * - req: 0 for read, 1 for write 32 * - 12 bits address 33 * - 8bits data (will ignore for read) 34 * --24----16------4-----0 35 * --|-data-|-addr-|-req-| 36 */ 37 #define IFC_REQ(req, addr, data) (FIELD_PREP(GENMASK(23, 16), data) | \ 38 FIELD_PREP(GENMASK(15, 4), addr) | \ 39 FIELD_PREP(GENMASK(1, 0), req)) 40 41 #define TEST_IFC_REQ_READ 0 42 #define TEST_IFC_REQ_WRITE 1 43 #define TEST_IFC_REQ_RESET 2 44 45 #define TEST_IFC_ACCESS_MODE_FSM 0 46 #define TEST_IFC_ACCESS_MODE_IFC_CTL 1 47 48 enum phy_fsm_state { 49 PHY_FSM_STATE_POWERON = 0, 50 PHY_FSM_STATE_BGPON = 1, 51 PHY_FSM_STATE_CAL_TYPE = 2, 52 PHY_FSM_STATE_BURNIN_CAL = 3, 53 PHY_FSM_STATE_TERMCAL = 4, 54 PHY_FSM_STATE_OFFSETCAL = 5, 55 PHY_FSM_STATE_OFFSET_LANE = 6, 56 PHY_FSM_STATE_IDLE = 7, 57 PHY_FSM_STATE_ULP = 8, 58 PHY_FSM_STATE_DDLTUNNING = 9, 59 PHY_FSM_STATE_SKEW_BACKWARD = 10, 60 PHY_FSM_STATE_INVALID, 61 }; 62 63 static void dwc_dphy_write(struct ipu6_isys *isys, u32 phy_id, u32 addr, 64 u32 data) 65 { 66 struct device *dev = &isys->adev->auxdev.dev; 67 void __iomem *isys_base = isys->pdata->base; 68 void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); 69 70 dev_dbg(dev, "write: reg 0x%lx = data 0x%x", base + addr - isys_base, 71 data); 72 writel(data, base + addr); 73 } 74 75 static u32 dwc_dphy_read(struct ipu6_isys *isys, u32 phy_id, u32 addr) 76 { 77 struct device *dev = &isys->adev->auxdev.dev; 78 void __iomem *isys_base = isys->pdata->base; 79 void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); 80 u32 data; 81 82 data = readl(base + addr); 83 dev_dbg(dev, "read: reg 0x%lx = data 0x%x", base + addr - isys_base, 84 data); 85 86 return data; 87 } 88 89 static void dwc_dphy_write_mask(struct ipu6_isys *isys, u32 phy_id, u32 addr, 90 u32 data, u8 shift, u8 width) 91 { 92 u32 temp; 93 u32 mask; 94 95 mask = (1 << width) - 1; 96 temp = dwc_dphy_read(isys, phy_id, addr); 97 temp &= ~(mask << shift); 98 temp |= (data & mask) << shift; 99 dwc_dphy_write(isys, phy_id, addr, temp); 100 } 101 102 static u32 __maybe_unused dwc_dphy_read_mask(struct ipu6_isys *isys, u32 phy_id, 103 u32 addr, u8 shift, u8 width) 104 { 105 u32 val; 106 107 val = dwc_dphy_read(isys, phy_id, addr) >> shift; 108 return val & ((1 << width) - 1); 109 } 110 111 #define DWC_DPHY_TIMEOUT (5 * USEC_PER_SEC) 112 static int dwc_dphy_ifc_read(struct ipu6_isys *isys, u32 phy_id, u32 addr, 113 u32 *val) 114 { 115 struct device *dev = &isys->adev->auxdev.dev; 116 void __iomem *isys_base = isys->pdata->base; 117 void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); 118 void __iomem *reg; 119 u32 completion; 120 int ret; 121 122 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, 123 IFC_REQ(TEST_IFC_REQ_READ, addr, 0)); 124 reg = base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION; 125 ret = readl_poll_timeout(reg, completion, !(completion & BIT(0)), 126 10, DWC_DPHY_TIMEOUT); 127 if (ret) { 128 dev_err(dev, "DWC ifc request read timeout\n"); 129 return ret; 130 } 131 132 *val = completion >> 8 & 0xff; 133 *val = FIELD_GET(GENMASK(15, 8), completion); 134 dev_dbg(dev, "DWC ifc read 0x%x = 0x%x", addr, *val); 135 136 return 0; 137 } 138 139 static int dwc_dphy_ifc_write(struct ipu6_isys *isys, u32 phy_id, u32 addr, 140 u32 data) 141 { 142 struct device *dev = &isys->adev->auxdev.dev; 143 void __iomem *isys_base = isys->pdata->base; 144 void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); 145 void __iomem *reg; 146 u32 completion; 147 int ret; 148 149 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, 150 IFC_REQ(TEST_IFC_REQ_WRITE, addr, data)); 151 completion = readl(base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION); 152 reg = base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION; 153 ret = readl_poll_timeout(reg, completion, !(completion & BIT(0)), 154 10, DWC_DPHY_TIMEOUT); 155 if (ret) 156 dev_err(dev, "DWC ifc request write timeout\n"); 157 158 return ret; 159 } 160 161 static void dwc_dphy_ifc_write_mask(struct ipu6_isys *isys, u32 phy_id, 162 u32 addr, u32 data, u8 shift, u8 width) 163 { 164 u32 temp, mask; 165 int ret; 166 167 ret = dwc_dphy_ifc_read(isys, phy_id, addr, &temp); 168 if (ret) 169 return; 170 171 mask = (1 << width) - 1; 172 temp &= ~(mask << shift); 173 temp |= (data & mask) << shift; 174 dwc_dphy_ifc_write(isys, phy_id, addr, temp); 175 } 176 177 static u32 dwc_dphy_ifc_read_mask(struct ipu6_isys *isys, u32 phy_id, u32 addr, 178 u8 shift, u8 width) 179 { 180 int ret; 181 u32 val; 182 183 ret = dwc_dphy_ifc_read(isys, phy_id, addr, &val); 184 if (ret) 185 return 0; 186 187 return ((val >> shift) & ((1 << width) - 1)); 188 } 189 190 static int dwc_dphy_pwr_up(struct ipu6_isys *isys, u32 phy_id) 191 { 192 struct device *dev = &isys->adev->auxdev.dev; 193 u32 fsm_state; 194 int ret; 195 196 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_RSTZ, 1); 197 usleep_range(10, 20); 198 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_SHUTDOWNZ, 1); 199 200 ret = read_poll_timeout(dwc_dphy_ifc_read_mask, fsm_state, 201 (fsm_state == PHY_FSM_STATE_IDLE || 202 fsm_state == PHY_FSM_STATE_ULP), 203 100, DWC_DPHY_TIMEOUT, false, isys, 204 phy_id, 0x1e, 0, 4); 205 206 if (ret) 207 dev_err(dev, "Dphy %d power up failed, state 0x%x", phy_id, 208 fsm_state); 209 210 return ret; 211 } 212 213 struct dwc_dphy_freq_range { 214 u8 hsfreq; 215 u16 min; 216 u16 max; 217 u16 default_mbps; 218 u16 osc_freq_target; 219 }; 220 221 #define DPHY_FREQ_RANGE_NUM (63) 222 #define DPHY_FREQ_RANGE_INVALID_INDEX (0xff) 223 static const struct dwc_dphy_freq_range freqranges[DPHY_FREQ_RANGE_NUM] = { 224 {0x00, 80, 97, 80, 335}, 225 {0x10, 80, 107, 90, 335}, 226 {0x20, 84, 118, 100, 335}, 227 {0x30, 93, 128, 110, 335}, 228 {0x01, 103, 139, 120, 335}, 229 {0x11, 112, 149, 130, 335}, 230 {0x21, 122, 160, 140, 335}, 231 {0x31, 131, 170, 150, 335}, 232 {0x02, 141, 181, 160, 335}, 233 {0x12, 150, 191, 170, 335}, 234 {0x22, 160, 202, 180, 335}, 235 {0x32, 169, 212, 190, 335}, 236 {0x03, 183, 228, 205, 335}, 237 {0x13, 198, 244, 220, 335}, 238 {0x23, 212, 259, 235, 335}, 239 {0x33, 226, 275, 250, 335}, 240 {0x04, 250, 301, 275, 335}, 241 {0x14, 274, 328, 300, 335}, 242 {0x25, 297, 354, 325, 335}, 243 {0x35, 321, 380, 350, 335}, 244 {0x05, 369, 433, 400, 335}, 245 {0x16, 416, 485, 450, 335}, 246 {0x26, 464, 538, 500, 335}, 247 {0x37, 511, 590, 550, 335}, 248 {0x07, 559, 643, 600, 335}, 249 {0x18, 606, 695, 650, 335}, 250 {0x28, 654, 748, 700, 335}, 251 {0x39, 701, 800, 750, 335}, 252 {0x09, 749, 853, 800, 335}, 253 {0x19, 796, 905, 850, 335}, 254 {0x29, 844, 958, 900, 335}, 255 {0x3a, 891, 1010, 950, 335}, 256 {0x0a, 939, 1063, 1000, 335}, 257 {0x1a, 986, 1115, 1050, 335}, 258 {0x2a, 1034, 1168, 1100, 335}, 259 {0x3b, 1081, 1220, 1150, 335}, 260 {0x0b, 1129, 1273, 1200, 335}, 261 {0x1b, 1176, 1325, 1250, 335}, 262 {0x2b, 1224, 1378, 1300, 335}, 263 {0x3c, 1271, 1430, 1350, 335}, 264 {0x0c, 1319, 1483, 1400, 335}, 265 {0x1c, 1366, 1535, 1450, 335}, 266 {0x2c, 1414, 1588, 1500, 335}, 267 {0x3d, 1461, 1640, 1550, 208}, 268 {0x0d, 1509, 1693, 1600, 214}, 269 {0x1d, 1556, 1745, 1650, 221}, 270 {0x2e, 1604, 1798, 1700, 228}, 271 {0x3e, 1651, 1850, 1750, 234}, 272 {0x0e, 1699, 1903, 1800, 241}, 273 {0x1e, 1746, 1955, 1850, 248}, 274 {0x2f, 1794, 2008, 1900, 255}, 275 {0x3f, 1841, 2060, 1950, 261}, 276 {0x0f, 1889, 2113, 2000, 268}, 277 {0x40, 1936, 2165, 2050, 275}, 278 {0x41, 1984, 2218, 2100, 281}, 279 {0x42, 2031, 2270, 2150, 288}, 280 {0x43, 2079, 2323, 2200, 294}, 281 {0x44, 2126, 2375, 2250, 302}, 282 {0x45, 2174, 2428, 2300, 308}, 283 {0x46, 2221, 2480, 2350, 315}, 284 {0x47, 2269, 2500, 2400, 321}, 285 {0x48, 2316, 2500, 2450, 328}, 286 {0x49, 2364, 2500, 2500, 335} 287 }; 288 289 static u16 get_hsfreq_by_mbps(u32 mbps) 290 { 291 unsigned int i = DPHY_FREQ_RANGE_NUM; 292 293 while (i--) { 294 if (freqranges[i].default_mbps == mbps || 295 (mbps >= freqranges[i].min && mbps <= freqranges[i].max)) 296 return i; 297 } 298 299 return DPHY_FREQ_RANGE_INVALID_INDEX; 300 } 301 302 static int ipu6_isys_dwc_phy_config(struct ipu6_isys *isys, 303 u32 phy_id, u32 mbps) 304 { 305 struct ipu6_bus_device *adev = isys->adev; 306 struct device *dev = &adev->auxdev.dev; 307 struct ipu6_device *isp = adev->isp; 308 u32 cfg_clk_freqrange; 309 u32 osc_freq_target; 310 u32 index; 311 312 dev_dbg(dev, "config Dphy %u with %u mbps", phy_id, mbps); 313 314 index = get_hsfreq_by_mbps(mbps); 315 if (index == DPHY_FREQ_RANGE_INVALID_INDEX) { 316 dev_err(dev, "link freq not found for mbps %u", mbps); 317 return -EINVAL; 318 } 319 320 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_HSFREQRANGE, 321 freqranges[index].hsfreq, 0, 7); 322 323 /* Force termination Calibration */ 324 if (isys->phy_termcal_val) { 325 dwc_dphy_ifc_write_mask(isys, phy_id, 0x20a, 0x1, 0, 1); 326 dwc_dphy_ifc_write_mask(isys, phy_id, 0x209, 0x3, 0, 2); 327 dwc_dphy_ifc_write_mask(isys, phy_id, 0x209, 328 isys->phy_termcal_val, 4, 4); 329 } 330 331 /* 332 * Enable override to configure the DDL target oscillation 333 * frequency on bit 0 of register 0xe4 334 */ 335 dwc_dphy_ifc_write_mask(isys, phy_id, 0xe4, 0x1, 0, 1); 336 /* 337 * configure registers 0xe2, 0xe3 with the 338 * appropriate DDL target oscillation frequency 339 * 0x1cc(460) 340 */ 341 osc_freq_target = freqranges[index].osc_freq_target; 342 dwc_dphy_ifc_write_mask(isys, phy_id, 0xe2, 343 osc_freq_target & 0xff, 0, 8); 344 dwc_dphy_ifc_write_mask(isys, phy_id, 0xe3, 345 (osc_freq_target >> 8) & 0xf, 0, 4); 346 347 if (mbps < 1500) { 348 /* deskew_polarity_rw, for < 1.5Gbps */ 349 dwc_dphy_ifc_write_mask(isys, phy_id, 0x8, 0x1, 5, 1); 350 } 351 352 /* 353 * Set cfgclkfreqrange[5:0] = round[(Fcfg_clk(MHz)-17)*4] 354 * (38.4 - 17) * 4 = ~85 (0x55) 355 */ 356 cfg_clk_freqrange = (isp->buttress.ref_clk - 170) * 4 / 10; 357 dev_dbg(dev, "ref_clk = %u clk_freqrange = %u", 358 isp->buttress.ref_clk, cfg_clk_freqrange); 359 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_CFGCLKFREQRANGE, 360 cfg_clk_freqrange, 0, 8); 361 362 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0x1, 4, 1); 363 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0x1, 8, 1); 364 365 return 0; 366 } 367 368 static void ipu6_isys_dwc_phy_aggr_setup(struct ipu6_isys *isys, u32 master, 369 u32 slave, u32 mbps) 370 { 371 /* Config mastermacro */ 372 dwc_dphy_ifc_write_mask(isys, master, 0x133, 0x1, 0, 1); 373 dwc_dphy_ifc_write_mask(isys, slave, 0x133, 0x0, 0, 1); 374 375 /* Config master PHY clk lane to drive long channel clk */ 376 dwc_dphy_ifc_write_mask(isys, master, 0x307, 0x1, 2, 1); 377 dwc_dphy_ifc_write_mask(isys, slave, 0x307, 0x0, 2, 1); 378 379 /* Config both PHYs data lanes to get clk from long channel */ 380 dwc_dphy_ifc_write_mask(isys, master, 0x508, 0x1, 5, 1); 381 dwc_dphy_ifc_write_mask(isys, slave, 0x508, 0x1, 5, 1); 382 dwc_dphy_ifc_write_mask(isys, master, 0x708, 0x1, 5, 1); 383 dwc_dphy_ifc_write_mask(isys, slave, 0x708, 0x1, 5, 1); 384 385 /* Config slave PHY clk lane to bypass long channel clk to DDR clk */ 386 dwc_dphy_ifc_write_mask(isys, master, 0x308, 0x0, 3, 1); 387 dwc_dphy_ifc_write_mask(isys, slave, 0x308, 0x1, 3, 1); 388 389 /* Override slave PHY clk lane enable (DPHYRXCLK_CLL_demux module) */ 390 dwc_dphy_ifc_write_mask(isys, slave, 0xe0, 0x3, 0, 2); 391 392 /* Override slave PHY DDR clk lane enable (DPHYHSRX_div124 module) */ 393 dwc_dphy_ifc_write_mask(isys, slave, 0xe1, 0x1, 1, 1); 394 dwc_dphy_ifc_write_mask(isys, slave, 0x307, 0x1, 3, 1); 395 396 /* Turn off slave PHY LP-RX clk lane */ 397 dwc_dphy_ifc_write_mask(isys, slave, 0x304, 0x1, 7, 1); 398 dwc_dphy_ifc_write_mask(isys, slave, 0x305, 0xa, 0, 5); 399 } 400 401 #define PHY_E 4 402 static int ipu6_isys_dwc_phy_powerup_ack(struct ipu6_isys *isys, u32 phy_id) 403 { 404 struct device *dev = &isys->adev->auxdev.dev; 405 u32 rescal_done; 406 int ret; 407 408 ret = dwc_dphy_pwr_up(isys, phy_id); 409 if (ret != 0) { 410 dev_err(dev, "Dphy %u power up failed(%d)", phy_id, ret); 411 return ret; 412 } 413 414 /* reset forcerxmode */ 415 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0, 4, 1); 416 dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0, 8, 1); 417 418 dev_dbg(dev, "Dphy %u is ready!", phy_id); 419 420 if (phy_id != PHY_E || isys->phy_termcal_val) 421 return 0; 422 423 usleep_range(100, 200); 424 rescal_done = dwc_dphy_ifc_read_mask(isys, phy_id, 0x221, 7, 1); 425 if (rescal_done) { 426 isys->phy_termcal_val = dwc_dphy_ifc_read_mask(isys, phy_id, 427 0x220, 2, 4); 428 dev_dbg(dev, "termcal done with value = %u", 429 isys->phy_termcal_val); 430 } 431 432 return 0; 433 } 434 435 static void ipu6_isys_dwc_phy_reset(struct ipu6_isys *isys, u32 phy_id) 436 { 437 dev_dbg(&isys->adev->auxdev.dev, "Reset phy %u", phy_id); 438 439 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_SHUTDOWNZ, 0); 440 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_RSTZ, 0); 441 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_ACCESS_MODE, 442 TEST_IFC_ACCESS_MODE_FSM); 443 dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, 444 TEST_IFC_REQ_RESET); 445 } 446 447 int ipu6_isys_dwc_phy_set_power(struct ipu6_isys *isys, 448 struct ipu6_isys_csi2_config *cfg, 449 const struct ipu6_isys_csi2_timing *timing, 450 bool on) 451 { 452 struct device *dev = &isys->adev->auxdev.dev; 453 void __iomem *isys_base = isys->pdata->base; 454 u32 phy_id, primary, secondary; 455 u32 nlanes, port, mbps; 456 s64 link_freq; 457 int ret; 458 459 port = cfg->port; 460 461 if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) { 462 dev_warn(dev, "invalid port ID %d\n", port); 463 return -EINVAL; 464 } 465 466 nlanes = cfg->nlanes; 467 /* only port 0, 2 and 4 support 4 lanes */ 468 if (nlanes == 4 && port % 2) { 469 dev_err(dev, "invalid csi-port %u with %u lanes\n", port, 470 nlanes); 471 return -EINVAL; 472 } 473 474 link_freq = ipu6_isys_csi2_get_link_freq(&isys->csi2[port]); 475 if (link_freq < 0) { 476 dev_err(dev, "get link freq failed(%lld).\n", link_freq); 477 return link_freq; 478 } 479 480 mbps = div_u64(link_freq, 500000); 481 482 phy_id = port; 483 primary = port & ~1; 484 secondary = primary + 1; 485 if (on) { 486 if (nlanes == 4) { 487 dev_dbg(dev, "config phy %u and %u in aggr mode\n", 488 primary, secondary); 489 490 ipu6_isys_dwc_phy_reset(isys, primary); 491 ipu6_isys_dwc_phy_reset(isys, secondary); 492 ipu6_isys_dwc_phy_aggr_setup(isys, primary, 493 secondary, mbps); 494 495 ret = ipu6_isys_dwc_phy_config(isys, primary, mbps); 496 if (ret) 497 return ret; 498 ret = ipu6_isys_dwc_phy_config(isys, secondary, mbps); 499 if (ret) 500 return ret; 501 502 ret = ipu6_isys_dwc_phy_powerup_ack(isys, primary); 503 if (ret) 504 return ret; 505 506 ret = ipu6_isys_dwc_phy_powerup_ack(isys, secondary); 507 return ret; 508 } 509 510 dev_dbg(dev, "config phy %u with %u lanes in non-aggr mode\n", 511 phy_id, nlanes); 512 513 ipu6_isys_dwc_phy_reset(isys, phy_id); 514 ret = ipu6_isys_dwc_phy_config(isys, phy_id, mbps); 515 if (ret) 516 return ret; 517 518 ret = ipu6_isys_dwc_phy_powerup_ack(isys, phy_id); 519 return ret; 520 } 521 522 if (nlanes == 4) { 523 dev_dbg(dev, "Power down phy %u and phy %u for port %u\n", 524 primary, secondary, port); 525 ipu6_isys_dwc_phy_reset(isys, secondary); 526 ipu6_isys_dwc_phy_reset(isys, primary); 527 528 return 0; 529 } 530 531 dev_dbg(dev, "Powerdown phy %u with %u lanes\n", phy_id, nlanes); 532 533 ipu6_isys_dwc_phy_reset(isys, phy_id); 534 535 return 0; 536 } 537