162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2017 Rockchip Electronics Co. Ltd. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Zheng Yang <zhengyang@rock-chips.com> 662306a36Sopenharmony_ci * Heiko Stuebner <heiko@sntech.de> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/clk-provider.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/nvmem-consumer.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/platform_device.h> 1962306a36Sopenharmony_ci#include <linux/regmap.h> 2062306a36Sopenharmony_ci#include <linux/phy/phy.h> 2162306a36Sopenharmony_ci#include <linux/slab.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* REG: 0x00 */ 2662306a36Sopenharmony_ci#define RK3228_PRE_PLL_REFCLK_SEL_PCLK BIT(0) 2762306a36Sopenharmony_ci/* REG: 0x01 */ 2862306a36Sopenharmony_ci#define RK3228_BYPASS_RXSENSE_EN BIT(2) 2962306a36Sopenharmony_ci#define RK3228_BYPASS_PWRON_EN BIT(1) 3062306a36Sopenharmony_ci#define RK3228_BYPASS_PLLPD_EN BIT(0) 3162306a36Sopenharmony_ci/* REG: 0x02 */ 3262306a36Sopenharmony_ci#define RK3228_BYPASS_PDATA_EN BIT(4) 3362306a36Sopenharmony_ci#define RK3228_PDATAEN_DISABLE BIT(0) 3462306a36Sopenharmony_ci/* REG: 0x03 */ 3562306a36Sopenharmony_ci#define RK3228_BYPASS_AUTO_TERM_RES_CAL BIT(7) 3662306a36Sopenharmony_ci#define RK3228_AUTO_TERM_RES_CAL_SPEED_14_8(x) UPDATE(x, 6, 0) 3762306a36Sopenharmony_ci/* REG: 0x04 */ 3862306a36Sopenharmony_ci#define RK3228_AUTO_TERM_RES_CAL_SPEED_7_0(x) UPDATE(x, 7, 0) 3962306a36Sopenharmony_ci/* REG: 0xaa */ 4062306a36Sopenharmony_ci#define RK3228_POST_PLL_CTRL_MANUAL BIT(0) 4162306a36Sopenharmony_ci/* REG: 0xe0 */ 4262306a36Sopenharmony_ci#define RK3228_POST_PLL_POWER_DOWN BIT(5) 4362306a36Sopenharmony_ci#define RK3228_PRE_PLL_POWER_DOWN BIT(4) 4462306a36Sopenharmony_ci#define RK3228_RXSENSE_CLK_CH_ENABLE BIT(3) 4562306a36Sopenharmony_ci#define RK3228_RXSENSE_DATA_CH2_ENABLE BIT(2) 4662306a36Sopenharmony_ci#define RK3228_RXSENSE_DATA_CH1_ENABLE BIT(1) 4762306a36Sopenharmony_ci#define RK3228_RXSENSE_DATA_CH0_ENABLE BIT(0) 4862306a36Sopenharmony_ci/* REG: 0xe1 */ 4962306a36Sopenharmony_ci#define RK3228_BANDGAP_ENABLE BIT(4) 5062306a36Sopenharmony_ci#define RK3228_TMDS_DRIVER_ENABLE GENMASK(3, 0) 5162306a36Sopenharmony_ci/* REG: 0xe2 */ 5262306a36Sopenharmony_ci#define RK3228_PRE_PLL_FB_DIV_8_MASK BIT(7) 5362306a36Sopenharmony_ci#define RK3228_PRE_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) 5462306a36Sopenharmony_ci#define RK3228_PCLK_VCO_DIV_5_MASK BIT(5) 5562306a36Sopenharmony_ci#define RK3228_PCLK_VCO_DIV_5(x) UPDATE(x, 5, 5) 5662306a36Sopenharmony_ci#define RK3228_PRE_PLL_PRE_DIV_MASK GENMASK(4, 0) 5762306a36Sopenharmony_ci#define RK3228_PRE_PLL_PRE_DIV(x) UPDATE(x, 4, 0) 5862306a36Sopenharmony_ci/* REG: 0xe3 */ 5962306a36Sopenharmony_ci#define RK3228_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) 6062306a36Sopenharmony_ci/* REG: 0xe4 */ 6162306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5) 6262306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_B_SHIFT 5 6362306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5) 6462306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0) 6562306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0) 6662306a36Sopenharmony_ci/* REG: 0xe5 */ 6762306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5) 6862306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5) 6962306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0) 7062306a36Sopenharmony_ci#define RK3228_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0) 7162306a36Sopenharmony_ci/* REG: 0xe6 */ 7262306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(5, 4) 7362306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 5, 4) 7462306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(3, 2) 7562306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 3, 2) 7662306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(1, 0) 7762306a36Sopenharmony_ci#define RK3228_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 1, 0) 7862306a36Sopenharmony_ci/* REG: 0xe8 */ 7962306a36Sopenharmony_ci#define RK3228_PRE_PLL_LOCK_STATUS BIT(0) 8062306a36Sopenharmony_ci/* REG: 0xe9 */ 8162306a36Sopenharmony_ci#define RK3228_POST_PLL_POST_DIV_ENABLE UPDATE(3, 7, 6) 8262306a36Sopenharmony_ci#define RK3228_POST_PLL_PRE_DIV_MASK GENMASK(4, 0) 8362306a36Sopenharmony_ci#define RK3228_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0) 8462306a36Sopenharmony_ci/* REG: 0xea */ 8562306a36Sopenharmony_ci#define RK3228_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) 8662306a36Sopenharmony_ci/* REG: 0xeb */ 8762306a36Sopenharmony_ci#define RK3228_POST_PLL_FB_DIV_8_MASK BIT(7) 8862306a36Sopenharmony_ci#define RK3228_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) 8962306a36Sopenharmony_ci#define RK3228_POST_PLL_POST_DIV_MASK GENMASK(5, 4) 9062306a36Sopenharmony_ci#define RK3228_POST_PLL_POST_DIV(x) UPDATE(x, 5, 4) 9162306a36Sopenharmony_ci#define RK3228_POST_PLL_LOCK_STATUS BIT(0) 9262306a36Sopenharmony_ci/* REG: 0xee */ 9362306a36Sopenharmony_ci#define RK3228_TMDS_CH_TA_ENABLE GENMASK(7, 4) 9462306a36Sopenharmony_ci/* REG: 0xef */ 9562306a36Sopenharmony_ci#define RK3228_TMDS_CLK_CH_TA(x) UPDATE(x, 7, 6) 9662306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH2_TA(x) UPDATE(x, 5, 4) 9762306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH1_TA(x) UPDATE(x, 3, 2) 9862306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH0_TA(x) UPDATE(x, 1, 0) 9962306a36Sopenharmony_ci/* REG: 0xf0 */ 10062306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS_MASK GENMASK(5, 4) 10162306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH2_PRE_EMPHASIS(x) UPDATE(x, 5, 4) 10262306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS_MASK GENMASK(3, 2) 10362306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH1_PRE_EMPHASIS(x) UPDATE(x, 3, 2) 10462306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS_MASK GENMASK(1, 0) 10562306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH0_PRE_EMPHASIS(x) UPDATE(x, 1, 0) 10662306a36Sopenharmony_ci/* REG: 0xf1 */ 10762306a36Sopenharmony_ci#define RK3228_TMDS_CLK_CH_OUTPUT_SWING(x) UPDATE(x, 7, 4) 10862306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH2_OUTPUT_SWING(x) UPDATE(x, 3, 0) 10962306a36Sopenharmony_ci/* REG: 0xf2 */ 11062306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH1_OUTPUT_SWING(x) UPDATE(x, 7, 4) 11162306a36Sopenharmony_ci#define RK3228_TMDS_DATA_CH0_OUTPUT_SWING(x) UPDATE(x, 3, 0) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* REG: 0x01 */ 11462306a36Sopenharmony_ci#define RK3328_BYPASS_RXSENSE_EN BIT(2) 11562306a36Sopenharmony_ci#define RK3328_BYPASS_POWERON_EN BIT(1) 11662306a36Sopenharmony_ci#define RK3328_BYPASS_PLLPD_EN BIT(0) 11762306a36Sopenharmony_ci/* REG: 0x02 */ 11862306a36Sopenharmony_ci#define RK3328_INT_POL_HIGH BIT(7) 11962306a36Sopenharmony_ci#define RK3328_BYPASS_PDATA_EN BIT(4) 12062306a36Sopenharmony_ci#define RK3328_PDATA_EN BIT(0) 12162306a36Sopenharmony_ci/* REG:0x05 */ 12262306a36Sopenharmony_ci#define RK3328_INT_TMDS_CLK(x) UPDATE(x, 7, 4) 12362306a36Sopenharmony_ci#define RK3328_INT_TMDS_D2(x) UPDATE(x, 3, 0) 12462306a36Sopenharmony_ci/* REG:0x07 */ 12562306a36Sopenharmony_ci#define RK3328_INT_TMDS_D1(x) UPDATE(x, 7, 4) 12662306a36Sopenharmony_ci#define RK3328_INT_TMDS_D0(x) UPDATE(x, 3, 0) 12762306a36Sopenharmony_ci/* for all RK3328_INT_TMDS_*, ESD_DET as defined in 0xc8-0xcb */ 12862306a36Sopenharmony_ci#define RK3328_INT_AGND_LOW_PULSE_LOCKED BIT(3) 12962306a36Sopenharmony_ci#define RK3328_INT_RXSENSE_LOW_PULSE_LOCKED BIT(2) 13062306a36Sopenharmony_ci#define RK3328_INT_VSS_AGND_ESD_DET BIT(1) 13162306a36Sopenharmony_ci#define RK3328_INT_AGND_VSS_ESD_DET BIT(0) 13262306a36Sopenharmony_ci/* REG: 0xa0 */ 13362306a36Sopenharmony_ci#define RK3328_PCLK_VCO_DIV_5_MASK BIT(1) 13462306a36Sopenharmony_ci#define RK3328_PCLK_VCO_DIV_5(x) UPDATE(x, 1, 1) 13562306a36Sopenharmony_ci#define RK3328_PRE_PLL_POWER_DOWN BIT(0) 13662306a36Sopenharmony_ci/* REG: 0xa1 */ 13762306a36Sopenharmony_ci#define RK3328_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0) 13862306a36Sopenharmony_ci#define RK3328_PRE_PLL_PRE_DIV(x) UPDATE(x, 5, 0) 13962306a36Sopenharmony_ci/* REG: 0xa2 */ 14062306a36Sopenharmony_ci/* unset means center spread */ 14162306a36Sopenharmony_ci#define RK3328_SPREAD_SPECTRUM_MOD_DOWN BIT(7) 14262306a36Sopenharmony_ci#define RK3328_SPREAD_SPECTRUM_MOD_DISABLE BIT(6) 14362306a36Sopenharmony_ci#define RK3328_PRE_PLL_FRAC_DIV_DISABLE UPDATE(3, 5, 4) 14462306a36Sopenharmony_ci#define RK3328_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0) 14562306a36Sopenharmony_ci#define RK3328_PRE_PLL_FB_DIV_11_8(x) UPDATE((x) >> 8, 3, 0) 14662306a36Sopenharmony_ci/* REG: 0xa3 */ 14762306a36Sopenharmony_ci#define RK3328_PRE_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) 14862306a36Sopenharmony_ci/* REG: 0xa4*/ 14962306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_C_MASK GENMASK(1, 0) 15062306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_C(x) UPDATE(x, 1, 0) 15162306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_B_MASK GENMASK(3, 2) 15262306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_B(x) UPDATE(x, 3, 2) 15362306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_A_MASK GENMASK(5, 4) 15462306a36Sopenharmony_ci#define RK3328_PRE_PLL_TMDSCLK_DIV_A(x) UPDATE(x, 5, 4) 15562306a36Sopenharmony_ci/* REG: 0xa5 */ 15662306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_B_SHIFT 5 15762306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_B_MASK GENMASK(6, 5) 15862306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_B(x) UPDATE(x, 6, 5) 15962306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_A_MASK GENMASK(4, 0) 16062306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_A(x) UPDATE(x, 4, 0) 16162306a36Sopenharmony_ci/* REG: 0xa6 */ 16262306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_C_SHIFT 5 16362306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_C_MASK GENMASK(6, 5) 16462306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_C(x) UPDATE(x, 6, 5) 16562306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_D_MASK GENMASK(4, 0) 16662306a36Sopenharmony_ci#define RK3328_PRE_PLL_PCLK_DIV_D(x) UPDATE(x, 4, 0) 16762306a36Sopenharmony_ci/* REG: 0xa9 */ 16862306a36Sopenharmony_ci#define RK3328_PRE_PLL_LOCK_STATUS BIT(0) 16962306a36Sopenharmony_ci/* REG: 0xaa */ 17062306a36Sopenharmony_ci#define RK3328_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2) 17162306a36Sopenharmony_ci#define RK3328_POST_PLL_REFCLK_SEL_TMDS BIT(1) 17262306a36Sopenharmony_ci#define RK3328_POST_PLL_POWER_DOWN BIT(0) 17362306a36Sopenharmony_ci/* REG:0xab */ 17462306a36Sopenharmony_ci#define RK3328_POST_PLL_FB_DIV_8(x) UPDATE((x) >> 8, 7, 7) 17562306a36Sopenharmony_ci#define RK3328_POST_PLL_PRE_DIV(x) UPDATE(x, 4, 0) 17662306a36Sopenharmony_ci/* REG: 0xac */ 17762306a36Sopenharmony_ci#define RK3328_POST_PLL_FB_DIV_7_0(x) UPDATE(x, 7, 0) 17862306a36Sopenharmony_ci/* REG: 0xad */ 17962306a36Sopenharmony_ci#define RK3328_POST_PLL_POST_DIV_MASK GENMASK(1, 0) 18062306a36Sopenharmony_ci#define RK3328_POST_PLL_POST_DIV_2 0x0 18162306a36Sopenharmony_ci#define RK3328_POST_PLL_POST_DIV_4 0x1 18262306a36Sopenharmony_ci#define RK3328_POST_PLL_POST_DIV_8 0x3 18362306a36Sopenharmony_ci/* REG: 0xaf */ 18462306a36Sopenharmony_ci#define RK3328_POST_PLL_LOCK_STATUS BIT(0) 18562306a36Sopenharmony_ci/* REG: 0xb0 */ 18662306a36Sopenharmony_ci#define RK3328_BANDGAP_ENABLE BIT(2) 18762306a36Sopenharmony_ci/* REG: 0xb2 */ 18862306a36Sopenharmony_ci#define RK3328_TMDS_CLK_DRIVER_EN BIT(3) 18962306a36Sopenharmony_ci#define RK3328_TMDS_D2_DRIVER_EN BIT(2) 19062306a36Sopenharmony_ci#define RK3328_TMDS_D1_DRIVER_EN BIT(1) 19162306a36Sopenharmony_ci#define RK3328_TMDS_D0_DRIVER_EN BIT(0) 19262306a36Sopenharmony_ci#define RK3328_TMDS_DRIVER_ENABLE (RK3328_TMDS_CLK_DRIVER_EN | \ 19362306a36Sopenharmony_ci RK3328_TMDS_D2_DRIVER_EN | \ 19462306a36Sopenharmony_ci RK3328_TMDS_D1_DRIVER_EN | \ 19562306a36Sopenharmony_ci RK3328_TMDS_D0_DRIVER_EN) 19662306a36Sopenharmony_ci/* REG:0xc5 */ 19762306a36Sopenharmony_ci#define RK3328_BYPASS_TERM_RESISTOR_CALIB BIT(7) 19862306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(x) UPDATE((x) >> 8, 6, 0) 19962306a36Sopenharmony_ci/* REG:0xc6 */ 20062306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(x) UPDATE(x, 7, 0) 20162306a36Sopenharmony_ci/* REG:0xc7 */ 20262306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_50 UPDATE(0, 2, 1) 20362306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_62_5 UPDATE(1, 2, 1) 20462306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_75 UPDATE(2, 2, 1) 20562306a36Sopenharmony_ci#define RK3328_TERM_RESISTOR_100 UPDATE(3, 2, 1) 20662306a36Sopenharmony_ci/* REG 0xc8 - 0xcb */ 20762306a36Sopenharmony_ci#define RK3328_ESD_DETECT_MASK GENMASK(7, 6) 20862306a36Sopenharmony_ci#define RK3328_ESD_DETECT_340MV (0x0 << 6) 20962306a36Sopenharmony_ci#define RK3328_ESD_DETECT_280MV (0x1 << 6) 21062306a36Sopenharmony_ci#define RK3328_ESD_DETECT_260MV (0x2 << 6) 21162306a36Sopenharmony_ci#define RK3328_ESD_DETECT_240MV (0x3 << 6) 21262306a36Sopenharmony_ci/* resistors can be used in parallel */ 21362306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_MASK GENMASK(5, 0) 21462306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_75 BIT(5) 21562306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_150 BIT(4) 21662306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_300 BIT(3) 21762306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_600 BIT(2) 21862306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_1000 BIT(1) 21962306a36Sopenharmony_ci#define RK3328_TMDS_TERM_RESIST_2000 BIT(0) 22062306a36Sopenharmony_ci/* REG: 0xd1 */ 22162306a36Sopenharmony_ci#define RK3328_PRE_PLL_FRAC_DIV_23_16(x) UPDATE((x) >> 16, 7, 0) 22262306a36Sopenharmony_ci/* REG: 0xd2 */ 22362306a36Sopenharmony_ci#define RK3328_PRE_PLL_FRAC_DIV_15_8(x) UPDATE((x) >> 8, 7, 0) 22462306a36Sopenharmony_ci/* REG: 0xd3 */ 22562306a36Sopenharmony_ci#define RK3328_PRE_PLL_FRAC_DIV_7_0(x) UPDATE(x, 7, 0) 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistruct inno_hdmi_phy_drv_data; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistruct inno_hdmi_phy { 23062306a36Sopenharmony_ci struct device *dev; 23162306a36Sopenharmony_ci struct regmap *regmap; 23262306a36Sopenharmony_ci int irq; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci struct phy *phy; 23562306a36Sopenharmony_ci struct clk *sysclk; 23662306a36Sopenharmony_ci struct clk *refoclk; 23762306a36Sopenharmony_ci struct clk *refpclk; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* platform data */ 24062306a36Sopenharmony_ci const struct inno_hdmi_phy_drv_data *plat_data; 24162306a36Sopenharmony_ci int chip_version; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* clk provider */ 24462306a36Sopenharmony_ci struct clk_hw hw; 24562306a36Sopenharmony_ci struct clk *phyclk; 24662306a36Sopenharmony_ci unsigned long pixclock; 24762306a36Sopenharmony_ci unsigned long tmdsclock; 24862306a36Sopenharmony_ci}; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistruct pre_pll_config { 25162306a36Sopenharmony_ci unsigned long pixclock; 25262306a36Sopenharmony_ci unsigned long tmdsclock; 25362306a36Sopenharmony_ci u8 prediv; 25462306a36Sopenharmony_ci u16 fbdiv; 25562306a36Sopenharmony_ci u8 tmds_div_a; 25662306a36Sopenharmony_ci u8 tmds_div_b; 25762306a36Sopenharmony_ci u8 tmds_div_c; 25862306a36Sopenharmony_ci u8 pclk_div_a; 25962306a36Sopenharmony_ci u8 pclk_div_b; 26062306a36Sopenharmony_ci u8 pclk_div_c; 26162306a36Sopenharmony_ci u8 pclk_div_d; 26262306a36Sopenharmony_ci u8 vco_div_5_en; 26362306a36Sopenharmony_ci u32 fracdiv; 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistruct post_pll_config { 26762306a36Sopenharmony_ci unsigned long tmdsclock; 26862306a36Sopenharmony_ci u8 prediv; 26962306a36Sopenharmony_ci u16 fbdiv; 27062306a36Sopenharmony_ci u8 postdiv; 27162306a36Sopenharmony_ci u8 version; 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistruct phy_config { 27562306a36Sopenharmony_ci unsigned long tmdsclock; 27662306a36Sopenharmony_ci u8 regs[14]; 27762306a36Sopenharmony_ci}; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistruct inno_hdmi_phy_ops { 28062306a36Sopenharmony_ci int (*init)(struct inno_hdmi_phy *inno); 28162306a36Sopenharmony_ci int (*power_on)(struct inno_hdmi_phy *inno, 28262306a36Sopenharmony_ci const struct post_pll_config *cfg, 28362306a36Sopenharmony_ci const struct phy_config *phy_cfg); 28462306a36Sopenharmony_ci void (*power_off)(struct inno_hdmi_phy *inno); 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistruct inno_hdmi_phy_drv_data { 28862306a36Sopenharmony_ci const struct inno_hdmi_phy_ops *ops; 28962306a36Sopenharmony_ci const struct clk_ops *clk_ops; 29062306a36Sopenharmony_ci const struct phy_config *phy_cfg_table; 29162306a36Sopenharmony_ci}; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic const struct pre_pll_config pre_pll_cfg_table[] = { 29462306a36Sopenharmony_ci { 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000}, 29562306a36Sopenharmony_ci { 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f}, 29662306a36Sopenharmony_ci { 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 29762306a36Sopenharmony_ci { 27000000, 33750000, 1, 45, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 29862306a36Sopenharmony_ci { 31500000, 31500000, 1, 42, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 29962306a36Sopenharmony_ci { 31500000, 39375000, 1, 105, 1, 3, 3, 10, 0, 3, 4, 0, 0x0}, 30062306a36Sopenharmony_ci { 33750000, 33750000, 1, 45, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 30162306a36Sopenharmony_ci { 33750000, 42187500, 1, 169, 2, 3, 3, 15, 0, 3, 4, 0, 0x0}, 30262306a36Sopenharmony_ci { 35500000, 35500000, 1, 71, 2, 2, 2, 6, 0, 3, 4, 0, 0x0}, 30362306a36Sopenharmony_ci { 35500000, 44375000, 1, 74, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 30462306a36Sopenharmony_ci { 36000000, 36000000, 1, 36, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 30562306a36Sopenharmony_ci { 36000000, 45000000, 1, 45, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 30662306a36Sopenharmony_ci { 40000000, 40000000, 1, 40, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 30762306a36Sopenharmony_ci { 40000000, 50000000, 1, 50, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 30862306a36Sopenharmony_ci { 49500000, 49500000, 1, 66, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 30962306a36Sopenharmony_ci { 49500000, 61875000, 1, 165, 1, 3, 3, 10, 0, 3, 4, 0, 0x0}, 31062306a36Sopenharmony_ci { 50000000, 50000000, 1, 50, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 31162306a36Sopenharmony_ci { 50000000, 62500000, 1, 125, 2, 2, 2, 15, 0, 2, 2, 0, 0x0}, 31262306a36Sopenharmony_ci { 54000000, 54000000, 1, 36, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 31362306a36Sopenharmony_ci { 54000000, 67500000, 1, 45, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 31462306a36Sopenharmony_ci { 56250000, 56250000, 1, 75, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 31562306a36Sopenharmony_ci { 56250000, 70312500, 1, 117, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 31662306a36Sopenharmony_ci { 59341000, 59341000, 1, 118, 2, 2, 2, 6, 0, 3, 4, 0, 0xae978d}, 31762306a36Sopenharmony_ci { 59341000, 74176250, 2, 148, 2, 1, 1, 15, 0, 1, 1, 0, 0x5a3d70}, 31862306a36Sopenharmony_ci { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0x0}, 31962306a36Sopenharmony_ci { 59400000, 74250000, 1, 99, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 32062306a36Sopenharmony_ci { 65000000, 65000000, 1, 65, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 32162306a36Sopenharmony_ci { 65000000, 81250000, 3, 325, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 32262306a36Sopenharmony_ci { 68250000, 68250000, 1, 91, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 32362306a36Sopenharmony_ci { 68250000, 85312500, 1, 142, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 32462306a36Sopenharmony_ci { 71000000, 71000000, 1, 71, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 32562306a36Sopenharmony_ci { 71000000, 88750000, 3, 355, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 32662306a36Sopenharmony_ci { 72000000, 72000000, 1, 36, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 32762306a36Sopenharmony_ci { 72000000, 90000000, 1, 60, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 32862306a36Sopenharmony_ci { 73250000, 73250000, 3, 293, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 32962306a36Sopenharmony_ci { 73250000, 91562500, 1, 61, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 33062306a36Sopenharmony_ci { 74176000, 74176000, 1, 37, 2, 0, 0, 1, 1, 2, 2, 0, 0x16872b}, 33162306a36Sopenharmony_ci { 74176000, 92720000, 2, 185, 2, 1, 1, 15, 0, 1, 1, 0, 0x70a3d7}, 33262306a36Sopenharmony_ci { 74250000, 74250000, 1, 99, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 33362306a36Sopenharmony_ci { 74250000, 92812500, 4, 495, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 33462306a36Sopenharmony_ci { 75000000, 75000000, 1, 50, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 33562306a36Sopenharmony_ci { 75000000, 93750000, 1, 125, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 33662306a36Sopenharmony_ci { 78750000, 78750000, 1, 105, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 33762306a36Sopenharmony_ci { 78750000, 98437500, 1, 164, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 33862306a36Sopenharmony_ci { 79500000, 79500000, 1, 53, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 33962306a36Sopenharmony_ci { 79500000, 99375000, 1, 199, 2, 2, 2, 15, 0, 2, 2, 0, 0x0}, 34062306a36Sopenharmony_ci { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 34162306a36Sopenharmony_ci { 83500000, 104375000, 1, 104, 2, 1, 1, 15, 0, 1, 1, 0, 0x600000}, 34262306a36Sopenharmony_ci { 85500000, 85500000, 1, 57, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 34362306a36Sopenharmony_ci { 85500000, 106875000, 1, 178, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 34462306a36Sopenharmony_ci { 85750000, 85750000, 3, 343, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 34562306a36Sopenharmony_ci { 85750000, 107187500, 1, 143, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 34662306a36Sopenharmony_ci { 88750000, 88750000, 3, 355, 0, 3, 3, 1, 2, 3, 4, 0, 0x0}, 34762306a36Sopenharmony_ci { 88750000, 110937500, 1, 110, 2, 1, 1, 15, 0, 1, 1, 0, 0xf00000}, 34862306a36Sopenharmony_ci { 94500000, 94500000, 1, 63, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 34962306a36Sopenharmony_ci { 94500000, 118125000, 1, 197, 3, 1, 1, 25, 0, 1, 1, 0, 0x0}, 35062306a36Sopenharmony_ci {101000000, 101000000, 1, 101, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 35162306a36Sopenharmony_ci {101000000, 126250000, 1, 42, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 35262306a36Sopenharmony_ci {102250000, 102250000, 4, 409, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 35362306a36Sopenharmony_ci {102250000, 127812500, 1, 128, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 35462306a36Sopenharmony_ci {106500000, 106500000, 1, 71, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 35562306a36Sopenharmony_ci {106500000, 133125000, 1, 133, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 35662306a36Sopenharmony_ci {108000000, 108000000, 1, 36, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 35762306a36Sopenharmony_ci {108000000, 135000000, 1, 45, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 35862306a36Sopenharmony_ci {115500000, 115500000, 1, 77, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 35962306a36Sopenharmony_ci {115500000, 144375000, 1, 48, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 36062306a36Sopenharmony_ci {117500000, 117500000, 2, 235, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 36162306a36Sopenharmony_ci {117500000, 146875000, 1, 49, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 36262306a36Sopenharmony_ci {119000000, 119000000, 1, 119, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 36362306a36Sopenharmony_ci {119000000, 148750000, 3, 148, 0, 1, 1, 1, 3, 1, 1, 0, 0xc00000}, 36462306a36Sopenharmony_ci {121750000, 121750000, 4, 487, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 36562306a36Sopenharmony_ci {121750000, 152187500, 1, 203, 0, 3, 3, 1, 3, 3, 4, 0, 0x0}, 36662306a36Sopenharmony_ci {122500000, 122500000, 2, 245, 2, 1, 1, 1, 1, 3, 4, 0, 0x0}, 36762306a36Sopenharmony_ci {122500000, 153125000, 1, 51, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 36862306a36Sopenharmony_ci {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 36962306a36Sopenharmony_ci {135000000, 168750000, 1, 169, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 37062306a36Sopenharmony_ci {136750000, 136750000, 1, 68, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, 37162306a36Sopenharmony_ci {136750000, 170937500, 1, 113, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f}, 37262306a36Sopenharmony_ci {140250000, 140250000, 2, 187, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 37362306a36Sopenharmony_ci {140250000, 175312500, 1, 117, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 37462306a36Sopenharmony_ci {146250000, 146250000, 2, 195, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 37562306a36Sopenharmony_ci {146250000, 182812500, 1, 61, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 37662306a36Sopenharmony_ci {148250000, 148250000, 3, 222, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, 37762306a36Sopenharmony_ci {148250000, 185312500, 1, 123, 0, 2, 2, 1, 3, 2, 2, 0, 0x8aaab0}, 37862306a36Sopenharmony_ci {148352000, 148352000, 2, 148, 2, 0, 0, 1, 1, 2, 2, 0, 0x5a1cac}, 37962306a36Sopenharmony_ci {148352000, 185440000, 3, 185, 0, 1, 1, 1, 3, 1, 1, 0, 0x70a3d7}, 38062306a36Sopenharmony_ci {148500000, 148500000, 1, 99, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 38162306a36Sopenharmony_ci {148500000, 185625000, 4, 495, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 38262306a36Sopenharmony_ci {154000000, 154000000, 1, 77, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 38362306a36Sopenharmony_ci {154000000, 192500000, 1, 64, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 38462306a36Sopenharmony_ci {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 38562306a36Sopenharmony_ci {156000000, 195000000, 1, 65, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 38662306a36Sopenharmony_ci {156750000, 156750000, 2, 209, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 38762306a36Sopenharmony_ci {156750000, 195937500, 1, 196, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 38862306a36Sopenharmony_ci {157000000, 157000000, 2, 157, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 38962306a36Sopenharmony_ci {157000000, 196250000, 1, 131, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 39062306a36Sopenharmony_ci {157500000, 157500000, 1, 105, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 39162306a36Sopenharmony_ci {157500000, 196875000, 1, 197, 2, 1, 1, 15, 0, 1, 1, 0, 0x0}, 39262306a36Sopenharmony_ci {162000000, 162000000, 1, 54, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 39362306a36Sopenharmony_ci {162000000, 202500000, 2, 135, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 39462306a36Sopenharmony_ci {175500000, 175500000, 1, 117, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 39562306a36Sopenharmony_ci {175500000, 219375000, 1, 73, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 39662306a36Sopenharmony_ci {179500000, 179500000, 3, 359, 0, 2, 2, 1, 0, 3, 4, 0, 0x0}, 39762306a36Sopenharmony_ci {179500000, 224375000, 1, 75, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 39862306a36Sopenharmony_ci {182750000, 182750000, 1, 91, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, 39962306a36Sopenharmony_ci {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0}, 40062306a36Sopenharmony_ci {182750000, 228437500, 1, 152, 0, 2, 2, 1, 3, 2, 2, 0, 0x4aaab0}, 40162306a36Sopenharmony_ci {187000000, 187000000, 2, 187, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 40262306a36Sopenharmony_ci {187000000, 233750000, 1, 39, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, 40362306a36Sopenharmony_ci {187250000, 187250000, 3, 280, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000}, 40462306a36Sopenharmony_ci {187250000, 234062500, 1, 156, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0}, 40562306a36Sopenharmony_ci {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 40662306a36Sopenharmony_ci {189000000, 236250000, 1, 79, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 40762306a36Sopenharmony_ci {193250000, 193250000, 3, 289, 2, 0, 0, 1, 1, 2, 2, 0, 0xe00000}, 40862306a36Sopenharmony_ci {193250000, 241562500, 1, 161, 0, 2, 2, 1, 3, 2, 2, 0, 0xaaab0}, 40962306a36Sopenharmony_ci {202500000, 202500000, 2, 135, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 41062306a36Sopenharmony_ci {202500000, 253125000, 1, 169, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 41162306a36Sopenharmony_ci {204750000, 204750000, 4, 273, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 41262306a36Sopenharmony_ci {204750000, 255937500, 1, 171, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 41362306a36Sopenharmony_ci {208000000, 208000000, 1, 104, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 41462306a36Sopenharmony_ci {208000000, 260000000, 1, 173, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 41562306a36Sopenharmony_ci {214750000, 214750000, 1, 107, 2, 0, 0, 1, 1, 2, 2, 0, 0x600000}, 41662306a36Sopenharmony_ci {214750000, 268437500, 1, 178, 0, 2, 2, 1, 3, 2, 2, 0, 0xf5554f}, 41762306a36Sopenharmony_ci {218250000, 218250000, 4, 291, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 41862306a36Sopenharmony_ci {218250000, 272812500, 1, 91, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 41962306a36Sopenharmony_ci {229500000, 229500000, 2, 153, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 42062306a36Sopenharmony_ci {229500000, 286875000, 1, 191, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 42162306a36Sopenharmony_ci {234000000, 234000000, 1, 39, 0, 0, 0, 1, 0, 1, 1, 0, 0x0}, 42262306a36Sopenharmony_ci {234000000, 292500000, 1, 195, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 42362306a36Sopenharmony_ci {241500000, 241500000, 2, 161, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 42462306a36Sopenharmony_ci {241500000, 301875000, 1, 201, 0, 2, 2, 1, 3, 2, 2, 0, 0x0}, 42562306a36Sopenharmony_ci {245250000, 245250000, 4, 327, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 42662306a36Sopenharmony_ci {245250000, 306562500, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, 42762306a36Sopenharmony_ci {245500000, 245500000, 4, 491, 2, 0, 0, 1, 1, 2, 2, 0, 0x0}, 42862306a36Sopenharmony_ci {245500000, 306875000, 1, 51, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, 42962306a36Sopenharmony_ci {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 43062306a36Sopenharmony_ci {261000000, 326250000, 1, 109, 0, 1, 1, 1, 3, 1, 1, 0, 0x0}, 43162306a36Sopenharmony_ci {268250000, 268250000, 9, 402, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000}, 43262306a36Sopenharmony_ci {268250000, 335312500, 1, 111, 0, 1, 1, 1, 3, 1, 1, 0, 0xc5554f}, 43362306a36Sopenharmony_ci {268500000, 268500000, 2, 179, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 43462306a36Sopenharmony_ci {268500000, 335625000, 1, 56, 0, 0, 0, 1, 3, 0, 0, 1, 0x0}, 43562306a36Sopenharmony_ci {281250000, 281250000, 4, 375, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 43662306a36Sopenharmony_ci {281250000, 351562500, 1, 117, 0, 3, 1, 1, 3, 1, 1, 0, 0x0}, 43762306a36Sopenharmony_ci {288000000, 288000000, 1, 48, 0, 0, 0, 1, 0, 1, 1, 0, 0x0}, 43862306a36Sopenharmony_ci {288000000, 360000000, 1, 60, 0, 2, 0, 1, 3, 0, 0, 1, 0x0}, 43962306a36Sopenharmony_ci {296703000, 296703000, 1, 49, 0, 0, 0, 1, 0, 1, 1, 0, 0x7353f7}, 44062306a36Sopenharmony_ci {296703000, 370878750, 1, 123, 0, 3, 1, 1, 3, 1, 1, 0, 0xa051eb}, 44162306a36Sopenharmony_ci {297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 44262306a36Sopenharmony_ci {297000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 1, 1, 0, 0x0}, 44362306a36Sopenharmony_ci {312250000, 312250000, 9, 468, 0, 0, 0, 1, 0, 1, 1, 0, 0x600000}, 44462306a36Sopenharmony_ci {312250000, 390312500, 1, 130, 0, 3, 1, 1, 3, 1, 1, 0, 0x1aaab0}, 44562306a36Sopenharmony_ci {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0x0}, 44662306a36Sopenharmony_ci {317000000, 396250000, 1, 66, 0, 2, 0, 1, 3, 0, 0, 1, 0x0}, 44762306a36Sopenharmony_ci {319750000, 319750000, 3, 159, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000}, 44862306a36Sopenharmony_ci {319750000, 399687500, 3, 199, 0, 2, 0, 1, 3, 0, 0, 1, 0xd80000}, 44962306a36Sopenharmony_ci {333250000, 333250000, 9, 499, 0, 0, 0, 1, 0, 1, 1, 0, 0xe00000}, 45062306a36Sopenharmony_ci {333250000, 416562500, 1, 138, 0, 3, 1, 1, 3, 1, 1, 0, 0xdaaab0}, 45162306a36Sopenharmony_ci {348500000, 348500000, 9, 522, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, 45262306a36Sopenharmony_ci {348500000, 435625000, 1, 145, 0, 3, 1, 1, 3, 1, 1, 0, 0x35554f}, 45362306a36Sopenharmony_ci {356500000, 356500000, 9, 534, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, 45462306a36Sopenharmony_ci {356500000, 445625000, 1, 148, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0}, 45562306a36Sopenharmony_ci {380500000, 380500000, 9, 570, 0, 2, 0, 1, 0, 1, 1, 0, 0xc00000}, 45662306a36Sopenharmony_ci {380500000, 475625000, 1, 158, 0, 3, 1, 1, 3, 1, 1, 0, 0x8aaab0}, 45762306a36Sopenharmony_ci {443250000, 443250000, 1, 73, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000}, 45862306a36Sopenharmony_ci {443250000, 554062500, 1, 92, 0, 2, 0, 1, 3, 0, 0, 1, 0x580000}, 45962306a36Sopenharmony_ci {505250000, 505250000, 9, 757, 0, 2, 0, 1, 0, 1, 1, 0, 0xe00000}, 46062306a36Sopenharmony_ci {552750000, 552750000, 3, 276, 0, 2, 0, 1, 0, 1, 1, 0, 0x600000}, 46162306a36Sopenharmony_ci {593407000, 296703500, 3, 296, 0, 1, 1, 1, 0, 1, 1, 0, 0xb41893}, 46262306a36Sopenharmony_ci {593407000, 370879375, 4, 494, 0, 3, 1, 1, 3, 0, 0, 1, 0x817e4a}, 46362306a36Sopenharmony_ci {593407000, 593407000, 3, 296, 0, 2, 0, 1, 0, 1, 1, 0, 0xb41893}, 46462306a36Sopenharmony_ci {594000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 1, 1, 0, 0x0}, 46562306a36Sopenharmony_ci {594000000, 371250000, 4, 495, 0, 3, 1, 1, 3, 0, 0, 1, 0x0}, 46662306a36Sopenharmony_ci {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0x0}, 46762306a36Sopenharmony_ci { /* sentinel */ } 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic const struct post_pll_config post_pll_cfg_table[] = { 47162306a36Sopenharmony_ci {33750000, 1, 40, 8, 1}, 47262306a36Sopenharmony_ci {33750000, 1, 80, 8, 2}, 47362306a36Sopenharmony_ci {74250000, 1, 40, 8, 1}, 47462306a36Sopenharmony_ci {74250000, 18, 80, 8, 2}, 47562306a36Sopenharmony_ci {148500000, 2, 40, 4, 3}, 47662306a36Sopenharmony_ci {297000000, 4, 40, 2, 3}, 47762306a36Sopenharmony_ci {594000000, 8, 40, 1, 3}, 47862306a36Sopenharmony_ci { /* sentinel */ } 47962306a36Sopenharmony_ci}; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci/* phy tuning values for an undocumented set of registers */ 48262306a36Sopenharmony_cistatic const struct phy_config rk3228_phy_cfg[] = { 48362306a36Sopenharmony_ci { 165000000, { 48462306a36Sopenharmony_ci 0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 48562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 48662306a36Sopenharmony_ci }, 48762306a36Sopenharmony_ci }, { 48862306a36Sopenharmony_ci 340000000, { 48962306a36Sopenharmony_ci 0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 49062306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 49162306a36Sopenharmony_ci }, 49262306a36Sopenharmony_ci }, { 49362306a36Sopenharmony_ci 594000000, { 49462306a36Sopenharmony_ci 0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 49562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 49662306a36Sopenharmony_ci }, 49762306a36Sopenharmony_ci }, { /* sentinel */ }, 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* phy tuning values for an undocumented set of registers */ 50162306a36Sopenharmony_cistatic const struct phy_config rk3328_phy_cfg[] = { 50262306a36Sopenharmony_ci { 165000000, { 50362306a36Sopenharmony_ci 0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08, 50462306a36Sopenharmony_ci 0x00, 0xac, 0xcc, 0xcc, 0xcc, 50562306a36Sopenharmony_ci }, 50662306a36Sopenharmony_ci }, { 50762306a36Sopenharmony_ci 340000000, { 50862306a36Sopenharmony_ci 0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08, 50962306a36Sopenharmony_ci 0x3f, 0xac, 0xcc, 0xcd, 0xdd, 51062306a36Sopenharmony_ci }, 51162306a36Sopenharmony_ci }, { 51262306a36Sopenharmony_ci 594000000, { 51362306a36Sopenharmony_ci 0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08, 51462306a36Sopenharmony_ci 0x00, 0xac, 0xcc, 0xcc, 0xcc, 51562306a36Sopenharmony_ci }, 51662306a36Sopenharmony_ci }, { /* sentinel */ }, 51762306a36Sopenharmony_ci}; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistatic inline struct inno_hdmi_phy *to_inno_hdmi_phy(struct clk_hw *hw) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci return container_of(hw, struct inno_hdmi_phy, hw); 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci/* 52562306a36Sopenharmony_ci * The register description of the IP block does not use any distinct names 52662306a36Sopenharmony_ci * but instead the databook simply numbers the registers in one-increments. 52762306a36Sopenharmony_ci * As the registers are obviously 32bit sized, the inno_* functions 52862306a36Sopenharmony_ci * translate the databook register names to the actual registers addresses. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_cistatic inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci regmap_write(inno->regmap, reg * 4, val); 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci u32 val; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci regmap_read(inno->regmap, reg * 4, &val); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return val; 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistatic inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg, 54562306a36Sopenharmony_ci u8 mask, u8 val) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci regmap_update_bits(inno->regmap, reg * 4, mask, val); 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci#define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \ 55162306a36Sopenharmony_ci regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \ 55262306a36Sopenharmony_ci sleep_us, timeout_us) 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno, 55562306a36Sopenharmony_ci unsigned long rate) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci int bus_width = phy_get_bus_width(inno->phy); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci switch (bus_width) { 56062306a36Sopenharmony_ci case 4: 56162306a36Sopenharmony_ci case 5: 56262306a36Sopenharmony_ci case 6: 56362306a36Sopenharmony_ci case 10: 56462306a36Sopenharmony_ci case 12: 56562306a36Sopenharmony_ci case 16: 56662306a36Sopenharmony_ci return (u64)rate * bus_width / 8; 56762306a36Sopenharmony_ci default: 56862306a36Sopenharmony_ci return rate; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistatic irqreturn_t inno_hdmi_phy_rk3328_hardirq(int irq, void *dev_id) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci struct inno_hdmi_phy *inno = dev_id; 57562306a36Sopenharmony_ci int intr_stat1, intr_stat2, intr_stat3; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci intr_stat1 = inno_read(inno, 0x04); 57862306a36Sopenharmony_ci intr_stat2 = inno_read(inno, 0x06); 57962306a36Sopenharmony_ci intr_stat3 = inno_read(inno, 0x08); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (intr_stat1) 58262306a36Sopenharmony_ci inno_write(inno, 0x04, intr_stat1); 58362306a36Sopenharmony_ci if (intr_stat2) 58462306a36Sopenharmony_ci inno_write(inno, 0x06, intr_stat2); 58562306a36Sopenharmony_ci if (intr_stat3) 58662306a36Sopenharmony_ci inno_write(inno, 0x08, intr_stat3); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (intr_stat1 || intr_stat2 || intr_stat3) 58962306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci return IRQ_HANDLED; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic irqreturn_t inno_hdmi_phy_rk3328_irq(int irq, void *dev_id) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci struct inno_hdmi_phy *inno = dev_id; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0); 59962306a36Sopenharmony_ci usleep_range(10, 20); 60062306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci return IRQ_HANDLED; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cistatic int inno_hdmi_phy_power_on(struct phy *phy) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci struct inno_hdmi_phy *inno = phy_get_drvdata(phy); 60862306a36Sopenharmony_ci const struct post_pll_config *cfg = post_pll_cfg_table; 60962306a36Sopenharmony_ci const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table; 61062306a36Sopenharmony_ci unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, 61162306a36Sopenharmony_ci inno->pixclock); 61262306a36Sopenharmony_ci int ret; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (!tmdsclock) { 61562306a36Sopenharmony_ci dev_err(inno->dev, "TMDS clock is zero!\n"); 61662306a36Sopenharmony_ci return -EINVAL; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (!inno->plat_data->ops->power_on) 62062306a36Sopenharmony_ci return -EINVAL; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci for (; cfg->tmdsclock != 0; cfg++) 62362306a36Sopenharmony_ci if (tmdsclock <= cfg->tmdsclock && 62462306a36Sopenharmony_ci cfg->version & inno->chip_version) 62562306a36Sopenharmony_ci break; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci for (; phy_cfg->tmdsclock != 0; phy_cfg++) 62862306a36Sopenharmony_ci if (tmdsclock <= phy_cfg->tmdsclock) 62962306a36Sopenharmony_ci break; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (cfg->tmdsclock == 0 || phy_cfg->tmdsclock == 0) 63262306a36Sopenharmony_ci return -EINVAL; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci dev_dbg(inno->dev, "Inno HDMI PHY Power On\n"); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci inno->plat_data->clk_ops->set_rate(&inno->hw, inno->pixclock, 24000000); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci ret = clk_prepare_enable(inno->phyclk); 63962306a36Sopenharmony_ci if (ret) 64062306a36Sopenharmony_ci return ret; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci ret = inno->plat_data->ops->power_on(inno, cfg, phy_cfg); 64362306a36Sopenharmony_ci if (ret) { 64462306a36Sopenharmony_ci clk_disable_unprepare(inno->phyclk); 64562306a36Sopenharmony_ci return ret; 64662306a36Sopenharmony_ci } 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci return 0; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic int inno_hdmi_phy_power_off(struct phy *phy) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci struct inno_hdmi_phy *inno = phy_get_drvdata(phy); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (!inno->plat_data->ops->power_off) 65662306a36Sopenharmony_ci return -EINVAL; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci inno->plat_data->ops->power_off(inno); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci clk_disable_unprepare(inno->phyclk); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci inno->tmdsclock = 0; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n"); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return 0; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic const struct phy_ops inno_hdmi_phy_ops = { 67062306a36Sopenharmony_ci .owner = THIS_MODULE, 67162306a36Sopenharmony_ci .power_on = inno_hdmi_phy_power_on, 67262306a36Sopenharmony_ci .power_off = inno_hdmi_phy_power_off, 67362306a36Sopenharmony_ci}; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic const 67662306a36Sopenharmony_cistruct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno, 67762306a36Sopenharmony_ci unsigned long rate) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci const struct pre_pll_config *cfg = pre_pll_cfg_table; 68062306a36Sopenharmony_ci unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci for (; cfg->pixclock != 0; cfg++) 68362306a36Sopenharmony_ci if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock) 68462306a36Sopenharmony_ci break; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci if (cfg->pixclock == 0) 68762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci return cfg; 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 69562306a36Sopenharmony_ci u8 status; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci status = inno_read(inno, 0xe0) & RK3228_PRE_PLL_POWER_DOWN; 69862306a36Sopenharmony_ci return status ? 0 : 1; 69962306a36Sopenharmony_ci} 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3228_clk_prepare(struct clk_hw *hw) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0); 70662306a36Sopenharmony_ci return 0; 70762306a36Sopenharmony_ci} 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_cistatic void inno_hdmi_phy_rk3228_clk_unprepare(struct clk_hw *hw) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 71462306a36Sopenharmony_ci RK3228_PRE_PLL_POWER_DOWN); 71562306a36Sopenharmony_ci} 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic 71862306a36Sopenharmony_ciunsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw, 71962306a36Sopenharmony_ci unsigned long parent_rate) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 72262306a36Sopenharmony_ci u8 nd, no_a, no_b, no_d; 72362306a36Sopenharmony_ci u64 vco; 72462306a36Sopenharmony_ci u16 nf; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci nd = inno_read(inno, 0xe2) & RK3228_PRE_PLL_PRE_DIV_MASK; 72762306a36Sopenharmony_ci nf = (inno_read(inno, 0xe2) & RK3228_PRE_PLL_FB_DIV_8_MASK) << 1; 72862306a36Sopenharmony_ci nf |= inno_read(inno, 0xe3); 72962306a36Sopenharmony_ci vco = parent_rate * nf; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (inno_read(inno, 0xe2) & RK3228_PCLK_VCO_DIV_5_MASK) { 73262306a36Sopenharmony_ci do_div(vco, nd * 5); 73362306a36Sopenharmony_ci } else { 73462306a36Sopenharmony_ci no_a = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_A_MASK; 73562306a36Sopenharmony_ci if (!no_a) 73662306a36Sopenharmony_ci no_a = 1; 73762306a36Sopenharmony_ci no_b = inno_read(inno, 0xe4) & RK3228_PRE_PLL_PCLK_DIV_B_MASK; 73862306a36Sopenharmony_ci no_b >>= RK3228_PRE_PLL_PCLK_DIV_B_SHIFT; 73962306a36Sopenharmony_ci no_b += 2; 74062306a36Sopenharmony_ci no_d = inno_read(inno, 0xe5) & RK3228_PRE_PLL_PCLK_DIV_D_MASK; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci inno->pixclock = vco; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return vco; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw, 75362306a36Sopenharmony_ci unsigned long rate, 75462306a36Sopenharmony_ci unsigned long *parent_rate) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci const struct pre_pll_config *cfg = pre_pll_cfg_table; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci rate = (rate / 1000) * 1000; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci for (; cfg->pixclock != 0; cfg++) 76162306a36Sopenharmony_ci if (cfg->pixclock == rate && !cfg->fracdiv) 76262306a36Sopenharmony_ci break; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci if (cfg->pixclock == 0) 76562306a36Sopenharmony_ci return -EINVAL; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci return cfg->pixclock; 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw, 77162306a36Sopenharmony_ci unsigned long rate, 77262306a36Sopenharmony_ci unsigned long parent_rate) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 77562306a36Sopenharmony_ci const struct pre_pll_config *cfg; 77662306a36Sopenharmony_ci unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); 77762306a36Sopenharmony_ci u32 v; 77862306a36Sopenharmony_ci int ret; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", 78162306a36Sopenharmony_ci __func__, rate, tmdsclock); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) 78462306a36Sopenharmony_ci return 0; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); 78762306a36Sopenharmony_ci if (IS_ERR(cfg)) 78862306a36Sopenharmony_ci return PTR_ERR(cfg); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* Power down PRE-PLL */ 79162306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 79262306a36Sopenharmony_ci RK3228_PRE_PLL_POWER_DOWN); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci inno_update_bits(inno, 0xe2, RK3228_PRE_PLL_FB_DIV_8_MASK | 79562306a36Sopenharmony_ci RK3228_PCLK_VCO_DIV_5_MASK | 79662306a36Sopenharmony_ci RK3228_PRE_PLL_PRE_DIV_MASK, 79762306a36Sopenharmony_ci RK3228_PRE_PLL_FB_DIV_8(cfg->fbdiv) | 79862306a36Sopenharmony_ci RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en) | 79962306a36Sopenharmony_ci RK3228_PRE_PLL_PRE_DIV(cfg->prediv)); 80062306a36Sopenharmony_ci inno_write(inno, 0xe3, RK3228_PRE_PLL_FB_DIV_7_0(cfg->fbdiv)); 80162306a36Sopenharmony_ci inno_update_bits(inno, 0xe4, RK3228_PRE_PLL_PCLK_DIV_B_MASK | 80262306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_A_MASK, 80362306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) | 80462306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a)); 80562306a36Sopenharmony_ci inno_update_bits(inno, 0xe5, RK3228_PRE_PLL_PCLK_DIV_C_MASK | 80662306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_D_MASK, 80762306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) | 80862306a36Sopenharmony_ci RK3228_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d)); 80962306a36Sopenharmony_ci inno_update_bits(inno, 0xe6, RK3228_PRE_PLL_TMDSCLK_DIV_C_MASK | 81062306a36Sopenharmony_ci RK3228_PRE_PLL_TMDSCLK_DIV_A_MASK | 81162306a36Sopenharmony_ci RK3228_PRE_PLL_TMDSCLK_DIV_B_MASK, 81262306a36Sopenharmony_ci RK3228_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) | 81362306a36Sopenharmony_ci RK3228_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) | 81462306a36Sopenharmony_ci RK3228_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b)); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* Power up PRE-PLL */ 81762306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN, 0); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* Wait for Pre-PLL lock */ 82062306a36Sopenharmony_ci ret = inno_poll(inno, 0xe8, v, v & RK3228_PRE_PLL_LOCK_STATUS, 82162306a36Sopenharmony_ci 100, 100000); 82262306a36Sopenharmony_ci if (ret) { 82362306a36Sopenharmony_ci dev_err(inno->dev, "Pre-PLL locking failed\n"); 82462306a36Sopenharmony_ci return ret; 82562306a36Sopenharmony_ci } 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci inno->pixclock = rate; 82862306a36Sopenharmony_ci inno->tmdsclock = tmdsclock; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci return 0; 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_cistatic const struct clk_ops inno_hdmi_phy_rk3228_clk_ops = { 83462306a36Sopenharmony_ci .prepare = inno_hdmi_phy_rk3228_clk_prepare, 83562306a36Sopenharmony_ci .unprepare = inno_hdmi_phy_rk3228_clk_unprepare, 83662306a36Sopenharmony_ci .is_prepared = inno_hdmi_phy_rk3228_clk_is_prepared, 83762306a36Sopenharmony_ci .recalc_rate = inno_hdmi_phy_rk3228_clk_recalc_rate, 83862306a36Sopenharmony_ci .round_rate = inno_hdmi_phy_rk3228_clk_round_rate, 83962306a36Sopenharmony_ci .set_rate = inno_hdmi_phy_rk3228_clk_set_rate, 84062306a36Sopenharmony_ci}; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3328_clk_is_prepared(struct clk_hw *hw) 84362306a36Sopenharmony_ci{ 84462306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 84562306a36Sopenharmony_ci u8 status; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci status = inno_read(inno, 0xa0) & RK3328_PRE_PLL_POWER_DOWN; 84862306a36Sopenharmony_ci return status ? 0 : 1; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3328_clk_prepare(struct clk_hw *hw) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0); 85662306a36Sopenharmony_ci return 0; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic void inno_hdmi_phy_rk3328_clk_unprepare(struct clk_hw *hw) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 86462306a36Sopenharmony_ci RK3328_PRE_PLL_POWER_DOWN); 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_cistatic 86862306a36Sopenharmony_ciunsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw, 86962306a36Sopenharmony_ci unsigned long parent_rate) 87062306a36Sopenharmony_ci{ 87162306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 87262306a36Sopenharmony_ci unsigned long frac; 87362306a36Sopenharmony_ci u8 nd, no_a, no_b, no_d; 87462306a36Sopenharmony_ci u64 vco; 87562306a36Sopenharmony_ci u16 nf; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK; 87862306a36Sopenharmony_ci nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8); 87962306a36Sopenharmony_ci nf |= inno_read(inno, 0xa3); 88062306a36Sopenharmony_ci vco = parent_rate * nf; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) { 88362306a36Sopenharmony_ci frac = inno_read(inno, 0xd3) | 88462306a36Sopenharmony_ci (inno_read(inno, 0xd2) << 8) | 88562306a36Sopenharmony_ci (inno_read(inno, 0xd1) << 16); 88662306a36Sopenharmony_ci vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24)); 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) { 89062306a36Sopenharmony_ci do_div(vco, nd * 5); 89162306a36Sopenharmony_ci } else { 89262306a36Sopenharmony_ci no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK; 89362306a36Sopenharmony_ci no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK; 89462306a36Sopenharmony_ci no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT; 89562306a36Sopenharmony_ci no_b += 2; 89662306a36Sopenharmony_ci no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2)); 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci dev_dbg(inno->dev, "%s rate %lu vco %llu\n", 90462306a36Sopenharmony_ci __func__, inno->pixclock, vco); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci return inno->pixclock; 90762306a36Sopenharmony_ci} 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_cistatic long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, 91062306a36Sopenharmony_ci unsigned long rate, 91162306a36Sopenharmony_ci unsigned long *parent_rate) 91262306a36Sopenharmony_ci{ 91362306a36Sopenharmony_ci const struct pre_pll_config *cfg = pre_pll_cfg_table; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci rate = (rate / 1000) * 1000; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci for (; cfg->pixclock != 0; cfg++) 91862306a36Sopenharmony_ci if (cfg->pixclock == rate) 91962306a36Sopenharmony_ci break; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci if (cfg->pixclock == 0) 92262306a36Sopenharmony_ci return -EINVAL; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci return cfg->pixclock; 92562306a36Sopenharmony_ci} 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw, 92862306a36Sopenharmony_ci unsigned long rate, 92962306a36Sopenharmony_ci unsigned long parent_rate) 93062306a36Sopenharmony_ci{ 93162306a36Sopenharmony_ci struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw); 93262306a36Sopenharmony_ci const struct pre_pll_config *cfg; 93362306a36Sopenharmony_ci unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate); 93462306a36Sopenharmony_ci u32 val; 93562306a36Sopenharmony_ci int ret; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n", 93862306a36Sopenharmony_ci __func__, rate, tmdsclock); 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci if (inno->pixclock == rate && inno->tmdsclock == tmdsclock) 94162306a36Sopenharmony_ci return 0; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate); 94462306a36Sopenharmony_ci if (IS_ERR(cfg)) 94562306a36Sopenharmony_ci return PTR_ERR(cfg); 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 94862306a36Sopenharmony_ci RK3328_PRE_PLL_POWER_DOWN); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* Configure pre-pll */ 95162306a36Sopenharmony_ci inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK, 95262306a36Sopenharmony_ci RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en)); 95362306a36Sopenharmony_ci inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv)); 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE; 95662306a36Sopenharmony_ci if (!cfg->fracdiv) 95762306a36Sopenharmony_ci val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE; 95862306a36Sopenharmony_ci inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val); 95962306a36Sopenharmony_ci inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv)); 96062306a36Sopenharmony_ci inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) | 96162306a36Sopenharmony_ci RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b)); 96262306a36Sopenharmony_ci inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) | 96362306a36Sopenharmony_ci RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d)); 96462306a36Sopenharmony_ci inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) | 96562306a36Sopenharmony_ci RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) | 96662306a36Sopenharmony_ci RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b)); 96762306a36Sopenharmony_ci inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv)); 96862306a36Sopenharmony_ci inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv)); 96962306a36Sopenharmony_ci inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv)); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0); 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci /* Wait for Pre-PLL lock */ 97462306a36Sopenharmony_ci ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS, 97562306a36Sopenharmony_ci 1000, 10000); 97662306a36Sopenharmony_ci if (ret) { 97762306a36Sopenharmony_ci dev_err(inno->dev, "Pre-PLL locking failed\n"); 97862306a36Sopenharmony_ci return ret; 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci inno->pixclock = rate; 98262306a36Sopenharmony_ci inno->tmdsclock = tmdsclock; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci return 0; 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_cistatic const struct clk_ops inno_hdmi_phy_rk3328_clk_ops = { 98862306a36Sopenharmony_ci .prepare = inno_hdmi_phy_rk3328_clk_prepare, 98962306a36Sopenharmony_ci .unprepare = inno_hdmi_phy_rk3328_clk_unprepare, 99062306a36Sopenharmony_ci .is_prepared = inno_hdmi_phy_rk3328_clk_is_prepared, 99162306a36Sopenharmony_ci .recalc_rate = inno_hdmi_phy_rk3328_clk_recalc_rate, 99262306a36Sopenharmony_ci .round_rate = inno_hdmi_phy_rk3328_clk_round_rate, 99362306a36Sopenharmony_ci .set_rate = inno_hdmi_phy_rk3328_clk_set_rate, 99462306a36Sopenharmony_ci}; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cistatic int inno_hdmi_phy_clk_register(struct inno_hdmi_phy *inno) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci struct device *dev = inno->dev; 99962306a36Sopenharmony_ci struct device_node *np = dev->of_node; 100062306a36Sopenharmony_ci struct clk_init_data init; 100162306a36Sopenharmony_ci const char *parent_name; 100262306a36Sopenharmony_ci int ret; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci parent_name = __clk_get_name(inno->refoclk); 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci init.parent_names = &parent_name; 100762306a36Sopenharmony_ci init.num_parents = 1; 100862306a36Sopenharmony_ci init.flags = 0; 100962306a36Sopenharmony_ci init.name = "pin_hd20_pclk"; 101062306a36Sopenharmony_ci init.ops = inno->plat_data->clk_ops; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci /* optional override of the clock name */ 101362306a36Sopenharmony_ci of_property_read_string(np, "clock-output-names", &init.name); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci inno->hw.init = &init; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci inno->phyclk = devm_clk_register(dev, &inno->hw); 101862306a36Sopenharmony_ci if (IS_ERR(inno->phyclk)) { 101962306a36Sopenharmony_ci ret = PTR_ERR(inno->phyclk); 102062306a36Sopenharmony_ci dev_err(dev, "failed to register clock: %d\n", ret); 102162306a36Sopenharmony_ci return ret; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci ret = of_clk_add_provider(np, of_clk_src_simple_get, inno->phyclk); 102562306a36Sopenharmony_ci if (ret) { 102662306a36Sopenharmony_ci dev_err(dev, "failed to register clock provider: %d\n", ret); 102762306a36Sopenharmony_ci return ret; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci return 0; 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci /* 103662306a36Sopenharmony_ci * Use phy internal register control 103762306a36Sopenharmony_ci * rxsense/poweron/pllpd/pdataen signal. 103862306a36Sopenharmony_ci */ 103962306a36Sopenharmony_ci inno_write(inno, 0x01, RK3228_BYPASS_RXSENSE_EN | 104062306a36Sopenharmony_ci RK3228_BYPASS_PWRON_EN | 104162306a36Sopenharmony_ci RK3228_BYPASS_PLLPD_EN); 104262306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3228_BYPASS_PDATA_EN, 104362306a36Sopenharmony_ci RK3228_BYPASS_PDATA_EN); 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci /* manual power down post-PLL */ 104662306a36Sopenharmony_ci inno_update_bits(inno, 0xaa, RK3228_POST_PLL_CTRL_MANUAL, 104762306a36Sopenharmony_ci RK3228_POST_PLL_CTRL_MANUAL); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci inno->chip_version = 1; 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci return 0; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_cistatic int 105562306a36Sopenharmony_ciinno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno, 105662306a36Sopenharmony_ci const struct post_pll_config *cfg, 105762306a36Sopenharmony_ci const struct phy_config *phy_cfg) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci int ret; 106062306a36Sopenharmony_ci u32 v; 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3228_PDATAEN_DISABLE, 106362306a36Sopenharmony_ci RK3228_PDATAEN_DISABLE); 106462306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN | 106562306a36Sopenharmony_ci RK3228_POST_PLL_POWER_DOWN, 106662306a36Sopenharmony_ci RK3228_PRE_PLL_POWER_DOWN | 106762306a36Sopenharmony_ci RK3228_POST_PLL_POWER_DOWN); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* Post-PLL update */ 107062306a36Sopenharmony_ci inno_update_bits(inno, 0xe9, RK3228_POST_PLL_PRE_DIV_MASK, 107162306a36Sopenharmony_ci RK3228_POST_PLL_PRE_DIV(cfg->prediv)); 107262306a36Sopenharmony_ci inno_update_bits(inno, 0xeb, RK3228_POST_PLL_FB_DIV_8_MASK, 107362306a36Sopenharmony_ci RK3228_POST_PLL_FB_DIV_8(cfg->fbdiv)); 107462306a36Sopenharmony_ci inno_write(inno, 0xea, RK3228_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (cfg->postdiv == 1) { 107762306a36Sopenharmony_ci inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, 107862306a36Sopenharmony_ci 0); 107962306a36Sopenharmony_ci } else { 108062306a36Sopenharmony_ci int div = cfg->postdiv / 2 - 1; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci inno_update_bits(inno, 0xe9, RK3228_POST_PLL_POST_DIV_ENABLE, 108362306a36Sopenharmony_ci RK3228_POST_PLL_POST_DIV_ENABLE); 108462306a36Sopenharmony_ci inno_update_bits(inno, 0xeb, RK3228_POST_PLL_POST_DIV_MASK, 108562306a36Sopenharmony_ci RK3228_POST_PLL_POST_DIV(div)); 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci for (v = 0; v < 4; v++) 108962306a36Sopenharmony_ci inno_write(inno, 0xef + v, phy_cfg->regs[v]); 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_PRE_PLL_POWER_DOWN | 109262306a36Sopenharmony_ci RK3228_POST_PLL_POWER_DOWN, 0); 109362306a36Sopenharmony_ci inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE, 109462306a36Sopenharmony_ci RK3228_BANDGAP_ENABLE); 109562306a36Sopenharmony_ci inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE, 109662306a36Sopenharmony_ci RK3228_TMDS_DRIVER_ENABLE); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci /* Wait for post PLL lock */ 109962306a36Sopenharmony_ci ret = inno_poll(inno, 0xeb, v, v & RK3228_POST_PLL_LOCK_STATUS, 110062306a36Sopenharmony_ci 100, 100000); 110162306a36Sopenharmony_ci if (ret) { 110262306a36Sopenharmony_ci dev_err(inno->dev, "Post-PLL locking failed\n"); 110362306a36Sopenharmony_ci return ret; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci if (cfg->tmdsclock > 340000000) 110762306a36Sopenharmony_ci msleep(100); 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3228_PDATAEN_DISABLE, 0); 111062306a36Sopenharmony_ci return 0; 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci inno_update_bits(inno, 0xe1, RK3228_TMDS_DRIVER_ENABLE, 0); 111662306a36Sopenharmony_ci inno_update_bits(inno, 0xe1, RK3228_BANDGAP_ENABLE, 0); 111762306a36Sopenharmony_ci inno_update_bits(inno, 0xe0, RK3228_POST_PLL_POWER_DOWN, 111862306a36Sopenharmony_ci RK3228_POST_PLL_POWER_DOWN); 111962306a36Sopenharmony_ci} 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_cistatic const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = { 112262306a36Sopenharmony_ci .init = inno_hdmi_phy_rk3228_init, 112362306a36Sopenharmony_ci .power_on = inno_hdmi_phy_rk3228_power_on, 112462306a36Sopenharmony_ci .power_off = inno_hdmi_phy_rk3228_power_off, 112562306a36Sopenharmony_ci}; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_cistatic int inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci struct nvmem_cell *cell; 113062306a36Sopenharmony_ci unsigned char *efuse_buf; 113162306a36Sopenharmony_ci size_t len; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci /* 113462306a36Sopenharmony_ci * Use phy internal register control 113562306a36Sopenharmony_ci * rxsense/poweron/pllpd/pdataen signal. 113662306a36Sopenharmony_ci */ 113762306a36Sopenharmony_ci inno_write(inno, 0x01, RK3328_BYPASS_RXSENSE_EN | 113862306a36Sopenharmony_ci RK3328_BYPASS_POWERON_EN | 113962306a36Sopenharmony_ci RK3328_BYPASS_PLLPD_EN); 114062306a36Sopenharmony_ci inno_write(inno, 0x02, RK3328_INT_POL_HIGH | RK3328_BYPASS_PDATA_EN | 114162306a36Sopenharmony_ci RK3328_PDATA_EN); 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci /* Disable phy irq */ 114462306a36Sopenharmony_ci inno_write(inno, 0x05, 0); 114562306a36Sopenharmony_ci inno_write(inno, 0x07, 0); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci /* try to read the chip-version */ 114862306a36Sopenharmony_ci inno->chip_version = 1; 114962306a36Sopenharmony_ci cell = nvmem_cell_get(inno->dev, "cpu-version"); 115062306a36Sopenharmony_ci if (IS_ERR(cell)) { 115162306a36Sopenharmony_ci if (PTR_ERR(cell) == -EPROBE_DEFER) 115262306a36Sopenharmony_ci return -EPROBE_DEFER; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci return 0; 115562306a36Sopenharmony_ci } 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci efuse_buf = nvmem_cell_read(cell, &len); 115862306a36Sopenharmony_ci nvmem_cell_put(cell); 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci if (IS_ERR(efuse_buf)) 116162306a36Sopenharmony_ci return 0; 116262306a36Sopenharmony_ci if (len == 1) 116362306a36Sopenharmony_ci inno->chip_version = efuse_buf[0] + 1; 116462306a36Sopenharmony_ci kfree(efuse_buf); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci return 0; 116762306a36Sopenharmony_ci} 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_cistatic int 117062306a36Sopenharmony_ciinno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno, 117162306a36Sopenharmony_ci const struct post_pll_config *cfg, 117262306a36Sopenharmony_ci const struct phy_config *phy_cfg) 117362306a36Sopenharmony_ci{ 117462306a36Sopenharmony_ci int ret; 117562306a36Sopenharmony_ci u32 v; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0); 117862306a36Sopenharmony_ci inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN, 117962306a36Sopenharmony_ci RK3328_POST_PLL_POWER_DOWN); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv)); 118262306a36Sopenharmony_ci if (cfg->postdiv == 1) { 118362306a36Sopenharmony_ci inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | 118462306a36Sopenharmony_ci RK3328_POST_PLL_PRE_DIV(cfg->prediv)); 118562306a36Sopenharmony_ci inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS | 118662306a36Sopenharmony_ci RK3328_POST_PLL_POWER_DOWN); 118762306a36Sopenharmony_ci } else { 118862306a36Sopenharmony_ci v = (cfg->postdiv / 2) - 1; 118962306a36Sopenharmony_ci v &= RK3328_POST_PLL_POST_DIV_MASK; 119062306a36Sopenharmony_ci inno_write(inno, 0xad, v); 119162306a36Sopenharmony_ci inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) | 119262306a36Sopenharmony_ci RK3328_POST_PLL_PRE_DIV(cfg->prediv)); 119362306a36Sopenharmony_ci inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE | 119462306a36Sopenharmony_ci RK3328_POST_PLL_REFCLK_SEL_TMDS | 119562306a36Sopenharmony_ci RK3328_POST_PLL_POWER_DOWN); 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci for (v = 0; v < 14; v++) 119962306a36Sopenharmony_ci inno_write(inno, 0xb5 + v, phy_cfg->regs[v]); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci /* set ESD detection threshold for TMDS CLK, D2, D1 and D0 */ 120262306a36Sopenharmony_ci for (v = 0; v < 4; v++) 120362306a36Sopenharmony_ci inno_update_bits(inno, 0xc8 + v, RK3328_ESD_DETECT_MASK, 120462306a36Sopenharmony_ci RK3328_ESD_DETECT_340MV); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci if (phy_cfg->tmdsclock > 340000000) { 120762306a36Sopenharmony_ci /* Set termination resistor to 100ohm */ 120862306a36Sopenharmony_ci v = clk_get_rate(inno->sysclk) / 100000; 120962306a36Sopenharmony_ci inno_write(inno, 0xc5, RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(v) 121062306a36Sopenharmony_ci | RK3328_BYPASS_TERM_RESISTOR_CALIB); 121162306a36Sopenharmony_ci inno_write(inno, 0xc6, RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(v)); 121262306a36Sopenharmony_ci inno_write(inno, 0xc7, RK3328_TERM_RESISTOR_100); 121362306a36Sopenharmony_ci inno_update_bits(inno, 0xc5, 121462306a36Sopenharmony_ci RK3328_BYPASS_TERM_RESISTOR_CALIB, 0); 121562306a36Sopenharmony_ci } else { 121662306a36Sopenharmony_ci inno_write(inno, 0xc5, RK3328_BYPASS_TERM_RESISTOR_CALIB); 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci /* clk termination resistor is 50ohm (parallel resistors) */ 121962306a36Sopenharmony_ci if (phy_cfg->tmdsclock > 165000000) 122062306a36Sopenharmony_ci inno_update_bits(inno, 0xc8, 122162306a36Sopenharmony_ci RK3328_TMDS_TERM_RESIST_MASK, 122262306a36Sopenharmony_ci RK3328_TMDS_TERM_RESIST_75 | 122362306a36Sopenharmony_ci RK3328_TMDS_TERM_RESIST_150); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci /* data termination resistor for D2, D1 and D0 is 150ohm */ 122662306a36Sopenharmony_ci for (v = 0; v < 3; v++) 122762306a36Sopenharmony_ci inno_update_bits(inno, 0xc9 + v, 122862306a36Sopenharmony_ci RK3328_TMDS_TERM_RESIST_MASK, 122962306a36Sopenharmony_ci RK3328_TMDS_TERM_RESIST_150); 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN, 0); 123362306a36Sopenharmony_ci inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE, 123462306a36Sopenharmony_ci RK3328_BANDGAP_ENABLE); 123562306a36Sopenharmony_ci inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE, 123662306a36Sopenharmony_ci RK3328_TMDS_DRIVER_ENABLE); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* Wait for post PLL lock */ 123962306a36Sopenharmony_ci ret = inno_poll(inno, 0xaf, v, v & RK3328_POST_PLL_LOCK_STATUS, 124062306a36Sopenharmony_ci 1000, 10000); 124162306a36Sopenharmony_ci if (ret) { 124262306a36Sopenharmony_ci dev_err(inno->dev, "Post-PLL locking failed\n"); 124362306a36Sopenharmony_ci return ret; 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (phy_cfg->tmdsclock > 340000000) 124762306a36Sopenharmony_ci msleep(100); 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci inno_update_bits(inno, 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci /* Enable PHY IRQ */ 125262306a36Sopenharmony_ci inno_write(inno, 0x05, RK3328_INT_TMDS_CLK(RK3328_INT_VSS_AGND_ESD_DET) 125362306a36Sopenharmony_ci | RK3328_INT_TMDS_D2(RK3328_INT_VSS_AGND_ESD_DET)); 125462306a36Sopenharmony_ci inno_write(inno, 0x07, RK3328_INT_TMDS_D1(RK3328_INT_VSS_AGND_ESD_DET) 125562306a36Sopenharmony_ci | RK3328_INT_TMDS_D0(RK3328_INT_VSS_AGND_ESD_DET)); 125662306a36Sopenharmony_ci return 0; 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_cistatic void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE, 0); 126262306a36Sopenharmony_ci inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE, 0); 126362306a36Sopenharmony_ci inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN, 126462306a36Sopenharmony_ci RK3328_POST_PLL_POWER_DOWN); 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci /* Disable PHY IRQ */ 126762306a36Sopenharmony_ci inno_write(inno, 0x05, 0); 126862306a36Sopenharmony_ci inno_write(inno, 0x07, 0); 126962306a36Sopenharmony_ci} 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_cistatic const struct inno_hdmi_phy_ops rk3328_hdmi_phy_ops = { 127262306a36Sopenharmony_ci .init = inno_hdmi_phy_rk3328_init, 127362306a36Sopenharmony_ci .power_on = inno_hdmi_phy_rk3328_power_on, 127462306a36Sopenharmony_ci .power_off = inno_hdmi_phy_rk3328_power_off, 127562306a36Sopenharmony_ci}; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_cistatic const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = { 127862306a36Sopenharmony_ci .ops = &rk3228_hdmi_phy_ops, 127962306a36Sopenharmony_ci .clk_ops = &inno_hdmi_phy_rk3228_clk_ops, 128062306a36Sopenharmony_ci .phy_cfg_table = rk3228_phy_cfg, 128162306a36Sopenharmony_ci}; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic const struct inno_hdmi_phy_drv_data rk3328_hdmi_phy_drv_data = { 128462306a36Sopenharmony_ci .ops = &rk3328_hdmi_phy_ops, 128562306a36Sopenharmony_ci .clk_ops = &inno_hdmi_phy_rk3328_clk_ops, 128662306a36Sopenharmony_ci .phy_cfg_table = rk3328_phy_cfg, 128762306a36Sopenharmony_ci}; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_cistatic const struct regmap_config inno_hdmi_phy_regmap_config = { 129062306a36Sopenharmony_ci .reg_bits = 32, 129162306a36Sopenharmony_ci .val_bits = 32, 129262306a36Sopenharmony_ci .reg_stride = 4, 129362306a36Sopenharmony_ci .max_register = 0x400, 129462306a36Sopenharmony_ci}; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_cistatic void inno_hdmi_phy_action(void *data) 129762306a36Sopenharmony_ci{ 129862306a36Sopenharmony_ci struct inno_hdmi_phy *inno = data; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci clk_disable_unprepare(inno->refpclk); 130162306a36Sopenharmony_ci clk_disable_unprepare(inno->sysclk); 130262306a36Sopenharmony_ci} 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_cistatic int inno_hdmi_phy_probe(struct platform_device *pdev) 130562306a36Sopenharmony_ci{ 130662306a36Sopenharmony_ci struct inno_hdmi_phy *inno; 130762306a36Sopenharmony_ci struct phy_provider *phy_provider; 130862306a36Sopenharmony_ci void __iomem *regs; 130962306a36Sopenharmony_ci int ret; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci inno = devm_kzalloc(&pdev->dev, sizeof(*inno), GFP_KERNEL); 131262306a36Sopenharmony_ci if (!inno) 131362306a36Sopenharmony_ci return -ENOMEM; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci inno->dev = &pdev->dev; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci inno->plat_data = of_device_get_match_data(inno->dev); 131862306a36Sopenharmony_ci if (!inno->plat_data || !inno->plat_data->ops) 131962306a36Sopenharmony_ci return -EINVAL; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci regs = devm_platform_ioremap_resource(pdev, 0); 132262306a36Sopenharmony_ci if (IS_ERR(regs)) 132362306a36Sopenharmony_ci return PTR_ERR(regs); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci inno->sysclk = devm_clk_get(inno->dev, "sysclk"); 132662306a36Sopenharmony_ci if (IS_ERR(inno->sysclk)) { 132762306a36Sopenharmony_ci ret = PTR_ERR(inno->sysclk); 132862306a36Sopenharmony_ci dev_err(inno->dev, "failed to get sysclk: %d\n", ret); 132962306a36Sopenharmony_ci return ret; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci inno->refpclk = devm_clk_get(inno->dev, "refpclk"); 133362306a36Sopenharmony_ci if (IS_ERR(inno->refpclk)) { 133462306a36Sopenharmony_ci ret = PTR_ERR(inno->refpclk); 133562306a36Sopenharmony_ci dev_err(inno->dev, "failed to get ref clock: %d\n", ret); 133662306a36Sopenharmony_ci return ret; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci inno->refoclk = devm_clk_get(inno->dev, "refoclk"); 134062306a36Sopenharmony_ci if (IS_ERR(inno->refoclk)) { 134162306a36Sopenharmony_ci ret = PTR_ERR(inno->refoclk); 134262306a36Sopenharmony_ci dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n", 134362306a36Sopenharmony_ci ret); 134462306a36Sopenharmony_ci return ret; 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci ret = clk_prepare_enable(inno->sysclk); 134862306a36Sopenharmony_ci if (ret) { 134962306a36Sopenharmony_ci dev_err(inno->dev, "Cannot enable inno phy sysclk: %d\n", ret); 135062306a36Sopenharmony_ci return ret; 135162306a36Sopenharmony_ci } 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci /* 135462306a36Sopenharmony_ci * Refpclk needs to be on, on at least the rk3328 for still 135562306a36Sopenharmony_ci * unknown reasons. 135662306a36Sopenharmony_ci */ 135762306a36Sopenharmony_ci ret = clk_prepare_enable(inno->refpclk); 135862306a36Sopenharmony_ci if (ret) { 135962306a36Sopenharmony_ci dev_err(inno->dev, "failed to enable refpclk\n"); 136062306a36Sopenharmony_ci clk_disable_unprepare(inno->sysclk); 136162306a36Sopenharmony_ci return ret; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci ret = devm_add_action_or_reset(inno->dev, inno_hdmi_phy_action, 136562306a36Sopenharmony_ci inno); 136662306a36Sopenharmony_ci if (ret) 136762306a36Sopenharmony_ci return ret; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci inno->regmap = devm_regmap_init_mmio(inno->dev, regs, 137062306a36Sopenharmony_ci &inno_hdmi_phy_regmap_config); 137162306a36Sopenharmony_ci if (IS_ERR(inno->regmap)) 137262306a36Sopenharmony_ci return PTR_ERR(inno->regmap); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci /* only the newer rk3328 hdmiphy has an interrupt */ 137562306a36Sopenharmony_ci inno->irq = platform_get_irq(pdev, 0); 137662306a36Sopenharmony_ci if (inno->irq > 0) { 137762306a36Sopenharmony_ci ret = devm_request_threaded_irq(inno->dev, inno->irq, 137862306a36Sopenharmony_ci inno_hdmi_phy_rk3328_hardirq, 137962306a36Sopenharmony_ci inno_hdmi_phy_rk3328_irq, 138062306a36Sopenharmony_ci IRQF_SHARED, 138162306a36Sopenharmony_ci dev_name(inno->dev), inno); 138262306a36Sopenharmony_ci if (ret) 138362306a36Sopenharmony_ci return ret; 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci inno->phy = devm_phy_create(inno->dev, NULL, &inno_hdmi_phy_ops); 138762306a36Sopenharmony_ci if (IS_ERR(inno->phy)) { 138862306a36Sopenharmony_ci dev_err(inno->dev, "failed to create HDMI PHY\n"); 138962306a36Sopenharmony_ci return PTR_ERR(inno->phy); 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci phy_set_drvdata(inno->phy, inno); 139362306a36Sopenharmony_ci phy_set_bus_width(inno->phy, 8); 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci if (inno->plat_data->ops->init) { 139662306a36Sopenharmony_ci ret = inno->plat_data->ops->init(inno); 139762306a36Sopenharmony_ci if (ret) 139862306a36Sopenharmony_ci return ret; 139962306a36Sopenharmony_ci } 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci ret = inno_hdmi_phy_clk_register(inno); 140262306a36Sopenharmony_ci if (ret) 140362306a36Sopenharmony_ci return ret; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci phy_provider = devm_of_phy_provider_register(inno->dev, 140662306a36Sopenharmony_ci of_phy_simple_xlate); 140762306a36Sopenharmony_ci return PTR_ERR_OR_ZERO(phy_provider); 140862306a36Sopenharmony_ci} 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_cistatic void inno_hdmi_phy_remove(struct platform_device *pdev) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci of_clk_del_provider(pdev->dev.of_node); 141362306a36Sopenharmony_ci} 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_cistatic const struct of_device_id inno_hdmi_phy_of_match[] = { 141662306a36Sopenharmony_ci { 141762306a36Sopenharmony_ci .compatible = "rockchip,rk3228-hdmi-phy", 141862306a36Sopenharmony_ci .data = &rk3228_hdmi_phy_drv_data 141962306a36Sopenharmony_ci }, { 142062306a36Sopenharmony_ci .compatible = "rockchip,rk3328-hdmi-phy", 142162306a36Sopenharmony_ci .data = &rk3328_hdmi_phy_drv_data 142262306a36Sopenharmony_ci }, { /* sentinel */ } 142362306a36Sopenharmony_ci}; 142462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match); 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_cistatic struct platform_driver inno_hdmi_phy_driver = { 142762306a36Sopenharmony_ci .probe = inno_hdmi_phy_probe, 142862306a36Sopenharmony_ci .remove_new = inno_hdmi_phy_remove, 142962306a36Sopenharmony_ci .driver = { 143062306a36Sopenharmony_ci .name = "inno-hdmi-phy", 143162306a36Sopenharmony_ci .of_match_table = inno_hdmi_phy_of_match, 143262306a36Sopenharmony_ci }, 143362306a36Sopenharmony_ci}; 143462306a36Sopenharmony_cimodule_platform_driver(inno_hdmi_phy_driver); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ciMODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>"); 143762306a36Sopenharmony_ciMODULE_DESCRIPTION("Innosilion HDMI 2.0 Transmitter PHY Driver"); 143862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1439