185e15df9SWyon Bi /*
285e15df9SWyon Bi * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
385e15df9SWyon Bi *
485e15df9SWyon Bi * SPDX-License-Identifier: GPL-2.0+
585e15df9SWyon Bi */
685e15df9SWyon Bi
785e15df9SWyon Bi #include <config.h>
885e15df9SWyon Bi #include <common.h>
985e15df9SWyon Bi #include <errno.h>
1085e15df9SWyon Bi #include <malloc.h>
1185e15df9SWyon Bi #include <asm/unaligned.h>
1285e15df9SWyon Bi #include <asm/io.h>
1385e15df9SWyon Bi #include <linux/list.h>
1485e15df9SWyon Bi #include <div64.h>
1585e15df9SWyon Bi #include <dm/device.h>
1685e15df9SWyon Bi #include <dm/read.h>
1785e15df9SWyon Bi #include <dm/uclass.h>
1885e15df9SWyon Bi #include <dm/uclass-id.h>
1985e15df9SWyon Bi
2085e15df9SWyon Bi #include "rockchip_phy.h"
2185e15df9SWyon Bi
2285e15df9SWyon Bi #define NSEC_PER_USEC 1000L
2385e15df9SWyon Bi #define USEC_PER_SEC 1000000L
2485e15df9SWyon Bi #define NSEC_PER_SEC 1000000000L
2585e15df9SWyon Bi
2685e15df9SWyon Bi #define UPDATE(v, h, l) (((v) << (l)) & GENMASK((h), (l)))
2785e15df9SWyon Bi
2885e15df9SWyon Bi /* Innosilicon MIPI D-PHY registers */
2927d50ce7SNickey Yang #define INNO_PHY_LANE_CTRL 0x0000
3085e15df9SWyon Bi #define MIPI_BGPD BIT(7)
3185e15df9SWyon Bi #define CLK_LANE_EN_MASK BIT(6)
3285e15df9SWyon Bi #define DATA_LANE_3_EN_MASK BIT(5)
3385e15df9SWyon Bi #define DATA_LANE_2_EN_MASK BIT(4)
3485e15df9SWyon Bi #define DATA_LANE_1_EN_MASK BIT(3)
3585e15df9SWyon Bi #define DATA_LANE_0_EN_MASK BIT(2)
3685e15df9SWyon Bi #define CLK_LANE_EN BIT(6)
3785e15df9SWyon Bi #define DATA_LANE_3_EN BIT(5)
3885e15df9SWyon Bi #define DATA_LANE_2_EN BIT(4)
3985e15df9SWyon Bi #define DATA_LANE_1_EN BIT(3)
4085e15df9SWyon Bi #define DATA_LANE_0_EN BIT(2)
4185e15df9SWyon Bi #define PWROK_BP BIT(1)
4285e15df9SWyon Bi #define PWROK BIT(0)
4327d50ce7SNickey Yang #define INNO_PHY_POWER_CTRL 0x0004
4485e15df9SWyon Bi #define ANALOG_RESET_MASK BIT(2)
4585e15df9SWyon Bi #define ANALOG_RESET BIT(2)
4685e15df9SWyon Bi #define ANALOG_NORMAL 0
4785e15df9SWyon Bi #define LDO_POWER_MASK BIT(1)
4885e15df9SWyon Bi #define LDO_POWER_DOWN BIT(1)
4985e15df9SWyon Bi #define LDO_POWER_ON 0
5085e15df9SWyon Bi #define PLL_POWER_MASK BIT(0)
5185e15df9SWyon Bi #define PLL_POWER_DOWN BIT(0)
5285e15df9SWyon Bi #define PLL_POWER_ON 0
5327d50ce7SNickey Yang #define INNO_PHY_PLL_CTRL_0 0x000c
5485e15df9SWyon Bi #define FBDIV_HI_MASK BIT(5)
5585e15df9SWyon Bi #define FBDIV_HI(x) UPDATE(x, 5, 5)
5685e15df9SWyon Bi #define PREDIV_MASK GENMASK(4, 0)
5785e15df9SWyon Bi #define PREDIV(x) UPDATE(x, 4, 0)
5827d50ce7SNickey Yang #define INNO_PHY_PLL_CTRL_1 0x0010
5985e15df9SWyon Bi #define FBDIV_LO_MASK GENMASK(7, 0)
6085e15df9SWyon Bi #define FBDIV_LO(x) UPDATE(x, 7, 0)
6127d50ce7SNickey Yang #define ANALOG_REG_08 0x0020
6227d50ce7SNickey Yang #define PRE_EMPHASIS_ENABLE_MASK BIT(7)
6327d50ce7SNickey Yang #define PRE_EMPHASIS_ENABLE BIT(7)
6427d50ce7SNickey Yang #define PRE_EMPHASIS_DISABLE 0
6527d50ce7SNickey Yang #define PLL_POST_DIV_ENABLE_MASK BIT(5)
6627d50ce7SNickey Yang #define PLL_POST_DIV_ENABLE BIT(5)
6727d50ce7SNickey Yang #define PLL_POST_DIV_DISABLE 0
6827d50ce7SNickey Yang #define DATA_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
6927d50ce7SNickey Yang #define DATA_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
7027d50ce7SNickey Yang #define ANALOG_REG_0B 0x002c
7127d50ce7SNickey Yang #define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
7227d50ce7SNickey Yang #define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
7327d50ce7SNickey Yang #define VOD_MIN_RANGE 0x1
7427d50ce7SNickey Yang #define VOD_MID_RANGE 0x3
7527d50ce7SNickey Yang #define VOD_BIG_RANGE 0x7
7627d50ce7SNickey Yang #define VOD_MAX_RANGE 0xf
776ab2ca6dSHongming Zou #define RK3506_VOD_MIN_RANGE 0x8
786ab2ca6dSHongming Zou #define RK3506_VOD_MID_RANGE 0xc
796ab2ca6dSHongming Zou #define RK3506_VOD_BIG_RANGE 0xe
806ab2ca6dSHongming Zou #define RK3506_VOD_MAX_RANGE 0xf
816ab2ca6dSHongming Zou #define RK3506_PRE_EMPHASIS 0x0060
826ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_ENABLE_MASK BIT(6)
836ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_ENABLE BIT(6)
846ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_DISABLE 0
856ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_ENABLE_MASK BIT(5)
866ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_ENABLE BIT(5)
876ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_DISABLE 0
886ab2ca6dSHongming Zou #define PRE_EMPHASIS_RANGE 0x0064
896ab2ca6dSHongming Zou #define PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6)
906ab2ca6dSHongming Zou #define PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6)
916ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_RANGE 0x0068
926ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6)
936ab2ca6dSHongming Zou #define LANE0_PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6)
946ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_RANGE 0x006c
956ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_RANGE_SET_MASK GENMASK(7, 6)
966ab2ca6dSHongming Zou #define LANE1_PRE_EMPHASIS_RANGE_SET(x) UPDATE(x, 7, 6)
976ab2ca6dSHongming Zou #define PRE_EMPHASIS_MIN_RANGE 0x0
986ab2ca6dSHongming Zou #define PRE_EMPHASIS_MID_RANGE 0x1
996ab2ca6dSHongming Zou #define PRE_EMPHASIS_MAX_RANGE 0x2
1006ab2ca6dSHongming Zou #define PRE_EMPHASIS_RESERVED_RANGE 0x3
10127d50ce7SNickey Yang #define INNO_PHY_DIG_CTRL 0x0080
10285e15df9SWyon Bi #define DIGITAL_RESET_MASK BIT(0)
10385e15df9SWyon Bi #define DIGITAL_NORMAL BIT(0)
10485e15df9SWyon Bi #define DIGITAL_RESET 0
1058697aa74SHongming Zou #define INNO_PHY_MODE_CTRL 0x038c
1068697aa74SHongming Zou #define MIPI_MODE_ENABLE BIT(0)
10727d50ce7SNickey Yang #define INNO_PHY_LVDS_CTRL 0x03ac
10885e15df9SWyon Bi #define LVDS_BGPD BIT(0)
10985e15df9SWyon Bi
11027d50ce7SNickey Yang #define INNO_CLOCK_LANE_REG_BASE 0x0100
11127d50ce7SNickey Yang #define INNO_DATA_LANE_0_REG_BASE 0x0180
11227d50ce7SNickey Yang #define INNO_DATA_LANE_1_REG_BASE 0x0200
11327d50ce7SNickey Yang #define INNO_DATA_LANE_2_REG_BASE 0x0280
11427d50ce7SNickey Yang #define INNO_DATA_LANE_3_REG_BASE 0x0300
11585e15df9SWyon Bi
11627d50ce7SNickey Yang #define T_LPX_OFFSET 0x0014
11727d50ce7SNickey Yang #define T_HS_PREPARE_OFFSET 0x0018
11827d50ce7SNickey Yang #define T_HS_ZERO_OFFSET 0x001c
11927d50ce7SNickey Yang #define T_HS_TRAIL_OFFSET 0x0020
12027d50ce7SNickey Yang #define T_HS_EXIT_OFFSET 0x0024
12127d50ce7SNickey Yang #define T_CLK_POST_OFFSET 0x0028
122ecc8aa5aSNickey Yang #define T_CLK_POST_OFFSET_H 0x0040
12327d50ce7SNickey Yang #define T_WAKUP_H_OFFSET 0x0030
12427d50ce7SNickey Yang #define T_WAKUP_L_OFFSET 0x0034
12527d50ce7SNickey Yang #define T_CLK_PRE_OFFSET 0x0038
12627d50ce7SNickey Yang #define T_TA_GO_OFFSET 0x0040
12727d50ce7SNickey Yang #define T_TA_SURE_OFFSET 0x0044
12827d50ce7SNickey Yang #define T_TA_WAIT_OFFSET 0x0048
12985e15df9SWyon Bi
13085e15df9SWyon Bi #define T_LPX_MASK GENMASK(5, 0)
13185e15df9SWyon Bi #define T_LPX(x) UPDATE(x, 5, 0)
13285e15df9SWyon Bi #define T_HS_PREPARE_MASK GENMASK(6, 0)
13385e15df9SWyon Bi #define T_HS_PREPARE(x) UPDATE(x, 6, 0)
13485e15df9SWyon Bi #define T_HS_ZERO_MASK GENMASK(5, 0)
13585e15df9SWyon Bi #define T_HS_ZERO(x) UPDATE(x, 5, 0)
13685e15df9SWyon Bi #define T_HS_TRAIL_MASK GENMASK(6, 0)
13785e15df9SWyon Bi #define T_HS_TRAIL(x) UPDATE(x, 6, 0)
13885e15df9SWyon Bi #define T_HS_EXIT_MASK GENMASK(4, 0)
13985e15df9SWyon Bi #define T_HS_EXIT(x) UPDATE(x, 4, 0)
14085e15df9SWyon Bi #define T_CLK_POST_MASK GENMASK(3, 0)
14185e15df9SWyon Bi #define T_CLK_POST(x) UPDATE(x, 3, 0)
142ecc8aa5aSNickey Yang #define T_CLK_POST_HI_MASK GENMASK(7, 6)
143ecc8aa5aSNickey Yang #define T_CLK_POST_HI(x) UPDATE(x, 7, 6)
14485e15df9SWyon Bi #define T_WAKUP_H_MASK GENMASK(1, 0)
14585e15df9SWyon Bi #define T_WAKUP_H(x) UPDATE(x, 1, 0)
14685e15df9SWyon Bi #define T_WAKUP_L_MASK GENMASK(7, 0)
14785e15df9SWyon Bi #define T_WAKUP_L(x) UPDATE(x, 7, 0)
14885e15df9SWyon Bi #define T_CLK_PRE_MASK GENMASK(3, 0)
14985e15df9SWyon Bi #define T_CLK_PRE(x) UPDATE(x, 3, 0)
15085e15df9SWyon Bi #define T_TA_GO_MASK GENMASK(5, 0)
15185e15df9SWyon Bi #define T_TA_GO(x) UPDATE(x, 5, 0)
15285e15df9SWyon Bi #define T_TA_SURE_MASK GENMASK(5, 0)
15385e15df9SWyon Bi #define T_TA_SURE(x) UPDATE(x, 5, 0)
15485e15df9SWyon Bi #define T_TA_WAIT_MASK GENMASK(5, 0)
15585e15df9SWyon Bi #define T_TA_WAIT(x) UPDATE(x, 5, 0)
15685e15df9SWyon Bi
15727d50ce7SNickey Yang enum soc_type {
15827d50ce7SNickey Yang RV1108_MIPI_DPHY,
15927d50ce7SNickey Yang RK1808_MIPI_DPHY,
1606ab2ca6dSHongming Zou RK3506_MIPI_DPHY,
16127d50ce7SNickey Yang };
16227d50ce7SNickey Yang
16385e15df9SWyon Bi enum lane_type {
16485e15df9SWyon Bi CLOCK_LANE,
16585e15df9SWyon Bi DATA_LANE_0,
16685e15df9SWyon Bi DATA_LANE_1,
16785e15df9SWyon Bi DATA_LANE_2,
16885e15df9SWyon Bi DATA_LANE_3,
16985e15df9SWyon Bi };
17085e15df9SWyon Bi
17185e15df9SWyon Bi struct mipi_dphy_timing {
17285e15df9SWyon Bi unsigned int clkmiss;
17385e15df9SWyon Bi unsigned int clkpost;
17485e15df9SWyon Bi unsigned int clkpre;
17585e15df9SWyon Bi unsigned int clkprepare;
17685e15df9SWyon Bi unsigned int clksettle;
17785e15df9SWyon Bi unsigned int clktermen;
17885e15df9SWyon Bi unsigned int clktrail;
17985e15df9SWyon Bi unsigned int clkzero;
18085e15df9SWyon Bi unsigned int dtermen;
18185e15df9SWyon Bi unsigned int eot;
18285e15df9SWyon Bi unsigned int hsexit;
18385e15df9SWyon Bi unsigned int hsprepare;
18485e15df9SWyon Bi unsigned int hszero;
18585e15df9SWyon Bi unsigned int hssettle;
18685e15df9SWyon Bi unsigned int hsskip;
18785e15df9SWyon Bi unsigned int hstrail;
18885e15df9SWyon Bi unsigned int init;
18985e15df9SWyon Bi unsigned int lpx;
19085e15df9SWyon Bi unsigned int taget;
19185e15df9SWyon Bi unsigned int tago;
19285e15df9SWyon Bi unsigned int tasure;
19385e15df9SWyon Bi unsigned int wakeup;
19485e15df9SWyon Bi };
19585e15df9SWyon Bi
19685e15df9SWyon Bi struct inno_mipi_dphy_timing {
19785e15df9SWyon Bi u8 lpx;
19885e15df9SWyon Bi u8 hs_prepare;
19985e15df9SWyon Bi u8 hs_zero;
20085e15df9SWyon Bi u8 hs_trail;
20185e15df9SWyon Bi u8 hs_exit;
20285e15df9SWyon Bi u8 clk_post;
20385e15df9SWyon Bi u8 wakup_h;
20485e15df9SWyon Bi u8 wakup_l;
20585e15df9SWyon Bi u8 clk_pre;
20685e15df9SWyon Bi u8 ta_go;
20785e15df9SWyon Bi u8 ta_sure;
20885e15df9SWyon Bi u8 ta_wait;
20985e15df9SWyon Bi };
21085e15df9SWyon Bi
21185e15df9SWyon Bi struct inno_mipi_dphy {
21285e15df9SWyon Bi struct udevice *dev;
21385e15df9SWyon Bi void __iomem *regs;
21485e15df9SWyon Bi unsigned int lane_mbps;
21585e15df9SWyon Bi int lanes;
21685e15df9SWyon Bi };
21785e15df9SWyon Bi
21885e15df9SWyon Bi static const u32 lane_reg_offset[] = {
21985e15df9SWyon Bi [CLOCK_LANE] = INNO_CLOCK_LANE_REG_BASE,
22085e15df9SWyon Bi [DATA_LANE_0] = INNO_DATA_LANE_0_REG_BASE,
22185e15df9SWyon Bi [DATA_LANE_1] = INNO_DATA_LANE_1_REG_BASE,
22285e15df9SWyon Bi [DATA_LANE_2] = INNO_DATA_LANE_2_REG_BASE,
22385e15df9SWyon Bi [DATA_LANE_3] = INNO_DATA_LANE_3_REG_BASE,
22485e15df9SWyon Bi };
22585e15df9SWyon Bi
226a3c5f2d5SNickey Yang #define FIXED_PARAM(_freq, _lpx, _prepare, _clk_zero, _data_zero, _trail) \
22785e15df9SWyon Bi { \
22885e15df9SWyon Bi .max_freq = _freq, \
229a3c5f2d5SNickey Yang .lpx = _lpx, \
23085e15df9SWyon Bi .hs_prepare = _prepare, \
23185e15df9SWyon Bi .clk_lane = { \
23285e15df9SWyon Bi .hs_zero = _clk_zero, \
23385e15df9SWyon Bi }, \
23485e15df9SWyon Bi .data_lane = { \
23585e15df9SWyon Bi .hs_zero = _data_zero, \
23685e15df9SWyon Bi }, \
23785e15df9SWyon Bi .hs_trail = _trail, \
23885e15df9SWyon Bi }
23985e15df9SWyon Bi
24085e15df9SWyon Bi struct fixed_param {
24185e15df9SWyon Bi unsigned int max_freq;
242a3c5f2d5SNickey Yang u8 lpx;
24385e15df9SWyon Bi u8 hs_prepare;
24485e15df9SWyon Bi struct {
24585e15df9SWyon Bi u8 hs_zero;
24685e15df9SWyon Bi } clk_lane;
24785e15df9SWyon Bi struct {
24885e15df9SWyon Bi u8 hs_zero;
24985e15df9SWyon Bi } data_lane;
25085e15df9SWyon Bi u8 hs_trail;
25185e15df9SWyon Bi };
25285e15df9SWyon Bi
25385e15df9SWyon Bi static const struct fixed_param fixed_param_table[] = {
254a3c5f2d5SNickey Yang FIXED_PARAM(110, 0x0, 0x20, 0x16, 0x02, 0x22),
255a3c5f2d5SNickey Yang FIXED_PARAM(150, 0x0, 0x06, 0x16, 0x03, 0x45),
256a3c5f2d5SNickey Yang FIXED_PARAM(200, 0x0, 0x18, 0x17, 0x04, 0x0b),
257a3c5f2d5SNickey Yang FIXED_PARAM(250, 0x0, 0x05, 0x17, 0x05, 0x16),
258a3c5f2d5SNickey Yang FIXED_PARAM(300, 0x0, 0x51, 0x18, 0x06, 0x2c),
259a3c5f2d5SNickey Yang FIXED_PARAM(400, 0x0, 0x64, 0x19, 0x07, 0x33),
260a3c5f2d5SNickey Yang FIXED_PARAM(500, 0x0, 0x20, 0x1b, 0x07, 0x4e),
261a3c5f2d5SNickey Yang FIXED_PARAM(600, 0x0, 0x6a, 0x1d, 0x08, 0x3a),
262a3c5f2d5SNickey Yang FIXED_PARAM(700, 0x0, 0x3e, 0x1e, 0x08, 0x6a),
263a3c5f2d5SNickey Yang FIXED_PARAM(800, 0x0, 0x21, 0x1f, 0x09, 0x29),
264a3c5f2d5SNickey Yang FIXED_PARAM(1000, 0x0, 0x09, 0x20, 0x09, 0x27)
26585e15df9SWyon Bi };
26685e15df9SWyon Bi
26727d50ce7SNickey Yang static const struct fixed_param rk1808_fixed_param_table[] = {
268a3c5f2d5SNickey Yang FIXED_PARAM(110, 0x02, 0x7f, 0x16, 0x02, 0x02),
269a3c5f2d5SNickey Yang FIXED_PARAM(150, 0x02, 0x7f, 0x16, 0x03, 0x02),
270a3c5f2d5SNickey Yang FIXED_PARAM(200, 0x02, 0x7f, 0x17, 0x04, 0x02),
271a3c5f2d5SNickey Yang FIXED_PARAM(250, 0x02, 0x7f, 0x17, 0x05, 0x04),
272a3c5f2d5SNickey Yang FIXED_PARAM(300, 0x02, 0x7f, 0x18, 0x06, 0x04),
273a3c5f2d5SNickey Yang FIXED_PARAM(400, 0x03, 0x7e, 0x19, 0x07, 0x04),
274a3c5f2d5SNickey Yang FIXED_PARAM(500, 0x03, 0x7c, 0x1b, 0x07, 0x08),
275a3c5f2d5SNickey Yang FIXED_PARAM(600, 0x03, 0x70, 0x1d, 0x08, 0x10),
276a3c5f2d5SNickey Yang FIXED_PARAM(700, 0x05, 0x40, 0x1e, 0x08, 0x30),
277a3c5f2d5SNickey Yang FIXED_PARAM(800, 0x05, 0x02, 0x1f, 0x09, 0x30),
278a3c5f2d5SNickey Yang FIXED_PARAM(1000, 0x05, 0x08, 0x20, 0x09, 0x30),
279a3c5f2d5SNickey Yang FIXED_PARAM(1400, 0x09, 0x03, 0x32, 0x14, 0x0f),
280a3c5f2d5SNickey Yang FIXED_PARAM(1600, 0x0d, 0x42, 0x36, 0x0e, 0x0f),
281a3c5f2d5SNickey Yang FIXED_PARAM(1800, 0x0e, 0x47, 0x7a, 0x0e, 0x0f),
282a3c5f2d5SNickey Yang FIXED_PARAM(2000, 0x11, 0x64, 0x7a, 0x0e, 0x0b),
28327d50ce7SNickey Yang };
28427d50ce7SNickey Yang
inno_write(struct inno_mipi_dphy * inno,u32 reg,u32 val)28585e15df9SWyon Bi static inline void inno_write(struct inno_mipi_dphy *inno, u32 reg, u32 val)
28685e15df9SWyon Bi {
28785e15df9SWyon Bi writel(val, inno->regs + reg);
28885e15df9SWyon Bi }
28985e15df9SWyon Bi
inno_read(struct inno_mipi_dphy * inno,u32 reg)29085e15df9SWyon Bi static inline u32 inno_read(struct inno_mipi_dphy *inno, u32 reg)
29185e15df9SWyon Bi {
29285e15df9SWyon Bi return readl(inno->regs + reg);
29385e15df9SWyon Bi }
29485e15df9SWyon Bi
inno_update_bits(struct inno_mipi_dphy * inno,u32 reg,u32 mask,u32 val)29585e15df9SWyon Bi static inline void inno_update_bits(struct inno_mipi_dphy *inno, u32 reg,
29685e15df9SWyon Bi u32 mask, u32 val)
29785e15df9SWyon Bi {
29885e15df9SWyon Bi u32 tmp, orig;
29985e15df9SWyon Bi
30085e15df9SWyon Bi orig = inno_read(inno, reg);
30185e15df9SWyon Bi tmp = orig & ~mask;
30285e15df9SWyon Bi tmp |= val & mask;
30385e15df9SWyon Bi inno_write(inno, reg, tmp);
30485e15df9SWyon Bi }
30585e15df9SWyon Bi
mipi_dphy_timing_get_default(struct mipi_dphy_timing * timing,unsigned long period)30685e15df9SWyon Bi static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
30785e15df9SWyon Bi unsigned long period)
30885e15df9SWyon Bi {
30985e15df9SWyon Bi /* Global Operation Timing Parameters */
31085e15df9SWyon Bi timing->clkmiss = 0;
31185e15df9SWyon Bi timing->clkpost = 70 + 52 * period;
31285e15df9SWyon Bi timing->clkpre = 8 * period;
31385e15df9SWyon Bi timing->clkprepare = 65;
31485e15df9SWyon Bi timing->clksettle = 95;
31585e15df9SWyon Bi timing->clktermen = 0;
31685e15df9SWyon Bi timing->clktrail = 80;
31785e15df9SWyon Bi timing->clkzero = 260;
31885e15df9SWyon Bi timing->dtermen = 0;
31985e15df9SWyon Bi timing->eot = 0;
32085e15df9SWyon Bi timing->hsexit = 120;
32185e15df9SWyon Bi timing->hsprepare = 65 + 4 * period;
32285e15df9SWyon Bi timing->hszero = 145 + 6 * period;
32385e15df9SWyon Bi timing->hssettle = 85 + 6 * period;
32485e15df9SWyon Bi timing->hsskip = 40;
32585e15df9SWyon Bi timing->hstrail = max(8 * period, 60 + 4 * period);
32685e15df9SWyon Bi timing->init = 100000;
32785e15df9SWyon Bi timing->lpx = 60;
32885e15df9SWyon Bi timing->taget = 5 * timing->lpx;
32985e15df9SWyon Bi timing->tago = 4 * timing->lpx;
33085e15df9SWyon Bi timing->tasure = 2 * timing->lpx;
33185e15df9SWyon Bi timing->wakeup = 1000000;
33285e15df9SWyon Bi }
33385e15df9SWyon Bi
inno_mipi_dphy_timing_update(struct inno_mipi_dphy * inno,enum lane_type lane_type,struct inno_mipi_dphy_timing * t)33485e15df9SWyon Bi static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno,
33585e15df9SWyon Bi enum lane_type lane_type,
33685e15df9SWyon Bi struct inno_mipi_dphy_timing *t)
33785e15df9SWyon Bi {
33885e15df9SWyon Bi u32 base = lane_reg_offset[lane_type];
33985e15df9SWyon Bi u32 m, v;
34085e15df9SWyon Bi
34185e15df9SWyon Bi m = T_HS_PREPARE_MASK;
34285e15df9SWyon Bi v = T_HS_PREPARE(t->hs_prepare);
34385e15df9SWyon Bi inno_update_bits(inno, base + T_HS_PREPARE_OFFSET, m, v);
34485e15df9SWyon Bi
34585e15df9SWyon Bi m = T_HS_ZERO_MASK;
34685e15df9SWyon Bi v = T_HS_ZERO(t->hs_zero);
34785e15df9SWyon Bi inno_update_bits(inno, base + T_HS_ZERO_OFFSET, m, v);
34885e15df9SWyon Bi
34985e15df9SWyon Bi m = T_HS_TRAIL_MASK;
35085e15df9SWyon Bi v = T_HS_TRAIL(t->hs_trail);
35185e15df9SWyon Bi inno_update_bits(inno, base + T_HS_TRAIL_OFFSET, m, v);
35285e15df9SWyon Bi
35385e15df9SWyon Bi m = T_HS_EXIT_MASK;
35485e15df9SWyon Bi v = T_HS_EXIT(t->hs_exit);
35585e15df9SWyon Bi inno_update_bits(inno, base + T_HS_EXIT_OFFSET, m, v);
35685e15df9SWyon Bi
35785e15df9SWyon Bi if (lane_type == CLOCK_LANE) {
35885e15df9SWyon Bi m = T_CLK_POST_MASK;
35985e15df9SWyon Bi v = T_CLK_POST(t->clk_post);
36085e15df9SWyon Bi inno_update_bits(inno, base + T_CLK_POST_OFFSET, m, v);
361ecc8aa5aSNickey Yang m = T_CLK_POST_HI_MASK;
362ecc8aa5aSNickey Yang v = T_CLK_POST_HI(t->clk_post >> 4);
363ecc8aa5aSNickey Yang inno_update_bits(inno, base + T_CLK_POST_OFFSET_H, m, v);
36485e15df9SWyon Bi m = T_CLK_PRE_MASK;
36585e15df9SWyon Bi v = T_CLK_PRE(t->clk_pre);
36685e15df9SWyon Bi inno_update_bits(inno, base + T_CLK_PRE_OFFSET, m, v);
36785e15df9SWyon Bi }
36885e15df9SWyon Bi
36985e15df9SWyon Bi m = T_WAKUP_H_MASK;
37085e15df9SWyon Bi v = T_WAKUP_H(t->wakup_h);
37185e15df9SWyon Bi inno_update_bits(inno, base + T_WAKUP_H_OFFSET, m, v);
37285e15df9SWyon Bi
37385e15df9SWyon Bi m = T_WAKUP_L_MASK;
37485e15df9SWyon Bi v = T_WAKUP_L(t->wakup_l);
37585e15df9SWyon Bi inno_update_bits(inno, base + T_WAKUP_L_OFFSET, m, v);
37685e15df9SWyon Bi
37785e15df9SWyon Bi m = T_LPX_MASK;
37885e15df9SWyon Bi v = T_LPX(t->lpx);
37985e15df9SWyon Bi inno_update_bits(inno, base + T_LPX_OFFSET, m, v);
38085e15df9SWyon Bi
38185e15df9SWyon Bi m = T_TA_GO_MASK;
38285e15df9SWyon Bi v = T_TA_GO(t->ta_go);
38385e15df9SWyon Bi inno_update_bits(inno, base + T_TA_GO_OFFSET, m, v);
38485e15df9SWyon Bi
38585e15df9SWyon Bi m = T_TA_SURE_MASK;
38685e15df9SWyon Bi v = T_TA_SURE(t->ta_sure);
38785e15df9SWyon Bi inno_update_bits(inno, base + T_TA_SURE_OFFSET, m, v);
38885e15df9SWyon Bi
38985e15df9SWyon Bi m = T_TA_WAIT_MASK;
39085e15df9SWyon Bi v = T_TA_WAIT(t->ta_wait);
39185e15df9SWyon Bi inno_update_bits(inno, base + T_TA_WAIT_OFFSET, m, v);
39285e15df9SWyon Bi }
39385e15df9SWyon Bi
inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing * t,unsigned int freq,enum soc_type soc_type,enum lane_type lane_type)39485e15df9SWyon Bi static void inno_mipi_dphy_get_fixed_param(struct inno_mipi_dphy_timing *t,
39585e15df9SWyon Bi unsigned int freq,
39627d50ce7SNickey Yang enum soc_type soc_type,
39785e15df9SWyon Bi enum lane_type lane_type)
39885e15df9SWyon Bi {
39927d50ce7SNickey Yang const struct fixed_param *param, *param_table;
40027d50ce7SNickey Yang int i, param_num;
40185e15df9SWyon Bi
402e57e55f8SHongming Zou if (soc_type == RK1808_MIPI_DPHY || soc_type == RK3506_MIPI_DPHY) {
40327d50ce7SNickey Yang param_table = rk1808_fixed_param_table;
40427d50ce7SNickey Yang param_num = ARRAY_SIZE(rk1808_fixed_param_table);
40527d50ce7SNickey Yang } else {
40627d50ce7SNickey Yang param_table = fixed_param_table;
40727d50ce7SNickey Yang param_num = ARRAY_SIZE(fixed_param_table);
40827d50ce7SNickey Yang }
40927d50ce7SNickey Yang
41027d50ce7SNickey Yang for (i = 0; i < param_num; i++)
41127d50ce7SNickey Yang if (freq <= param_table[i].max_freq)
41285e15df9SWyon Bi break;
41385e15df9SWyon Bi
41427d50ce7SNickey Yang if (i == param_num)
41585e15df9SWyon Bi --i;
41685e15df9SWyon Bi
41727d50ce7SNickey Yang param = ¶m_table[i];
41885e15df9SWyon Bi
41985e15df9SWyon Bi if (lane_type == CLOCK_LANE)
42085e15df9SWyon Bi t->hs_zero = param->clk_lane.hs_zero;
42185e15df9SWyon Bi else
42285e15df9SWyon Bi t->hs_zero = param->data_lane.hs_zero;
42385e15df9SWyon Bi
42485e15df9SWyon Bi t->hs_prepare = param->hs_prepare;
42585e15df9SWyon Bi t->hs_trail = param->hs_trail;
426a3c5f2d5SNickey Yang
427e57e55f8SHongming Zou if (soc_type == RK1808_MIPI_DPHY || soc_type == RK3506_MIPI_DPHY)
428a3c5f2d5SNickey Yang t->lpx = param->lpx;
42985e15df9SWyon Bi }
43085e15df9SWyon Bi
inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy * inno,enum lane_type lane_type)43185e15df9SWyon Bi static void inno_mipi_dphy_lane_timing_init(struct inno_mipi_dphy *inno,
43285e15df9SWyon Bi enum lane_type lane_type)
43385e15df9SWyon Bi {
43427d50ce7SNickey Yang struct rockchip_phy *phy =
43527d50ce7SNickey Yang (struct rockchip_phy *)dev_get_driver_data(inno->dev);
43685e15df9SWyon Bi struct mipi_dphy_timing timing;
43785e15df9SWyon Bi struct inno_mipi_dphy_timing data;
43885e15df9SWyon Bi unsigned long txbyteclk, txclkesc, UI;
43985e15df9SWyon Bi unsigned int esc_clk_div;
44085e15df9SWyon Bi
44185e15df9SWyon Bi memset(&timing, 0, sizeof(timing));
44285e15df9SWyon Bi memset(&data, 0, sizeof(data));
44385e15df9SWyon Bi
44485e15df9SWyon Bi txbyteclk = inno->lane_mbps * USEC_PER_SEC / 8;
44585e15df9SWyon Bi esc_clk_div = DIV_ROUND_UP(txbyteclk, 20000000);
44685e15df9SWyon Bi txclkesc = txbyteclk / esc_clk_div;
44785e15df9SWyon Bi UI = DIV_ROUND_CLOSEST(NSEC_PER_USEC, inno->lane_mbps);
44885e15df9SWyon Bi
44985e15df9SWyon Bi debug("txbyteclk=%lu, txclkesc=%lu, esc_clk_div=%u, UI=%lu\n",
45085e15df9SWyon Bi txbyteclk, txclkesc, esc_clk_div, UI);
45185e15df9SWyon Bi
45285e15df9SWyon Bi mipi_dphy_timing_get_default(&timing, UI);
45327d50ce7SNickey Yang inno_mipi_dphy_get_fixed_param(&data, inno->lane_mbps,
45427d50ce7SNickey Yang phy->soc_type, lane_type);
45585e15df9SWyon Bi
45685e15df9SWyon Bi /*
45785e15df9SWyon Bi * Ttxbyteclk * val >= Ths-exit
45885e15df9SWyon Bi * Ttxbyteclk * val >= Tclk-post
45985e15df9SWyon Bi * Ttxbyteclk * val >= Tclk-pre
46085e15df9SWyon Bi * Ttxbyteclk * (2 + val) >= Tlpx
46185e15df9SWyon Bi */
46285e15df9SWyon Bi data.hs_exit = DIV_ROUND_UP(timing.hsexit * txbyteclk, NSEC_PER_SEC);
46385e15df9SWyon Bi data.clk_post = DIV_ROUND_UP(timing.clkpost * txbyteclk, NSEC_PER_SEC);
46485e15df9SWyon Bi data.clk_pre = DIV_ROUND_UP(timing.clkpre * txbyteclk, NSEC_PER_SEC);
46585e15df9SWyon Bi data.wakup_h = 0x3;
46685e15df9SWyon Bi data.wakup_l = 0xff;
467a3c5f2d5SNickey Yang
468a3c5f2d5SNickey Yang if (phy->soc_type == RV1108_MIPI_DPHY) {
46985e15df9SWyon Bi data.lpx = DIV_ROUND_UP(txbyteclk * timing.lpx, NSEC_PER_SEC);
47085e15df9SWyon Bi if (data.lpx > 2)
47185e15df9SWyon Bi data.lpx -= 2;
472a3c5f2d5SNickey Yang }
47385e15df9SWyon Bi
47485e15df9SWyon Bi /*
47585e15df9SWyon Bi * Ttxclkesc * val >= Tta-go
47685e15df9SWyon Bi * Ttxclkesc * val >= Tta-sure
47785e15df9SWyon Bi * Ttxclkesc * val >= Tta-wait
47885e15df9SWyon Bi */
47985e15df9SWyon Bi data.ta_go = DIV_ROUND_UP(timing.tago * txclkesc, NSEC_PER_SEC);
48085e15df9SWyon Bi data.ta_sure = DIV_ROUND_UP(timing.tasure * txclkesc, NSEC_PER_SEC);
48185e15df9SWyon Bi data.ta_wait = DIV_ROUND_UP(timing.taget * txclkesc, NSEC_PER_SEC);
48285e15df9SWyon Bi
48385e15df9SWyon Bi inno_mipi_dphy_timing_update(inno, lane_type, &data);
48485e15df9SWyon Bi
48585e15df9SWyon Bi #define TIMING_NS(x, freq) (((x) * (DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq))))
48685e15df9SWyon Bi debug("hs-exit=%lu, clk-post=%lu, clk-pre=%lu, lpx=%lu\n",
48785e15df9SWyon Bi TIMING_NS(data.hs_exit, txbyteclk),
48885e15df9SWyon Bi TIMING_NS(data.clk_post, txbyteclk),
48985e15df9SWyon Bi TIMING_NS(data.clk_pre, txbyteclk),
49085e15df9SWyon Bi TIMING_NS(data.lpx + 2, txbyteclk));
49185e15df9SWyon Bi debug("ta-go=%lu, ta-sure=%lu, ta-wait=%lu\n",
49285e15df9SWyon Bi TIMING_NS(data.ta_go, txclkesc),
49385e15df9SWyon Bi TIMING_NS(data.ta_sure, txclkesc),
49485e15df9SWyon Bi TIMING_NS(data.ta_wait, txclkesc));
49585e15df9SWyon Bi }
49685e15df9SWyon Bi
inno_mipi_dphy_pll_round_rate(unsigned long fin,unsigned long fout,u8 * prediv,u16 * fbdiv)49785e15df9SWyon Bi static unsigned long inno_mipi_dphy_pll_round_rate(unsigned long fin,
49885e15df9SWyon Bi unsigned long fout,
49985e15df9SWyon Bi u8 *prediv, u16 *fbdiv)
50085e15df9SWyon Bi {
50185e15df9SWyon Bi unsigned long best_freq = 0;
50285e15df9SWyon Bi u8 min_prediv, max_prediv;
50385e15df9SWyon Bi u8 _prediv, best_prediv = 0;
50485e15df9SWyon Bi u16 _fbdiv, best_fbdiv = 0;
50585e15df9SWyon Bi u32 min_delta = 0xffffffff;
50685e15df9SWyon Bi
50785e15df9SWyon Bi fout *= 2;
50885e15df9SWyon Bi
50985e15df9SWyon Bi min_prediv = DIV_ROUND_UP(fin, 40000000);
51085e15df9SWyon Bi max_prediv = fin / 5000000;
51185e15df9SWyon Bi
51285e15df9SWyon Bi for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
51385e15df9SWyon Bi u64 tmp;
51485e15df9SWyon Bi u32 delta;
51585e15df9SWyon Bi tmp = (u64)fout * _prediv;
51685e15df9SWyon Bi do_div(tmp, fin);
51785e15df9SWyon Bi _fbdiv = tmp;
51885e15df9SWyon Bi if ((_fbdiv == 15) || (_fbdiv < 12) || (_fbdiv > 511))
51985e15df9SWyon Bi continue;
52085e15df9SWyon Bi tmp = (u64)_fbdiv * fin;
52185e15df9SWyon Bi do_div(tmp, _prediv);
52285e15df9SWyon Bi
52385e15df9SWyon Bi delta = abs(fout - tmp);
52485e15df9SWyon Bi if (delta < min_delta) {
52585e15df9SWyon Bi best_prediv = _prediv;
52685e15df9SWyon Bi best_fbdiv = _fbdiv;
52785e15df9SWyon Bi min_delta = delta;
52885e15df9SWyon Bi best_freq = tmp;
52985e15df9SWyon Bi }
53085e15df9SWyon Bi }
53185e15df9SWyon Bi
53285e15df9SWyon Bi if (best_freq) {
53385e15df9SWyon Bi *prediv = best_prediv;
53485e15df9SWyon Bi *fbdiv = best_fbdiv;
53585e15df9SWyon Bi }
53685e15df9SWyon Bi
53785e15df9SWyon Bi return best_freq / 2;
53885e15df9SWyon Bi }
53985e15df9SWyon Bi
inno_mipi_dphy_reset(struct inno_mipi_dphy * inno)54085e15df9SWyon Bi static inline void inno_mipi_dphy_reset(struct inno_mipi_dphy *inno)
54185e15df9SWyon Bi {
54285e15df9SWyon Bi /* Reset analog */
54385e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_POWER_CTRL,
54485e15df9SWyon Bi ANALOG_RESET_MASK, ANALOG_RESET);
54585e15df9SWyon Bi udelay(1);
54685e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_POWER_CTRL,
54785e15df9SWyon Bi ANALOG_RESET_MASK, ANALOG_NORMAL);
54885e15df9SWyon Bi /* Reset digital */
54985e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_DIG_CTRL,
55085e15df9SWyon Bi DIGITAL_RESET_MASK, DIGITAL_RESET);
55185e15df9SWyon Bi udelay(1);
55285e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_DIG_CTRL,
55385e15df9SWyon Bi DIGITAL_RESET_MASK, DIGITAL_NORMAL);
55485e15df9SWyon Bi }
55585e15df9SWyon Bi
inno_mipi_dphy_timing_init(struct inno_mipi_dphy * inno)55685e15df9SWyon Bi static void inno_mipi_dphy_timing_init(struct inno_mipi_dphy *inno)
55785e15df9SWyon Bi {
55885e15df9SWyon Bi switch (inno->lanes) {
55985e15df9SWyon Bi case 4:
56085e15df9SWyon Bi inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_3);
56185e15df9SWyon Bi /* Fall through */
56285e15df9SWyon Bi case 3:
56385e15df9SWyon Bi inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_2);
56485e15df9SWyon Bi /* Fall through */
56585e15df9SWyon Bi case 2:
56685e15df9SWyon Bi inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_1);
56785e15df9SWyon Bi /* Fall through */
56885e15df9SWyon Bi case 1:
56985e15df9SWyon Bi default:
57085e15df9SWyon Bi inno_mipi_dphy_lane_timing_init(inno, DATA_LANE_0);
57185e15df9SWyon Bi inno_mipi_dphy_lane_timing_init(inno, CLOCK_LANE);
57285e15df9SWyon Bi break;
57385e15df9SWyon Bi }
57485e15df9SWyon Bi }
57585e15df9SWyon Bi
inno_mipi_dphy_lane_enable(struct inno_mipi_dphy * inno)57685e15df9SWyon Bi static inline void inno_mipi_dphy_lane_enable(struct inno_mipi_dphy *inno)
57785e15df9SWyon Bi {
57885e15df9SWyon Bi u32 m = 0, v = 0;
57985e15df9SWyon Bi
58085e15df9SWyon Bi switch (inno->lanes) {
58185e15df9SWyon Bi case 4:
58285e15df9SWyon Bi m |= DATA_LANE_3_EN_MASK;
58385e15df9SWyon Bi v |= DATA_LANE_3_EN;
58485e15df9SWyon Bi /* Fall through */
58585e15df9SWyon Bi case 3:
58685e15df9SWyon Bi m |= DATA_LANE_2_EN_MASK;
58785e15df9SWyon Bi v |= DATA_LANE_2_EN;
58885e15df9SWyon Bi /* Fall through */
58985e15df9SWyon Bi case 2:
59085e15df9SWyon Bi m |= DATA_LANE_1_EN_MASK;
59185e15df9SWyon Bi v |= DATA_LANE_1_EN;
59285e15df9SWyon Bi /* Fall through */
59385e15df9SWyon Bi default:
59485e15df9SWyon Bi case 1:
59585e15df9SWyon Bi m |= DATA_LANE_0_EN_MASK | CLK_LANE_EN_MASK;
59685e15df9SWyon Bi v |= DATA_LANE_0_EN | CLK_LANE_EN;
59785e15df9SWyon Bi break;
59885e15df9SWyon Bi }
59985e15df9SWyon Bi
60085e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, m, v);
60185e15df9SWyon Bi }
60285e15df9SWyon Bi
inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy * inno)60385e15df9SWyon Bi static inline void inno_mipi_dphy_pll_ldo_disable(struct inno_mipi_dphy *inno)
60485e15df9SWyon Bi {
60585e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_POWER_CTRL,
60685e15df9SWyon Bi PLL_POWER_MASK | LDO_POWER_MASK,
60785e15df9SWyon Bi PLL_POWER_DOWN | LDO_POWER_DOWN);
60885e15df9SWyon Bi }
60985e15df9SWyon Bi
inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy * inno)61085e15df9SWyon Bi static inline void inno_mipi_dphy_pll_ldo_enable(struct inno_mipi_dphy *inno)
61185e15df9SWyon Bi {
61285e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_POWER_CTRL,
61385e15df9SWyon Bi PLL_POWER_MASK | LDO_POWER_MASK,
61485e15df9SWyon Bi PLL_POWER_ON | LDO_POWER_ON);
61585e15df9SWyon Bi }
61685e15df9SWyon Bi
inno_mipi_dphy_da_pwrok_enable(struct inno_mipi_dphy * inno)61785e15df9SWyon Bi static inline void inno_mipi_dphy_da_pwrok_enable(struct inno_mipi_dphy *inno)
61885e15df9SWyon Bi {
61985e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK);
62085e15df9SWyon Bi }
62185e15df9SWyon Bi
inno_mipi_dphy_da_pwrok_disable(struct inno_mipi_dphy * inno)62285e15df9SWyon Bi static inline void inno_mipi_dphy_da_pwrok_disable(struct inno_mipi_dphy *inno)
62385e15df9SWyon Bi {
62485e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, PWROK_BP | PWROK, PWROK_BP);
62585e15df9SWyon Bi }
62685e15df9SWyon Bi
inno_mipi_dphy_bgpd_enable(struct inno_mipi_dphy * inno)62785e15df9SWyon Bi static inline void inno_mipi_dphy_bgpd_enable(struct inno_mipi_dphy *inno)
62885e15df9SWyon Bi {
62985e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, 0);
63085e15df9SWyon Bi }
63185e15df9SWyon Bi
inno_mipi_dphy_bgpd_disable(struct inno_mipi_dphy * inno)63285e15df9SWyon Bi static inline void inno_mipi_dphy_bgpd_disable(struct inno_mipi_dphy *inno)
63385e15df9SWyon Bi {
63485e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, MIPI_BGPD, MIPI_BGPD);
63585e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LVDS_CTRL, LVDS_BGPD, LVDS_BGPD);
63685e15df9SWyon Bi }
63785e15df9SWyon Bi
inno_mipi_dphy_power_on(struct rockchip_phy * phy)63885e15df9SWyon Bi static int inno_mipi_dphy_power_on(struct rockchip_phy *phy)
63985e15df9SWyon Bi {
64085e15df9SWyon Bi struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
64185e15df9SWyon Bi
64285e15df9SWyon Bi inno_mipi_dphy_bgpd_enable(inno);
64385e15df9SWyon Bi inno_mipi_dphy_da_pwrok_enable(inno);
64485e15df9SWyon Bi inno_mipi_dphy_pll_ldo_enable(inno);
64585e15df9SWyon Bi inno_mipi_dphy_lane_enable(inno);
64685e15df9SWyon Bi inno_mipi_dphy_reset(inno);
64785e15df9SWyon Bi inno_mipi_dphy_timing_init(inno);
64885e15df9SWyon Bi udelay(1);
64985e15df9SWyon Bi
65085e15df9SWyon Bi return 0;
65185e15df9SWyon Bi }
65285e15df9SWyon Bi
inno_mipi_dphy_lane_disable(struct inno_mipi_dphy * inno)65385e15df9SWyon Bi static inline void inno_mipi_dphy_lane_disable(struct inno_mipi_dphy *inno)
65485e15df9SWyon Bi {
65585e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_LANE_CTRL, 0x7c, 0x00);
65685e15df9SWyon Bi }
65785e15df9SWyon Bi
inno_mipi_dphy_power_off(struct rockchip_phy * phy)65885e15df9SWyon Bi static int inno_mipi_dphy_power_off(struct rockchip_phy *phy)
65985e15df9SWyon Bi {
66085e15df9SWyon Bi struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
66185e15df9SWyon Bi
66285e15df9SWyon Bi inno_mipi_dphy_lane_disable(inno);
66385e15df9SWyon Bi inno_mipi_dphy_pll_ldo_disable(inno);
66485e15df9SWyon Bi inno_mipi_dphy_da_pwrok_disable(inno);
66585e15df9SWyon Bi inno_mipi_dphy_bgpd_disable(inno);
66685e15df9SWyon Bi
66785e15df9SWyon Bi return 0;
66885e15df9SWyon Bi }
66985e15df9SWyon Bi
inno_mipi_dphy_set_pll(struct rockchip_phy * phy,unsigned long rate)67085e15df9SWyon Bi static unsigned long inno_mipi_dphy_set_pll(struct rockchip_phy *phy,
67185e15df9SWyon Bi unsigned long rate)
67285e15df9SWyon Bi {
67385e15df9SWyon Bi struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
67485e15df9SWyon Bi unsigned long fin, fout;
67585e15df9SWyon Bi u16 fbdiv = 0;
67685e15df9SWyon Bi u8 prediv = 0;
67785e15df9SWyon Bi u32 m, v;
67885e15df9SWyon Bi
67985e15df9SWyon Bi fin = 24000000;
68085e15df9SWyon Bi fout = inno_mipi_dphy_pll_round_rate(fin, rate, &prediv, &fbdiv);
68185e15df9SWyon Bi
68285e15df9SWyon Bi debug("%s: fin=%lu, fout=%lu, prediv=%u, fbdiv=%u\n",
68385e15df9SWyon Bi __func__, fin, fout, prediv, fbdiv);
68485e15df9SWyon Bi
68585e15df9SWyon Bi m = FBDIV_HI_MASK | PREDIV_MASK;
68685e15df9SWyon Bi v = FBDIV_HI(fbdiv >> 8) | PREDIV(prediv);
68785e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_PLL_CTRL_0, m, v);
68885e15df9SWyon Bi
68985e15df9SWyon Bi m = FBDIV_LO_MASK;
69085e15df9SWyon Bi v = FBDIV_LO(fbdiv);
69185e15df9SWyon Bi inno_update_bits(inno, INNO_PHY_PLL_CTRL_1, m, v);
69285e15df9SWyon Bi
69327d50ce7SNickey Yang if (phy->soc_type == RK1808_MIPI_DPHY) {
69427d50ce7SNickey Yang inno_update_bits(inno, ANALOG_REG_08,
69527d50ce7SNickey Yang PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
69627d50ce7SNickey Yang inno_update_bits(inno, ANALOG_REG_0B,
69727d50ce7SNickey Yang CLOCK_LANE_VOD_RANGE_SET_MASK,
69827d50ce7SNickey Yang CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
69927d50ce7SNickey Yang }
70027d50ce7SNickey Yang
7016ab2ca6dSHongming Zou if (phy->soc_type == RK3506_MIPI_DPHY) {
7026ab2ca6dSHongming Zou inno_update_bits(inno, RK3506_PRE_EMPHASIS,
7036ab2ca6dSHongming Zou LANE0_PRE_EMPHASIS_ENABLE_MASK, LANE0_PRE_EMPHASIS_ENABLE);
7046ab2ca6dSHongming Zou inno_update_bits(inno, RK3506_PRE_EMPHASIS,
7056ab2ca6dSHongming Zou LANE1_PRE_EMPHASIS_ENABLE_MASK, LANE1_PRE_EMPHASIS_ENABLE);
7066ab2ca6dSHongming Zou inno_update_bits(inno, PRE_EMPHASIS_RANGE,
7076ab2ca6dSHongming Zou PRE_EMPHASIS_RANGE_SET_MASK,
7086ab2ca6dSHongming Zou PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE));
709b5238271SHongming Zou inno_update_bits(inno, LANE0_PRE_EMPHASIS_RANGE,
7106ab2ca6dSHongming Zou LANE0_PRE_EMPHASIS_RANGE_SET_MASK,
7116ab2ca6dSHongming Zou LANE0_PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE));
7126ab2ca6dSHongming Zou inno_update_bits(inno, LANE1_PRE_EMPHASIS_RANGE,
7136ab2ca6dSHongming Zou LANE1_PRE_EMPHASIS_RANGE_SET_MASK,
7146ab2ca6dSHongming Zou LANE1_PRE_EMPHASIS_RANGE_SET(PRE_EMPHASIS_MID_RANGE));
7156ab2ca6dSHongming Zou inno_update_bits(inno, ANALOG_REG_0B,
7166ab2ca6dSHongming Zou CLOCK_LANE_VOD_RANGE_SET_MASK,
7176ab2ca6dSHongming Zou CLOCK_LANE_VOD_RANGE_SET(RK3506_VOD_MAX_RANGE));
7186ab2ca6dSHongming Zou }
7196ab2ca6dSHongming Zou
72085e15df9SWyon Bi inno->lane_mbps = fout / USEC_PER_SEC;
72185e15df9SWyon Bi
72285e15df9SWyon Bi return fout;
72385e15df9SWyon Bi }
72485e15df9SWyon Bi
inno_mipi_dphy_parse_dt(struct inno_mipi_dphy * inno)72585e15df9SWyon Bi static int inno_mipi_dphy_parse_dt(struct inno_mipi_dphy *inno)
72685e15df9SWyon Bi {
72785e15df9SWyon Bi struct udevice *dev = inno->dev;
72885e15df9SWyon Bi
7296ab2ca6dSHongming Zou #if defined(CONFIG_ROCKCHIP_RK3506)
7306ab2ca6dSHongming Zou inno->lanes = ofnode_read_u32_default(dev->node, "inno,lanes", 2);
7316ab2ca6dSHongming Zou #else
73285e15df9SWyon Bi inno->lanes = ofnode_read_u32_default(dev->node, "inno,lanes", 4);
7336ab2ca6dSHongming Zou #endif
73485e15df9SWyon Bi
73585e15df9SWyon Bi return 0;
73685e15df9SWyon Bi }
73785e15df9SWyon Bi
inno_mipi_dphy_init(struct rockchip_phy * phy)73885e15df9SWyon Bi static int inno_mipi_dphy_init(struct rockchip_phy *phy)
73985e15df9SWyon Bi {
74085e15df9SWyon Bi struct inno_mipi_dphy *inno = dev_get_priv(phy->dev);
74185e15df9SWyon Bi int ret;
74285e15df9SWyon Bi
74385e15df9SWyon Bi ret = inno_mipi_dphy_parse_dt(inno);
74485e15df9SWyon Bi if (ret) {
74585e15df9SWyon Bi printf("%s: failed to parse DT\n", __func__);
74685e15df9SWyon Bi return ret;
74785e15df9SWyon Bi }
74885e15df9SWyon Bi
74985e15df9SWyon Bi inno->regs = dev_read_addr_ptr(inno->dev);
75085e15df9SWyon Bi
7518697aa74SHongming Zou #if defined(CONFIG_ROCKCHIP_RK3506)
7528697aa74SHongming Zou /* The following command switches gpio to MIPI */
7538697aa74SHongming Zou inno_write(inno, INNO_PHY_MODE_CTRL, MIPI_MODE_ENABLE);
7548697aa74SHongming Zou #endif
7558697aa74SHongming Zou
75685e15df9SWyon Bi return 0;
75785e15df9SWyon Bi }
75885e15df9SWyon Bi
75985e15df9SWyon Bi static const struct rockchip_phy_funcs inno_mipi_dphy_funcs = {
76085e15df9SWyon Bi .init = inno_mipi_dphy_init,
76185e15df9SWyon Bi .power_on = inno_mipi_dphy_power_on,
76285e15df9SWyon Bi .power_off = inno_mipi_dphy_power_off,
76385e15df9SWyon Bi .set_pll = inno_mipi_dphy_set_pll,
76485e15df9SWyon Bi };
76585e15df9SWyon Bi
76685e15df9SWyon Bi static const struct udevice_id inno_mipi_dphy_ids[] = {
76785e15df9SWyon Bi {
76885e15df9SWyon Bi .compatible = "rockchip,rv1108-mipi-dphy",
76985e15df9SWyon Bi },
77027d50ce7SNickey Yang {
77127d50ce7SNickey Yang .compatible = "rockchip,rk1808-mipi-dphy",
77227d50ce7SNickey Yang },
7738f1f6d60SNickey Yang {
774*e5e3ca80SHongming Zou .compatible = "rockchip,rv1126-dsi-dphy",
775c3a1ac49SGuochun Huang },
776b5238271SHongming Zou {
777b5238271SHongming Zou .compatible = "rockchip,rk3506-dsi-dphy",
778b5238271SHongming Zou },
77985e15df9SWyon Bi {}
78085e15df9SWyon Bi };
78185e15df9SWyon Bi
inno_mipi_dphy_probe(struct udevice * dev)78285e15df9SWyon Bi static int inno_mipi_dphy_probe(struct udevice *dev)
78385e15df9SWyon Bi {
78485e15df9SWyon Bi struct inno_mipi_dphy *inno = dev_get_priv(dev);
785c3a1ac49SGuochun Huang struct rockchip_phy *phy;
78685e15df9SWyon Bi
787c3a1ac49SGuochun Huang phy = calloc(1, sizeof(*phy));
788c3a1ac49SGuochun Huang if (!phy)
789c3a1ac49SGuochun Huang return -ENOMEM;
790c3a1ac49SGuochun Huang
791c3a1ac49SGuochun Huang dev->driver_data = (ulong)phy;
79285e15df9SWyon Bi inno->dev = dev;
79385e15df9SWyon Bi phy->dev = dev;
794c3a1ac49SGuochun Huang phy->funcs = &inno_mipi_dphy_funcs;
795c3a1ac49SGuochun Huang
796c3a1ac49SGuochun Huang #if defined(CONFIG_ROCKCHIP_RV1108)
797c3a1ac49SGuochun Huang phy->soc_type = RV1108_MIPI_DPHY;
7986ab2ca6dSHongming Zou #elif defined(CONFIG_ROCKCHIP_RK3506)
7996ab2ca6dSHongming Zou phy->soc_type = RK3506_MIPI_DPHY;
800c3a1ac49SGuochun Huang #else
801c3a1ac49SGuochun Huang phy->soc_type = RK1808_MIPI_DPHY;
802c3a1ac49SGuochun Huang #endif
80385e15df9SWyon Bi
80485e15df9SWyon Bi return 0;
80585e15df9SWyon Bi }
80685e15df9SWyon Bi
80785e15df9SWyon Bi U_BOOT_DRIVER(inno_mipi_dphy) = {
80885e15df9SWyon Bi .name = "inno_mipi_dphy",
80985e15df9SWyon Bi .id = UCLASS_PHY,
81085e15df9SWyon Bi .of_match = inno_mipi_dphy_ids,
81185e15df9SWyon Bi .probe = inno_mipi_dphy_probe,
81285e15df9SWyon Bi .priv_auto_alloc_size = sizeof(struct inno_mipi_dphy),
81385e15df9SWyon Bi };
814