FILE
ipu7-isys-csi-phy.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/ipu7/ipu7-isys-csi-phy.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2013 - 2025 Intel Corporation 4 */ 5 6#include <linux/bitmap.h> 7#include <linux/bug.h> 8#include <linux/delay.h> 9#include <linux/device.h> 10#include <linux/iopoll.h> 11#include <linux/kernel.h> 12#include <linux/types.h> 13 14#include <media/mipi-csi2.h> 15#include <media/v4l2-device.h> 16 17#include "ipu7.h" 18#include "ipu7-bus.h" 19#include "ipu7-buttress.h" 20#include "ipu7-isys.h" 21#include "ipu7-isys-csi2.h" 22#include "ipu7-isys-csi2-regs.h" 23#include "ipu7-platform-regs.h" 24#include "ipu7-isys-csi-phy.h" 25 26#define PORT_A 0U 27#define PORT_B 1U 28#define PORT_C 2U 29#define PORT_D 3U 30 31#define N_DATA_IDS 8U 32static DECLARE_BITMAP(data_ids, N_DATA_IDS); 33 34struct ddlcal_counter_ref_s { 35 u16 min_mbps; 36 u16 max_mbps; 37 38 u16 ddlcal_counter_ref; 39}; 40 41struct ddlcal_params { 42 u16 min_mbps; 43 u16 max_mbps; 44 u16 oa_lanex_hsrx_cdphy_sel_fast; 45 u16 ddlcal_max_phase; 46 u16 phase_bound; 47 u16 ddlcal_dll_fbk; 48 u16 ddlcal_ddl_coarse_bank; 49 u16 fjump_deskew; 50 u16 min_eye_opening_deskew; 51}; 52 53struct i_thssettle_params { 54 u16 min_mbps; 55 u16 max_mbps; 56 u16 i_thssettle; 57}; 58 59 /* lane2 for 4l3t, lane1 for 2l2t */ 60struct oa_lane_clk_div_params { 61 u16 min_mbps; 62 u16 max_mbps; 63 u16 oa_lane_hsrx_hs_clk_div; 64}; 65 66struct cdr_fbk_cap_prog_params { 67 u16 min_mbps; 68 u16 max_mbps; 69 u16 val; 70}; 71 72static const struct ddlcal_counter_ref_s table0[] = { 73 { 1500, 1999, 118 }, 74 { 2000, 2499, 157 }, 75 { 2500, 3499, 196 }, 76 { 3500, 4499, 274 }, 77 { 4500, 4500, 352 }, 78 { } 79}; 80 81static const struct ddlcal_params table1[] = { 82 { 1500, 1587, 0, 143, 167, 17, 3, 4, 29 }, 83 { 1588, 1687, 0, 135, 167, 15, 3, 4, 27 }, 84 { 1688, 1799, 0, 127, 135, 15, 2, 4, 26 }, 85 { 1800, 1928, 0, 119, 135, 13, 2, 3, 24 }, 86 { 1929, 2076, 0, 111, 135, 13, 2, 3, 23 }, 87 { 2077, 2249, 0, 103, 135, 11, 2, 3, 21 }, 88 { 2250, 2454, 0, 95, 103, 11, 1, 3, 19 }, 89 { 2455, 2699, 0, 87, 103, 9, 1, 3, 18 }, 90 { 2700, 2999, 0, 79, 103, 9, 1, 2, 16 }, 91 { 3000, 3229, 0, 71, 71, 7, 1, 2, 15 }, 92 { 3230, 3599, 1, 87, 103, 9, 1, 3, 18 }, 93 { 3600, 3999, 1, 79, 103, 9, 1, 2, 16 }, 94 { 4000, 4499, 1, 71, 103, 7, 1, 2, 15 }, 95 { 4500, 4500, 1, 63, 71, 7, 0, 2, 13 }, 96 { } 97}; 98 99static const struct i_thssettle_params table2[] = { 100 { 80, 124, 24 }, 101 { 125, 249, 20 }, 102 { 250, 499, 16 }, 103 { 500, 749, 14 }, 104 { 750, 1499, 13 }, 105 { 1500, 4500, 12 }, 106 { } 107}; 108 109static const struct oa_lane_clk_div_params table6[] = { 110 { 80, 159, 0x1 }, 111 { 160, 319, 0x2 }, 112 { 320, 639, 0x3 }, 113 { 640, 1279, 0x4 }, 114 { 1280, 2560, 0x5 }, 115 { 2561, 4500, 0x6 }, 116 { } 117}; 118 119static const struct cdr_fbk_cap_prog_params table7[] = { 120 { 80, 919, 0 }, 121 { 920, 1029, 1 }, 122 { 1030, 1169, 2 }, 123 { 1170, 1349, 3 }, 124 { 1350, 1589, 4 }, 125 { 1590, 1949, 5 }, 126 { 1950, 2499, 6 }, 127 { 2500, 3500, 7 }, 128 { } 129}; 130 131static void dwc_phy_write(struct ipu7_isys *isys, u32 id, u32 addr, u16 data) 132{ 133 void __iomem *isys_base = isys->pdata->base; 134 void __iomem *base = isys_base + IS_IO_CDPHY_BASE(id); 135 136 dev_dbg(&isys->adev->auxdev.dev, "phy write: reg 0x%zx = data 0x%04x", 137 base + addr - isys_base, data); 138 writew(data, base + addr); 139} 140 141static u16 dwc_phy_read(struct ipu7_isys *isys, u32 id, u32 addr) 142{ 143 void __iomem *isys_base = isys->pdata->base; 144 void __iomem *base = isys_base + IS_IO_CDPHY_BASE(id); 145 u16 data; 146 147 data = readw(base + addr); 148 dev_dbg(&isys->adev->auxdev.dev, "phy read: reg 0x%zx = data 0x%04x", 149 base + addr - isys_base, data); 150 151 return data; 152} 153 154static void dwc_csi_write(struct ipu7_isys *isys, u32 id, u32 addr, u32 data) 155{ 156 void __iomem *isys_base = isys->pdata->base; 157 void __iomem *base = isys_base + IS_IO_CSI2_HOST_BASE(id); 158 struct device *dev = &isys->adev->auxdev.dev; 159 160 dev_dbg(dev, "csi write: reg 0x%zx = data 0x%08x", 161 base + addr - isys_base, data); 162 writel(data, base + addr); 163 dev_dbg(dev, "csi read: reg 0x%zx = data 0x%08x", 164 base + addr - isys_base, readl(base + addr)); 165} 166 167static void gpreg_write(struct ipu7_isys *isys, u32 id, u32 addr, u32 data) 168{ 169 void __iomem *isys_base = isys->pdata->base; 170 u32 gpreg = isys->pdata->ipdata->csi2.gpreg; 171 void __iomem *base = isys_base + gpreg + 0x1000 * id; 172 struct device *dev = &isys->adev->auxdev.dev; 173 174 dev_dbg(dev, "gpreg write: reg 0x%zx = data 0x%08x", 175 base + addr - isys_base, data); 176 writel(data, base + addr); 177 dev_dbg(dev, "gpreg read: reg 0x%zx = data 0x%08x", 178 base + addr - isys_base, readl(base + addr)); 179} 180 181static u32 dwc_csi_read(struct ipu7_isys *isys, u32 id, u32 addr) 182{ 183 void __iomem *isys_base = isys->pdata->base; 184 void __iomem *base = isys_base + IS_IO_CSI2_HOST_BASE(id); 185 u32 data; 186 187 data = readl(base + addr); 188 dev_dbg(&isys->adev->auxdev.dev, "csi read: reg 0x%zx = data 0x%x", 189 base + addr - isys_base, data); 190 191 return data; 192} 193 194static void dwc_phy_write_mask(struct ipu7_isys *isys, u32 id, u32 addr, 195 u16 val, u8 lo, u8 hi) 196{ 197 u32 temp, mask; 198 199 WARN_ON(lo > hi); 200 WARN_ON(hi > 15); 201 202 mask = ((~0U - (1U << lo) + 1U)) & (~0U >> (31 - hi)); 203 temp = dwc_phy_read(isys, id, addr); 204 temp &= ~mask; 205 temp |= (val << lo) & mask; 206 dwc_phy_write(isys, id, addr, temp); 207} 208 209static void dwc_csi_write_mask(struct ipu7_isys *isys, u32 id, u32 addr, 210 u32 val, u8 hi, u8 lo) 211{ 212 u32 temp, mask; 213 214 WARN_ON(lo > hi); 215 216 mask = ((~0U - (1U << lo) + 1U)) & (~0U >> (31 - hi)); 217 temp = dwc_csi_read(isys, id, addr); 218 temp &= ~mask; 219 temp |= (val << lo) & mask; 220 dwc_csi_write(isys, id, addr, temp); 221} 222 223static void ipu7_isys_csi_ctrl_cfg(struct ipu7_isys_csi2 *csi2) 224{ 225 struct ipu7_isys *isys = csi2->isys; 226 struct device *dev = &isys->adev->auxdev.dev; 227 u32 id, lanes, phy_mode; 228 u32 val; 229 230 id = csi2->port; 231 lanes = csi2->nlanes; 232 phy_mode = csi2->phy_mode; 233 dev_dbg(dev, "csi-%d controller init with %u lanes, phy mode %u", 234 id, lanes, phy_mode); 235 236 val = dwc_csi_read(isys, id, VERSION); 237 dev_dbg(dev, "csi-%d controller version = 0x%x", id, val); 238 239 /* num of active data lanes */ 240 dwc_csi_write(isys, id, N_LANES, lanes - 1); 241 dwc_csi_write(isys, id, CDPHY_MODE, phy_mode); 242 dwc_csi_write(isys, id, VC_EXTENSION, 0); 243 244 /* only mask PHY_FATAL and PKT_FATAL interrupts */ 245 dwc_csi_write(isys, id, INT_MSK_PHY_FATAL, 0xff); 246 dwc_csi_write(isys, id, INT_MSK_PKT_FATAL, 0x3); 247 dwc_csi_write(isys, id, INT_MSK_PHY, 0x0); 248 dwc_csi_write(isys, id, INT_MSK_LINE, 0x0); 249 dwc_csi_write(isys, id, INT_MSK_BNDRY_FRAME_FATAL, 0x0); 250 dwc_csi_write(isys, id, INT_MSK_SEQ_FRAME_FATAL, 0x0); 251 dwc_csi_write(isys, id, INT_MSK_CRC_FRAME_FATAL, 0x0); 252 dwc_csi_write(isys, id, INT_MSK_PLD_CRC_FATAL, 0x0); 253 dwc_csi_write(isys, id, INT_MSK_DATA_ID, 0x0); 254 dwc_csi_write(isys, id, INT_MSK_ECC_CORRECTED, 0x0); 255} 256 257static void ipu7_isys_csi_phy_reset(struct ipu7_isys *isys, u32 id) 258{ 259 dwc_csi_write(isys, id, PHY_SHUTDOWNZ, 0); 260 dwc_csi_write(isys, id, DPHY_RSTZ, 0); 261 dwc_csi_write(isys, id, CSI2_RESETN, 0); 262 gpreg_write(isys, id, PHY_RESET, 0); 263 gpreg_write(isys, id, PHY_SHUTDOWN, 0); 264} 265 266/* 8 Data ID monitors, each Data ID is composed by pair of VC and data type */ 267static int __dids_config(struct ipu7_isys_csi2 *csi2, u32 id, u8 vc, u8 dt) 268{ 269 struct ipu7_isys *isys = csi2->isys; 270 u32 reg, n; 271 u8 lo, hi; 272 int ret; 273 274 dev_dbg(&isys->adev->auxdev.dev, "config CSI-%u with vc:%u dt:0x%02x\n", 275 id, vc, dt); 276 277 dwc_csi_write(isys, id, VC_EXTENSION, 0x0); 278 n = find_first_zero_bit(data_ids, N_DATA_IDS); 279 if (n == N_DATA_IDS) 280 return -ENOSPC; 281 282 ret = test_and_set_bit(n, data_ids); 283 if (ret) 284 return -EBUSY; 285 286 reg = n < 4 ? DATA_IDS_VC_1 : DATA_IDS_VC_2; 287 lo = (n % 4) * 8; 288 hi = lo + 4; 289 dwc_csi_write_mask(isys, id, reg, vc & GENMASK(4, 0), hi, lo); 290 291 reg = n < 4 ? DATA_IDS_1 : DATA_IDS_2; 292 lo = (n % 4) * 8; 293 hi = lo + 5; 294 dwc_csi_write_mask(isys, id, reg, dt & GENMASK(5, 0), hi, lo); 295 296 return 0; 297} 298 299static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id) 300{ 301 struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; 302 struct device *dev = &csi2->isys->adev->auxdev.dev; 303 struct v4l2_mbus_frame_desc desc; 304 struct v4l2_subdev *ext_sd; 305 struct media_pad *pad; 306 unsigned int i; 307 int ret; 308 309 pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); 310 if (IS_ERR(pad)) { 311 dev_warn(dev, "can't get remote source pad of %s (%pe)\n", 312 csi2->asd.sd.name, pad); 313 return PTR_ERR(pad); 314 } 315 316 ext_sd = media_entity_to_v4l2_subdev(pad->entity); 317 if (WARN(!ext_sd, "Failed to get subdev for entity %s\n", 318 pad->entity->name)) 319 return -ENODEV; 320 321 ret = v4l2_subdev_call(ext_sd, pad, get_frame_desc, pad->index, &desc); 322 if (ret) 323 return ret; 324 325 if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { 326 dev_warn(dev, "Unsupported frame descriptor type\n"); 327 return -EINVAL; 328 } 329 330 for (i = 0; i < desc.num_entries; i++) { 331 desc_entry = &desc.entry[i]; 332 if (desc_entry->bus.csi2.vc < IPU7_NR_OF_CSI2_VC) { 333 ret = __dids_config(csi2, id, desc_entry->bus.csi2.vc, 334 desc_entry->bus.csi2.dt); 335 if (ret) 336 return ret; 337 } 338 } 339 340 return 0; 341} 342 343#define CDPHY_TIMEOUT 5000000U 344static int ipu7_isys_phy_ready(struct ipu7_isys *isys, u32 id) 345{ 346 void __iomem *isys_base = isys->pdata->base; 347 u32 gpreg_offset = isys->pdata->ipdata->csi2.gpreg; 348 void __iomem *gpreg = isys_base + gpreg_offset + 0x1000 * id; 349 struct device *dev = &isys->adev->auxdev.dev; 350 unsigned int i; 351 u32 phy_ready; 352 u32 reg, rext; 353 int ret; 354 355 dev_dbg(dev, "waiting phy ready...\n"); 356 ret = readl_poll_timeout(gpreg + PHY_READY, phy_ready, 357 phy_ready & BIT(0) && phy_ready != ~0U, 358 100, CDPHY_TIMEOUT); 359 dev_dbg(dev, "phy %u ready = 0x%08x\n", id, readl(gpreg + PHY_READY)); 360 dev_dbg(dev, "csi %u PHY_RX = 0x%08x\n", id, 361 dwc_csi_read(isys, id, PHY_RX)); 362 dev_dbg(dev, "csi %u PHY_STOPSTATE = 0x%08x\n", id, 363 dwc_csi_read(isys, id, PHY_STOPSTATE)); 364 dev_dbg(dev, "csi %u PHY_CAL = 0x%08x\n", id, 365 dwc_csi_read(isys, id, PHY_CAL)); 366 for (i = 0; i < 4U; i++) { 367 reg = CORE_DIG_DLANE_0_R_HS_RX_0 + (i * 0x400U); 368 dev_dbg(dev, "phy %u DLANE%u skewcal = 0x%04x\n", 369 id, i, dwc_phy_read(isys, id, reg)); 370 } 371 dev_dbg(dev, "phy %u DDLCAL = 0x%04x\n", id, 372 dwc_phy_read(isys, id, PPI_CALIBCTRL_R_COMMON_CALIBCTRL_2_5)); 373 dev_dbg(dev, "phy %u TERMCAL = 0x%04x\n", id, 374 dwc_phy_read(isys, id, PPI_R_TERMCAL_DEBUG_0)); 375 dev_dbg(dev, "phy %u LPDCOCAL = 0x%04x\n", id, 376 dwc_phy_read(isys, id, PPI_R_LPDCOCAL_DEBUG_RB)); 377 dev_dbg(dev, "phy %u HSDCOCAL = 0x%04x\n", id, 378 dwc_phy_read(isys, id, PPI_R_HSDCOCAL_DEBUG_RB)); 379 dev_dbg(dev, "phy %u LPDCOCAL_VT = 0x%04x\n", id, 380 dwc_phy_read(isys, id, PPI_R_LPDCOCAL_DEBUG_VT)); 381 382 if (!ret) { 383 if (id) { 384 dev_dbg(dev, "ignore phy %u rext\n", id); 385 return 0; 386 } 387 388 rext = dwc_phy_read(isys, id, 389 CORE_DIG_IOCTRL_R_AFE_CB_CTRL_2_15) & 0xfU; 390 dev_dbg(dev, "phy %u rext value = %u\n", id, rext); 391 isys->phy_rext_cal = (rext ? rext : 5); 392 393 return 0; 394 } 395 396 dev_err(dev, "wait phy ready timeout!\n"); 397 398 return ret; 399} 400 401static int lookup_table1(u64 mbps) 402{ 403 unsigned int i; 404 405 for (i = 0; i < ARRAY_SIZE(table1); i++) { 406 if (mbps >= table1[i].min_mbps && mbps <= table1[i].max_mbps) 407 return i; 408 } 409 410 return -ENXIO; 411} 412 413static const u16 deskew_fine_mem[] = { 414 0x0404, 0x040c, 0x0414, 0x041c, 415 0x0423, 0x0429, 0x0430, 0x043a, 416 0x0445, 0x044a, 0x0450, 0x045a, 417 0x0465, 0x0469, 0x0472, 0x047a, 418 0x0485, 0x0489, 0x0490, 0x049a, 419 0x04a4, 0x04ac, 0x04b4, 0x04bc, 420 0x04c4, 0x04cc, 0x04d4, 0x04dc, 421 0x04e4, 0x04ec, 0x04f4, 0x04fc, 422 0x0504, 0x050c, 0x0514, 0x051c, 423 0x0523, 0x0529, 0x0530, 0x053a, 424 0x0545, 0x054a, 0x0550, 0x055a, 425 0x0565, 0x0569, 0x0572, 0x057a, 426 0x0585, 0x0589, 0x0590, 0x059a, 427 0x05a4, 0x05ac, 0x05b4, 0x05bc, 428 0x05c4, 0x05cc, 0x05d4, 0x05dc, 429 0x05e4, 0x05ec, 0x05f4, 0x05fc, 430 0x0604, 0x060c, 0x0614, 0x061c, 431 0x0623, 0x0629, 0x0632, 0x063a, 432 0x0645, 0x064a, 0x0650, 0x065a, 433 0x0665, 0x0669, 0x0672, 0x067a, 434 0x0685, 0x0689, 0x0690, 0x069a, 435 0x06a4, 0x06ac, 0x06b4, 0x06bc, 436 0x06c4, 0x06cc, 0x06d4, 0x06dc, 437 0x06e4, 0x06ec, 0x06f4, 0x06fc, 438 0x0704, 0x070c, 0x0714, 0x071c, 439 0x0723, 0x072a, 0x0730, 0x073a, 440 0x0745, 0x074a, 0x0750, 0x075a, 441 0x0765, 0x0769, 0x0772, 0x077a, 442 0x0785, 0x0789, 0x0790, 0x079a, 443 0x07a4, 0x07ac, 0x07b4, 0x07bc, 444 0x07c4, 0x07cc, 0x07d4, 0x07dc, 445 0x07e4, 0x07ec, 0x07f4, 0x07fc, 446}; 447 448static void ipu7_isys_dphy_config(struct ipu7_isys *isys, u8 id, u8 lanes, 449 bool aggregation, u64 mbps) 450{ 451 u16 hsrxval0 = 0; 452 u16 hsrxval1 = 0; 453 u16 hsrxval2 = 0; 454 int index; 455 u16 reg; 456 u16 val; 457 u32 i; 458 459 dwc_phy_write_mask(isys, id, CORE_DIG_RW_COMMON_7, 0, 0, 9); 460 if (mbps > 1500) 461 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_7, 462 40, 0, 7); 463 else 464 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_7, 465 104, 0, 7); 466 467 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_8, 80, 0, 7); 468 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_0, 191, 0, 9); 469 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_7, 34, 7, 12); 470 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_1, 38, 8, 15); 471 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_2, 4, 12, 15); 472 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_2, 2, 10, 11); 473 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_2, 1, 8, 8); 474 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_2, 38, 0, 7); 475 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_2, 1, 9, 9); 476 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_4, 10, 0, 9); 477 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_6, 20, 0, 9); 478 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_7, 19, 0, 6); 479 480 for (i = 0; i < ARRAY_SIZE(table0); i++) { 481 if (mbps >= table0[i].min_mbps && mbps <= table0[i].max_mbps) { 482 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_3, 483 table0[i].ddlcal_counter_ref, 484 0, 9); 485 break; 486 } 487 } 488 489 index = lookup_table1(mbps); 490 if (index >= 0) { 491 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_1, 492 table1[index].phase_bound, 0, 7); 493 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_5, 494 table1[index].ddlcal_dll_fbk, 4, 9); 495 dwc_phy_write_mask(isys, id, PPI_RW_DDLCAL_CFG_5, 496 table1[index].ddlcal_ddl_coarse_bank, 0, 3); 497 498 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_8; 499 val = table1[index].oa_lanex_hsrx_cdphy_sel_fast; 500 for (i = 0; i < lanes + 1; i++) 501 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 502 12, 12); 503 } 504 505 reg = CORE_DIG_DLANE_0_RW_LP_0; 506 for (i = 0; i < lanes; i++) 507 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 6, 8, 11); 508 509 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_2, 510 0, 0, 0); 511 if (!is_ipu7(isys->adev->isp->hw_ver) || 512 id == PORT_B || id == PORT_C) { 513 dwc_phy_write_mask(isys, id, 514 CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_2, 515 1, 0, 0); 516 dwc_phy_write_mask(isys, id, 517 CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_2, 518 0, 0, 0); 519 } else { 520 dwc_phy_write_mask(isys, id, 521 CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_2, 522 0, 0, 0); 523 dwc_phy_write_mask(isys, id, 524 CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_2, 525 1, 0, 0); 526 } 527 528 if (lanes == 4 && is_ipu7(isys->adev->isp->hw_ver)) { 529 dwc_phy_write_mask(isys, id, 530 CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_2, 531 0, 0, 0); 532 dwc_phy_write_mask(isys, id, 533 CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_2, 534 0, 0, 0); 535 } 536 537 dwc_phy_write_mask(isys, id, CORE_DIG_RW_COMMON_6, 1, 0, 2); 538 dwc_phy_write_mask(isys, id, CORE_DIG_RW_COMMON_6, 1, 3, 5); 539 540 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_12; 541 val = (mbps > 1500) ? 0 : 1; 542 for (i = 0; i < lanes + 1; i++) { 543 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 1, 1); 544 dwc_phy_write_mask(isys, id, reg + (i * 0x400), !val, 3, 3); 545 } 546 547 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_13; 548 val = (mbps > 1500) ? 0 : 1; 549 for (i = 0; i < lanes + 1; i++) { 550 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 1, 1); 551 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 3, 3); 552 } 553 554 if (!is_ipu7(isys->adev->isp->hw_ver) || id == PORT_B || id == PORT_C) 555 reg = CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_9; 556 else 557 reg = CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_9; 558 559 for (i = 0; i < ARRAY_SIZE(table6); i++) { 560 if (mbps >= table6[i].min_mbps && mbps <= table6[i].max_mbps) { 561 dwc_phy_write_mask(isys, id, reg, 562 table6[i].oa_lane_hsrx_hs_clk_div, 563 5, 7); 564 break; 565 } 566 } 567 568 if (aggregation) { 569 dwc_phy_write_mask(isys, id, CORE_DIG_RW_COMMON_0, 1, 570 1, 1); 571 572 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_15; 573 dwc_phy_write_mask(isys, id, reg, 3, 3, 4); 574 575 val = (id == PORT_A) ? 3 : 0; 576 reg = CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_15; 577 dwc_phy_write_mask(isys, id, reg, val, 3, 4); 578 579 reg = CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_15; 580 dwc_phy_write_mask(isys, id, reg, 3, 3, 4); 581 } 582 583 dwc_phy_write_mask(isys, id, CORE_DIG_DLANE_CLK_RW_HS_RX_0, 28, 0, 7); 584 dwc_phy_write_mask(isys, id, CORE_DIG_DLANE_CLK_RW_HS_RX_7, 6, 0, 7); 585 586 reg = CORE_DIG_DLANE_0_RW_HS_RX_0; 587 for (i = 0; i < ARRAY_SIZE(table2); i++) { 588 if (mbps >= table2[i].min_mbps && mbps <= table2[i].max_mbps) { 589 u8 j; 590 591 for (j = 0; j < lanes; j++) 592 dwc_phy_write_mask(isys, id, reg + (j * 0x400), 593 table2[i].i_thssettle, 594 8, 15); 595 break; 596 } 597 } 598 599 /* deskew */ 600 for (i = 0; i < lanes; i++) { 601 reg = CORE_DIG_DLANE_0_RW_CFG_1; 602 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 603 ((mbps > 1500) ? 0x1 : 0x2), 2, 3); 604 605 reg = CORE_DIG_DLANE_0_RW_HS_RX_2; 606 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 607 ((mbps > 2500) ? 0 : 1), 15, 15); 608 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 1, 13, 13); 609 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 7, 9, 12); 610 611 reg = CORE_DIG_DLANE_0_RW_LP_0; 612 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 1, 12, 15); 613 614 reg = CORE_DIG_DLANE_0_RW_LP_2; 615 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 0, 0, 0); 616 617 reg = CORE_DIG_DLANE_0_RW_HS_RX_1; 618 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 16, 0, 7); 619 620 reg = CORE_DIG_DLANE_0_RW_HS_RX_3; 621 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 2, 0, 2); 622 index = lookup_table1(mbps); 623 if (index >= 0) { 624 val = table1[index].fjump_deskew; 625 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 626 3, 8); 627 } 628 629 reg = CORE_DIG_DLANE_0_RW_HS_RX_4; 630 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 150, 0, 15); 631 632 reg = CORE_DIG_DLANE_0_RW_HS_RX_5; 633 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 0, 0, 7); 634 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 1, 8, 15); 635 636 reg = CORE_DIG_DLANE_0_RW_HS_RX_6; 637 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 2, 0, 7); 638 index = lookup_table1(mbps); 639 if (index >= 0) { 640 val = table1[index].min_eye_opening_deskew; 641 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 642 8, 15); 643 } 644 reg = CORE_DIG_DLANE_0_RW_HS_RX_7; 645 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 0, 13, 13); 646 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 0, 15, 15); 647 648 reg = CORE_DIG_DLANE_0_RW_HS_RX_9; 649 index = lookup_table1(mbps); 650 if (index >= 0) { 651 val = table1[index].ddlcal_max_phase; 652 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 653 val, 0, 7); 654 } 655 } 656 657 dwc_phy_write_mask(isys, id, CORE_DIG_DLANE_CLK_RW_LP_0, 1, 12, 15); 658 dwc_phy_write_mask(isys, id, CORE_DIG_DLANE_CLK_RW_LP_2, 0, 0, 0); 659 660 for (i = 0; i < ARRAY_SIZE(deskew_fine_mem); i++) 661 dwc_phy_write_mask(isys, id, CORE_DIG_COMMON_RW_DESKEW_FINE_MEM, 662 deskew_fine_mem[i], 0, 15); 663 664 if (mbps > 1500) { 665 hsrxval0 = 4; 666 hsrxval2 = 3; 667 } 668 669 if (mbps > 2500) 670 hsrxval1 = 2; 671 672 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_9, 673 hsrxval0, 0, 2); 674 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_9, 675 hsrxval0, 0, 2); 676 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_9, 677 hsrxval0, 0, 2); 678 if (lanes == 4 && is_ipu7(isys->adev->isp->hw_ver)) { 679 dwc_phy_write_mask(isys, id, 680 CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_9, 681 hsrxval0, 0, 2); 682 dwc_phy_write_mask(isys, id, 683 CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_9, 684 hsrxval0, 0, 2); 685 } 686 687 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_9, 688 hsrxval1, 3, 4); 689 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_9, 690 hsrxval1, 3, 4); 691 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_9, 692 hsrxval1, 3, 4); 693 if (lanes == 4 && is_ipu7(isys->adev->isp->hw_ver)) { 694 dwc_phy_write_mask(isys, id, 695 CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_9, 696 hsrxval1, 3, 4); 697 dwc_phy_write_mask(isys, id, 698 CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_9, 699 hsrxval1, 3, 4); 700 } 701 702 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_15, 703 hsrxval2, 0, 2); 704 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_15, 705 hsrxval2, 0, 2); 706 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_15, 707 hsrxval2, 0, 2); 708 if (lanes == 4 && is_ipu7(isys->adev->isp->hw_ver)) { 709 dwc_phy_write_mask(isys, id, 710 CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_15, 711 hsrxval2, 0, 2); 712 dwc_phy_write_mask(isys, id, 713 CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_15, 714 hsrxval2, 0, 2); 715 } 716 717 /* force and override rext */ 718 if (isys->phy_rext_cal && id) { 719 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_8, 720 isys->phy_rext_cal, 0, 3); 721 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_7, 722 1, 11, 11); 723 } 724} 725 726static void ipu7_isys_cphy_config(struct ipu7_isys *isys, u8 id, u8 lanes, 727 bool aggregation, u64 mbps) 728{ 729 u8 trios = 2; 730 u16 coarse_target; 731 u16 deass_thresh; 732 u16 delay_thresh; 733 u16 reset_thresh; 734 u16 cap_prog = 6U; 735 u16 reg; 736 u16 val; 737 u32 i; 738 u64 r64; 739 u32 r; 740 741 if (is_ipu7p5(isys->adev->isp->hw_ver)) 742 val = 0x15; 743 else 744 val = 0x155; 745 746 if (is_ipu7(isys->adev->isp->hw_ver)) 747 trios = 3; 748 749 dwc_phy_write_mask(isys, id, CORE_DIG_RW_COMMON_7, val, 0, 9); 750 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_7, 104, 0, 7); 751 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_8, 16, 0, 7); 752 753 reg = CORE_DIG_CLANE_0_RW_LP_0; 754 for (i = 0; i < trios; i++) 755 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 6, 8, 11); 756 757 val = (mbps > 900U) ? 1U : 0U; 758 for (i = 0; i < trios; i++) { 759 reg = CORE_DIG_CLANE_0_RW_HS_RX_0; 760 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 1, 0, 0); 761 dwc_phy_write_mask(isys, id, reg + (i * 0x400), val, 1, 1); 762 763 reg = CORE_DIG_CLANE_0_RW_HS_RX_1; 764 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 38, 0, 15); 765 766 reg = CORE_DIG_CLANE_0_RW_HS_RX_5; 767 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 38, 0, 15); 768 769 reg = CORE_DIG_CLANE_0_RW_HS_RX_6; 770 dwc_phy_write_mask(isys, id, reg + (i * 0x400), 10, 0, 15); 771 } 772 773 /* 774 * Below 900Msps, always use the same value. 775 * The formula is suitable for data rate 80-3500Msps. 776 * Timebase (us) = 1, DIV = 32, TDDL (UI) = 0.5 777 */ 778 if (mbps >= 80U) 779 coarse_target = DIV_ROUND_UP_ULL(mbps, 16) - 1; 780 else 781 coarse_target = 56; 782 783 for (i = 0; i < trios; i++) { 784 reg = CORE_DIG_CLANE_0_RW_HS_RX_2 + i * 0x400; 785 dwc_phy_write_mask(isys, id, reg, coarse_target, 0, 15); 786 } 787 788 dwc_phy_write_mask(isys, id, 789 CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_2, 1, 0, 0); 790 dwc_phy_write_mask(isys, id, 791 CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_2, 0, 0, 0); 792 dwc_phy_write_mask(isys, id, 793 CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_2, 1, 0, 0); 794 795 if (!is_ipu7p5(isys->adev->isp->hw_ver) && lanes == 4) { 796 dwc_phy_write_mask(isys, id, 797 CORE_DIG_IOCTRL_RW_AFE_LANE3_CTRL_2_2, 798 1, 0, 0); 799 dwc_phy_write_mask(isys, id, 800 CORE_DIG_IOCTRL_RW_AFE_LANE4_CTRL_2_2, 801 0, 0, 0); 802 } 803 804 for (i = 0; i < trios; i++) { 805 reg = CORE_DIG_RW_TRIO0_0 + i * 0x400; 806 dwc_phy_write_mask(isys, id, reg, 1, 6, 8); 807 dwc_phy_write_mask(isys, id, reg, 1, 3, 5); 808 dwc_phy_write_mask(isys, id, reg, 2, 0, 2); 809 } 810 811 deass_thresh = (u16)div64_u64_rem(7 * 1000 * 6, mbps * 5U, &r64) + 1; 812 if (r64 != 0) 813 deass_thresh++; 814 815 reg = CORE_DIG_RW_TRIO0_2; 816 for (i = 0; i < trios; i++) 817 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 818 deass_thresh, 0, 7); 819 820 delay_thresh = div64_u64((224U - (9U * 7U)) * 1000U, 5U * mbps) - 7u; 821 822 if (delay_thresh < 1) 823 delay_thresh = 1; 824 825 reg = CORE_DIG_RW_TRIO0_1; 826 for (i = 0; i < trios; i++) 827 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 828 delay_thresh, 0, 15); 829 830 reset_thresh = (u16)div_u64_rem(2U * 5U * mbps, 7U * 1000U, &r); 831 if (!r) 832 reset_thresh--; 833 834 if (reset_thresh < 1) 835 reset_thresh = 1; 836 837 reg = CORE_DIG_RW_TRIO0_0; 838 for (i = 0; i < trios; i++) 839 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 840 reset_thresh, 9, 11); 841 842 /* Tuning ITMINRX to 2 for CPHY */ 843 reg = CORE_DIG_CLANE_0_RW_LP_0; 844 for (i = 0; i < trios; i++) 845 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 2, 12, 15); 846 847 reg = CORE_DIG_CLANE_0_RW_LP_2; 848 for (i = 0; i < trios; i++) 849 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 0, 0, 0); 850 851 reg = CORE_DIG_CLANE_0_RW_HS_RX_0; 852 for (i = 0; i < trios; i++) 853 dwc_phy_write_mask(isys, id, reg + 0x400 * i, 12, 2, 6); 854 855 for (i = 0; i < ARRAY_SIZE(table7); i++) { 856 if (mbps >= table7[i].min_mbps && mbps <= table7[i].max_mbps) { 857 cap_prog = table7[i].val; 858 break; 859 } 860 } 861 862 for (i = 0; i < (lanes + 1); i++) { 863 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_9 + 0x400 * i; 864 dwc_phy_write_mask(isys, id, reg, 4U, 0, 2); 865 /* Set GMODE to 2 when CPHY >= 1.5Gsps */ 866 if (mbps >= 1500) 867 dwc_phy_write_mask(isys, id, reg, 2U, 3, 4); 868 else 869 dwc_phy_write_mask(isys, id, reg, 0U, 3, 4); 870 871 reg = CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_7 + 0x400 * i; 872 dwc_phy_write_mask(isys, id, reg, cap_prog, 10, 12); 873 } 874} 875 876static int ipu7_isys_phy_config(struct ipu7_isys *isys, u8 id, u8 lanes, 877 bool aggregation) 878{ 879 struct device *dev = &isys->adev->auxdev.dev; 880 u32 phy_mode; 881 s64 link_freq; 882 u64 mbps; 883 884 if (aggregation) 885 link_freq = ipu7_isys_csi2_get_link_freq(&isys->csi2[0]); 886 else 887 link_freq = ipu7_isys_csi2_get_link_freq(&isys->csi2[id]); 888 889 if (link_freq < 0) { 890 dev_err(dev, "get link freq failed (%lld)\n", link_freq); 891 return link_freq; 892 } 893 894 mbps = div_u64(link_freq, 500000); 895 dev_dbg(dev, "config phy %u with lanes %u aggregation %d mbps %lld\n", 896 id, lanes, aggregation, mbps); 897 898 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_10, 48, 0, 7); 899 dwc_phy_write_mask(isys, id, CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_2, 900 1, 12, 13); 901 dwc_phy_write_mask(isys, id, CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_0, 902 63, 2, 7); 903 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_STARTUP_1_1, 904 563, 0, 11); 905 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_2, 5, 0, 7); 906 /* bypass the RCAL state (bit6) */ 907 if (aggregation && id != PORT_A) 908 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_2, 0x45, 909 0, 7); 910 911 dwc_phy_write_mask(isys, id, PPI_STARTUP_RW_COMMON_DPHY_6, 39, 0, 7); 912 dwc_phy_write_mask(isys, id, PPI_CALIBCTRL_RW_COMMON_BG_0, 500, 0, 8); 913 dwc_phy_write_mask(isys, id, PPI_RW_TERMCAL_CFG_0, 38, 0, 6); 914 dwc_phy_write_mask(isys, id, PPI_RW_OFFSETCAL_CFG_0, 7, 0, 4); 915 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_TIMEBASE, 153, 0, 9); 916 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_NREF, 800, 0, 10); 917 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_NREF_RANGE, 27, 0, 4); 918 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_TWAIT_CONFIG, 47, 0, 8); 919 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_TWAIT_CONFIG, 127, 9, 15); 920 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_VT_CONFIG, 47, 7, 15); 921 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_VT_CONFIG, 27, 2, 6); 922 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_VT_CONFIG, 3, 0, 1); 923 dwc_phy_write_mask(isys, id, PPI_RW_LPDCOCAL_COARSE_CFG, 1, 0, 1); 924 dwc_phy_write_mask(isys, id, PPI_RW_COMMON_CFG, 3, 0, 1); 925 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_0, 926 0, 10, 10); 927 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_1, 928 1, 10, 10); 929 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_1, 930 0, 15, 15); 931 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_3, 932 3, 8, 9); 933 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_0, 934 0, 15, 15); 935 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_6, 936 7, 12, 14); 937 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_7, 938 0, 8, 10); 939 /* resistance tuning: 1 for 45ohm, 0 for 50ohm */ 940 dwc_phy_write_mask(isys, id, CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_5, 941 1, 8, 8); 942 943 if (aggregation) 944 phy_mode = isys->csi2[0].phy_mode; 945 else 946 phy_mode = isys->csi2[id].phy_mode; 947 948 if (phy_mode == PHY_MODE_DPHY) { 949 ipu7_isys_dphy_config(isys, id, lanes, aggregation, mbps); 950 } else if (phy_mode == PHY_MODE_CPHY) { 951 ipu7_isys_cphy_config(isys, id, lanes, aggregation, mbps); 952 } else { 953 dev_err(dev, "unsupported phy mode %d!\n", 954 isys->csi2[id].phy_mode); 955 } 956 957 return 0; 958} 959 960int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2) 961{ 962 struct ipu7_isys *isys = csi2->isys; 963 u32 lanes = csi2->nlanes; 964 bool aggregation = false; 965 u32 id = csi2->port; 966 int ret; 967 968 /* lanes remapping for aggregation (port AB) mode */ 969 if (!is_ipu7(isys->adev->isp->hw_ver) && lanes > 2 && id == PORT_A) { 970 aggregation = true; 971 lanes = 2; 972 } 973 974 ipu7_isys_csi_phy_reset(isys, id); 975 gpreg_write(isys, id, PHY_CLK_LANE_CONTROL, 0x1); 976 gpreg_write(isys, id, PHY_CLK_LANE_FORCE_CONTROL, 0x2); 977 gpreg_write(isys, id, PHY_LANE_CONTROL_EN, (1U << lanes) - 1U); 978 gpreg_write(isys, id, PHY_LANE_FORCE_CONTROL, 0xf); 979 gpreg_write(isys, id, PHY_MODE, csi2->phy_mode); 980 981 /* config PORT_B if aggregation mode */ 982 if (aggregation) { 983 ipu7_isys_csi_phy_reset(isys, PORT_B); 984 gpreg_write(isys, PORT_B, PHY_CLK_LANE_CONTROL, 0x0); 985 gpreg_write(isys, PORT_B, PHY_LANE_CONTROL_EN, 0x3); 986 gpreg_write(isys, PORT_B, PHY_CLK_LANE_FORCE_CONTROL, 0x2); 987 gpreg_write(isys, PORT_B, PHY_LANE_FORCE_CONTROL, 0xf); 988 gpreg_write(isys, PORT_B, PHY_MODE, csi2->phy_mode); 989 } 990 991 ipu7_isys_csi_ctrl_cfg(csi2); 992 ipu7_isys_csi_ctrl_dids_config(csi2, id); 993 994 ret = ipu7_isys_phy_config(isys, id, lanes, aggregation); 995 if (ret < 0) 996 return ret; 997 998 gpreg_write(isys, id, PHY_RESET, 1); 999 gpreg_write(isys, id, PHY_SHUTDOWN, 1); 1000 dwc_csi_write(isys, id, DPHY_RSTZ, 1); 1001 dwc_csi_write(isys, id, PHY_SHUTDOWNZ, 1); 1002 dwc_csi_write(isys, id, CSI2_RESETN, 1); 1003 1004 ret = ipu7_isys_phy_ready(isys, id); 1005 if (ret < 0) 1006 return ret; 1007 1008 gpreg_write(isys, id, PHY_LANE_FORCE_CONTROL, 0); 1009 gpreg_write(isys, id, PHY_CLK_LANE_FORCE_CONTROL, 0); 1010 1011 /* config PORT_B if aggregation mode */ 1012 if (aggregation) { 1013 ret = ipu7_isys_phy_config(isys, PORT_B, 2, aggregation); 1014 if (ret < 0) 1015 return ret; 1016 1017 gpreg_write(isys, PORT_B, PHY_RESET, 1); 1018 gpreg_write(isys, PORT_B, PHY_SHUTDOWN, 1); 1019 dwc_csi_write(isys, PORT_B, DPHY_RSTZ, 1); 1020 dwc_csi_write(isys, PORT_B, PHY_SHUTDOWNZ, 1); 1021 dwc_csi_write(isys, PORT_B, CSI2_RESETN, 1); 1022 ret = ipu7_isys_phy_ready(isys, PORT_B); 1023 if (ret < 0) 1024 return ret; 1025 1026 gpreg_write(isys, PORT_B, PHY_LANE_FORCE_CONTROL, 0); 1027 gpreg_write(isys, PORT_B, PHY_CLK_LANE_FORCE_CONTROL, 0); 1028 } 1029 1030 return 0; 1031} 1032 1033void ipu7_isys_csi_phy_powerdown(struct ipu7_isys_csi2 *csi2) 1034{ 1035 struct ipu7_isys *isys = csi2->isys; 1036 1037 ipu7_isys_csi_phy_reset(isys, csi2->port); 1038 if (!is_ipu7(isys->adev->isp->hw_ver) && 1039 csi2->nlanes > 2U && csi2->port == PORT_A) 1040 ipu7_isys_csi_phy_reset(isys, PORT_B); 1041}
~/
Read-only file preview.