794 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Rockchip Electronics Co. Ltd.4 *5 * Author: Wyon Bi <bivvy.bi@rock-chips.com>6 */7 8#include <linux/bits.h>9#include <linux/kernel.h>10#include <linux/clk.h>11#include <linux/iopoll.h>12#include <linux/clk-provider.h>13#include <linux/delay.h>14#include <linux/init.h>15#include <linux/mfd/syscon.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/platform_device.h>19#include <linux/pm_runtime.h>20#include <linux/reset.h>21#include <linux/time64.h>22 23#include <linux/phy/phy.h>24#include <linux/phy/phy-mipi-dphy.h>25 26#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))27 28/*29 * The offset address[7:0] is distributed two parts, one from the bit7 to bit530 * is the first address, the other from the bit4 to bit0 is the second address.31 * when you configure the registers, you must set both of them. The Clock Lane32 * and Data Lane use the same registers with the same second address, but the33 * first address is different.34 */35#define FIRST_ADDRESS(x) (((x) & 0x7) << 5)36#define SECOND_ADDRESS(x) (((x) & 0x1f) << 0)37#define PHY_REG(first, second) (FIRST_ADDRESS(first) | \38 SECOND_ADDRESS(second))39 40/* Analog Register Part: reg00 */41#define BANDGAP_POWER_MASK BIT(7)42#define BANDGAP_POWER_DOWN BIT(7)43#define BANDGAP_POWER_ON 044#define LANE_EN_MASK GENMASK(6, 2)45#define LANE_EN_CK BIT(6)46#define LANE_EN_3 BIT(5)47#define LANE_EN_2 BIT(4)48#define LANE_EN_1 BIT(3)49#define LANE_EN_0 BIT(2)50#define POWER_WORK_MASK GENMASK(1, 0)51#define POWER_WORK_ENABLE UPDATE(1, 1, 0)52#define POWER_WORK_DISABLE UPDATE(2, 1, 0)53/* Analog Register Part: reg01 */54#define REG_SYNCRST_MASK BIT(2)55#define REG_SYNCRST_RESET BIT(2)56#define REG_SYNCRST_NORMAL 057#define REG_LDOPD_MASK BIT(1)58#define REG_LDOPD_POWER_DOWN BIT(1)59#define REG_LDOPD_POWER_ON 060#define REG_PLLPD_MASK BIT(0)61#define REG_PLLPD_POWER_DOWN BIT(0)62#define REG_PLLPD_POWER_ON 063/* Analog Register Part: reg03 */64#define REG_FBDIV_HI_MASK BIT(5)65#define REG_FBDIV_HI(x) UPDATE((x >> 8), 5, 5)66#define REG_PREDIV_MASK GENMASK(4, 0)67#define REG_PREDIV(x) UPDATE(x, 4, 0)68/* Analog Register Part: reg04 */69#define REG_FBDIV_LO_MASK GENMASK(7, 0)70#define REG_FBDIV_LO(x) UPDATE(x, 7, 0)71/* Analog Register Part: reg05 */72#define SAMPLE_CLOCK_PHASE_MASK GENMASK(6, 4)73#define SAMPLE_CLOCK_PHASE(x) UPDATE(x, 6, 4)74#define CLOCK_LANE_SKEW_PHASE_MASK GENMASK(2, 0)75#define CLOCK_LANE_SKEW_PHASE(x) UPDATE(x, 2, 0)76/* Analog Register Part: reg06 */77#define DATA_LANE_3_SKEW_PHASE_MASK GENMASK(6, 4)78#define DATA_LANE_3_SKEW_PHASE(x) UPDATE(x, 6, 4)79#define DATA_LANE_2_SKEW_PHASE_MASK GENMASK(2, 0)80#define DATA_LANE_2_SKEW_PHASE(x) UPDATE(x, 2, 0)81/* Analog Register Part: reg07 */82#define DATA_LANE_1_SKEW_PHASE_MASK GENMASK(6, 4)83#define DATA_LANE_1_SKEW_PHASE(x) UPDATE(x, 6, 4)84#define DATA_LANE_0_SKEW_PHASE_MASK GENMASK(2, 0)85#define DATA_LANE_0_SKEW_PHASE(x) UPDATE(x, 2, 0)86/* Analog Register Part: reg08 */87#define PLL_POST_DIV_ENABLE_MASK BIT(5)88#define PLL_POST_DIV_ENABLE BIT(5)89#define SAMPLE_CLOCK_DIRECTION_MASK BIT(4)90#define SAMPLE_CLOCK_DIRECTION_REVERSE BIT(4)91#define SAMPLE_CLOCK_DIRECTION_FORWARD 092#define LOWFRE_EN_MASK BIT(5)93#define PLL_OUTPUT_FREQUENCY_DIV_BY_1 094#define PLL_OUTPUT_FREQUENCY_DIV_BY_2 195/* Analog Register Part: reg0b */96#define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)97#define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)98#define VOD_MIN_RANGE 0x199#define VOD_MID_RANGE 0x3100#define VOD_BIG_RANGE 0x7101#define VOD_MAX_RANGE 0xf102/* Analog Register Part: reg1E */103#define PLL_MODE_SEL_MASK GENMASK(6, 5)104#define PLL_MODE_SEL_LVDS_MODE 0105#define PLL_MODE_SEL_MIPI_MODE BIT(5)106/* Digital Register Part: reg00 */107#define REG_DIG_RSTN_MASK BIT(0)108#define REG_DIG_RSTN_NORMAL BIT(0)109#define REG_DIG_RSTN_RESET 0110/* Digital Register Part: reg01 */111#define INVERT_TXCLKESC_MASK BIT(1)112#define INVERT_TXCLKESC_ENABLE BIT(1)113#define INVERT_TXCLKESC_DISABLE 0114#define INVERT_TXBYTECLKHS_MASK BIT(0)115#define INVERT_TXBYTECLKHS_ENABLE BIT(0)116#define INVERT_TXBYTECLKHS_DISABLE 0117/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg05 */118#define T_LPX_CNT_MASK GENMASK(5, 0)119#define T_LPX_CNT(x) UPDATE(x, 5, 0)120/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */121#define T_HS_ZERO_CNT_HI_MASK BIT(7)122#define T_HS_ZERO_CNT_HI(x) UPDATE(x, 7, 7)123#define T_HS_PREPARE_CNT_MASK GENMASK(6, 0)124#define T_HS_PREPARE_CNT(x) UPDATE(x, 6, 0)125/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */126#define T_HS_ZERO_CNT_LO_MASK GENMASK(5, 0)127#define T_HS_ZERO_CNT_LO(x) UPDATE(x, 5, 0)128/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */129#define T_HS_TRAIL_CNT_MASK GENMASK(6, 0)130#define T_HS_TRAIL_CNT(x) UPDATE(x, 6, 0)131/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */132#define T_HS_EXIT_CNT_LO_MASK GENMASK(4, 0)133#define T_HS_EXIT_CNT_LO(x) UPDATE(x, 4, 0)134/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */135#define T_CLK_POST_CNT_LO_MASK GENMASK(3, 0)136#define T_CLK_POST_CNT_LO(x) UPDATE(x, 3, 0)137/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */138#define LPDT_TX_PPI_SYNC_MASK BIT(2)139#define LPDT_TX_PPI_SYNC_ENABLE BIT(2)140#define LPDT_TX_PPI_SYNC_DISABLE 0141#define T_WAKEUP_CNT_HI_MASK GENMASK(1, 0)142#define T_WAKEUP_CNT_HI(x) UPDATE(x, 1, 0)143/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0d */144#define T_WAKEUP_CNT_LO_MASK GENMASK(7, 0)145#define T_WAKEUP_CNT_LO(x) UPDATE(x, 7, 0)146/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0e */147#define T_CLK_PRE_CNT_MASK GENMASK(3, 0)148#define T_CLK_PRE_CNT(x) UPDATE(x, 3, 0)149/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */150#define T_CLK_POST_CNT_HI_MASK GENMASK(7, 6)151#define T_CLK_POST_CNT_HI(x) UPDATE(x, 7, 6)152#define T_TA_GO_CNT_MASK GENMASK(5, 0)153#define T_TA_GO_CNT(x) UPDATE(x, 5, 0)154/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */155#define T_HS_EXIT_CNT_HI_MASK BIT(6)156#define T_HS_EXIT_CNT_HI(x) UPDATE(x, 6, 6)157#define T_TA_SURE_CNT_MASK GENMASK(5, 0)158#define T_TA_SURE_CNT(x) UPDATE(x, 5, 0)159/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */160#define T_TA_WAIT_CNT_MASK GENMASK(5, 0)161#define T_TA_WAIT_CNT(x) UPDATE(x, 5, 0)162/* LVDS Register Part: reg00 */163#define LVDS_DIGITAL_INTERNAL_RESET_MASK BIT(2)164#define LVDS_DIGITAL_INTERNAL_RESET_DISABLE BIT(2)165#define LVDS_DIGITAL_INTERNAL_RESET_ENABLE 0166/* LVDS Register Part: reg01 */167#define LVDS_DIGITAL_INTERNAL_ENABLE_MASK BIT(7)168#define LVDS_DIGITAL_INTERNAL_ENABLE BIT(7)169#define LVDS_DIGITAL_INTERNAL_DISABLE 0170/* LVDS Register Part: reg03 */171#define MODE_ENABLE_MASK GENMASK(2, 0)172#define TTL_MODE_ENABLE BIT(2)173#define LVDS_MODE_ENABLE BIT(1)174#define MIPI_MODE_ENABLE BIT(0)175/* LVDS Register Part: reg0b */176#define LVDS_LANE_EN_MASK GENMASK(7, 3)177#define LVDS_DATA_LANE0_EN BIT(7)178#define LVDS_DATA_LANE1_EN BIT(6)179#define LVDS_DATA_LANE2_EN BIT(5)180#define LVDS_DATA_LANE3_EN BIT(4)181#define LVDS_CLK_LANE_EN BIT(3)182#define LVDS_PLL_POWER_MASK BIT(2)183#define LVDS_PLL_POWER_OFF BIT(2)184#define LVDS_PLL_POWER_ON 0185#define LVDS_BANDGAP_POWER_MASK BIT(0)186#define LVDS_BANDGAP_POWER_DOWN BIT(0)187#define LVDS_BANDGAP_POWER_ON 0188 189#define DSI_PHY_RSTZ 0xa0190#define PHY_ENABLECLK BIT(2)191#define DSI_PHY_STATUS 0xb0192#define PHY_LOCK BIT(0)193 194enum phy_max_rate {195 MAX_1GHZ,196 MAX_2_5GHZ,197};198 199struct inno_video_phy_plat_data {200 const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;201 const unsigned int num_timings;202 enum phy_max_rate max_rate;203};204 205struct inno_dsidphy {206 struct device *dev;207 struct clk *ref_clk;208 struct clk *pclk_phy;209 struct clk *pclk_host;210 const struct inno_video_phy_plat_data *pdata;211 void __iomem *phy_base;212 void __iomem *host_base;213 struct reset_control *rst;214 enum phy_mode mode;215 struct phy_configure_opts_mipi_dphy dphy_cfg;216 217 struct clk *pll_clk;218 struct {219 struct clk_hw hw;220 u8 prediv;221 u16 fbdiv;222 unsigned long rate;223 } pll;224};225 226enum {227 REGISTER_PART_ANALOG,228 REGISTER_PART_DIGITAL,229 REGISTER_PART_CLOCK_LANE,230 REGISTER_PART_DATA0_LANE,231 REGISTER_PART_DATA1_LANE,232 REGISTER_PART_DATA2_LANE,233 REGISTER_PART_DATA3_LANE,234 REGISTER_PART_LVDS,235};236 237struct inno_mipi_dphy_timing {238 unsigned long rate;239 u8 lpx;240 u8 hs_prepare;241 u8 clk_lane_hs_zero;242 u8 data_lane_hs_zero;243 u8 hs_trail;244};245 246static const247struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {248 { 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},249 { 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},250 { 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},251 { 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},252 { 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},253 { 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},254 { 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},255 { 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},256 { 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},257 { 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},258 {1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},259};260 261static const262struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {263 { 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},264 { 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},265 { 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},266 { 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},267 { 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},268 { 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},269 { 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},270 { 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},271 { 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},272 { 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},273 {1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},274 {1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},275 {1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},276 {1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},277 {1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},278 {2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},279 {2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},280 {2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},281 {2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},282};283 284static void phy_update_bits(struct inno_dsidphy *inno,285 u8 first, u8 second, u8 mask, u8 val)286{287 u32 reg = PHY_REG(first, second) << 2;288 unsigned int tmp, orig;289 290 orig = readl(inno->phy_base + reg);291 tmp = orig & ~mask;292 tmp |= val & mask;293 writel(tmp, inno->phy_base + reg);294}295 296static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,297 unsigned long rate)298{299 unsigned long prate = clk_get_rate(inno->ref_clk);300 unsigned long best_freq = 0;301 unsigned long fref, fout;302 u8 min_prediv, max_prediv;303 u8 _prediv, best_prediv = 1;304 u16 _fbdiv, best_fbdiv = 1;305 u32 min_delta = UINT_MAX;306 307 /*308 * The PLL output frequency can be calculated using a simple formula:309 * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2310 * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2311 */312 fref = prate / 2;313 if (rate > 1000000000UL)314 fout = 1000000000UL;315 else316 fout = rate;317 318 /* 5Mhz < Fref / prediv < 40MHz */319 min_prediv = DIV_ROUND_UP(fref, 40000000);320 max_prediv = fref / 5000000;321 322 for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {323 u64 tmp;324 u32 delta;325 326 tmp = (u64)fout * _prediv;327 do_div(tmp, fref);328 _fbdiv = tmp;329 330 /*331 * The possible settings of feedback divider are332 * 12, 13, 14, 16, ~ 511333 */334 if (_fbdiv == 15)335 continue;336 337 if (_fbdiv < 12 || _fbdiv > 511)338 continue;339 340 tmp = (u64)_fbdiv * fref;341 do_div(tmp, _prediv);342 343 delta = abs(fout - tmp);344 if (!delta) {345 best_prediv = _prediv;346 best_fbdiv = _fbdiv;347 best_freq = tmp;348 break;349 } else if (delta < min_delta) {350 best_prediv = _prediv;351 best_fbdiv = _fbdiv;352 best_freq = tmp;353 min_delta = delta;354 }355 }356 357 if (best_freq) {358 inno->pll.prediv = best_prediv;359 inno->pll.fbdiv = best_fbdiv;360 inno->pll.rate = best_freq;361 }362 363 return best_freq;364}365 366static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)367{368 struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;369 const struct inno_mipi_dphy_timing *timings;370 u32 t_txbyteclkhs, t_txclkesc;371 u32 txbyteclkhs, txclkesc, esc_clk_div;372 u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;373 u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;374 unsigned int i;375 376 timings = inno->pdata->inno_mipi_dphy_timing_table;377 378 inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);379 380 /* Select MIPI mode */381 phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,382 MODE_ENABLE_MASK, MIPI_MODE_ENABLE);383 /* Configure PLL */384 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,385 REG_PREDIV_MASK, REG_PREDIV(inno->pll.prediv));386 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,387 REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));388 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,389 REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));390 if (inno->pdata->max_rate == MAX_2_5GHZ) {391 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,392 PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);393 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,394 CLOCK_LANE_VOD_RANGE_SET_MASK,395 CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));396 }397 /* Enable PLL and LDO */398 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,399 REG_LDOPD_MASK | REG_PLLPD_MASK,400 REG_LDOPD_POWER_ON | REG_PLLPD_POWER_ON);401 /* Reset analog */402 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,403 REG_SYNCRST_MASK, REG_SYNCRST_RESET);404 udelay(1);405 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,406 REG_SYNCRST_MASK, REG_SYNCRST_NORMAL);407 /* Reset digital */408 phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,409 REG_DIG_RSTN_MASK, REG_DIG_RSTN_RESET);410 udelay(1);411 phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,412 REG_DIG_RSTN_MASK, REG_DIG_RSTN_NORMAL);413 414 txbyteclkhs = inno->pll.rate / 8;415 t_txbyteclkhs = div_u64(PSEC_PER_SEC, txbyteclkhs);416 417 esc_clk_div = DIV_ROUND_UP(txbyteclkhs, 20000000);418 txclkesc = txbyteclkhs / esc_clk_div;419 t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc);420 421 /*422 * The value of counter for HS Ths-exit423 * Ths-exit = Tpin_txbyteclkhs * value424 */425 hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs);426 /*427 * The value of counter for HS Tclk-post428 * Tclk-post = Tpin_txbyteclkhs * value429 */430 clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs);431 /*432 * The value of counter for HS Tclk-pre433 * Tclk-pre = Tpin_txbyteclkhs * value434 */435 clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);436 437 /*438 * The value of counter for HS Tta-go439 * Tta-go for turnaround440 * Tta-go = Ttxclkesc * value441 */442 ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc);443 /*444 * The value of counter for HS Tta-sure445 * Tta-sure for turnaround446 * Tta-sure = Ttxclkesc * value447 */448 ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc);449 /*450 * The value of counter for HS Tta-wait451 * Tta-wait for turnaround452 * Tta-wait = Ttxclkesc * value453 */454 ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);455 456 for (i = 0; i < inno->pdata->num_timings; i++)457 if (inno->pll.rate <= timings[i].rate)458 break;459 460 if (i == inno->pdata->num_timings)461 --i;462 463 /*464 * The value of counter for HS Tlpx Time465 * Tlpx = Tpin_txbyteclkhs * (2 + value)466 */467 if (inno->pdata->max_rate == MAX_1GHZ) {468 lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);469 if (lpx >= 2)470 lpx -= 2;471 } else472 lpx = timings[i].lpx;473 474 hs_prepare = timings[i].hs_prepare;475 hs_trail = timings[i].hs_trail;476 clk_lane_hs_zero = timings[i].clk_lane_hs_zero;477 data_lane_hs_zero = timings[i].data_lane_hs_zero;478 wakeup = 0x3ff;479 480 for (i = REGISTER_PART_CLOCK_LANE; i <= REGISTER_PART_DATA3_LANE; i++) {481 if (i == REGISTER_PART_CLOCK_LANE)482 hs_zero = clk_lane_hs_zero;483 else484 hs_zero = data_lane_hs_zero;485 486 phy_update_bits(inno, i, 0x05, T_LPX_CNT_MASK,487 T_LPX_CNT(lpx));488 phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,489 T_HS_PREPARE_CNT(hs_prepare));490 if (inno->pdata->max_rate == MAX_2_5GHZ)491 phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,492 T_HS_ZERO_CNT_HI(hs_zero >> 6));493 phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,494 T_HS_ZERO_CNT_LO(hs_zero));495 phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,496 T_HS_TRAIL_CNT(hs_trail));497 if (inno->pdata->max_rate == MAX_2_5GHZ)498 phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,499 T_HS_EXIT_CNT_HI(hs_exit >> 5));500 phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,501 T_HS_EXIT_CNT_LO(hs_exit));502 if (inno->pdata->max_rate == MAX_2_5GHZ)503 phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,504 T_CLK_POST_CNT_HI(clk_post >> 4));505 phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,506 T_CLK_POST_CNT_LO(clk_post));507 phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,508 T_CLK_PRE_CNT(clk_pre));509 phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,510 T_WAKEUP_CNT_HI(wakeup >> 8));511 phy_update_bits(inno, i, 0x0d, T_WAKEUP_CNT_LO_MASK,512 T_WAKEUP_CNT_LO(wakeup));513 phy_update_bits(inno, i, 0x10, T_TA_GO_CNT_MASK,514 T_TA_GO_CNT(ta_go));515 phy_update_bits(inno, i, 0x11, T_TA_SURE_CNT_MASK,516 T_TA_SURE_CNT(ta_sure));517 phy_update_bits(inno, i, 0x12, T_TA_WAIT_CNT_MASK,518 T_TA_WAIT_CNT(ta_wait));519 }520 521 /* Enable all lanes on analog part */522 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,523 LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 |524 LANE_EN_1 | LANE_EN_0);525}526 527static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)528{529 u8 prediv = 2;530 u16 fbdiv = 28;531 532 /* Sample clock reverse direction */533 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,534 SAMPLE_CLOCK_DIRECTION_MASK | LOWFRE_EN_MASK,535 SAMPLE_CLOCK_DIRECTION_REVERSE |536 PLL_OUTPUT_FREQUENCY_DIV_BY_1);537 538 /* Select LVDS mode */539 phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,540 MODE_ENABLE_MASK, LVDS_MODE_ENABLE);541 /* Configure PLL */542 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,543 REG_PREDIV_MASK, REG_PREDIV(prediv));544 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,545 REG_FBDIV_HI_MASK, REG_FBDIV_HI(fbdiv));546 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,547 REG_FBDIV_LO_MASK, REG_FBDIV_LO(fbdiv));548 phy_update_bits(inno, REGISTER_PART_LVDS, 0x08, 0xff, 0xfc);549 /* Enable PLL and Bandgap */550 phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,551 LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,552 LVDS_PLL_POWER_ON | LVDS_BANDGAP_POWER_ON);553 554 msleep(20);555 556 /* Select PLL mode */557 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x1e,558 PLL_MODE_SEL_MASK, PLL_MODE_SEL_LVDS_MODE);559 560 /* Reset LVDS digital logic */561 phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,562 LVDS_DIGITAL_INTERNAL_RESET_MASK,563 LVDS_DIGITAL_INTERNAL_RESET_ENABLE);564 udelay(1);565 phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,566 LVDS_DIGITAL_INTERNAL_RESET_MASK,567 LVDS_DIGITAL_INTERNAL_RESET_DISABLE);568 /* Enable LVDS digital logic */569 phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,570 LVDS_DIGITAL_INTERNAL_ENABLE_MASK,571 LVDS_DIGITAL_INTERNAL_ENABLE);572 /* Enable LVDS analog driver */573 phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,574 LVDS_LANE_EN_MASK, LVDS_CLK_LANE_EN |575 LVDS_DATA_LANE0_EN | LVDS_DATA_LANE1_EN |576 LVDS_DATA_LANE2_EN | LVDS_DATA_LANE3_EN);577}578 579static int inno_dsidphy_power_on(struct phy *phy)580{581 struct inno_dsidphy *inno = phy_get_drvdata(phy);582 583 clk_prepare_enable(inno->pclk_phy);584 clk_prepare_enable(inno->ref_clk);585 pm_runtime_get_sync(inno->dev);586 587 /* Bandgap power on */588 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,589 BANDGAP_POWER_MASK, BANDGAP_POWER_ON);590 /* Enable power work */591 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,592 POWER_WORK_MASK, POWER_WORK_ENABLE);593 594 switch (inno->mode) {595 case PHY_MODE_MIPI_DPHY:596 inno_dsidphy_mipi_mode_enable(inno);597 break;598 case PHY_MODE_LVDS:599 inno_dsidphy_lvds_mode_enable(inno);600 break;601 default:602 return -EINVAL;603 }604 605 return 0;606}607 608static int inno_dsidphy_power_off(struct phy *phy)609{610 struct inno_dsidphy *inno = phy_get_drvdata(phy);611 612 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, LANE_EN_MASK, 0);613 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,614 REG_LDOPD_MASK | REG_PLLPD_MASK,615 REG_LDOPD_POWER_DOWN | REG_PLLPD_POWER_DOWN);616 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,617 POWER_WORK_MASK, POWER_WORK_DISABLE);618 phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,619 BANDGAP_POWER_MASK, BANDGAP_POWER_DOWN);620 621 phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b, LVDS_LANE_EN_MASK, 0);622 phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,623 LVDS_DIGITAL_INTERNAL_ENABLE_MASK,624 LVDS_DIGITAL_INTERNAL_DISABLE);625 phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,626 LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,627 LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);628 629 pm_runtime_put(inno->dev);630 clk_disable_unprepare(inno->ref_clk);631 clk_disable_unprepare(inno->pclk_phy);632 633 return 0;634}635 636static int inno_dsidphy_set_mode(struct phy *phy, enum phy_mode mode,637 int submode)638{639 struct inno_dsidphy *inno = phy_get_drvdata(phy);640 641 switch (mode) {642 case PHY_MODE_MIPI_DPHY:643 case PHY_MODE_LVDS:644 inno->mode = mode;645 break;646 default:647 return -EINVAL;648 }649 650 return 0;651}652 653static int inno_dsidphy_configure(struct phy *phy,654 union phy_configure_opts *opts)655{656 struct inno_dsidphy *inno = phy_get_drvdata(phy);657 int ret;658 659 if (inno->mode != PHY_MODE_MIPI_DPHY)660 return -EINVAL;661 662 ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);663 if (ret)664 return ret;665 666 memcpy(&inno->dphy_cfg, &opts->mipi_dphy, sizeof(inno->dphy_cfg));667 668 return 0;669}670 671static const struct phy_ops inno_dsidphy_ops = {672 .configure = inno_dsidphy_configure,673 .set_mode = inno_dsidphy_set_mode,674 .power_on = inno_dsidphy_power_on,675 .power_off = inno_dsidphy_power_off,676 .owner = THIS_MODULE,677};678 679static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {680 .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,681 .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),682 .max_rate = MAX_1GHZ,683};684 685static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {686 .inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,687 .num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),688 .max_rate = MAX_2_5GHZ,689};690 691static int inno_dsidphy_probe(struct platform_device *pdev)692{693 struct device *dev = &pdev->dev;694 struct inno_dsidphy *inno;695 struct phy_provider *phy_provider;696 struct phy *phy;697 int ret;698 699 inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);700 if (!inno)701 return -ENOMEM;702 703 inno->dev = dev;704 inno->pdata = of_device_get_match_data(inno->dev);705 platform_set_drvdata(pdev, inno);706 707 inno->phy_base = devm_platform_ioremap_resource(pdev, 0);708 if (IS_ERR(inno->phy_base))709 return PTR_ERR(inno->phy_base);710 711 inno->ref_clk = devm_clk_get(dev, "ref");712 if (IS_ERR(inno->ref_clk)) {713 ret = PTR_ERR(inno->ref_clk);714 dev_err(dev, "failed to get ref clock: %d\n", ret);715 return ret;716 }717 718 inno->pclk_phy = devm_clk_get(dev, "pclk");719 if (IS_ERR(inno->pclk_phy)) {720 ret = PTR_ERR(inno->pclk_phy);721 dev_err(dev, "failed to get phy pclk: %d\n", ret);722 return ret;723 }724 725 inno->rst = devm_reset_control_get(dev, "apb");726 if (IS_ERR(inno->rst)) {727 ret = PTR_ERR(inno->rst);728 dev_err(dev, "failed to get system reset control: %d\n", ret);729 return ret;730 }731 732 phy = devm_phy_create(dev, NULL, &inno_dsidphy_ops);733 if (IS_ERR(phy)) {734 ret = PTR_ERR(phy);735 dev_err(dev, "failed to create phy: %d\n", ret);736 return ret;737 }738 739 phy_set_drvdata(phy, inno);740 741 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);742 if (IS_ERR(phy_provider)) {743 ret = PTR_ERR(phy_provider);744 dev_err(dev, "failed to register phy provider: %d\n", ret);745 return ret;746 }747 748 pm_runtime_enable(dev);749 750 return 0;751}752 753static void inno_dsidphy_remove(struct platform_device *pdev)754{755 struct inno_dsidphy *inno = platform_get_drvdata(pdev);756 757 pm_runtime_disable(inno->dev);758}759 760static const struct of_device_id inno_dsidphy_of_match[] = {761 {762 .compatible = "rockchip,px30-dsi-dphy",763 .data = &max_1ghz_video_phy_plat_data,764 }, {765 .compatible = "rockchip,rk3128-dsi-dphy",766 .data = &max_1ghz_video_phy_plat_data,767 }, {768 .compatible = "rockchip,rk3368-dsi-dphy",769 .data = &max_1ghz_video_phy_plat_data,770 }, {771 .compatible = "rockchip,rk3568-dsi-dphy",772 .data = &max_2_5ghz_video_phy_plat_data,773 }, {774 .compatible = "rockchip,rv1126-dsi-dphy",775 .data = &max_2_5ghz_video_phy_plat_data,776 },777 {}778};779MODULE_DEVICE_TABLE(of, inno_dsidphy_of_match);780 781static struct platform_driver inno_dsidphy_driver = {782 .driver = {783 .name = "inno-dsidphy",784 .of_match_table = of_match_ptr(inno_dsidphy_of_match),785 },786 .probe = inno_dsidphy_probe,787 .remove_new = inno_dsidphy_remove,788};789module_platform_driver(inno_dsidphy_driver);790 791MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");792MODULE_DESCRIPTION("Innosilicon MIPI/LVDS/TTL Video Combo PHY driver");793MODULE_LICENSE("GPL v2");794