Commit e7faa095 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-imx', 'clk-samsung', 'clk-ti', 'clk-uniphier-gear' and...

Merge branches 'clk-imx', 'clk-samsung', 'clk-ti', 'clk-uniphier-gear' and 'clk-mmp2-lcdc' into clk-next

 - Split LCDC into two clks on the Marvell MMP2 SoC

* clk-imx:
  clk: imx8mq: add GPIO clocks to clock tree
  clk: imx: Refactor entire sccg pll clk
  clk: imx: scu: add cpu frequency scaling support
  clk: imx: imx8mm: Mark init function __init
  clk: imx8mq: Add the missing ARM clock
  dt-bindings: imx8mq-clock: Add the missing ARM clock
  clk: imx: imx8mq: Fix the rate propagation for arm pll
  clk: imx8mq: Add support for the CLKO1 clock
  clk: imx8mq: Fix the CLKO2 source select list
  clk: imx8mq: Add missing M4 clocks
  clk: imx: Add clock driver support for imx8mm
  dt-bindings: imx: Add clock binding doc for imx8mm
  clk: imx: Add PLLs driver for imx8mm soc
  clk: imx5: add imx5_SCC2_IPG_GATE
  clk: imx: scu: add set parent support
  clk: imx: scu: add fallback compatible string support
  clk: imx8mq: Make parent names arrays const pointers
  clk: imx: Make parents const pointer in mux wrappers
  clk: imx: Make parent_names const pointer in composite-8m

* clk-samsung:
  clk: samsung: s3c2443: Mark expected switch fall-through
  clk: samsung: exynos5: Fix kfree() of const memory on setting driver_override
  clk: samsung: exynos5: Fix possible NULL pointer exception on platform_device_alloc() failure
  clk: samsung: exynos5433: Add selected IMEM clocks
  clk: samsung: dt-bindings: Document Exynos5433 IMEM CMU
  clk: samsung: exynos5433: Fix name typo in sssx
  clk: samsung: exynos5433: Fix definition of CLK_ACLK_IMEM_{200, 266} clocks
  clk: samsung: dt-bindings: Add Exynos5433 IMEM CMU clock IDs

* clk-ti:
  clk: clk-twl6040: Fix imprecise external abort for pdmclk
  ARM: OMAP2+: hwmod: disable ick autoidling when a hwmod requires that
  clk: ti: check clock type before doing autoidle ops
  clk: ti: add a usecount for autoidle
  clk: ti: generalize the init sequence of clk_hw_omap clocks
  clk: ti: remove usage of CLK_IS_BASIC
  clk: ti: add new API for checking if a provided clock is an OMAP clock
  clk: ti: move clk_hw_omap list handling under generic part of the driver

* clk-uniphier-gear:
  clk: uniphier: Fix update register for CPU-gear

* clk-mmp2-lcdc:
  clk: mmp2: separate LCDC peripheral clk form the display clock
  dt-bindings: marvell,mmp2: Add clock id for the LCDC clock
