Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/nvmem-consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/rockchip/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT	1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define UPDATE(x, h, l)		(((x) << (l)) & GENMASK((h), (l)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) /* REG: 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define PRE_PLL_REFCLK_SEL_MASK			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define PRE_PLL_REFCLK_SEL_PCLK			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define PRE_PLL_REFCLK_SEL_OSCCLK		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) /* REG: 0x01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #define BYPASS_RXSENSE_EN_MASK			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define BYPASS_RXSENSE_EN			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define BYPASS_PWRON_EN_MASK			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #define BYPASS_PWRON_EN				BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define BYPASS_PLLPD_EN_MASK			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #define BYPASS_PLLPD_EN				BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) /* REG: 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define BYPASS_PDATA_EN_MASK			BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define BYPASS_PDATA_EN				BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #define PDATAEN_MASK				BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define PDATAEN_DISABLE				BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #define PDATAEN_ENABLE				0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) /* REG: 0x03 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define BYPASS_AUTO_TERM_RES_CAL		BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define AUDO_TERM_RES_CAL_SPEED_14_8(x)		UPDATE(x, 6, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) /* REG: 0x04 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define AUDO_TERM_RES_CAL_SPEED_7_0(x)		UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) /* REG: 0xaa */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define POST_PLL_CTRL_MASK			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define POST_PLL_CTRL_MANUAL			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) /* REG: 0xe0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define POST_PLL_POWER_MASK			BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define POST_PLL_POWER_DOWN			BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define POST_PLL_POWER_UP			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define PRE_PLL_POWER_MASK			BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define PRE_PLL_POWER_DOWN			BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define PRE_PLL_POWER_UP			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define RXSENSE_CLK_CH_MASK			BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define RXSENSE_CLK_CH_ENABLE			BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define RXSENSE_DATA_CH2_MASK			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #define RXSENSE_DATA_CH2_ENABLE			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define RXSENSE_DATA_CH1_MASK			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define RXSENSE_DATA_CH1_ENABLE			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define RXSENSE_DATA_CH0_MASK			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define RXSENSE_DATA_CH0_ENABLE			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) /* REG: 0xe1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define BANDGAP_MASK				BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #define BANDGAP_ENABLE				BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define BANDGAP_DISABLE				0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define TMDS_DRIVER_MASK			GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define TMDS_DRIVER_ENABLE			UPDATE(0xf, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define TMDS_DRIVER_DISABLE			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) /* REG: 0xe2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define PRE_PLL_FB_DIV_8_MASK			BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define PRE_PLL_FB_DIV_8_SHIFT			7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define PRE_PLL_FB_DIV_8(x)			UPDATE(x, 7, 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define PCLK_VCO_DIV_5_MASK			BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define PCLK_VCO_DIV_5_SHIFT			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define PCLK_VCO_DIV_5(x)			UPDATE(x, 5, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define PRE_PLL_PRE_DIV_MASK			GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define PRE_PLL_PRE_DIV(x)			UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) /* REG: 0xe3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define PRE_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) /* REG: 0xe4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define PRE_PLL_PCLK_DIV_B_MASK			GENMASK(6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define PRE_PLL_PCLK_DIV_B_SHIFT		5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define PRE_PLL_PCLK_DIV_B(x)			UPDATE(x, 6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define PRE_PLL_PCLK_DIV_A_MASK			GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define PRE_PLL_PCLK_DIV_A_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #define PRE_PLL_PCLK_DIV_A(x)			UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) /* REG: 0xe5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) #define PRE_PLL_PCLK_DIV_C_MASK			GENMASK(6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define PRE_PLL_PCLK_DIV_C_SHIFT		5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #define PRE_PLL_PCLK_DIV_C(x)			UPDATE(x, 6, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define PRE_PLL_PCLK_DIV_D_MASK			GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #define PRE_PLL_PCLK_DIV_D_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #define PRE_PLL_PCLK_DIV_D(x)			UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) /* REG: 0xe6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #define PRE_PLL_TMDSCLK_DIV_C_MASK		GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) #define PRE_PLL_TMDSCLK_DIV_C(x)		UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) #define PRE_PLL_TMDSCLK_DIV_A_MASK		GENMASK(3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) #define PRE_PLL_TMDSCLK_DIV_A(x)		UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) #define PRE_PLL_TMDSCLK_DIV_B_MASK		GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) #define PRE_PLL_TMDSCLK_DIV_B(x)		UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) /* REG: 0xe8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define PRE_PLL_LOCK_STATUS			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) /* REG: 0xe9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define POST_PLL_POST_DIV_EN_MASK		GENMASK(7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define POST_PLL_POST_DIV_ENABLE		UPDATE(3, 7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) #define POST_PLL_POST_DIV_DISABLE		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) #define POST_PLL_PRE_DIV_MASK			GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define POST_PLL_PRE_DIV(x)			UPDATE(x, 4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) /* REG: 0xea */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) #define POST_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) /* REG: 0xeb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) #define POST_PLL_FB_DIV_8_MASK			BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #define POST_PLL_FB_DIV_8(x)			UPDATE(x, 7, 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) #define POST_PLL_POST_DIV_MASK			GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) #define POST_PLL_POST_DIV(x)			UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) #define POST_PLL_LOCK_STATUS			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) /* REG: 0xee */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) #define TMDS_CH_TA_MASK				GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #define TMDS_CH_TA_ENABLE			UPDATE(0xf, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) #define TMDS_CH_TA_DISABLE			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) /* REG: 0xef */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) #define TMDS_CLK_CH_TA(x)			UPDATE(x, 7, 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) #define TMDS_DATA_CH2_TA(x)			UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) #define TMDS_DATA_CH1_TA(x)			UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) #define TMDS_DATA_CH0_TA(x)			UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) /* REG: 0xf0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) #define TMDS_DATA_CH2_PRE_EMPHASIS_MASK		GENMASK(5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) #define TMDS_DATA_CH2_PRE_EMPHASIS(x)		UPDATE(x, 5, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) #define TMDS_DATA_CH1_PRE_EMPHASIS_MASK		GENMASK(3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) #define TMDS_DATA_CH1_PRE_EMPHASIS(x)		UPDATE(x, 3, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) #define TMDS_DATA_CH0_PRE_EMPHASIS_MASK		GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) #define TMDS_DATA_CH0_PRE_EMPHASIS(x)		UPDATE(x, 1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) /* REG: 0xf1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) #define TMDS_CLK_CH_OUTPUT_SWING(x)		UPDATE(x, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) #define TMDS_DATA_CH2_OUTPUT_SWING(x)		UPDATE(x, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) /* REG: 0xf2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) #define TMDS_DATA_CH1_OUTPUT_SWING(x)		UPDATE(x, 7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) #define TMDS_DATA_CH0_OUTPUT_SWING(x)		UPDATE(x, 3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) enum inno_hdmi_phy_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	INNO_HDMI_PHY_RK3228,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	INNO_HDMI_PHY_RK3328
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) struct phy_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	unsigned long	tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	u8		regs[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) struct inno_hdmi_phy_drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) struct inno_hdmi_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	struct clk *sysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	struct phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	/* platform data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	struct inno_hdmi_phy_drv_data *plat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	/* efuse flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	bool efuse_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	/* clk provider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	struct clk *pclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	unsigned long pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) struct pre_pll_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	unsigned long pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	u8 prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	u16 fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	u8 tmds_div_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	u8 tmds_div_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	u8 tmds_div_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	u8 pclk_div_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	u8 pclk_div_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	u8 pclk_div_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	u8 pclk_div_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	u8 vco_div_5_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	u32 fracdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) struct post_pll_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	unsigned long tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	u8 prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	u16 fbdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	u8 postdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) struct inno_hdmi_phy_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	void (*init)(struct inno_hdmi_phy *inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	int (*power_on)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 			const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 			const struct phy_config *phy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	void (*power_off)(struct inno_hdmi_phy *inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	int (*pre_pll_update)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 			      const struct pre_pll_config *cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	unsigned long (*recalc_rate)(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 				     unsigned long parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) struct inno_hdmi_phy_drv_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	enum inno_hdmi_phy_type		dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	const struct inno_hdmi_phy_ops	*ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	const struct phy_config		*phy_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  * If only using integer freq div can't get frequency we want, frac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)  * freq div is needed. For example, pclk 88.75 Mhz and tmdsclk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234)  * 110.9375 Mhz must use frac div 0xF00000. The actual frequency is different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235)  * from the target frequency. Such as the tmds clock 110.9375 Mhz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236)  * the actual tmds clock we get is 110.93719 Mhz. It is important
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237)  * to note that RK322X platforms do not support frac div.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) static const struct pre_pll_config pre_pll_cfg_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	{ 27000000,  27000000, 1,  90, 3, 2, 2, 10, 3, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	{ 27000000,  33750000, 1,  90, 1, 3, 3, 10, 3, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	{ 40000000,  40000000, 1,  80, 2, 2, 2, 12, 2, 2,  2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	{ 40000000,  50000000, 1, 100, 2, 2, 2,  1, 0, 0, 15, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	{ 59341000,  59341000, 1,  98, 3, 1, 2,  1, 3, 3,  4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	{ 59400000,  59400000, 1,  99, 3, 1, 1,  1, 3, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	{ 59341000,  74176250, 1,  98, 0, 3, 3,  1, 3, 3,  4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	{ 59400000,  74250000, 1,  99, 1, 2, 2,  1, 3, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	{ 65000000,  65000000, 1, 130, 2, 2, 2,  1, 0, 0, 12, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	{ 65000000,  81250000, 3, 325, 0, 3, 3,  1, 0, 0, 10, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	{ 71000000,  71000000, 3, 284, 0, 3, 3,  1, 0, 0,  8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	{ 71000000,  88750000, 3, 355, 0, 3, 3,  1, 0, 0, 10, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	{ 74176000,  74176000, 1,  98, 1, 2, 2,  1, 2, 3,  4, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	{ 74250000,  74250000, 1,  99, 1, 2, 2,  1, 2, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	{ 74176000,  92720000, 4, 494, 1, 2, 2,  1, 3, 3,  4, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	{ 74250000,  92812500, 4, 495, 1, 2, 2,  1, 3, 3,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	{ 83500000,  83500000, 2, 167, 2, 1, 1,  1, 0, 0,  6, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	{ 83500000, 104375000, 1, 104, 2, 1, 1,  1, 1, 0,  5, 0, 0x600000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	{ 85750000,  85750000, 3, 343, 0, 3, 3,  1, 0, 0,  8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	{ 88750000,  88750000, 3, 355, 0, 3, 3,  1, 0, 0,  8, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	{ 88750000, 110937500, 1, 110, 2, 1, 1,  1, 1, 0,  5, 0, 0xF00000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	{108000000, 108000000, 1,  90, 3, 0, 0,  1, 0, 0,  5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	{108000000, 135000000, 1,  90, 0, 2, 2,  1, 0, 0,  5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	{119000000, 119000000, 1, 119, 2, 1, 1,  1, 0, 0,  6, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	{119000000, 148750000, 1,  99, 0, 2, 2,  1, 0, 0,  5, 0, 0x2AAAAA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	{148352000, 148352000, 1,  98, 1, 1, 1,  1, 2, 2,  2, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	{148500000, 148500000, 1,  99, 1, 1, 1,  1, 2, 2,  2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	{148352000, 185440000, 4, 494, 0, 2, 2,  1, 3, 2,  2, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	{148500000, 185625000, 4, 495, 0, 2, 2,  1, 3, 2,  2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	{162000000, 162000000, 1, 108, 0, 2, 2,  1, 0, 0,  4, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	{162000000, 202500000, 1, 135, 0, 2, 2,  1, 0, 0,  5, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	{296703000, 296703000, 1,  98, 0, 1, 1,  1, 0, 2,  2, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	{297000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2,  2, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	{296703000, 370878750, 4, 494, 1, 2, 0,  1, 3, 1,  1, 0, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	{297000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1,  1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	{593407000, 296703500, 1,  98, 0, 1, 1,  1, 0, 2,  1, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	{594000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2,  1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	{593407000, 370879375, 4, 494, 1, 2, 0,  1, 3, 1,  1, 1, 0x816817},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	{594000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1,  1, 1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	{593407000, 593407000, 1,  98, 0, 2, 0,  1, 0, 1,  1, 0, 0xE6AE6B},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	{594000000, 594000000, 1,  99, 0, 2, 0,  1, 0, 1,  1, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	{     ~0UL,	    0, 0,   0, 0, 0, 0,  0, 0, 0,  0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) static const struct post_pll_config post_pll_cfg_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	{33750000,  1, 40, 8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	{33750000,  1, 80, 8, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	{33750000,  1, 10, 2, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	{74250000,  1, 40, 8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	{74250000, 18, 80, 8, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	{148500000, 2, 40, 4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	{297000000, 4, 40, 2, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	{594000000, 8, 40, 1, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	{     ~0UL, 0,  0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) static const struct phy_config rk3228_phy_cfg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	{	165000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 			0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 			0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		340000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 			0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		594000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 			0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 			0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		~0UL, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 			0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) static const struct phy_config rk3328_phy_cfg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	{	165000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 			0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 			0x00, 0xac, 0xcc, 0xcc, 0xcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		340000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 			0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 			0x3f, 0xac, 0xcc, 0xcd, 0xdd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		594000000, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 			0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			0x00, 0xac, 0xcc, 0xcc, 0xcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		~0UL, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 			0x00, 0x00, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) static inline struct inno_hdmi_phy *to_inno_hdmi_phy(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	return container_of(hw, struct inno_hdmi_phy, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	regmap_write(inno->regmap, reg * 4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	regmap_read(inno->regmap, reg * 4, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 				    u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	regmap_update_bits(inno->regmap, reg * 4, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	int bus_width = phy_get_bus_width(inno->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	u32 tmdsclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	switch (bus_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		tmdsclk = (u32)rate / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		tmdsclk = (u32)rate * 5 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		tmdsclk = (u32)rate * 3 / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		tmdsclk = (u32)rate * 5 / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	case 12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		tmdsclk = (u32)rate * 3 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		tmdsclk = (u32)rate * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 		tmdsclk = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	return tmdsclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) static irqreturn_t inno_hdmi_phy_hardirq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	struct inno_hdmi_phy *inno = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	int intr_stat1, intr_stat2, intr_stat3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	intr_stat1 = inno_read(inno, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	intr_stat2 = inno_read(inno, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	intr_stat3 = inno_read(inno, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	if (intr_stat1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		inno_write(inno, 0x04, intr_stat1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	if (intr_stat2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		inno_write(inno, 0x06, intr_stat2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	if (intr_stat3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		inno_write(inno, 0x08, intr_stat3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	if (intr_stat1 || intr_stat2 || intr_stat3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		return IRQ_WAKE_THREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) static irqreturn_t inno_hdmi_phy_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	struct inno_hdmi_phy *inno = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	/* set pdata_en to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	inno_update_bits(inno, 0x02, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	/* set pdata_en to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	inno_update_bits(inno, 0x02, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) static int inno_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 				      unsigned long parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) static int inno_hdmi_phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	const struct post_pll_config *cfg = post_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	u32 chipversion = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	if (inno->phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		phy_cfg = inno->phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	if (!tmdsclock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		dev_err(inno->dev, "TMDS clock is zero!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3328 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	    rockchip_get_cpu_version())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		chipversion = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		 tmdsclock <= 33750000 && inno->efuse_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		chipversion = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	for (; cfg->tmdsclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		if (tmdsclock <= cfg->tmdsclock &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		    cfg->version & chipversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		if (tmdsclock <= phy_cfg->tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	if (cfg->tmdsclock == ~0UL || phy_cfg->tmdsclock == ~0UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	dev_dbg(inno->dev, "Inno HDMI PHY Power On\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	inno_hdmi_phy_clk_set_rate(&inno->hw, inno->pixclock, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	if (inno->plat_data->ops->power_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		return inno->plat_data->ops->power_on(inno, cfg, phy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) static int inno_hdmi_phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	struct inno_hdmi_phy *inno = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	if (inno->plat_data->ops->power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		inno->plat_data->ops->power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	inno->tmdsclock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) static const struct phy_ops inno_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	.owner	   = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	.power_on  = inno_hdmi_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	.power_off = inno_hdmi_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) static int inno_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		status = inno_read(inno, 0xe0) & PRE_PLL_POWER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		status = inno_read(inno, 0xa0) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	return status ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) static int inno_hdmi_phy_clk_prepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 				 PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		inno_update_bits(inno, 0xa0, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) static void inno_hdmi_phy_clk_unprepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 				 PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		inno_update_bits(inno, 0xa0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) static unsigned long inno_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 						   unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	if (inno->plat_data->ops->recalc_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		return inno->plat_data->ops->recalc_rate(inno, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		return inno->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) static long inno_hdmi_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 					 unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	for (; cfg->pixclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		if (cfg->pixclock == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	/* XXX: Limit pixel clock under 600MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	if (cfg->pixclock > 600000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	 * If there is no dts phy cfg table, use default phy cfg table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	 * The tmds clock maximum is 594MHz. So there is no need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	 * whether tmds clock is out of range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	if (!inno->phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		return cfg->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	/* Check if tmds clock is out of dts phy config's range. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	for (i = 0; inno->phy_cfg[i].tmdsclock != ~0UL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		if (inno->phy_cfg[i].tmdsclock >= tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	if (inno->phy_cfg[i].tmdsclock == ~0UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	return cfg->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) static int inno_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 				      unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	dev_dbg(inno->dev, "%s rate %lu tmdsclk %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		__func__, rate, tmdsclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	if (inno->tmdsclock == tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	for (; cfg->pixclock != ~0UL; cfg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	if (cfg->pixclock == ~0UL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		dev_err(inno->dev, "unsupported rate %lu\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	if (inno->plat_data->ops->pre_pll_update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		inno->plat_data->ops->pre_pll_update(inno, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	inno->pixclock = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	inno->tmdsclock = tmdsclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) static const struct clk_ops inno_hdmi_phy_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	.prepare = inno_hdmi_phy_clk_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	.unprepare = inno_hdmi_phy_clk_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	.is_prepared = inno_hdmi_phy_clk_is_prepared,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	.recalc_rate = inno_hdmi_phy_clk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	.round_rate = inno_hdmi_phy_clk_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	.set_rate = inno_hdmi_phy_clk_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) static int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	struct device *dev = inno->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	struct clk_init_data init = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	struct clk *refclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	refclk = devm_clk_get(dev, "refclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	if (IS_ERR(refclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		dev_err(dev, "failed to get ref clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		return PTR_ERR(refclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	parent_name = __clk_get_name(refclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	init.name = "pin_hd20_pclk";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	init.ops = &inno_hdmi_phy_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	/* optional override of the clock name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	of_property_read_string(np, "clock-output-names", &init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	inno->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	inno->pclk = devm_clk_register(dev, &inno->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	if (IS_ERR(inno->pclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		ret = PTR_ERR(inno->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		dev_err(dev, "failed to register clock: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	ret = of_clk_add_provider(np, of_clk_src_simple_get, inno->pclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		dev_err(dev, "failed to register OF clock provider: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) inno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 			      const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 			      const struct phy_config *phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	int pll_tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	/* pdata_en disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	/* Power down Post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	/* Post-PLL update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	m = POST_PLL_PRE_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	v = POST_PLL_PRE_DIV(cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	m = POST_PLL_FB_DIV_8_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	v = POST_PLL_FB_DIV_8(cfg->fbdiv >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	inno_update_bits(inno, 0xeb, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	inno_write(inno, 0xea, POST_PLL_FB_DIV_7_0(cfg->fbdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	if (cfg->postdiv == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		/* Disable Post-PLL post divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		m = POST_PLL_POST_DIV_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		v = POST_PLL_POST_DIV_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		/* Enable Post-PLL post divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		m = POST_PLL_POST_DIV_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		v = POST_PLL_POST_DIV_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		inno_update_bits(inno, 0xe9, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		m = POST_PLL_POST_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		v = POST_PLL_POST_DIV(cfg->postdiv / 2 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		inno_update_bits(inno, 0xeb, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	for (v = 0; v < 4; v++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		inno_write(inno, 0xef + v, phy_cfg->regs[v]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	/* Power up Post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	/* BandGap enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	/* TMDS driver enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	/* Wait for post PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	pll_tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	while (!(inno_read(inno, 0xeb) & POST_PLL_LOCK_STATUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			dev_err(inno->dev, "Post-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 			return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		pll_tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		usleep_range(100, 110);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	if (cfg->tmdsclock > 340000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	/* pdata_en enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) static void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	/* TMDS driver Disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	/* BandGap Disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	/* Post-PLL power down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) static void inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	struct nvmem_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	unsigned char *efuse_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	 * Use phy internal register control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	 * rxsense/poweron/pllpd/pdataen signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	m = BYPASS_RXSENSE_EN_MASK | BYPASS_PWRON_EN_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	    BYPASS_PLLPD_EN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	v = BYPASS_RXSENSE_EN | BYPASS_PWRON_EN | BYPASS_PLLPD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	inno_update_bits(inno, 0x01, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	inno_update_bits(inno, 0x02, BYPASS_PDATA_EN_MASK, BYPASS_PDATA_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	 * reg0xe9 default value is 0xe4, reg0xea is 0x50.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	 * if phy had been set in uboot, one of them will be different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	if ((inno_read(inno, 0xe9) != 0xe4 || inno_read(inno, 0xea) != 0x50)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		dev_info(inno->dev, "phy had been powered up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		inno->phy->power_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		inno_hdmi_phy_rk3228_power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		/* manual power down post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		inno_update_bits(inno, 0xaa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 				 POST_PLL_CTRL_MASK, POST_PLL_CTRL_MANUAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	cell = nvmem_cell_get(inno->dev, "hdmi_phy_flag");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	if (IS_ERR(cell)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		dev_err(inno->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			"failed to get id cell: %ld\n", PTR_ERR(cell));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	efuse_buf = nvmem_cell_read(cell, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	nvmem_cell_put(cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	if (len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		inno->efuse_flag = efuse_buf[0] ? true : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	kfree(efuse_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) inno_hdmi_phy_rk3228_pre_pll_update(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 				    const struct pre_pll_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	int pll_tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	/* Power down PRE-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	m = PRE_PLL_FB_DIV_8_MASK | PCLK_VCO_DIV_5_MASK | PRE_PLL_PRE_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	v = PRE_PLL_FB_DIV_8(cfg->fbdiv >> 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	    PCLK_VCO_DIV_5(cfg->vco_div_5_en) | PRE_PLL_PRE_DIV(cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	inno_update_bits(inno, 0xe2, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	inno_write(inno, 0xe3, PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	m = PRE_PLL_PCLK_DIV_B_MASK | PRE_PLL_PCLK_DIV_A_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	v = PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	    PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	inno_update_bits(inno, 0xe4, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	m = PRE_PLL_PCLK_DIV_C_MASK | PRE_PLL_PCLK_DIV_D_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	v = PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	    PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	inno_update_bits(inno, 0xe5, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	m = PRE_PLL_TMDSCLK_DIV_C_MASK | PRE_PLL_TMDSCLK_DIV_A_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	    PRE_PLL_TMDSCLK_DIV_B_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	v = PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	    PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	    PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	inno_update_bits(inno, 0xe6, m, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	/* Power up PRE-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	/* Wait for Pre-PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	pll_tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	while (!(inno_read(inno, 0xe8) & PRE_PLL_LOCK_STATUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 			dev_err(inno->dev, "Pre-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 			return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		pll_tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		usleep_range(100, 110);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			      const struct post_pll_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 			      const struct phy_config *phy_cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	u64 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	/* set pdata_en to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	inno_update_bits(inno, 0x02, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	/* Power off post PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	inno_update_bits(inno, 0xaa, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	val = cfg->fbdiv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	inno_write(inno, 0xac, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	if (cfg->postdiv == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		inno_write(inno, 0xaa, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		val = (cfg->fbdiv >> 8) | cfg->prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		inno_write(inno, 0xab, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		val = (cfg->postdiv / 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		inno_write(inno, 0xad, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 		val = (cfg->fbdiv >> 8) | cfg->prediv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		inno_write(inno, 0xab, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		inno_write(inno, 0xaa, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	for (val = 0; val < 14; val++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		inno_write(inno, 0xb5 + val, phy_cfg->regs[val]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	/* bit[7:6] of reg c8/c9/ca/c8 is ESD detect threshold:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	 * 00 - 340mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	 * 01 - 280mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	 * 10 - 260mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	 * 11 - 240mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	 * default is 240mV, now we set it to 340mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	inno_write(inno, 0xc8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	inno_write(inno, 0xc9, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	inno_write(inno, 0xca, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	inno_write(inno, 0xcb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	if (phy_cfg->tmdsclock > 340000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		/* Set termination resistor to 100ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		val = clk_get_rate(inno->sysclk) / 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		inno_write(inno, 0xc5, ((val >> 8) & 0xff) | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		inno_write(inno, 0xc6, val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		inno_write(inno, 0xc7, 3 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		inno_write(inno, 0xc5, ((val >> 8) & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		inno_write(inno, 0xc5, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		/* clk termination resistor is 50ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		if (phy_cfg->tmdsclock > 165000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 			inno_write(inno, 0xc8, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		/* data termination resistor is 150ohm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		inno_write(inno, 0xc9, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		inno_write(inno, 0xca, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		inno_write(inno, 0xcb, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	/* set TMDS sync detection counter length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	temp = 47520000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	do_div(temp, inno->tmdsclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	inno_write(inno, 0xd8, (temp >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	inno_write(inno, 0xd9, temp & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	/* Power up post PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	inno_update_bits(inno, 0xaa, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	/* Power up tmds driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	inno_update_bits(inno, 0xb0, 4, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	inno_write(inno, 0xb2, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	/* Wait for post PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	for (val = 0; val < 5; val++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		if (inno_read(inno, 0xaf) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	if (!(inno_read(inno, 0xaf) & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		dev_err(inno->dev, "HDMI PHY Post PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	if (phy_cfg->tmdsclock > 340000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	/* set pdata_en to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	inno_update_bits(inno, 0x02, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	/* Enable PHY IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	inno_write(inno, 0x05, 0x22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	inno_write(inno, 0x07, 0x22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	/* Power off driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	inno_write(inno, 0xb2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	/* Power off band gap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	inno_update_bits(inno, 0xb0, 4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	/* Power off post pll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	inno_update_bits(inno, 0xaa, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	/* Disable PHY IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	inno_write(inno, 0x05, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	inno_write(inno, 0x07, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	 * Use phy internal register control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	 * rxsense/poweron/pllpd/pdataen signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	inno_write(inno, 0x01, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	inno_write(inno, 0x02, 0x91);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	 * reg0xc8 default value is 0xc0, if phy had been set in uboot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	 * the value of bit[7:6] will be zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	if ((inno_read(inno, 0xc8) & 0xc0) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		dev_info(inno->dev, "phy had been powered up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		inno->phy->power_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		/* manual power down post-PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		inno_hdmi_phy_rk3328_power_off(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) inno_hdmi_phy_rk3328_pre_pll_update(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 				    const struct pre_pll_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	/* Power off PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	inno_update_bits(inno, 0xa0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	/* Configure pre-pll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	inno_write(inno, 0xa1, cfg->prediv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	if (cfg->fracdiv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	inno_write(inno, 0xa2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	inno_write(inno, 0xa3, cfg->fbdiv & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	val = (cfg->pclk_div_a & 0x1f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	      ((cfg->pclk_div_b & 3) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	inno_write(inno, 0xa5, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	val = (cfg->pclk_div_d & 0x1f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	      ((cfg->pclk_div_c & 3) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	inno_write(inno, 0xa6, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	val = ((cfg->tmds_div_a & 3) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	      ((cfg->tmds_div_b & 3) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	      (cfg->tmds_div_c & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	inno_write(inno, 0xa4, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	if (cfg->fracdiv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		val = cfg->fracdiv & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		inno_write(inno, 0xd3, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 		val = (cfg->fracdiv >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		inno_write(inno, 0xd2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		val = (cfg->fracdiv >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		inno_write(inno, 0xd1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		inno_write(inno, 0xd3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		inno_write(inno, 0xd2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		inno_write(inno, 0xd1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	/* Power up PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	inno_update_bits(inno, 0xa0, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	/* Wait for PLL lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	for (val = 0; val < 5; val++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		if (inno_read(inno, 0xa9) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	if (val == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		dev_err(inno->dev, "Pre-PLL unlock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) inno_hdmi_rk3328_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 				     unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	unsigned long frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	u8 nd, no_a, no_b, no_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	u16 nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	u64 vco = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	nd = inno_read(inno, 0xa1) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	vco *= nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	if ((inno_read(inno, 0xa2) & 0x30) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		frac = inno_read(inno, 0xd3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		       (inno_read(inno, 0xd2) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		       (inno_read(inno, 0xd1) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	if (inno_read(inno, 0xa0) & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		do_div(vco, nd * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		no_a = inno_read(inno, 0xa5) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 		no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 		no_d = inno_read(inno, 0xa6) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 		if (no_a == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			do_div(vco, nd * no_b * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 			do_div(vco, nd * no_a * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	frac = vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	inno->pixclock = DIV_ROUND_CLOSEST(frac, 1000) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	return frac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) inno_hdmi_rk3228_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 				     unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	u8 nd, no_a, no_b, no_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	u16 nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	u64 vco = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	nd = inno_read(inno, 0xe2) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	nf = ((inno_read(inno, 0xe2) & 0x80) << 1) | inno_read(inno, 0xe3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	vco *= nf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	if ((inno_read(inno, 0xe2) >> 5) & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		do_div(vco, nd * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		no_a = inno_read(inno, 0xe4) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		if (!no_a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 			no_a = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		no_b = ((inno_read(inno, 0xe4) >> 5) & 0x3) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 		no_d = inno_read(inno, 0xe5) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		if (no_a == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 			do_div(vco, nd * no_b * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 			do_div(vco, nd * no_a * no_d * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 	inno->pixclock = vco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	return inno->pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	.init = inno_hdmi_phy_rk3228_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	.power_on = inno_hdmi_phy_rk3228_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	.power_off = inno_hdmi_phy_rk3228_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	.pre_pll_update = inno_hdmi_phy_rk3228_pre_pll_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	.recalc_rate = inno_hdmi_rk3228_phy_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static const struct inno_hdmi_phy_ops rk3328_hdmi_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	.init = inno_hdmi_phy_rk3328_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	.power_on = inno_hdmi_phy_rk3328_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	.power_off = inno_hdmi_phy_rk3328_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	.pre_pll_update = inno_hdmi_phy_rk3328_pre_pll_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	.recalc_rate = inno_hdmi_rk3328_phy_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	.dev_type = INNO_HDMI_PHY_RK3228,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	.ops = &rk3228_hdmi_phy_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	.phy_cfg_table = rk3228_phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static const struct inno_hdmi_phy_drv_data rk3328_hdmi_phy_drv_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	.dev_type = INNO_HDMI_PHY_RK3328,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	.ops = &rk3328_hdmi_phy_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	.phy_cfg_table = rk3328_phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static const struct of_device_id inno_hdmi_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	{ .compatible = "rockchip,rk3228-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	  .data = &rk3228_hdmi_phy_drv_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	{ .compatible = "rockchip,rk3328-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	  .data = &rk3328_hdmi_phy_drv_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static const struct regmap_config inno_hdmi_phy_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	.reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	.val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	.reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	.max_register = 0x400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int inno_hdmi_update_phy_table(struct inno_hdmi_phy *inno, u32 *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 			       struct phy_config *phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 			       int phy_table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	for (i = 0; i < phy_table_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		phy_cfg[i].tmdsclock =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 			(unsigned long)config[i * 15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		for (j = 0; j < 14; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 			phy_cfg[i].regs[j] = (u8)config[i * 15 + 1 + j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	 * The last set of phy cfg is used to indicate whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	 * there is no more phy cfg data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	phy_cfg[i].tmdsclock = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	for (j = 0; j < 14; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		phy_cfg[i].regs[j] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) #define PHY_TAB_LEN 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int inno_hdmi_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	struct inno_hdmi_phy *inno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	u32 *phy_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	int ret, val, phy_table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	if (!inno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	inno->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	match = of_match_node(inno_hdmi_phy_of_match, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	inno->plat_data = (struct inno_hdmi_phy_drv_data *)match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	if (!inno->plat_data || !inno->plat_data->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	regs = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	if (IS_ERR(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		return PTR_ERR(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	inno->sysclk = devm_clk_get(inno->dev, "sysclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	if (IS_ERR(inno->sysclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		ret = PTR_ERR(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 		dev_err(inno->dev, "Unable to get inno phy sysclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	ret = clk_prepare_enable(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		dev_err(inno->dev, "Cannot enable inno phy sysclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	inno->regmap = devm_regmap_init_mmio(dev, regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 					     &inno_hdmi_phy_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	if (IS_ERR(inno->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 		ret = PTR_ERR(inno->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 		dev_err(dev, "failed to init regmap: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 		goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	inno->phy = devm_phy_create(dev, NULL, &inno_hdmi_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	if (IS_ERR(inno->phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		dev_err(dev, "failed to create HDMI PHY\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 		ret = PTR_ERR(inno->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 		goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	if (of_get_property(np, "rockchip,phy-table", &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		if (val % PHY_TAB_LEN || !val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 			dev_err(dev, "Invalid phy cfg table format!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		phy_config = kmalloc(val, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		if (!phy_config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 			dev_err(dev, "kmalloc phy table failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		phy_table_size = val / PHY_TAB_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		/* Effective phy cfg data and the end of phy cfg table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		inno->phy_cfg = devm_kzalloc(dev, val + PHY_TAB_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 					     GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		if (!inno->phy_cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 			kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		of_property_read_u32_array(np, "rockchip,phy-table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 					   phy_config, val / sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 		ret = inno_hdmi_update_phy_table(inno, phy_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 						 inno->phy_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 						 phy_table_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 			kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		kfree(phy_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		dev_dbg(dev, "use default hdmi phy table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	phy_set_drvdata(inno->phy, inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	phy_set_bus_width(inno->phy, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		dev_err(dev, "failed to register PHY provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		ret = PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	if (inno->plat_data->ops->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 		inno->plat_data->ops->init(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	ret = inno_hdmi_phy_clk_register(inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 		goto err_regsmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	inno->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	if (inno->irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 		ret = devm_request_threaded_irq(inno->dev, inno->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 						inno_hdmi_phy_hardirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 						inno_hdmi_phy_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 						dev_name(inno->dev), inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 			goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	platform_set_drvdata(pdev, inno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	of_clk_del_provider(pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) err_regsmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 	clk_disable_unprepare(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static int inno_hdmi_phy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	struct inno_hdmi_phy *inno = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	of_clk_del_provider(pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 	clk_disable_unprepare(inno->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) static struct platform_driver inno_hdmi_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	.probe  = inno_hdmi_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	.remove = inno_hdmi_phy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 		.name = "inno-hdmi-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 		.of_match_table = of_match_ptr(inno_hdmi_phy_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) module_platform_driver(inno_hdmi_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) MODULE_DESCRIPTION("Innosilion HDMI 2.0 Transmitter PHY Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) MODULE_LICENSE("GPL v2");