2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-29 15:43:59 +08:00
linux-next/drivers/clk/imx/clk-pllv1.c
Linus Torvalds fc35c1966e We have two changes to the core framework this time around. The first being a
large change that introduces runtime PM support to the clk framework. Now we
 properly call runtime PM operations on the device providing a clk when the clk
 is in use. This helps on SoCs where the clks provided by a device need
 something to be powered on before using the clks, like power domains or
 regulators. It also helps power those things down when clks aren't in use. The
 other core change is a devm API addition for clk providers so we can get rid of
 a bunch of clk driver remove functions that are just doing
 of_clk_del_provider().
 
 Outside of the core, we have the usual addition of clk drivers and smattering
 of non-critical fixes to existing drivers. The biggest diff is support for
 Mediatek MT2712 and MT7622 SoCs, but those patches really just add a bunch
 of data.
 
 By the way, we're trying something new here where we build the tree up with
 topic branches. We plan to work this into our workflow so that we don't step
 on each other's toes, and so the fixes branch can be merged on an as-needed
 basis.
 
 Core:
  - Runtime PM support for clk providers
  - devm API for of_clk_add_hw_provider()
 
 New Drivers:
  - Mediatek MT2712 and MT7622
  - Renesas R-Car V3M SoC
 
 Updates:
  - Runtime PM support for Samsung exynos5433/exynos4412 providers
  - Removal of clkdev aliases on Samsung SoCs
  - Convert clk-gpio to use gpio descriptors
  - Various driver cleanups to match kernel coding style
  - Amlogic Video Processing Unit VPU and VAPB clks
  - Sigma-delta modulation for Allwinner audio PLLs
  - Allwinner A83t Display clks
  - Support for the second display unit clock on Renesas RZ/G1E
  - Suspend/resume support for Renesas R-Car Gen3 CPG/MSSR
  - New clock ids for Rockchip rk3188 and rk3368 SoCs
  - Various 'const' markings on clk_ops structures
  - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCAAGBQJaD3qRAAoJEK0CiJfG5JUlOLgQAKWekgG/IYgcPzPWDYfg8Hwr
 sVVUK7+q7TVfbHsbYVikJuUaxutKZ0onnrYmOalTTyyxqL2E1/rYScnxdYHfcwX8
 cyfHebRHsbh/Xg45ktwjzBkO49nwuppkpXd/V80GSBUZ+lsIVl5DUrrFAZdRUEdr
 CEsAsF9tEWIl+0gqXYNuiKBV7QAYv5BUPrbJQf0PwL6jX0OAhLv+ukfN8BdmYsOb
 rdoqhdgmyHkTuIMqsC/H2yP59aAKBse7wxIYebDiTdbPWfTkC9q927fTs4A02F6L
 sHfLvCpfuB4rOjXy6LSd1gMGWIcjotZai+idHBqtNLLVz6exF1QpUCp+pZjEULbA
 /Sx9lk8A3cYoa8pTu1NrrZbZX17iHkFswqMF3T20nhUN9+Ti597ZEbRcWDcoEZtw
 v2NznOTJ7Mm2SrNHOvDklstggNIGcwiAEePGMo7rJNEQZChpDjQj/gJWKzn0UwL4
 zfk+0EzoejPdvZ5FJUfmlr8Tqk53uw+y7/0xQ6gf8lDviTrzzoeXtJUyumGBiuGx
 RxFywf8n02oLYRJm5hu+0NkC+/bX0Lxg/kwiR6FLBFbBFgkWyp7FGcxhlm6ZiBfe
 0KkPciWslNavn5KhljIkZDbXymbvhhSr9uBEFsyeJueA5q7sSghWloL8Ag1cac3W
 e6swD1ngXtM/t5gjOLhR
 =hC7z
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Stephen Boyd:
 "We have two changes to the core framework this time around.

  The first being a large change that introduces runtime PM support to
  the clk framework. Now we properly call runtime PM operations on the
  device providing a clk when the clk is in use. This helps on SoCs
  where the clks provided by a device need something to be powered on
  before using the clks, like power domains or regulators. It also helps
  power those things down when clks aren't in use.

  The other core change is a devm API addition for clk providers so we
  can get rid of a bunch of clk driver remove functions that are just
  doing of_clk_del_provider().

  Outside of the core, we have the usual addition of clk drivers and
  smattering of non-critical fixes to existing drivers. The biggest diff
  is support for Mediatek MT2712 and MT7622 SoCs, but those patches
  really just add a bunch of data.

  By the way, we're trying something new here where we build the tree up
  with topic branches. We plan to work this into our workflow so that we
  don't step on each other's toes, and so the fixes branch can be merged
  on an as-needed basis.

  Summary:

  Core:
   - runtime PM support for clk providers
   - devm API for of_clk_add_hw_provider()

  New Drivers:
   - Mediatek MT2712 and MT7622
   - Renesas R-Car V3M SoC

  Updates:
   - runtime PM support for Samsung exynos5433/exynos4412 providers
   - removal of clkdev aliases on Samsung SoCs
   - convert clk-gpio to use gpio descriptors
   - various driver cleanups to match kernel coding style
   - Amlogic Video Processing Unit VPU and VAPB clks
   - sigma-delta modulation for Allwinner audio PLLs
   - Allwinner A83t Display clks
   - support for the second display unit clock on Renesas RZ/G1E
   - suspend/resume support for Renesas R-Car Gen3 CPG/MSSR
   - new clock ids for Rockchip rk3188 and rk3368 SoCs
   - various 'const' markings on clk_ops structures
   - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (137 commits)
  clk: stm32h7: fix test of clock config
  clk: pxa: fix building on older compilers
  clk: sunxi-ng: a83t: Fix i2c buses bits
  clk: ti: dra7-atl-clock: fix child-node lookups
  clk: qcom: common: fix legacy board-clock registration
  clk: uniphier: fix DAPLL2 clock rate of Pro5
  clk: uniphier: fix parent of miodmac clock data
  clk: hi3798cv200: correct parent mux clock for 'clk_sdio0_ciu'
  clk: hisilicon: Delete an error message for a failed memory allocation in hisi_register_clkgate_sep()
  clk: hi3660: fix incorrect uart3 clock freqency
  clk: kona-setup: Delete error messages for failed memory allocations
  ARC: clk: fix spelling mistake: "configurarion" -> "configuration"
  clk: cdce925: remove redundant check for non-null parent_name
  clk: versatile: Improve sizeof() usage
  clk: versatile: Delete error messages for failed memory allocations
  clk: ux500: Improve sizeof() usage
  clk: ux500: Delete error messages for failed memory allocations
  clk: spear: Delete error messages for failed memory allocations
  clk: ti: Delete error messages for failed memory allocations
  clk: mmp: Adjust checks for NULL pointers
  ...
