459 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.4 * Copyright (C) 2013 Red Hat5 * Author: Rob Clark <robdclark@gmail.com>6 */7 8#include <linux/clk-provider.h>9#include <linux/delay.h>10 11#include "hdmi.h"12 13struct hdmi_pll_8960 {14 struct platform_device *pdev;15 struct clk_hw clk_hw;16 void __iomem *mmio;17 18 unsigned long pixclk;19};20 21#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8960, clk_hw)22 23/*24 * HDMI PLL:25 *26 * To get the parent clock setup properly, we need to plug in hdmi pll27 * configuration into common-clock-framework.28 */29 30struct pll_rate {31 unsigned long rate;32 int num_reg;33 struct {34 u32 val;35 u32 reg;36 } conf[32];37};38 39/* NOTE: keep sorted highest freq to lowest: */40static const struct pll_rate freqtbl[] = {41 { 154000000, 14, {42 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },43 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },44 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },45 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },46 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },47 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },48 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },49 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },50 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },51 { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },52 { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },53 { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },54 { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },55 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },56 }57 },58 /* 1080p60/1080p50 case */59 { 148500000, 27, {60 { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },61 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },62 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },63 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },64 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },65 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },66 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },67 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },68 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },69 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },70 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },71 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },72 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },73 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },74 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },75 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },76 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },77 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },78 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },79 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },80 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },81 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },82 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },83 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },84 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },85 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },86 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },87 }88 },89 { 108000000, 13, {90 { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },91 { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },92 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },93 { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },94 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },95 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },96 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },97 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },98 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },99 { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },100 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },101 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },102 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },103 }104 },105 /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */106 { 74250000, 8, {107 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },108 { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },109 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },110 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },111 { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },112 { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },113 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },114 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },115 }116 },117 { 74176000, 14, {118 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },119 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },120 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },121 { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },122 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },123 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },124 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },125 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },126 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },127 { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },128 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },129 { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },130 { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },131 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },132 }133 },134 { 65000000, 14, {135 { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },136 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },137 { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },138 { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },139 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },140 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },141 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },142 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },143 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },144 { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },145 { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },146 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },147 { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },148 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },149 }150 },151 /* 480p60/480i60 */152 { 27030000, 18, {153 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },154 { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },155 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },156 { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },157 { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },158 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },159 { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },160 { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },161 { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },162 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },163 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },164 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },165 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },166 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },167 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },168 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },169 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },170 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },171 }172 },173 /* 576p50/576i50 */174 { 27000000, 27, {175 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },176 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },177 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },178 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },179 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },180 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },181 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },182 { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },183 { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },184 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },185 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },186 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },187 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },188 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },189 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },190 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },191 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },192 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },193 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },194 { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },195 { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },196 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },197 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },198 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },199 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },200 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },201 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },202 }203 },204 /* 640x480p60 */205 { 25200000, 27, {206 { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },207 { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },208 { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },209 { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },210 { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },211 { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },212 { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },213 { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },214 { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },215 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },216 { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },217 { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },218 { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },219 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },220 { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },221 { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },222 { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },223 { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },224 { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },225 { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },226 { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },227 { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },228 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },229 { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },230 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },231 { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },232 { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },233 }234 },235};236 237static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data)238{239 writel(data, pll->mmio + reg);240}241 242static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg)243{244 return readl(pll->mmio + reg);245}246 247static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll)248{249 return platform_get_drvdata(pll->pdev);250}251 252static int hdmi_pll_enable(struct clk_hw *hw)253{254 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);255 struct hdmi_phy *phy = pll_get_phy(pll);256 int timeout_count, pll_lock_retry = 10;257 unsigned int val;258 259 DBG("");260 261 /* Assert PLL S/W reset */262 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);263 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);264 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);265 266 /* Wait for a short time before de-asserting267 * to allow the hardware to complete its job.268 * This much of delay should be fine for hardware269 * to assert and de-assert.270 */271 udelay(10);272 273 /* De-assert PLL S/W reset */274 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);275 276 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);277 val |= HDMI_8960_PHY_REG12_SW_RESET;278 /* Assert PHY S/W reset */279 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);280 val &= ~HDMI_8960_PHY_REG12_SW_RESET;281 /*282 * Wait for a short time before de-asserting to allow the hardware to283 * complete its job. This much of delay should be fine for hardware to284 * assert and de-assert.285 */286 udelay(10);287 /* De-assert PHY S/W reset */288 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);289 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x3f);290 291 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);292 val |= HDMI_8960_PHY_REG12_PWRDN_B;293 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);294 /* Wait 10 us for enabling global power for PHY */295 mb();296 udelay(10);297 298 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);299 val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;300 val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;301 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);302 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80);303 304 timeout_count = 1000;305 while (--pll_lock_retry > 0) {306 /* are we there yet? */307 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_STATUS0);308 if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)309 break;310 311 udelay(1);312 313 if (--timeout_count > 0)314 continue;315 316 /*317 * PLL has still not locked.318 * Do a software reset and try again319 * Assert PLL S/W reset first320 */321 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);322 udelay(10);323 pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);324 325 /*326 * Wait for a short duration for the PLL calibration327 * before checking if the PLL gets locked328 */329 udelay(350);330 331 timeout_count = 1000;332 }333 334 return 0;335}336 337static void hdmi_pll_disable(struct clk_hw *hw)338{339 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);340 struct hdmi_phy *phy = pll_get_phy(pll);341 unsigned int val;342 343 DBG("");344 345 val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12);346 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;347 hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val);348 349 val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B);350 val |= HDMI_8960_PHY_REG12_SW_RESET;351 val &= ~HDMI_8960_PHY_REG12_PWRDN_B;352 pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);353 /* Make sure HDMI PHY/PLL are powered down */354 mb();355}356 357static const struct pll_rate *find_rate(unsigned long rate)358{359 int i;360 361 for (i = 1; i < ARRAY_SIZE(freqtbl); i++)362 if (rate > freqtbl[i].rate)363 return &freqtbl[i - 1];364 365 return &freqtbl[i - 1];366}367 368static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,369 unsigned long parent_rate)370{371 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);372 373 return pll->pixclk;374}375 376static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,377 unsigned long *parent_rate)378{379 const struct pll_rate *pll_rate = find_rate(rate);380 381 return pll_rate->rate;382}383 384static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,385 unsigned long parent_rate)386{387 struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw);388 const struct pll_rate *pll_rate = find_rate(rate);389 int i;390 391 DBG("rate=%lu", rate);392 393 for (i = 0; i < pll_rate->num_reg; i++)394 pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val);395 396 pll->pixclk = rate;397 398 return 0;399}400 401static const struct clk_ops hdmi_pll_ops = {402 .enable = hdmi_pll_enable,403 .disable = hdmi_pll_disable,404 .recalc_rate = hdmi_pll_recalc_rate,405 .round_rate = hdmi_pll_round_rate,406 .set_rate = hdmi_pll_set_rate,407};408 409static const struct clk_parent_data hdmi_pll_parents[] = {410 { .fw_name = "pxo", .name = "pxo_board" },411};412 413static struct clk_init_data pll_init = {414 .name = "hdmi_pll",415 .ops = &hdmi_pll_ops,416 .parent_data = hdmi_pll_parents,417 .num_parents = ARRAY_SIZE(hdmi_pll_parents),418 .flags = CLK_IGNORE_UNUSED,419};420 421int msm_hdmi_pll_8960_init(struct platform_device *pdev)422{423 struct device *dev = &pdev->dev;424 struct hdmi_pll_8960 *pll;425 int i, ret;426 427 /* sanity check: */428 for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)429 if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate))430 return -EINVAL;431 432 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);433 if (!pll)434 return -ENOMEM;435 436 pll->mmio = msm_ioremap(pdev, "hdmi_pll");437 if (IS_ERR(pll->mmio)) {438 DRM_DEV_ERROR(dev, "failed to map pll base\n");439 return -ENOMEM;440 }441 442 pll->pdev = pdev;443 pll->clk_hw.init = &pll_init;444 445 ret = devm_clk_hw_register(dev, &pll->clk_hw);446 if (ret < 0) {447 DRM_DEV_ERROR(dev, "failed to register pll clock\n");448 return ret;449 }450 451 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);452 if (ret) {453 DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);454 return ret;455 }456 457 return 0;458}459