......@@ -50,6 +50,8 @@ Required Properties:
IPs.
- "samsung,exynos5433-cmu-cam1" - clock controller compatible for CMU_CAM1
which generates clocks for Cortex-A5/MIPI_CSIS2/FIMC-LITE_C/FIMC-FD IPs.
- "samsung,exynos5433-cmu-imem" - clock controller compatible for CMU_IMEM
which generates clocks for SSS (Security SubSystem) and SlimSSS IPs.
- reg: physical base address of the controller and length of memory mapped
region.
......@@ -168,6 +170,12 @@ Required Properties:
- aclk_cam1_400
- aclk_cam1_552
Input clocks for imem clock controller:
- oscclk
- aclk_imem_sssx_266
- aclk_imem_266
- aclk_imem_200
Optional properties:
- power-domains: a phandle to respective power domain node as described by
generic PM domain bindings (see power/power_domain.txt for more
......@@ -469,6 +477,21 @@ Example 2: Examples of clock controller nodes are listed below.
power-domains = <&pd_cam1>;
};
cmu_imem: clock-controller@11060000 {
compatible = "samsung,exynos5433-cmu-imem";
reg = <0x11060000 0x1000>;
#clock-cells = <1>;
clock-names = "oscclk",
"aclk_imem_sssx_266",
"aclk_imem_266",
"aclk_imem_200";
clocks = <&xxti>,
<&cmu_top CLK_DIV_ACLK_IMEM_SSSX_266>,
<&cmu_top CLK_DIV_ACLK_IMEM_266>,
<&cmu_top CLK_DIV_ACLK_IMEM_200>;
};
Example 3: UART controller node that consumes the clock generated by the clock
controller.
......
* Clock bindings for NXP i.MX8M Mini
Required properties:
- compatible: Should be "fsl,imx8mm-ccm"
- reg: Address and length of the register set
- #clock-cells: Should be <1>
- clocks: list of clock specifiers, must contain an entry for each required
entry in clock-names
- clock-names: should include the following entries:
- "osc_32k"
- "osc_24m"
- "clk_ext1"
- "clk_ext2"
- "clk_ext3"
- "clk_ext4"
clk: clock-controller@30380000 {
compatible = "fsl,imx8mm-ccm";
reg = <0x0 0x30380000 0x0 0x10000>;
#clock-cells = <1>;
clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
<&clk_ext3>, <&clk_ext4>;
clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
"clk_ext3", "clk_ext4";
};
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h
for the full list of i.MX8M Mini clock IDs.
......@@ -1002,8 +1002,10 @@ static int _enable_clocks(struct omap_hwmod *oh)
clk_enable(oh->_clk);
list_for_each_entry(os, &oh->slave_ports, node) {
if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
omap2_clk_deny_idle(os->_clk);
clk_enable(os->_clk);
}
}
/* The opt clocks are controlled by the device driver. */
......@@ -1055,8 +1057,10 @@ static int _disable_clocks(struct omap_hwmod *oh)
clk_disable(oh->_clk);
list_for_each_entry(os, &oh->slave_ports, node) {
if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
clk_disable(os->_clk);
omap2_clk_allow_idle(os->_clk);
}
}
if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
......@@ -2436,9 +2440,13 @@ static void _setup_iclk_autoidle(struct omap_hwmod *oh)
continue;
if (os->flags & OCPIF_SWSUP_IDLE) {
/* XXX omap_iclk_deny_idle(c); */
/*
* we might have multiple users of one iclk with
* different requirements, disable autoidle when
* the module is enabled, e.g. dss iclk
*/
} else {
/* XXX omap_iclk_allow_idle(c); */
/* we are enabling autoidle afterwards anyways */
clk_enable(os->_clk);
}
}
......
......@@ -41,6 +41,43 @@ static int twl6040_pdmclk_is_prepared(struct clk_hw *hw)
return pdmclk->enabled;
}
static int twl6040_pdmclk_reset_one_clock(struct twl6040_pdmclk *pdmclk,
unsigned int reg)
{
const u8 reset_mask = TWL6040_HPLLRST; /* Same for HPPLL and LPPLL */
int ret;
ret = twl6040_set_bits(pdmclk->twl6040, reg, reset_mask);
if (ret < 0)
return ret;
ret = twl6040_clear_bits(pdmclk->twl6040, reg, reset_mask);
if (ret < 0)
return ret;
return 0;
}
/*
* TWL6040A2 Phoenix Audio IC erratum #6: "PDM Clock Generation Issue At
* Cold Temperature". This affects cold boot and deeper idle states it
* seems. The workaround consists of resetting HPPLL and LPPLL.
*/
static int twl6040_pdmclk_quirk_reset_clocks(struct twl6040_pdmclk *pdmclk)
{
int ret;
ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_HPPLLCTL);
if (ret)
return ret;
ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_LPPLLCTL);
if (ret)
return ret;
return 0;
}
static int twl6040_pdmclk_prepare(struct clk_hw *hw)
{
struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
......@@ -48,8 +85,20 @@ static int twl6040_pdmclk_prepare(struct clk_hw *hw)
int ret;
ret = twl6040_power(pdmclk->twl6040, 1);
if (!ret)
pdmclk->enabled = 1;
if (ret)
return ret;
ret = twl6040_pdmclk_quirk_reset_clocks(pdmclk);
if (ret)
goto out_err;
pdmclk->enabled = 1;
return 0;
out_err:
dev_err(pdmclk->dev, "%s: error %i\n", __func__, ret);
twl6040_power(pdmclk->twl6040, 0);
return ret;
}
......
......@@ -8,6 +8,12 @@ config MXC_CLK_SCU
bool
depends on IMX_SCU
config CLK_IMX8MM
bool "IMX8MM CCM Clock Driver"
depends on ARCH_MXC && ARM64
help
Build the driver for i.MX8MM CCM Clock Driver
config CLK_IMX8MQ
bool "IMX8MQ CCM Clock Driver"
depends on ARCH_MXC && ARM64
......
......@@ -18,12 +18,14 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pllv2.o \
clk-pllv3.o \
clk-pllv4.o \
clk-sccg-pll.o
clk-sccg-pll.o \
clk-pll14xx.o
obj-$(CONFIG_MXC_CLK_SCU) += \
clk-scu.o \
clk-lpcg-scu.o
obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
......
......@@ -123,7 +123,7 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
};
struct clk *imx8m_clk_composite_flags(const char *name,
const char **parent_names,
const char * const *parent_names,
int num_parents, void __iomem *reg,
unsigned long flags)
{
......
......@@ -428,6 +428,7 @@ static void __init mx51_clocks_init(struct device_node *np)
clk[IMX5_CLK_ESDHC4_PER_GATE] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
clk[IMX5_CLK_USB_PHY_GATE] = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
clk[IMX5_CLK_HSI2C_GATE] = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
clk[IMX5_CLK_SCC2_IPG_GATE] = imx_clk_gate2("scc2_gate", "ipg", MXC_CCM_CCGR1, 30);
clk[IMX5_CLK_MIPI_HSC1_GATE] = imx_clk_gate2_flags("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6, CLK_IS_CRITICAL);
clk[IMX5_CLK_MIPI_HSC2_GATE] = imx_clk_gate2_flags("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8, CLK_IS_CRITICAL);
clk[IMX5_CLK_MIPI_ESC_GATE] = imx_clk_gate2_flags("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10, CLK_IS_CRITICAL);
......
This diff is collapsed.
This diff is collapsed.
......@@ -138,6 +138,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
}
static const struct of_device_id imx8qxp_match[] = {
{ .compatible = "fsl,scu-clk", },
{ .compatible = "fsl,imx8qxp-clk", },
{ /* sentinel */ }
};
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2017-2018 NXP.
*/
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include "clk.h"
#define GNRL_CTL 0x0
#define DIV_CTL 0x4
#define LOCK_STATUS BIT(31)
#define LOCK_SEL_MASK BIT(29)
#define CLKE_MASK BIT(11)
#define RST_MASK BIT(9)
#define BYPASS_MASK BIT(4)
#define MDIV_SHIFT 12
#define MDIV_MASK GENMASK(21, 12)
#define PDIV_SHIFT 4
#define PDIV_MASK GENMASK(9, 4)
#define SDIV_SHIFT 0
#define SDIV_MASK GENMASK(2, 0)
#define KDIV_SHIFT 0
#define KDIV_MASK GENMASK(15, 0)
#define LOCK_TIMEOUT_US 10000
struct clk_pll14xx {
struct clk_hw hw;
void __iomem *base;
enum imx_pll14xx_type type;
const struct imx_pll14xx_rate_table *rate_table;
int rate_count;
};
#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
struct clk_pll14xx *pll, unsigned long rate)
{
const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++)
if (rate == rate_table[i].rate)
return &rate_table[i];
return NULL;
}
static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
int i;
/* Assumming rate_table is in descending order */
for (i = 0; i < pll->rate_count; i++)
if (rate >= rate_table[i].rate)
return rate_table[i].rate;
/* return minimum supported value */
return rate_table[i - 1].rate;
}
static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
u64 fvco = parent_rate;
pll_gnrl = readl_relaxed(pll->base);
pll_div = readl_relaxed(pll->base + 4);
mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
fvco *= mdiv;
do_div(fvco, pdiv << sdiv);
return fvco;
}
static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
short int kdiv;
u64 fvco = parent_rate;
pll_gnrl = readl_relaxed(pll->base);
pll_div_ctl0 = readl_relaxed(pll->base + 4);
pll_div_ctl1 = readl_relaxed(pll->base + 8);
mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
kdiv = pll_div_ctl1 & KDIV_MASK;
/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
fvco *= (mdiv * 65536 + kdiv);
pdiv *= 65536;
do_div(fvco, pdiv << sdiv);
return fvco;
}
static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
u32 pll_div)
{
u32 old_mdiv, old_pdiv;
old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
}
static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
u32 pll_div_ctl0, u32 pll_div_ctl1)
{
u32 old_mdiv, old_pdiv, old_kdiv;
old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
rate->kdiv != old_kdiv;
}
static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
u32 pll_div_ctl0, u32 pll_div_ctl1)
{
u32 old_mdiv, old_pdiv, old_kdiv;
old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
rate->kdiv != old_kdiv;
}
static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
{
u32 val;
return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
LOCK_TIMEOUT_US);
}
static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
const struct imx_pll14xx_rate_table *rate;
u32 tmp, div_val;
int ret;
rate = imx_get_pll_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
tmp = readl_relaxed(pll->base + 4);
if (!clk_pll1416x_mp_change(rate, tmp)) {
tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
tmp |= rate->sdiv << SDIV_SHIFT;
writel_relaxed(tmp, pll->base + 4);
return 0;
}
/* Bypass clock and set lock to pll output lock */
tmp = readl_relaxed(pll->base);
tmp |= LOCK_SEL_MASK;
writel_relaxed(tmp, pll->base);
/* Enable RST */
tmp &= ~RST_MASK;
writel_relaxed(tmp, pll->base);
div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
(rate->sdiv << SDIV_SHIFT);
writel_relaxed(div_val, pll->base + 0x4);
/*
* According to SPEC, t3 - t2 need to be greater than
* 1us and 1/FREF, respectively.
* FREF is FIN / Prediv, the prediv is [1, 63], so choose
* 3us.
*/
udelay(3);
/* Disable RST */
tmp |= RST_MASK;
writel_relaxed(tmp, pll->base);
/* Wait Lock */
ret = clk_pll14xx_wait_lock(pll);
if (ret)
return ret;
/* Bypass */
tmp &= ~BYPASS_MASK;
writel_relaxed(tmp, pll->base);
return 0;
}
static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
const struct imx_pll14xx_rate_table *rate;
u32 tmp, div_val;
int ret;
rate = imx_get_pll_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
tmp = readl_relaxed(pll->base + 4);
div_val = readl_relaxed(pll->base + 8);
if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
tmp |= rate->sdiv << SDIV_SHIFT;
writel_relaxed(tmp, pll->base + 4);
return 0;
}
/* Enable RST */
tmp = readl_relaxed(pll->base);
tmp &= ~RST_MASK;
writel_relaxed(tmp, pll->base);
div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
(rate->sdiv << SDIV_SHIFT);
writel_relaxed(div_val, pll->base + 0x4);
writel_relaxed(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
/*
* According to SPEC, t3 - t2 need to be greater than
* 1us and 1/FREF, respectively.
* FREF is FIN / Prediv, the prediv is [1, 63], so choose
* 3us.
*/
udelay(3);
/* Disable RST */
tmp |= RST_MASK;
writel_relaxed(tmp, pll->base);
/* Wait Lock*/
ret = clk_pll14xx_wait_lock(pll);
if (ret)
return ret;
/* Bypass */
tmp &= ~BYPASS_MASK;
writel_relaxed(tmp, pll->base);
return 0;
}
static int clk_pll14xx_prepare(struct clk_hw *hw)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
/*
* RESETB = 1 from 0, PLL starts its normal
* operation after lock time
*/
val = readl_relaxed(pll->base + GNRL_CTL);
val |= RST_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
return clk_pll14xx_wait_lock(pll);
}
static int clk_pll14xx_is_prepared(struct clk_hw *hw)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
val = readl_relaxed(pll->base + GNRL_CTL);
return (val & RST_MASK) ? 1 : 0;
}
static void clk_pll14xx_unprepare(struct clk_hw *hw)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
/*
* Set RST to 0, power down mode is enabled and
* every digital block is reset
*/
val = readl_relaxed(pll->base + GNRL_CTL);
val &= ~RST_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
}
static const struct clk_ops clk_pll1416x_ops = {
.prepare = clk_pll14xx_prepare,
.unprepare = clk_pll14xx_unprepare,
.is_prepared = clk_pll14xx_is_prepared,
.recalc_rate = clk_pll1416x_recalc_rate,
.round_rate = clk_pll14xx_round_rate,
.set_rate = clk_pll1416x_set_rate,
};
static const struct clk_ops clk_pll1416x_min_ops = {
.recalc_rate = clk_pll1416x_recalc_rate,
};
static const struct clk_ops clk_pll1443x_ops = {
.prepare = clk_pll14xx_prepare,
.unprepare = clk_pll14xx_unprepare,
.is_prepared = clk_pll14xx_is_prepared,
.recalc_rate = clk_pll1443x_recalc_rate,
.round_rate = clk_pll14xx_round_rate,
.set_rate = clk_pll1443x_set_rate,
};
struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
void __iomem *base,
const struct imx_pll14xx_clk *pll_clk)
{
struct clk_pll14xx *pll;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
init.name = name;
init.flags = pll_clk->flags;
init.parent_names = &parent_name;
init.num_parents = 1;
switch (pll_clk->type) {
case PLL_1416X:
if (!pll->rate_table)
init.ops = &clk_pll1416x_min_ops;
else
init.ops = &clk_pll1416x_ops;
break;
case PLL_1443X:
init.ops = &clk_pll1443x_ops;
break;
default:
pr_err("%s: Unknown pll type for pll clk %s\n",
__func__, name);
};
pll->base = base;
pll->hw.init = &init;
pll->type = pll_clk->type;
pll->rate_table = pll_clk->rate_table;
pll->rate_count = pll_clk->rate_count;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll %s %lu\n",
__func__, name, PTR_ERR(clk));
kfree(pll);
}
return clk;
}
This diff is collapsed.
......@@ -4,12 +4,17 @@
* Dong Aisheng <aisheng.dong@nxp.com>
*/
#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/arm-smccc.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/slab.h>
#include "clk-scu.h"
#define IMX_SIP_CPUFREQ 0xC2000001
#define IMX_SIP_SET_CPUFREQ 0x00
static struct imx_sc_ipc *ccm_ipc_handle;
/*
......@@ -65,6 +70,41 @@ struct imx_sc_msg_get_clock_rate {
} data;
};
/*
* struct imx_sc_msg_get_clock_parent - clock get parent protocol
* @hdr: SCU protocol header
* @req: get parent request protocol
* @resp: get parent response protocol
*
* This structure describes the SCU protocol of clock get parent
*/
struct imx_sc_msg_get_clock_parent {
struct imx_sc_rpc_msg hdr;
union {
struct req_get_clock_parent {
__le16 resource;
u8 clk;
} __packed req;
struct resp_get_clock_parent {
u8 parent;
} resp;
} data;
};
/*
* struct imx_sc_msg_set_clock_parent - clock set parent protocol
* @hdr: SCU protocol header
* @req: set parent request protocol
*
* This structure describes the SCU protocol of clock set parent
*/
struct imx_sc_msg_set_clock_parent {
struct imx_sc_rpc_msg hdr;
__le16 resource;
u8 clk;
u8 parent;
} __packed;
/*
* struct imx_sc_msg_req_clock_enable - clock gate protocol
* @hdr: SCU protocol header
......@@ -145,6 +185,25 @@ static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate,
return rate;
}
static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_scu *clk = to_clk_scu(hw);
struct arm_smccc_res res;
unsigned long cluster_id;
if (clk->rsrc_id == IMX_SC_R_A35)
cluster_id = 0;
else
return -EINVAL;
/* CPU frequency scaling can ONLY be done by ARM-Trusted-Firmware */
arm_smccc_smc(IMX_SIP_CPUFREQ, IMX_SIP_SET_CPUFREQ,
cluster_id, rate, 0, 0, 0, 0, &res);
return 0;
}
/*
* clk_scu_set_rate - Set rate for a SCU clock
* @hw: clock to change rate for
......@@ -173,6 +232,49 @@ static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
}
static u8 clk_scu_get_parent(struct clk_hw *hw)
{
struct clk_scu *clk = to_clk_scu(hw);
struct imx_sc_msg_get_clock_parent msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;
int ret;
hdr->ver = IMX_SC_RPC_VERSION;
hdr->svc = IMX_SC_RPC_SVC_PM;
hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_PARENT;
hdr->size = 2;
msg.data.req.resource = cpu_to_le16(clk->rsrc_id);
msg.data.req.clk = clk->clk_type;
ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
if (ret) {
pr_err("%s: failed to get clock parent %d\n",
clk_hw_get_name(hw), ret);
return 0;
}
return msg.data.resp.parent;
}
static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_scu *clk = to_clk_scu(hw);
struct imx_sc_msg_set_clock_parent msg;
struct imx_sc_rpc_msg *hdr = &msg.hdr;
hdr->ver = IMX_SC_RPC_VERSION;
hdr->svc = IMX_SC_RPC_SVC_PM;
hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_PARENT;
hdr->size = 2;
msg.resource = cpu_to_le16(clk->rsrc_id);
msg.clk = clk->clk_type;
msg.parent = index;
return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
}
static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
u8 clk, bool enable, bool autog)
{
......@@ -228,11 +330,22 @@ static const struct clk_ops clk_scu_ops = {
.recalc_rate = clk_scu_recalc_rate,
.round_rate = clk_scu_round_rate,
.set_rate = clk_scu_set_rate,
.get_parent = clk_scu_get_parent,
.set_parent = clk_scu_set_parent,
.prepare = clk_scu_prepare,
.unprepare = clk_scu_unprepare,
};
static const struct clk_ops clk_scu_cpu_ops = {
.recalc_rate = clk_scu_recalc_rate,
.round_rate = clk_scu_round_rate,
.set_rate = clk_scu_atf_set_cpu_rate,
.prepare = clk_scu_prepare,
.unprepare = clk_scu_unprepare,
};
struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type)
{
struct clk_init_data init;
struct clk_scu *clk;
......@@ -248,7 +361,13 @@ struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
init.name = name;
init.ops = &clk_scu_ops;
init.num_parents = 0;
if (rsrc_id == IMX_SC_R_A35)
init.ops = &clk_scu_cpu_ops;
else
init.ops = &clk_scu_ops;
init.parent_names = parents;
init.num_parents = num_parents;
/*
* Note on MX8, the clocks are tightly coupled with power domain
* that once the power domain is off, the clock status may be
......
......@@ -10,7 +10,21 @@
#include <linux/firmware/imx/sci.h>
int imx_clk_scu_init(void);
struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type);
static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
u8 clk_type)
{
return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
}
static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type)
{
return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
}
struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
unsigned long flags, void __iomem *reg,
......
......@@ -27,6 +27,30 @@ enum imx_sccg_pll_type {
SCCG_PLL2,
};
enum imx_pll14xx_type {
PLL_1416X,
PLL_1443X,
};
/* NOTE: Rate table should be kept sorted in descending order. */
struct imx_pll14xx_rate_table {
unsigned int rate;
unsigned int pdiv;
unsigned int mdiv;
unsigned int sdiv;
unsigned int kdiv;
};
struct imx_pll14xx_clk {
enum imx_pll14xx_type type;
const struct imx_pll14xx_rate_table *rate_table;
int rate_count;
int flags;
};
struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
void __iomem *base, const struct imx_pll14xx_clk *pll_clk);
struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
const char *parent, void __iomem *base);
......@@ -36,9 +60,12 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent,
struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
void __iomem *base);
struct clk *imx_clk_sccg_pll(const char *name, const char *parent_name,
void __iomem *base,
enum imx_sccg_pll_type pll_type);
struct clk *imx_clk_sccg_pll(const char *name,
const char * const *parent_names,
u8 num_parents,
u8 parent, u8 bypass1, u8 bypass2,
void __iomem *base,
unsigned long flags);
enum imx_pllv3_type {
IMX_PLLV3_GENERIC,
......@@ -329,7 +356,8 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
}
static inline struct clk *imx_clk_mux2_flags(const char *name,
void __iomem *reg, u8 shift, u8 width, const char **parents,
void __iomem *reg, u8 shift, u8 width,
const char * const *parents,
int num_parents, unsigned long flags)
{
return clk_register_mux(NULL, name, parents, num_parents,
......@@ -354,7 +382,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
struct clk *step);
struct clk *imx8m_clk_composite_flags(const char *name,
const char **parent_names,
const char * const *parent_names,
int num_parents, void __iomem *reg,
unsigned long flags);
......
......@@ -229,9 +229,10 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
{MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_SDH2, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_SDH3, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x09, 0x09, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP0_LCDC, "disp0_lcdc_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x12, 0x12, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock},
{MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x09, 0x09, 0x0, 0, &disp1_lock},
{MMP2_CLK_CCIC_ARBITER, "ccic_arbiter", "vctcxo", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1800, 0x1800, 0x0, 0, &ccic0_lock},
{MMP2_CLK_CCIC0, "ccic0_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock},
{MMP2_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock},
......
......@@ -136,15 +136,20 @@ static int __init exynos5_clk_register_subcmu(struct device *parent,
{
struct of_phandle_args genpdspec = { .np = pd_node };
struct platform_device *pdev;
int ret;
pdev = platform_device_alloc("exynos5-subcmu", PLATFORM_DEVID_AUTO);
if (!pdev)
return -ENOMEM;
pdev = platform_device_alloc(info->pd_name, -1);
pdev->dev.parent = parent;
pdev->driver_override = "exynos5-subcmu";
platform_set_drvdata(pdev, (void *)info);
of_genpd_add_device(&genpdspec, &pdev->dev);
platform_device_add(pdev);
ret = platform_device_add(pdev);
if (ret)
platform_device_put(pdev);
return 0;
return ret;
}
static int __init exynos5_clk_probe(struct platform_device *pdev)
......
......@@ -559,7 +559,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
/* ENABLE_ACLK_TOP */
GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
ENABLE_ACLK_TOP, 30, CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
GATE(CLK_ACLK_IMEM_SSSX_266, "aclk_imem_sssx_266",
"div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
29, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK_BUS0_400, "aclk_bus0_400", "div_aclk_bus0_400",
......@@ -568,10 +568,10 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
GATE(CLK_ACLK_BUS1_400, "aclk_bus1_400", "div_aclk_bus1_400",
ENABLE_ACLK_TOP, 25,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_200",
ENABLE_ACLK_TOP, 24,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_266",
ENABLE_ACLK_TOP, 23,
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
......@@ -5467,6 +5467,35 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = {
.clk_name = "aclk_cam1_400",
};
/*
* Register offset definitions for CMU_IMEM
*/
#define ENABLE_ACLK_IMEM_SLIMSSS 0x080c
#define ENABLE_PCLK_IMEM_SLIMSSS 0x0908
static const unsigned long imem_clk_regs[] __initconst = {
ENABLE_ACLK_IMEM_SLIMSSS,
ENABLE_PCLK_IMEM_SLIMSSS,
};
static const struct samsung_gate_clock imem_gate_clks[] __initconst = {
/* ENABLE_ACLK_IMEM_SLIMSSS */
GATE(CLK_ACLK_SLIMSSS, "aclk_slimsss", "aclk_imem_sssx_266",
ENABLE_ACLK_IMEM_SLIMSSS, 0, CLK_IGNORE_UNUSED, 0),
/* ENABLE_PCLK_IMEM_SLIMSSS */
GATE(CLK_PCLK_SLIMSSS, "pclk_slimsss", "aclk_imem_200",
ENABLE_PCLK_IMEM_SLIMSSS, 0, CLK_IGNORE_UNUSED, 0),
};
static const struct samsung_cmu_info imem_cmu_info __initconst = {
.gate_clks = imem_gate_clks,
.nr_gate_clks = ARRAY_SIZE(imem_gate_clks),
.nr_clk_ids = IMEM_NR_CLK,
.clk_regs = imem_clk_regs,
.nr_clk_regs = ARRAY_SIZE(imem_clk_regs),
.clk_name = "aclk_imem_200",
};
struct exynos5433_cmu_data {
struct samsung_clk_reg_dump *clk_save;
......@@ -5654,6 +5683,9 @@ static const struct of_device_id exynos5433_cmu_of_match[] = {
}, {
.compatible = "samsung,exynos5433-cmu-mscl",
.data = &mscl_cmu_info,
}, {
.compatible = "samsung,exynos5433-cmu-imem",
.data = &imem_cmu_info,
}, {
},
};
......
......@@ -389,7 +389,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
ARRAY_SIZE(s3c2450_gates));
samsung_clk_register_alias(ctx, s3c2450_aliases,
ARRAY_SIZE(s3c2450_aliases));
/* fall through, as s3c2450 extends the s3c2416 clocks */
/* fall through - as s3c2450 extends the s3c2416 clocks */
case S3C2416:
samsung_clk_register_div(ctx, s3c2416_dividers,
ARRAY_SIZE(s3c2416_dividers));
......
......@@ -614,7 +614,7 @@ static int ti_adpll_init_clkout(struct ti_adpll_data *d,
init.name = child_name;
init.ops = ops;
init.flags = CLK_IS_BASIC;
init.flags = 0;
co->hw.init = &init;
parent_names[0] = __clk_get_name(clk0);
parent_names[1] = __clk_get_name(clk1);
......
......@@ -165,7 +165,7 @@ static void __init omap_clk_register_apll(void *user,
ad->clk_bypass = __clk_get_hw(clk);
clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
kfree(clk_hw->hw.init->parent_names);
......@@ -402,7 +402,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
if (ret)
goto cleanup;
clk = clk_register(NULL, &clk_hw->hw);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
kfree(init);
......
......@@ -35,7 +35,44 @@ struct clk_ti_autoidle {
#define AUTOIDLE_LOW 0x1
static LIST_HEAD(autoidle_clks);
static LIST_HEAD(clk_hw_omap_clocks);
/*
* we have some non-atomic read/write
* operations behind it, so lets
* take one lock for handling autoidle
* of all clocks
*/
static DEFINE_SPINLOCK(autoidle_spinlock);
static int _omap2_clk_deny_idle(struct clk_hw_omap *clk)
{
if (clk->ops && clk->ops->deny_idle) {
unsigned long irqflags;
spin_lock_irqsave(&autoidle_spinlock, irqflags);
clk->autoidle_count++;
if (clk->autoidle_count == 1)
clk->ops->deny_idle(clk);
spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
}
return 0;
}
static int _omap2_clk_allow_idle(struct clk_hw_omap *clk)
{
if (clk->ops && clk->ops->allow_idle) {
unsigned long irqflags;
spin_lock_irqsave(&autoidle_spinlock, irqflags);
clk->autoidle_count--;
if (clk->autoidle_count == 0)
clk->ops->allow_idle(clk);
spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
}
return 0;
}
/**
* omap2_clk_deny_idle - disable autoidle on an OMAP clock
......@@ -45,12 +82,15 @@ static LIST_HEAD(clk_hw_omap_clocks);
*/
int omap2_clk_deny_idle(struct clk *clk)
{
struct clk_hw_omap *c;
struct clk_hw *hw = __clk_get_hw(clk);
c = to_clk_hw_omap(__clk_get_hw(clk));
if (c->ops && c->ops->deny_idle)
c->ops->deny_idle(c);
return 0;
if (omap2_clk_is_hw_omap(hw)) {
struct clk_hw_omap *c = to_clk_hw_omap(hw);
return _omap2_clk_deny_idle(c);
}
return -EINVAL;
}
/**
......@@ -61,12 +101,15 @@ int omap2_clk_deny_idle(struct clk *clk)
*/
int omap2_clk_allow_idle(struct clk *clk)
{
struct clk_hw_omap *c;
struct clk_hw *hw = __clk_get_hw(clk);
c = to_clk_hw_omap(__clk_get_hw(clk));
if (c->ops && c->ops->allow_idle)
c->ops->allow_idle(c);
return 0;
if (omap2_clk_is_hw_omap(hw)) {
struct clk_hw_omap *c = to_clk_hw_omap(hw);
return _omap2_clk_allow_idle(c);
}
return -EINVAL;
}
static void _allow_autoidle(struct clk_ti_autoidle *clk)
......@@ -167,26 +210,6 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
return 0;
}
/**
* omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
* @hw: struct clk_hw * to initialize
*
* Add an OMAP clock @clk to the internal list of OMAP clocks. Used
* temporarily for autoidle handling, until this support can be
* integrated into the common clock framework code in some way. No
* return value.
*/
void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
{
struct clk_hw_omap *c;
if (clk_hw_get_flags(hw) & CLK_IS_BASIC)
return;
c = to_clk_hw_omap(hw);
list_add(&c->node, &clk_hw_omap_clocks);
}
/**
* omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
* support it
......@@ -198,11 +221,11 @@ void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
*/
int omap2_clk_enable_autoidle_all(void)
{
struct clk_hw_omap *c;
int ret;
list_for_each_entry(c, &clk_hw_omap_clocks, node)
if (c->ops && c->ops->allow_idle)
c->ops->allow_idle(c);
ret = omap2_clk_for_each(_omap2_clk_allow_idle);
if (ret)
return ret;
_clk_generic_allow_autoidle_all();
......@@ -220,11 +243,11 @@ int omap2_clk_enable_autoidle_all(void)
*/
int omap2_clk_disable_autoidle_all(void)
{
struct clk_hw_omap *c;
int ret;
list_for_each_entry(c, &clk_hw_omap_clocks, node)
if (c->ops && c->ops->deny_idle)
c->ops->deny_idle(c);
ret = omap2_clk_for_each(_omap2_clk_deny_idle);
if (ret)
return ret;
_clk_generic_deny_autoidle_all();
......
......@@ -31,6 +31,7 @@
#undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt, __func__
static LIST_HEAD(clk_hw_omap_clocks);
struct ti_clk_ll_ops *ti_clk_ll_ops;
static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
......@@ -521,3 +522,74 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
return clk;
}
/**
* ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
* @dev: device for this clock
* @hw: hardware clock handle
* @con: connection ID for this clock
*
* Registers a clk_hw_omap clock to the clock framewor, adds a clock alias
* for it, and adds the list to the available clk_hw_omap type clocks.
* Returns a handle to the registered clock if successful, ERR_PTR value
* in failure.
*/
struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
const char *con)
{
struct clk *clk;
struct clk_hw_omap *oclk;
clk = ti_clk_register(dev, hw, con);
if (IS_ERR(clk))
return clk;
oclk = to_clk_hw_omap(hw);
list_add(&oclk->node, &clk_hw_omap_clocks);
return clk;
}
/**
* omap2_clk_for_each - call function for each registered clk_hw_omap
* @fn: pointer to a callback function
*
* Call @fn for each registered clk_hw_omap, passing @hw to each
* function. @fn must return 0 for success or any other value for
* failure. If @fn returns non-zero, the iteration across clocks
* will stop and the non-zero return value will be passed to the
* caller of omap2_clk_for_each().
*/
int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw))
{
int ret;
struct clk_hw_omap *hw;
list_for_each_entry(hw, &clk_hw_omap_clocks, node) {
ret = (*fn)(hw);
if (ret)
break;
}
return ret;
}
/**
* omap2_clk_is_hw_omap - check if the provided clk_hw is OMAP clock
* @hw: clk_hw to check if it is an omap clock or not
*
* Checks if the provided clk_hw is OMAP clock or not. Returns true if
* it is, false otherwise.
*/
bool omap2_clk_is_hw_omap(struct clk_hw *hw)
{
struct clk_hw_omap *oclk;
list_for_each_entry(oclk, &clk_hw_omap_clocks, node) {
if (&oclk->hw == hw)
return true;
}
return false;
}
......@@ -276,7 +276,7 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
init.parent_names = parents;
init.num_parents = num_parents;
init.ops = ops;
init.flags = CLK_IS_BASIC;
init.flags = 0;
clk = ti_clk_register(NULL, clk_hw, init.name);
if (IS_ERR_OR_NULL(clk)) {
......
......@@ -203,6 +203,8 @@ typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
const char *con);
struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
const char *con);
int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
void ti_clk_add_aliases(void);
......@@ -221,7 +223,6 @@ int ti_clk_retry_init(struct device_node *node, void *user,
ti_of_clk_init_cb_t func);
int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw);
int of_ti_clk_autoidle_setup(struct device_node *node);
void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
......@@ -301,6 +302,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
unsigned long *parent_rate);
int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req);
int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw));
bool omap2_clk_is_hw_omap(struct clk_hw *hw);
extern struct ti_clk_ll_ops *ti_clk_ll_ops;
......
......@@ -143,7 +143,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
continue;
}
clk_hw = __clk_get_hw(clk);
if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
if (!omap2_clk_is_hw_omap(clk_hw)) {
pr_warn("can't setup clkdm for basic clk %s\n",
__clk_get_name(clk));
continue;
......
......@@ -336,7 +336,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
init.name = name;
init.ops = &ti_clk_divider_ops;
init.flags = flags | CLK_IS_BASIC;
init.flags = flags;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
......
......@@ -192,10 +192,9 @@ static void __init _register_dpll(void *user,
dd->clk_bypass = __clk_get_hw(clk);
/* register the clock */
clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
if (!IS_ERR(clk)) {
omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
of_clk_add_provider(node, of_clk_src_simple_get, clk);
kfree(clk_hw->hw.init->parent_names);
kfree(clk_hw->hw.init);
......@@ -265,14 +264,12 @@ static void _register_dpll_x2(struct device_node *node,
#endif
/* register the clock */
clk = ti_clk_register(NULL, &clk_hw->hw, name);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
if (IS_ERR(clk)) {
if (IS_ERR(clk))
kfree(clk_hw);
} else {
omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
else
of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
}
#endif
......
......@@ -731,7 +731,7 @@ static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
do {
do {
hw = clk_hw_get_parent(hw);
} while (hw && (clk_hw_get_flags(hw) & CLK_IS_BASIC));
} while (hw && (!omap2_clk_is_hw_omap(hw)));
if (!hw)
break;
pclk = to_clk_hw_omap(hw);
......
......@@ -123,7 +123,7 @@ static struct clk *_register_gate(struct device *dev, const char *name,
init.flags = flags;
clk = ti_clk_register(NULL, &clk_hw->hw, name);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
if (IS_ERR(clk))
kfree(clk_hw);
......
......@@ -57,12 +57,10 @@ static struct clk *_register_interface(struct device *dev, const char *name,
init.num_parents = 1;
init.parent_names = &parent_name;
clk = ti_clk_register(NULL, &clk_hw->hw, name);
clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
if (IS_ERR(clk))
kfree(clk_hw);
else
omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
return clk;
}
......
......@@ -143,7 +143,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
init.name = name;
init.ops = &ti_clk_mux_ops;
init.flags = flags | CLK_IS_BASIC;
init.flags = flags;
init.parent_names = parent_names;
init.num_parents = num_parents;
......
......@@ -47,7 +47,7 @@ static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
return ret;
ret = regmap_write_bits(gear->regmap,
gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
UNIPHIER_CLK_CPUGEAR_UPD_BIT,
UNIPHIER_CLK_CPUGEAR_UPD_BIT);
if (ret)
......
......@@ -156,7 +156,7 @@
#define CLK_ACLK_G2D_266 220
#define CLK_ACLK_G2D_400 221
#define CLK_ACLK_G3D_400 222
#define CLK_ACLK_IMEM_SSX_266 223
#define CLK_ACLK_IMEM_SSSX_266 223
#define CLK_ACLK_BUS0_400 224
#define CLK_ACLK_BUS1_400 225
#define CLK_ACLK_IMEM_200 226
......@@ -1406,4 +1406,10 @@
#define CAM1_NR_CLK 113
/* CMU_IMEM */
#define CLK_ACLK_SLIMSSS 2
#define CLK_PCLK_SLIMSSS 35
#define IMEM_NR_CLK 36
#endif /* _DT_BINDINGS_CLOCK_EXYNOS5433_H */
......@@ -214,6 +214,7 @@
#define IMX5_CLK_IEEE1588_SEL 202
#define IMX5_CLK_IEEE1588_PODF 203
#define IMX5_CLK_IEEE1588_GATE 204
#define IMX5_CLK_END 205
#define IMX5_CLK_SCC2_IPG_GATE 205
#define IMX5_CLK_END 206
#endif /* __DT_BINDINGS_CLOCK_IMX5_H */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2017-2018 NXP
*/
#ifndef __DT_BINDINGS_CLOCK_IMX8MM_H
#define __DT_BINDINGS_CLOCK_IMX8MM_H
#define IMX8MM_CLK_DUMMY 0
#define IMX8MM_CLK_32K 1
#define IMX8MM_CLK_24M 2
#define IMX8MM_OSC_HDMI_CLK 3
#define IMX8MM_CLK_EXT1 4
#define IMX8MM_CLK_EXT2 5
#define IMX8MM_CLK_EXT3 6
#define IMX8MM_CLK_EXT4 7
#define IMX8MM_AUDIO_PLL1_REF_SEL 8
#define IMX8MM_AUDIO_PLL2_REF_SEL 9
#define IMX8MM_VIDEO_PLL1_REF_SEL 10
#define IMX8MM_DRAM_PLL_REF_SEL 11
#define IMX8MM_GPU_PLL_REF_SEL 12
#define IMX8MM_VPU_PLL_REF_SEL 13
#define IMX8MM_ARM_PLL_REF_SEL 14
#define IMX8MM_SYS_PLL1_REF_SEL 15
#define IMX8MM_SYS_PLL2_REF_SEL 16
#define IMX8MM_SYS_PLL3_REF_SEL 17
#define IMX8MM_AUDIO_PLL1 18
#define IMX8MM_AUDIO_PLL2 19
#define IMX8MM_VIDEO_PLL1 20
#define IMX8MM_DRAM_PLL 21
#define IMX8MM_GPU_PLL 22
#define IMX8MM_VPU_PLL 23
#define IMX8MM_ARM_PLL 24
#define IMX8MM_SYS_PLL1 25
#define IMX8MM_SYS_PLL2 26
#define IMX8MM_SYS_PLL3 27
#define IMX8MM_AUDIO_PLL1_BYPASS 28
#define IMX8MM_AUDIO_PLL2_BYPASS 29
#define IMX8MM_VIDEO_PLL1_BYPASS 30
#define IMX8MM_DRAM_PLL_BYPASS 31
#define IMX8MM_GPU_PLL_BYPASS 32
#define IMX8MM_VPU_PLL_BYPASS 33
#define IMX8MM_ARM_PLL_BYPASS 34
#define IMX8MM_SYS_PLL1_BYPASS 35
#define IMX8MM_SYS_PLL2_BYPASS 36
#define IMX8MM_SYS_PLL3_BYPASS 37
#define IMX8MM_AUDIO_PLL1_OUT 38
#define IMX8MM_AUDIO_PLL2_OUT 39
#define IMX8MM_VIDEO_PLL1_OUT 40
#define IMX8MM_DRAM_PLL_OUT 41
#define IMX8MM_GPU_PLL_OUT 42
#define IMX8MM_VPU_PLL_OUT 43
#define IMX8MM_ARM_PLL_OUT 44
#define IMX8MM_SYS_PLL1_OUT 45
#define IMX8MM_SYS_PLL2_OUT 46
#define IMX8MM_SYS_PLL3_OUT 47
#define IMX8MM_SYS_PLL1_40M 48
#define IMX8MM_SYS_PLL1_80M 49
#define IMX8MM_SYS_PLL1_100M 50
#define IMX8MM_SYS_PLL1_133M 51
#define IMX8MM_SYS_PLL1_160M 52
#define IMX8MM_SYS_PLL1_200M 53
#define IMX8MM_SYS_PLL1_266M 54
#define IMX8MM_SYS_PLL1_400M 55
#define IMX8MM_SYS_PLL1_800M 56
#define IMX8MM_SYS_PLL2_50M 57
#define IMX8MM_SYS_PLL2_100M 58
#define IMX8MM_SYS_PLL2_125M 59
#define IMX8MM_SYS_PLL2_166M 60
#define IMX8MM_SYS_PLL2_200M 61
#define IMX8MM_SYS_PLL2_250M 62
#define IMX8MM_SYS_PLL2_333M 63
#define IMX8MM_SYS_PLL2_500M 64
#define IMX8MM_SYS_PLL2_1000M 65
/* core */
#define IMX8MM_CLK_A53_SRC 66
#define IMX8MM_CLK_M4_SRC 67
#define IMX8MM_CLK_VPU_SRC 68
#define IMX8MM_CLK_GPU3D_SRC 69
#define IMX8MM_CLK_GPU2D_SRC 70
#define IMX8MM_CLK_A53_CG 71
#define IMX8MM_CLK_M4_CG 72
#define IMX8MM_CLK_VPU_CG 73
#define IMX8MM_CLK_GPU3D_CG 74
#define IMX8MM_CLK_GPU2D_CG 75
#define IMX8MM_CLK_A53_DIV 76
#define IMX8MM_CLK_M4_DIV 77
#define IMX8MM_CLK_VPU_DIV 78
#define IMX8MM_CLK_GPU3D_DIV 79
#define IMX8MM_CLK_GPU2D_DIV 80
/* bus */
#define IMX8MM_CLK_MAIN_AXI 81
#define IMX8MM_CLK_ENET_AXI 82
#define IMX8MM_CLK_NAND_USDHC_BUS 83
#define IMX8MM_CLK_VPU_BUS 84
#define IMX8MM_CLK_DISP_AXI 85
#define IMX8MM_CLK_DISP_APB 86
#define IMX8MM_CLK_DISP_RTRM 87
#define IMX8MM_CLK_USB_BUS 88
#define IMX8MM_CLK_GPU_AXI 89
#define IMX8MM_CLK_GPU_AHB 90
#define IMX8MM_CLK_NOC 91
#define IMX8MM_CLK_NOC_APB 92
#define IMX8MM_CLK_AHB 93
#define IMX8MM_CLK_AUDIO_AHB 94
#define IMX8MM_CLK_IPG_ROOT 95
#define IMX8MM_CLK_IPG_AUDIO_ROOT 96
#define IMX8MM_CLK_DRAM_ALT 97
#define IMX8MM_CLK_DRAM_APB 98
#define IMX8MM_CLK_VPU_G1 99
#define IMX8MM_CLK_VPU_G2 100
#define IMX8MM_CLK_DISP_DTRC 101
#define IMX8MM_CLK_DISP_DC8000 102
#define IMX8MM_CLK_PCIE1_CTRL 103
#define IMX8MM_CLK_PCIE1_PHY 104
#define IMX8MM_CLK_PCIE1_AUX 105
#define IMX8MM_CLK_DC_PIXEL 106
#define IMX8MM_CLK_LCDIF_PIXEL 107
#define IMX8MM_CLK_SAI1 108
#define IMX8MM_CLK_SAI2 109
#define IMX8MM_CLK_SAI3 110
#define IMX8MM_CLK_SAI4 111
#define IMX8MM_CLK_SAI5 112
#define IMX8MM_CLK_SAI6 113
#define IMX8MM_CLK_SPDIF1 114
#define IMX8MM_CLK_SPDIF2 115
#define IMX8MM_CLK_ENET_REF 116
#define IMX8MM_CLK_ENET_TIMER 117
#define IMX8MM_CLK_ENET_PHY_REF 118
#define IMX8MM_CLK_NAND 119
#define IMX8MM_CLK_QSPI 120
#define IMX8MM_CLK_USDHC1 121
#define IMX8MM_CLK_USDHC2 122
#define IMX8MM_CLK_I2C1 123
#define IMX8MM_CLK_I2C2 124
#define IMX8MM_CLK_I2C3 125
#define IMX8MM_CLK_I2C4 126
#define IMX8MM_CLK_UART1 127
#define IMX8MM_CLK_UART2 128
#define IMX8MM_CLK_UART3 129
#define IMX8MM_CLK_UART4 130
#define IMX8MM_CLK_USB_CORE_REF 131
#define IMX8MM_CLK_USB_PHY_REF 132
#define IMX8MM_CLK_ECSPI1 133
#define IMX8MM_CLK_ECSPI2 134
#define IMX8MM_CLK_PWM1 135
#define IMX8MM_CLK_PWM2 136
#define IMX8MM_CLK_PWM3 137
#define IMX8MM_CLK_PWM4 138
#define IMX8MM_CLK_GPT1 139
#define IMX8MM_CLK_WDOG 140
#define IMX8MM_CLK_WRCLK 141
#define IMX8MM_CLK_DSI_CORE 142
#define IMX8MM_CLK_DSI_PHY_REF 143
#define IMX8MM_CLK_DSI_DBI 144
#define IMX8MM_CLK_USDHC3 145
#define IMX8MM_CLK_CSI1_CORE 146
#define IMX8MM_CLK_CSI1_PHY_REF 147
#define IMX8MM_CLK_CSI1_ESC 148
#define IMX8MM_CLK_CSI2_CORE 149
#define IMX8MM_CLK_CSI2_PHY_REF 150
#define IMX8MM_CLK_CSI2_ESC 151
#define IMX8MM_CLK_PCIE2_CTRL 152
#define IMX8MM_CLK_PCIE2_PHY 153
#define IMX8MM_CLK_PCIE2_AUX 154
#define IMX8MM_CLK_ECSPI3 155
#define IMX8MM_CLK_PDM 156
#define IMX8MM_CLK_VPU_H1 157
#define IMX8MM_CLK_CLKO1 158
#define IMX8MM_CLK_ECSPI1_ROOT 159
#define IMX8MM_CLK_ECSPI2_ROOT 160
#define IMX8MM_CLK_ECSPI3_ROOT 161
#define IMX8MM_CLK_ENET1_ROOT 162
#define IMX8MM_CLK_GPT1_ROOT 163
#define IMX8MM_CLK_I2C1_ROOT 164
#define IMX8MM_CLK_I2C2_ROOT 165
#define IMX8MM_CLK_I2C3_ROOT 166
#define IMX8MM_CLK_I2C4_ROOT 167
#define IMX8MM_CLK_OCOTP_ROOT 168
#define IMX8MM_CLK_PCIE1_ROOT 169
#define IMX8MM_CLK_PWM1_ROOT 170
#define IMX8MM_CLK_PWM2_ROOT 171
#define IMX8MM_CLK_PWM3_ROOT 172
#define IMX8MM_CLK_PWM4_ROOT 173
#define IMX8MM_CLK_QSPI_ROOT 174
#define IMX8MM_CLK_NAND_ROOT 175
#define IMX8MM_CLK_SAI1_ROOT 176
#define IMX8MM_CLK_SAI1_IPG 177
#define IMX8MM_CLK_SAI2_ROOT 178
#define IMX8MM_CLK_SAI2_IPG 179
#define IMX8MM_CLK_SAI3_ROOT 180
#define IMX8MM_CLK_SAI3_IPG 181
#define IMX8MM_CLK_SAI4_ROOT 182
#define IMX8MM_CLK_SAI4_IPG 183
#define IMX8MM_CLK_SAI5_ROOT 184
#define IMX8MM_CLK_SAI5_IPG 185
#define IMX8MM_CLK_SAI6_ROOT 186
#define IMX8MM_CLK_SAI6_IPG 187
#define IMX8MM_CLK_UART1_ROOT 188
#define IMX8MM_CLK_UART2_ROOT 189
#define IMX8MM_CLK_UART3_ROOT 190
#define IMX8MM_CLK_UART4_ROOT 191
#define IMX8MM_CLK_USB1_CTRL_ROOT 192
#define IMX8MM_CLK_GPU3D_ROOT 193
#define IMX8MM_CLK_USDHC1_ROOT 194
#define IMX8MM_CLK_USDHC2_ROOT 195
#define IMX8MM_CLK_WDOG1_ROOT 196
#define IMX8MM_CLK_WDOG2_ROOT 197
#define IMX8MM_CLK_WDOG3_ROOT 198
#define IMX8MM_CLK_VPU_G1_ROOT 199
#define IMX8MM_CLK_GPU_BUS_ROOT 200
#define IMX8MM_CLK_VPU_H1_ROOT 201
#define IMX8MM_CLK_VPU_G2_ROOT 202
#define IMX8MM_CLK_PDM_ROOT 203
#define IMX8MM_CLK_DISP_ROOT 204
#define IMX8MM_CLK_DISP_AXI_ROOT 205
#define IMX8MM_CLK_DISP_APB_ROOT 206
#define IMX8MM_CLK_DISP_RTRM_ROOT 207
#define IMX8MM_CLK_USDHC3_ROOT 208
#define IMX8MM_CLK_TMU_ROOT 209
#define IMX8MM_CLK_VPU_DEC_ROOT 210
#define IMX8MM_CLK_SDMA1_ROOT 211
#define IMX8MM_CLK_SDMA2_ROOT 212
#define IMX8MM_CLK_SDMA3_ROOT 213
#define IMX8MM_CLK_GPT_3M 214
#define IMX8MM_CLK_ARM 215
#define IMX8MM_CLK_PDM_IPG 216
#define IMX8MM_CLK_GPU2D_ROOT 217
#define IMX8MM_CLK_MU_ROOT 218
#define IMX8MM_CLK_CSI1_ROOT 219
#define IMX8MM_CLK_DRAM_CORE 220
#define IMX8MM_CLK_DRAM_ALT_ROOT 221
#define IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK 222
#define IMX8MM_CLK_END 223
#endif
......@@ -391,5 +391,14 @@
#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK 267
#define IMX8MQ_CLK_END 268
#define IMX8MQ_CLK_CLKO1 268
#define IMX8MQ_CLK_ARM 269
#define IMX8MQ_CLK_GPIO1_ROOT 270
#define IMX8MQ_CLK_GPIO2_ROOT 271
#define IMX8MQ_CLK_GPIO3_ROOT 272
#define IMX8MQ_CLK_GPIO4_ROOT 273
#define IMX8MQ_CLK_GPIO5_ROOT 274
#define IMX8MQ_CLK_END 275
#endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */
......@@ -71,6 +71,7 @@
#define MMP2_CLK_CCIC1_MIX 117
#define MMP2_CLK_CCIC1_PHY 118
#define MMP2_CLK_CCIC1_SPHY 119
#define MMP2_CLK_DISP0_LCDC 120
#define MMP2_NR_CLKS 200
#endif
......@@ -160,6 +160,7 @@ struct clk_hw_omap {
struct clockdomain *clkdm;
const struct clk_hw_omap_ops *ops;
u32 context;
int autoidle_count;
};
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment