xref: /rk3399_rockchip-uboot/drivers/video/rk_eink/rk_ebc_tcon.c (revision be899ebc8b99774c976415853e214dc3a7b5c747)
193a7515aSWenping Zhang // SPDX-License-Identifier: GPL-2.0
293a7515aSWenping Zhang /*
393a7515aSWenping Zhang  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
493a7515aSWenping Zhang  *
593a7515aSWenping Zhang  * Author: Wenping Zhang <wenping.zhang@rock-chips.com>
693a7515aSWenping Zhang  */
793a7515aSWenping Zhang #include <common.h>
893a7515aSWenping Zhang #include <clk.h>
993a7515aSWenping Zhang #include <dm.h>
1093a7515aSWenping Zhang #include <dm/pinctrl.h>
1193a7515aSWenping Zhang #include <pwm.h>
1293a7515aSWenping Zhang #include <regmap.h>
1393a7515aSWenping Zhang #include <syscon.h>
1493a7515aSWenping Zhang #include <asm/arch/clock.h>
1593a7515aSWenping Zhang #include <asm/io.h>
1693a7515aSWenping Zhang #include <syscon.h>
1793a7515aSWenping Zhang #include <linux/io.h>
1893a7515aSWenping Zhang #include "rk_ebc.h"
1993a7515aSWenping Zhang #ifdef CONFIG_IRQ
2093a7515aSWenping Zhang #include <irq-generic.h>
2193a7515aSWenping Zhang #endif
2293a7515aSWenping Zhang 
2393a7515aSWenping Zhang struct ebc_tcon_priv {
2493a7515aSWenping Zhang 	struct udevice *dev;
2593a7515aSWenping Zhang 	void __iomem *reg;
2693a7515aSWenping Zhang 	u32 *regcache;
2793a7515aSWenping Zhang 	u32 reg_len;
2893a7515aSWenping Zhang 	void *grf;
2993a7515aSWenping Zhang 	void *pmugrf;
30f968f3bcSZorro Liu 	struct clk dclk;
3193a7515aSWenping Zhang };
3293a7515aSWenping Zhang 
3393a7515aSWenping Zhang #define msleep(a)		udelay((a) * 1000)
3493a7515aSWenping Zhang #define HIWORD_UPDATE(x, l, h)	(((x) << (l)) | (GENMASK(h, l) << 16))
3593a7515aSWenping Zhang #define UPDATE(x, h, l)		(((x) << (l)) & GENMASK((h), (l)))
3693a7515aSWenping Zhang 
3793a7515aSWenping Zhang #define REG_LOAD_GLOBAL_EN	0x1
3893a7515aSWenping Zhang 
3993a7515aSWenping Zhang /* ebc register define */
4093a7515aSWenping Zhang #define EBC_DSP_START		0x0000 //Frame statrt register
4193a7515aSWenping Zhang #define EBC_EPD_CTRL		0x0004 //EPD control register
4293a7515aSWenping Zhang #define EBC_DSP_CTRL		0x0008 //Display control register
4393a7515aSWenping Zhang #define EBC_DSP_HTIMING0	0x000c //H-Timing setting register0
4493a7515aSWenping Zhang #define EBC_DSP_HTIMING1	0x0010 //H-Timing setting register1
4593a7515aSWenping Zhang #define EBC_DSP_VTIMING0	0x0014 //V-Timing setting register0
4693a7515aSWenping Zhang #define EBC_DSP_VTIMING1	0x0018 //V-Timing setting register1
4793a7515aSWenping Zhang #define EBC_DSP_ACT_INFO	0x001c //ACTIVE width/height
4893a7515aSWenping Zhang #define EBC_WIN_CTRL		0x0020 //Window ctrl
4993a7515aSWenping Zhang #define EBC_WIN_MST0		0x0024 //Current win memory start
5093a7515aSWenping Zhang #define EBC_WIN_MST1		0x0028 //Next win memory start
5193a7515aSWenping Zhang #define EBC_WIN_VIR		0x002c //Window vir width/height
5293a7515aSWenping Zhang #define EBC_WIN_ACT		0x0030 //Window act width/height
5393a7515aSWenping Zhang #define EBC_WIN_DSP		0x0034 //Window dsp width/height
5493a7515aSWenping Zhang #define EBC_WIN_DSP_ST		0x0038 //Window display start point
5593a7515aSWenping Zhang #define EBC_INT_STATUS		0x003c //Interrupt register
5693a7515aSWenping Zhang #define EBC_VCOM0		0x0040 //VCOM setting register0
5793a7515aSWenping Zhang #define EBC_VCOM1		0x0044 //VCOM setting register1
5893a7515aSWenping Zhang #define EBC_VCOM2		0x0048 //VCOM setting register2
5993a7515aSWenping Zhang #define EBC_VCOM3		0x004c //VCOM setting register3
6093a7515aSWenping Zhang #define EBC_CONFIG_DONE		0x0050 //Config done register
6193a7515aSWenping Zhang #define EBC_VNUM		0x0054 //Line flag num
6293a7515aSWenping Zhang #define EBC_WIN_MST2		0x0058 //Framecount memory start
6393a7515aSWenping Zhang #define EBC_LUT_DATA_ADDR	0x1000 //lut data address
6493a7515aSWenping Zhang 
6593a7515aSWenping Zhang #define DSP_HTOTAL(x)		UPDATE(x, 27, 16)
6693a7515aSWenping Zhang #define DSP_HS_END(x)		UPDATE(x, 7, 0)
6793a7515aSWenping Zhang #define DSP_HACT_END(x)		UPDATE(x, 26, 16)
6893a7515aSWenping Zhang #define DSP_HACT_ST(x)		UPDATE(x, 7, 0)
6993a7515aSWenping Zhang #define DSP_VTOTAL(x)		UPDATE(x, 26, 16)
7093a7515aSWenping Zhang #define DSP_VS_END(x)		UPDATE(x, 7, 0)
7193a7515aSWenping Zhang #define DSP_VACT_END(x)		UPDATE(x, 26, 16)
7293a7515aSWenping Zhang #define DSP_VACT_ST(x)		UPDATE(x, 7, 0)
7393a7515aSWenping Zhang #define DSP_HEIGHT(x)		UPDATE(x, 26, 16)
7493a7515aSWenping Zhang #define DSP_WIDTH(x)		UPDATE(x, 11, 0)
7593a7515aSWenping Zhang 
7693a7515aSWenping Zhang #define WIN2_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 27, 19)
7793a7515aSWenping Zhang #define WIN_EN(x)			UPDATE(x, 18, 18)
7893a7515aSWenping Zhang #define BURST_REG(x)			UPDATE(x, 12, 10)
7993a7515aSWenping Zhang #define WIN_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 9, 2)
8093a7515aSWenping Zhang #define WIN_FMT(x)			UPDATE(x, 1, 0)
8193a7515aSWenping Zhang 
8293a7515aSWenping Zhang #define WIN_VIR_HEIGHT(x)		UPDATE(x, 31, 16)
8393a7515aSWenping Zhang #define WIN_VIR_WIDTH(x)		UPDATE(x, 15, 0)
8493a7515aSWenping Zhang #define WIN_ACT_HEIGHT(x)		UPDATE(x, 26, 16)
8593a7515aSWenping Zhang #define WIN_ACT_WIDTH(x)		UPDATE(x, 11, 0)
8693a7515aSWenping Zhang #define WIN_DSP_HEIGHT(x)		UPDATE(x, 26, 16)
8793a7515aSWenping Zhang #define WIN_DSP_WIDTH(x)		UPDATE(x, 11, 0)
8893a7515aSWenping Zhang #define WIN_DSP_YST(x)			UPDATE(x, 26, 16)
8993a7515aSWenping Zhang #define WIN_DSP_XST(x)			UPDATE(x, 11, 0)
9093a7515aSWenping Zhang 
9193a7515aSWenping Zhang #define DSP_OUT_LOW			BIT(31)
9293a7515aSWenping Zhang #define DSP_EINK_MODE(x)		UPDATE(x, 13, 13)
9393a7515aSWenping Zhang #define DSP_EINK_MODE_MASK		BIT(13)
9493a7515aSWenping Zhang #define DSP_SDCE_WIDTH(x)		UPDATE(x, 25, 16)
9593a7515aSWenping Zhang #define DSP_FRM_TOTAL(x)		UPDATE(x, 9, 2)
9693a7515aSWenping Zhang #define DSP_FRM_TOTAL_MASK		GENMASK(9, 2)
9793a7515aSWenping Zhang #define DSP_FRM_START			BIT(0)
9893a7515aSWenping Zhang #define DSP_FRM_START_MASK		BIT(0)
9993a7515aSWenping Zhang #define SW_BURST_CTRL			BIT(12)
10093a7515aSWenping Zhang 
10193a7515aSWenping Zhang #define EINK_MODE_SWAP(x)		UPDATE(x, 31, 31)
10293a7515aSWenping Zhang #define EINK_MODE_FRM_SEL(x)		UPDATE(x, 30, 30)
10393a7515aSWenping Zhang #define DSP_GD_END(x)			UPDATE(x, 26, 16)
10493a7515aSWenping Zhang #define DSP_GD_ST(x)			UPDATE(x, 15, 8)
10593a7515aSWenping Zhang #define DSP_THREE_WIN_MODE(x)		UPDATE(x, 7, 7)
10693a7515aSWenping Zhang #define THREE_WIN_MODE_MASK		BIT(7)
10793a7515aSWenping Zhang #define DSP_SDDW_MODE(x)		UPDATE(x, 6, 6)
10893a7515aSWenping Zhang #define EPD_AUO(x)			UPDATE(x, 5, 5)
10993a7515aSWenping Zhang #define EPD_PWR(x)			UPDATE(x, 4, 2)
11093a7515aSWenping Zhang #define EPD_GDRL(x)			UPDATE(x, 1, 1)
11193a7515aSWenping Zhang #define EPD_SDSHR(x)			UPDATE(x, 0, 0)
11293a7515aSWenping Zhang 
11393a7515aSWenping Zhang #define DSP_SWAP_MODE(x)		UPDATE(x, 31, 30)
11493a7515aSWenping Zhang #define DSP_SWAP_MODE_MASK		GENMASK(31, 30)
11593a7515aSWenping Zhang #define DSP_SDCLK_DIV(x)		UPDATE(x, 19, 16)
11693a7515aSWenping Zhang #define DSP_SDCLK_DIV_MASK		GENMASK(19, 16)
11793a7515aSWenping Zhang #define DSP_VCOM_MODE(x)		UPDATE(x, 27, 27)
11893a7515aSWenping Zhang #define DSP_VCOM_MODE_MASK		BIT(27)
11993a7515aSWenping Zhang 
12093a7515aSWenping Zhang #define DSP_UPDATE_MODE(x)	UPDATE(x, 29, 29)
12193a7515aSWenping Zhang #define DSP_DISPLAY_MODE(x)	UPDATE(x, 28, 28)
12293a7515aSWenping Zhang #define UPDATE_MODE_MASK	BIT(29)
12393a7515aSWenping Zhang #define DISPLAY_MODE_MASK	BIT(28)
12493a7515aSWenping Zhang 
12593a7515aSWenping Zhang #define DSP_FRM_INT_NUM(x)	UPDATE(x, 19, 12)
12693a7515aSWenping Zhang #define FRM_END_INT		BIT(0)
12793a7515aSWenping Zhang #define DSP_END_INT		BIT(1)
12893a7515aSWenping Zhang #define DSP_FRM_INT		BIT(2)
12993a7515aSWenping Zhang #define LINE_FLAG_INT		BIT(3)
13093a7515aSWenping Zhang #define FRM_END_INT_MASK	BIT(4)
13193a7515aSWenping Zhang #define DSP_END_INT_MASK	BIT(5)
13293a7515aSWenping Zhang #define DSP_FRM_INT_MASK	BIT(6)
13393a7515aSWenping Zhang #define LINE_FLAG_INT_MASK	BIT(7)
13493a7515aSWenping Zhang #define FRM_END_INT_CLR		BIT(8)
13593a7515aSWenping Zhang #define DSP_END_INT_CLR		BIT(9)
13693a7515aSWenping Zhang #define DSP_FRM_INT_CLR		BIT(10)
13793a7515aSWenping Zhang #define LINE_FLAG_INT_CLR	BIT(11)
13893a7515aSWenping Zhang 
1398766792cSChaoyi Chen #define RK3576_EBC_DSP_START			0x0000
1408766792cSChaoyi Chen #define RK3576_EBC_EPD_CTRL			0x0004
1418766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL			0x0008
1428766792cSChaoyi Chen #define RK3576_EBC_DSP_HTIMING0			0x000C
1438766792cSChaoyi Chen #define RK3576_EBC_DSP_HTIMING1			0x0010
1448766792cSChaoyi Chen #define RK3576_EBC_DSP_VTIMING0			0x0014
1458766792cSChaoyi Chen #define RK3576_EBC_DSP_VTIMING1			0x0018
1468766792cSChaoyi Chen #define RK3576_EBC_DSP_ACT_INFO			0x001C
1478766792cSChaoyi Chen #define RK3576_EBC_WIN_CTRL			0x0020
1488766792cSChaoyi Chen #define RK3576_EBC_WIN_MST0			0x0024
1498766792cSChaoyi Chen #define RK3576_EBC_WIN_MST1			0x0028
1508766792cSChaoyi Chen #define RK3576_EBC_WIN_VIR			0x002C
1518766792cSChaoyi Chen #define RK3576_EBC_WIN_ACT			0x0030
1528766792cSChaoyi Chen #define RK3576_EBC_WIN_DSP			0x0034
1538766792cSChaoyi Chen #define RK3576_EBC_WIN_DSP_ST			0x0038
1548766792cSChaoyi Chen #define RK3576_EBC_INT_STATUS			0x003C
1558766792cSChaoyi Chen #define RK3576_EBC_VCOM0			0x0040
1568766792cSChaoyi Chen #define RK3576_EBC_VCOM1			0x0044
1578766792cSChaoyi Chen #define RK3576_EBC_VCOM2			0x0048
1588766792cSChaoyi Chen #define RK3576_EBC_VCOM3			0x004C
1598766792cSChaoyi Chen #define RK3576_EBC_CONFIG_DONE			0x0050
1608766792cSChaoyi Chen #define RK3576_EBC_VNUM				0x0054
1618766792cSChaoyi Chen #define RK3576_EBC_WIN_MST2			0x0058
1628766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL2			0x005C
1638766792cSChaoyi Chen #define RK3576_EBC_DSP_CTRL3			0x0060
1648766792cSChaoyi Chen #define RK3576_EBC_WIN0_CTRL			0x0064
1658766792cSChaoyi Chen #define RK3576_EBC_WIN1_CTRL			0x0068
1668766792cSChaoyi Chen #define RK3576_EBC_WIN2_CTRL			0x006C
1678766792cSChaoyi Chen #define RK3576_EBC_SYS_CTRL			0x0070
1688766792cSChaoyi Chen #define RK3576_EBC_LUT_ADDRESS_MAP_0		0x1000
1698766792cSChaoyi Chen 
1708766792cSChaoyi Chen #define RK3576_DSP_FRM_START			BIT(0)
1718766792cSChaoyi Chen #define RK3576_DSP_FRM_START_MASK		BIT(0)
1728766792cSChaoyi Chen 
1738766792cSChaoyi Chen #define RK3576_EINK_MODE_SWAP(x)		UPDATE(x, 31, 31)
1748766792cSChaoyi Chen #define RK3576_EINK_MODE_FRM_SEL(x)		UPDATE(x, 30, 30)
1758766792cSChaoyi Chen #define RK3576_DSP_THREE_WIN_MODE(x)		UPDATE(x, 29, 29)
1768766792cSChaoyi Chen #define RK3576_THREE_WIN_MODE_MASK		BIT(29)
1778766792cSChaoyi Chen #define RK3576_DSP_GD_END(x)			UPDATE(x, 26, 16)
1788766792cSChaoyi Chen #define RK3576_DSP_GD_ST(x)			UPDATE(x, 15, 8)
1798766792cSChaoyi Chen #define RK3576_DSP_SDDW_MODE(x)			UPDATE(x, 7, 6)
1808766792cSChaoyi Chen #define RK3576_EPD_AUO(x)			UPDATE(x, 5, 5)
1818766792cSChaoyi Chen #define RK3576_EPD_PWR(x)			UPDATE(x, 4, 2)
1828766792cSChaoyi Chen #define RK3576_EPD_GDRL(x)			UPDATE(x, 1, 1)
1838766792cSChaoyi Chen #define RK3576_EPD_SDSHR(x)			UPDATE(x, 0, 0)
1848766792cSChaoyi Chen 
1858766792cSChaoyi Chen #define RK3576_DSP_SWAP_MODE(x)			UPDATE(x, 31, 30)
1868766792cSChaoyi Chen #define RK3576_DSP_UPDATE_MODE(x)		UPDATE(x, 29, 29)
1878766792cSChaoyi Chen #define RK3576_DSP_DISPLAY_MODE(x)		UPDATE(x, 28, 28)
1888766792cSChaoyi Chen #define RK3576_UPDATE_MODE_MASK			BIT(29)
1898766792cSChaoyi Chen #define RK3576_DISPLAY_MODE_MASK		BIT(28)
1908766792cSChaoyi Chen #define RK3576_DSP_VCOM_MODE(x)			UPDATE(x, 27, 27)
1918766792cSChaoyi Chen #define RK3576_DSP_SDCLK_DIV(x)			UPDATE(x, 19, 16)
1928766792cSChaoyi Chen #define RK3576_DSP_SDCLK_DIV_MASK		GENMASK(19, 16)
1931020d760SChaoyi Chen #define RK3576_DSP_SDOE_MODE(x)			UPDATE(x, 0, 0)
1948766792cSChaoyi Chen 
1958766792cSChaoyi Chen #define RK3576_DSP_HTOTAL(x)			UPDATE(x, 31, 16)
1968766792cSChaoyi Chen #define RK3576_DSP_HS_END(x)			UPDATE(x, 15, 0)
1978766792cSChaoyi Chen #define RK3576_DSP_HACT_END(x)			UPDATE(x, 31, 16)
1988766792cSChaoyi Chen #define RK3576_DSP_HACT_ST(x)			UPDATE(x, 15, 0)
1998766792cSChaoyi Chen #define RK3576_DSP_VTOTAL(x)			UPDATE(x, 31, 16)
2008766792cSChaoyi Chen #define RK3576_DSP_VS_END(x)			UPDATE(x, 15, 0)
2018766792cSChaoyi Chen #define RK3576_DSP_VACT_END(x)			UPDATE(x, 31, 16)
2028766792cSChaoyi Chen #define RK3576_DSP_VACT_ST(x)			UPDATE(x, 15, 0)
2038766792cSChaoyi Chen #define RK3576_DSP_HEIGHT(x)			UPDATE(x, 31, 16)
2048766792cSChaoyi Chen #define RK3576_DSP_WIDTH(x)			UPDATE(x, 15, 0)
2058766792cSChaoyi Chen 
2068766792cSChaoyi Chen #define RK3576_WIN_VIR_HEIGHT(x)		UPDATE(x, 31, 16)
2078766792cSChaoyi Chen #define RK3576_WIN_VIR_WIDTH(x)			UPDATE(x, 15, 0)
2088766792cSChaoyi Chen #define RK3576_WIN_ACT_HEIGHT(x)		UPDATE(x, 31, 16)
2098766792cSChaoyi Chen #define RK3576_WIN_ACT_WIDTH(x)			UPDATE(x, 15, 0)
2108766792cSChaoyi Chen #define RK3576_WIN_DSP_HEIGHT(x)		UPDATE(x, 31, 16)
2118766792cSChaoyi Chen #define RK3576_WIN_DSP_WIDTH(x)			UPDATE(x, 15, 0)
2128766792cSChaoyi Chen #define RK3576_WIN_DSP_YST(x)			UPDATE(x, 31, 16)
2138766792cSChaoyi Chen #define RK3576_WIN_DSP_XST(x)			UPDATE(x, 15, 0)
2148766792cSChaoyi Chen 
2158766792cSChaoyi Chen #define RK3576_DMA_BURST_LENGTH(x)		UPDATE(x, 25, 24)
2168766792cSChaoyi Chen #define RK3576_WIN2_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 20, 12)
2178766792cSChaoyi Chen #define RK3576_WIN_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 11, 4)
2188766792cSChaoyi Chen #define RK3576_WIN_FMT(x)			UPDATE(x, 2, 0)
2198766792cSChaoyi Chen #define RK3576_WIN_FMT_MASK			GENMASK(2, 0)
2208766792cSChaoyi Chen 
2218766792cSChaoyi Chen #define RK3576_WIN_RID(x)			UPDATE(x, 7, 4)
2228766792cSChaoyi Chen #define RK3576_WIN_AXI_GATHER_NUM(x)		UPDATE(x, 11, 8)
2238766792cSChaoyi Chen #define RK3576_WIN_AXI_GATHER_EN		BIT(1)
2248766792cSChaoyi Chen #define RK3576_WIN_EN				BIT(0)
2258766792cSChaoyi Chen 
2268766792cSChaoyi Chen #define RK3576_WIN2_EMPTY_INT_MASK		BIT(26)
2278766792cSChaoyi Chen #define RK3576_WIN1_EMPTY_INT_MASK		BIT(25)
2288766792cSChaoyi Chen #define RK3576_WIN0_EMPTY_INT_MASK		BIT(24)
2298766792cSChaoyi Chen #define RK3576_FRM_END_INT_MASK			BIT(4)
2308766792cSChaoyi Chen #define RK3576_DSP_FRM_INT_MASK			BIT(6)
2318766792cSChaoyi Chen #define RK3576_LINE_FLAG_INT_MASK		BIT(7)
2328766792cSChaoyi Chen 
2338766792cSChaoyi Chen #define RK3576_DSP_SDCE_WIDTH(x)		UPDATE(x, 23, 12)
2348766792cSChaoyi Chen #define RK3576_DSP_SDCE_WIDTH_MASK(x)		GENMASK(x, 23, 12)
2358766792cSChaoyi Chen #define RK3576_DSP_FRM_TOTAL(x)			UPDATE(x, 11, 4)
2368766792cSChaoyi Chen #define RK3576_DSP_FRM_TOTAL_MASK		GENMASK(11, 4)
2378766792cSChaoyi Chen #define RK3576_DSP_EINK_MODE(x)			UPDATE(x, 2, 2)
2388766792cSChaoyi Chen #define RK3576_DSP_EINK_MODE_MASK		BIT(2)
2398766792cSChaoyi Chen #define RK3576_SW_BURST_CTRL			BIT(1)
2408766792cSChaoyi Chen #define RK3576_DSP_OUT_LOW			BIT(0)
2418766792cSChaoyi Chen 
2428766792cSChaoyi Chen #define RK3576_SW_AXI_RD_URGENCY_EN		BIT(24)
2438766792cSChaoyi Chen #define RK3576_SW_AXI_MAX_OUTSTAND_NUM(x)	UPDATE(x, 20, 16)
2448766792cSChaoyi Chen #define RK3576_SW_AXI_MAX_OUTSTAND_EN		BIT(12)
2458766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_THRESHOLD(x)	UPDATE(x, 11, 8)
2468766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_VALUE(x)		UPDATE(x, 6, 5)
2478766792cSChaoyi Chen #define RK3576_SW_NOC_HURRY_EN			BIT(4)
2488766792cSChaoyi Chen #define RK3576_SW_NOC_QOS_VALUE(x)		UPDATE(x, 2, 1)
2498766792cSChaoyi Chen #define RK3576_SW_NOC_QOS_EN			BIT(0)
2508766792cSChaoyi Chen 
25193a7515aSWenping Zhang #define PMU_BASE_ADDR		0xfdd90000
25293a7515aSWenping Zhang #define PMU_PWR_GATE_SFTCON	0xA0
25393a7515aSWenping Zhang #define PMU_PWR_DWN_ST		0x98
25493a7515aSWenping Zhang #define RGA_PD_OFF		BIT(5)
25593a7515aSWenping Zhang #define RGA_PD_STAT		BIT(5)
25693a7515aSWenping Zhang enum ebc_win_data_fmt {
25793a7515aSWenping Zhang 	Y_DATA_4BPP = 0,
25893a7515aSWenping Zhang 	Y_DATA_8BPP = 1,
25993a7515aSWenping Zhang 	RGB888 = 2,
26093a7515aSWenping Zhang 	RGB565 = 3,
26193a7515aSWenping Zhang };
26293a7515aSWenping Zhang 
26339939100SWenping Zhang static volatile int last_frame_done = -1;
regs_dump(struct ebc_tcon_priv * tcon)26493a7515aSWenping Zhang static inline void regs_dump(struct ebc_tcon_priv *tcon)
26593a7515aSWenping Zhang {
26693a7515aSWenping Zhang 	int i;
26793a7515aSWenping Zhang 
26893a7515aSWenping Zhang 	printf("dump registers:\n");
26993a7515aSWenping Zhang 	for (i = 0; i <= EBC_WIN_MST2; i = i + 4) {
27093a7515aSWenping Zhang 		if (!(i % 16))
27193a7515aSWenping Zhang 			printf("\n 0x%p:\t", tcon->reg + i);
27293a7515aSWenping Zhang 		printf("0x%x\t", readl(tcon->reg + i));
27393a7515aSWenping Zhang 	}
27493a7515aSWenping Zhang 	printf("\nlut data:\n");
27593a7515aSWenping Zhang 	for (i = 0x1000; i <= 0x1100; i = i + 4) {
27693a7515aSWenping Zhang 		if (!(i % 16))
27793a7515aSWenping Zhang 			printf("\n 0x%p:\t", tcon->reg + i);
27893a7515aSWenping Zhang 		printf("0x%x\t", readl(tcon->reg + i));
27993a7515aSWenping Zhang 	}
28093a7515aSWenping Zhang 	printf("\n");
28193a7515aSWenping Zhang }
28293a7515aSWenping Zhang 
2831a77b5f7SChaoyi Chen /* RK356X ebc power domain is enabled by default when power up */
ebc_power_domain(int on)2841a77b5f7SChaoyi Chen static int __maybe_unused ebc_power_domain(int on)
28593a7515aSWenping Zhang {
28693a7515aSWenping Zhang 	u32 pd_reg;
28793a7515aSWenping Zhang 	u32 pd_stat;
28893a7515aSWenping Zhang 	int delay = 0;
28993a7515aSWenping Zhang 
29093a7515aSWenping Zhang 	if (on) {
29193a7515aSWenping Zhang 		pd_reg = RGA_PD_OFF << 16;
29293a7515aSWenping Zhang 		pd_stat = RGA_PD_STAT;
29393a7515aSWenping Zhang 	} else {
29493a7515aSWenping Zhang 		pd_reg = RGA_PD_OFF | (RGA_PD_OFF << 16);
29593a7515aSWenping Zhang 		pd_stat = ~((u32)RGA_PD_STAT);
29693a7515aSWenping Zhang 	}
29793a7515aSWenping Zhang 
29893a7515aSWenping Zhang 	/* enable rga pd for ebc tcon*/
29993a7515aSWenping Zhang 	writel(pd_reg, PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON);
30093a7515aSWenping Zhang 	delay = 1000;
30193a7515aSWenping Zhang 	do {
30293a7515aSWenping Zhang 		udelay(1);
30393a7515aSWenping Zhang 		delay--;
30493a7515aSWenping Zhang 		if (delay == 0) {
30593a7515aSWenping Zhang 			printf("Enable rga pd for ebc failed !\n");
30693a7515aSWenping Zhang 			return -1;
30793a7515aSWenping Zhang 		}
30893a7515aSWenping Zhang 	} while (readl(PMU_BASE_ADDR + PMU_PWR_DWN_ST) & pd_stat);
30993a7515aSWenping Zhang 
31093a7515aSWenping Zhang 	return 0;
31193a7515aSWenping Zhang }
31293a7515aSWenping Zhang 
tcon_write(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int value)31393a7515aSWenping Zhang static inline void tcon_write(struct ebc_tcon_priv *tcon, unsigned int reg,
31493a7515aSWenping Zhang 			      unsigned int value)
31593a7515aSWenping Zhang {
31693a7515aSWenping Zhang 	unsigned int *cache = tcon->regcache + (reg >> 2);
31793a7515aSWenping Zhang 
31893a7515aSWenping Zhang 	writel(value, tcon->reg + reg);
31993a7515aSWenping Zhang 	*cache = value;
32093a7515aSWenping Zhang }
32193a7515aSWenping Zhang 
tcon_read(struct ebc_tcon_priv * tcon,unsigned int reg)32293a7515aSWenping Zhang static inline unsigned int tcon_read(struct ebc_tcon_priv *tcon,
32393a7515aSWenping Zhang 				     unsigned int reg)
32493a7515aSWenping Zhang {
32593a7515aSWenping Zhang 	return readl(tcon->reg + reg);
32693a7515aSWenping Zhang }
32793a7515aSWenping Zhang 
tcon_update_bits(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int mask,unsigned int val)32893a7515aSWenping Zhang static inline void tcon_update_bits(struct ebc_tcon_priv *tcon,
32993a7515aSWenping Zhang 				    unsigned int reg, unsigned int mask,
33093a7515aSWenping Zhang 				    unsigned int val)
33193a7515aSWenping Zhang {
33293a7515aSWenping Zhang 	unsigned int tmp;
33393a7515aSWenping Zhang 	unsigned int *cache = tcon->regcache + (reg >> 2);
33493a7515aSWenping Zhang 
33593a7515aSWenping Zhang 	tmp = *cache & ~mask;
33693a7515aSWenping Zhang 	tmp |= val & mask;
33793a7515aSWenping Zhang 
33893a7515aSWenping Zhang 	writel(tmp, tcon->reg + reg);
33993a7515aSWenping Zhang 	*cache = tmp;
34093a7515aSWenping Zhang }
34193a7515aSWenping Zhang 
34293a7515aSWenping Zhang #ifdef CONFIG_IRQ
ebc_irq_handler(int irq,void * data)34393a7515aSWenping Zhang static void ebc_irq_handler(int irq, void *data)
34493a7515aSWenping Zhang {
34593a7515aSWenping Zhang 	u32 intr_status;
34693a7515aSWenping Zhang 	struct udevice *dev = data;
34793a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
34893a7515aSWenping Zhang 
34993a7515aSWenping Zhang 	intr_status = readl(tcon->reg + EBC_INT_STATUS);
35093a7515aSWenping Zhang 
35193a7515aSWenping Zhang 	if (intr_status & DSP_END_INT) {
35293a7515aSWenping Zhang 		tcon_update_bits(tcon, EBC_INT_STATUS,
35393a7515aSWenping Zhang 				 DSP_END_INT_CLR, DSP_END_INT_CLR);
35439939100SWenping Zhang 		last_frame_done = 1;
35593a7515aSWenping Zhang 	}
35693a7515aSWenping Zhang }
35793a7515aSWenping Zhang #endif
35893a7515aSWenping Zhang 
tcon_cfg_done(struct ebc_tcon_priv * tcon)35993a7515aSWenping Zhang static inline void tcon_cfg_done(struct ebc_tcon_priv *tcon)
36093a7515aSWenping Zhang {
36193a7515aSWenping Zhang 	writel(REG_LOAD_GLOBAL_EN, tcon->reg + EBC_CONFIG_DONE);
36293a7515aSWenping Zhang }
36393a7515aSWenping Zhang 
3648766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_enable(struct udevice * dev,struct ebc_panel * panel)36593a7515aSWenping Zhang static int ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel)
36693a7515aSWenping Zhang {
367f968f3bcSZorro Liu 	int ret;
36893a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
369dfc47936SZorro Liu 	u32 width, height, vir_width, vir_height;
370dfc47936SZorro Liu 
371dfc47936SZorro Liu 	if (panel->rearrange) {
372dfc47936SZorro Liu 		width = panel->width * 2;
373dfc47936SZorro Liu 		height = panel->height / 2;
374dfc47936SZorro Liu 		vir_width = panel->vir_width * 2;
375dfc47936SZorro Liu 		vir_height = panel->vir_height / 2;
376dfc47936SZorro Liu 	} else {
377dfc47936SZorro Liu 		width = panel->width;
378dfc47936SZorro Liu 		height = panel->height;
379dfc47936SZorro Liu 		vir_width = panel->vir_width;
380dfc47936SZorro Liu 		vir_height = panel->vir_height;
381dfc47936SZorro Liu 	}
38293a7515aSWenping Zhang 
38393a7515aSWenping Zhang 	/* panel timing and win info config */
38493a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_HTIMING0,
38593a7515aSWenping Zhang 		   DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl +
386514e00a9SZorro Liu 			      panel->lel) | DSP_HS_END(panel->lsl));
38793a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_HTIMING1,
38893a7515aSWenping Zhang 		   DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) |
38993a7515aSWenping Zhang 		   DSP_HACT_ST(panel->lsl + panel->lbl - 1));
39093a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_VTIMING0,
39193a7515aSWenping Zhang 		   DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl +
39293a7515aSWenping Zhang 			      panel->fel) | DSP_VS_END(panel->fsl));
39393a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_VTIMING1,
39493a7515aSWenping Zhang 		   DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) |
39593a7515aSWenping Zhang 		   DSP_VACT_ST(panel->fsl + panel->fbl));
39693a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_ACT_INFO,
397db4dd7a8SChaoyi Chen 		   DSP_HEIGHT(vir_height) |
398db4dd7a8SChaoyi Chen 		   DSP_WIDTH(vir_width));
39993a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_VIR,
400db4dd7a8SChaoyi Chen 		   WIN_VIR_HEIGHT(height) |
401db4dd7a8SChaoyi Chen 		   WIN_VIR_WIDTH(width));
40293a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_ACT,
403dfc47936SZorro Liu 		   WIN_ACT_HEIGHT(height) |
404dfc47936SZorro Liu 		   WIN_ACT_WIDTH(width));
40593a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_DSP,
406dfc47936SZorro Liu 		   WIN_DSP_HEIGHT(height) |
407dfc47936SZorro Liu 		   WIN_DSP_WIDTH(width));
40893a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_DSP_ST,
40993a7515aSWenping Zhang 		   WIN_DSP_YST(panel->fsl + panel->fbl) |
41093a7515aSWenping Zhang 		   WIN_DSP_XST(panel->lsl + panel->lbl));
41193a7515aSWenping Zhang 
41293a7515aSWenping Zhang 	/* win2 fifo is 512x128, win fifo is 256x128,
41393a7515aSWenping Zhang 	 * we set fifo almost value (fifo_size - 16)
41493a7515aSWenping Zhang 	 * burst_reg = 7 mean ahb burst is incr16
41593a7515aSWenping Zhang 	 */
41693a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_CTRL,
41793a7515aSWenping Zhang 		   WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1) |
41893a7515aSWenping Zhang 		   BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) |
41993a7515aSWenping Zhang 		   WIN_FMT(Y_DATA_4BPP));
42093a7515aSWenping Zhang 
42193a7515aSWenping Zhang 	/*
42293a7515aSWenping Zhang 	 * EBC_EPD_CTRL info:
42393a7515aSWenping Zhang 	 * DSP_GD_ST: GCLK rising edge point(SCLK), which count from
42493a7515aSWenping Zhang 	 *            the rasing edge of hsync(spec is wrong, count
42593a7515aSWenping Zhang 	 *            from rasing edge of hsync, not falling edge of hsync)
42693a7515aSWenping Zhang 	 * DSP_GD_END : GCLK falling edge point(SCLK), which count from
42793a7515aSWenping Zhang 	 *              the rasing edge of hsync
42893a7515aSWenping Zhang 	 * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
42993a7515aSWenping Zhang 	 * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
43093a7515aSWenping Zhang 	 * EPD_AUO: 0: EINK; 1:AUO
43193a7515aSWenping Zhang 	 * EPD_GDRL: gate scanning direction: 1:button to top 0:top to button
43293a7515aSWenping Zhang 	 * EPD_SDSHR: source scanning direction 1:right to left 0:left to right
43393a7515aSWenping Zhang 	 */
43493a7515aSWenping Zhang 	tcon_write(tcon, EBC_EPD_CTRL,
43593a7515aSWenping Zhang 		   EINK_MODE_SWAP(1) |
43693a7515aSWenping Zhang 		   DSP_GD_ST(panel->lsl + panel->gdck_sta) |
43793a7515aSWenping Zhang 		   DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) |
43893a7515aSWenping Zhang 		   DSP_THREE_WIN_MODE(0) |
43993a7515aSWenping Zhang 		   DSP_SDDW_MODE(!!panel->panel_16bit) |
44093a7515aSWenping Zhang 		   EPD_AUO(0) |
44193a7515aSWenping Zhang 		   EPD_GDRL(1) |
44293a7515aSWenping Zhang 		   EPD_SDSHR(1));
44393a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_START,
44493a7515aSWenping Zhang 		   DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL);
44593a7515aSWenping Zhang 
44693a7515aSWenping Zhang 	tcon_write(tcon, EBC_DSP_CTRL,
44793a7515aSWenping Zhang 		   DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) |
44893a7515aSWenping Zhang 		   DSP_VCOM_MODE(1) |
44993a7515aSWenping Zhang 		   DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3));
45093a7515aSWenping Zhang 
45193a7515aSWenping Zhang 	tcon_cfg_done(tcon);
45293a7515aSWenping Zhang 
453f968f3bcSZorro Liu 	ret = clk_set_rate(&tcon->dclk, panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1));
454f968f3bcSZorro Liu 	if (ret < 0) {
455f968f3bcSZorro Liu 		printf("%s: set clock rate failed, %d\n", __func__, ret);
456f968f3bcSZorro Liu 		return ret;
457f968f3bcSZorro Liu 	}
458f968f3bcSZorro Liu 
45993a7515aSWenping Zhang 	return 0;
46093a7515aSWenping Zhang }
4618766792cSChaoyi Chen #endif
46293a7515aSWenping Zhang 
ebc_tcon_disable(struct udevice * dev)46393a7515aSWenping Zhang static int ebc_tcon_disable(struct udevice *dev)
46493a7515aSWenping Zhang {
46593a7515aSWenping Zhang 	return 0;
46693a7515aSWenping Zhang }
46793a7515aSWenping Zhang 
4688766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_dsp_mode_set(struct udevice * dev,int update_mode,int display_mode,int three_win_mode,int eink_mode)46993a7515aSWenping Zhang static int ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode,
47093a7515aSWenping Zhang 				 int display_mode, int three_win_mode,
47193a7515aSWenping Zhang 				 int eink_mode)
47293a7515aSWenping Zhang {
47393a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
47493a7515aSWenping Zhang 
47593a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_DSP_CTRL,
47693a7515aSWenping Zhang 			 UPDATE_MODE_MASK | DISPLAY_MODE_MASK,
47793a7515aSWenping Zhang 			 DSP_UPDATE_MODE(!!update_mode) |
47893a7515aSWenping Zhang 			 DSP_DISPLAY_MODE(!!display_mode));
47993a7515aSWenping Zhang 
48093a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK,
48193a7515aSWenping Zhang 			 DSP_THREE_WIN_MODE(!!three_win_mode));
48293a7515aSWenping Zhang 	/* always set frm start bit 0 before real frame start */
48393a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_DSP_START,
48493a7515aSWenping Zhang 			 DSP_EINK_MODE_MASK | DSP_FRM_START_MASK,
48593a7515aSWenping Zhang 			 DSP_EINK_MODE(!!eink_mode));
48693a7515aSWenping Zhang 	tcon_cfg_done(tcon);
48793a7515aSWenping Zhang 
48893a7515aSWenping Zhang 	return 0;
48993a7515aSWenping Zhang }
4908766792cSChaoyi Chen #endif
49193a7515aSWenping Zhang 
ebc_tcon_image_addr_set(struct udevice * dev,u32 pre_image_addr,u32 cur_image_addr)49293a7515aSWenping Zhang static int ebc_tcon_image_addr_set(struct udevice *dev, u32 pre_image_addr,
49393a7515aSWenping Zhang 				   u32 cur_image_addr)
49493a7515aSWenping Zhang {
49593a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
49693a7515aSWenping Zhang 
49793a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_MST0, pre_image_addr);
49893a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_MST1, cur_image_addr);
49993a7515aSWenping Zhang 	tcon_cfg_done(tcon);
50093a7515aSWenping Zhang 
50193a7515aSWenping Zhang 	return 0;
50293a7515aSWenping Zhang }
50393a7515aSWenping Zhang 
ebc_tcon_frame_addr_set(struct udevice * dev,u32 frame_addr)50493a7515aSWenping Zhang static int ebc_tcon_frame_addr_set(struct udevice *dev, u32 frame_addr)
50593a7515aSWenping Zhang {
50693a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
50793a7515aSWenping Zhang 
50893a7515aSWenping Zhang 	tcon_write(tcon, EBC_WIN_MST2, frame_addr);
50993a7515aSWenping Zhang 	tcon_cfg_done(tcon);
51093a7515aSWenping Zhang 
51193a7515aSWenping Zhang 	return 0;
51293a7515aSWenping Zhang }
51393a7515aSWenping Zhang 
ebc_tcon_lut_data_set(struct udevice * dev,unsigned int * lut_data,int frame_count,int lut_32)51493a7515aSWenping Zhang static int ebc_tcon_lut_data_set(struct udevice *dev, unsigned int *lut_data,
51593a7515aSWenping Zhang 				 int frame_count, int lut_32)
51693a7515aSWenping Zhang {
51793a7515aSWenping Zhang 	int i, lut_size;
51893a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
51993a7515aSWenping Zhang 
52093a7515aSWenping Zhang 	if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) {
52193a7515aSWenping Zhang 		dev_err(tcon->dev, "frame count over flow\n");
52293a7515aSWenping Zhang 		return -1;
52393a7515aSWenping Zhang 	}
52493a7515aSWenping Zhang 
52593a7515aSWenping Zhang 	if (lut_32)
52693a7515aSWenping Zhang 		lut_size = frame_count * 64;
52793a7515aSWenping Zhang 	else
52893a7515aSWenping Zhang 		lut_size = frame_count * 16;
52993a7515aSWenping Zhang 
53093a7515aSWenping Zhang 	for (i = 0; i < lut_size; i++)
53193a7515aSWenping Zhang 		tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]);
53293a7515aSWenping Zhang 
53393a7515aSWenping Zhang 	tcon_cfg_done(tcon);
53493a7515aSWenping Zhang 
53593a7515aSWenping Zhang 	return 0;
53693a7515aSWenping Zhang }
53793a7515aSWenping Zhang 
wait_for_last_frame_complete(struct udevice * dev)53893a7515aSWenping Zhang static int wait_for_last_frame_complete(struct udevice *dev)
53993a7515aSWenping Zhang {
54093a7515aSWenping Zhang #ifndef CONFIG_IRQ
54193a7515aSWenping Zhang 	u32 intr_status;
54293a7515aSWenping Zhang #endif
54393a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
54493a7515aSWenping Zhang 
54593a7515aSWenping Zhang #ifdef CONFIG_IRQ
54639939100SWenping Zhang 	while (1) {
54739939100SWenping Zhang 		if ((last_frame_done == -1) || (last_frame_done == 1))
54839939100SWenping Zhang 			break;
54993a7515aSWenping Zhang 		msleep(1);
55039939100SWenping Zhang 	}
55193a7515aSWenping Zhang #else
55293a7515aSWenping Zhang 	/* wait for frame display end*/
55339939100SWenping Zhang 	while (1) {
55439939100SWenping Zhang 		/* first frame don't need to wait*/
55539939100SWenping Zhang 		if (last_frame_done == -1)
55639939100SWenping Zhang 			break;
55793a7515aSWenping Zhang 		intr_status = readl(tcon->reg + EBC_INT_STATUS);
55839939100SWenping Zhang 		if (intr_status & DSP_END_INT)
55939939100SWenping Zhang 			break;
56039939100SWenping Zhang 		msleep(1);
56139939100SWenping Zhang 	}
56293a7515aSWenping Zhang #endif
56393a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_INT_STATUS,
56493a7515aSWenping Zhang 			 DSP_END_INT_CLR, DSP_END_INT_CLR);
56593a7515aSWenping Zhang 
56693a7515aSWenping Zhang 	return 0;
56793a7515aSWenping Zhang }
56893a7515aSWenping Zhang 
5698766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
ebc_tcon_frame_start(struct udevice * dev,int frame_total)57093a7515aSWenping Zhang static int ebc_tcon_frame_start(struct udevice *dev, int frame_total)
57193a7515aSWenping Zhang {
57293a7515aSWenping Zhang 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
57393a7515aSWenping Zhang 
57493a7515aSWenping Zhang 	tcon_write(tcon, EBC_INT_STATUS,
57593a7515aSWenping Zhang 		   LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK);
57693a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_DSP_START,
57793a7515aSWenping Zhang 			 DSP_FRM_TOTAL_MASK, DSP_FRM_TOTAL(frame_total - 1));
57893a7515aSWenping Zhang 	tcon_cfg_done(tcon);
57993a7515aSWenping Zhang 
58093a7515aSWenping Zhang 	tcon_update_bits(tcon, EBC_DSP_START,
58193a7515aSWenping Zhang 			 DSP_FRM_START_MASK, DSP_FRM_START);
58239939100SWenping Zhang 	last_frame_done = 0;
58393a7515aSWenping Zhang 	return 0;
58493a7515aSWenping Zhang }
5858766792cSChaoyi Chen #endif
5868766792cSChaoyi Chen 
5878766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
rk3576_ebc_tcon_enable(struct udevice * dev,struct ebc_panel * panel)5888766792cSChaoyi Chen static int rk3576_ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel)
5898766792cSChaoyi Chen {
5908766792cSChaoyi Chen 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
5918766792cSChaoyi Chen 	u32 width, height, vir_width, vir_height;
5920b3fbe3bSChaoyi Chen 	u32 val;
5930b3fbe3bSChaoyi Chen 	int ret;
5948766792cSChaoyi Chen 
5958766792cSChaoyi Chen 	if (panel->rearrange) {
5968766792cSChaoyi Chen 		width = panel->width * 2;
5978766792cSChaoyi Chen 		height = panel->height / 2;
5988766792cSChaoyi Chen 		vir_width = panel->vir_width * 2;
5998766792cSChaoyi Chen 		vir_height = panel->vir_height / 2;
6008766792cSChaoyi Chen 	} else {
6018766792cSChaoyi Chen 		width = panel->width;
6028766792cSChaoyi Chen 		height = panel->height;
6038766792cSChaoyi Chen 		vir_width = panel->vir_width;
6048766792cSChaoyi Chen 		vir_height = panel->vir_height;
6058766792cSChaoyi Chen 	}
6068766792cSChaoyi Chen 
6078766792cSChaoyi Chen 	/* panel timing and win info config */
6088766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_HTIMING0,
6098766792cSChaoyi Chen 		   RK3576_DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl + panel->lel) |
6108766792cSChaoyi Chen 		   RK3576_DSP_HS_END(panel->lsl));
6118766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_HTIMING1,
6128766792cSChaoyi Chen 		   RK3576_DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) |
6138766792cSChaoyi Chen 		   RK3576_DSP_HACT_ST(panel->lsl + panel->lbl - 1));
6148766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_VTIMING0,
6158766792cSChaoyi Chen 		   RK3576_DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl + panel->fel) |
6168766792cSChaoyi Chen 		   RK3576_DSP_VS_END(panel->fsl));
6178766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_VTIMING1,
6188766792cSChaoyi Chen 		   RK3576_DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) |
6198766792cSChaoyi Chen 		   RK3576_DSP_VACT_ST(panel->fsl + panel->fbl));
6208766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_ACT_INFO,
621db4dd7a8SChaoyi Chen 		   RK3576_DSP_HEIGHT(vir_height) |
622db4dd7a8SChaoyi Chen 		   RK3576_DSP_WIDTH(vir_width));
6238766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN_VIR,
624db4dd7a8SChaoyi Chen 		   RK3576_WIN_VIR_HEIGHT(height) |
625db4dd7a8SChaoyi Chen 		   RK3576_WIN_VIR_WIDTH(width));
6268766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN_ACT,
6278766792cSChaoyi Chen 		   RK3576_WIN_ACT_HEIGHT(height) |
6288766792cSChaoyi Chen 		   RK3576_WIN_ACT_WIDTH(width));
6298766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN_DSP,
6308766792cSChaoyi Chen 		   RK3576_WIN_DSP_HEIGHT(height) |
6318766792cSChaoyi Chen 		   RK3576_WIN_DSP_WIDTH(width));
6320b3fbe3bSChaoyi Chen 	if (width != vir_width || height != vir_height) {
6330b3fbe3bSChaoyi Chen 		if (((vir_width - width) / 2) % 2)
6340b3fbe3bSChaoyi Chen 			dev_warn(dev,
6350b3fbe3bSChaoyi Chen 				 "Margin left/right between width/vir_width must be same\n");
6360b3fbe3bSChaoyi Chen 		if (((vir_height - height) / 2) % 2)
6370b3fbe3bSChaoyi Chen 			dev_warn(tcon->dev,
6380b3fbe3bSChaoyi Chen 				 "Margin top/bottom between height/vir_height must be same\n");
6390b3fbe3bSChaoyi Chen 
6400b3fbe3bSChaoyi Chen 		val = panel->panel_16bit ? 8 : 4;
6410b3fbe3bSChaoyi Chen 		if (((vir_width - width) / 2) % val)
6420b3fbe3bSChaoyi Chen 			dev_warn(dev,
6430b3fbe3bSChaoyi Chen 				 "Margin left/right between width/vir_width must align with %d\n",
6440b3fbe3bSChaoyi Chen 				 val);
6450b3fbe3bSChaoyi Chen 
6460b3fbe3bSChaoyi Chen 		val = RK3576_WIN_DSP_YST(panel->fsl + panel->fbl + (vir_height - height) / 2);
6470b3fbe3bSChaoyi Chen 		if (panel->panel_16bit)
6480b3fbe3bSChaoyi Chen 			val |= RK3576_WIN_DSP_XST(panel->lsl + panel->lbl +
6490b3fbe3bSChaoyi Chen 						  (vir_width - width) / 2 / 8);
6500b3fbe3bSChaoyi Chen 		else
6510b3fbe3bSChaoyi Chen 			val |= RK3576_WIN_DSP_XST(panel->lsl + panel->lbl +
6520b3fbe3bSChaoyi Chen 						  (vir_width - width) / 2 / 4);
6530b3fbe3bSChaoyi Chen 		tcon_write(tcon, RK3576_EBC_WIN_DSP_ST, val);
6540b3fbe3bSChaoyi Chen 	} else {
6558766792cSChaoyi Chen 		tcon_write(tcon, RK3576_EBC_WIN_DSP_ST,
6568766792cSChaoyi Chen 			   RK3576_WIN_DSP_YST(panel->fsl + panel->fbl) |
6578766792cSChaoyi Chen 			   RK3576_WIN_DSP_XST(panel->lsl + panel->lbl));
6580b3fbe3bSChaoyi Chen 	}
6598766792cSChaoyi Chen 
6608766792cSChaoyi Chen 	/*
6618766792cSChaoyi Chen 	 * win2 fifo is 512x64, win fifo is 256x64,
6628766792cSChaoyi Chen 	 * we set fifo almost value (fifo_size - 16(brust_length))
6638766792cSChaoyi Chen 	 *
6648766792cSChaoyi Chen 	 * dma_burst_length mean axi burst length = 16
6658766792cSChaoyi Chen 	 */
6668766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN_CTRL,
6678766792cSChaoyi Chen 		   RK3576_WIN2_FIFO_ALMOST_FULL_LEVEL(496) |
6688766792cSChaoyi Chen 		   RK3576_DMA_BURST_LENGTH(0) |
6698766792cSChaoyi Chen 		   RK3576_WIN_FIFO_ALMOST_FULL_LEVEL(240) |
6708766792cSChaoyi Chen 		   RK3576_WIN_FMT(Y_DATA_4BPP));
6718766792cSChaoyi Chen 
6728766792cSChaoyi Chen 	/* win0 always enable */
6738766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN0_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
6748766792cSChaoyi Chen 		   RK3576_WIN_AXI_GATHER_EN | RK3576_WIN_RID(1) |
6758766792cSChaoyi Chen 		   RK3576_WIN_EN);
6768766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN1_CTRL, RK3576_WIN_RID(2));
6778766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN2_CTRL, RK3576_WIN_RID(3));
6788766792cSChaoyi Chen 
6798766792cSChaoyi Chen 	/*
6808766792cSChaoyi Chen 	 * RK3576_EBC_EPD_CTRL info:
6818766792cSChaoyi Chen 	 * DSP_GD_END : GCLK falling edge point(SCLK), which count from the rising edge of hsync
6828766792cSChaoyi Chen 	 * DSP_GD_ST: GCLK rising edge point(SCLK), which count from the rising edge of hsync
6838766792cSChaoyi Chen 	 * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
6848766792cSChaoyi Chen 	 * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
6858766792cSChaoyi Chen 	 * EPD_AUO: 0: EINK; 1:AUO
6868766792cSChaoyi Chen 	 * EPD_GDRL: gate scanning direction: 1: button to top 0: top to button
6878766792cSChaoyi Chen 	 * EPD_SDSHR: source scanning direction 1: right to left 0: left to right
6888766792cSChaoyi Chen 	 */
6898766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_EPD_CTRL, RK3576_EINK_MODE_SWAP(1) |
6908766792cSChaoyi Chen 		   RK3576_DSP_GD_ST(panel->lsl + panel->gdck_sta) |
6918766792cSChaoyi Chen 		   RK3576_DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) |
6928766792cSChaoyi Chen 		   RK3576_DSP_THREE_WIN_MODE(0) |
6938766792cSChaoyi Chen 		   RK3576_DSP_SDDW_MODE(!!panel->panel_16bit) |
6948766792cSChaoyi Chen 		   RK3576_EPD_AUO(0) |
6958766792cSChaoyi Chen 		   RK3576_EPD_GDRL(1) |
6968766792cSChaoyi Chen 		   RK3576_EPD_SDSHR(1));
6978766792cSChaoyi Chen 
6988766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_START, 0);
6991020d760SChaoyi Chen 
7001020d760SChaoyi Chen 	if (panel->sdce_width == 0)
7011020d760SChaoyi Chen 		val = RK3576_DSP_SDCE_WIDTH(panel->ldl);
7021020d760SChaoyi Chen 	else
7031020d760SChaoyi Chen 		val = RK3576_DSP_SDCE_WIDTH(panel->sdce_width);
7041020d760SChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_CTRL2, RK3576_SW_BURST_CTRL | val);
7051020d760SChaoyi Chen 
7061020d760SChaoyi Chen 	/**
7071020d760SChaoyi Chen 	 *  SDOE_MODE 1 : sdce signal act as vden
7081020d760SChaoyi Chen 	 *  SDOE_MODE 0 : sdce signal act as hden
7091020d760SChaoyi Chen 	 */
7101020d760SChaoyi Chen 	if (panel->sdoe_mode == 1)
7111020d760SChaoyi Chen 		val = RK3576_DSP_SDOE_MODE(1);
7121020d760SChaoyi Chen 	else
7131020d760SChaoyi Chen 		val = RK3576_DSP_SDOE_MODE(0);
7148766792cSChaoyi Chen 
7158766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_CTRL,
7161020d760SChaoyi Chen 		   RK3576_DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) | RK3576_DSP_VCOM_MODE(1) |
7171020d760SChaoyi Chen 		   RK3576_DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3) | val);
7188766792cSChaoyi Chen 
7198766792cSChaoyi Chen 	tcon_cfg_done(tcon);
7208766792cSChaoyi Chen 
7218766792cSChaoyi Chen 	ret = clk_set_rate(&tcon->dclk,
7228766792cSChaoyi Chen 			   panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1));
7238766792cSChaoyi Chen 	if (ret < 0) {
7248766792cSChaoyi Chen 		printf("%s: set clock rate failed, %d\n", __func__, ret);
7258766792cSChaoyi Chen 		return ret;
7268766792cSChaoyi Chen 	}
7278766792cSChaoyi Chen 
7288766792cSChaoyi Chen 	return 0;
7298766792cSChaoyi Chen }
7308766792cSChaoyi Chen 
rk3576_ebc_tcon_dsp_mode_set(struct udevice * dev,int update_mode,int display_mode,int three_win_mode,int eink_mode)7318766792cSChaoyi Chen static int rk3576_ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode,
7328766792cSChaoyi Chen 					int display_mode, int three_win_mode,
7338766792cSChaoyi Chen 					int eink_mode)
7348766792cSChaoyi Chen {
7358766792cSChaoyi Chen 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
7368766792cSChaoyi Chen 
7378766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN1_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
7388766792cSChaoyi Chen 		   RK3576_WIN_AXI_GATHER_EN |
7398766792cSChaoyi Chen 		   RK3576_WIN_RID(2) |
7408766792cSChaoyi Chen 		   ((!!display_mode) | (!!three_win_mode)));
7418766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_WIN2_CTRL, RK3576_WIN_AXI_GATHER_NUM(8) |
7428766792cSChaoyi Chen 		   RK3576_WIN_AXI_GATHER_EN |
7438766792cSChaoyi Chen 		   RK3576_WIN_RID(3) |
7448766792cSChaoyi Chen 		   (!!three_win_mode));
7458766792cSChaoyi Chen 
7468766792cSChaoyi Chen 	tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL,
7478766792cSChaoyi Chen 			 RK3576_UPDATE_MODE_MASK | RK3576_DISPLAY_MODE_MASK,
7488766792cSChaoyi Chen 			 RK3576_DSP_UPDATE_MODE(!!update_mode) |
7498766792cSChaoyi Chen 			 RK3576_DSP_DISPLAY_MODE(!!display_mode));
7508766792cSChaoyi Chen 	tcon_update_bits(tcon, RK3576_EBC_EPD_CTRL, RK3576_THREE_WIN_MODE_MASK,
7518766792cSChaoyi Chen 			 RK3576_DSP_THREE_WIN_MODE(!!three_win_mode));
7528766792cSChaoyi Chen 	/* always set frm start bit 0 before real frame start */
7538766792cSChaoyi Chen 	tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL2, RK3576_DSP_EINK_MODE_MASK,
7548766792cSChaoyi Chen 			 RK3576_DSP_EINK_MODE(!!eink_mode));
7558766792cSChaoyi Chen 	tcon_cfg_done(tcon);
7568766792cSChaoyi Chen 
7578766792cSChaoyi Chen 	return 0;
7588766792cSChaoyi Chen }
7598766792cSChaoyi Chen 
rk3576_ebc_tcon_frame_start(struct udevice * dev,int frame_total)7608766792cSChaoyi Chen static int rk3576_ebc_tcon_frame_start(struct udevice *dev, int frame_total)
7618766792cSChaoyi Chen {
7628766792cSChaoyi Chen 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
7638766792cSChaoyi Chen 
7648766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_INT_STATUS, RK3576_LINE_FLAG_INT_MASK |
7658766792cSChaoyi Chen 		   RK3576_DSP_FRM_INT_MASK | RK3576_FRM_END_INT_MASK |
7668766792cSChaoyi Chen 		   RK3576_WIN2_EMPTY_INT_MASK | RK3576_WIN1_EMPTY_INT_MASK |
7678766792cSChaoyi Chen 		   RK3576_WIN0_EMPTY_INT_MASK);
7688766792cSChaoyi Chen 	/* always set frm start bit 0 before real frame start */
7698766792cSChaoyi Chen 	tcon_update_bits(tcon, RK3576_EBC_DSP_CTRL2, RK3576_DSP_FRM_TOTAL_MASK,
7708766792cSChaoyi Chen 			 RK3576_DSP_FRM_TOTAL(frame_total - 1));
7718766792cSChaoyi Chen 	tcon_cfg_done(tcon);
7728766792cSChaoyi Chen 
7738766792cSChaoyi Chen 	last_frame_done = 0;
7748766792cSChaoyi Chen 	tcon_write(tcon, RK3576_EBC_DSP_START, 1);
7758766792cSChaoyi Chen 
7768766792cSChaoyi Chen 	return 0;
7778766792cSChaoyi Chen }
7788766792cSChaoyi Chen #endif
77993a7515aSWenping Zhang 
rk_ebc_tcon_probe(struct udevice * dev)78093a7515aSWenping Zhang static int rk_ebc_tcon_probe(struct udevice *dev)
78193a7515aSWenping Zhang {
78293a7515aSWenping Zhang 	int ret;
78393a7515aSWenping Zhang 	struct ebc_tcon_priv *priv = dev_get_priv(dev);
7841a77b5f7SChaoyi Chen 	struct driver *driver = (struct driver *)dev->driver;
7851a77b5f7SChaoyi Chen 	const struct rk_ebc_tcon_ops *tcon_ops;
7861a77b5f7SChaoyi Chen #ifdef CONFIG_IRQ
7871a77b5f7SChaoyi Chen 	u32 interrupt[2];
7881a77b5f7SChaoyi Chen 	int irq;
7891a77b5f7SChaoyi Chen #endif
79093a7515aSWenping Zhang 
7911a77b5f7SChaoyi Chen 	tcon_ops = (const struct rk_ebc_tcon_ops *)dev_get_driver_data(dev);
7921a77b5f7SChaoyi Chen 	driver->ops = tcon_ops;
79393a7515aSWenping Zhang 
79493a7515aSWenping Zhang 	priv->dev = dev;
795*be899ebcSChaoyi Chen 
796*be899ebcSChaoyi Chen 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
797*be899ebcSChaoyi Chen 	ret = clk_set_defaults(dev);
798*be899ebcSChaoyi Chen 	if (ret)
799*be899ebcSChaoyi Chen 		dev_warn(dev, "clk_set_defaults failed %d\n", ret);
800*be899ebcSChaoyi Chen 
8011a77b5f7SChaoyi Chen 	ret = clk_get_by_name(dev, "dclk", &priv->dclk);
802f968f3bcSZorro Liu 	if (ret < 0) {
803f968f3bcSZorro Liu 		printf("%s get clock fail! %d\n", __func__, ret);
804f968f3bcSZorro Liu 		return -EINVAL;
805f968f3bcSZorro Liu 	}
80693a7515aSWenping Zhang 
80793a7515aSWenping Zhang #ifdef CONFIG_IRQ
8081a77b5f7SChaoyi Chen 	ret = dev_read_u32_array(dev, "interrupts", interrupt, 2);
8091a77b5f7SChaoyi Chen 	if (ret) {
8101a77b5f7SChaoyi Chen 		printf("read ebc irq failed:%d\n", ret);
8111a77b5f7SChaoyi Chen 		return ret;
8121a77b5f7SChaoyi Chen 	}
8131a77b5f7SChaoyi Chen 
8141a77b5f7SChaoyi Chen 	/* convert to Shared Peripheral Interrupt */
8151a77b5f7SChaoyi Chen 	irq = interrupt[1] + 32;
8161a77b5f7SChaoyi Chen 	irq_install_handler(irq, ebc_irq_handler, dev);
8171a77b5f7SChaoyi Chen 	irq_handler_enable(irq);
81893a7515aSWenping Zhang #endif
81993a7515aSWenping Zhang 	return 0;
82093a7515aSWenping Zhang }
82193a7515aSWenping Zhang 
8228766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
8238766792cSChaoyi Chen const struct rk_ebc_tcon_ops rk3568_ebc_tcon_funcs = {
82493a7515aSWenping Zhang 	.enable = ebc_tcon_enable,
82593a7515aSWenping Zhang 	.disable = ebc_tcon_disable,
82693a7515aSWenping Zhang 	.dsp_mode_set = ebc_tcon_dsp_mode_set,
82793a7515aSWenping Zhang 	.image_addr_set = ebc_tcon_image_addr_set,
82893a7515aSWenping Zhang 	.frame_addr_set = ebc_tcon_frame_addr_set,
82993a7515aSWenping Zhang 	.lut_data_set = ebc_tcon_lut_data_set,
83093a7515aSWenping Zhang 	.frame_start = ebc_tcon_frame_start,
83193a7515aSWenping Zhang 	.wait_for_last_frame_complete = wait_for_last_frame_complete,
83293a7515aSWenping Zhang };
8338766792cSChaoyi Chen #endif
8348766792cSChaoyi Chen 
8358766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
8368766792cSChaoyi Chen const struct rk_ebc_tcon_ops rk3576_ebc_tcon_funcs = {
8378766792cSChaoyi Chen 	.enable = rk3576_ebc_tcon_enable,
8388766792cSChaoyi Chen 	.disable = ebc_tcon_disable,
8398766792cSChaoyi Chen 	.dsp_mode_set = rk3576_ebc_tcon_dsp_mode_set,
8408766792cSChaoyi Chen 	.image_addr_set = ebc_tcon_image_addr_set,
8418766792cSChaoyi Chen 	.frame_addr_set = ebc_tcon_frame_addr_set,
8428766792cSChaoyi Chen 	.lut_data_set = ebc_tcon_lut_data_set,
8438766792cSChaoyi Chen 	.frame_start = rk3576_ebc_tcon_frame_start,
8448766792cSChaoyi Chen 	.wait_for_last_frame_complete = wait_for_last_frame_complete,
8458766792cSChaoyi Chen };
8468766792cSChaoyi Chen #endif
84793a7515aSWenping Zhang 
rk_ebc_tcon_ofdata_to_platdata(struct udevice * dev)84893a7515aSWenping Zhang static int rk_ebc_tcon_ofdata_to_platdata(struct udevice *dev)
84993a7515aSWenping Zhang {
85093a7515aSWenping Zhang 	fdt_size_t size;
85193a7515aSWenping Zhang 	fdt_addr_t addr;
85293a7515aSWenping Zhang 	struct ebc_tcon_priv *priv = dev_get_priv(dev);
85393a7515aSWenping Zhang 
85493a7515aSWenping Zhang 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
85593a7515aSWenping Zhang 	if (priv->grf <= 0) {
85693a7515aSWenping Zhang 		debug("%s: Get syscon grf failed (ret=%p)\n",
85793a7515aSWenping Zhang 		      __func__, priv->grf);
85893a7515aSWenping Zhang 		return  -ENXIO;
85993a7515aSWenping Zhang 	}
86093a7515aSWenping Zhang 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
86193a7515aSWenping Zhang 	if (priv->pmugrf <= 0) {
86293a7515aSWenping Zhang 		debug("%s: Get syscon pmugrf failed (ret=%p)\n",
86393a7515aSWenping Zhang 		      __func__, priv->grf);
86493a7515aSWenping Zhang 		return  -ENXIO;
86593a7515aSWenping Zhang 	}
86693a7515aSWenping Zhang 	addr = dev_read_addr_size(dev, "reg", &size);
86793a7515aSWenping Zhang 	if (addr == FDT_ADDR_T_NONE) {
86893a7515aSWenping Zhang 		debug("%s: Get ebc_tcon address failed\n", __func__);
86993a7515aSWenping Zhang 		return  -ENXIO;
87093a7515aSWenping Zhang 	}
87193a7515aSWenping Zhang 
87293a7515aSWenping Zhang 	priv->reg = ioremap(addr, size);
87393a7515aSWenping Zhang 	priv->reg_len = size;
87493a7515aSWenping Zhang 	priv->regcache = malloc(size);
87593a7515aSWenping Zhang 	memset(priv->regcache, 0, size);
87693a7515aSWenping Zhang 	return 0;
87793a7515aSWenping Zhang }
87893a7515aSWenping Zhang 
87993a7515aSWenping Zhang static const struct udevice_id ebc_tcon_ids[] = {
8808766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3568
8811a77b5f7SChaoyi Chen 	{
8821a77b5f7SChaoyi Chen 		.compatible = "rockchip,rk3568-ebc-tcon",
8838766792cSChaoyi Chen 		.data = (ulong)&rk3568_ebc_tcon_funcs,
8841a77b5f7SChaoyi Chen 	},
8858766792cSChaoyi Chen #endif
8868766792cSChaoyi Chen #ifdef CONFIG_ROCKCHIP_RK3576
8878766792cSChaoyi Chen 	{
8888766792cSChaoyi Chen 		.compatible = "rockchip,rk3576-ebc-tcon",
8898766792cSChaoyi Chen 		.data = (ulong)&rk3576_ebc_tcon_funcs,
8908766792cSChaoyi Chen 	},
8918766792cSChaoyi Chen #endif
89293a7515aSWenping Zhang 	{}
89393a7515aSWenping Zhang };
89493a7515aSWenping Zhang 
89593a7515aSWenping Zhang U_BOOT_DRIVER(rk_ebc_tcon) = {
89693a7515aSWenping Zhang 	.name	= "rk_ebc_tcon",
89793a7515aSWenping Zhang 	.id	= UCLASS_EBC,
89893a7515aSWenping Zhang 	.of_match = ebc_tcon_ids,
89993a7515aSWenping Zhang 	.ofdata_to_platdata = rk_ebc_tcon_ofdata_to_platdata,
90093a7515aSWenping Zhang 	.probe	= rk_ebc_tcon_probe,
90193a7515aSWenping Zhang 	.priv_auto_alloc_size   = sizeof(struct ebc_tcon_priv),
90293a7515aSWenping Zhang };
90393a7515aSWenping Zhang 
90493a7515aSWenping Zhang UCLASS_DRIVER(ebc_tcon) = {
90593a7515aSWenping Zhang 	.id	= UCLASS_EBC,
90693a7515aSWenping Zhang 	.name	= "ebc_tcon",
90793a7515aSWenping Zhang };
90893a7515aSWenping Zhang 
909