13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 23d0407baSopenharmony_ci/* 33d0407baSopenharmony_ci * Rockchip MIPI CSI2 DPHY driver 43d0407baSopenharmony_ci * 53d0407baSopenharmony_ci * Copyright (C) 2022 Rockchip Electronics Co., Ltd. 63d0407baSopenharmony_ci */ 73d0407baSopenharmony_ci 83d0407baSopenharmony_ci#include <linux/clk.h> 93d0407baSopenharmony_ci#include <linux/delay.h> 103d0407baSopenharmony_ci#include <linux/io.h> 113d0407baSopenharmony_ci#include <linux/module.h> 123d0407baSopenharmony_ci#include <linux/of.h> 133d0407baSopenharmony_ci#include <linux/of_graph.h> 143d0407baSopenharmony_ci#include <linux/of_platform.h> 153d0407baSopenharmony_ci#include <linux/platform_device.h> 163d0407baSopenharmony_ci#include <linux/pm_runtime.h> 173d0407baSopenharmony_ci#include <linux/regmap.h> 183d0407baSopenharmony_ci#include <linux/mfd/syscon.h> 193d0407baSopenharmony_ci#include <media/media-entity.h> 203d0407baSopenharmony_ci#include <media/v4l2-ctrls.h> 213d0407baSopenharmony_ci#include <media/v4l2-fwnode.h> 223d0407baSopenharmony_ci#include <media/v4l2-subdev.h> 233d0407baSopenharmony_ci#include <media/v4l2-device.h> 243d0407baSopenharmony_ci#include <linux/reset.h> 253d0407baSopenharmony_ci#include "phy-rockchip-csi2-dphy-common.h" 263d0407baSopenharmony_ci 273d0407baSopenharmony_ci/* GRF REG OFFSET */ 283d0407baSopenharmony_ci#define GRF_VI_CON0 (0x0340) 293d0407baSopenharmony_ci#define GRF_VI_CON1 (0x0344) 303d0407baSopenharmony_ci 313d0407baSopenharmony_ci/* RK3588 DPHY GRF REG OFFSET */ 323d0407baSopenharmony_ci#define GRF_DPHY_CON0 (0x0) 333d0407baSopenharmony_ci#define GRF_SOC_CON2 (0x0308) 343d0407baSopenharmony_ci 353d0407baSopenharmony_ci/* GRF REG BIT DEFINE */ 363d0407baSopenharmony_ci#define GRF_CSI2PHY_LANE_SEL_SPLIT (0x1) 373d0407baSopenharmony_ci#define GRF_CSI2PHY_SEL_SPLIT_0_1 (0x0) 383d0407baSopenharmony_ci#define GRF_CSI2PHY_SEL_SPLIT_2_3 BIT(0) 393d0407baSopenharmony_ci 403d0407baSopenharmony_ci/* RK3588 DCPHY GRF REG OFFSET */ 413d0407baSopenharmony_ci#define GRF_DCPHY_CON0 (0x0) 423d0407baSopenharmony_ci 433d0407baSopenharmony_ci/* PHY REG OFFSET */ 443d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_INVALID_OFFSET (0xffff) 453d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_PWRCTL CSI2_DPHY_CTRL_INVALID_OFFSET 463d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_LANE_ENABLE (0x00) 473d0407baSopenharmony_ci#define CSI2_DPHY_CLK1_LANE_EN (0x2C) 483d0407baSopenharmony_ci#define CSI2_DPHY_DUAL_CAL_EN (0x80) 493d0407baSopenharmony_ci#define CSI2_DPHY_CLK_WR_THS_SETTLE (0x160) 503d0407baSopenharmony_ci#define CSI2_DPHY_CLK_CALIB_EN (0x168) 513d0407baSopenharmony_ci#define CSI2_DPHY_LANE0_WR_THS_SETTLE (0x1e0) 523d0407baSopenharmony_ci#define CSI2_DPHY_LANE0_CALIB_EN (0x1e8) 533d0407baSopenharmony_ci#define CSI2_DPHY_LANE1_WR_THS_SETTLE (0x260) 543d0407baSopenharmony_ci#define CSI2_DPHY_LANE1_CALIB_EN (0x268) 553d0407baSopenharmony_ci#define CSI2_DPHY_LANE2_WR_THS_SETTLE (0x2e0) 563d0407baSopenharmony_ci#define CSI2_DPHY_LANE2_CALIB_EN (0x2e8) 573d0407baSopenharmony_ci#define CSI2_DPHY_LANE3_WR_THS_SETTLE (0x360) 583d0407baSopenharmony_ci#define CSI2_DPHY_LANE3_CALIB_EN (0x368) 593d0407baSopenharmony_ci#define CSI2_DPHY_CLK1_WR_THS_SETTLE (0x3e0) 603d0407baSopenharmony_ci#define CSI2_DPHY_CLK1_CALIB_EN (0x3e8) 613d0407baSopenharmony_ci 623d0407baSopenharmony_ci#define CSI2_DCPHY_CLK_WR_THS_SETTLE (0x030) 633d0407baSopenharmony_ci#define CSI2_DCPHY_LANE0_WR_THS_SETTLE (0x130) 643d0407baSopenharmony_ci#define CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC (0x134) 653d0407baSopenharmony_ci#define CSI2_DCPHY_LANE1_WR_THS_SETTLE (0x230) 663d0407baSopenharmony_ci#define CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC (0x234) 673d0407baSopenharmony_ci#define CSI2_DCPHY_LANE2_WR_THS_SETTLE (0x330) 683d0407baSopenharmony_ci#define CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC (0x334) 693d0407baSopenharmony_ci#define CSI2_DCPHY_LANE3_WR_THS_SETTLE (0x430) 703d0407baSopenharmony_ci#define CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC (0x434) 713d0407baSopenharmony_ci#define CSI2_DCPHY_CLK_LANE_ENABLE (0x000) 723d0407baSopenharmony_ci#define CSI2_DCPHY_DATA_LANE0_ENABLE (0x100) 733d0407baSopenharmony_ci#define CSI2_DCPHY_DATA_LANE1_ENABLE (0x200) 743d0407baSopenharmony_ci#define CSI2_DCPHY_DATA_LANE2_ENABLE (0x300) 753d0407baSopenharmony_ci#define CSI2_DCPHY_DATA_LANE3_ENABLE (0x400) 763d0407baSopenharmony_ci 773d0407baSopenharmony_ci#define CSI2_DCPHY_S0C_GNR_CON1 (0x004) 783d0407baSopenharmony_ci#define CSI2_DCPHY_COMBO_S0D0_GNR_CON1 (0x104) 793d0407baSopenharmony_ci#define CSI2_DCPHY_COMBO_S0D1_GNR_CON1 (0x204) 803d0407baSopenharmony_ci#define CSI2_DCPHY_COMBO_S0D2_GNR_CON1 (0x304) 813d0407baSopenharmony_ci#define CSI2_DCPHY_S0D3_GNR_CON1 (0x304) 823d0407baSopenharmony_ci 833d0407baSopenharmony_ci/* PHY REG BIT DEFINE */ 843d0407baSopenharmony_ci#define CSI2_DPHY_LANE_MODE_FULL (0x4) 853d0407baSopenharmony_ci#define CSI2_DPHY_LANE_MODE_SPLIT (0x2) 863d0407baSopenharmony_ci#define CSI2_DPHY_LANE_SPLIT_TOP (0x1) 873d0407baSopenharmony_ci#define CSI2_DPHY_LANE_SPLIT_BOT (0x2) 883d0407baSopenharmony_ci#define CSI2_DPHY_LANE_SPLIT_LANE0_1 (0x3 << 2) 893d0407baSopenharmony_ci#define CSI2_DPHY_LANE_SPLIT_LANE2_3 (0x3 << 4) 903d0407baSopenharmony_ci#define CSI2_DPHY_LANE_DUAL_MODE_EN BIT(6) 913d0407baSopenharmony_ci#define CSI2_DPHY_LANE_PARA_ARR_NUM (0x2) 923d0407baSopenharmony_ci 933d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT 2 943d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT 4 953d0407baSopenharmony_ci#define CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT 6 963d0407baSopenharmony_ci 973d0407baSopenharmony_cienum csi2_dphy_index { 983d0407baSopenharmony_ci DPHY0 = 0x0, 993d0407baSopenharmony_ci DPHY1, 1003d0407baSopenharmony_ci DPHY2, 1013d0407baSopenharmony_ci}; 1023d0407baSopenharmony_ci 1033d0407baSopenharmony_cienum csi2_dphy_lane { 1043d0407baSopenharmony_ci CSI2_DPHY_LANE_CLOCK = 0, 1053d0407baSopenharmony_ci CSI2_DPHY_LANE_CLOCK1, 1063d0407baSopenharmony_ci CSI2_DPHY_LANE_DATA0, 1073d0407baSopenharmony_ci CSI2_DPHY_LANE_DATA1, 1083d0407baSopenharmony_ci CSI2_DPHY_LANE_DATA2, 1093d0407baSopenharmony_ci CSI2_DPHY_LANE_DATA3 1103d0407baSopenharmony_ci}; 1113d0407baSopenharmony_ci 1123d0407baSopenharmony_cienum grf_reg_id { 1133d0407baSopenharmony_ci GRF_DPHY_RX0_TURNDISABLE = 0, 1143d0407baSopenharmony_ci GRF_DPHY_RX0_FORCERXMODE, 1153d0407baSopenharmony_ci GRF_DPHY_RX0_FORCETXSTOPMODE, 1163d0407baSopenharmony_ci GRF_DPHY_RX0_ENABLE, 1173d0407baSopenharmony_ci GRF_DPHY_RX0_TESTCLR, 1183d0407baSopenharmony_ci GRF_DPHY_RX0_TESTCLK, 1193d0407baSopenharmony_ci GRF_DPHY_RX0_TESTEN, 1203d0407baSopenharmony_ci GRF_DPHY_RX0_TESTDIN, 1213d0407baSopenharmony_ci GRF_DPHY_RX0_TURNREQUEST, 1223d0407baSopenharmony_ci GRF_DPHY_RX0_TESTDOUT, 1233d0407baSopenharmony_ci GRF_DPHY_TX0_TURNDISABLE, 1243d0407baSopenharmony_ci GRF_DPHY_TX0_FORCERXMODE, 1253d0407baSopenharmony_ci GRF_DPHY_TX0_FORCETXSTOPMODE, 1263d0407baSopenharmony_ci GRF_DPHY_TX0_TURNREQUEST, 1273d0407baSopenharmony_ci GRF_DPHY_TX1RX1_TURNDISABLE, 1283d0407baSopenharmony_ci GRF_DPHY_TX1RX1_FORCERXMODE, 1293d0407baSopenharmony_ci GRF_DPHY_TX1RX1_FORCETXSTOPMODE, 1303d0407baSopenharmony_ci GRF_DPHY_TX1RX1_ENABLE, 1313d0407baSopenharmony_ci GRF_DPHY_TX1RX1_MASTERSLAVEZ, 1323d0407baSopenharmony_ci GRF_DPHY_TX1RX1_BASEDIR, 1333d0407baSopenharmony_ci GRF_DPHY_TX1RX1_ENABLECLK, 1343d0407baSopenharmony_ci GRF_DPHY_TX1RX1_TURNREQUEST, 1353d0407baSopenharmony_ci GRF_DPHY_RX1_SRC_SEL, 1363d0407baSopenharmony_ci /* rk3288 only */ 1373d0407baSopenharmony_ci GRF_CON_DISABLE_ISP, 1383d0407baSopenharmony_ci GRF_CON_ISP_DPHY_SEL, 1393d0407baSopenharmony_ci GRF_DSI_CSI_TESTBUS_SEL, 1403d0407baSopenharmony_ci GRF_DVP_V18SEL, 1413d0407baSopenharmony_ci /* rk1808 & rk3326 & rv1126 */ 1423d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_FORCERXMODE, 1433d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_CLKLANE_EN, 1443d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_DATALANE_EN, 1453d0407baSopenharmony_ci /* rv1126 only */ 1463d0407baSopenharmony_ci GRF_DPHY_CLK_INV_SEL, 1473d0407baSopenharmony_ci GRF_DPHY_SEL, 1483d0407baSopenharmony_ci /* rk3368 only */ 1493d0407baSopenharmony_ci GRF_ISP_MIPI_CSI_HOST_SEL, 1503d0407baSopenharmony_ci /* below is for rk3399 only */ 1513d0407baSopenharmony_ci GRF_DPHY_RX0_CLK_INV_SEL, 1523d0407baSopenharmony_ci GRF_DPHY_RX1_CLK_INV_SEL, 1533d0407baSopenharmony_ci GRF_DPHY_TX1RX1_SRC_SEL, 1543d0407baSopenharmony_ci /* below is for rk3568 only */ 1553d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_CLKLANE1_EN, 1563d0407baSopenharmony_ci GRF_DPHY_CLK1_INV_SEL, 1573d0407baSopenharmony_ci GRF_DPHY_ISP_CSI2PHY_SEL, 1583d0407baSopenharmony_ci GRF_DPHY_CIF_CSI2PHY_SEL, 1593d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_LANE_SEL, 1603d0407baSopenharmony_ci GRF_DPHY_CSI2PHY1_LANE_SEL, 1613d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_DATALANE_EN0, 1623d0407baSopenharmony_ci GRF_DPHY_CSI2PHY_DATALANE_EN1, 1633d0407baSopenharmony_ci GRF_CPHY_MODE, 1643d0407baSopenharmony_ci GRF_DPHY_CSIHOST2_SEL, 1653d0407baSopenharmony_ci GRF_DPHY_CSIHOST3_SEL, 1663d0407baSopenharmony_ci GRF_DPHY_CSIHOST4_SEL, 1673d0407baSopenharmony_ci GRF_DPHY_CSIHOST5_SEL, 1683d0407baSopenharmony_ci}; 1693d0407baSopenharmony_ci 1703d0407baSopenharmony_cienum csi2dphy_reg_id { 1713d0407baSopenharmony_ci CSI2PHY_REG_CTRL_LANE_ENABLE = 0, 1723d0407baSopenharmony_ci CSI2PHY_CTRL_PWRCTL, 1733d0407baSopenharmony_ci CSI2PHY_CTRL_DIG_RST, 1743d0407baSopenharmony_ci CSI2PHY_CLK_THS_SETTLE, 1753d0407baSopenharmony_ci CSI2PHY_LANE0_THS_SETTLE, 1763d0407baSopenharmony_ci CSI2PHY_LANE1_THS_SETTLE, 1773d0407baSopenharmony_ci CSI2PHY_LANE2_THS_SETTLE, 1783d0407baSopenharmony_ci CSI2PHY_LANE3_THS_SETTLE, 1793d0407baSopenharmony_ci CSI2PHY_CLK_CALIB_ENABLE, 1803d0407baSopenharmony_ci CSI2PHY_LANE0_CALIB_ENABLE, 1813d0407baSopenharmony_ci CSI2PHY_LANE1_CALIB_ENABLE, 1823d0407baSopenharmony_ci CSI2PHY_LANE2_CALIB_ENABLE, 1833d0407baSopenharmony_ci CSI2PHY_LANE3_CALIB_ENABLE, 1843d0407baSopenharmony_ci // rv1126 only 1853d0407baSopenharmony_ci CSI2PHY_MIPI_LVDS_MODEL, 1863d0407baSopenharmony_ci CSI2PHY_LVDS_MODE, 1873d0407baSopenharmony_ci // rk3568 only 1883d0407baSopenharmony_ci CSI2PHY_DUAL_CLK_EN, 1893d0407baSopenharmony_ci CSI2PHY_CLK1_THS_SETTLE, 1903d0407baSopenharmony_ci CSI2PHY_CLK1_CALIB_ENABLE, 1913d0407baSopenharmony_ci // rk3588 1923d0407baSopenharmony_ci CSI2PHY_CLK_LANE_ENABLE, 1933d0407baSopenharmony_ci CSI2PHY_CLK1_LANE_ENABLE, 1943d0407baSopenharmony_ci CSI2PHY_DATA_LANE0_ENABLE, 1953d0407baSopenharmony_ci CSI2PHY_DATA_LANE1_ENABLE, 1963d0407baSopenharmony_ci CSI2PHY_DATA_LANE2_ENABLE, 1973d0407baSopenharmony_ci CSI2PHY_DATA_LANE3_ENABLE, 1983d0407baSopenharmony_ci CSI2PHY_LANE0_ERR_SOT_SYNC, 1993d0407baSopenharmony_ci CSI2PHY_LANE1_ERR_SOT_SYNC, 2003d0407baSopenharmony_ci CSI2PHY_LANE2_ERR_SOT_SYNC, 2013d0407baSopenharmony_ci CSI2PHY_LANE3_ERR_SOT_SYNC, 2023d0407baSopenharmony_ci CSI2PHY_S0C_GNR_CON1, 2033d0407baSopenharmony_ci CSI2PHY_COMBO_S0D0_GNR_CON1, 2043d0407baSopenharmony_ci CSI2PHY_COMBO_S0D1_GNR_CON1, 2053d0407baSopenharmony_ci CSI2PHY_COMBO_S0D2_GNR_CON1, 2063d0407baSopenharmony_ci CSI2PHY_S0D3_GNR_CON1, 2073d0407baSopenharmony_ci}; 2083d0407baSopenharmony_ci 2093d0407baSopenharmony_ci#define HIWORD_UPDATE(val, mask, shift) ((val) << (shift) | (mask) << ((shift) + 16)) 2103d0407baSopenharmony_ci 2113d0407baSopenharmony_ci#define GRF_REG(_offset, _width, _shift) \ 2123d0407baSopenharmony_ci { \ 2133d0407baSopenharmony_ci .offset = (_offset), .mask = BIT(_width) - 1, .shift = (_shift), \ 2143d0407baSopenharmony_ci } 2153d0407baSopenharmony_ci 2163d0407baSopenharmony_ci#define CSI2PHY_REG(_offset) \ 2173d0407baSopenharmony_ci { \ 2183d0407baSopenharmony_ci .offset = (_offset), \ 2193d0407baSopenharmony_ci } 2203d0407baSopenharmony_ci 2213d0407baSopenharmony_cistruct hsfreq_range { 2223d0407baSopenharmony_ci u32 range_h; 2233d0407baSopenharmony_ci u16 cfg_bit; 2243d0407baSopenharmony_ci}; 2253d0407baSopenharmony_ci 2263d0407baSopenharmony_cistatic inline void write_sys_grf_reg(struct csi2_dphy_hw *hw, int index, u8 value) 2273d0407baSopenharmony_ci{ 2283d0407baSopenharmony_ci const struct grf_reg *reg = &hw->grf_regs[index]; 2293d0407baSopenharmony_ci unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift); 2303d0407baSopenharmony_ci 2313d0407baSopenharmony_ci if (reg->shift) { 2323d0407baSopenharmony_ci regmap_write(hw->regmap_sys_grf, reg->offset, val); 2333d0407baSopenharmony_ci } 2343d0407baSopenharmony_ci} 2353d0407baSopenharmony_ci 2363d0407baSopenharmony_cistatic inline void write_grf_reg(struct csi2_dphy_hw *hw, int index, u8 value) 2373d0407baSopenharmony_ci{ 2383d0407baSopenharmony_ci const struct grf_reg *reg = &hw->grf_regs[index]; 2393d0407baSopenharmony_ci unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift); 2403d0407baSopenharmony_ci 2413d0407baSopenharmony_ci if (reg->shift) { 2423d0407baSopenharmony_ci regmap_write(hw->regmap_grf, reg->offset, val); 2433d0407baSopenharmony_ci } 2443d0407baSopenharmony_ci} 2453d0407baSopenharmony_ci 2463d0407baSopenharmony_cistatic inline u32 read_grf_reg(struct csi2_dphy_hw *hw, int index) 2473d0407baSopenharmony_ci{ 2483d0407baSopenharmony_ci const struct grf_reg *reg = &hw->grf_regs[index]; 2493d0407baSopenharmony_ci unsigned int val = 0; 2503d0407baSopenharmony_ci 2513d0407baSopenharmony_ci if (reg->shift) { 2523d0407baSopenharmony_ci regmap_read(hw->regmap_grf, reg->offset, &val); 2533d0407baSopenharmony_ci val = (val >> reg->shift) & reg->mask; 2543d0407baSopenharmony_ci } 2553d0407baSopenharmony_ci 2563d0407baSopenharmony_ci return val; 2573d0407baSopenharmony_ci} 2583d0407baSopenharmony_ci 2593d0407baSopenharmony_cistatic inline void write_csi2_dphy_reg(struct csi2_dphy_hw *hw, int index, u32 value) 2603d0407baSopenharmony_ci{ 2613d0407baSopenharmony_ci const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; 2623d0407baSopenharmony_ci 2633d0407baSopenharmony_ci if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) || (index == CSI2PHY_CLK_LANE_ENABLE) || 2643d0407baSopenharmony_ci (index != CSI2PHY_REG_CTRL_LANE_ENABLE && reg->offset != 0x0)) { 2653d0407baSopenharmony_ci writel(value, hw->hw_base_addr + reg->offset); 2663d0407baSopenharmony_ci } 2673d0407baSopenharmony_ci} 2683d0407baSopenharmony_ci 2693d0407baSopenharmony_cistatic inline void write_csi2_dphy_reg_mask(struct csi2_dphy_hw *hw, int index, u32 value, u32 mask) 2703d0407baSopenharmony_ci{ 2713d0407baSopenharmony_ci const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; 2723d0407baSopenharmony_ci u32 read_val = 0; 2733d0407baSopenharmony_ci 2743d0407baSopenharmony_ci read_val = readl(hw->hw_base_addr + reg->offset); 2753d0407baSopenharmony_ci read_val &= ~mask; 2763d0407baSopenharmony_ci read_val |= value; 2773d0407baSopenharmony_ci writel(read_val, hw->hw_base_addr + reg->offset); 2783d0407baSopenharmony_ci} 2793d0407baSopenharmony_ci 2803d0407baSopenharmony_cistatic inline void read_csi2_dphy_reg(struct csi2_dphy_hw *hw, int index, u32 *value) 2813d0407baSopenharmony_ci{ 2823d0407baSopenharmony_ci const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index]; 2833d0407baSopenharmony_ci 2843d0407baSopenharmony_ci if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) || (index == CSI2PHY_CLK_LANE_ENABLE) || 2853d0407baSopenharmony_ci (index != CSI2PHY_REG_CTRL_LANE_ENABLE && reg->offset != 0x0)) { 2863d0407baSopenharmony_ci *value = readl(hw->hw_base_addr + reg->offset); 2873d0407baSopenharmony_ci } 2883d0407baSopenharmony_ci} 2893d0407baSopenharmony_ci 2903d0407baSopenharmony_cistatic void csi_mipidphy_wr_ths_settle(struct csi2_dphy_hw *hw, int hsfreq, enum csi2_dphy_lane lane) 2913d0407baSopenharmony_ci{ 2923d0407baSopenharmony_ci unsigned int val = 0; 2933d0407baSopenharmony_ci unsigned int offset; 2943d0407baSopenharmony_ci 2953d0407baSopenharmony_ci switch (lane) { 2963d0407baSopenharmony_ci case CSI2_DPHY_LANE_CLOCK: 2973d0407baSopenharmony_ci offset = CSI2PHY_CLK_THS_SETTLE; 2983d0407baSopenharmony_ci break; 2993d0407baSopenharmony_ci case CSI2_DPHY_LANE_CLOCK1: 3003d0407baSopenharmony_ci offset = CSI2PHY_CLK1_THS_SETTLE; 3013d0407baSopenharmony_ci break; 3023d0407baSopenharmony_ci case CSI2_DPHY_LANE_DATA0: 3033d0407baSopenharmony_ci offset = CSI2PHY_LANE0_THS_SETTLE; 3043d0407baSopenharmony_ci break; 3053d0407baSopenharmony_ci case CSI2_DPHY_LANE_DATA1: 3063d0407baSopenharmony_ci offset = CSI2PHY_LANE1_THS_SETTLE; 3073d0407baSopenharmony_ci break; 3083d0407baSopenharmony_ci case CSI2_DPHY_LANE_DATA2: 3093d0407baSopenharmony_ci offset = CSI2PHY_LANE2_THS_SETTLE; 3103d0407baSopenharmony_ci break; 3113d0407baSopenharmony_ci case CSI2_DPHY_LANE_DATA3: 3123d0407baSopenharmony_ci offset = CSI2PHY_LANE3_THS_SETTLE; 3133d0407baSopenharmony_ci break; 3143d0407baSopenharmony_ci default: 3153d0407baSopenharmony_ci return; 3163d0407baSopenharmony_ci } 3173d0407baSopenharmony_ci 3183d0407baSopenharmony_ci read_csi2_dphy_reg(hw, offset, &val); 3193d0407baSopenharmony_ci val = (val & ~0x7f) | hsfreq; 3203d0407baSopenharmony_ci write_csi2_dphy_reg(hw, offset, val); 3213d0407baSopenharmony_ci} 3223d0407baSopenharmony_ci 3233d0407baSopenharmony_cistatic const struct grf_reg rk3568_grf_dphy_regs[] = { 3243d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_VI_CON0, 4, 0), 3253d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_VI_CON0, 4, 4), 3263d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_VI_CON0, 2, 4), 3273d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_VI_CON0, 2, 6), 3283d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_VI_CON0, 1, 8), 3293d0407baSopenharmony_ci [GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_VI_CON0, 1, 9), 3303d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_VI_CON0, 1, 10), 3313d0407baSopenharmony_ci [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_VI_CON0, 1, 11), 3323d0407baSopenharmony_ci [GRF_DPHY_ISP_CSI2PHY_SEL] = GRF_REG(GRF_VI_CON1, 1, 12), 3333d0407baSopenharmony_ci [GRF_DPHY_CIF_CSI2PHY_SEL] = GRF_REG(GRF_VI_CON1, 1, 11), 3343d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_VI_CON1, 1, 7), 3353d0407baSopenharmony_ci}; 3363d0407baSopenharmony_ci 3373d0407baSopenharmony_cistatic const struct csi2dphy_reg rk3568_csi2dphy_regs[] = { 3383d0407baSopenharmony_ci [CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE), 3393d0407baSopenharmony_ci [CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN), 3403d0407baSopenharmony_ci [CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE), 3413d0407baSopenharmony_ci [CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN), 3423d0407baSopenharmony_ci [CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE), 3433d0407baSopenharmony_ci [CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN), 3443d0407baSopenharmony_ci [CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE), 3453d0407baSopenharmony_ci [CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN), 3463d0407baSopenharmony_ci [CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE), 3473d0407baSopenharmony_ci [CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN), 3483d0407baSopenharmony_ci [CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE), 3493d0407baSopenharmony_ci [CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN), 3503d0407baSopenharmony_ci [CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE), 3513d0407baSopenharmony_ci [CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN), 3523d0407baSopenharmony_ci}; 3533d0407baSopenharmony_ci 3543d0407baSopenharmony_cistatic const struct grf_reg rk3588_grf_dphy_regs[] = { 3553d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_DPHY_CON0, 4, 0), 3563d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_DPHY_CON0, 4, 4), 3573d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_DPHY_CON0, 2, 4), 3583d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_DPHY_CON0, 2, 6), 3593d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_DPHY_CON0, 1, 8), 3603d0407baSopenharmony_ci [GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 9), 3613d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_DPHY_CON0, 1, 10), 3623d0407baSopenharmony_ci [GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 11), 3633d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 6), 3643d0407baSopenharmony_ci [GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 7), 3653d0407baSopenharmony_ci [GRF_DPHY_CSIHOST2_SEL] = GRF_REG(GRF_SOC_CON2, 1, 8), 3663d0407baSopenharmony_ci [GRF_DPHY_CSIHOST3_SEL] = GRF_REG(GRF_SOC_CON2, 1, 9), 3673d0407baSopenharmony_ci [GRF_DPHY_CSIHOST4_SEL] = GRF_REG(GRF_SOC_CON2, 1, 10), 3683d0407baSopenharmony_ci [GRF_DPHY_CSIHOST5_SEL] = GRF_REG(GRF_SOC_CON2, 1, 11), 3693d0407baSopenharmony_ci}; 3703d0407baSopenharmony_ci 3713d0407baSopenharmony_cistatic const struct csi2dphy_reg rk3588_csi2dphy_regs[] = { 3723d0407baSopenharmony_ci [CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE), 3733d0407baSopenharmony_ci [CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN), 3743d0407baSopenharmony_ci [CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE), 3753d0407baSopenharmony_ci [CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN), 3763d0407baSopenharmony_ci [CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE), 3773d0407baSopenharmony_ci [CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN), 3783d0407baSopenharmony_ci [CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE), 3793d0407baSopenharmony_ci [CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN), 3803d0407baSopenharmony_ci [CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE), 3813d0407baSopenharmony_ci [CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN), 3823d0407baSopenharmony_ci [CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE), 3833d0407baSopenharmony_ci [CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN), 3843d0407baSopenharmony_ci [CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE), 3853d0407baSopenharmony_ci [CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN), 3863d0407baSopenharmony_ci [CSI2PHY_CLK1_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_LANE_EN), 3873d0407baSopenharmony_ci}; 3883d0407baSopenharmony_ci 3893d0407baSopenharmony_cistatic const struct grf_reg rk3588_grf_dcphy_regs[] = { 3903d0407baSopenharmony_ci [GRF_CPHY_MODE] = GRF_REG(GRF_DCPHY_CON0, 9, 0), 3913d0407baSopenharmony_ci}; 3923d0407baSopenharmony_ci 3933d0407baSopenharmony_cistatic const struct csi2dphy_reg rk3588_csi2dcphy_regs[] = { 3943d0407baSopenharmony_ci [CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_WR_THS_SETTLE), 3953d0407baSopenharmony_ci [CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_THS_SETTLE), 3963d0407baSopenharmony_ci [CSI2PHY_LANE0_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC), 3973d0407baSopenharmony_ci [CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_THS_SETTLE), 3983d0407baSopenharmony_ci [CSI2PHY_LANE1_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC), 3993d0407baSopenharmony_ci [CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_THS_SETTLE), 4003d0407baSopenharmony_ci [CSI2PHY_LANE2_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC), 4013d0407baSopenharmony_ci [CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_THS_SETTLE), 4023d0407baSopenharmony_ci [CSI2PHY_LANE3_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC), 4033d0407baSopenharmony_ci [CSI2PHY_CLK_LANE_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_LANE_ENABLE), 4043d0407baSopenharmony_ci [CSI2PHY_DATA_LANE0_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE0_ENABLE), 4053d0407baSopenharmony_ci [CSI2PHY_DATA_LANE1_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE1_ENABLE), 4063d0407baSopenharmony_ci [CSI2PHY_DATA_LANE2_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE2_ENABLE), 4073d0407baSopenharmony_ci [CSI2PHY_DATA_LANE3_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE3_ENABLE), 4083d0407baSopenharmony_ci [CSI2PHY_S0C_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0C_GNR_CON1), 4093d0407baSopenharmony_ci [CSI2PHY_COMBO_S0D0_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_GNR_CON1), 4103d0407baSopenharmony_ci [CSI2PHY_COMBO_S0D1_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_GNR_CON1), 4113d0407baSopenharmony_ci [CSI2PHY_COMBO_S0D2_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_GNR_CON1), 4123d0407baSopenharmony_ci [CSI2PHY_S0D3_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0D3_GNR_CON1), 4133d0407baSopenharmony_ci}; 4143d0407baSopenharmony_ci 4153d0407baSopenharmony_ci/* These tables must be sorted by .range_h ascending. */ 4163d0407baSopenharmony_cistatic const struct hsfreq_range rk3568_csi2_dphy_hw_hsfreq_ranges[] = { 4173d0407baSopenharmony_ci {109, 0x02}, {149, 0x03}, {199, 0x06}, {249, 0x06}, {299, 0x06}, {399, 0x08}, {499, 0x0b}, 4183d0407baSopenharmony_ci {599, 0x0e}, {699, 0x10}, {799, 0x12}, {999, 0x16}, {1199, 0x1e}, {1399, 0x23}, {1599, 0x2d}, 4193d0407baSopenharmony_ci {1799, 0x32}, {1999, 0x37}, {2199, 0x3c}, {2399, 0x41}, {2499, 0x46}}; 4203d0407baSopenharmony_ci 4213d0407baSopenharmony_ci/* These tables must be sorted by .range_h ascending. */ 4223d0407baSopenharmony_cistatic const struct hsfreq_range rk3588_csi2_dcphy_d_hw_hsfreq_ranges[] = { 4233d0407baSopenharmony_ci {80, 0x105}, {100, 0x106}, {120, 0x107}, {140, 0x108}, {160, 0x109}, {180, 0x10a}, {200, 0x10b}, 4243d0407baSopenharmony_ci {220, 0x10c}, {240, 0x10d}, {270, 0x10e}, {290, 0x10f}, {310, 0x110}, {330, 0x111}, {350, 0x112}, 4253d0407baSopenharmony_ci {370, 0x113}, {390, 0x114}, {410, 0x115}, {430, 0x116}, {450, 0x117}, {470, 0x118}, {490, 0x119}, 4263d0407baSopenharmony_ci {510, 0x11a}, {540, 0x11b}, {560, 0x11c}, {580, 0x11d}, {600, 0x11e}, {620, 0x11f}, {640, 0x120}, 4273d0407baSopenharmony_ci {660, 0x121}, {680, 0x122}, {700, 0x123}, {720, 0x124}, {740, 0x125}, {760, 0x126}, {790, 0x127}, 4283d0407baSopenharmony_ci {810, 0x128}, {830, 0x129}, {850, 0x12a}, {870, 0x12b}, {890, 0x12c}, {910, 0x12d}, {930, 0x12e}, 4293d0407baSopenharmony_ci {950, 0x12f}, {970, 0x130}, {990, 0x131}, {1010, 0x132}, {1030, 0x133}, {1060, 0x134}, {1080, 0x135}, 4303d0407baSopenharmony_ci {1100, 0x136}, {1120, 0x137}, {1140, 0x138}, {1160, 0x139}, {1180, 0x13a}, {1200, 0x13b}, {1220, 0x13c}, 4313d0407baSopenharmony_ci {1240, 0x13d}, {1260, 0x13e}, {1280, 0x13f}, {1310, 0x140}, {1330, 0x141}, {1350, 0x142}, {1370, 0x143}, 4323d0407baSopenharmony_ci {1390, 0x144}, {1410, 0x145}, {1430, 0x146}, {1450, 0x147}, {1470, 0x148}, {1490, 0x149}, {1580, 0x007}, 4333d0407baSopenharmony_ci {1740, 0x008}, {1910, 0x009}, {2070, 0x00a}, {2240, 0x00b}, {2410, 0x00c}, {2570, 0x00d}, {2740, 0x00e}, 4343d0407baSopenharmony_ci {2910, 0x00f}, {3070, 0x010}, {3240, 0x011}, {3410, 0x012}, {3570, 0x013}, {3740, 0x014}, {3890, 0x015}, 4353d0407baSopenharmony_ci {4070, 0x016}, {4240, 0x017}, {4400, 0x018}, {4500, 0x019}, 4363d0407baSopenharmony_ci}; 4373d0407baSopenharmony_ci 4383d0407baSopenharmony_ci/* These tables must be sorted by .range_h ascending. */ 4393d0407baSopenharmony_cistatic const struct hsfreq_range rk3588_csi2_dcphy_c_hw_hsfreq_ranges[] = { 4403d0407baSopenharmony_ci {500, 0x102}, 4413d0407baSopenharmony_ci {990, 0x002}, 4423d0407baSopenharmony_ci {2500, 0x001}, 4433d0407baSopenharmony_ci}; 4443d0407baSopenharmony_ci 4453d0407baSopenharmony_cistatic struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd) 4463d0407baSopenharmony_ci{ 4473d0407baSopenharmony_ci struct media_pad *local, *remote; 4483d0407baSopenharmony_ci struct media_entity *sensor_me; 4493d0407baSopenharmony_ci 4503d0407baSopenharmony_ci local = &sd->entity.pads[CSI2_DPHY_RX_PAD_SINK]; 4513d0407baSopenharmony_ci remote = media_entity_remote_pad(local); 4523d0407baSopenharmony_ci if (!remote) { 4533d0407baSopenharmony_ci v4l2_warn(sd, "No link between dphy and sensor\n"); 4543d0407baSopenharmony_ci return NULL; 4553d0407baSopenharmony_ci } 4563d0407baSopenharmony_ci 4573d0407baSopenharmony_ci sensor_me = media_entity_remote_pad(local)->entity; 4583d0407baSopenharmony_ci return media_entity_to_v4l2_subdev(sensor_me); 4593d0407baSopenharmony_ci} 4603d0407baSopenharmony_ci 4613d0407baSopenharmony_cistatic struct csi2_sensor *sd_to_sensor(struct csi2_dphy *dphy, struct v4l2_subdev *sd) 4623d0407baSopenharmony_ci{ 4633d0407baSopenharmony_ci int i; 4643d0407baSopenharmony_ci 4653d0407baSopenharmony_ci for (i = 0; i < dphy->num_sensors; ++i) { 4663d0407baSopenharmony_ci if (dphy->sensors[i].sd == sd) { 4673d0407baSopenharmony_ci return &dphy->sensors[i]; 4683d0407baSopenharmony_ci } 4693d0407baSopenharmony_ci } 4703d0407baSopenharmony_ci 4713d0407baSopenharmony_ci return NULL; 4723d0407baSopenharmony_ci} 4733d0407baSopenharmony_ci 4743d0407baSopenharmony_cistatic void csi2_dphy_hw_do_reset(struct csi2_dphy_hw *hw) 4753d0407baSopenharmony_ci{ 4763d0407baSopenharmony_ci if (hw->rsts_bulk) { 4773d0407baSopenharmony_ci reset_control_assert(hw->rsts_bulk); 4783d0407baSopenharmony_ci } 4793d0407baSopenharmony_ci 4803d0407baSopenharmony_ci udelay(0X05); 4813d0407baSopenharmony_ci 4823d0407baSopenharmony_ci if (hw->rsts_bulk) { 4833d0407baSopenharmony_ci reset_control_deassert(hw->rsts_bulk); 4843d0407baSopenharmony_ci } 4853d0407baSopenharmony_ci} 4863d0407baSopenharmony_ci 4873d0407baSopenharmony_cistatic void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, struct csi2_sensor *sensor) 4883d0407baSopenharmony_ci{ 4893d0407baSopenharmony_ci struct csi2_dphy_hw *hw = dphy->dphy_hw; 4903d0407baSopenharmony_ci struct v4l2_subdev *sd = &dphy->sd; 4913d0407baSopenharmony_ci bool is_cif = false; 4923d0407baSopenharmony_ci char *model; 4933d0407baSopenharmony_ci u32 val; 4943d0407baSopenharmony_ci 4953d0407baSopenharmony_ci model = sd->v4l2_dev->mdev->model; 4963d0407baSopenharmony_ci if (!strncmp(model, "rkcif_mipi_lvds", sizeof("rkcif_mipi_lvds") - 1)) { 4973d0407baSopenharmony_ci is_cif = true; 4983d0407baSopenharmony_ci } else { 4993d0407baSopenharmony_ci is_cif = false; 5003d0407baSopenharmony_ci } 5013d0407baSopenharmony_ci 5023d0407baSopenharmony_ci if (hw->lane_mode == LANE_MODE_FULL) { 5033d0407baSopenharmony_ci val = ~GRF_CSI2PHY_LANE_SEL_SPLIT; 5043d0407baSopenharmony_ci if (dphy->phy_index < 0X03) { 5053d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, GENMASK(sensor->lanes - 1, 0)); 5063d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); 5073d0407baSopenharmony_ci if (hw->drv_data->chip_id < CHIP_ID_RK3588) { 5083d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5093d0407baSopenharmony_ci } else { 5103d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5113d0407baSopenharmony_ci } 5123d0407baSopenharmony_ci } else { 5133d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN, GENMASK(sensor->lanes - 1, 0)); 5143d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); 5153d0407baSopenharmony_ci if (hw->drv_data->chip_id < CHIP_ID_RK3588) { 5163d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); 5173d0407baSopenharmony_ci } else { 5183d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); 5193d0407baSopenharmony_ci } 5203d0407baSopenharmony_ci } 5213d0407baSopenharmony_ci } else { 5223d0407baSopenharmony_ci val = GRF_CSI2PHY_LANE_SEL_SPLIT; 5233d0407baSopenharmony_ci 5243d0407baSopenharmony_ci switch (dphy->phy_index) { 5253d0407baSopenharmony_ci case 1: 5263d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN0, GENMASK(sensor->lanes - 1, 0)); 5273d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); 5283d0407baSopenharmony_ci if (hw->drv_data->chip_id < CHIP_ID_RK3588) { 5293d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5303d0407baSopenharmony_ci if (is_cif) { 5313d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_0_1); 5323d0407baSopenharmony_ci } else { 5333d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_0_1); 5343d0407baSopenharmony_ci } 5353d0407baSopenharmony_ci } else { 5363d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSIHOST2_SEL, 0x0); 5373d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5383d0407baSopenharmony_ci } 5393d0407baSopenharmony_ci break; 5403d0407baSopenharmony_ci case 0X02: 5413d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN1, GENMASK(sensor->lanes - 1, 0)); 5423d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1); 5433d0407baSopenharmony_ci if (hw->drv_data->chip_id < CHIP_ID_RK3588) { 5443d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5453d0407baSopenharmony_ci if (is_cif) { 5463d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_2_3); 5473d0407baSopenharmony_ci } else { 5483d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_2_3); 5493d0407baSopenharmony_ci } 5503d0407baSopenharmony_ci } else { 5513d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSIHOST3_SEL, 0x1); 5523d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); 5533d0407baSopenharmony_ci } 5543d0407baSopenharmony_ci break; 5553d0407baSopenharmony_ci case 0X04: 5563d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); 5573d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSIHOST4_SEL, 0x0); 5583d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN0, GENMASK(sensor->lanes - 1, 0)); 5593d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); 5603d0407baSopenharmony_ci break; 5613d0407baSopenharmony_ci case 0X05: 5623d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val); 5633d0407baSopenharmony_ci write_sys_grf_reg(hw, GRF_DPHY_CSIHOST5_SEL, 0x1); 5643d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN1, GENMASK(sensor->lanes - 1, 0)); 5653d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1); 5663d0407baSopenharmony_ci break; 5673d0407baSopenharmony_ci default: 5683d0407baSopenharmony_ci break; 5693d0407baSopenharmony_ci }; 5703d0407baSopenharmony_ci } 5713d0407baSopenharmony_ci} 5723d0407baSopenharmony_ci 5733d0407baSopenharmony_cistatic int csi2_dphy_hw_stream_on(struct csi2_dphy *dphy, struct v4l2_subdev *sd) 5743d0407baSopenharmony_ci{ 5753d0407baSopenharmony_ci struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); 5763d0407baSopenharmony_ci struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd); 5773d0407baSopenharmony_ci struct csi2_dphy_hw *hw = dphy->dphy_hw; 5783d0407baSopenharmony_ci const struct dphy_hw_drv_data *drv_data = hw->drv_data; 5793d0407baSopenharmony_ci const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; 5803d0407baSopenharmony_ci int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; 5813d0407baSopenharmony_ci int i, hsfreq = 0; 5823d0407baSopenharmony_ci u32 val = 0, pre_val; 5833d0407baSopenharmony_ci 5843d0407baSopenharmony_ci mutex_lock(&hw->mutex); 5853d0407baSopenharmony_ci 5863d0407baSopenharmony_ci /* set data lane num and enable clock lane */ 5873d0407baSopenharmony_ci /* 5883d0407baSopenharmony_ci * for rk356x: dphy0 is used just for full mode, 5893d0407baSopenharmony_ci * dphy1 is used just for split mode,uses lane0_1, 5903d0407baSopenharmony_ci * dphy2 is used just for split mode,uses lane2_3 5913d0407baSopenharmony_ci */ 5923d0407baSopenharmony_ci read_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, &pre_val); 5933d0407baSopenharmony_ci if (hw->lane_mode == LANE_MODE_FULL) { 5943d0407baSopenharmony_ci val |= (GENMASK(sensor->lanes - 1, 0) << CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) | 5953d0407baSopenharmony_ci (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT); 5963d0407baSopenharmony_ci } else { 5973d0407baSopenharmony_ci if (!(pre_val & (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT))) { 5983d0407baSopenharmony_ci val |= (0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT); 5993d0407baSopenharmony_ci } 6003d0407baSopenharmony_ci 6013d0407baSopenharmony_ci if (dphy->phy_index % 0X03 == DPHY1) { 6023d0407baSopenharmony_ci val |= (GENMASK(sensor->lanes - 1, 0) << CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT); 6033d0407baSopenharmony_ci } 6043d0407baSopenharmony_ci 6053d0407baSopenharmony_ci if (dphy->phy_index % 0x03 == DPHY2) { 6063d0407baSopenharmony_ci val |= (GENMASK(sensor->lanes - 1, 0) << CSI2_DPHY_CTRL_DATALANE_SPLIT_LANE2_3_OFFSET_BIT); 6073d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK1_LANE_ENABLE, BIT(0x06)); 6083d0407baSopenharmony_ci } 6093d0407baSopenharmony_ci } 6103d0407baSopenharmony_ci val |= pre_val; 6113d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, val); 6123d0407baSopenharmony_ci 6133d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 6143d0407baSopenharmony_ci /* Reset dphy digital part */ 6153d0407baSopenharmony_ci if (hw->lane_mode == LANE_MODE_FULL) { 6163d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1e); 6173d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1f); 6183d0407baSopenharmony_ci } else { 6193d0407baSopenharmony_ci read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val); 6203d0407baSopenharmony_ci if (!(val & CSI2_DPHY_LANE_DUAL_MODE_EN)) { 6213d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5e); 6223d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x5f); 6233d0407baSopenharmony_ci } 6243d0407baSopenharmony_ci } 6253d0407baSopenharmony_ci csi2_dphy_config_dual_mode(dphy, sensor); 6263d0407baSopenharmony_ci } 6273d0407baSopenharmony_ci 6283d0407baSopenharmony_ci /* not into receive mode/wait stopstate */ 6293d0407baSopenharmony_ci write_grf_reg(hw, GRF_DPHY_CSI2PHY_FORCERXMODE, 0x0); 6303d0407baSopenharmony_ci 6313d0407baSopenharmony_ci /* enable calibration */ 6323d0407baSopenharmony_ci if (dphy->data_rate_mbps > 0x5dc) { 6333d0407baSopenharmony_ci if (hw->lane_mode == LANE_MODE_FULL) { 6343d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK_CALIB_ENABLE, 0x80); 6353d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 6363d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE0_CALIB_ENABLE, 0x80); 6373d0407baSopenharmony_ci } 6383d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 6393d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE1_CALIB_ENABLE, 0x80); 6403d0407baSopenharmony_ci } 6413d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 6423d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE2_CALIB_ENABLE, 0x80); 6433d0407baSopenharmony_ci } 6443d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 6453d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE3_CALIB_ENABLE, 0x80); 6463d0407baSopenharmony_ci } 6473d0407baSopenharmony_ci } else { 6483d0407baSopenharmony_ci if (dphy->phy_index % 0x03 == DPHY1) { 6493d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK_CALIB_ENABLE, 0x80); 6503d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 6513d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE0_CALIB_ENABLE, 0x80); 6523d0407baSopenharmony_ci } 6533d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 6543d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE1_CALIB_ENABLE, 0x80); 6553d0407baSopenharmony_ci } 6563d0407baSopenharmony_ci } 6573d0407baSopenharmony_ci 6583d0407baSopenharmony_ci if (dphy->phy_index % 0x03 == DPHY2) { 6593d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK1_CALIB_ENABLE, 0x80); 6603d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 6613d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE2_CALIB_ENABLE, 0x80); 6623d0407baSopenharmony_ci } 6633d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 6643d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_LANE3_CALIB_ENABLE, 0x80); 6653d0407baSopenharmony_ci } 6663d0407baSopenharmony_ci } 6673d0407baSopenharmony_ci } 6683d0407baSopenharmony_ci } 6693d0407baSopenharmony_ci 6703d0407baSopenharmony_ci /* set clock lane and data lane */ 6713d0407baSopenharmony_ci for (i = 0; i < num_hsfreq_ranges; i++) { 6723d0407baSopenharmony_ci if (hsfreq_ranges[i].range_h >= dphy->data_rate_mbps) { 6733d0407baSopenharmony_ci hsfreq = hsfreq_ranges[i].cfg_bit; 6743d0407baSopenharmony_ci break; 6753d0407baSopenharmony_ci } 6763d0407baSopenharmony_ci } 6773d0407baSopenharmony_ci 6783d0407baSopenharmony_ci if (i == num_hsfreq_ranges) { 6793d0407baSopenharmony_ci i = num_hsfreq_ranges - 1; 6803d0407baSopenharmony_ci dev_warn(dphy->dev, "data rate: %lld mbps, max support %d mbps", dphy->data_rate_mbps, 6813d0407baSopenharmony_ci hsfreq_ranges[i].range_h + 1); 6823d0407baSopenharmony_ci hsfreq = hsfreq_ranges[i].cfg_bit; 6833d0407baSopenharmony_ci } 6843d0407baSopenharmony_ci 6853d0407baSopenharmony_ci if (hw->lane_mode == LANE_MODE_FULL) { 6863d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK); 6873d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 6883d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA0); 6893d0407baSopenharmony_ci } 6903d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 6913d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA1); 6923d0407baSopenharmony_ci } 6933d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 6943d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA2); 6953d0407baSopenharmony_ci } 6963d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 6973d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA3); 6983d0407baSopenharmony_ci } 6993d0407baSopenharmony_ci } else { 7003d0407baSopenharmony_ci if (dphy->phy_index % 0x03 == DPHY1) { 7013d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK); 7023d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA0); 7033d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA1); 7043d0407baSopenharmony_ci } 7053d0407baSopenharmony_ci 7063d0407baSopenharmony_ci if (dphy->phy_index % 0x03 == DPHY2) { 7073d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK1); 7083d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA2); 7093d0407baSopenharmony_ci csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA3); 7103d0407baSopenharmony_ci } 7113d0407baSopenharmony_ci } 7123d0407baSopenharmony_ci 7133d0407baSopenharmony_ci atomic_inc(&hw->stream_cnt); 7143d0407baSopenharmony_ci 7153d0407baSopenharmony_ci mutex_unlock(&hw->mutex); 7163d0407baSopenharmony_ci 7173d0407baSopenharmony_ci return 0; 7183d0407baSopenharmony_ci} 7193d0407baSopenharmony_ci 7203d0407baSopenharmony_cistatic int csi2_dphy_hw_stream_off(struct csi2_dphy *dphy, struct v4l2_subdev *sd) 7213d0407baSopenharmony_ci{ 7223d0407baSopenharmony_ci struct csi2_dphy_hw *hw = dphy->dphy_hw; 7233d0407baSopenharmony_ci 7243d0407baSopenharmony_ci if (atomic_dec_return(&hw->stream_cnt)) { 7253d0407baSopenharmony_ci return 0; 7263d0407baSopenharmony_ci } 7273d0407baSopenharmony_ci 7283d0407baSopenharmony_ci mutex_lock(&hw->mutex); 7293d0407baSopenharmony_ci 7303d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x01); 7313d0407baSopenharmony_ci csi2_dphy_hw_do_reset(hw); 7323d0407baSopenharmony_ci usleep_range(0x1F4, 0x3E8); 7333d0407baSopenharmony_ci 7343d0407baSopenharmony_ci mutex_unlock(&hw->mutex); 7353d0407baSopenharmony_ci 7363d0407baSopenharmony_ci return 0; 7373d0407baSopenharmony_ci} 7383d0407baSopenharmony_ci 7393d0407baSopenharmony_cistatic int csi_dcphy_wait_lane_prepare(struct csi2_dphy_hw *hw, int index) 7403d0407baSopenharmony_ci{ 7413d0407baSopenharmony_ci int count = 0; 7423d0407baSopenharmony_ci u32 val = 0; 7433d0407baSopenharmony_ci 7443d0407baSopenharmony_ci read_csi2_dphy_reg(hw, index, &val); 7453d0407baSopenharmony_ci while (!(val & BIT(1))) { 7463d0407baSopenharmony_ci usleep_range(0x0A, 0x14); 7473d0407baSopenharmony_ci read_csi2_dphy_reg(hw, index, &val); 7483d0407baSopenharmony_ci count++; 7493d0407baSopenharmony_ci if (count > 0x7D0) { 7503d0407baSopenharmony_ci return -EINVAL; 7513d0407baSopenharmony_ci } 7523d0407baSopenharmony_ci } 7533d0407baSopenharmony_ci return 0; 7543d0407baSopenharmony_ci} 7553d0407baSopenharmony_ci 7563d0407baSopenharmony_cistatic int csi2_dcphy_hw_stream_on(struct csi2_dphy *dphy, struct v4l2_subdev *sd) 7573d0407baSopenharmony_ci{ 7583d0407baSopenharmony_ci struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); 7593d0407baSopenharmony_ci struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd); 7603d0407baSopenharmony_ci struct csi2_dphy_hw *hw = dphy->dphy_hw; 7613d0407baSopenharmony_ci const struct dphy_hw_drv_data *drv_data = hw->drv_data; 7623d0407baSopenharmony_ci const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges; 7633d0407baSopenharmony_ci int num_hsfreq_ranges = drv_data->num_hsfreq_ranges; 7643d0407baSopenharmony_ci int i, hsfreq = 0; 7653d0407baSopenharmony_ci u32 sot_sync = 0; 7663d0407baSopenharmony_ci 7673d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 7683d0407baSopenharmony_ci hsfreq_ranges = drv_data->hsfreq_ranges; 7693d0407baSopenharmony_ci num_hsfreq_ranges = drv_data->num_hsfreq_ranges; 7703d0407baSopenharmony_ci sot_sync = 0x03; 7713d0407baSopenharmony_ci } else if (sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { 7723d0407baSopenharmony_ci hsfreq_ranges = drv_data->hsfreq_ranges_cphy; 7733d0407baSopenharmony_ci num_hsfreq_ranges = drv_data->num_hsfreq_ranges_cphy; 7743d0407baSopenharmony_ci sot_sync = 0x32; 7753d0407baSopenharmony_ci } 7763d0407baSopenharmony_ci 7773d0407baSopenharmony_ci mutex_lock(&hw->mutex); 7783d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { 7793d0407baSopenharmony_ci write_grf_reg(hw, GRF_CPHY_MODE, 0x9); 7803d0407baSopenharmony_ci } 7813d0407baSopenharmony_ci 7823d0407baSopenharmony_ci if (hw->rsts_bulk) { 7833d0407baSopenharmony_ci reset_control_assert(hw->rsts_bulk); 7843d0407baSopenharmony_ci } 7853d0407baSopenharmony_ci 7863d0407baSopenharmony_ci /* clk settle fix to 0x301 */ 7873d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 7883d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK_THS_SETTLE, 0x301); 7893d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_S0C_GNR_CON1, 0x1450); 7903d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_COMBO_S0D0_GNR_CON1, 0x1450); 7913d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_COMBO_S0D1_GNR_CON1, 0x1450); 7923d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_COMBO_S0D2_GNR_CON1, 0x1450); 7933d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_S0D3_GNR_CON1, 0x1450); 7943d0407baSopenharmony_ci } 7953d0407baSopenharmony_ci /* set data lane */ 7963d0407baSopenharmony_ci for (i = 0; i < num_hsfreq_ranges; i++) { 7973d0407baSopenharmony_ci if (hsfreq_ranges[i].range_h >= dphy->data_rate_mbps) { 7983d0407baSopenharmony_ci hsfreq = hsfreq_ranges[i].cfg_bit; 7993d0407baSopenharmony_ci break; 8003d0407baSopenharmony_ci } 8013d0407baSopenharmony_ci } 8023d0407baSopenharmony_ci 8033d0407baSopenharmony_ci if (i == num_hsfreq_ranges) { 8043d0407baSopenharmony_ci i = num_hsfreq_ranges - 1; 8053d0407baSopenharmony_ci dev_warn(dphy->dev, "data rate: %lld mbps, max support %d mbps", dphy->data_rate_mbps, 8063d0407baSopenharmony_ci hsfreq_ranges[i].range_h + 1); 8073d0407baSopenharmony_ci hsfreq = hsfreq_ranges[i].cfg_bit; 8083d0407baSopenharmony_ci } 8093d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 8103d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE0_THS_SETTLE, hsfreq, 0x1ff); 8113d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE0_ERR_SOT_SYNC, sot_sync, 0xff); 8123d0407baSopenharmony_ci } 8133d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 8143d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE1_THS_SETTLE, hsfreq, 0x1ff); 8153d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE1_ERR_SOT_SYNC, sot_sync, 0xff); 8163d0407baSopenharmony_ci } 8173d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 8183d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE2_THS_SETTLE, hsfreq, 0x1ff); 8193d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE2_ERR_SOT_SYNC, sot_sync, 0xff); 8203d0407baSopenharmony_ci } 8213d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 8223d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE3_THS_SETTLE, hsfreq, 0x1ff); 8233d0407baSopenharmony_ci write_csi2_dphy_reg_mask(hw, CSI2PHY_LANE3_ERR_SOT_SYNC, sot_sync, 0xff); 8243d0407baSopenharmony_ci } 8253d0407baSopenharmony_ci 8263d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 8273d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK_LANE_ENABLE, BIT(0)); 8283d0407baSopenharmony_ci } 8293d0407baSopenharmony_ci 8303d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 8313d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE0_ENABLE, BIT(0)); 8323d0407baSopenharmony_ci } 8333d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 8343d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE1_ENABLE, BIT(0)); 8353d0407baSopenharmony_ci } 8363d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 8373d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE2_ENABLE, BIT(0)); 8383d0407baSopenharmony_ci } 8393d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 8403d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE3_ENABLE, BIT(0)); 8413d0407baSopenharmony_ci } 8423d0407baSopenharmony_ci 8433d0407baSopenharmony_ci /* wait for clk lane ready */ 8443d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 8453d0407baSopenharmony_ci if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_CLK_LANE_ENABLE)) { 8463d0407baSopenharmony_ci goto out_streamon; 8473d0407baSopenharmony_ci } 8483d0407baSopenharmony_ci } 8493d0407baSopenharmony_ci 8503d0407baSopenharmony_ci /* wait for data lane ready */ 8513d0407baSopenharmony_ci if (sensor->lanes > 0) { 8523d0407baSopenharmony_ci if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE0_ENABLE)) { 8533d0407baSopenharmony_ci goto out_streamon; 8543d0407baSopenharmony_ci } 8553d0407baSopenharmony_ci } 8563d0407baSopenharmony_ci if (sensor->lanes > 1) { 8573d0407baSopenharmony_ci if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE1_ENABLE)) { 8583d0407baSopenharmony_ci goto out_streamon; 8593d0407baSopenharmony_ci } 8603d0407baSopenharmony_ci } 8613d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 8623d0407baSopenharmony_ci if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE2_ENABLE)) { 8633d0407baSopenharmony_ci goto out_streamon; 8643d0407baSopenharmony_ci } 8653d0407baSopenharmony_ci } 8663d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 8673d0407baSopenharmony_ci if (csi_dcphy_wait_lane_prepare(hw, CSI2PHY_DATA_LANE3_ENABLE)) { 8683d0407baSopenharmony_ci goto out_streamon; 8693d0407baSopenharmony_ci } 8703d0407baSopenharmony_ci } 8713d0407baSopenharmony_ci 8723d0407baSopenharmony_ci if (hw->rsts_bulk) { 8733d0407baSopenharmony_ci reset_control_deassert(hw->rsts_bulk); 8743d0407baSopenharmony_ci } 8753d0407baSopenharmony_ci atomic_inc(&hw->stream_cnt); 8763d0407baSopenharmony_ci 8773d0407baSopenharmony_ci mutex_unlock(&hw->mutex); 8783d0407baSopenharmony_ci 8793d0407baSopenharmony_ci return 0; 8803d0407baSopenharmony_ciout_streamon: 8813d0407baSopenharmony_ci if (hw->rsts_bulk) { 8823d0407baSopenharmony_ci reset_control_deassert(hw->rsts_bulk); 8833d0407baSopenharmony_ci } 8843d0407baSopenharmony_ci mutex_unlock(&hw->mutex); 8853d0407baSopenharmony_ci dev_err(dphy->dev, "stream on error\n"); 8863d0407baSopenharmony_ci return -EINVAL; 8873d0407baSopenharmony_ci} 8883d0407baSopenharmony_ci 8893d0407baSopenharmony_cistatic int csi2_dcphy_hw_stream_off(struct csi2_dphy *dphy, struct v4l2_subdev *sd) 8903d0407baSopenharmony_ci{ 8913d0407baSopenharmony_ci struct csi2_dphy_hw *hw = dphy->dphy_hw; 8923d0407baSopenharmony_ci struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); 8933d0407baSopenharmony_ci struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd); 8943d0407baSopenharmony_ci 8953d0407baSopenharmony_ci if (atomic_dec_return(&hw->stream_cnt)) { 8963d0407baSopenharmony_ci return 0; 8973d0407baSopenharmony_ci } 8983d0407baSopenharmony_ci 8993d0407baSopenharmony_ci mutex_lock(&hw->mutex); 9003d0407baSopenharmony_ci if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) { 9013d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_CLK_LANE_ENABLE, 0); 9023d0407baSopenharmony_ci } 9033d0407baSopenharmony_ci if (sensor->lanes > 0x00) { 9043d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE0_ENABLE, 0); 9053d0407baSopenharmony_ci } 9063d0407baSopenharmony_ci if (sensor->lanes > 0x01) { 9073d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE1_ENABLE, 0); 9083d0407baSopenharmony_ci } 9093d0407baSopenharmony_ci if (sensor->lanes > 0x02) { 9103d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE2_ENABLE, 0); 9113d0407baSopenharmony_ci } 9123d0407baSopenharmony_ci if (sensor->lanes > 0x03) { 9133d0407baSopenharmony_ci write_csi2_dphy_reg(hw, CSI2PHY_DATA_LANE3_ENABLE, 0); 9143d0407baSopenharmony_ci } 9153d0407baSopenharmony_ci 9163d0407baSopenharmony_ci usleep_range(0x1F4, 0x3E8); 9173d0407baSopenharmony_ci 9183d0407baSopenharmony_ci mutex_unlock(&hw->mutex); 9193d0407baSopenharmony_ci 9203d0407baSopenharmony_ci return 0; 9213d0407baSopenharmony_ci} 9223d0407baSopenharmony_ci 9233d0407baSopenharmony_cistatic void rk3568_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) 9243d0407baSopenharmony_ci{ 9253d0407baSopenharmony_ci hw->grf_regs = rk3568_grf_dphy_regs; 9263d0407baSopenharmony_ci} 9273d0407baSopenharmony_ci 9283d0407baSopenharmony_cistatic void rk3588_csi2_dphy_hw_individual_init(struct csi2_dphy_hw *hw) 9293d0407baSopenharmony_ci{ 9303d0407baSopenharmony_ci hw->grf_regs = rk3588_grf_dphy_regs; 9313d0407baSopenharmony_ci} 9323d0407baSopenharmony_ci 9333d0407baSopenharmony_cistatic void rk3588_csi2_dcphy_hw_individual_init(struct csi2_dphy_hw *hw) 9343d0407baSopenharmony_ci{ 9353d0407baSopenharmony_ci hw->grf_regs = rk3588_grf_dcphy_regs; 9363d0407baSopenharmony_ci} 9373d0407baSopenharmony_ci 9383d0407baSopenharmony_cistatic const struct dphy_hw_drv_data rk3568_csi2_dphy_hw_drv_data = { 9393d0407baSopenharmony_ci .hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges, 9403d0407baSopenharmony_ci .num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges), 9413d0407baSopenharmony_ci .csi2dphy_regs = rk3568_csi2dphy_regs, 9423d0407baSopenharmony_ci .grf_regs = rk3568_grf_dphy_regs, 9433d0407baSopenharmony_ci .individual_init = rk3568_csi2_dphy_hw_individual_init, 9443d0407baSopenharmony_ci .chip_id = CHIP_ID_RK3568, 9453d0407baSopenharmony_ci .stream_on = csi2_dphy_hw_stream_on, 9463d0407baSopenharmony_ci .stream_off = csi2_dphy_hw_stream_off, 9473d0407baSopenharmony_ci}; 9483d0407baSopenharmony_ci 9493d0407baSopenharmony_cistatic const struct dphy_hw_drv_data rk3588_csi2_dphy_hw_drv_data = { 9503d0407baSopenharmony_ci .hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges, 9513d0407baSopenharmony_ci .num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges), 9523d0407baSopenharmony_ci .csi2dphy_regs = rk3588_csi2dphy_regs, 9533d0407baSopenharmony_ci .grf_regs = rk3588_grf_dphy_regs, 9543d0407baSopenharmony_ci .individual_init = rk3588_csi2_dphy_hw_individual_init, 9553d0407baSopenharmony_ci .chip_id = CHIP_ID_RK3588, 9563d0407baSopenharmony_ci .stream_on = csi2_dphy_hw_stream_on, 9573d0407baSopenharmony_ci .stream_off = csi2_dphy_hw_stream_off, 9583d0407baSopenharmony_ci}; 9593d0407baSopenharmony_ci 9603d0407baSopenharmony_cistatic const struct dphy_hw_drv_data rk3588_csi2_dcphy_hw_drv_data = { 9613d0407baSopenharmony_ci .hsfreq_ranges = rk3588_csi2_dcphy_d_hw_hsfreq_ranges, 9623d0407baSopenharmony_ci .num_hsfreq_ranges = ARRAY_SIZE(rk3588_csi2_dcphy_d_hw_hsfreq_ranges), 9633d0407baSopenharmony_ci .hsfreq_ranges_cphy = rk3588_csi2_dcphy_c_hw_hsfreq_ranges, 9643d0407baSopenharmony_ci .num_hsfreq_ranges_cphy = ARRAY_SIZE(rk3588_csi2_dcphy_c_hw_hsfreq_ranges), 9653d0407baSopenharmony_ci .csi2dphy_regs = rk3588_csi2dcphy_regs, 9663d0407baSopenharmony_ci .grf_regs = rk3588_grf_dcphy_regs, 9673d0407baSopenharmony_ci .individual_init = rk3588_csi2_dcphy_hw_individual_init, 9683d0407baSopenharmony_ci .chip_id = CHIP_ID_RK3588_DCPHY, 9693d0407baSopenharmony_ci .stream_on = csi2_dcphy_hw_stream_on, 9703d0407baSopenharmony_ci .stream_off = csi2_dcphy_hw_stream_off, 9713d0407baSopenharmony_ci}; 9723d0407baSopenharmony_ci 9733d0407baSopenharmony_cistatic const struct of_device_id rockchip_csi2_dphy_hw_match_id[] = {{ 9743d0407baSopenharmony_ci .compatible = "rockchip,rk3568-csi2-dphy-hw", 9753d0407baSopenharmony_ci .data = &rk3568_csi2_dphy_hw_drv_data, 9763d0407baSopenharmony_ci}, { 9773d0407baSopenharmony_ci .compatible = "rockchip,rk3588-csi2-dphy-hw", 9783d0407baSopenharmony_ci .data = &rk3588_csi2_dphy_hw_drv_data, 9793d0407baSopenharmony_ci}, { 9803d0407baSopenharmony_ci .compatible = "rockchip,rk3588-csi2-dcphy-hw", 9813d0407baSopenharmony_ci .data = &rk3588_csi2_dcphy_hw_drv_data, 9823d0407baSopenharmony_ci}, { 9833d0407baSopenharmony_ci}}; 9843d0407baSopenharmony_ciMODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_hw_match_id); 9853d0407baSopenharmony_ci 9863d0407baSopenharmony_cistatic int rockchip_csi2_dphy_hw_probe(struct platform_device *pdev) 9873d0407baSopenharmony_ci{ 9883d0407baSopenharmony_ci struct device *dev = &pdev->dev; 9893d0407baSopenharmony_ci struct csi2_dphy_hw *dphy_hw; 9903d0407baSopenharmony_ci struct regmap *grf; 9913d0407baSopenharmony_ci struct resource *res; 9923d0407baSopenharmony_ci const struct of_device_id *of_id; 9933d0407baSopenharmony_ci const struct dphy_hw_drv_data *drv_data; 9943d0407baSopenharmony_ci 9953d0407baSopenharmony_ci dphy_hw = devm_kzalloc(dev, sizeof(*dphy_hw), GFP_KERNEL); 9963d0407baSopenharmony_ci if (!dphy_hw) { 9973d0407baSopenharmony_ci return -ENOMEM; 9983d0407baSopenharmony_ci } 9993d0407baSopenharmony_ci dphy_hw->dev = dev; 10003d0407baSopenharmony_ci 10013d0407baSopenharmony_ci of_id = of_match_device(rockchip_csi2_dphy_hw_match_id, dev); 10023d0407baSopenharmony_ci if (!of_id) { 10033d0407baSopenharmony_ci return -EINVAL; 10043d0407baSopenharmony_ci } 10053d0407baSopenharmony_ci 10063d0407baSopenharmony_ci drv_data = of_id->data; 10073d0407baSopenharmony_ci 10083d0407baSopenharmony_ci grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); 10093d0407baSopenharmony_ci if (IS_ERR(grf)) { 10103d0407baSopenharmony_ci dev_err(dev, "Can't find GRF syscon\n"); 10113d0407baSopenharmony_ci return -ENODEV; 10123d0407baSopenharmony_ci } 10133d0407baSopenharmony_ci dphy_hw->regmap_grf = grf; 10143d0407baSopenharmony_ci 10153d0407baSopenharmony_ci if (drv_data->chip_id == CHIP_ID_RK3588) { 10163d0407baSopenharmony_ci grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,sys_grf"); 10173d0407baSopenharmony_ci if (IS_ERR(grf)) { 10183d0407baSopenharmony_ci dev_err(dev, "Can't find SYS GRF syscon\n"); 10193d0407baSopenharmony_ci return -ENODEV; 10203d0407baSopenharmony_ci } 10213d0407baSopenharmony_ci dphy_hw->regmap_sys_grf = grf; 10223d0407baSopenharmony_ci } 10233d0407baSopenharmony_ci 10243d0407baSopenharmony_ci dphy_hw->num_clks = devm_clk_bulk_get_all(dev, &dphy_hw->clks_bulk); 10253d0407baSopenharmony_ci if (dphy_hw->num_clks < 0) { 10263d0407baSopenharmony_ci dev_err(dev, "failed to get csi2 clks\n"); 10273d0407baSopenharmony_ci } 10283d0407baSopenharmony_ci 10293d0407baSopenharmony_ci dphy_hw->rsts_bulk = devm_reset_control_array_get_optional_exclusive(dev); 10303d0407baSopenharmony_ci if (IS_ERR(dphy_hw->rsts_bulk)) { 10313d0407baSopenharmony_ci dev_err_probe(dev, PTR_ERR(dphy_hw->rsts_bulk), "failed to get dphy reset\n"); 10323d0407baSopenharmony_ci } 10333d0407baSopenharmony_ci 10343d0407baSopenharmony_ci dphy_hw->dphy_dev_num = 0; 10353d0407baSopenharmony_ci dphy_hw->drv_data = drv_data; 10363d0407baSopenharmony_ci dphy_hw->lane_mode = LANE_MODE_UNDEF; 10373d0407baSopenharmony_ci dphy_hw->grf_regs = drv_data->grf_regs; 10383d0407baSopenharmony_ci dphy_hw->txrx_regs = drv_data->txrx_regs; 10393d0407baSopenharmony_ci dphy_hw->csi2dphy_regs = drv_data->csi2dphy_regs; 10403d0407baSopenharmony_ci 10413d0407baSopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10423d0407baSopenharmony_ci dphy_hw->hw_base_addr = devm_ioremap_resource(dev, res); 10433d0407baSopenharmony_ci if (IS_ERR(dphy_hw->hw_base_addr)) { 10443d0407baSopenharmony_ci resource_size_t offset = res->start; 10453d0407baSopenharmony_ci resource_size_t size = resource_size(res); 10463d0407baSopenharmony_ci 10473d0407baSopenharmony_ci dphy_hw->hw_base_addr = devm_ioremap(dev, offset, size); 10483d0407baSopenharmony_ci if (IS_ERR(dphy_hw->hw_base_addr)) { 10493d0407baSopenharmony_ci dev_err(dev, "Can't find csi2 dphy hw addr!\n"); 10503d0407baSopenharmony_ci return -ENODEV; 10513d0407baSopenharmony_ci } 10523d0407baSopenharmony_ci } 10533d0407baSopenharmony_ci dphy_hw->stream_on = drv_data->stream_on; 10543d0407baSopenharmony_ci dphy_hw->stream_off = drv_data->stream_off; 10553d0407baSopenharmony_ci 10563d0407baSopenharmony_ci atomic_set(&dphy_hw->stream_cnt, 0); 10573d0407baSopenharmony_ci 10583d0407baSopenharmony_ci mutex_init(&dphy_hw->mutex); 10593d0407baSopenharmony_ci 10603d0407baSopenharmony_ci platform_set_drvdata(pdev, dphy_hw); 10613d0407baSopenharmony_ci 10623d0407baSopenharmony_ci pm_runtime_enable(&pdev->dev); 10633d0407baSopenharmony_ci 10643d0407baSopenharmony_ci dev_info(dev, "csi2 dphy hw probe successfully!\n"); 10653d0407baSopenharmony_ci 10663d0407baSopenharmony_ci return 0; 10673d0407baSopenharmony_ci} 10683d0407baSopenharmony_ci 10693d0407baSopenharmony_cistatic int rockchip_csi2_dphy_hw_remove(struct platform_device *pdev) 10703d0407baSopenharmony_ci{ 10713d0407baSopenharmony_ci struct csi2_dphy_hw *hw = platform_get_drvdata(pdev); 10723d0407baSopenharmony_ci 10733d0407baSopenharmony_ci pm_runtime_disable(&pdev->dev); 10743d0407baSopenharmony_ci mutex_destroy(&hw->mutex); 10753d0407baSopenharmony_ci 10763d0407baSopenharmony_ci return 0; 10773d0407baSopenharmony_ci} 10783d0407baSopenharmony_ci 10793d0407baSopenharmony_cistatic struct platform_driver rockchip_csi2_dphy_hw_driver = { 10803d0407baSopenharmony_ci .probe = rockchip_csi2_dphy_hw_probe, 10813d0407baSopenharmony_ci .remove = rockchip_csi2_dphy_hw_remove, 10823d0407baSopenharmony_ci .driver = 10833d0407baSopenharmony_ci { 10843d0407baSopenharmony_ci .name = "rockchip-csi2-dphy-hw", 10853d0407baSopenharmony_ci .of_match_table = rockchip_csi2_dphy_hw_match_id, 10863d0407baSopenharmony_ci }, 10873d0407baSopenharmony_ci}; 10883d0407baSopenharmony_cimodule_platform_driver(rockchip_csi2_dphy_hw_driver); 10893d0407baSopenharmony_ci 10903d0407baSopenharmony_ciMODULE_AUTHOR("Rockchip Camera/ISP team"); 10913d0407baSopenharmony_ciMODULE_DESCRIPTION("Rockchip MIPI CSI2 DPHY HW driver"); 10923d0407baSopenharmony_ciMODULE_LICENSE("GPL v2"); 1093