| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 2012 Freescale Semiconductor, Inc. |
|---|
| 3 | 4 | * Copyright 2012 Linaro Ltd. |
|---|
| 4 | | - * |
|---|
| 5 | | - * The code contained herein is licensed under the GNU General Public |
|---|
| 6 | | - * License. You may obtain a copy of the GNU General Public License |
|---|
| 7 | | - * Version 2 or later at the following locations: |
|---|
| 8 | | - * |
|---|
| 9 | | - * http://www.opensource.org/licenses/gpl-license.html |
|---|
| 10 | | - * http://www.gnu.org/copyleft/gpl.html |
|---|
| 11 | 5 | */ |
|---|
| 12 | 6 | |
|---|
| 13 | 7 | #include <linux/clk-provider.h> |
|---|
| 14 | 8 | #include <linux/delay.h> |
|---|
| 15 | 9 | #include <linux/io.h> |
|---|
| 10 | +#include <linux/iopoll.h> |
|---|
| 16 | 11 | #include <linux/slab.h> |
|---|
| 17 | 12 | #include <linux/jiffies.h> |
|---|
| 18 | 13 | #include <linux/err.h> |
|---|
| .. | .. |
|---|
| 20 | 15 | |
|---|
| 21 | 16 | #define PLL_NUM_OFFSET 0x10 |
|---|
| 22 | 17 | #define PLL_DENOM_OFFSET 0x20 |
|---|
| 18 | +#define PLL_IMX7_NUM_OFFSET 0x20 |
|---|
| 19 | +#define PLL_IMX7_DENOM_OFFSET 0x30 |
|---|
| 23 | 20 | |
|---|
| 24 | 21 | #define PLL_VF610_NUM_OFFSET 0x20 |
|---|
| 25 | 22 | #define PLL_VF610_DENOM_OFFSET 0x30 |
|---|
| .. | .. |
|---|
| 29 | 26 | #define IMX7_ENET_PLL_POWER (0x1 << 5) |
|---|
| 30 | 27 | #define IMX7_DDR_PLL_POWER (0x1 << 20) |
|---|
| 31 | 28 | |
|---|
| 29 | +#define PLL_LOCK_TIMEOUT 10000 |
|---|
| 30 | + |
|---|
| 32 | 31 | /** |
|---|
| 33 | 32 | * struct clk_pllv3 - IMX PLL clock version 3 |
|---|
| 34 | | - * @clk_hw: clock source |
|---|
| 33 | + * @hw: clock source |
|---|
| 35 | 34 | * @base: base address of PLL registers |
|---|
| 36 | 35 | * @power_bit: pll power bit mask |
|---|
| 37 | 36 | * @powerup_set: set power_bit to power up the PLL |
|---|
| 38 | 37 | * @div_mask: mask of divider bits |
|---|
| 39 | 38 | * @div_shift: shift of divider bits |
|---|
| 39 | + * @ref_clock: reference clock rate |
|---|
| 40 | + * @num_offset: num register offset |
|---|
| 41 | + * @denom_offset: denom register offset |
|---|
| 40 | 42 | * |
|---|
| 41 | 43 | * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 |
|---|
| 42 | 44 | * is actually a multiplier, and always sits at bit 0. |
|---|
| .. | .. |
|---|
| 49 | 51 | u32 div_mask; |
|---|
| 50 | 52 | u32 div_shift; |
|---|
| 51 | 53 | unsigned long ref_clock; |
|---|
| 54 | + u32 num_offset; |
|---|
| 55 | + u32 denom_offset; |
|---|
| 52 | 56 | }; |
|---|
| 53 | 57 | |
|---|
| 54 | 58 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) |
|---|
| 55 | 59 | |
|---|
| 56 | 60 | static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) |
|---|
| 57 | 61 | { |
|---|
| 58 | | - unsigned long timeout = jiffies + msecs_to_jiffies(10); |
|---|
| 59 | 62 | u32 val = readl_relaxed(pll->base) & pll->power_bit; |
|---|
| 60 | 63 | |
|---|
| 61 | 64 | /* No need to wait for lock when pll is not powered up */ |
|---|
| 62 | 65 | if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) |
|---|
| 63 | 66 | return 0; |
|---|
| 64 | 67 | |
|---|
| 65 | | - /* Wait for PLL to lock */ |
|---|
| 66 | | - do { |
|---|
| 67 | | - if (readl_relaxed(pll->base) & BM_PLL_LOCK) |
|---|
| 68 | | - break; |
|---|
| 69 | | - if (time_after(jiffies, timeout)) |
|---|
| 70 | | - break; |
|---|
| 71 | | - usleep_range(50, 500); |
|---|
| 72 | | - } while (1); |
|---|
| 73 | | - |
|---|
| 74 | | - return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT; |
|---|
| 68 | + return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK, |
|---|
| 69 | + 500, PLL_LOCK_TIMEOUT); |
|---|
| 75 | 70 | } |
|---|
| 76 | 71 | |
|---|
| 77 | 72 | static int clk_pllv3_prepare(struct clk_hw *hw) |
|---|
| .. | .. |
|---|
| 219 | 214 | unsigned long parent_rate) |
|---|
| 220 | 215 | { |
|---|
| 221 | 216 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
|---|
| 222 | | - u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); |
|---|
| 223 | | - u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); |
|---|
| 217 | + u32 mfn = readl_relaxed(pll->base + pll->num_offset); |
|---|
| 218 | + u32 mfd = readl_relaxed(pll->base + pll->denom_offset); |
|---|
| 224 | 219 | u32 div = readl_relaxed(pll->base) & pll->div_mask; |
|---|
| 225 | 220 | u64 temp64 = (u64)parent_rate; |
|---|
| 226 | 221 | |
|---|
| .. | .. |
|---|
| 289 | 284 | val &= ~pll->div_mask; |
|---|
| 290 | 285 | val |= div; |
|---|
| 291 | 286 | writel_relaxed(val, pll->base); |
|---|
| 292 | | - writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); |
|---|
| 293 | | - writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); |
|---|
| 287 | + writel_relaxed(mfn, pll->base + pll->num_offset); |
|---|
| 288 | + writel_relaxed(mfd, pll->base + pll->denom_offset); |
|---|
| 294 | 289 | |
|---|
| 295 | 290 | return clk_pllv3_wait_lock(pll); |
|---|
| 296 | 291 | } |
|---|
| .. | .. |
|---|
| 352 | 347 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
|---|
| 353 | 348 | struct clk_pllv3_vf610_mf mf; |
|---|
| 354 | 349 | |
|---|
| 355 | | - mf.mfn = readl_relaxed(pll->base + PLL_VF610_NUM_OFFSET); |
|---|
| 356 | | - mf.mfd = readl_relaxed(pll->base + PLL_VF610_DENOM_OFFSET); |
|---|
| 350 | + mf.mfn = readl_relaxed(pll->base + pll->num_offset); |
|---|
| 351 | + mf.mfd = readl_relaxed(pll->base + pll->denom_offset); |
|---|
| 357 | 352 | mf.mfi = (readl_relaxed(pll->base) & pll->div_mask) ? 22 : 20; |
|---|
| 358 | 353 | |
|---|
| 359 | 354 | return clk_pllv3_vf610_mf_to_rate(parent_rate, mf); |
|---|
| .. | .. |
|---|
| 382 | 377 | val |= pll->div_mask; /* set bit for mfi=22 */ |
|---|
| 383 | 378 | writel_relaxed(val, pll->base); |
|---|
| 384 | 379 | |
|---|
| 385 | | - writel_relaxed(mf.mfn, pll->base + PLL_VF610_NUM_OFFSET); |
|---|
| 386 | | - writel_relaxed(mf.mfd, pll->base + PLL_VF610_DENOM_OFFSET); |
|---|
| 380 | + writel_relaxed(mf.mfn, pll->base + pll->num_offset); |
|---|
| 381 | + writel_relaxed(mf.mfd, pll->base + pll->denom_offset); |
|---|
| 387 | 382 | |
|---|
| 388 | 383 | return clk_pllv3_wait_lock(pll); |
|---|
| 389 | 384 | } |
|---|
| .. | .. |
|---|
| 412 | 407 | .recalc_rate = clk_pllv3_enet_recalc_rate, |
|---|
| 413 | 408 | }; |
|---|
| 414 | 409 | |
|---|
| 415 | | -struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, |
|---|
| 410 | +struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, |
|---|
| 416 | 411 | const char *parent_name, void __iomem *base, |
|---|
| 417 | 412 | u32 div_mask) |
|---|
| 418 | 413 | { |
|---|
| 419 | 414 | struct clk_pllv3 *pll; |
|---|
| 420 | 415 | const struct clk_ops *ops; |
|---|
| 421 | | - struct clk *clk; |
|---|
| 422 | | - struct clk_init_data init = {}; |
|---|
| 416 | + struct clk_hw *hw; |
|---|
| 417 | + struct clk_init_data init; |
|---|
| 418 | + int ret; |
|---|
| 423 | 419 | |
|---|
| 424 | 420 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); |
|---|
| 425 | 421 | if (!pll) |
|---|
| 426 | 422 | return ERR_PTR(-ENOMEM); |
|---|
| 427 | 423 | |
|---|
| 428 | 424 | pll->power_bit = BM_PLL_POWER; |
|---|
| 425 | + pll->num_offset = PLL_NUM_OFFSET; |
|---|
| 426 | + pll->denom_offset = PLL_DENOM_OFFSET; |
|---|
| 429 | 427 | |
|---|
| 430 | 428 | switch (type) { |
|---|
| 431 | 429 | case IMX_PLLV3_SYS: |
|---|
| .. | .. |
|---|
| 433 | 431 | break; |
|---|
| 434 | 432 | case IMX_PLLV3_SYS_VF610: |
|---|
| 435 | 433 | ops = &clk_pllv3_vf610_ops; |
|---|
| 434 | + pll->num_offset = PLL_VF610_NUM_OFFSET; |
|---|
| 435 | + pll->denom_offset = PLL_VF610_DENOM_OFFSET; |
|---|
| 436 | 436 | break; |
|---|
| 437 | 437 | case IMX_PLLV3_USB_VF610: |
|---|
| 438 | 438 | pll->div_shift = 1; |
|---|
| 439 | + fallthrough; |
|---|
| 439 | 440 | case IMX_PLLV3_USB: |
|---|
| 440 | 441 | ops = &clk_pllv3_ops; |
|---|
| 441 | 442 | pll->powerup_set = true; |
|---|
| 442 | 443 | break; |
|---|
| 444 | + case IMX_PLLV3_AV_IMX7: |
|---|
| 445 | + pll->num_offset = PLL_IMX7_NUM_OFFSET; |
|---|
| 446 | + pll->denom_offset = PLL_IMX7_DENOM_OFFSET; |
|---|
| 447 | + fallthrough; |
|---|
| 443 | 448 | case IMX_PLLV3_AV: |
|---|
| 444 | 449 | ops = &clk_pllv3_av_ops; |
|---|
| 445 | 450 | break; |
|---|
| .. | .. |
|---|
| 454 | 459 | break; |
|---|
| 455 | 460 | case IMX_PLLV3_DDR_IMX7: |
|---|
| 456 | 461 | pll->power_bit = IMX7_DDR_PLL_POWER; |
|---|
| 462 | + pll->num_offset = PLL_IMX7_NUM_OFFSET; |
|---|
| 463 | + pll->denom_offset = PLL_IMX7_DENOM_OFFSET; |
|---|
| 457 | 464 | ops = &clk_pllv3_av_ops; |
|---|
| 458 | 465 | break; |
|---|
| 459 | 466 | default: |
|---|
| .. | .. |
|---|
| 469 | 476 | init.num_parents = 1; |
|---|
| 470 | 477 | |
|---|
| 471 | 478 | pll->hw.init = &init; |
|---|
| 479 | + hw = &pll->hw; |
|---|
| 472 | 480 | |
|---|
| 473 | | - clk = clk_register(NULL, &pll->hw); |
|---|
| 474 | | - if (IS_ERR(clk)) |
|---|
| 481 | + ret = clk_hw_register(NULL, hw); |
|---|
| 482 | + if (ret) { |
|---|
| 475 | 483 | kfree(pll); |
|---|
| 484 | + return ERR_PTR(ret); |
|---|
| 485 | + } |
|---|
| 476 | 486 | |
|---|
| 477 | | - return clk; |
|---|
| 487 | + return hw; |
|---|
| 478 | 488 | } |
|---|