Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: rockchip: Add Samsung MIPI D-/C-PHY driver

Add driver for the MIPI D-/C-PHY block based around a Samsung IP-block
that is for example needed to drive a MIPI DSI output on rk3588.

Right now only the D-PHY portion is implemented, with the C-PHY part
needing separate work.

Tested-by: Daniel Semkowicz <dse@thaumatec.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: Quentin Schulz <quentin.schulz@cherry.de>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
Link: https://lore.kernel.org/r/20250313134035.278133-3-heiko@sntech.de
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Heiko Stuebner and committed by
Vinod Koul
b2a1a2ae 301587cf

+1732
+12
drivers/phy/rockchip/Kconfig
··· 83 83 help 84 84 Enable this to support the Rockchip PCIe PHY. 85 85 86 + config PHY_ROCKCHIP_SAMSUNG_DCPHY 87 + tristate "Rockchip Samsung MIPI DCPHY driver" 88 + depends on (ARCH_ROCKCHIP || COMPILE_TEST) 89 + select GENERIC_PHY 90 + select GENERIC_PHY_MIPI_DPHY 91 + help 92 + Enable this to support the Rockchip MIPI DCPHY with 93 + Samsung IP block. 94 + 95 + To compile this driver as a module, choose M here: the module 96 + will be called phy-rockchip-samsung-dcphy 97 + 86 98 config PHY_ROCKCHIP_SAMSUNG_HDPTX 87 99 tristate "Rockchip Samsung HDMI/eDP Combo PHY driver" 88 100 depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+1
drivers/phy/rockchip/Makefile
··· 8 8 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o 9 9 obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o 10 10 obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o 11 + obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY) += phy-rockchip-samsung-dcphy.o 11 12 obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o 12 13 obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o 13 14 obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
+1719
drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2025 Rockchip Electronics Co.Ltd 4 + * Author: 5 + * Guochun Huang <hero.huang@rock-chips.com> 6 + */ 7 + 8 + #include <dt-bindings/phy/phy.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/clk.h> 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + #include <linux/mfd/syscon.h> 14 + #include <linux/module.h> 15 + #include <linux/mod_devicetable.h> 16 + #include <linux/of.h> 17 + #include <linux/phy/phy.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/pm_runtime.h> 20 + #include <linux/regmap.h> 21 + #include <linux/reset.h> 22 + 23 + #define FIELD_PREP_HIWORD(_mask, _val) \ 24 + ( \ 25 + FIELD_PREP((_mask), (_val)) | \ 26 + ((_mask) << 16) \ 27 + ) 28 + 29 + #define BIAS_CON0 0x0000 30 + #define I_RES_CNTL_MASK GENMASK(6, 4) 31 + #define I_RES_CNTL(x) FIELD_PREP(I_RES_CNTL_MASK, x) 32 + #define I_RES_059_2UA I_RES_CNTL(0) 33 + #define I_RES_100_2UA I_RES_CNTL(1) 34 + #define I_RES_094_2UA I_RES_CNTL(2) 35 + #define I_RES_113_8UA I_RES_CNTL(3) 36 + #define I_RES_089_7UA I_RES_CNTL(4) 37 + #define I_RES_111_8UA I_RES_CNTL(5) 38 + #define I_RES_108_2UA I_RES_CNTL(6) 39 + #define I_RES_120_8UA I_RES_CNTL(7) 40 + #define I_DEV_SEL_MASK GENMASK(1, 0) 41 + #define I_DEV_SEL(x) FIELD_PREP(I_DEV_SEL_MASK, x) 42 + #define I_DEV_DIV_6 I_DEV_SEL(0) 43 + #define I_DEV_DIV_12 I_DEV_SEL(1) 44 + #define I_DEV_DIV_20 I_DEV_SEL(2) 45 + #define I_DEV_DIV_40 I_DEV_SEL(3) 46 + 47 + #define BIAS_CON1 0x0004 48 + #define I_VBG_SEL_MASK GENMASK(9, 8) 49 + #define I_VBG_SEL(x) FIELD_PREP(I_VBG_SEL_MASK, x) 50 + #define I_VBG_SEL_780MV I_VBG_SEL(0) 51 + #define I_VBG_SEL_820MV I_VBG_SEL(1) 52 + #define I_VBG_SEL_860MV I_VBG_SEL(2) 53 + #define I_VBG_SEL_900MV I_VBG_SEL(3) 54 + #define I_BGR_VREF_SEL_MASK GENMASK(5, 4) 55 + #define I_BGR_VREF_SEL(x) FIELD_PREP(I_BGR_VREF_SEL_MASK, x) 56 + #define I_BGR_VREF_810MV I_BGR_VREF_SEL(0) 57 + #define I_BGR_VREF_820MV I_BGR_VREF_SEL(1) 58 + #define I_BGR_VREF_830MV I_BGR_VREF_SEL(2) 59 + #define I_BGR_VREF_840MV I_BGR_VREF_SEL(3) 60 + #define I_LADDER_SEL_MASK GENMASK(2, 0) 61 + #define I_LADDER_SEL(x) FIELD_PREP(I_LADDER_SEL_MASK, x) 62 + #define I_LADDER_1_00V I_LADDER_SEL(0) 63 + #define I_LADDER_0_96V I_LADDER_SEL(1) 64 + #define I_LADDER_0_92V I_LADDER_SEL(2) 65 + #define I_LADDER_0_88V I_LADDER_SEL(3) 66 + #define I_LADDER_0_84V I_LADDER_SEL(4) 67 + #define I_LADDER_0_80V I_LADDER_SEL(5) 68 + #define I_LADDER_0_76V I_LADDER_SEL(6) 69 + #define I_LADDER_0_72V I_LADDER_SEL(7) 70 + 71 + /* 72 + * Voltage corrections around reference voltages 73 + * The selection between the 400-based or 200-based values for REG_400M 74 + * is done by the hw depending on I_MUX below being 400MV or 200MV. 75 + */ 76 + #define BIAS_CON2 0x0008 77 + #define REG_325M_MASK GENMASK(14, 12) 78 + #define REG_325M(x) FIELD_PREP(REG_325M_MASK, x) 79 + #define REG_325M_295MV REG_325M(0) 80 + #define REG_325M_305MV REG_325M(1) 81 + #define REG_325M_315MV REG_325M(2) 82 + #define REG_325M_325MV REG_325M(3) 83 + #define REG_325M_335MV REG_325M(4) 84 + #define REG_325M_345MV REG_325M(5) 85 + #define REG_325M_355MV REG_325M(6) 86 + #define REG_325M_365MV REG_325M(7) 87 + #define REG_LP_400M_MASK GENMASK(10, 8) 88 + #define REG_LP_400M(x) FIELD_PREP(REG_LP_400M_MASK, x) 89 + #define REG_LP_400M_380MV REG_LP_400M(0) 90 + #define REG_LP_400M_390MV REG_LP_400M(1) 91 + #define REG_LP_400M_400MV REG_LP_400M(2) 92 + #define REG_LP_400M_410MV REG_LP_400M(3) 93 + #define REG_LP_400M_420MV REG_LP_400M(4) 94 + #define REG_LP_400M_430MV REG_LP_400M(5) 95 + #define REG_LP_400M_440MV REG_LP_400M(6) 96 + #define REG_LP_400M_450MV REG_LP_400M(7) 97 + #define REG_400M_MASK GENMASK(6, 4) 98 + #define REG_400M(x) FIELD_PREP(REG_400M_MASK, x) 99 + #define REG_400M_380MV REG_400M(0) 100 + #define REG_400M_390MV REG_400M(1) 101 + #define REG_400M_400MV REG_400M(2) 102 + #define REG_400M_410MV REG_400M(3) 103 + #define REG_400M_420MV REG_400M(4) 104 + #define REG_400M_430MV REG_400M(5) 105 + #define REG_400M_440MV REG_400M(6) 106 + #define REG_400M_450MV REG_400M(7) 107 + #define REG_400M_230MV REG_400M(0) 108 + #define REG_400M_220MV REG_400M(1) 109 + #define REG_400M_210MV REG_400M(2) 110 + #define REG_400M_200MV REG_400M(3) 111 + #define REG_400M_190MV REG_400M(4) 112 + #define REG_400M_180MV REG_400M(5) 113 + #define REG_400M_170MV REG_400M(6) 114 + #define REG_400M_160MV REG_400M(7) 115 + #define REG_645M_MASK GENMASK(2, 0) 116 + #define REG_645M(x) FIELD_PREP(REG_645M_MASK, x) 117 + #define REG_645M_605MV REG_645M(0) 118 + #define REG_645M_625MV REG_645M(1) 119 + #define REG_645M_635MV REG_645M(2) 120 + #define REG_645M_645MV REG_645M(3) 121 + #define REG_645M_655MV REG_645M(4) 122 + #define REG_645M_665MV REG_645M(5) 123 + #define REG_645M_685MV REG_645M(6) 124 + #define REG_645M_725MV REG_645M(7) 125 + 126 + #define BIAS_CON4 0x0010 127 + #define I_MUX_SEL_MASK GENMASK(6, 5) 128 + #define I_MUX_SEL(x) FIELD_PREP(I_MUX_SEL_MASK, x) 129 + #define I_MUX_400MV I_MUX_SEL(0) 130 + #define I_MUX_200MV I_MUX_SEL(1) 131 + #define I_MUX_530MV I_MUX_SEL(2) 132 + 133 + #define PLL_CON0 0x0100 134 + #define PLL_EN BIT(12) 135 + #define S_MASK GENMASK(10, 8) 136 + #define S(x) FIELD_PREP(S_MASK, x) 137 + #define P_MASK GENMASK(5, 0) 138 + #define P(x) FIELD_PREP(P_MASK, x) 139 + #define PLL_CON1 0x0104 140 + #define PLL_CON2 0x0108 141 + #define M_MASK GENMASK(9, 0) 142 + #define M(x) FIELD_PREP(M_MASK, x) 143 + #define PLL_CON3 0x010c 144 + #define MRR_MASK GENMASK(13, 8) 145 + #define MRR(x) FIELD_PREP(MRR_MASK, x) 146 + #define MFR_MASK GENMASK(7, 0) 147 + #define MFR(x) FIELD_PREP(MFR_MASK, x) 148 + #define PLL_CON4 0x0110 149 + #define SSCG_EN BIT(11) 150 + #define PLL_CON5 0x0114 151 + #define RESET_N_SEL BIT(10) 152 + #define PLL_ENABLE_SEL BIT(8) 153 + #define PLL_CON6 0x0118 154 + #define PLL_CON7 0x011c 155 + #define PLL_LOCK_CNT(x) FIELD_PREP(GENMASK(15, 0), x) 156 + #define PLL_CON8 0x0120 157 + #define PLL_STB_CNT(x) FIELD_PREP(GENMASK(15, 0), x) 158 + #define PLL_STAT0 0x0140 159 + #define PLL_LOCK BIT(0) 160 + 161 + #define DPHY_MC_GNR_CON0 0x0300 162 + #define PHY_READY BIT(1) 163 + #define PHY_ENABLE BIT(0) 164 + #define DPHY_MC_GNR_CON1 0x0304 165 + #define T_PHY_READY(x) FIELD_PREP(GENMASK(15, 0), x) 166 + #define DPHY_MC_ANA_CON0 0x0308 167 + #define EDGE_CON(x) FIELD_PREP(GENMASK(14, 12), x) 168 + #define EDGE_CON_DIR(x) FIELD_PREP(BIT(9), x) 169 + #define EDGE_CON_EN BIT(8) 170 + #define RES_UP(x) FIELD_PREP(GENMASK(7, 4), x) 171 + #define RES_DN(x) FIELD_PREP(GENMASK(3, 0), x) 172 + #define DPHY_MC_ANA_CON1 0x030c 173 + #define DPHY_MC_ANA_CON2 0x0310 174 + #define HS_VREG_AMP_ICON(x) FIELD_PREP(GENMASK(1, 0), x) 175 + #define DPHY_MC_TIME_CON0 0x0330 176 + #define HSTX_CLK_SEL BIT(12) 177 + #define T_LPX(x) FIELD_PREP(GENMASK(11, 4), x) 178 + #define DPHY_MC_TIME_CON1 0x0334 179 + #define T_CLK_ZERO(x) FIELD_PREP(GENMASK(15, 8), x) 180 + #define T_CLK_PREPARE(x) FIELD_PREP(GENMASK(7, 0), x) 181 + #define DPHY_MC_TIME_CON2 0x0338 182 + #define T_HS_EXIT(x) FIELD_PREP(GENMASK(15, 8), x) 183 + #define T_CLK_TRAIL(x) FIELD_PREP(GENMASK(7, 0), x) 184 + #define DPHY_MC_TIME_CON3 0x033c 185 + #define T_CLK_POST(x) FIELD_PREP(GENMASK(7, 0), x) 186 + #define DPHY_MC_TIME_CON4 0x0340 187 + #define T_ULPS_EXIT(x) FIELD_PREP(GENMASK(9, 0), x) 188 + #define DPHY_MC_DESKEW_CON0 0x0350 189 + #define SKEW_CAL_RUN_TIME(x) FIELD_PREP(GENMASK(15, 12), x) 190 + 191 + #define SKEW_CAL_INIT_RUN_TIME(x) FIELD_PREP(GENMASK(11, 8), x) 192 + #define SKEW_CAL_INIT_WAIT_TIME(x) FIELD_PREP(GENMASK(7, 4), x) 193 + #define SKEW_CAL_EN BIT(0) 194 + 195 + #define COMBO_MD0_GNR_CON0 0x0400 196 + #define COMBO_MD0_GNR_CON1 0x0404 197 + #define COMBO_MD0_ANA_CON0 0x0408 198 + #define COMBO_MD0_ANA_CON1 0x040c 199 + #define COMBO_MD0_ANA_CON2 0x0410 200 + 201 + #define COMBO_MD0_TIME_CON0 0x0430 202 + #define COMBO_MD0_TIME_CON1 0x0434 203 + #define COMBO_MD0_TIME_CON2 0x0438 204 + #define COMBO_MD0_TIME_CON3 0x043c 205 + #define COMBO_MD0_TIME_CON4 0x0440 206 + #define COMBO_MD0_DATA_CON0 0x0444 207 + 208 + #define COMBO_MD1_GNR_CON0 0x0500 209 + #define COMBO_MD1_GNR_CON1 0x0504 210 + #define COMBO_MD1_ANA_CON0 0x0508 211 + #define COMBO_MD1_ANA_CON1 0x050c 212 + #define COMBO_MD1_ANA_CON2 0x0510 213 + #define COMBO_MD1_TIME_CON0 0x0530 214 + #define COMBO_MD1_TIME_CON1 0x0534 215 + #define COMBO_MD1_TIME_CON2 0x0538 216 + #define COMBO_MD1_TIME_CON3 0x053c 217 + #define COMBO_MD1_TIME_CON4 0x0540 218 + #define COMBO_MD1_DATA_CON0 0x0544 219 + 220 + #define COMBO_MD2_GNR_CON0 0x0600 221 + #define COMBO_MD2_GNR_CON1 0x0604 222 + #define COMBO_MD2_ANA_CON0 0X0608 223 + #define COMBO_MD2_ANA_CON1 0X060c 224 + #define COMBO_MD2_ANA_CON2 0X0610 225 + #define COMBO_MD2_TIME_CON0 0x0630 226 + #define COMBO_MD2_TIME_CON1 0x0634 227 + #define COMBO_MD2_TIME_CON2 0x0638 228 + #define COMBO_MD2_TIME_CON3 0x063c 229 + #define COMBO_MD2_TIME_CON4 0x0640 230 + #define COMBO_MD2_DATA_CON0 0x0644 231 + 232 + #define DPHY_MD3_GNR_CON0 0x0700 233 + #define DPHY_MD3_GNR_CON1 0x0704 234 + #define DPHY_MD3_ANA_CON0 0X0708 235 + #define DPHY_MD3_ANA_CON1 0X070c 236 + #define DPHY_MD3_ANA_CON2 0X0710 237 + #define DPHY_MD3_TIME_CON0 0x0730 238 + #define DPHY_MD3_TIME_CON1 0x0734 239 + #define DPHY_MD3_TIME_CON2 0x0738 240 + #define DPHY_MD3_TIME_CON3 0x073c 241 + #define DPHY_MD3_TIME_CON4 0x0740 242 + #define DPHY_MD3_DATA_CON0 0x0744 243 + 244 + #define T_LP_EXIT_SKEW(x) FIELD_PREP(GENMASK(3, 2), x) 245 + #define T_LP_ENTRY_SKEW(x) FIELD_PREP(GENMASK(1, 0), x) 246 + #define T_HS_ZERO(x) FIELD_PREP(GENMASK(15, 8), x) 247 + #define T_HS_PREPARE(x) FIELD_PREP(GENMASK(7, 0), x) 248 + #define T_HS_EXIT(x) FIELD_PREP(GENMASK(15, 8), x) 249 + #define T_HS_TRAIL(x) FIELD_PREP(GENMASK(7, 0), x) 250 + #define T_TA_GET(x) FIELD_PREP(GENMASK(7, 4), x) 251 + #define T_TA_GO(x) FIELD_PREP(GENMASK(3, 0), x) 252 + 253 + /* MIPI_CDPHY_GRF registers */ 254 + #define MIPI_DCPHY_GRF_CON0 0x0000 255 + #define S_CPHY_MODE FIELD_PREP_HIWORD(BIT(3), 1) 256 + #define M_CPHY_MODE FIELD_PREP_HIWORD(BIT(0), 1) 257 + 258 + enum hs_drv_res_ohm { 259 + STRENGTH_30_OHM = 0x8, 260 + STRENGTH_31_2_OHM, 261 + STRENGTH_32_5_OHM, 262 + STRENGTH_34_OHM, 263 + STRENGTH_35_5_OHM, 264 + STRENGTH_37_OHM, 265 + STRENGTH_39_OHM, 266 + STRENGTH_41_OHM, 267 + STRENGTH_43_OHM = 0x0, 268 + STRENGTH_46_OHM, 269 + STRENGTH_49_OHM, 270 + STRENGTH_52_OHM, 271 + STRENGTH_56_OHM, 272 + STRENGTH_60_OHM, 273 + STRENGTH_66_OHM, 274 + STRENGTH_73_OHM, 275 + }; 276 + 277 + struct hs_drv_res_cfg { 278 + enum hs_drv_res_ohm clk_hs_drv_up_ohm; 279 + enum hs_drv_res_ohm clk_hs_drv_down_ohm; 280 + enum hs_drv_res_ohm data_hs_drv_up_ohm; 281 + enum hs_drv_res_ohm data_hs_drv_down_ohm; 282 + }; 283 + 284 + struct samsung_mipi_dcphy_plat_data { 285 + const struct hs_drv_res_cfg *dphy_hs_drv_res_cfg; 286 + u32 dphy_tx_max_lane_kbps; 287 + }; 288 + 289 + struct samsung_mipi_dcphy { 290 + struct device *dev; 291 + struct clk *ref_clk; 292 + struct clk *pclk; 293 + struct regmap *regmap; 294 + struct regmap *grf_regmap; 295 + struct reset_control *m_phy_rst; 296 + struct reset_control *s_phy_rst; 297 + struct reset_control *apb_rst; 298 + struct reset_control *grf_apb_rst; 299 + unsigned int lanes; 300 + struct phy *phy; 301 + u8 type; 302 + 303 + const struct samsung_mipi_dcphy_plat_data *pdata; 304 + struct { 305 + unsigned long long rate; 306 + u8 prediv; 307 + u16 fbdiv; 308 + long dsm; 309 + u8 scaler; 310 + 311 + bool ssc_en; 312 + u8 mfr; 313 + u8 mrr; 314 + } pll; 315 + }; 316 + 317 + struct samsung_mipi_dphy_timing { 318 + unsigned int max_lane_mbps; 319 + u8 clk_prepare; 320 + u8 clk_zero; 321 + u8 clk_post; 322 + u8 clk_trail_eot; 323 + u8 hs_prepare; 324 + u8 hs_zero; 325 + u8 hs_trail_eot; 326 + u8 lpx; 327 + u8 hs_exit; 328 + u8 hs_settle; 329 + }; 330 + 331 + /* 332 + * Timing values taken from rk3588 vendor kernel. 333 + * Not documented in hw documentation. 334 + */ 335 + static const 336 + struct samsung_mipi_dphy_timing samsung_mipi_dphy_timing_table[] = { 337 + {6500, 32, 117, 31, 28, 30, 56, 27, 24, 44, 37}, 338 + {6490, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 339 + {6480, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 340 + {6470, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 341 + {6460, 32, 116, 31, 28, 30, 56, 27, 24, 44, 37}, 342 + {6450, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37}, 343 + {6440, 32, 115, 31, 28, 30, 56, 27, 24, 44, 37}, 344 + {6430, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37}, 345 + {6420, 31, 116, 31, 28, 30, 55, 27, 24, 44, 37}, 346 + {6410, 31, 116, 31, 27, 30, 55, 27, 24, 44, 37}, 347 + {6400, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 348 + {6390, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 349 + {6380, 31, 115, 30, 27, 30, 55, 27, 23, 43, 36}, 350 + {6370, 31, 115, 30, 27, 30, 55, 26, 23, 43, 36}, 351 + {6360, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 352 + {6350, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 353 + {6340, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 354 + {6330, 31, 114, 30, 27, 30, 54, 26, 23, 43, 36}, 355 + {6320, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 356 + {6310, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 357 + {6300, 31, 113, 30, 27, 30, 54, 26, 23, 43, 36}, 358 + {6290, 31, 113, 30, 27, 29, 54, 26, 23, 43, 36}, 359 + {6280, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 360 + {6270, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 361 + {6260, 31, 112, 30, 27, 29, 54, 26, 23, 43, 36}, 362 + {6250, 31, 112, 30, 27, 29, 54, 26, 23, 42, 36}, 363 + {6240, 30, 113, 30, 27, 29, 54, 26, 23, 42, 36}, 364 + {6230, 30, 112, 30, 27, 29, 54, 26, 23, 42, 35}, 365 + {6220, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35}, 366 + {6210, 30, 112, 30, 27, 29, 53, 26, 23, 42, 35}, 367 + {6200, 30, 112, 29, 27, 29, 53, 26, 23, 42, 35}, 368 + {6190, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35}, 369 + {6180, 30, 111, 29, 27, 29, 53, 26, 23, 42, 35}, 370 + {6170, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35}, 371 + {6160, 30, 111, 29, 26, 29, 53, 26, 23, 42, 35}, 372 + {6150, 30, 110, 29, 26, 29, 53, 26, 23, 42, 35}, 373 + {6140, 30, 110, 29, 26, 29, 52, 26, 23, 42, 35}, 374 + {6130, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 375 + {6120, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 376 + {6110, 30, 110, 29, 26, 29, 52, 25, 22, 42, 35}, 377 + {6100, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35}, 378 + {6090, 30, 109, 29, 26, 29, 52, 25, 22, 41, 35}, 379 + {6080, 30, 109, 29, 26, 28, 53, 25, 22, 41, 35}, 380 + {6070, 30, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 381 + {6060, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 382 + {6050, 30, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 383 + {6040, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 384 + {6030, 29, 109, 29, 26, 28, 52, 25, 22, 41, 34}, 385 + {6020, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 386 + {6010, 29, 108, 29, 26, 28, 52, 25, 22, 41, 34}, 387 + {6000, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34}, 388 + {5990, 29, 108, 28, 26, 28, 51, 25, 22, 41, 34}, 389 + {5980, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34}, 390 + {5970, 29, 107, 28, 26, 28, 51, 25, 22, 41, 34}, 391 + {5960, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34}, 392 + {5950, 29, 107, 28, 26, 28, 51, 25, 22, 40, 34}, 393 + {5940, 29, 107, 28, 25, 28, 51, 25, 22, 40, 34}, 394 + {5930, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 395 + {5920, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 396 + {5910, 29, 106, 28, 25, 28, 50, 25, 22, 40, 34}, 397 + {5900, 29, 106, 28, 25, 28, 50, 24, 22, 40, 33}, 398 + {5890, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33}, 399 + {5880, 29, 105, 28, 25, 28, 50, 24, 22, 40, 33}, 400 + {5870, 29, 105, 28, 25, 27, 51, 24, 22, 40, 33}, 401 + {5860, 29, 105, 28, 25, 27, 51, 24, 21, 40, 33}, 402 + {5850, 29, 104, 28, 25, 27, 50, 24, 21, 40, 33}, 403 + {5840, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 404 + {5830, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 405 + {5820, 28, 105, 28, 25, 27, 50, 24, 21, 40, 33}, 406 + {5810, 28, 104, 28, 25, 27, 50, 24, 21, 39, 33}, 407 + {5800, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33}, 408 + {5790, 28, 104, 27, 25, 27, 50, 24, 21, 39, 33}, 409 + {5780, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33}, 410 + {5770, 28, 104, 27, 25, 27, 49, 24, 21, 39, 33}, 411 + {5760, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 412 + {5750, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 413 + {5740, 28, 103, 27, 25, 27, 49, 24, 21, 39, 33}, 414 + {5730, 28, 103, 27, 25, 27, 49, 24, 21, 39, 32}, 415 + {5720, 28, 102, 27, 25, 27, 49, 24, 21, 39, 32}, 416 + {5710, 28, 102, 27, 25, 27, 48, 24, 21, 39, 32}, 417 + {5700, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32}, 418 + {5690, 28, 102, 27, 24, 27, 48, 24, 21, 39, 32}, 419 + {5680, 28, 101, 27, 24, 27, 48, 24, 21, 39, 32}, 420 + {5670, 28, 101, 27, 24, 27, 48, 23, 21, 38, 32}, 421 + {5660, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32}, 422 + {5650, 28, 101, 27, 24, 26, 49, 23, 21, 38, 32}, 423 + {5640, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 424 + {5630, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 425 + {5620, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 426 + {5610, 27, 101, 27, 24, 26, 48, 23, 21, 38, 32}, 427 + {5600, 27, 101, 26, 24, 26, 48, 23, 20, 38, 32}, 428 + {5590, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32}, 429 + {5580, 27, 100, 26, 24, 26, 48, 23, 20, 38, 32}, 430 + {5570, 27, 100, 26, 24, 26, 48, 23, 20, 38, 31}, 431 + {5560, 27, 100, 26, 24, 26, 47, 23, 20, 38, 31}, 432 + {5550, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 433 + {5540, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 434 + {5530, 27, 99, 26, 24, 26, 47, 23, 20, 38, 31}, 435 + {5520, 27, 99, 26, 24, 26, 47, 23, 20, 37, 31}, 436 + {5510, 27, 98, 26, 24, 26, 47, 23, 20, 37, 31}, 437 + {5500, 27, 98, 26, 24, 26, 47, 23, 20, 37, 31}, 438 + {5490, 27, 98, 26, 24, 26, 46, 23, 20, 37, 31}, 439 + {5480, 27, 98, 26, 24, 26, 46, 23, 20, 37, 31}, 440 + {5470, 27, 97, 26, 23, 26, 46, 23, 20, 37, 31}, 441 + {5460, 27, 97, 26, 23, 26, 46, 23, 20, 37, 31}, 442 + {5450, 27, 97, 26, 23, 25, 47, 23, 20, 37, 31}, 443 + {5440, 26, 98, 26, 23, 25, 47, 23, 20, 37, 31}, 444 + {5430, 26, 98, 26, 23, 25, 47, 22, 20, 37, 31}, 445 + {5420, 26, 97, 26, 23, 25, 46, 22, 20, 37, 31}, 446 + {5410, 26, 97, 26, 23, 25, 46, 22, 20, 37, 31}, 447 + {5400, 26, 97, 25, 23, 25, 46, 22, 20, 37, 30}, 448 + {5390, 26, 97, 25, 23, 25, 46, 22, 20, 37, 30}, 449 + {5380, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 450 + {5370, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 451 + {5360, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 452 + {5350, 26, 96, 25, 23, 25, 46, 22, 20, 36, 30}, 453 + {5340, 26, 95, 25, 23, 25, 45, 22, 20, 36, 30}, 454 + {5330, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 455 + {5320, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 456 + {5310, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 457 + {5300, 26, 95, 25, 23, 25, 45, 22, 19, 36, 30}, 458 + {5290, 26, 94, 25, 23, 25, 45, 22, 19, 36, 30}, 459 + {5280, 26, 94, 25, 23, 25, 45, 22, 19, 36, 30}, 460 + {5270, 26, 94, 25, 23, 25, 44, 22, 19, 36, 30}, 461 + {5260, 26, 94, 25, 23, 25, 44, 22, 19, 36, 30}, 462 + {5250, 25, 94, 25, 23, 24, 45, 22, 19, 36, 30}, 463 + {5240, 25, 94, 25, 23, 24, 45, 22, 19, 36, 29}, 464 + {5230, 25, 94, 25, 22, 24, 45, 22, 19, 35, 29}, 465 + {5220, 25, 94, 25, 22, 24, 45, 22, 19, 35, 29}, 466 + {5210, 25, 93, 25, 22, 24, 45, 22, 19, 35, 29}, 467 + {5200, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 468 + {5190, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 469 + {5180, 25, 93, 24, 22, 24, 44, 21, 19, 35, 29}, 470 + {5170, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 471 + {5160, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 472 + {5150, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 473 + {5140, 25, 92, 24, 22, 24, 44, 21, 19, 35, 29}, 474 + {5130, 25, 92, 24, 22, 24, 43, 21, 19, 35, 29}, 475 + {5120, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 476 + {5110, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 477 + {5100, 25, 91, 24, 22, 24, 43, 21, 19, 35, 29}, 478 + {5090, 25, 91, 24, 22, 24, 43, 21, 19, 34, 29}, 479 + {5080, 25, 90, 24, 22, 24, 43, 21, 19, 34, 29}, 480 + {5070, 25, 90, 24, 22, 24, 43, 21, 19, 34, 28}, 481 + {5060, 25, 90, 24, 22, 24, 43, 21, 18, 34, 28}, 482 + {5050, 24, 91, 24, 22, 24, 42, 21, 18, 34, 28}, 483 + {5040, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 484 + {5030, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 485 + {5020, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 486 + {5010, 24, 90, 24, 22, 23, 43, 21, 18, 34, 28}, 487 + {5000, 24, 89, 23, 21, 23, 43, 21, 18, 34, 28}, 488 + {4990, 24, 89, 23, 21, 23, 43, 21, 18, 34, 28}, 489 + {4980, 24, 89, 23, 21, 23, 42, 21, 18, 34, 28}, 490 + {4970, 24, 89, 23, 21, 23, 42, 21, 18, 34, 28}, 491 + {4960, 24, 89, 23, 21, 23, 42, 20, 18, 34, 28}, 492 + {4950, 24, 88, 23, 21, 23, 42, 20, 18, 34, 28}, 493 + {4940, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 494 + {4930, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 495 + {4920, 24, 88, 23, 21, 23, 42, 20, 18, 33, 28}, 496 + {4910, 24, 87, 23, 21, 23, 41, 20, 18, 33, 28}, 497 + {4900, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 498 + {4890, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 499 + {4880, 24, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 500 + {4870, 24, 86, 23, 21, 23, 41, 20, 18, 33, 27}, 501 + {4860, 24, 86, 23, 21, 23, 41, 20, 18, 33, 27}, 502 + {4850, 23, 87, 23, 21, 23, 41, 20, 18, 33, 27}, 503 + {4840, 23, 87, 23, 21, 23, 40, 20, 18, 33, 27}, 504 + {4830, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 505 + {4820, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 506 + {4810, 23, 86, 23, 21, 22, 41, 20, 18, 33, 27}, 507 + {4800, 23, 86, 22, 21, 22, 41, 20, 17, 32, 27}, 508 + {4790, 23, 86, 22, 21, 22, 41, 20, 17, 32, 27}, 509 + {4780, 23, 85, 22, 21, 22, 41, 20, 17, 32, 27}, 510 + {4770, 23, 85, 22, 21, 22, 41, 20, 17, 32, 27}, 511 + {4760, 23, 85, 22, 20, 22, 40, 20, 17, 32, 27}, 512 + {4750, 23, 85, 22, 20, 22, 40, 20, 17, 32, 27}, 513 + {4740, 23, 84, 22, 20, 22, 40, 20, 17, 32, 26}, 514 + {4730, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 515 + {4720, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 516 + {4710, 23, 84, 22, 20, 22, 40, 19, 17, 32, 26}, 517 + {4700, 23, 83, 22, 20, 22, 40, 19, 17, 32, 26}, 518 + {4690, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 519 + {4680, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 520 + {4670, 23, 83, 22, 20, 22, 39, 19, 17, 32, 26}, 521 + {4660, 23, 82, 22, 20, 22, 39, 19, 17, 32, 26}, 522 + {4650, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 523 + {4640, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 524 + {4630, 22, 83, 22, 20, 22, 39, 19, 17, 31, 26}, 525 + {4620, 22, 83, 22, 20, 21, 39, 19, 17, 31, 26}, 526 + {4610, 22, 82, 22, 20, 21, 39, 19, 17, 31, 26}, 527 + {4600, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 528 + {4590, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 529 + {4580, 22, 82, 21, 20, 21, 39, 19, 17, 31, 26}, 530 + {4570, 22, 81, 21, 20, 21, 39, 19, 17, 31, 25}, 531 + {4560, 22, 81, 21, 20, 21, 39, 19, 17, 31, 25}, 532 + {4550, 22, 81, 21, 20, 21, 38, 19, 17, 31, 25}, 533 + {4540, 22, 81, 21, 20, 21, 38, 19, 17, 31, 25}, 534 + {4530, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 535 + {4520, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 536 + {4510, 22, 80, 21, 19, 21, 38, 19, 16, 31, 25}, 537 + {4500, 22, 80, 21, 19, 21, 38, 19, 16, 30, 25}, 538 + {4490, 22, 80, 21, 19, 21, 38, 18, 16, 30, 25}, 539 + {4480, 22, 79, 21, 19, 21, 38, 18, 16, 30, 25}, 540 + {4470, 22, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 541 + {4460, 22, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 542 + {4450, 21, 80, 21, 19, 21, 37, 18, 16, 30, 25}, 543 + {4440, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 544 + {4430, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 545 + {4420, 21, 79, 21, 19, 21, 37, 18, 16, 30, 25}, 546 + {4410, 21, 79, 21, 19, 20, 38, 18, 16, 30, 25}, 547 + {4400, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 548 + {4390, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 549 + {4380, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 550 + {4370, 21, 78, 20, 19, 20, 37, 18, 16, 30, 24}, 551 + {4360, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 552 + {4350, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 553 + {4340, 21, 77, 20, 19, 20, 37, 18, 16, 29, 24}, 554 + {4330, 21, 77, 20, 19, 20, 36, 18, 16, 29, 24}, 555 + {4320, 21, 77, 20, 19, 20, 36, 18, 16, 29, 24}, 556 + {4310, 21, 76, 20, 19, 20, 36, 18, 16, 29, 24}, 557 + {4300, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 558 + {4290, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 559 + {4280, 21, 76, 20, 18, 20, 36, 18, 16, 29, 24}, 560 + {4270, 21, 75, 20, 18, 20, 36, 18, 16, 29, 24}, 561 + {4260, 21, 75, 20, 18, 20, 35, 17, 15, 29, 24}, 562 + {4250, 20, 76, 20, 18, 20, 35, 17, 15, 29, 24}, 563 + {4240, 20, 76, 20, 18, 20, 35, 17, 15, 29, 23}, 564 + {4230, 20, 75, 20, 18, 20, 35, 17, 15, 29, 23}, 565 + {4220, 20, 75, 20, 18, 20, 35, 17, 15, 29, 23}, 566 + {4210, 20, 75, 20, 18, 20, 35, 17, 15, 28, 23}, 567 + {4200, 20, 75, 19, 18, 19, 36, 17, 15, 28, 23}, 568 + {4190, 20, 74, 19, 18, 19, 36, 17, 15, 28, 23}, 569 + {4180, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 570 + {4170, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 571 + {4160, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 572 + {4150, 20, 74, 19, 18, 19, 35, 17, 15, 28, 23}, 573 + {4140, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 574 + {4130, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 575 + {4120, 20, 73, 19, 18, 19, 35, 17, 15, 28, 23}, 576 + {4110, 20, 73, 19, 18, 19, 34, 17, 15, 28, 23}, 577 + {4100, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 578 + {4090, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 579 + {4080, 20, 72, 19, 18, 19, 34, 17, 15, 28, 23}, 580 + {4070, 20, 72, 19, 18, 19, 34, 17, 15, 27, 22}, 581 + {4060, 19, 72, 19, 17, 19, 34, 17, 15, 27, 22}, 582 + {4050, 19, 72, 19, 17, 19, 34, 17, 15, 27, 22}, 583 + {4040, 19, 72, 19, 17, 19, 33, 17, 15, 27, 22}, 584 + {4030, 19, 72, 19, 17, 19, 33, 17, 15, 27, 22}, 585 + {4020, 19, 71, 19, 17, 19, 33, 16, 15, 27, 22}, 586 + {4010, 19, 71, 19, 17, 19, 33, 16, 15, 27, 22}, 587 + {4000, 19, 71, 18, 17, 19, 33, 16, 14, 27, 22}, 588 + {3990, 19, 71, 18, 17, 18, 34, 16, 14, 27, 22}, 589 + {3980, 19, 71, 18, 17, 18, 34, 16, 14, 27, 22}, 590 + {3970, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 591 + {3960, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 592 + {3950, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 593 + {3940, 19, 70, 18, 17, 18, 33, 16, 14, 27, 22}, 594 + {3930, 19, 69, 18, 17, 18, 33, 16, 14, 27, 22}, 595 + {3920, 19, 69, 18, 17, 18, 33, 16, 14, 26, 22}, 596 + {3910, 19, 69, 18, 17, 18, 33, 16, 14, 26, 22}, 597 + {3900, 19, 69, 18, 17, 18, 33, 16, 14, 26, 21}, 598 + {3890, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 599 + {3880, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 600 + {3870, 19, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 601 + {3860, 18, 69, 18, 17, 18, 32, 16, 14, 26, 21}, 602 + {3850, 18, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 603 + {3840, 18, 68, 18, 17, 18, 32, 16, 14, 26, 21}, 604 + {3830, 18, 68, 18, 16, 18, 32, 16, 14, 26, 21}, 605 + {3820, 18, 68, 18, 16, 18, 31, 16, 14, 26, 21}, 606 + {3810, 18, 68, 18, 16, 18, 31, 16, 14, 26, 21}, 607 + {3800, 18, 67, 17, 16, 18, 31, 16, 14, 26, 21}, 608 + {3790, 18, 67, 17, 16, 17, 32, 15, 14, 26, 21}, 609 + {3780, 18, 67, 17, 16, 17, 32, 15, 14, 25, 21}, 610 + {3770, 18, 67, 17, 16, 17, 32, 15, 14, 25, 21}, 611 + {3760, 18, 66, 17, 16, 17, 32, 15, 14, 25, 21}, 612 + {3750, 18, 66, 17, 16, 17, 31, 15, 14, 25, 21}, 613 + {3740, 18, 66, 17, 16, 17, 31, 15, 14, 25, 20}, 614 + {3730, 18, 66, 17, 16, 17, 31, 15, 13, 25, 20}, 615 + {3720, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 616 + {3710, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 617 + {3700, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 618 + {3690, 18, 65, 17, 16, 17, 31, 15, 13, 25, 20}, 619 + {3680, 18, 64, 17, 16, 17, 31, 15, 13, 25, 20}, 620 + {3670, 18, 64, 17, 16, 17, 30, 15, 13, 25, 20}, 621 + {3660, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 622 + {3650, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 623 + {3640, 17, 65, 17, 16, 17, 30, 15, 13, 25, 20}, 624 + {3630, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 625 + {3620, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 626 + {3610, 17, 64, 17, 16, 17, 30, 15, 13, 24, 20}, 627 + {3600, 17, 64, 16, 16, 17, 29, 15, 13, 24, 20}, 628 + {3590, 17, 63, 16, 15, 17, 29, 15, 13, 24, 20}, 629 + {3580, 17, 63, 16, 15, 16, 30, 15, 13, 24, 20}, 630 + {3570, 17, 63, 16, 15, 16, 30, 15, 13, 24, 19}, 631 + {3560, 17, 63, 16, 15, 16, 30, 14, 13, 24, 19}, 632 + {3550, 17, 62, 16, 15, 16, 30, 14, 13, 24, 19}, 633 + {3540, 17, 62, 16, 15, 16, 30, 14, 13, 24, 19}, 634 + {3530, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 635 + {3520, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 636 + {3510, 17, 62, 16, 15, 16, 29, 14, 13, 24, 19}, 637 + {3500, 17, 61, 16, 15, 16, 29, 14, 13, 24, 19}, 638 + {3490, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 639 + {3480, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 640 + {3470, 17, 61, 16, 15, 16, 29, 14, 13, 23, 19}, 641 + {3460, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 642 + {3450, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 643 + {3440, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 644 + {3430, 16, 61, 16, 15, 16, 28, 14, 12, 23, 19}, 645 + {3420, 16, 60, 16, 15, 16, 28, 14, 12, 23, 19}, 646 + {3410, 16, 60, 16, 15, 16, 28, 14, 12, 23, 18}, 647 + {3400, 16, 60, 15, 15, 16, 28, 14, 12, 23, 18}, 648 + {3390, 16, 60, 15, 15, 16, 28, 14, 12, 23, 18}, 649 + {3380, 16, 59, 15, 15, 16, 27, 14, 12, 23, 18}, 650 + {3370, 16, 59, 15, 15, 15, 28, 14, 12, 23, 18}, 651 + {3360, 16, 59, 15, 14, 15, 28, 14, 12, 23, 18}, 652 + {3350, 16, 59, 15, 14, 15, 28, 14, 12, 23, 18}, 653 + {3340, 16, 59, 15, 14, 15, 28, 14, 12, 22, 18}, 654 + {3330, 16, 58, 15, 14, 15, 28, 14, 12, 22, 18}, 655 + {3320, 16, 58, 15, 14, 15, 28, 13, 12, 22, 18}, 656 + {3310, 16, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 657 + {3300, 16, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 658 + {3290, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 659 + {3280, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 660 + {3270, 16, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 661 + {3260, 15, 58, 15, 14, 15, 27, 13, 12, 22, 18}, 662 + {3250, 15, 57, 15, 14, 15, 27, 13, 12, 22, 18}, 663 + {3240, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 664 + {3230, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 665 + {3220, 15, 57, 15, 14, 15, 26, 13, 12, 22, 17}, 666 + {3210, 15, 56, 15, 14, 15, 26, 13, 12, 22, 17}, 667 + {3200, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 668 + {3190, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 669 + {3180, 15, 56, 14, 14, 15, 26, 13, 11, 21, 17}, 670 + {3170, 15, 56, 14, 14, 15, 25, 13, 11, 21, 17}, 671 + {3160, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 672 + {3150, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 673 + {3140, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 674 + {3130, 15, 55, 14, 14, 14, 26, 13, 11, 21, 17}, 675 + {3120, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 676 + {3110, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 677 + {3100, 15, 54, 14, 13, 14, 26, 13, 11, 21, 17}, 678 + {3090, 15, 54, 14, 13, 14, 25, 12, 11, 21, 17}, 679 + {3080, 15, 53, 14, 13, 14, 25, 12, 11, 21, 17}, 680 + {3070, 14, 54, 14, 13, 14, 25, 12, 11, 21, 16}, 681 + {3060, 14, 54, 14, 13, 14, 25, 12, 11, 21, 16}, 682 + {3050, 14, 54, 14, 13, 14, 25, 12, 11, 20, 16}, 683 + {3040, 14, 53, 14, 13, 14, 25, 12, 11, 20, 16}, 684 + {3030, 14, 53, 14, 13, 14, 25, 12, 11, 20, 16}, 685 + {3020, 14, 53, 14, 13, 14, 24, 12, 11, 20, 16}, 686 + {3010, 14, 53, 14, 13, 14, 24, 12, 11, 20, 16}, 687 + {3000, 14, 53, 13, 13, 14, 24, 12, 11, 20, 16}, 688 + {2990, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 689 + {2980, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 690 + {2970, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 691 + {2960, 14, 52, 13, 13, 14, 24, 12, 11, 20, 16}, 692 + {2950, 14, 51, 13, 13, 13, 24, 12, 11, 20, 16}, 693 + {2940, 14, 51, 13, 13, 13, 24, 12, 11, 20, 16}, 694 + {2930, 14, 51, 13, 13, 13, 24, 12, 10, 20, 16}, 695 + {2920, 14, 51, 13, 13, 13, 24, 12, 10, 20, 16}, 696 + {2910, 14, 50, 13, 13, 13, 24, 12, 10, 20, 15}, 697 + {2900, 14, 50, 13, 13, 13, 24, 12, 10, 19, 15}, 698 + {2890, 14, 50, 13, 12, 13, 24, 12, 10, 19, 15}, 699 + {2880, 14, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 700 + {2870, 13, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 701 + {2860, 13, 50, 13, 12, 13, 23, 12, 10, 19, 15}, 702 + {2850, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 703 + {2840, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 704 + {2830, 13, 50, 13, 12, 13, 23, 11, 10, 19, 15}, 705 + {2820, 13, 49, 13, 12, 13, 23, 11, 10, 19, 15}, 706 + {2810, 13, 49, 13, 12, 13, 23, 11, 10, 19, 15}, 707 + {2800, 13, 49, 12, 12, 13, 22, 11, 10, 19, 15}, 708 + {2790, 13, 49, 12, 12, 13, 22, 11, 10, 19, 15}, 709 + {2780, 13, 48, 12, 12, 13, 22, 11, 10, 19, 15}, 710 + {2770, 13, 48, 12, 12, 13, 22, 11, 10, 19, 15}, 711 + {2760, 13, 48, 12, 12, 13, 22, 11, 10, 18, 15}, 712 + {2750, 13, 48, 12, 12, 13, 22, 11, 10, 18, 15}, 713 + {2740, 13, 47, 12, 12, 12, 23, 11, 10, 18, 14}, 714 + {2730, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 715 + {2720, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 716 + {2710, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 717 + {2700, 13, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 718 + {2690, 13, 46, 12, 12, 12, 22, 11, 10, 18, 14}, 719 + {2680, 13, 46, 12, 12, 12, 22, 11, 10, 18, 14}, 720 + {2670, 12, 47, 12, 12, 12, 22, 11, 10, 18, 14}, 721 + {2660, 12, 47, 12, 12, 12, 21, 11, 9, 18, 14}, 722 + {2650, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 723 + {2640, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 724 + {2630, 12, 46, 12, 11, 12, 21, 11, 9, 18, 14}, 725 + {2620, 12, 46, 12, 11, 12, 21, 10, 9, 18, 14}, 726 + {2610, 12, 45, 12, 11, 12, 21, 10, 9, 17, 14}, 727 + {2600, 12, 45, 11, 11, 12, 21, 10, 9, 17, 14}, 728 + {2590, 12, 45, 11, 11, 12, 20, 10, 9, 17, 14}, 729 + {2580, 12, 45, 11, 11, 12, 20, 10, 9, 17, 14}, 730 + {2570, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 731 + {2560, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 732 + {2550, 12, 44, 11, 11, 12, 20, 10, 9, 17, 13}, 733 + {2540, 12, 44, 11, 11, 11, 21, 10, 9, 17, 13}, 734 + {2530, 12, 44, 11, 11, 11, 21, 10, 9, 17, 13}, 735 + {2520, 12, 43, 11, 11, 11, 21, 10, 9, 17, 13}, 736 + {2510, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 737 + {2500, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 738 + {2490, 12, 43, 11, 11, 11, 20, 10, 9, 17, 13}, 739 + {2480, 12, 42, 11, 11, 11, 20, 10, 9, 17, 13}, 740 + {2470, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 741 + {2460, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 742 + {2450, 11, 43, 11, 11, 11, 20, 10, 9, 16, 13}, 743 + {2440, 11, 42, 11, 11, 11, 19, 10, 9, 16, 13}, 744 + {2430, 11, 42, 11, 11, 11, 19, 10, 9, 16, 13}, 745 + {2420, 11, 42, 11, 10, 11, 19, 10, 9, 16, 13}, 746 + {2410, 11, 42, 11, 10, 11, 19, 10, 9, 16, 12}, 747 + {2400, 11, 41, 10, 10, 11, 19, 10, 8, 16, 12}, 748 + {2390, 11, 41, 10, 10, 11, 19, 10, 8, 16, 12}, 749 + {2380, 11, 41, 10, 10, 11, 19, 9, 8, 16, 12}, 750 + {2370, 11, 41, 10, 10, 11, 18, 9, 8, 16, 12}, 751 + {2360, 11, 41, 10, 10, 11, 18, 9, 8, 16, 12}, 752 + {2350, 11, 40, 10, 10, 11, 18, 9, 8, 16, 12}, 753 + {2340, 11, 40, 10, 10, 11, 18, 9, 8, 16, 12}, 754 + {2330, 11, 40, 10, 10, 10, 19, 9, 8, 16, 12}, 755 + {2320, 11, 40, 10, 10, 10, 19, 9, 8, 15, 12}, 756 + {2310, 11, 39, 10, 10, 10, 19, 9, 8, 15, 12}, 757 + {2300, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 758 + {2290, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 759 + {2280, 11, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 760 + {2270, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 761 + {2260, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 762 + {2250, 10, 39, 10, 10, 10, 18, 9, 8, 15, 12}, 763 + {2240, 10, 39, 10, 10, 10, 18, 9, 8, 15, 11}, 764 + {2230, 10, 38, 10, 10, 10, 18, 9, 8, 15, 11}, 765 + {2220, 10, 38, 10, 10, 10, 17, 9, 8, 15, 11}, 766 + {2210, 10, 38, 10, 10, 10, 17, 9, 8, 15, 11}, 767 + {2200, 10, 38, 9, 10, 10, 17, 9, 8, 15, 11}, 768 + {2190, 10, 38, 9, 9, 10, 17, 9, 8, 15, 11}, 769 + {2180, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 770 + {2170, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 771 + {2160, 10, 37, 9, 9, 10, 17, 9, 8, 14, 11}, 772 + {2150, 10, 37, 9, 9, 10, 16, 8, 8, 14, 11}, 773 + {2140, 10, 36, 9, 9, 10, 16, 8, 8, 14, 11}, 774 + {2130, 10, 36, 9, 9, 10, 16, 8, 7, 14, 11}, 775 + {2120, 10, 36, 9, 9, 9, 17, 8, 7, 14, 11}, 776 + {2110, 10, 36, 9, 9, 9, 17, 8, 7, 14, 11}, 777 + {2100, 10, 35, 9, 9, 9, 17, 8, 7, 14, 11}, 778 + {2090, 10, 35, 9, 9, 9, 17, 8, 7, 14, 11}, 779 + {2080, 9, 36, 9, 9, 9, 16, 8, 7, 14, 11}, 780 + {2070, 9, 36, 9, 9, 9, 16, 8, 7, 14, 10}, 781 + {2060, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 782 + {2050, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 783 + {2040, 9, 35, 9, 9, 9, 16, 8, 7, 14, 10}, 784 + {2030, 9, 35, 9, 9, 9, 16, 8, 7, 13, 10}, 785 + {2020, 9, 35, 9, 9, 9, 16, 8, 7, 13, 10}, 786 + {2010, 9, 34, 9, 9, 9, 15, 8, 7, 13, 10}, 787 + {2000, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 788 + {1990, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 789 + {1980, 9, 34, 8, 9, 9, 15, 8, 7, 13, 10}, 790 + {1970, 9, 33, 8, 9, 9, 15, 8, 7, 13, 10}, 791 + {1960, 9, 33, 8, 9, 9, 15, 8, 7, 13, 10}, 792 + {1950, 9, 33, 8, 8, 9, 15, 8, 7, 13, 10}, 793 + {1940, 9, 33, 8, 8, 9, 15, 8, 7, 13, 10}, 794 + {1930, 9, 32, 8, 8, 9, 14, 8, 7, 13, 10}, 795 + {1920, 9, 32, 8, 8, 9, 14, 8, 7, 13, 10}, 796 + {1910, 9, 32, 8, 8, 8, 15, 7, 7, 13, 9}, 797 + {1900, 9, 32, 8, 8, 8, 15, 7, 7, 13, 9}, 798 + {1890, 9, 31, 8, 8, 8, 15, 7, 7, 12, 9}, 799 + {1880, 8, 32, 8, 8, 8, 15, 7, 7, 12, 9}, 800 + {1870, 8, 32, 8, 8, 8, 15, 7, 7, 12, 9}, 801 + {1860, 8, 32, 8, 8, 8, 14, 7, 6, 12, 9}, 802 + {1850, 8, 32, 8, 8, 8, 14, 7, 6, 12, 9}, 803 + {1840, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 804 + {1830, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 805 + {1820, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 806 + {1810, 8, 31, 8, 8, 8, 14, 7, 6, 12, 9}, 807 + {1800, 8, 30, 7, 8, 8, 14, 7, 6, 12, 9}, 808 + {1790, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 809 + {1780, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 810 + {1770, 8, 30, 7, 8, 8, 13, 7, 6, 12, 9}, 811 + {1760, 8, 29, 7, 8, 8, 13, 7, 6, 12, 9}, 812 + {1750, 8, 29, 7, 8, 8, 13, 7, 6, 12, 9}, 813 + {1740, 8, 29, 7, 8, 8, 13, 7, 6, 11, 8}, 814 + {1730, 8, 29, 7, 8, 8, 13, 7, 6, 11, 8}, 815 + {1720, 8, 29, 7, 7, 8, 13, 7, 6, 11, 8}, 816 + {1710, 8, 28, 7, 7, 8, 12, 7, 6, 11, 8}, 817 + {1700, 8, 28, 7, 7, 7, 13, 7, 6, 11, 8}, 818 + {1690, 8, 28, 7, 7, 7, 13, 7, 6, 11, 8}, 819 + {1680, 7, 29, 7, 7, 7, 13, 6, 6, 11, 8}, 820 + {1670, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 821 + {1660, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 822 + {1650, 7, 28, 7, 7, 7, 13, 6, 6, 11, 8}, 823 + {1640, 7, 28, 7, 7, 7, 12, 6, 6, 11, 8}, 824 + {1630, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 825 + {1620, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 826 + {1610, 7, 27, 7, 7, 7, 12, 6, 6, 11, 8}, 827 + {1600, 7, 27, 6, 7, 7, 12, 6, 5, 10, 8}, 828 + {1590, 7, 26, 6, 7, 7, 12, 6, 5, 10, 8}, 829 + {1580, 7, 26, 6, 7, 7, 12, 6, 5, 10, 7}, 830 + {1570, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 831 + {1560, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 832 + {1550, 7, 26, 6, 7, 7, 11, 6, 5, 10, 7}, 833 + {1540, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 834 + {1530, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 835 + {1520, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 836 + {1510, 7, 25, 6, 7, 7, 11, 6, 5, 10, 7}, 837 + {1500, 7, 24, 6, 7, 7, 10, 6, 5, 10, 7}, 838 + {1490, 59, 25, 6, 77, 59, 10, 70, 44, 9, 73}, 839 + {1480, 59, 24, 6, 76, 58, 10, 70, 44, 9, 73}, 840 + {1470, 58, 24, 6, 76, 58, 10, 69, 44, 9, 72}, 841 + {1460, 58, 24, 6, 76, 58, 10, 69, 43, 9, 72}, 842 + {1450, 58, 24, 6, 75, 57, 10, 68, 43, 9, 71}, 843 + {1440, 57, 24, 6, 75, 57, 10, 68, 43, 9, 71}, 844 + {1430, 57, 23, 6, 75, 57, 10, 68, 43, 8, 70}, 845 + {1420, 56, 23, 6, 74, 57, 9, 67, 43, 8, 70}, 846 + {1410, 56, 23, 6, 74, 57, 9, 67, 43, 8, 69}, 847 + {1400, 56, 23, 5, 74, 55, 9, 67, 41, 8, 69}, 848 + {1390, 55, 23, 5, 73, 55, 9, 66, 41, 8, 68}, 849 + {1380, 55, 23, 5, 73, 54, 9, 66, 41, 8, 68}, 850 + {1370, 54, 22, 5, 72, 54, 9, 66, 41, 8, 67}, 851 + {1360, 54, 22, 5, 72, 54, 9, 65, 40, 8, 67}, 852 + {1350, 54, 22, 5, 72, 53, 9, 65, 40, 8, 66}, 853 + {1340, 53, 22, 5, 71, 53, 9, 65, 40, 8, 66}, 854 + {1330, 53, 22, 5, 71, 53, 9, 64, 39, 8, 65}, 855 + {1320, 52, 22, 5, 71, 53, 8, 64, 40, 8, 65}, 856 + {1310, 52, 21, 5, 70, 53, 8, 64, 40, 8, 64}, 857 + {1300, 51, 21, 5, 70, 51, 8, 63, 38, 8, 64}, 858 + {1290, 51, 21, 5, 70, 51, 8, 63, 38, 7, 64}, 859 + {1280, 51, 21, 5, 69, 51, 8, 63, 38, 7, 63}, 860 + {1270, 50, 21, 5, 69, 50, 8, 62, 38, 7, 63}, 861 + {1260, 50, 20, 5, 69, 50, 8, 62, 37, 7, 62}, 862 + {1250, 49, 20, 5, 68, 49, 8, 62, 37, 7, 62}, 863 + {1240, 49, 20, 5, 68, 49, 8, 61, 37, 7, 61}, 864 + {1230, 49, 20, 5, 68, 49, 8, 61, 36, 7, 61}, 865 + {1220, 48, 20, 5, 67, 48, 8, 61, 36, 7, 60}, 866 + {1210, 48, 19, 5, 67, 48, 7, 60, 36, 7, 60}, 867 + {1200, 49, 19, 4, 67, 49, 7, 60, 36, 7, 59}, 868 + {1190, 48, 19, 4, 66, 48, 7, 60, 36, 7, 59}, 869 + {1180, 48, 19, 4, 66, 48, 7, 59, 36, 7, 58}, 870 + {1170, 46, 19, 4, 66, 46, 7, 59, 35, 7, 58}, 871 + {1160, 46, 18, 4, 65, 46, 7, 59, 34, 7, 57}, 872 + {1150, 45, 18, 4, 65, 46, 7, 58, 34, 7, 57}, 873 + {1140, 45, 18, 4, 65, 45, 7, 58, 34, 6, 56}, 874 + {1130, 45, 18, 4, 64, 45, 7, 58, 33, 6, 56}, 875 + {1120, 44, 18, 4, 64, 44, 7, 57, 33, 6, 55}, 876 + {1110, 44, 18, 4, 64, 44, 7, 57, 33, 6, 55}, 877 + {1100, 43, 17, 4, 63, 44, 6, 57, 32, 6, 54}, 878 + {1090, 43, 17, 4, 63, 44, 6, 56, 33, 6, 54}, 879 + {1080, 43, 17, 4, 63, 44, 6, 56, 33, 6, 53}, 880 + {1070, 42, 17, 4, 62, 44, 6, 56, 33, 6, 53}, 881 + {1060, 42, 17, 4, 62, 42, 6, 55, 31, 6, 52}, 882 + {1050, 41, 17, 4, 62, 42, 6, 55, 31, 6, 52}, 883 + {1040, 41, 16, 4, 61, 41, 6, 54, 31, 6, 52}, 884 + {1030, 41, 16, 4, 61, 41, 6, 54, 30, 6, 51}, 885 + {1020, 40, 16, 4, 61, 41, 6, 54, 30, 6, 51}, 886 + {1010, 40, 16, 4, 60, 40, 6, 53, 30, 6, 50}, 887 + {1000, 39, 16, 3, 60, 40, 6, 53, 29, 5, 50}, 888 + { 990, 39, 15, 3, 60, 39, 6, 53, 29, 5, 49}, 889 + { 980, 39, 15, 3, 59, 39, 5, 52, 29, 5, 49}, 890 + { 970, 38, 15, 3, 59, 39, 5, 52, 29, 5, 48}, 891 + { 960, 38, 15, 3, 59, 39, 5, 52, 29, 5, 48}, 892 + { 950, 37, 15, 3, 58, 39, 5, 51, 29, 5, 47}, 893 + { 940, 37, 14, 3, 58, 39, 5, 51, 29, 5, 47}, 894 + { 930, 37, 14, 3, 57, 37, 5, 51, 27, 5, 46}, 895 + { 920, 36, 14, 3, 57, 37, 5, 50, 27, 5, 46}, 896 + { 910, 36, 14, 3, 57, 36, 5, 50, 27, 5, 45}, 897 + { 900, 35, 14, 3, 56, 36, 5, 50, 26, 5, 45}, 898 + { 890, 35, 14, 3, 56, 36, 5, 49, 26, 5, 44}, 899 + { 880, 35, 13, 3, 56, 35, 5, 49, 26, 5, 44}, 900 + { 870, 34, 13, 3, 55, 35, 4, 49, 26, 5, 43}, 901 + { 860, 34, 13, 3, 55, 35, 4, 48, 25, 5, 43}, 902 + { 850, 33, 13, 3, 55, 35, 4, 48, 26, 4, 42}, 903 + { 840, 33, 13, 3, 54, 35, 4, 48, 26, 4, 42}, 904 + { 830, 33, 12, 3, 54, 33, 4, 47, 24, 4, 41}, 905 + { 820, 32, 12, 3, 54, 33, 4, 47, 24, 4, 41}, 906 + { 810, 32, 12, 3, 53, 33, 4, 47, 24, 4, 40}, 907 + { 800, 31, 12, 2, 53, 32, 4, 46, 23, 4, 40}, 908 + { 790, 31, 12, 2, 53, 32, 4, 46, 23, 4, 39}, 909 + { 780, 30, 12, 2, 52, 31, 4, 46, 23, 4, 39}, 910 + { 770, 30, 11, 2, 52, 31, 4, 45, 23, 4, 39}, 911 + { 760, 30, 11, 2, 52, 31, 3, 45, 22, 4, 38}, 912 + { 750, 29, 11, 2, 51, 30, 3, 45, 22, 4, 38}, 913 + { 740, 29, 11, 2, 51, 30, 3, 44, 22, 4, 37}, 914 + { 730, 28, 11, 2, 51, 31, 3, 44, 22, 4, 37}, 915 + { 720, 28, 10, 2, 50, 30, 3, 44, 22, 4, 36}, 916 + { 710, 28, 10, 2, 50, 30, 3, 43, 22, 4, 36}, 917 + { 700, 27, 10, 2, 50, 28, 3, 43, 20, 3, 35}, 918 + { 690, 27, 10, 2, 49, 28, 3, 43, 20, 3, 35}, 919 + { 680, 26, 10, 2, 49, 28, 3, 42, 20, 3, 34}, 920 + { 670, 26, 10, 2, 49, 27, 3, 42, 20, 3, 34}, 921 + { 660, 26, 9, 2, 48, 27, 3, 42, 19, 3, 33}, 922 + { 650, 25, 9, 2, 48, 26, 3, 41, 19, 3, 33}, 923 + { 640, 25, 9, 2, 48, 26, 2, 41, 19, 3, 32}, 924 + { 630, 24, 9, 2, 47, 26, 2, 40, 18, 3, 32}, 925 + { 620, 24, 9, 2, 47, 26, 2, 40, 19, 3, 31}, 926 + { 610, 24, 8, 2, 47, 26, 2, 40, 19, 3, 31}, 927 + { 600, 23, 8, 1, 46, 26, 2, 39, 18, 3, 30}, 928 + { 590, 23, 8, 1, 46, 24, 2, 39, 17, 3, 30}, 929 + { 580, 22, 8, 1, 46, 24, 2, 39, 17, 3, 29}, 930 + { 570, 22, 8, 1, 45, 23, 2, 38, 17, 3, 29}, 931 + { 560, 22, 7, 1, 45, 23, 2, 38, 16, 2, 28}, 932 + { 550, 21, 7, 1, 45, 23, 2, 38, 16, 2, 28}, 933 + { 540, 21, 7, 1, 44, 22, 2, 37, 16, 2, 27}, 934 + { 530, 20, 7, 1, 44, 22, 1, 37, 15, 2, 27}, 935 + { 520, 20, 7, 1, 43, 21, 1, 37, 15, 2, 27}, 936 + { 510, 20, 6, 1, 43, 21, 1, 36, 15, 2, 26}, 937 + { 500, 19, 6, 1, 43, 22, 1, 36, 15, 2, 26}, 938 + { 490, 19, 6, 1, 42, 21, 1, 36, 15, 2, 25}, 939 + { 480, 18, 6, 1, 42, 21, 1, 35, 15, 2, 25}, 940 + { 470, 18, 6, 1, 42, 21, 1, 35, 15, 2, 24}, 941 + { 460, 18, 6, 1, 41, 19, 1, 35, 13, 2, 24}, 942 + { 450, 17, 5, 1, 41, 19, 1, 34, 13, 2, 23}, 943 + { 440, 17, 5, 1, 41, 18, 1, 34, 13, 2, 23}, 944 + { 430, 16, 5, 1, 40, 18, 0, 34, 12, 2, 22}, 945 + { 420, 16, 5, 1, 40, 18, 0, 33, 12, 2, 22}, 946 + { 410, 16, 5, 1, 40, 17, 0, 33, 12, 1, 21}, 947 + { 400, 15, 5, 0, 39, 17, 0, 33, 11, 1, 21}, 948 + { 390, 15, 4, 0, 39, 17, 0, 32, 12, 1, 20}, 949 + { 380, 14, 4, 0, 39, 17, 0, 32, 12, 1, 20}, 950 + { 370, 14, 4, 0, 38, 17, 0, 32, 12, 1, 19}, 951 + { 360, 14, 4, 0, 38, 15, 0, 31, 10, 1, 19}, 952 + { 350, 13, 4, 0, 38, 15, 0, 31, 10, 1, 18}, 953 + { 340, 13, 3, 0, 37, 15, 0, 31, 10, 1, 18}, 954 + { 330, 12, 3, 0, 37, 14, 0, 30, 9, 1, 17}, 955 + { 320, 12, 3, 0, 37, 14, 0, 30, 9, 1, 17}, 956 + { 310, 12, 3, 0, 36, 13, 0, 30, 9, 1, 16}, 957 + { 300, 11, 3, 0, 36, 13, 0, 29, 8, 1, 16}, 958 + { 290, 11, 2, 0, 36, 13, 0, 29, 8, 1, 15}, 959 + { 280, 10, 2, 0, 35, 12, 0, 29, 8, 1, 15}, 960 + { 270, 10, 2, 0, 35, 12, 0, 28, 8, 0, 14}, 961 + { 260, 9, 2, 0, 35, 12, 0, 28, 8, 0, 14}, 962 + { 250, 9, 2, 0, 34, 12, 0, 28, 8, 0, 14}, 963 + { 240, 9, 2, 0, 34, 12, 0, 27, 8, 0, 13}, 964 + { 230, 8, 1, 0, 34, 10, 0, 27, 6, 0, 13}, 965 + { 220, 8, 1, 0, 33, 10, 0, 27, 6, 0, 12}, 966 + { 210, 7, 1, 0, 33, 10, 0, 26, 6, 0, 12}, 967 + { 200, 7, 1, 0, 33, 9, 0, 26, 5, 0, 11}, 968 + { 190, 7, 1, 0, 32, 9, 0, 25, 5, 0, 11}, 969 + { 180, 6, 1, 0, 32, 8, 0, 25, 5, 0, 10}, 970 + { 170, 6, 0, 0, 32, 8, 0, 25, 5, 0, 10}, 971 + { 160, 5, 0, 0, 31, 8, 0, 24, 4, 0, 9}, 972 + { 150, 5, 0, 0, 31, 8, 0, 24, 5, 0, 9}, 973 + { 140, 5, 0, 0, 31, 8, 0, 24, 5, 0, 8}, 974 + { 130, 4, 0, 0, 30, 6, 0, 23, 3, 0, 8}, 975 + { 120, 4, 0, 0, 30, 6, 0, 23, 3, 0, 7}, 976 + { 110, 3, 0, 0, 30, 6, 0, 23, 3, 0, 7}, 977 + { 100, 3, 0, 0, 29, 5, 0, 22, 2, 0, 6}, 978 + { 90, 3, 0, 0, 29, 5, 0, 22, 2, 0, 6}, 979 + { 80, 2, 0, 0, 28, 5, 0, 22, 2, 0, 5}, 980 + }; 981 + 982 + static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung) 983 + { 984 + regmap_write(samsung->regmap, BIAS_CON0, I_DEV_DIV_6 | I_RES_100_2UA); 985 + regmap_write(samsung->regmap, BIAS_CON1, I_VBG_SEL_820MV | I_BGR_VREF_820MV | 986 + I_LADDER_1_00V); 987 + regmap_write(samsung->regmap, BIAS_CON2, REG_325M_325MV | REG_LP_400M_400MV | 988 + REG_400M_400MV | REG_645M_645MV); 989 + 990 + /* default output voltage select: 991 + * dphy: 400mv 992 + * cphy: 530mv 993 + */ 994 + regmap_update_bits(samsung->regmap, BIAS_CON4, 995 + I_MUX_SEL_MASK, I_MUX_400MV); 996 + } 997 + 998 + static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung) 999 + { 1000 + regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0x2000)); 1001 + regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, 1002 + PHY_ENABLE, PHY_ENABLE); 1003 + 1004 + switch (samsung->lanes) { 1005 + case 4: 1006 + regmap_write(samsung->regmap, DPHY_MD3_GNR_CON1, 1007 + T_PHY_READY(0x2000)); 1008 + regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0, 1009 + PHY_ENABLE, PHY_ENABLE); 1010 + fallthrough; 1011 + case 3: 1012 + regmap_write(samsung->regmap, COMBO_MD2_GNR_CON1, 1013 + T_PHY_READY(0x2000)); 1014 + regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0, 1015 + PHY_ENABLE, PHY_ENABLE); 1016 + fallthrough; 1017 + case 2: 1018 + regmap_write(samsung->regmap, COMBO_MD1_GNR_CON1, 1019 + T_PHY_READY(0x2000)); 1020 + regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0, 1021 + PHY_ENABLE, PHY_ENABLE); 1022 + fallthrough; 1023 + case 1: 1024 + default: 1025 + regmap_write(samsung->regmap, COMBO_MD0_GNR_CON1, 1026 + T_PHY_READY(0x2000)); 1027 + regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0, 1028 + PHY_ENABLE, PHY_ENABLE); 1029 + break; 1030 + } 1031 + } 1032 + 1033 + static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung) 1034 + { 1035 + switch (samsung->lanes) { 1036 + case 4: 1037 + regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0, 1038 + PHY_ENABLE, 0); 1039 + fallthrough; 1040 + case 3: 1041 + regmap_update_bits(samsung->regmap, COMBO_MD2_GNR_CON0, 1042 + PHY_ENABLE, 0); 1043 + fallthrough; 1044 + case 2: 1045 + regmap_update_bits(samsung->regmap, COMBO_MD1_GNR_CON0, 1046 + PHY_ENABLE, 0); 1047 + fallthrough; 1048 + case 1: 1049 + default: 1050 + regmap_update_bits(samsung->regmap, COMBO_MD0_GNR_CON0, 1051 + PHY_ENABLE, 0); 1052 + break; 1053 + } 1054 + 1055 + regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0, PHY_ENABLE, 0); 1056 + } 1057 + 1058 + static void samsung_mipi_dcphy_pll_configure(struct samsung_mipi_dcphy *samsung) 1059 + { 1060 + regmap_update_bits(samsung->regmap, PLL_CON0, S_MASK | P_MASK, 1061 + S(samsung->pll.scaler) | P(samsung->pll.prediv)); 1062 + 1063 + if (samsung->pll.dsm < 0) { 1064 + u16 dsm_tmp; 1065 + 1066 + /* Using opposite number subtraction to find complement */ 1067 + dsm_tmp = abs(samsung->pll.dsm); 1068 + dsm_tmp = dsm_tmp - 1; 1069 + dsm_tmp ^= 0xffff; 1070 + regmap_write(samsung->regmap, PLL_CON1, dsm_tmp); 1071 + } else { 1072 + regmap_write(samsung->regmap, PLL_CON1, samsung->pll.dsm); 1073 + } 1074 + 1075 + regmap_update_bits(samsung->regmap, PLL_CON2, 1076 + M_MASK, M(samsung->pll.fbdiv)); 1077 + 1078 + if (samsung->pll.ssc_en) { 1079 + regmap_write(samsung->regmap, PLL_CON3, 1080 + MRR(samsung->pll.mrr) | MFR(samsung->pll.mfr)); 1081 + regmap_update_bits(samsung->regmap, PLL_CON4, SSCG_EN, SSCG_EN); 1082 + } 1083 + 1084 + regmap_write(samsung->regmap, PLL_CON5, RESET_N_SEL | PLL_ENABLE_SEL); 1085 + regmap_write(samsung->regmap, PLL_CON7, PLL_LOCK_CNT(0xf000)); 1086 + regmap_write(samsung->regmap, PLL_CON8, PLL_STB_CNT(0xf000)); 1087 + } 1088 + 1089 + static int samsung_mipi_dcphy_pll_enable(struct samsung_mipi_dcphy *samsung) 1090 + { 1091 + u32 sts; 1092 + int ret; 1093 + 1094 + regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, PLL_EN); 1095 + 1096 + ret = regmap_read_poll_timeout(samsung->regmap, PLL_STAT0, 1097 + sts, (sts & PLL_LOCK), 1000, 20000); 1098 + if (ret < 0) 1099 + dev_err(samsung->dev, "DC-PHY pll failed to lock\n"); 1100 + 1101 + return ret; 1102 + } 1103 + 1104 + static void samsung_mipi_dcphy_pll_disable(struct samsung_mipi_dcphy *samsung) 1105 + { 1106 + regmap_update_bits(samsung->regmap, PLL_CON0, PLL_EN, 0); 1107 + } 1108 + 1109 + static const struct samsung_mipi_dphy_timing * 1110 + samsung_mipi_dphy_get_timing(struct samsung_mipi_dcphy *samsung) 1111 + { 1112 + const struct samsung_mipi_dphy_timing *timings; 1113 + unsigned int num_timings; 1114 + unsigned int lane_mbps = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1115 + unsigned int i; 1116 + 1117 + timings = samsung_mipi_dphy_timing_table; 1118 + num_timings = ARRAY_SIZE(samsung_mipi_dphy_timing_table); 1119 + 1120 + for (i = num_timings; i > 1; i--) 1121 + if (lane_mbps <= timings[i - 1].max_lane_mbps) 1122 + break; 1123 + 1124 + return &timings[i - 1]; 1125 + } 1126 + 1127 + static unsigned long 1128 + samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung, 1129 + unsigned long prate, unsigned long rate, 1130 + u8 *prediv, u16 *fbdiv, int *dsm, u8 *scaler) 1131 + { 1132 + u32 max_fout = samsung->pdata->dphy_tx_max_lane_kbps; 1133 + u64 best_freq = 0; 1134 + u64 fin, fvco, fout; 1135 + u8 min_prediv, max_prediv; 1136 + u8 _prediv, best_prediv = 1; 1137 + u16 _fbdiv, best_fbdiv = 1; 1138 + u8 _scaler, best_scaler = 0; 1139 + u32 min_delta = UINT_MAX; 1140 + long _dsm, best_dsm = 0; 1141 + 1142 + if (!prate) { 1143 + dev_err(samsung->dev, "parent rate of PLL can not be zero\n"); 1144 + return 0; 1145 + } 1146 + 1147 + /* 1148 + * The PLL output frequency can be calculated using a simple formula: 1149 + * Fvco = ((m+k/65536) x 2 x Fin) / p 1150 + * Fout = ((m+k/65536) x 2 x Fin) / (p x 2^s) 1151 + */ 1152 + fin = div64_ul(prate, MSEC_PER_SEC); 1153 + 1154 + while (!best_freq) { 1155 + fout = div64_ul(rate, MSEC_PER_SEC); 1156 + if (fout > max_fout) 1157 + fout = max_fout; 1158 + 1159 + /* 0 ≤ S[2:0] ≤ 6 */ 1160 + for (_scaler = 0; _scaler < 7; _scaler++) { 1161 + fvco = fout << _scaler; 1162 + 1163 + /* 1164 + * 2600MHz ≤ FVCO ≤ 6600MHz 1165 + */ 1166 + if (fvco < 2600 * MSEC_PER_SEC || fvco > 6600 * MSEC_PER_SEC) 1167 + continue; 1168 + 1169 + /* 6MHz ≤ Fref(Fin / p) ≤ 30MHz */ 1170 + min_prediv = DIV_ROUND_UP_ULL(fin, 30 * MSEC_PER_SEC); 1171 + max_prediv = DIV_ROUND_CLOSEST_ULL(fin, 6 * MSEC_PER_SEC); 1172 + 1173 + for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) { 1174 + u64 delta, tmp; 1175 + 1176 + _fbdiv = DIV_ROUND_CLOSEST_ULL(fvco * _prediv, 2 * fin); 1177 + 1178 + /* 64 ≤ M[9:0] ≤ 1023 */ 1179 + if (_fbdiv < 64 || _fbdiv > 1023) 1180 + continue; 1181 + 1182 + /* -32767 ≤ K[15:0] ≤ 32767 */ 1183 + _dsm = ((_prediv * fvco) - (2 * _fbdiv * fin)); 1184 + _dsm = DIV_ROUND_UP_ULL(_dsm << 15, fin); 1185 + if (abs(_dsm) > 32767) 1186 + continue; 1187 + 1188 + tmp = DIV_ROUND_CLOSEST_ULL((_fbdiv * fin * 2 * 1000), _prediv); 1189 + tmp += DIV_ROUND_CLOSEST_ULL((_dsm * fin * 1000), _prediv << 15); 1190 + 1191 + delta = abs(fvco * MSEC_PER_SEC - tmp); 1192 + if (delta < min_delta) { 1193 + best_prediv = _prediv; 1194 + best_fbdiv = _fbdiv; 1195 + best_dsm = _dsm; 1196 + best_scaler = _scaler; 1197 + min_delta = delta; 1198 + best_freq = DIV_ROUND_CLOSEST_ULL(tmp, 1000) * MSEC_PER_SEC; 1199 + } 1200 + } 1201 + } 1202 + 1203 + rate += 100 * MSEC_PER_SEC; 1204 + } 1205 + 1206 + *prediv = best_prediv; 1207 + *fbdiv = best_fbdiv; 1208 + *dsm = (int)best_dsm & 0xffff; 1209 + *scaler = best_scaler; 1210 + dev_dbg(samsung->dev, "p: %d, m: %d, dsm:%ld, scaler: %d\n", 1211 + best_prediv, best_fbdiv, best_dsm, best_scaler); 1212 + 1213 + return best_freq >> best_scaler; 1214 + } 1215 + 1216 + static void 1217 + samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung) 1218 + { 1219 + const struct samsung_mipi_dphy_timing *timing; 1220 + unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1221 + u32 val, res_up, res_down; 1222 + 1223 + timing = samsung_mipi_dphy_get_timing(samsung); 1224 + regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0xf000); 1225 + 1226 + /* 1227 + * The Drive-Strength / Voltage-Amplitude is adjusted by setting 1228 + * the Driver-Up Resistor and Driver-Down Resistor. 1229 + */ 1230 + res_up = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_up_ohm; 1231 + res_down = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_down_ohm; 1232 + val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN | 1233 + RES_UP(res_up) | RES_DN(res_down); 1234 + regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, val); 1235 + 1236 + if (lane_hs_rate >= 4500) 1237 + regmap_write(samsung->regmap, DPHY_MC_ANA_CON1, 0x0001); 1238 + 1239 + val = 0; 1240 + /* 1241 + * Divide-by-2 Clock from Serial Clock. Use this when data rate is under 1242 + * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock 1243 + */ 1244 + if (lane_hs_rate < 1500) 1245 + val = HSTX_CLK_SEL; 1246 + 1247 + val |= T_LPX(timing->lpx); 1248 + /* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */ 1249 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, val); 1250 + 1251 + val = T_CLK_ZERO(timing->clk_zero) | T_CLK_PREPARE(timing->clk_prepare); 1252 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON1, val); 1253 + 1254 + val = T_HS_EXIT(timing->hs_exit) | T_CLK_TRAIL(timing->clk_trail_eot); 1255 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON2, val); 1256 + 1257 + val = T_CLK_POST(timing->clk_post); 1258 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON3, val); 1259 + 1260 + /* Escape Clock is 20.00MHz */ 1261 + regmap_write(samsung->regmap, DPHY_MC_TIME_CON4, 0x1f4); 1262 + 1263 + /* 1264 + * skew calibration should be off, if the operation data rate is 1265 + * under 1.5Gbps or equal to 1.5Gbps. 1266 + */ 1267 + if (lane_hs_rate > 1500) 1268 + regmap_write(samsung->regmap, DPHY_MC_DESKEW_CON0, 0x9cb1); 1269 + } 1270 + 1271 + static void 1272 + samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung) 1273 + { 1274 + const struct samsung_mipi_dphy_timing *timing; 1275 + unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC); 1276 + u32 val, res_up, res_down; 1277 + 1278 + timing = samsung_mipi_dphy_get_timing(samsung); 1279 + 1280 + /* 1281 + * The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the 1282 + * Driver-Up Resistor and Driver-Down Resistor. 1283 + */ 1284 + res_up = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_up_ohm; 1285 + res_down = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_down_ohm; 1286 + val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN | 1287 + RES_UP(res_up) | RES_DN(res_down); 1288 + regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, val); 1289 + regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, val); 1290 + regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, val); 1291 + regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, val); 1292 + 1293 + if (lane_hs_rate >= 4500) { 1294 + regmap_write(samsung->regmap, COMBO_MD0_ANA_CON1, 0x0001); 1295 + regmap_write(samsung->regmap, COMBO_MD1_ANA_CON1, 0x0001); 1296 + regmap_write(samsung->regmap, COMBO_MD2_ANA_CON1, 0x0001); 1297 + regmap_write(samsung->regmap, DPHY_MD3_ANA_CON1, 0x0001); 1298 + } 1299 + 1300 + val = 0; 1301 + /* 1302 + * Divide-by-2 Clock from Serial Clock. Use this when data rate is under 1303 + * 1500Mbps, otherwise divide-by-16 Clock from Serial Clock 1304 + */ 1305 + if (lane_hs_rate < 1500) 1306 + val = HSTX_CLK_SEL; 1307 + 1308 + val |= T_LPX(timing->lpx); 1309 + /* T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */ 1310 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, val); 1311 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, val); 1312 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, val); 1313 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, val); 1314 + 1315 + val = T_HS_ZERO(timing->hs_zero) | T_HS_PREPARE(timing->hs_prepare); 1316 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON1, val); 1317 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON1, val); 1318 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON1, val); 1319 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON1, val); 1320 + 1321 + val = T_HS_EXIT(timing->hs_exit) | T_HS_TRAIL(timing->hs_trail_eot); 1322 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON2, val); 1323 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON2, val); 1324 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON2, val); 1325 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON2, val); 1326 + 1327 + /* TTA-GET/TTA-GO Timing Counter register use default value */ 1328 + val = T_TA_GET(0x3) | T_TA_GO(0x0); 1329 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON3, val); 1330 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON3, val); 1331 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON3, val); 1332 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON3, val); 1333 + 1334 + /* Escape Clock is 20.00MHz */ 1335 + regmap_write(samsung->regmap, COMBO_MD0_TIME_CON4, 0x1f4); 1336 + regmap_write(samsung->regmap, COMBO_MD1_TIME_CON4, 0x1f4); 1337 + regmap_write(samsung->regmap, COMBO_MD2_TIME_CON4, 0x1f4); 1338 + regmap_write(samsung->regmap, DPHY_MD3_TIME_CON4, 0x1f4); 1339 + } 1340 + 1341 + static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung) 1342 + { 1343 + int ret; 1344 + 1345 + reset_control_assert(samsung->m_phy_rst); 1346 + 1347 + samsung_mipi_dcphy_bias_block_enable(samsung); 1348 + samsung_mipi_dcphy_pll_configure(samsung); 1349 + samsung_mipi_dphy_clk_lane_timing_init(samsung); 1350 + samsung_mipi_dphy_data_lane_timing_init(samsung); 1351 + ret = samsung_mipi_dcphy_pll_enable(samsung); 1352 + if (ret < 0) 1353 + return ret; 1354 + 1355 + samsung_mipi_dphy_lane_enable(samsung); 1356 + 1357 + reset_control_deassert(samsung->m_phy_rst); 1358 + 1359 + /* The TSKEWCAL maximum is 100 µsec 1360 + * at initial calibration. 1361 + */ 1362 + usleep_range(100, 110); 1363 + 1364 + return 0; 1365 + } 1366 + 1367 + static int samsung_mipi_dcphy_power_on(struct phy *phy) 1368 + { 1369 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1370 + 1371 + reset_control_assert(samsung->apb_rst); 1372 + udelay(1); 1373 + reset_control_deassert(samsung->apb_rst); 1374 + 1375 + switch (samsung->type) { 1376 + case PHY_TYPE_DPHY: 1377 + return samsung_mipi_dphy_power_on(samsung); 1378 + default: 1379 + /* CPHY part to be implemented later */ 1380 + return -EOPNOTSUPP; 1381 + } 1382 + 1383 + return 0; 1384 + } 1385 + 1386 + static int samsung_mipi_dcphy_power_off(struct phy *phy) 1387 + { 1388 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1389 + 1390 + switch (samsung->type) { 1391 + case PHY_TYPE_DPHY: 1392 + samsung_mipi_dphy_lane_disable(samsung); 1393 + break; 1394 + default: 1395 + /* CPHY part to be implemented later */ 1396 + return -EOPNOTSUPP; 1397 + } 1398 + 1399 + samsung_mipi_dcphy_pll_disable(samsung); 1400 + 1401 + return 0; 1402 + } 1403 + 1404 + static int 1405 + samsung_mipi_dcphy_pll_ssc_modulation_calc(struct samsung_mipi_dcphy *samsung, 1406 + u8 *mfr, u8 *mrr) 1407 + { 1408 + unsigned long fin = div64_ul(clk_get_rate(samsung->ref_clk), MSEC_PER_SEC); 1409 + u16 prediv = samsung->pll.prediv; 1410 + u16 fbdiv = samsung->pll.fbdiv; 1411 + u16 min_mfr, max_mfr; 1412 + u16 _mfr, best_mfr = 0; 1413 + u16 mr, _mrr, best_mrr = 0; 1414 + 1415 + /* 20KHz ≤ MF ≤ 150KHz */ 1416 + max_mfr = DIV_ROUND_UP(fin, (20 * prediv) << 5); 1417 + min_mfr = div64_ul(fin, ((150 * prediv) << 5)); 1418 + /*0 ≤ mfr ≤ 255 */ 1419 + if (max_mfr > 256) 1420 + max_mfr = 256; 1421 + 1422 + for (_mfr = min_mfr; _mfr < max_mfr; _mfr++) { 1423 + /* 1 ≤ mrr ≤ 31 */ 1424 + for (_mrr = 1; _mrr < 32; _mrr++) { 1425 + mr = DIV_ROUND_UP(_mfr * _mrr * 100, fbdiv << 6); 1426 + /* 0 ≤ MR ≤ 5% */ 1427 + if (mr > 5) 1428 + continue; 1429 + 1430 + if (_mfr * _mrr < 513) { 1431 + best_mfr = _mfr; 1432 + best_mrr = _mrr; 1433 + break; 1434 + } 1435 + } 1436 + } 1437 + 1438 + if (best_mrr) { 1439 + *mfr = best_mfr & 0xff; 1440 + *mrr = best_mrr & 0x3f; 1441 + } else { 1442 + dev_err(samsung->dev, "failed to calc ssc parameter mfr and mrr\n"); 1443 + return -EINVAL; 1444 + } 1445 + 1446 + return 0; 1447 + } 1448 + 1449 + static void 1450 + samsung_mipi_dcphy_pll_calc_rate(struct samsung_mipi_dcphy *samsung, 1451 + unsigned long long rate) 1452 + { 1453 + unsigned long prate = clk_get_rate(samsung->ref_clk); 1454 + unsigned long fout; 1455 + u8 scaler = 0, mfr = 0, mrr = 0; 1456 + u16 fbdiv = 0; 1457 + u8 prediv = 1; 1458 + int dsm = 0; 1459 + int ret; 1460 + 1461 + fout = samsung_mipi_dcphy_pll_round_rate(samsung, prate, rate, 1462 + &prediv, &fbdiv, &dsm, 1463 + &scaler); 1464 + 1465 + dev_dbg(samsung->dev, "%s: fin=%lu, req_rate=%llu\n", 1466 + __func__, prate, rate); 1467 + dev_dbg(samsung->dev, "%s: fout=%lu, prediv=%u, fbdiv=%u\n", 1468 + __func__, fout, prediv, fbdiv); 1469 + 1470 + samsung->pll.prediv = prediv; 1471 + samsung->pll.fbdiv = fbdiv; 1472 + samsung->pll.dsm = dsm; 1473 + samsung->pll.scaler = scaler; 1474 + samsung->pll.rate = fout; 1475 + 1476 + /* 1477 + * All DPHY 2.0 compliant Transmitters shall support SSC operating above 1478 + * 2.5 Gbps 1479 + */ 1480 + if (fout > 2500000000LL) { 1481 + ret = samsung_mipi_dcphy_pll_ssc_modulation_calc(samsung, 1482 + &mfr, &mrr); 1483 + if (!ret) { 1484 + samsung->pll.ssc_en = true; 1485 + samsung->pll.mfr = mfr; 1486 + samsung->pll.mrr = mrr; 1487 + } 1488 + } 1489 + } 1490 + 1491 + static int samsung_mipi_dcphy_configure(struct phy *phy, 1492 + union phy_configure_opts *opts) 1493 + { 1494 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1495 + unsigned long long target_rate = opts->mipi_dphy.hs_clk_rate; 1496 + 1497 + samsung->lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes; 1498 + 1499 + samsung_mipi_dcphy_pll_calc_rate(samsung, target_rate); 1500 + opts->mipi_dphy.hs_clk_rate = samsung->pll.rate; 1501 + 1502 + return 0; 1503 + } 1504 + 1505 + static int samsung_mipi_dcphy_init(struct phy *phy) 1506 + { 1507 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1508 + 1509 + return pm_runtime_resume_and_get(samsung->dev); 1510 + } 1511 + 1512 + static int samsung_mipi_dcphy_exit(struct phy *phy) 1513 + { 1514 + struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); 1515 + 1516 + return pm_runtime_put(samsung->dev); 1517 + } 1518 + 1519 + static const struct phy_ops samsung_mipi_dcphy_ops = { 1520 + .configure = samsung_mipi_dcphy_configure, 1521 + .power_on = samsung_mipi_dcphy_power_on, 1522 + .power_off = samsung_mipi_dcphy_power_off, 1523 + .init = samsung_mipi_dcphy_init, 1524 + .exit = samsung_mipi_dcphy_exit, 1525 + .owner = THIS_MODULE, 1526 + }; 1527 + 1528 + static const struct regmap_config samsung_mipi_dcphy_regmap_config = { 1529 + .name = "dcphy", 1530 + .reg_bits = 32, 1531 + .val_bits = 32, 1532 + .reg_stride = 4, 1533 + .max_register = 0x10000, 1534 + }; 1535 + 1536 + static struct phy *samsung_mipi_dcphy_xlate(struct device *dev, 1537 + const struct of_phandle_args *args) 1538 + { 1539 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1540 + 1541 + if (args->args_count != 1) { 1542 + dev_err(dev, "invalid number of arguments\n"); 1543 + return ERR_PTR(-EINVAL); 1544 + } 1545 + 1546 + if (samsung->type != PHY_NONE && samsung->type != args->args[0]) 1547 + dev_warn(dev, "phy type select %d overwriting type %d\n", 1548 + args->args[0], samsung->type); 1549 + 1550 + samsung->type = args->args[0]; 1551 + 1552 + return samsung->phy; 1553 + } 1554 + 1555 + static int samsung_mipi_dcphy_probe(struct platform_device *pdev) 1556 + { 1557 + struct device *dev = &pdev->dev; 1558 + struct device_node *np = dev->of_node; 1559 + struct samsung_mipi_dcphy *samsung; 1560 + struct phy_provider *phy_provider; 1561 + struct resource *res; 1562 + void __iomem *regs; 1563 + int ret; 1564 + 1565 + samsung = devm_kzalloc(dev, sizeof(*samsung), GFP_KERNEL); 1566 + if (!samsung) 1567 + return -ENOMEM; 1568 + 1569 + samsung->dev = dev; 1570 + samsung->pdata = device_get_match_data(dev); 1571 + platform_set_drvdata(pdev, samsung); 1572 + 1573 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1574 + regs = devm_ioremap_resource(dev, res); 1575 + if (IS_ERR(regs)) 1576 + return PTR_ERR(regs); 1577 + 1578 + samsung->regmap = devm_regmap_init_mmio(dev, regs, 1579 + &samsung_mipi_dcphy_regmap_config); 1580 + if (IS_ERR(samsung->regmap)) 1581 + return dev_err_probe(dev, PTR_ERR(samsung->regmap), "Failed to init regmap\n"); 1582 + 1583 + samsung->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 1584 + if (IS_ERR(samsung->grf_regmap)) 1585 + return dev_err_probe(dev, PTR_ERR(samsung->grf_regmap), 1586 + "Unable to get rockchip,grf\n"); 1587 + 1588 + samsung->ref_clk = devm_clk_get(dev, "ref"); 1589 + if (IS_ERR(samsung->ref_clk)) 1590 + return dev_err_probe(dev, PTR_ERR(samsung->ref_clk), 1591 + "Failed to get reference clock\n"); 1592 + 1593 + samsung->pclk = devm_clk_get(dev, "pclk"); 1594 + if (IS_ERR(samsung->pclk)) 1595 + return dev_err_probe(dev, PTR_ERR(samsung->pclk), "Failed to get pclk\n"); 1596 + 1597 + samsung->m_phy_rst = devm_reset_control_get(dev, "m_phy"); 1598 + if (IS_ERR(samsung->m_phy_rst)) 1599 + return dev_err_probe(dev, PTR_ERR(samsung->m_phy_rst), 1600 + "Failed to get system m_phy_rst control\n"); 1601 + 1602 + samsung->s_phy_rst = devm_reset_control_get(dev, "s_phy"); 1603 + if (IS_ERR(samsung->s_phy_rst)) 1604 + return dev_err_probe(dev, PTR_ERR(samsung->s_phy_rst), 1605 + "Failed to get system s_phy_rst control\n"); 1606 + 1607 + samsung->apb_rst = devm_reset_control_get(dev, "apb"); 1608 + if (IS_ERR(samsung->apb_rst)) 1609 + return dev_err_probe(dev, PTR_ERR(samsung->apb_rst), 1610 + "Failed to get system apb_rst control\n"); 1611 + 1612 + samsung->grf_apb_rst = devm_reset_control_get(dev, "grf"); 1613 + if (IS_ERR(samsung->grf_apb_rst)) 1614 + return dev_err_probe(dev, PTR_ERR(samsung->grf_apb_rst), 1615 + "Failed to get system grf_apb_rst control\n"); 1616 + 1617 + samsung->phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_ops); 1618 + if (IS_ERR(samsung->phy)) 1619 + return dev_err_probe(dev, PTR_ERR(samsung->phy), "Failed to create MIPI DC-PHY\n"); 1620 + 1621 + phy_set_drvdata(samsung->phy, samsung); 1622 + 1623 + ret = devm_pm_runtime_enable(dev); 1624 + if (ret) 1625 + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 1626 + 1627 + phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate); 1628 + if (IS_ERR(phy_provider)) 1629 + return dev_err_probe(dev, PTR_ERR(phy_provider), 1630 + "Failed to register phy provider\n"); 1631 + 1632 + return 0; 1633 + } 1634 + 1635 + static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev) 1636 + { 1637 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1638 + 1639 + clk_disable_unprepare(samsung->ref_clk); 1640 + clk_disable_unprepare(samsung->pclk); 1641 + 1642 + return 0; 1643 + } 1644 + 1645 + static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev) 1646 + { 1647 + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); 1648 + int ret; 1649 + 1650 + ret = clk_prepare_enable(samsung->pclk); 1651 + if (ret) { 1652 + dev_err(samsung->dev, "Failed to enable pclk, %d\n", ret); 1653 + return ret; 1654 + } 1655 + 1656 + clk_prepare_enable(samsung->ref_clk); 1657 + if (ret) { 1658 + dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret); 1659 + clk_disable_unprepare(samsung->pclk); 1660 + return ret; 1661 + } 1662 + 1663 + return 0; 1664 + } 1665 + 1666 + static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = { 1667 + SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend, 1668 + samsung_mipi_dcphy_runtime_resume, NULL) 1669 + }; 1670 + 1671 + static const struct hs_drv_res_cfg rk3576_dphy_hs_drv_res_cfg = { 1672 + .clk_hs_drv_up_ohm = STRENGTH_52_OHM, 1673 + .clk_hs_drv_down_ohm = STRENGTH_52_OHM, 1674 + .data_hs_drv_up_ohm = STRENGTH_39_OHM, 1675 + .data_hs_drv_down_ohm = STRENGTH_39_OHM, 1676 + }; 1677 + 1678 + static const struct hs_drv_res_cfg rk3588_dphy_hs_drv_res_cfg = { 1679 + .clk_hs_drv_up_ohm = STRENGTH_34_OHM, 1680 + .clk_hs_drv_down_ohm = STRENGTH_34_OHM, 1681 + .data_hs_drv_up_ohm = STRENGTH_43_OHM, 1682 + .data_hs_drv_down_ohm = STRENGTH_43_OHM, 1683 + }; 1684 + 1685 + static const struct samsung_mipi_dcphy_plat_data rk3576_samsung_mipi_dcphy_plat_data = { 1686 + .dphy_hs_drv_res_cfg = &rk3576_dphy_hs_drv_res_cfg, 1687 + .dphy_tx_max_lane_kbps = 2500000L, 1688 + }; 1689 + 1690 + static const struct samsung_mipi_dcphy_plat_data rk3588_samsung_mipi_dcphy_plat_data = { 1691 + .dphy_hs_drv_res_cfg = &rk3588_dphy_hs_drv_res_cfg, 1692 + .dphy_tx_max_lane_kbps = 4500000L, 1693 + }; 1694 + 1695 + static const struct of_device_id samsung_mipi_dcphy_of_match[] = { 1696 + { 1697 + .compatible = "rockchip,rk3576-mipi-dcphy", 1698 + .data = &rk3576_samsung_mipi_dcphy_plat_data, 1699 + }, { 1700 + .compatible = "rockchip,rk3588-mipi-dcphy", 1701 + .data = &rk3588_samsung_mipi_dcphy_plat_data, 1702 + }, 1703 + { /* sentinel */ } 1704 + }; 1705 + MODULE_DEVICE_TABLE(of, samsung_mipi_dcphy_of_match); 1706 + 1707 + static struct platform_driver samsung_mipi_dcphy_driver = { 1708 + .driver = { 1709 + .name = "samsung-mipi-dcphy", 1710 + .of_match_table = samsung_mipi_dcphy_of_match, 1711 + .pm = &samsung_mipi_dcphy_pm_ops, 1712 + }, 1713 + .probe = samsung_mipi_dcphy_probe, 1714 + }; 1715 + module_platform_driver(samsung_mipi_dcphy_driver); 1716 + 1717 + MODULE_AUTHOR("Guochun Huang <hero.huang@rock-chips.com>"); 1718 + MODULE_DESCRIPTION("Samsung MIPI DCPHY Driver"); 1719 + MODULE_LICENSE("GPL");