2017-11-17 20:04:24 -08:00

142 lines
2.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include "clk.h"
/**
* pll v1
*
* @clk_hw clock source
* @parent the parent clock name
* @base base address of pll registers
*
* PLL clock version 1, found on i.MX1/21/25/27/31/35
*/
#define MFN_BITS (10)
#define MFN_SIGN (BIT(MFN_BITS - 1))
#define MFN_MASK (MFN_SIGN - 1)
struct clk_pllv1 {
struct clk_hw hw;
void __iomem *base;
enum imx_pllv1_type type;
};
#define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
static inline bool is_imx1_pllv1(struct clk_pllv1 *pll)
{
return pll->type == IMX_PLLV1_IMX1;
}
static inline bool is_imx21_pllv1(struct clk_pllv1 *pll)
{
return pll->type == IMX_PLLV1_IMX21;
}
static inline bool is_imx27_pllv1(struct clk_pllv1 *pll)
{
return pll->type == IMX_PLLV1_IMX27;
}
static inline bool mfn_is_negative(struct clk_pllv1 *pll, unsigned int mfn)
{
return !is_imx1_pllv1(pll) && !is_imx21_pllv1(pll) && (mfn & MFN_SIGN);
}
static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv1 *pll = to_clk_pllv1(hw);
unsigned long long ull;
int mfn_abs;
unsigned int mfi, mfn, mfd, pd;
u32 reg;
unsigned long rate;
reg = readl(pll->base);
/*
* Get the resulting clock rate from a PLL register value and the input
* frequency. PLLs with this register layout can be found on i.MX1,
* i.MX21, i.MX27 and i,MX31
*
* mfi + mfn / (mfd + 1)
* f = 2 * f_ref * --------------------
* pd + 1
*/
mfi = (reg >> 10) & 0xf;
mfn = reg & 0x3ff;
mfd = (reg >> 16) & 0x3ff;
pd = (reg >> 26) & 0xf;
mfi = mfi <= 5 ? 5 : mfi;
mfn_abs = mfn;
/*
* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
* 2's complements number.
* On i.MX27 the bit 9 is the sign bit.
*/
if (mfn_is_negative(pll, mfn)) {
if (is_imx27_pllv1(pll))
mfn_abs = mfn & MFN_MASK;
else
mfn_abs = BIT(MFN_BITS) - mfn;
}
rate = parent_rate * 2;
rate /= pd + 1;
ull = (unsigned long long)rate * mfn_abs;
do_div(ull, mfd + 1);
if (mfn_is_negative(pll, mfn))
ull = (rate * mfi) - ull;
else
ull = (rate * mfi) + ull;
return ull;
}
static const struct clk_ops clk_pllv1_ops = {
.recalc_rate = clk_pllv1_recalc_rate,
};
struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
const char *parent, void __iomem *base)
{
struct clk_pllv1 *pll;
struct clk *clk;
struct clk_init_data init;
pll = kmalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
pll->base = base;
pll->type = type;
init.name = name;
init.ops = &clk_pllv1_ops;
init.flags = 0;
init.parent_names = &parent;
init.num_parents = 1;
pll->hw.init = &init;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk))
kfree(pll);
return clk;
}