···11+NVIDIA Tegra124 Clock And Reset Controller22+33+This binding uses the common clock binding:44+Documentation/devicetree/bindings/clock/clock-bindings.txt55+66+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible77+for muxing and gating Tegra's clocks, and setting their rates.88+99+Required properties :1010+- compatible : Should be "nvidia,tegra124-car"1111+- reg : Should contain CAR registers location and length1212+- clocks : Should contain phandle and clock specifiers for two clocks:1313+ the 32 KHz "32k_in", and the board-specific oscillator "osc".1414+- #clock-cells : Should be 1.1515+ In clock consumers, this cell represents the clock ID exposed by the1616+ CAR. The assignments may be found in header file1717+ <dt-bindings/clock/tegra124-car.h>.1818+1919+Example SoC include file:2020+2121+/ {2222+ tegra_car: clock {2323+ compatible = "nvidia,tegra124-car";2424+ reg = <0x60006000 0x1000>;2525+ #clock-cells = <1>;2626+ };2727+2828+ usb@c5004000 {2929+ clocks = <&tegra_car TEGRA124_CLK_USB2>;3030+ };3131+};3232+3333+Example board file:3434+3535+/ {3636+ clocks {3737+ compatible = "simple-bus";3838+ #address-cells = <1>;3939+ #size-cells = <0>;4040+4141+ osc: clock@0 {4242+ compatible = "fixed-clock";4343+ reg = <0>;4444+ #clock-cells = <0>;4545+ clock-frequency = <112400000>;4646+ };4747+4848+ clk_32k: clock@1 {4949+ compatible = "fixed-clock";5050+ reg = <1>;5151+ #clock-cells = <0>;5252+ clock-frequency = <32768>;5353+ };5454+ };5555+5656+ &tegra_car {5757+ clocks = <&clk_32k> <&osc>;5858+ };5959+};
···7777#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)78787979#define PLLE_SS_CTRL 0x688080-#define PLLE_SS_DISABLE (7 << 10)8080+#define PLLE_SS_CNTL_BYPASS_SS BIT(10)8181+#define PLLE_SS_CNTL_INTERP_RESET BIT(11)8282+#define PLLE_SS_CNTL_SSC_BYP BIT(12)8383+#define PLLE_SS_CNTL_CENTER BIT(14)8484+#define PLLE_SS_CNTL_INVERT BIT(15)8585+#define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\8686+ PLLE_SS_CNTL_SSC_BYP)8787+#define PLLE_SS_MAX_MASK 0x1ff8888+#define PLLE_SS_MAX_VAL 0x258989+#define PLLE_SS_INC_MASK (0xff << 16)9090+#define PLLE_SS_INC_VAL (0x1 << 16)9191+#define PLLE_SS_INCINTRV_MASK (0x3f << 24)9292+#define PLLE_SS_INCINTRV_VAL (0x20 << 24)9393+#define PLLE_SS_COEFFICIENTS_MASK \9494+ (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK)9595+#define PLLE_SS_COEFFICIENTS_VAL \9696+ (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)81978298#define PLLE_AUX_PLLP_SEL BIT(2)8399#define PLLE_AUX_ENABLE_SWCTL BIT(4)···137121#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)138122#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)139123124124+#define PLLSS_MISC_KCP 0125125+#define PLLSS_MISC_KVCO 0126126+#define PLLSS_MISC_SETUP 0127127+#define PLLSS_EN_SDM 0128128+#define PLLSS_EN_SSC 0129129+#define PLLSS_EN_DITHER2 0130130+#define PLLSS_EN_DITHER 1131131+#define PLLSS_SDM_RESET 0132132+#define PLLSS_CLAMP 0133133+#define PLLSS_SDM_SSC_MAX 0134134+#define PLLSS_SDM_SSC_MIN 0135135+#define PLLSS_SDM_SSC_STEP 0136136+#define PLLSS_SDM_DIN 0137137+#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \138138+ (PLLSS_MISC_KVCO << 24) | \139139+ PLLSS_MISC_SETUP)140140+#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \141141+ (PLLSS_EN_SSC << 30) | \142142+ (PLLSS_EN_DITHER2 << 29) | \143143+ (PLLSS_EN_DITHER << 28) | \144144+ (PLLSS_SDM_RESET) << 27 | \145145+ (PLLSS_CLAMP << 22))146146+#define PLLSS_CTRL1_DEFAULT \147147+ ((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN)148148+#define PLLSS_CTRL2_DEFAULT \149149+ ((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN)150150+#define PLLSS_LOCK_OVERRIDE BIT(24)151151+#define PLLSS_REF_SRC_SEL_SHIFT 25152152+#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)153153+140154#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)141155#define pll_readl_base(p) pll_readl(p->params->base_reg, p)142156#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)···180134#define mask(w) ((1 << (w)) - 1)181135#define divm_mask(p) mask(p->params->div_nmp->divm_width)182136#define divn_mask(p) mask(p->params->div_nmp->divn_width)183183-#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \137137+#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\184138 mask(p->params->div_nmp->divp_width))185139186140#define divm_max(p) (divm_mask(p))···200154{201155 u32 val;202156203203- if (!(pll->flags & TEGRA_PLL_USE_LOCK))157157+ if (!(pll->params->flags & TEGRA_PLL_USE_LOCK))204158 return;205159206206- if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE))160160+ if (!(pll->params->flags & TEGRA_PLL_HAS_LOCK_ENABLE))207161 return;208162209163 val = pll_readl_misc(pll);···217171 u32 val, lock_mask;218172 void __iomem *lock_addr;219173220220- if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {174174+ if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) {221175 udelay(pll->params->lock_delay);222176 return 0;223177 }224178225179 lock_addr = pll->clk_base;226226- if (pll->flags & TEGRA_PLL_LOCK_MISC)180180+ if (pll->params->flags & TEGRA_PLL_LOCK_MISC)227181 lock_addr += pll->params->misc_reg;228182 else229183 lock_addr += pll->params->base_reg;···250204 struct tegra_clk_pll *pll = to_clk_pll(hw);251205 u32 val;252206253253- if (pll->flags & TEGRA_PLLM) {207207+ if (pll->params->flags & TEGRA_PLLM) {254208 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);255209 if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)256210 return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;···269223 clk_pll_enable_lock(pll);270224271225 val = pll_readl_base(pll);272272- if (pll->flags & TEGRA_PLL_BYPASS)226226+ if (pll->params->flags & TEGRA_PLL_BYPASS)273227 val &= ~PLL_BASE_BYPASS;274228 val |= PLL_BASE_ENABLE;275229 pll_writel_base(val, pll);276230277277- if (pll->flags & TEGRA_PLLM) {231231+ if (pll->params->flags & TEGRA_PLLM) {278232 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);279233 val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;280234 writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);···287241 u32 val;288242289243 val = pll_readl_base(pll);290290- if (pll->flags & TEGRA_PLL_BYPASS)244244+ if (pll->params->flags & TEGRA_PLL_BYPASS)291245 val &= ~PLL_BASE_BYPASS;292246 val &= ~PLL_BASE_ENABLE;293247 pll_writel_base(val, pll);294248295295- if (pll->flags & TEGRA_PLLM) {249249+ if (pll->params->flags & TEGRA_PLLM) {296250 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);297251 val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;298252 writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);···372326 struct tegra_clk_pll *pll = to_clk_pll(hw);373327 struct tegra_clk_pll_freq_table *sel;374328375375- for (sel = pll->freq_table; sel->input_rate != 0; sel++)329329+ for (sel = pll->params->freq_table; sel->input_rate != 0; sel++)376330 if (sel->input_rate == parent_rate &&377331 sel->output_rate == rate)378332 break;···435389 if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||436390 (1 << p_div) > divp_max(pll)437391 || cfg->output_rate > pll->params->vco_max) {438438- pr_err("%s: Failed to set %s rate %lu\n",439439- __func__, __clk_get_name(hw->clk), rate);440440- WARN_ON(1);441392 return -EINVAL;442393 }394394+395395+ cfg->output_rate >>= p_div;443396444397 if (pll->params->pdiv_tohw) {445398 ret = _p_div_to_hw(hw, 1 << p_div);···459414 struct tegra_clk_pll_params *params = pll->params;460415 struct div_nmp *div_nmp = params->div_nmp;461416462462- if ((pll->flags & TEGRA_PLLM) &&417417+ if ((params->flags & TEGRA_PLLM) &&463418 (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &464419 PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {465420 val = pll_override_readl(params->pmc_divp_reg, pll);···495450 struct tegra_clk_pll_params *params = pll->params;496451 struct div_nmp *div_nmp = params->div_nmp;497452498498- if ((pll->flags & TEGRA_PLLM) &&453453+ if ((params->flags & TEGRA_PLLM) &&499454 (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &500455 PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {501456 val = pll_override_readl(params->pmc_divp_reg, pll);···524479 val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);525480 val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;526481527527- if (pll->flags & TEGRA_PLL_SET_LFCON) {482482+ if (pll->params->flags & TEGRA_PLL_SET_LFCON) {528483 val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);529484 if (cfg->n >= PLLDU_LFCON_SET_DIVN)530485 val |= 1 << PLL_MISC_LFCON_SHIFT;531531- } else if (pll->flags & TEGRA_PLL_SET_DCCON) {486486+ } else if (pll->params->flags & TEGRA_PLL_SET_DCCON) {532487 val &= ~(1 << PLL_MISC_DCCON_SHIFT);533488 if (rate >= (pll->params->vco_max >> 1))534489 val |= 1 << PLL_MISC_DCCON_SHIFT;···550505551506 _update_pll_mnp(pll, cfg);552507553553- if (pll->flags & TEGRA_PLL_HAS_CPCON)508508+ if (pll->params->flags & TEGRA_PLL_HAS_CPCON)554509 _update_pll_cpcon(pll, cfg, rate);555510556511 if (state) {···569524 unsigned long flags = 0;570525 int ret = 0;571526572572- if (pll->flags & TEGRA_PLL_FIXED) {573573- if (rate != pll->fixed_rate) {527527+ if (pll->params->flags & TEGRA_PLL_FIXED) {528528+ if (rate != pll->params->fixed_rate) {574529 pr_err("%s: Can not change %s fixed rate %lu to %lu\n",575530 __func__, __clk_get_name(hw->clk),576576- pll->fixed_rate, rate);531531+ pll->params->fixed_rate, rate);577532 return -EINVAL;578533 }579534 return 0;···581536582537 if (_get_table_rate(hw, &cfg, rate, parent_rate) &&583538 _calc_rate(hw, &cfg, rate, parent_rate)) {539539+ pr_err("%s: Failed to set %s rate %lu\n", __func__,540540+ __clk_get_name(hw->clk), rate);584541 WARN_ON(1);585542 return -EINVAL;586543 }···606559 struct tegra_clk_pll *pll = to_clk_pll(hw);607560 struct tegra_clk_pll_freq_table cfg;608561609609- if (pll->flags & TEGRA_PLL_FIXED)610610- return pll->fixed_rate;562562+ if (pll->params->flags & TEGRA_PLL_FIXED)563563+ return pll->params->fixed_rate;611564612565 /* PLLM is used for memory; we do not change rate */613613- if (pll->flags & TEGRA_PLLM)566566+ if (pll->params->flags & TEGRA_PLLM)614567 return __clk_get_rate(hw->clk);615568616569 if (_get_table_rate(hw, &cfg, rate, *prate) &&617617- _calc_rate(hw, &cfg, rate, *prate)) {618618- WARN_ON(1);570570+ _calc_rate(hw, &cfg, rate, *prate))619571 return -EINVAL;620620- }621572622573 return cfg.output_rate;623574}···631586632587 val = pll_readl_base(pll);633588634634- if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))589589+ if ((pll->params->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))635590 return parent_rate;636591637637- if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {592592+ if ((pll->params->flags & TEGRA_PLL_FIXED) &&593593+ !(val & PLL_BASE_OVERRIDE)) {638594 struct tegra_clk_pll_freq_table sel;639639- if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {595595+ if (_get_table_rate(hw, &sel, pll->params->fixed_rate,596596+ parent_rate)) {640597 pr_err("Clock %s has unknown fixed frequency\n",641598 __clk_get_name(hw->clk));642599 BUG();643600 }644644- return pll->fixed_rate;601601+ return pll->params->fixed_rate;645602 }646603647604 _get_pll_mnp(pll, &cfg);···711664 u32 val;712665 int err;713666714714- if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))667667+ if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))715668 return -EINVAL;716669717670 clk_pll_disable(hw);···727680 return err;728681 }729682730730- if (pll->flags & TEGRA_PLLE_CONFIGURE) {683683+ if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {731684 /* configure dividers */732685 val = pll_readl_base(pll);733686 val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));···791744 .enable = clk_plle_enable,792745};793746794794-#ifdef CONFIG_ARCH_TEGRA_114_SOC747747+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)795748796749static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,797750 unsigned long parent_rate)···800753 return 2;801754 else802755 return 1;756756+}757757+758758+static unsigned long _clip_vco_min(unsigned long vco_min,759759+ unsigned long parent_rate)760760+{761761+ return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate;762762+}763763+764764+static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,765765+ void __iomem *clk_base,766766+ unsigned long parent_rate)767767+{768768+ u32 val;769769+ u32 step_a, step_b;770770+771771+ switch (parent_rate) {772772+ case 12000000:773773+ case 13000000:774774+ case 26000000:775775+ step_a = 0x2B;776776+ step_b = 0x0B;777777+ break;778778+ case 16800000:779779+ step_a = 0x1A;780780+ step_b = 0x09;781781+ break;782782+ case 19200000:783783+ step_a = 0x12;784784+ step_b = 0x08;785785+ break;786786+ default:787787+ pr_err("%s: Unexpected reference rate %lu\n",788788+ __func__, parent_rate);789789+ WARN_ON(1);790790+ return -EINVAL;791791+ }792792+793793+ val = step_a << pll_params->stepa_shift;794794+ val |= step_b << pll_params->stepb_shift;795795+ writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);796796+797797+ return 0;803798}804799805800static int clk_pll_iddq_enable(struct clk_hw *hw)···12621173 unsigned long flags = 0;12631174 unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));1264117512651265- if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))11761176+ if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))12661177 return -EINVAL;1267117812681179 if (pll->lock)···13061217 if (ret < 0)13071218 goto out;1308121912201220+ val = pll_readl(PLLE_SS_CTRL, pll);12211221+ val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);12221222+ val &= ~PLLE_SS_COEFFICIENTS_MASK;12231223+ val |= PLLE_SS_COEFFICIENTS_VAL;12241224+ pll_writel(val, PLLE_SS_CTRL, pll);12251225+ val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);12261226+ pll_writel(val, PLLE_SS_CTRL, pll);12271227+ udelay(1);12281228+ val &= ~PLLE_SS_CNTL_INTERP_RESET;12291229+ pll_writel(val, PLLE_SS_CTRL, pll);12301230+ udelay(1);12311231+13091232 /* TODO: enable hw control of xusb brick pll */1310123313111234out:···13491248#endif1350124913511250static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,13521352- void __iomem *pmc, unsigned long fixed_rate,13531353- struct tegra_clk_pll_params *pll_params, u32 pll_flags,13541354- struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)12511251+ void __iomem *pmc, struct tegra_clk_pll_params *pll_params,12521252+ spinlock_t *lock)13551253{13561254 struct tegra_clk_pll *pll;13571255···13611261 pll->clk_base = clk_base;13621262 pll->pmc = pmc;1363126313641364- pll->freq_table = freq_table;13651264 pll->params = pll_params;13661366- pll->fixed_rate = fixed_rate;13671367- pll->flags = pll_flags;13681265 pll->lock = lock;1369126613701267 if (!pll_params->div_nmp)···1390129313911294struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,13921295 void __iomem *clk_base, void __iomem *pmc,13931393- unsigned long flags, unsigned long fixed_rate,13941394- struct tegra_clk_pll_params *pll_params, u32 pll_flags,13951395- struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)12961296+ unsigned long flags, struct tegra_clk_pll_params *pll_params,12971297+ spinlock_t *lock)13961298{13971299 struct tegra_clk_pll *pll;13981300 struct clk *clk;1399130114001400- pll_flags |= TEGRA_PLL_BYPASS;14011401- pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;14021402- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,14031403- freq_table, lock);13021302+ pll_params->flags |= TEGRA_PLL_BYPASS;13031303+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;13041304+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);14041305 if (IS_ERR(pll))14051306 return ERR_CAST(pll);14061307···1412131714131318struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,14141319 void __iomem *clk_base, void __iomem *pmc,14151415- unsigned long flags, unsigned long fixed_rate,14161416- struct tegra_clk_pll_params *pll_params, u32 pll_flags,14171417- struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)13201320+ unsigned long flags, struct tegra_clk_pll_params *pll_params,13211321+ spinlock_t *lock)14181322{14191323 struct tegra_clk_pll *pll;14201324 struct clk *clk;1421132514221422- pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;14231423- pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;14241424- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,14251425- freq_table, lock);13261326+ pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;13271327+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;13281328+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);14261329 if (IS_ERR(pll))14271330 return ERR_CAST(pll);14281331···14321339 return clk;14331340}1434134114351435-#ifdef CONFIG_ARCH_TEGRA_114_SOC13421342+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)14361343const struct clk_ops tegra_clk_pllxc_ops = {14371344 .is_enabled = clk_pll_is_enabled,14381345 .enable = clk_pll_iddq_enable,···1479138614801387struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,14811388 void __iomem *clk_base, void __iomem *pmc,14821482- unsigned long flags, unsigned long fixed_rate,13891389+ unsigned long flags,14831390 struct tegra_clk_pll_params *pll_params,14841484- u32 pll_flags,14851485- struct tegra_clk_pll_freq_table *freq_table,14861391 spinlock_t *lock)14871392{14881393 struct tegra_clk_pll *pll;14891489- struct clk *clk;13941394+ struct clk *clk, *parent;13951395+ unsigned long parent_rate;13961396+ int err;13971397+ u32 val, val_iddq;13981398+13991399+ parent = __clk_lookup(parent_name);14001400+ if (!parent) {14011401+ WARN(1, "parent clk %s of %s must be registered first\n",14021402+ name, parent_name);14031403+ return ERR_PTR(-EINVAL);14041404+ }1490140514911406 if (!pll_params->pdiv_tohw)14921407 return ERR_PTR(-EINVAL);1493140814941494- pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;14951495- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,14961496- freq_table, lock);14091409+ parent_rate = __clk_get_rate(parent);14101410+14111411+ pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);14121412+14131413+ err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);14141414+ if (err)14151415+ return ERR_PTR(err);14161416+14171417+ val = readl_relaxed(clk_base + pll_params->base_reg);14181418+ val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);14191419+14201420+ if (val & PLL_BASE_ENABLE)14211421+ WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));14221422+ else {14231423+ val_iddq |= BIT(pll_params->iddq_bit_idx);14241424+ writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);14251425+ }14261426+14271427+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;14281428+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);14971429 if (IS_ERR(pll))14981430 return ERR_CAST(pll);14991431···1532141415331415struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,15341416 void __iomem *clk_base, void __iomem *pmc,15351535- unsigned long flags, unsigned long fixed_rate,14171417+ unsigned long flags,15361418 struct tegra_clk_pll_params *pll_params,15371537- u32 pll_flags,15381538- struct tegra_clk_pll_freq_table *freq_table,15391419 spinlock_t *lock, unsigned long parent_rate)15401420{15411421 u32 val;15421422 struct tegra_clk_pll *pll;15431423 struct clk *clk;1544142415451545- pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;15461546- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,15471547- freq_table, lock);14251425+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;14261426+14271427+ pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);14281428+14291429+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);15481430 if (IS_ERR(pll))15491431 return ERR_CAST(pll);15501432···1579146115801462struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,15811463 void __iomem *clk_base, void __iomem *pmc,15821582- unsigned long flags, unsigned long fixed_rate,14641464+ unsigned long flags,15831465 struct tegra_clk_pll_params *pll_params,15841584- u32 pll_flags,15851585- struct tegra_clk_pll_freq_table *freq_table,15861466 spinlock_t *lock)15871467{15881468 struct tegra_clk_pll *pll;15891589- struct clk *clk;14691469+ struct clk *clk, *parent;14701470+ unsigned long parent_rate;1590147115911472 if (!pll_params->pdiv_tohw)15921473 return ERR_PTR(-EINVAL);1593147415941594- pll_flags |= TEGRA_PLL_BYPASS;15951595- pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;15961596- pll_flags |= TEGRA_PLLM;15971597- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,15981598- freq_table, lock);14751475+ parent = __clk_lookup(parent_name);14761476+ if (!parent) {14771477+ WARN(1, "parent clk %s of %s must be registered first\n",14781478+ name, parent_name);14791479+ return ERR_PTR(-EINVAL);14801480+ }14811481+14821482+ parent_rate = __clk_get_rate(parent);14831483+14841484+ pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);14851485+14861486+ pll_params->flags |= TEGRA_PLL_BYPASS;14871487+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;14881488+ pll_params->flags |= TEGRA_PLLM;14891489+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);15991490 if (IS_ERR(pll))16001491 return ERR_CAST(pll);16011492···1618149116191492struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,16201493 void __iomem *clk_base, void __iomem *pmc,16211621- unsigned long flags, unsigned long fixed_rate,14941494+ unsigned long flags,16221495 struct tegra_clk_pll_params *pll_params,16231623- u32 pll_flags,16241624- struct tegra_clk_pll_freq_table *freq_table,16251496 spinlock_t *lock)16261497{16271498 struct clk *parent, *clk;···16321507 return ERR_PTR(-EINVAL);1633150816341509 parent = __clk_lookup(parent_name);16351635- if (IS_ERR(parent)) {15101510+ if (!parent) {16361511 WARN(1, "parent clk %s of %s must be registered first\n",16371512 name, parent_name);16381513 return ERR_PTR(-EINVAL);16391514 }1640151516411641- pll_flags |= TEGRA_PLL_BYPASS;16421642- pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,16431643- freq_table, lock);15161516+ parent_rate = __clk_get_rate(parent);15171517+15181518+ pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);15191519+15201520+ pll_params->flags |= TEGRA_PLL_BYPASS;15211521+ pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);16441522 if (IS_ERR(pll))16451523 return ERR_CAST(pll);16461646-16471647- parent_rate = __clk_get_rate(parent);1648152416491525 /*16501526 * Most of PLLC register fields are shadowed, and can not be read···16931567struct clk *tegra_clk_register_plle_tegra114(const char *name,16941568 const char *parent_name,16951569 void __iomem *clk_base, unsigned long flags,16961696- unsigned long fixed_rate,16971570 struct tegra_clk_pll_params *pll_params,16981698- struct tegra_clk_pll_freq_table *freq_table,16991571 spinlock_t *lock)17001572{17011573 struct tegra_clk_pll *pll;17021574 struct clk *clk;17031575 u32 val, val_aux;1704157617051705- pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params,17061706- TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock);15771577+ pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;15781578+ pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);17071579 if (IS_ERR(pll))17081580 return ERR_CAST(pll);17091581···17111587 val_aux = pll_readl(pll_params->aux_reg, pll);1712158817131589 if (val & PLL_BASE_ENABLE) {17141714- if (!(val_aux & PLLE_AUX_PLLRE_SEL))15901590+ if ((val_aux & PLLE_AUX_PLLRE_SEL) ||15911591+ (val_aux & PLLE_AUX_PLLP_SEL))17151592 WARN(1, "pll_e enabled with unsupported parent %s\n",17161716- (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");15931593+ (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :15941594+ "pll_re_vco");17171595 } else {17181718- val_aux |= PLLE_AUX_PLLRE_SEL;15961596+ val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);17191597 pll_writel(val, pll_params->aux_reg, pll);17201598 }1721159917221600 clk = _tegra_clk_register_pll(pll, name, parent_name, flags,17231601 &tegra_clk_plle_tegra114_ops);16021602+ if (IS_ERR(clk))16031603+ kfree(pll);16041604+16051605+ return clk;16061606+}16071607+#endif16081608+16091609+#ifdef CONFIG_ARCH_TEGRA_124_SOC16101610+const struct clk_ops tegra_clk_pllss_ops = {16111611+ .is_enabled = clk_pll_is_enabled,16121612+ .enable = clk_pll_iddq_enable,16131613+ .disable = clk_pll_iddq_disable,16141614+ .recalc_rate = clk_pll_recalc_rate,16151615+ .round_rate = clk_pll_ramp_round_rate,16161616+ .set_rate = clk_pllxc_set_rate,16171617+};16181618+16191619+struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,16201620+ void __iomem *clk_base, unsigned long flags,16211621+ struct tegra_clk_pll_params *pll_params,16221622+ spinlock_t *lock)16231623+{16241624+ struct tegra_clk_pll *pll;16251625+ struct clk *clk, *parent;16261626+ struct tegra_clk_pll_freq_table cfg;16271627+ unsigned long parent_rate;16281628+ u32 val;16291629+ int i;16301630+16311631+ if (!pll_params->div_nmp)16321632+ return ERR_PTR(-EINVAL);16331633+16341634+ parent = __clk_lookup(parent_name);16351635+ if (!parent) {16361636+ WARN(1, "parent clk %s of %s must be registered first\n",16371637+ name, parent_name);16381638+ return ERR_PTR(-EINVAL);16391639+ }16401640+16411641+ pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;16421642+ pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);16431643+ if (IS_ERR(pll))16441644+ return ERR_CAST(pll);16451645+16461646+ val = pll_readl_base(pll);16471647+ val &= ~PLLSS_REF_SRC_SEL_MASK;16481648+ pll_writel_base(val, pll);16491649+16501650+ parent_rate = __clk_get_rate(parent);16511651+16521652+ pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);16531653+16541654+ /* initialize PLL to minimum rate */16551655+16561656+ cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);16571657+ cfg.n = cfg.m * pll_params->vco_min / parent_rate;16581658+16591659+ for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)16601660+ ;16611661+ if (!i) {16621662+ kfree(pll);16631663+ return ERR_PTR(-EINVAL);16641664+ }16651665+16661666+ cfg.p = pll_params->pdiv_tohw[i-1].hw_val;16671667+16681668+ _update_pll_mnp(pll, &cfg);16691669+16701670+ pll_writel_misc(PLLSS_MISC_DEFAULT, pll);16711671+ pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll);16721672+ pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll);16731673+ pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);16741674+16751675+ val = pll_readl_base(pll);16761676+ if (val & PLL_BASE_ENABLE) {16771677+ if (val & BIT(pll_params->iddq_bit_idx)) {16781678+ WARN(1, "%s is on but IDDQ set\n", name);16791679+ kfree(pll);16801680+ return ERR_PTR(-EINVAL);16811681+ }16821682+ } else16831683+ val |= BIT(pll_params->iddq_bit_idx);16841684+16851685+ val &= ~PLLSS_LOCK_OVERRIDE;16861686+ pll_writel_base(val, pll);16871687+16881688+ clk = _tegra_clk_register_pll(pll, name, parent_name, flags,16891689+ &tegra_clk_pllss_ops);16901690+17241691 if (IS_ERR(clk))17251692 kfree(pll);17261693
+215
drivers/clk/tegra/clk-tegra-audio.c
···11+/*22+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope it will be useful, but WITHOUT99+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1010+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1111+ * more details.1212+ *1313+ * You should have received a copy of the GNU General Public License1414+ * along with this program. If not, see <http://www.gnu.org/licenses/>.1515+ */1616+1717+#include <linux/io.h>1818+#include <linux/clk.h>1919+#include <linux/clk-provider.h>2020+#include <linux/of.h>2121+#include <linux/of_address.h>2222+#include <linux/delay.h>2323+#include <linux/export.h>2424+#include <linux/clk/tegra.h>2525+2626+#include "clk.h"2727+#include "clk-id.h"2828+2929+#define AUDIO_SYNC_CLK_I2S0 0x4a03030+#define AUDIO_SYNC_CLK_I2S1 0x4a43131+#define AUDIO_SYNC_CLK_I2S2 0x4a83232+#define AUDIO_SYNC_CLK_I2S3 0x4ac3333+#define AUDIO_SYNC_CLK_I2S4 0x4b03434+#define AUDIO_SYNC_CLK_SPDIF 0x4b43535+3636+#define AUDIO_SYNC_DOUBLER 0x49c3737+3838+#define PLLA_OUT 0xb43939+4040+struct tegra_sync_source_initdata {4141+ char *name;4242+ unsigned long rate;4343+ unsigned long max_rate;4444+ int clk_id;4545+};4646+4747+#define SYNC(_name) \4848+ {\4949+ .name = #_name,\5050+ .rate = 24000000,\5151+ .max_rate = 24000000,\5252+ .clk_id = tegra_clk_ ## _name,\5353+ }5454+5555+struct tegra_audio_clk_initdata {5656+ char *gate_name;5757+ char *mux_name;5858+ u32 offset;5959+ int gate_clk_id;6060+ int mux_clk_id;6161+};6262+6363+#define AUDIO(_name, _offset) \6464+ {\6565+ .gate_name = #_name,\6666+ .mux_name = #_name"_mux",\6767+ .offset = _offset,\6868+ .gate_clk_id = tegra_clk_ ## _name,\6969+ .mux_clk_id = tegra_clk_ ## _name ## _mux,\7070+ }7171+7272+struct tegra_audio2x_clk_initdata {7373+ char *parent;7474+ char *gate_name;7575+ char *name_2x;7676+ char *div_name;7777+ int clk_id;7878+ int clk_num;7979+ u8 div_offset;8080+};8181+8282+#define AUDIO2X(_name, _num, _offset) \8383+ {\8484+ .parent = #_name,\8585+ .gate_name = #_name"_2x",\8686+ .name_2x = #_name"_doubler",\8787+ .div_name = #_name"_div",\8888+ .clk_id = tegra_clk_ ## _name ## _2x,\8989+ .clk_num = _num,\9090+ .div_offset = _offset,\9191+ }9292+9393+static DEFINE_SPINLOCK(clk_doubler_lock);9494+9595+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",9696+ "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",9797+};9898+9999+static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {100100+ SYNC(spdif_in_sync),101101+ SYNC(i2s0_sync),102102+ SYNC(i2s1_sync),103103+ SYNC(i2s2_sync),104104+ SYNC(i2s3_sync),105105+ SYNC(i2s4_sync),106106+ SYNC(vimclk_sync),107107+};108108+109109+static struct tegra_audio_clk_initdata audio_clks[] = {110110+ AUDIO(audio0, AUDIO_SYNC_CLK_I2S0),111111+ AUDIO(audio1, AUDIO_SYNC_CLK_I2S1),112112+ AUDIO(audio2, AUDIO_SYNC_CLK_I2S2),113113+ AUDIO(audio3, AUDIO_SYNC_CLK_I2S3),114114+ AUDIO(audio4, AUDIO_SYNC_CLK_I2S4),115115+ AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),116116+};117117+118118+static struct tegra_audio2x_clk_initdata audio2x_clks[] = {119119+ AUDIO2X(audio0, 113, 24),120120+ AUDIO2X(audio1, 114, 25),121121+ AUDIO2X(audio2, 115, 26),122122+ AUDIO2X(audio3, 116, 27),123123+ AUDIO2X(audio4, 117, 28),124124+ AUDIO2X(spdif, 118, 29),125125+};126126+127127+void __init tegra_audio_clk_init(void __iomem *clk_base,128128+ void __iomem *pmc_base, struct tegra_clk *tegra_clks,129129+ struct tegra_clk_pll_params *pll_a_params)130130+{131131+ struct clk *clk;132132+ struct clk **dt_clk;133133+ int i;134134+135135+ /* PLLA */136136+ dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);137137+ if (dt_clk) {138138+ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,139139+ pmc_base, 0, pll_a_params, NULL);140140+ *dt_clk = clk;141141+ }142142+143143+ /* PLLA_OUT0 */144144+ dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks);145145+ if (dt_clk) {146146+ clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",147147+ clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,148148+ 8, 8, 1, NULL);149149+ clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",150150+ clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |151151+ CLK_SET_RATE_PARENT, 0, NULL);152152+ *dt_clk = clk;153153+ }154154+155155+ for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) {156156+ struct tegra_sync_source_initdata *data;157157+158158+ data = &sync_source_clks[i];159159+160160+ dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);161161+ if (!dt_clk)162162+ continue;163163+164164+ clk = tegra_clk_register_sync_source(data->name,165165+ data->rate, data->max_rate);166166+ *dt_clk = clk;167167+ }168168+169169+ for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {170170+ struct tegra_audio_clk_initdata *data;171171+172172+ data = &audio_clks[i];173173+ dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);174174+175175+ if (!dt_clk)176176+ continue;177177+ clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,178178+ ARRAY_SIZE(mux_audio_sync_clk),179179+ CLK_SET_RATE_NO_REPARENT,180180+ clk_base + data->offset, 0, 3, 0,181181+ NULL);182182+ *dt_clk = clk;183183+184184+ dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);185185+ if (!dt_clk)186186+ continue;187187+188188+ clk = clk_register_gate(NULL, data->gate_name, data->mux_name,189189+ 0, clk_base + data->offset, 4,190190+ CLK_GATE_SET_TO_DISABLE, NULL);191191+ *dt_clk = clk;192192+ }193193+194194+ for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {195195+ struct tegra_audio2x_clk_initdata *data;196196+197197+ data = &audio2x_clks[i];198198+ dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);199199+ if (!dt_clk)200200+ continue;201201+202202+ clk = clk_register_fixed_factor(NULL, data->name_2x,203203+ data->parent, CLK_SET_RATE_PARENT, 2, 1);204204+ clk = tegra_clk_register_divider(data->div_name,205205+ data->name_2x, clk_base + AUDIO_SYNC_DOUBLER,206206+ 0, 0, data->div_offset, 1, 0,207207+ &clk_doubler_lock);208208+ clk = tegra_clk_register_periph_gate(data->gate_name,209209+ data->div_name, TEGRA_PERIPH_NO_RESET,210210+ clk_base, CLK_SET_RATE_PARENT, data->clk_num,211211+ periph_clk_enb_refcnt);212212+ *dt_clk = clk;213213+ }214214+}215215+
+111
drivers/clk/tegra/clk-tegra-fixed.c
···11+/*22+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope it will be useful, but WITHOUT99+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1010+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1111+ * more details.1212+ *1313+ * You should have received a copy of the GNU General Public License1414+ * along with this program. If not, see <http://www.gnu.org/licenses/>.1515+ */1616+1717+#include <linux/io.h>1818+#include <linux/clk.h>1919+#include <linux/clk-provider.h>2020+#include <linux/of.h>2121+#include <linux/of_address.h>2222+#include <linux/delay.h>2323+#include <linux/export.h>2424+#include <linux/clk/tegra.h>2525+2626+#include "clk.h"2727+#include "clk-id.h"2828+2929+#define OSC_CTRL 0x503030+#define OSC_CTRL_OSC_FREQ_SHIFT 283131+#define OSC_CTRL_PLL_REF_DIV_SHIFT 263232+3333+int __init tegra_osc_clk_init(void __iomem *clk_base,3434+ struct tegra_clk *tegra_clks,3535+ unsigned long *input_freqs, int num,3636+ unsigned long *osc_freq,3737+ unsigned long *pll_ref_freq)3838+{3939+ struct clk *clk;4040+ struct clk **dt_clk;4141+ u32 val, pll_ref_div;4242+ unsigned osc_idx;4343+4444+ val = readl_relaxed(clk_base + OSC_CTRL);4545+ osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;4646+4747+ if (osc_idx < num)4848+ *osc_freq = input_freqs[osc_idx];4949+ else5050+ *osc_freq = 0;5151+5252+ if (!*osc_freq) {5353+ WARN_ON(1);5454+ return -EINVAL;5555+ }5656+5757+ dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);5858+ if (!dt_clk)5959+ return 0;6060+6161+ clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,6262+ *osc_freq);6363+ *dt_clk = clk;6464+6565+ /* pll_ref */6666+ val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;6767+ pll_ref_div = 1 << val;6868+ dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);6969+ if (!dt_clk)7070+ return 0;7171+7272+ clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",7373+ 0, 1, pll_ref_div);7474+ *dt_clk = clk;7575+7676+ if (pll_ref_freq)7777+ *pll_ref_freq = *osc_freq / pll_ref_div;7878+7979+ return 0;8080+}8181+8282+void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)8383+{8484+ struct clk *clk;8585+ struct clk **dt_clk;8686+8787+ /* clk_32k */8888+ dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);8989+ if (dt_clk) {9090+ clk = clk_register_fixed_rate(NULL, "clk_32k", NULL,9191+ CLK_IS_ROOT, 32768);9292+ *dt_clk = clk;9393+ }9494+9595+ /* clk_m_div2 */9696+ dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks);9797+ if (dt_clk) {9898+ clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",9999+ CLK_SET_RATE_PARENT, 1, 2);100100+ *dt_clk = clk;101101+ }102102+103103+ /* clk_m_div4 */104104+ dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks);105105+ if (dt_clk) {106106+ clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",107107+ CLK_SET_RATE_PARENT, 1, 4);108108+ *dt_clk = clk;109109+ }110110+}111111+