956 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#include <linux/clk.h>4#include <linux/clkdev.h>5#include <linux/clk-provider.h>6#include <linux/delay.h>7#include <linux/err.h>8#include <linux/io.h>9#include <linux/math64.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/platform_device.h>13#include <linux/property.h>14#include <linux/string.h>15 16#define ADPLL_PLLSS_MMR_LOCK_OFFSET 0x00 /* Managed by MPPULL */17#define ADPLL_PLLSS_MMR_LOCK_ENABLED 0x1f125B6418#define ADPLL_PLLSS_MMR_UNLOCK_MAGIC 0x1eda4c3d19 20#define ADPLL_PWRCTRL_OFFSET 0x0021#define ADPLL_PWRCTRL_PONIN 522#define ADPLL_PWRCTRL_PGOODIN 423#define ADPLL_PWRCTRL_RET 324#define ADPLL_PWRCTRL_ISORET 225#define ADPLL_PWRCTRL_ISOSCAN 126#define ADPLL_PWRCTRL_OFFMODE 027 28#define ADPLL_CLKCTRL_OFFSET 0x0429#define ADPLL_CLKCTRL_CLKDCOLDOEN 2930#define ADPLL_CLKCTRL_IDLE 2331#define ADPLL_CLKCTRL_CLKOUTEN 2032#define ADPLL_CLKINPHIFSEL_ADPLL_S 19 /* REVISIT: which bit? */33#define ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ 1934#define ADPLL_CLKCTRL_ULOWCLKEN 1835#define ADPLL_CLKCTRL_CLKDCOLDOPWDNZ 1736#define ADPLL_CLKCTRL_M2PWDNZ 1637#define ADPLL_CLKCTRL_M3PWDNZ_ADPLL_S 1538#define ADPLL_CLKCTRL_LOWCURRSTDBY_ADPLL_S 1339#define ADPLL_CLKCTRL_LPMODE_ADPLL_S 1240#define ADPLL_CLKCTRL_REGM4XEN_ADPLL_S 1041#define ADPLL_CLKCTRL_SELFREQDCO_ADPLL_LJ 1042#define ADPLL_CLKCTRL_TINITZ 043 44#define ADPLL_TENABLE_OFFSET 0x0845#define ADPLL_TENABLEDIV_OFFSET 0x8c46 47#define ADPLL_M2NDIV_OFFSET 0x1048#define ADPLL_M2NDIV_M2 1649#define ADPLL_M2NDIV_M2_ADPLL_S_WIDTH 550#define ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH 751 52#define ADPLL_MN2DIV_OFFSET 0x1453#define ADPLL_MN2DIV_N2 1654 55#define ADPLL_FRACDIV_OFFSET 0x1856#define ADPLL_FRACDIV_REGSD 2457#define ADPLL_FRACDIV_FRACTIONALM 058#define ADPLL_FRACDIV_FRACTIONALM_MASK 0x3ffff59 60#define ADPLL_BWCTRL_OFFSET 0x1c61#define ADPLL_BWCTRL_BWCONTROL 162#define ADPLL_BWCTRL_BW_INCR_DECRZ 063 64#define ADPLL_RESERVED_OFFSET 0x2065 66#define ADPLL_STATUS_OFFSET 0x2467#define ADPLL_STATUS_PONOUT 3168#define ADPLL_STATUS_PGOODOUT 3069#define ADPLL_STATUS_LDOPWDN 2970#define ADPLL_STATUS_RECAL_BSTATUS3 2871#define ADPLL_STATUS_RECAL_OPPIN 2772#define ADPLL_STATUS_PHASELOCK 1073#define ADPLL_STATUS_FREQLOCK 974#define ADPLL_STATUS_BYPASSACK 875#define ADPLL_STATUS_LOSSREF 676#define ADPLL_STATUS_CLKOUTENACK 577#define ADPLL_STATUS_LOCK2 478#define ADPLL_STATUS_M2CHANGEACK 379#define ADPLL_STATUS_HIGHJITTER 180#define ADPLL_STATUS_BYPASS 081#define ADPLL_STATUS_PREPARED_MASK (BIT(ADPLL_STATUS_PHASELOCK) | \82 BIT(ADPLL_STATUS_FREQLOCK))83 84#define ADPLL_M3DIV_OFFSET 0x28 /* Only on MPUPLL */85#define ADPLL_M3DIV_M3 086#define ADPLL_M3DIV_M3_WIDTH 587#define ADPLL_M3DIV_M3_MASK 0x1f88 89#define ADPLL_RAMPCTRL_OFFSET 0x2c /* Only on MPUPLL */90#define ADPLL_RAMPCTRL_CLKRAMPLEVEL 1991#define ADPLL_RAMPCTRL_CLKRAMPRATE 1692#define ADPLL_RAMPCTRL_RELOCK_RAMP_EN 093 94#define MAX_ADPLL_INPUTS 395#define MAX_ADPLL_OUTPUTS 496#define ADPLL_MAX_RETRIES 597 98#define to_dco(_hw) container_of(_hw, struct ti_adpll_dco_data, hw)99#define to_adpll(_hw) container_of(_hw, struct ti_adpll_data, dco)100#define to_clkout(_hw) container_of(_hw, struct ti_adpll_clkout_data, hw)101 102enum ti_adpll_clocks {103 TI_ADPLL_DCO,104 TI_ADPLL_DCO_GATE,105 TI_ADPLL_N2,106 TI_ADPLL_M2,107 TI_ADPLL_M2_GATE,108 TI_ADPLL_BYPASS,109 TI_ADPLL_HIF,110 TI_ADPLL_DIV2,111 TI_ADPLL_CLKOUT,112 TI_ADPLL_CLKOUT2,113 TI_ADPLL_M3,114};115 116#define TI_ADPLL_NR_CLOCKS (TI_ADPLL_M3 + 1)117 118enum ti_adpll_inputs {119 TI_ADPLL_CLKINP,120 TI_ADPLL_CLKINPULOW,121 TI_ADPLL_CLKINPHIF,122};123 124enum ti_adpll_s_outputs {125 TI_ADPLL_S_DCOCLKLDO,126 TI_ADPLL_S_CLKOUT,127 TI_ADPLL_S_CLKOUTX2,128 TI_ADPLL_S_CLKOUTHIF,129};130 131enum ti_adpll_lj_outputs {132 TI_ADPLL_LJ_CLKDCOLDO,133 TI_ADPLL_LJ_CLKOUT,134 TI_ADPLL_LJ_CLKOUTLDO,135};136 137struct ti_adpll_platform_data {138 const bool is_type_s;139 const int nr_max_inputs;140 const int nr_max_outputs;141 const int output_index;142};143 144struct ti_adpll_clock {145 struct clk *clk;146 struct clk_lookup *cl;147 void (*unregister)(struct clk *clk);148};149 150struct ti_adpll_dco_data {151 struct clk_hw hw;152};153 154struct ti_adpll_clkout_data {155 struct ti_adpll_data *adpll;156 struct clk_gate gate;157 struct clk_hw hw;158};159 160struct ti_adpll_data {161 struct device *dev;162 const struct ti_adpll_platform_data *c;163 struct device_node *np;164 unsigned long pa;165 void __iomem *iobase;166 void __iomem *regs;167 spinlock_t lock; /* For ADPLL shared register access */168 const char *parent_names[MAX_ADPLL_INPUTS];169 struct clk *parent_clocks[MAX_ADPLL_INPUTS];170 struct ti_adpll_clock *clocks;171 struct clk_onecell_data outputs;172 struct ti_adpll_dco_data dco;173};174 175static const char *ti_adpll_clk_get_name(struct ti_adpll_data *d,176 int output_index,177 const char *postfix)178{179 const char *name;180 int err;181 182 if (output_index >= 0) {183 err = of_property_read_string_index(d->np,184 "clock-output-names",185 output_index,186 &name);187 if (err)188 return NULL;189 } else {190 name = devm_kasprintf(d->dev, GFP_KERNEL, "%08lx.adpll.%s",191 d->pa, postfix);192 }193 194 return name;195}196 197#define ADPLL_MAX_CON_ID 16 /* See MAX_CON_ID */198 199static int ti_adpll_setup_clock(struct ti_adpll_data *d, struct clk *clock,200 int index, int output_index, const char *name,201 void (*unregister)(struct clk *clk))202{203 struct clk_lookup *cl;204 const char *postfix = NULL;205 char con_id[ADPLL_MAX_CON_ID];206 207 d->clocks[index].clk = clock;208 d->clocks[index].unregister = unregister;209 210 /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */211 postfix = strrchr(name, '.');212 if (postfix && strlen(postfix) > 1) {213 if (strlen(postfix) > ADPLL_MAX_CON_ID)214 dev_warn(d->dev, "clock %s con_id lookup may fail\n",215 name);216 snprintf(con_id, 16, "pll%03lx%s", d->pa & 0xfff, postfix + 1);217 cl = clkdev_create(clock, con_id, NULL);218 if (!cl)219 return -ENOMEM;220 d->clocks[index].cl = cl;221 } else {222 dev_warn(d->dev, "no con_id for clock %s\n", name);223 }224 225 if (output_index < 0)226 return 0;227 228 d->outputs.clks[output_index] = clock;229 d->outputs.clk_num++;230 231 return 0;232}233 234static int ti_adpll_init_divider(struct ti_adpll_data *d,235 enum ti_adpll_clocks index,236 int output_index, char *name,237 struct clk *parent_clock,238 void __iomem *reg,239 u8 shift, u8 width,240 u8 clk_divider_flags)241{242 const char *child_name;243 const char *parent_name;244 struct clk *clock;245 246 child_name = ti_adpll_clk_get_name(d, output_index, name);247 if (!child_name)248 return -EINVAL;249 250 parent_name = __clk_get_name(parent_clock);251 clock = clk_register_divider(d->dev, child_name, parent_name, 0,252 reg, shift, width, clk_divider_flags,253 &d->lock);254 if (IS_ERR(clock)) {255 dev_err(d->dev, "failed to register divider %s: %li\n",256 name, PTR_ERR(clock));257 return PTR_ERR(clock);258 }259 260 return ti_adpll_setup_clock(d, clock, index, output_index, child_name,261 clk_unregister_divider);262}263 264static int ti_adpll_init_mux(struct ti_adpll_data *d,265 enum ti_adpll_clocks index,266 char *name, struct clk *clk0,267 struct clk *clk1,268 void __iomem *reg,269 u8 shift)270{271 const char *child_name;272 const char *parents[2];273 struct clk *clock;274 275 child_name = ti_adpll_clk_get_name(d, -ENODEV, name);276 if (!child_name)277 return -ENOMEM;278 parents[0] = __clk_get_name(clk0);279 parents[1] = __clk_get_name(clk1);280 clock = clk_register_mux(d->dev, child_name, parents, 2, 0,281 reg, shift, 1, 0, &d->lock);282 if (IS_ERR(clock)) {283 dev_err(d->dev, "failed to register mux %s: %li\n",284 name, PTR_ERR(clock));285 return PTR_ERR(clock);286 }287 288 return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name,289 clk_unregister_mux);290}291 292static int ti_adpll_init_gate(struct ti_adpll_data *d,293 enum ti_adpll_clocks index,294 int output_index, char *name,295 struct clk *parent_clock,296 void __iomem *reg,297 u8 bit_idx,298 u8 clk_gate_flags)299{300 const char *child_name;301 const char *parent_name;302 struct clk *clock;303 304 child_name = ti_adpll_clk_get_name(d, output_index, name);305 if (!child_name)306 return -EINVAL;307 308 parent_name = __clk_get_name(parent_clock);309 clock = clk_register_gate(d->dev, child_name, parent_name, 0,310 reg, bit_idx, clk_gate_flags,311 &d->lock);312 if (IS_ERR(clock)) {313 dev_err(d->dev, "failed to register gate %s: %li\n",314 name, PTR_ERR(clock));315 return PTR_ERR(clock);316 }317 318 return ti_adpll_setup_clock(d, clock, index, output_index, child_name,319 clk_unregister_gate);320}321 322static int ti_adpll_init_fixed_factor(struct ti_adpll_data *d,323 enum ti_adpll_clocks index,324 char *name,325 struct clk *parent_clock,326 unsigned int mult,327 unsigned int div)328{329 const char *child_name;330 const char *parent_name;331 struct clk *clock;332 333 child_name = ti_adpll_clk_get_name(d, -ENODEV, name);334 if (!child_name)335 return -ENOMEM;336 337 parent_name = __clk_get_name(parent_clock);338 clock = clk_register_fixed_factor(d->dev, child_name, parent_name,339 0, mult, div);340 if (IS_ERR(clock))341 return PTR_ERR(clock);342 343 return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name,344 clk_unregister);345}346 347static void ti_adpll_set_idle_bypass(struct ti_adpll_data *d)348{349 unsigned long flags;350 u32 v;351 352 spin_lock_irqsave(&d->lock, flags);353 v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);354 v |= BIT(ADPLL_CLKCTRL_IDLE);355 writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET);356 spin_unlock_irqrestore(&d->lock, flags);357}358 359static void ti_adpll_clear_idle_bypass(struct ti_adpll_data *d)360{361 unsigned long flags;362 u32 v;363 364 spin_lock_irqsave(&d->lock, flags);365 v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);366 v &= ~BIT(ADPLL_CLKCTRL_IDLE);367 writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET);368 spin_unlock_irqrestore(&d->lock, flags);369}370 371static bool ti_adpll_clock_is_bypass(struct ti_adpll_data *d)372{373 u32 v;374 375 v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET);376 377 return v & BIT(ADPLL_STATUS_BYPASS);378}379 380/*381 * Locked and bypass are not actually mutually exclusive: if you only care382 * about the DCO clock and not CLKOUT you can clear M2PWDNZ before enabling383 * the PLL, resulting in status (FREQLOCK | PHASELOCK | BYPASS) after lock.384 */385static bool ti_adpll_is_locked(struct ti_adpll_data *d)386{387 u32 v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET);388 389 return (v & ADPLL_STATUS_PREPARED_MASK) == ADPLL_STATUS_PREPARED_MASK;390}391 392static int ti_adpll_wait_lock(struct ti_adpll_data *d)393{394 int retries = ADPLL_MAX_RETRIES;395 396 do {397 if (ti_adpll_is_locked(d))398 return 0;399 usleep_range(200, 300);400 } while (retries--);401 402 dev_err(d->dev, "pll failed to lock\n");403 return -ETIMEDOUT;404}405 406static int ti_adpll_prepare(struct clk_hw *hw)407{408 struct ti_adpll_dco_data *dco = to_dco(hw);409 struct ti_adpll_data *d = to_adpll(dco);410 411 ti_adpll_clear_idle_bypass(d);412 ti_adpll_wait_lock(d);413 414 return 0;415}416 417static void ti_adpll_unprepare(struct clk_hw *hw)418{419 struct ti_adpll_dco_data *dco = to_dco(hw);420 struct ti_adpll_data *d = to_adpll(dco);421 422 ti_adpll_set_idle_bypass(d);423}424 425static int ti_adpll_is_prepared(struct clk_hw *hw)426{427 struct ti_adpll_dco_data *dco = to_dco(hw);428 struct ti_adpll_data *d = to_adpll(dco);429 430 return ti_adpll_is_locked(d);431}432 433/*434 * Note that the DCO clock is never subject to bypass: if the PLL is off,435 * dcoclk is low.436 */437static unsigned long ti_adpll_recalc_rate(struct clk_hw *hw,438 unsigned long parent_rate)439{440 struct ti_adpll_dco_data *dco = to_dco(hw);441 struct ti_adpll_data *d = to_adpll(dco);442 u32 frac_m, divider, v;443 u64 rate;444 unsigned long flags;445 446 if (ti_adpll_clock_is_bypass(d))447 return 0;448 449 spin_lock_irqsave(&d->lock, flags);450 frac_m = readl_relaxed(d->regs + ADPLL_FRACDIV_OFFSET);451 frac_m &= ADPLL_FRACDIV_FRACTIONALM_MASK;452 rate = (u64)readw_relaxed(d->regs + ADPLL_MN2DIV_OFFSET) << 18;453 rate += frac_m;454 rate *= parent_rate;455 divider = (readw_relaxed(d->regs + ADPLL_M2NDIV_OFFSET) + 1) << 18;456 spin_unlock_irqrestore(&d->lock, flags);457 458 do_div(rate, divider);459 460 if (d->c->is_type_s) {461 v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);462 if (v & BIT(ADPLL_CLKCTRL_REGM4XEN_ADPLL_S))463 rate *= 4;464 rate *= 2;465 }466 467 return rate;468}469 470/* PLL parent is always clkinp, bypass only affects the children */471static u8 ti_adpll_get_parent(struct clk_hw *hw)472{473 return 0;474}475 476static const struct clk_ops ti_adpll_ops = {477 .prepare = ti_adpll_prepare,478 .unprepare = ti_adpll_unprepare,479 .is_prepared = ti_adpll_is_prepared,480 .recalc_rate = ti_adpll_recalc_rate,481 .get_parent = ti_adpll_get_parent,482};483 484static int ti_adpll_init_dco(struct ti_adpll_data *d)485{486 struct clk_init_data init;487 struct clk *clock;488 const char *postfix;489 int width, err;490 491 d->outputs.clks = devm_kcalloc(d->dev,492 MAX_ADPLL_OUTPUTS,493 sizeof(struct clk *),494 GFP_KERNEL);495 if (!d->outputs.clks)496 return -ENOMEM;497 498 if (d->c->output_index < 0)499 postfix = "dco";500 else501 postfix = NULL;502 503 init.name = ti_adpll_clk_get_name(d, d->c->output_index, postfix);504 if (!init.name)505 return -EINVAL;506 507 init.parent_names = d->parent_names;508 init.num_parents = d->c->nr_max_inputs;509 init.ops = &ti_adpll_ops;510 init.flags = CLK_GET_RATE_NOCACHE;511 d->dco.hw.init = &init;512 513 if (d->c->is_type_s)514 width = 5;515 else516 width = 4;517 518 /* Internal input clock divider N2 */519 err = ti_adpll_init_divider(d, TI_ADPLL_N2, -ENODEV, "n2",520 d->parent_clocks[TI_ADPLL_CLKINP],521 d->regs + ADPLL_MN2DIV_OFFSET,522 ADPLL_MN2DIV_N2, width, 0);523 if (err)524 return err;525 526 clock = devm_clk_register(d->dev, &d->dco.hw);527 if (IS_ERR(clock))528 return PTR_ERR(clock);529 530 return ti_adpll_setup_clock(d, clock, TI_ADPLL_DCO, d->c->output_index,531 init.name, NULL);532}533 534static int ti_adpll_clkout_enable(struct clk_hw *hw)535{536 struct ti_adpll_clkout_data *co = to_clkout(hw);537 struct clk_hw *gate_hw = &co->gate.hw;538 539 __clk_hw_set_clk(gate_hw, hw);540 541 return clk_gate_ops.enable(gate_hw);542}543 544static void ti_adpll_clkout_disable(struct clk_hw *hw)545{546 struct ti_adpll_clkout_data *co = to_clkout(hw);547 struct clk_hw *gate_hw = &co->gate.hw;548 549 __clk_hw_set_clk(gate_hw, hw);550 clk_gate_ops.disable(gate_hw);551}552 553static int ti_adpll_clkout_is_enabled(struct clk_hw *hw)554{555 struct ti_adpll_clkout_data *co = to_clkout(hw);556 struct clk_hw *gate_hw = &co->gate.hw;557 558 __clk_hw_set_clk(gate_hw, hw);559 560 return clk_gate_ops.is_enabled(gate_hw);561}562 563/* Setting PLL bypass puts clkout and clkoutx2 into bypass */564static u8 ti_adpll_clkout_get_parent(struct clk_hw *hw)565{566 struct ti_adpll_clkout_data *co = to_clkout(hw);567 struct ti_adpll_data *d = co->adpll;568 569 return ti_adpll_clock_is_bypass(d);570}571 572static int ti_adpll_init_clkout(struct ti_adpll_data *d,573 enum ti_adpll_clocks index,574 int output_index, int gate_bit,575 char *name, struct clk *clk0,576 struct clk *clk1)577{578 struct ti_adpll_clkout_data *co;579 struct clk_init_data init;580 struct clk_ops *ops;581 const char *parent_names[2];582 const char *child_name;583 struct clk *clock;584 int err;585 586 co = devm_kzalloc(d->dev, sizeof(*co), GFP_KERNEL);587 if (!co)588 return -ENOMEM;589 co->adpll = d;590 591 err = of_property_read_string_index(d->np,592 "clock-output-names",593 output_index,594 &child_name);595 if (err)596 return err;597 598 ops = devm_kzalloc(d->dev, sizeof(*ops), GFP_KERNEL);599 if (!ops)600 return -ENOMEM;601 602 init.name = child_name;603 init.ops = ops;604 init.flags = 0;605 co->hw.init = &init;606 parent_names[0] = __clk_get_name(clk0);607 parent_names[1] = __clk_get_name(clk1);608 init.parent_names = parent_names;609 init.num_parents = 2;610 611 ops->get_parent = ti_adpll_clkout_get_parent;612 ops->determine_rate = __clk_mux_determine_rate;613 if (gate_bit) {614 co->gate.lock = &d->lock;615 co->gate.reg = d->regs + ADPLL_CLKCTRL_OFFSET;616 co->gate.bit_idx = gate_bit;617 ops->enable = ti_adpll_clkout_enable;618 ops->disable = ti_adpll_clkout_disable;619 ops->is_enabled = ti_adpll_clkout_is_enabled;620 }621 622 clock = devm_clk_register(d->dev, &co->hw);623 if (IS_ERR(clock)) {624 dev_err(d->dev, "failed to register output %s: %li\n",625 name, PTR_ERR(clock));626 return PTR_ERR(clock);627 }628 629 return ti_adpll_setup_clock(d, clock, index, output_index, child_name,630 NULL);631}632 633static int ti_adpll_init_children_adpll_s(struct ti_adpll_data *d)634{635 int err;636 637 if (!d->c->is_type_s)638 return 0;639 640 /* Internal mux, sources from divider N2 or clkinpulow */641 err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass",642 d->clocks[TI_ADPLL_N2].clk,643 d->parent_clocks[TI_ADPLL_CLKINPULOW],644 d->regs + ADPLL_CLKCTRL_OFFSET,645 ADPLL_CLKCTRL_ULOWCLKEN);646 if (err)647 return err;648 649 /* Internal divider M2, sources DCO */650 err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV, "m2",651 d->clocks[TI_ADPLL_DCO].clk,652 d->regs + ADPLL_M2NDIV_OFFSET,653 ADPLL_M2NDIV_M2,654 ADPLL_M2NDIV_M2_ADPLL_S_WIDTH,655 CLK_DIVIDER_ONE_BASED);656 if (err)657 return err;658 659 /* Internal fixed divider, after M2 before clkout */660 err = ti_adpll_init_fixed_factor(d, TI_ADPLL_DIV2, "div2",661 d->clocks[TI_ADPLL_M2].clk,662 1, 2);663 if (err)664 return err;665 666 /* Output clkout with a mux and gate, sources from div2 or bypass */667 err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT,668 ADPLL_CLKCTRL_CLKOUTEN, "clkout",669 d->clocks[TI_ADPLL_DIV2].clk,670 d->clocks[TI_ADPLL_BYPASS].clk);671 if (err)672 return err;673 674 /* Output clkoutx2 with a mux and gate, sources from M2 or bypass */675 err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT2, TI_ADPLL_S_CLKOUTX2, 0,676 "clkout2", d->clocks[TI_ADPLL_M2].clk,677 d->clocks[TI_ADPLL_BYPASS].clk);678 if (err)679 return err;680 681 /* Internal mux, sources from DCO and clkinphif */682 if (d->parent_clocks[TI_ADPLL_CLKINPHIF]) {683 err = ti_adpll_init_mux(d, TI_ADPLL_HIF, "hif",684 d->clocks[TI_ADPLL_DCO].clk,685 d->parent_clocks[TI_ADPLL_CLKINPHIF],686 d->regs + ADPLL_CLKCTRL_OFFSET,687 ADPLL_CLKINPHIFSEL_ADPLL_S);688 if (err)689 return err;690 }691 692 /* Output clkouthif with a divider M3, sources from hif */693 err = ti_adpll_init_divider(d, TI_ADPLL_M3, TI_ADPLL_S_CLKOUTHIF, "m3",694 d->clocks[TI_ADPLL_HIF].clk,695 d->regs + ADPLL_M3DIV_OFFSET,696 ADPLL_M3DIV_M3,697 ADPLL_M3DIV_M3_WIDTH,698 CLK_DIVIDER_ONE_BASED);699 if (err)700 return err;701 702 /* Output clock dcoclkldo is the DCO */703 704 return 0;705}706 707static int ti_adpll_init_children_adpll_lj(struct ti_adpll_data *d)708{709 int err;710 711 if (d->c->is_type_s)712 return 0;713 714 /* Output clkdcoldo, gated output of DCO */715 err = ti_adpll_init_gate(d, TI_ADPLL_DCO_GATE, TI_ADPLL_LJ_CLKDCOLDO,716 "clkdcoldo", d->clocks[TI_ADPLL_DCO].clk,717 d->regs + ADPLL_CLKCTRL_OFFSET,718 ADPLL_CLKCTRL_CLKDCOLDOEN, 0);719 if (err)720 return err;721 722 /* Internal divider M2, sources from DCO */723 err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV,724 "m2", d->clocks[TI_ADPLL_DCO].clk,725 d->regs + ADPLL_M2NDIV_OFFSET,726 ADPLL_M2NDIV_M2,727 ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH,728 CLK_DIVIDER_ONE_BASED);729 if (err)730 return err;731 732 /* Output clkoutldo, gated output of M2 */733 err = ti_adpll_init_gate(d, TI_ADPLL_M2_GATE, TI_ADPLL_LJ_CLKOUTLDO,734 "clkoutldo", d->clocks[TI_ADPLL_M2].clk,735 d->regs + ADPLL_CLKCTRL_OFFSET,736 ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ,737 0);738 if (err)739 return err;740 741 /* Internal mux, sources from divider N2 or clkinpulow */742 err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass",743 d->clocks[TI_ADPLL_N2].clk,744 d->parent_clocks[TI_ADPLL_CLKINPULOW],745 d->regs + ADPLL_CLKCTRL_OFFSET,746 ADPLL_CLKCTRL_ULOWCLKEN);747 if (err)748 return err;749 750 /* Output clkout, sources M2 or bypass */751 err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT,752 ADPLL_CLKCTRL_CLKOUTEN, "clkout",753 d->clocks[TI_ADPLL_M2].clk,754 d->clocks[TI_ADPLL_BYPASS].clk);755 if (err)756 return err;757 758 return 0;759}760 761static void ti_adpll_free_resources(struct ti_adpll_data *d)762{763 int i;764 765 for (i = TI_ADPLL_M3; i >= 0; i--) {766 struct ti_adpll_clock *ac = &d->clocks[i];767 768 if (!ac || IS_ERR_OR_NULL(ac->clk))769 continue;770 if (ac->cl)771 clkdev_drop(ac->cl);772 if (ac->unregister)773 ac->unregister(ac->clk);774 }775}776 777/* MPU PLL manages the lock register for all PLLs */778static void ti_adpll_unlock_all(void __iomem *reg)779{780 u32 v;781 782 v = readl_relaxed(reg);783 if (v == ADPLL_PLLSS_MMR_LOCK_ENABLED)784 writel_relaxed(ADPLL_PLLSS_MMR_UNLOCK_MAGIC, reg);785}786 787static int ti_adpll_init_registers(struct ti_adpll_data *d)788{789 int register_offset = 0;790 791 if (d->c->is_type_s) {792 register_offset = 8;793 ti_adpll_unlock_all(d->iobase + ADPLL_PLLSS_MMR_LOCK_OFFSET);794 }795 796 d->regs = d->iobase + register_offset + ADPLL_PWRCTRL_OFFSET;797 798 return 0;799}800 801static int ti_adpll_init_inputs(struct ti_adpll_data *d)802{803 static const char error[] = "need at least %i inputs";804 struct clk *clock;805 int nr_inputs;806 807 nr_inputs = of_clk_get_parent_count(d->np);808 if (nr_inputs < d->c->nr_max_inputs) {809 dev_err(d->dev, error, nr_inputs);810 return -EINVAL;811 }812 of_clk_parent_fill(d->np, d->parent_names, nr_inputs);813 814 clock = devm_clk_get(d->dev, d->parent_names[0]);815 if (IS_ERR(clock)) {816 dev_err(d->dev, "could not get clkinp\n");817 return PTR_ERR(clock);818 }819 d->parent_clocks[TI_ADPLL_CLKINP] = clock;820 821 clock = devm_clk_get(d->dev, d->parent_names[1]);822 if (IS_ERR(clock)) {823 dev_err(d->dev, "could not get clkinpulow clock\n");824 return PTR_ERR(clock);825 }826 d->parent_clocks[TI_ADPLL_CLKINPULOW] = clock;827 828 if (d->c->is_type_s) {829 clock = devm_clk_get(d->dev, d->parent_names[2]);830 if (IS_ERR(clock)) {831 dev_err(d->dev, "could not get clkinphif clock\n");832 return PTR_ERR(clock);833 }834 d->parent_clocks[TI_ADPLL_CLKINPHIF] = clock;835 }836 837 return 0;838}839 840static const struct ti_adpll_platform_data ti_adpll_type_s = {841 .is_type_s = true,842 .nr_max_inputs = MAX_ADPLL_INPUTS,843 .nr_max_outputs = MAX_ADPLL_OUTPUTS,844 .output_index = TI_ADPLL_S_DCOCLKLDO,845};846 847static const struct ti_adpll_platform_data ti_adpll_type_lj = {848 .is_type_s = false,849 .nr_max_inputs = MAX_ADPLL_INPUTS - 1,850 .nr_max_outputs = MAX_ADPLL_OUTPUTS - 1,851 .output_index = -EINVAL,852};853 854static const struct of_device_id ti_adpll_match[] = {855 { .compatible = "ti,dm814-adpll-s-clock", &ti_adpll_type_s },856 { .compatible = "ti,dm814-adpll-lj-clock", &ti_adpll_type_lj },857 {},858};859MODULE_DEVICE_TABLE(of, ti_adpll_match);860 861static int ti_adpll_probe(struct platform_device *pdev)862{863 struct device_node *node = pdev->dev.of_node;864 struct device *dev = &pdev->dev;865 struct ti_adpll_data *d;866 struct resource *res;867 int err;868 869 d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);870 if (!d)871 return -ENOMEM;872 d->dev = dev;873 d->np = node;874 d->c = device_get_match_data(dev);875 dev_set_drvdata(d->dev, d);876 spin_lock_init(&d->lock);877 878 d->iobase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);879 if (IS_ERR(d->iobase))880 return PTR_ERR(d->iobase);881 d->pa = res->start;882 883 err = ti_adpll_init_registers(d);884 if (err)885 return err;886 887 err = ti_adpll_init_inputs(d);888 if (err)889 return err;890 891 d->clocks = devm_kcalloc(d->dev,892 TI_ADPLL_NR_CLOCKS,893 sizeof(struct ti_adpll_clock),894 GFP_KERNEL);895 if (!d->clocks)896 return -ENOMEM;897 898 err = ti_adpll_init_dco(d);899 if (err) {900 dev_err(dev, "could not register dco: %i\n", err);901 goto free;902 }903 904 err = ti_adpll_init_children_adpll_s(d);905 if (err)906 goto free;907 err = ti_adpll_init_children_adpll_lj(d);908 if (err)909 goto free;910 911 err = of_clk_add_provider(d->np, of_clk_src_onecell_get, &d->outputs);912 if (err)913 goto free;914 915 return 0;916 917free:918 WARN_ON(1);919 ti_adpll_free_resources(d);920 921 return err;922}923 924static void ti_adpll_remove(struct platform_device *pdev)925{926 struct ti_adpll_data *d = dev_get_drvdata(&pdev->dev);927 928 ti_adpll_free_resources(d);929}930 931static struct platform_driver ti_adpll_driver = {932 .driver = {933 .name = "ti-adpll",934 .of_match_table = ti_adpll_match,935 },936 .probe = ti_adpll_probe,937 .remove = ti_adpll_remove,938};939 940static int __init ti_adpll_init(void)941{942 return platform_driver_register(&ti_adpll_driver);943}944core_initcall(ti_adpll_init);945 946static void __exit ti_adpll_exit(void)947{948 platform_driver_unregister(&ti_adpll_driver);949}950module_exit(ti_adpll_exit);951 952MODULE_DESCRIPTION("Clock driver for dm814x ADPLL");953MODULE_ALIAS("platform:dm814-adpll-clock");954MODULE_AUTHOR("Tony LIndgren <tony@atomide.com>");955MODULE_LICENSE("GPL v2");956