mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 09:16:06 +07:00
Merge branches 'clk-tegra', 'clk-imx', 'clk-zynq', 'clk-socfpga', 'clk-at91' and 'clk-ti' into clk-next
- Support custom flags in Xilinx zynq firmware - Various small fixes to the Xilinx clk driver - Support for Intel Agilex clks * clk-tegra: clk: tegra: Add Tegra210 CSI TPG clock gate clk: tegra30: Use custom CCLK implementation clk: tegra20: Use custom CCLK implementation clk: tegra: cclk: Add helpers for handling PLLX rate changes clk: tegra: pll: Add pre/post rate-change hooks clk: tegra: Add custom CCLK implementation clk: tegra: Remove the old emc_mux clock for Tegra210 clk: tegra: Implement Tegra210 EMC clock clk: tegra: Export functions for EMC clock scaling clk: tegra: Add PLLP_UD and PLLMB_UD for Tegra210 clk: tegra: Rename Tegra124 EMC clock source file dt-bindings: clock: tegra: Add clock ID for CSI TPG clock * clk-imx: clk: imx: use imx8m_clk_hw_composite_bus for i.MX8M bus clk slice clk: imx: add imx8m_clk_hw_composite_bus clk: imx: add mux ops for i.MX8M composite clk clk: imx8m: migrate A53 clk root to use composite core clk: imx8mp: use imx8m_clk_hw_composite_core to simplify code clk: imx8mp: Define gates for pll1/2 fixed dividers clk: imx: imx8mp: fix pll mux bit clk: imx8m: drop clk_hw_set_parent for A53 dt-bindings: clocks: imx8mp: Add ids for audiomix clocks clk: imx: Add helpers for passing the device as argument clk: imx: pll14xx: Add the device as argument when registering clk: imx: gate2: Allow single bit gating clock clk: imx: clk-pllv3: Use readl_relaxed_poll_timeout() for PLL lock wait clk: imx: clk-sscg-pll: Remove unnecessary blank lines clk: imx: drop the dependency on ARM64 for i.MX8M clk: imx7ulp: make it easy to change ARM core clk clk: imx: imx6ul: change flexcan clock to support CiA bitrates * clk-zynq: clk: zynqmp: Make zynqmp_clk_get_max_divisor static clk: zynqmp: Update fraction clock check from custom type flags clk: zynqmp: Add support for custom type flags clk: zynqmp: fix memory leak in zynqmp_register_clocks clk: zynqmp: Fix invalid clock name queries clk: zynqmp: Fix divider2 calculation clk: zynqmp: Limit bestdiv with maxdiv * clk-socfpga: clk: socfpga: agilex: add clock driver for the Agilex platform dt-bindings: documentation: add clock bindings information for Agilex clk: socfpga: add const to _ops data structures clk: socfpga: remove clk_ops enable/disable methods clk: socfpga: stratix10: use new parent data scheme * clk-at91: clk: at91: allow setting all PMC clock parents via DT clk: at91: allow setting PCKx parent via DT clk: at91: optimize pmc data allocation clk: at91: pmc: decrement node's refcount clk: at91: pmc: do not continue if compatible not located clk: at91: Add peripheral clock for PTC * clk-ti: clk: ti: dra7: remove two unused symbols clk: ti: dra7xx: fix RNG clock parent clk: ti: dra7xx: mark MCAN clock as DRA76x only clk: ti: dra7xx: fix gpu clkctrl parent clk: ti: omap5: Add proper parent clocks for l4-secure clocks clk: ti: omap4: Add proper parent clocks for l4-secure clocks clk: ti: composite: fix memory leak
This commit is contained in:
commit
8c88e568b5
46
Documentation/devicetree/bindings/clock/intel,agilex.yaml
Normal file
46
Documentation/devicetree/bindings/clock/intel,agilex.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/intel,agilex.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Intel SoCFPGA Agilex platform clock controller binding
|
||||
|
||||
maintainers:
|
||||
- Dinh Nguyen <dinguyen@kernel.org>
|
||||
|
||||
description:
|
||||
The Intel Agilex Clock controller is an integrated clock controller, which
|
||||
generates and supplies to all modules.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: intel,agilex-clkmgr
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Clock controller node:
|
||||
- |
|
||||
clkmgr: clock-controller@ffd10000 {
|
||||
compatible = "intel,agilex-clkmgr";
|
||||
reg = <0xffd10000 0x1000>;
|
||||
clocks = <&osc1>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
...
|
@ -104,10 +104,11 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
|
||||
obj-$(CONFIG_CLK_SIFIVE) += sifive/
|
||||
obj-$(CONFIG_ARCH_SIRF) += sirf/
|
||||
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
|
||||
obj-$(CONFIG_ARCH_AGILEX) += socfpga/
|
||||
obj-$(CONFIG_ARCH_STRATIX10) += socfpga/
|
||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||
obj-$(CONFIG_ARCH_SPRD) += sprd/
|
||||
obj-$(CONFIG_ARCH_STI) += st/
|
||||
obj-$(CONFIG_ARCH_STRATIX10) += socfpga/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
|
@ -98,9 +98,9 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91rm9200_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
at91rm9200_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
|
||||
nck(at91rm9200_systemck),
|
||||
nck(at91rm9200_periphck), 0);
|
||||
nck(at91rm9200_periphck), 0, 4);
|
||||
if (!at91rm9200_pmc)
|
||||
return;
|
||||
|
||||
@ -123,12 +123,16 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91rm9200_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
|
||||
&at91rm9200_pll_layout,
|
||||
&rm9200_pll_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91rm9200_pmc->chws[PMC_PLLBCK] = hw;
|
||||
|
||||
parent_names[0] = slowxtal_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
@ -159,6 +163,8 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
&at91rm9200_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91rm9200_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91rm9200_systemck); i++) {
|
||||
@ -187,7 +193,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91rm9200_pmc);
|
||||
kfree(at91rm9200_pmc);
|
||||
}
|
||||
/*
|
||||
* While the TCB can be used as the clocksource, the system timer is most likely
|
||||
|
@ -352,9 +352,10 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9260_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
at91sam9260_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
|
||||
ndck(data->sck, data->num_sck),
|
||||
ndck(data->pck, data->num_pck), 0);
|
||||
ndck(data->pck, data->num_pck),
|
||||
0, data->num_progck);
|
||||
if (!at91sam9260_pmc)
|
||||
return;
|
||||
|
||||
@ -398,12 +399,16 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
|
||||
data->pllb_layout,
|
||||
data->pllb_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->chws[PMC_PLLBCK] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
@ -434,6 +439,8 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
&at91rm9200_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->num_sck; i++) {
|
||||
@ -462,7 +469,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9260_pmc);
|
||||
kfree(at91sam9260_pmc);
|
||||
}
|
||||
|
||||
static void __init at91sam9260_pmc_setup(struct device_node *np)
|
||||
|
@ -115,9 +115,9 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9g45_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
at91sam9g45_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(at91sam9g45_systemck),
|
||||
nck(at91sam9g45_periphck), 0);
|
||||
nck(at91sam9g45_periphck), 0, 2);
|
||||
if (!at91sam9g45_pmc)
|
||||
return;
|
||||
|
||||
@ -143,6 +143,8 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9g45_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
@ -182,6 +184,8 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
&at91sam9g45_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9g45_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9g45_systemck); i++) {
|
||||
@ -210,7 +214,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9g45_pmc);
|
||||
kfree(at91sam9g45_pmc);
|
||||
}
|
||||
/*
|
||||
* The TCB is used as the clocksource so its clock is needed early. This means
|
||||
|
@ -128,8 +128,8 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9n12_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
nck(at91sam9n12_systemck), 31, 0);
|
||||
at91sam9n12_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
|
||||
nck(at91sam9n12_systemck), 31, 0, 2);
|
||||
if (!at91sam9n12_pmc)
|
||||
return;
|
||||
|
||||
@ -162,11 +162,15 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9n12_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
|
||||
&at91rm9200_pll_layout, &pllb_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9n12_pmc->chws[PMC_PLLBCK] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
@ -198,6 +202,8 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9n12_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9n12_systemck); i++) {
|
||||
@ -228,7 +234,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9n12_pmc);
|
||||
kfree(at91sam9n12_pmc);
|
||||
}
|
||||
/*
|
||||
* The TCB is used as the clocksource so its clock is needed early. This means
|
||||
|
@ -87,9 +87,9 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
at91sam9rl_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(at91sam9rl_systemck),
|
||||
nck(at91sam9rl_periphck), 0);
|
||||
nck(at91sam9rl_periphck), 0, 2);
|
||||
if (!at91sam9rl_pmc)
|
||||
return;
|
||||
|
||||
@ -105,6 +105,8 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
@ -138,6 +140,8 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
&at91rm9200_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
|
||||
@ -166,6 +170,6 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9rl_pmc);
|
||||
kfree(at91sam9rl_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
|
||||
|
@ -150,8 +150,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
nck(at91sam9x5_systemck), 31, 0);
|
||||
at91sam9x5_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(at91sam9x5_systemck), 31, 0, 2);
|
||||
if (!at91sam9x5_pmc)
|
||||
return;
|
||||
|
||||
@ -184,6 +184,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
@ -227,6 +229,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
|
||||
@ -278,7 +282,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9x5_pmc);
|
||||
kfree(at91sam9x5_pmc);
|
||||
}
|
||||
|
||||
static void __init at91sam9g15_pmc_setup(struct device_node *np)
|
||||
|
@ -67,6 +67,10 @@ struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
|
||||
if (idx < pmc_data->ngck)
|
||||
return pmc_data->ghws[idx];
|
||||
break;
|
||||
case PMC_TYPE_PROGRAMMABLE:
|
||||
if (idx < pmc_data->npck)
|
||||
return pmc_data->pchws[idx];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -76,48 +80,34 @@ struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
void pmc_data_free(struct pmc_data *pmc_data)
|
||||
{
|
||||
kfree(pmc_data->chws);
|
||||
kfree(pmc_data->shws);
|
||||
kfree(pmc_data->phws);
|
||||
kfree(pmc_data->ghws);
|
||||
}
|
||||
|
||||
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
|
||||
unsigned int nperiph, unsigned int ngck)
|
||||
unsigned int nperiph, unsigned int ngck,
|
||||
unsigned int npck)
|
||||
{
|
||||
struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
|
||||
unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
|
||||
struct pmc_data *pmc_data;
|
||||
|
||||
pmc_data = kzalloc(struct_size(pmc_data, hwtable, num_clks),
|
||||
GFP_KERNEL);
|
||||
if (!pmc_data)
|
||||
return NULL;
|
||||
|
||||
pmc_data->ncore = ncore;
|
||||
pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->chws)
|
||||
goto err;
|
||||
pmc_data->chws = pmc_data->hwtable;
|
||||
|
||||
pmc_data->nsystem = nsystem;
|
||||
pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->shws)
|
||||
goto err;
|
||||
pmc_data->shws = pmc_data->chws + ncore;
|
||||
|
||||
pmc_data->nperiph = nperiph;
|
||||
pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->phws)
|
||||
goto err;
|
||||
pmc_data->phws = pmc_data->shws + nsystem;
|
||||
|
||||
pmc_data->ngck = ngck;
|
||||
pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->ghws)
|
||||
goto err;
|
||||
pmc_data->ghws = pmc_data->phws + nperiph;
|
||||
|
||||
pmc_data->npck = npck;
|
||||
pmc_data->pchws = pmc_data->ghws + ngck;
|
||||
|
||||
return pmc_data;
|
||||
|
||||
err:
|
||||
pmc_data_free(pmc_data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -274,8 +264,11 @@ static int __init pmc_register_ops(void)
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
pmcreg = device_node_to_regmap(np);
|
||||
of_node_put(np);
|
||||
if (IS_ERR(pmcreg))
|
||||
return PTR_ERR(pmcreg);
|
||||
|
||||
|
@ -24,6 +24,10 @@ struct pmc_data {
|
||||
struct clk_hw **phws;
|
||||
unsigned int ngck;
|
||||
struct clk_hw **ghws;
|
||||
unsigned int npck;
|
||||
struct clk_hw **pchws;
|
||||
|
||||
struct clk_hw *hwtable[];
|
||||
};
|
||||
|
||||
struct clk_range {
|
||||
@ -94,8 +98,8 @@ struct clk_pcr_layout {
|
||||
#define ndck(a, s) (a[s - 1].id + 1)
|
||||
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
|
||||
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
|
||||
unsigned int nperiph, unsigned int ngck);
|
||||
void pmc_data_free(struct pmc_data *pmc_data);
|
||||
unsigned int nperiph, unsigned int ngck,
|
||||
unsigned int npck);
|
||||
|
||||
int of_at91_get_clk_range(struct device_node *np, const char *propname,
|
||||
struct clk_range *range);
|
||||
|
@ -182,10 +182,10 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sam9x60_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
sam9x60_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(sam9x60_systemck),
|
||||
nck(sam9x60_periphck),
|
||||
nck(sam9x60_gck));
|
||||
nck(sam9x60_gck), 8);
|
||||
if (!sam9x60_pmc)
|
||||
return;
|
||||
|
||||
@ -214,6 +214,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sam9x60_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck",
|
||||
"main_osc", 1, &upll_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
@ -255,6 +257,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
&sam9x60_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sam9x60_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
|
||||
@ -299,7 +303,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sam9x60_pmc);
|
||||
kfree(sam9x60_pmc);
|
||||
}
|
||||
/* Some clks are used for a clocksource */
|
||||
CLK_OF_DECLARE(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup);
|
||||
|
@ -89,6 +89,7 @@ static const struct {
|
||||
{ .n = "i2s1_clk", .id = 55, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "can0_clk", .id = 56, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "can1_clk", .id = 57, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "ptc_clk", .id = 58, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "classd_clk", .id = 59, .r = { .min = 0, .max = 83000000 }, },
|
||||
};
|
||||
|
||||
@ -166,10 +167,10 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama5d2_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
|
||||
sama5d2_pmc = pmc_data_allocate(PMC_AUDIOPLLCK + 1,
|
||||
nck(sama5d2_systemck),
|
||||
nck(sama5d2_periph32ck),
|
||||
nck(sama5d2_gck));
|
||||
nck(sama5d2_gck), 3);
|
||||
if (!sama5d2_pmc)
|
||||
return;
|
||||
|
||||
@ -202,6 +203,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_audio_pll_frac(regmap, "audiopll_fracck",
|
||||
"mainck");
|
||||
if (IS_ERR(hw))
|
||||
@ -217,6 +220,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_AUDIOPLLCK] = hw;
|
||||
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
regmap_sfr = NULL;
|
||||
@ -267,6 +272,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
&sama5d2_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
|
||||
@ -350,6 +357,6 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sama5d2_pmc);
|
||||
kfree(sama5d2_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
|
||||
|
@ -125,9 +125,9 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama5d3_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
sama5d3_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(sama5d3_systemck),
|
||||
nck(sama5d3_periphck), 0);
|
||||
nck(sama5d3_periphck), 0, 3);
|
||||
if (!sama5d3_pmc)
|
||||
return;
|
||||
|
||||
@ -158,6 +158,8 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d3_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
@ -201,6 +203,8 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d3_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d3_systemck); i++) {
|
||||
@ -231,7 +235,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sama5d3_pmc);
|
||||
kfree(sama5d3_pmc);
|
||||
}
|
||||
/*
|
||||
* The TCB is used as the clocksource so its clock is needed early. This means
|
||||
|
@ -140,9 +140,9 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1,
|
||||
sama5d4_pmc = pmc_data_allocate(PMC_PLLACK + 1,
|
||||
nck(sama5d4_systemck),
|
||||
nck(sama5d4_periph32ck), 0);
|
||||
nck(sama5d4_periph32ck), 0, 3);
|
||||
if (!sama5d4_pmc)
|
||||
return;
|
||||
|
||||
@ -173,6 +173,8 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->chws[PMC_PLLACK] = hw;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
@ -224,6 +226,8 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->pchws[i] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
|
||||
@ -267,6 +271,6 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sama5d4_pmc);
|
||||
kfree(sama5d4_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
|
||||
|
@ -10,25 +10,25 @@ config MXC_CLK_SCU
|
||||
|
||||
config CLK_IMX8MM
|
||||
bool "IMX8MM CCM Clock Driver"
|
||||
depends on ARCH_MXC && ARM64
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
Build the driver for i.MX8MM CCM Clock Driver
|
||||
|
||||
config CLK_IMX8MN
|
||||
bool "IMX8MN CCM Clock Driver"
|
||||
depends on ARCH_MXC && ARM64
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
Build the driver for i.MX8MN CCM Clock Driver
|
||||
|
||||
config CLK_IMX8MP
|
||||
bool "IMX8MP CCM Clock Driver"
|
||||
depends on ARCH_MXC && ARM64
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
Build the driver for i.MX8MP CCM Clock Driver
|
||||
|
||||
config CLK_IMX8MQ
|
||||
bool "IMX8MQ CCM Clock Driver"
|
||||
depends on ARCH_MXC && ARM64
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
Build the driver for i.MX8MQ CCM Clock Driver
|
||||
|
||||
|
@ -124,6 +124,52 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
|
||||
.set_rate = imx8m_clk_composite_divider_set_rate,
|
||||
};
|
||||
|
||||
static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
return clk_mux_ops.get_parent(hw);
|
||||
}
|
||||
|
||||
static int imx8m_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_mux *mux = to_clk_mux(hw);
|
||||
u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
|
||||
unsigned long flags = 0;
|
||||
u32 reg;
|
||||
|
||||
if (mux->lock)
|
||||
spin_lock_irqsave(mux->lock, flags);
|
||||
|
||||
reg = readl(mux->reg);
|
||||
reg &= ~(mux->mask << mux->shift);
|
||||
val = val << mux->shift;
|
||||
reg |= val;
|
||||
/*
|
||||
* write twice to make sure non-target interface
|
||||
* SEL_A/B point the same clk input.
|
||||
*/
|
||||
writel(reg, mux->reg);
|
||||
writel(reg, mux->reg);
|
||||
|
||||
if (mux->lock)
|
||||
spin_unlock_irqrestore(mux->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
imx8m_clk_composite_mux_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
return clk_mux_ops.determine_rate(hw, req);
|
||||
}
|
||||
|
||||
|
||||
static const struct clk_ops imx8m_clk_composite_mux_ops = {
|
||||
.get_parent = imx8m_clk_composite_mux_get_parent,
|
||||
.set_parent = imx8m_clk_composite_mux_set_parent,
|
||||
.determine_rate = imx8m_clk_composite_mux_determine_rate,
|
||||
};
|
||||
|
||||
struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
const char * const *parent_names,
|
||||
int num_parents, void __iomem *reg,
|
||||
@ -136,6 +182,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
struct clk_gate *gate = NULL;
|
||||
struct clk_mux *mux = NULL;
|
||||
const struct clk_ops *divider_ops;
|
||||
const struct clk_ops *mux_ops;
|
||||
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
@ -157,10 +204,17 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
div->shift = PCG_DIV_SHIFT;
|
||||
div->width = PCG_CORE_DIV_WIDTH;
|
||||
divider_ops = &clk_divider_ops;
|
||||
mux_ops = &imx8m_clk_composite_mux_ops;
|
||||
} else if (composite_flags & IMX_COMPOSITE_BUS) {
|
||||
div->shift = PCG_PREDIV_SHIFT;
|
||||
div->width = PCG_PREDIV_WIDTH;
|
||||
divider_ops = &imx8m_clk_composite_divider_ops;
|
||||
mux_ops = &imx8m_clk_composite_mux_ops;
|
||||
} else {
|
||||
div->shift = PCG_PREDIV_SHIFT;
|
||||
div->width = PCG_PREDIV_WIDTH;
|
||||
divider_ops = &imx8m_clk_composite_divider_ops;
|
||||
mux_ops = &clk_mux_ops;
|
||||
}
|
||||
|
||||
div->lock = &imx_ccm_lock;
|
||||
@ -176,7 +230,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
gate->lock = &imx_ccm_lock;
|
||||
|
||||
hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
|
||||
mux_hw, &clk_mux_ops, div_hw,
|
||||
mux_hw, mux_ops, div_hw,
|
||||
divider_ops, gate_hw, &clk_gate_ops, flags);
|
||||
if (IS_ERR(hw))
|
||||
goto fail;
|
||||
|
@ -41,21 +41,26 @@ static int clk_gate2_enable(struct clk_hw *hw)
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (gate->share_count && (*gate->share_count)++ > 0)
|
||||
goto out;
|
||||
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
reg |= gate->cgr_val << gate->bit_idx;
|
||||
writel(reg, gate->reg);
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
|
||||
ret = clk_gate_ops.enable(hw);
|
||||
} else {
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
reg |= gate->cgr_val << gate->bit_idx;
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_gate2_disable(struct clk_hw *hw)
|
||||
@ -73,9 +78,13 @@ static void clk_gate2_disable(struct clk_hw *hw)
|
||||
goto out;
|
||||
}
|
||||
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
writel(reg, gate->reg);
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
|
||||
clk_gate_ops.disable(hw);
|
||||
} else {
|
||||
reg = readl(gate->reg);
|
||||
reg &= ~(3 << gate->bit_idx);
|
||||
writel(reg, gate->reg);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
@ -95,6 +104,9 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_gate2 *gate = to_clk_gate2(hw);
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
|
||||
return clk_gate_ops.is_enabled(hw);
|
||||
|
||||
return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
|
||||
}
|
||||
|
||||
@ -104,6 +116,9 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (!gate->share_count || *gate->share_count == 0) {
|
||||
|
@ -503,7 +503,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
||||
clk_prepare_enable(hws[IMX6UL_CLK_USBPHY2_GATE]->clk);
|
||||
}
|
||||
|
||||
clk_set_parent(hws[IMX6UL_CLK_CAN_SEL]->clk, hws[IMX6UL_CLK_PLL3_60M]->clk);
|
||||
clk_set_parent(hws[IMX6UL_CLK_CAN_SEL]->clk, hws[IMX6UL_CLK_PLL3_80M]->clk);
|
||||
if (clk_on_imx6ul())
|
||||
clk_set_parent(hws[IMX6UL_CLK_SIM_PRE_SEL]->clk, hws[IMX6UL_CLK_PLL3_USB_OTG]->clk);
|
||||
else if (clk_on_imx6ull())
|
||||
|
@ -29,7 +29,7 @@ static const char * const ddr_sels[] = { "apll_pfd_sel", "dummy", "dummy", "dum
|
||||
static const char * const nic_sels[] = { "firc", "ddr_clk", };
|
||||
static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
|
||||
static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk", "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
|
||||
static const char * const arm_sels[] = { "divcore", "dummy", "dummy", "hsrun_divcore", };
|
||||
static const char * const arm_sels[] = { "core", "dummy", "dummy", "hsrun_core", };
|
||||
|
||||
/* used by sosc/sirc/firc/ddr/spll/apll dividers */
|
||||
static const struct clk_div_table ulp_div_table[] = {
|
||||
@ -121,7 +121,9 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
|
||||
hws[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
|
||||
|
||||
hws[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore", "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
|
||||
hws[IMX7ULP_CLK_CORE] = imx_clk_hw_cpu("core", "divcore", hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
|
||||
hws[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
|
||||
hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core", "hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk, hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
|
||||
|
||||
hws[IMX7ULP_CLK_DDR_DIV] = imx_clk_hw_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
|
||||
0, ulp_div_table, &imx_ccm_lock);
|
||||
@ -270,7 +272,7 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
|
||||
base = of_iomap(np, 0);
|
||||
WARN_ON(!base);
|
||||
|
||||
hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
|
||||
hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);
|
||||
|
||||
imx_check_clk_hws(hws, clk_data->num);
|
||||
|
||||
|
@ -416,9 +416,9 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(base);
|
||||
|
||||
/* Core Slice */
|
||||
hws[IMX8MM_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels));
|
||||
hws[IMX8MM_CLK_A53_CG] = imx_clk_hw_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28);
|
||||
hws[IMX8MM_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
|
||||
hws[IMX8MM_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mm_a53_sels, base + 0x8000);
|
||||
hws[IMX8MM_CLK_A53_CG] = hws[IMX8MM_CLK_A53_DIV];
|
||||
hws[IMX8MM_CLK_A53_SRC] = hws[IMX8MM_CLK_A53_DIV];
|
||||
|
||||
hws[IMX8MM_CLK_M4_CORE] = imx8m_clk_hw_composite_core("arm_m4_core", imx8mm_m4_sels, base + 0x8080);
|
||||
hws[IMX8MM_CLK_VPU_CORE] = imx8m_clk_hw_composite_core("vpu_core", imx8mm_vpu_sels, base + 0x8100);
|
||||
@ -444,21 +444,21 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
|
||||
|
||||
/* BUS */
|
||||
hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800);
|
||||
hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
|
||||
hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
|
||||
hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MM_CLK_DISP_RTRM] = imx8m_clk_hw_composite("disp_rtrm", imx8mm_disp_rtrm_sels, base + 0x8b00);
|
||||
hws[IMX8MM_CLK_USB_BUS] = imx8m_clk_hw_composite("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MM_CLK_GPU_AXI] = imx8m_clk_hw_composite("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MM_CLK_GPU_AHB] = imx8m_clk_hw_composite("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
|
||||
hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MM_CLK_DISP_RTRM] = imx8m_clk_hw_composite_bus("disp_rtrm", imx8mm_disp_rtrm_sels, base + 0x8b00);
|
||||
hws[IMX8MM_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MM_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MM_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MM_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00);
|
||||
hws[IMX8MM_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
|
||||
|
||||
/* AHB */
|
||||
hws[IMX8MM_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
|
||||
hws[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_hw_composite("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
|
||||
hws[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
|
||||
|
||||
/* IPG */
|
||||
hws[IMX8MM_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
|
||||
@ -614,9 +614,6 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MM_ARM_PLL_OUT]->clk,
|
||||
hws[IMX8MM_CLK_A53_DIV]->clk);
|
||||
|
||||
clk_hw_set_parent(hws[IMX8MM_CLK_A53_SRC], hws[IMX8MM_SYS_PLL1_800M]);
|
||||
clk_hw_set_parent(hws[IMX8MM_CLK_A53_CORE], hws[IMX8MM_ARM_PLL_OUT]);
|
||||
|
||||
imx_check_clk_hws(hws, IMX8MM_CLK_END);
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
|
||||
|
@ -413,9 +413,9 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* CORE */
|
||||
hws[IMX8MN_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mn_a53_sels, ARRAY_SIZE(imx8mn_a53_sels));
|
||||
hws[IMX8MN_CLK_A53_CG] = imx_clk_hw_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28);
|
||||
hws[IMX8MN_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
|
||||
hws[IMX8MN_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mn_a53_sels, base + 0x8000);
|
||||
hws[IMX8MN_CLK_A53_SRC] = hws[IMX8MN_CLK_A53_DIV];
|
||||
hws[IMX8MN_CLK_A53_CG] = hws[IMX8MN_CLK_A53_DIV];
|
||||
|
||||
hws[IMX8MN_CLK_GPU_CORE] = imx8m_clk_hw_composite_core("gpu_core", imx8mn_gpu_core_sels, base + 0x8180);
|
||||
hws[IMX8MN_CLK_GPU_SHADER] = imx8m_clk_hw_composite_core("gpu_shader", imx8mn_gpu_shader_sels, base + 0x8200);
|
||||
@ -432,17 +432,17 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
|
||||
|
||||
/* BUS */
|
||||
hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
|
||||
hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
|
||||
hws[IMX8MN_CLK_DISP_AXI] = imx8m_clk_hw_composite("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MN_CLK_DISP_APB] = imx8m_clk_hw_composite("disp_apb", imx8mn_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MN_CLK_USB_BUS] = imx8m_clk_hw_composite("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MN_CLK_GPU_AXI] = imx8m_clk_hw_composite("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MN_CLK_GPU_AHB] = imx8m_clk_hw_composite("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
|
||||
hws[IMX8MN_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MN_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mn_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MN_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MN_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MN_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MN_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00);
|
||||
|
||||
hws[IMX8MN_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
|
||||
hws[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_hw_composite("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
|
||||
hws[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
|
||||
hws[IMX8MN_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
|
||||
hws[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
|
||||
hws[IMX8MN_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mn_dram_core_sels, ARRAY_SIZE(imx8mn_dram_core_sels), CLK_IS_CRITICAL);
|
||||
@ -565,9 +565,6 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MN_ARM_PLL_OUT]->clk,
|
||||
hws[IMX8MN_CLK_A53_DIV]->clk);
|
||||
|
||||
clk_hw_set_parent(hws[IMX8MN_CLK_A53_SRC], hws[IMX8MN_SYS_PLL1_800M]);
|
||||
clk_hw_set_parent(hws[IMX8MN_CLK_A53_CORE], hws[IMX8MN_ARM_PLL_OUT]);
|
||||
|
||||
imx_check_clk_hws(hws, IMX8MN_CLK_END);
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
|
||||
|
@ -486,16 +486,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_SYS_PLL2] = imx_clk_hw_pll14xx("sys_pll2", "sys_pll2_ref_sel", anatop_base + 0x104, &imx_1416x_pll);
|
||||
hws[IMX8MP_SYS_PLL3] = imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", anatop_base + 0x114, &imx_1416x_pll);
|
||||
|
||||
hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", anatop_base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", anatop_base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", anatop_base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", anatop_base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", anatop_base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", anatop_base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", anatop_base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL1_BYPASS] = imx_clk_hw_mux_flags("sys_pll1_bypass", anatop_base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL2_BYPASS] = imx_clk_hw_mux_flags("sys_pll2_bypass", anatop_base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", anatop_base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", anatop_base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", anatop_base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", anatop_base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", anatop_base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", anatop_base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", anatop_base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", anatop_base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL1_BYPASS] = imx_clk_hw_mux_flags("sys_pll1_bypass", anatop_base + 0x94, 28, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL2_BYPASS] = imx_clk_hw_mux_flags("sys_pll2_bypass", anatop_base + 0x104, 28, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
hws[IMX8MP_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", anatop_base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
|
||||
|
||||
hws[IMX8MP_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", anatop_base, 13);
|
||||
hws[IMX8MP_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", anatop_base + 0x14, 13);
|
||||
@ -504,79 +504,82 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", anatop_base + 0x64, 11);
|
||||
hws[IMX8MP_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", anatop_base + 0x74, 11);
|
||||
hws[IMX8MP_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", anatop_base + 0x84, 11);
|
||||
hws[IMX8MP_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass", anatop_base + 0x94, 11);
|
||||
hws[IMX8MP_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass", anatop_base + 0x104, 11);
|
||||
hws[IMX8MP_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", anatop_base + 0x114, 11);
|
||||
|
||||
hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
|
||||
hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
|
||||
hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
|
||||
hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
|
||||
hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
|
||||
hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
|
||||
hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
|
||||
hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
|
||||
hws[IMX8MP_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1_bypass", anatop_base + 0x94, 27);
|
||||
hws[IMX8MP_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1_bypass", anatop_base + 0x94, 25);
|
||||
hws[IMX8MP_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1_bypass", anatop_base + 0x94, 23);
|
||||
hws[IMX8MP_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1_bypass", anatop_base + 0x94, 21);
|
||||
hws[IMX8MP_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1_bypass", anatop_base + 0x94, 19);
|
||||
hws[IMX8MP_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1_bypass", anatop_base + 0x94, 17);
|
||||
hws[IMX8MP_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1_bypass", anatop_base + 0x94, 15);
|
||||
hws[IMX8MP_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1_bypass", anatop_base + 0x94, 13);
|
||||
hws[IMX8MP_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass", anatop_base + 0x94, 11);
|
||||
|
||||
hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20);
|
||||
hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10);
|
||||
hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8);
|
||||
hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6);
|
||||
hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5);
|
||||
hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4);
|
||||
hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3);
|
||||
hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2);
|
||||
hws[IMX8MP_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
|
||||
|
||||
hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
|
||||
hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
|
||||
hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
|
||||
hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
|
||||
hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
|
||||
hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
|
||||
hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
|
||||
hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
|
||||
hws[IMX8MP_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2_bypass", anatop_base + 0x104, 27);
|
||||
hws[IMX8MP_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2_bypass", anatop_base + 0x104, 25);
|
||||
hws[IMX8MP_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2_bypass", anatop_base + 0x104, 23);
|
||||
hws[IMX8MP_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2_bypass", anatop_base + 0x104, 21);
|
||||
hws[IMX8MP_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2_bypass", anatop_base + 0x104, 19);
|
||||
hws[IMX8MP_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2_bypass", anatop_base + 0x104, 17);
|
||||
hws[IMX8MP_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2_bypass", anatop_base + 0x104, 15);
|
||||
hws[IMX8MP_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2_bypass", anatop_base + 0x104, 13);
|
||||
hws[IMX8MP_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass", anatop_base + 0x104, 11);
|
||||
|
||||
hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20);
|
||||
hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10);
|
||||
hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8);
|
||||
hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6);
|
||||
hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5);
|
||||
hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4);
|
||||
hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3);
|
||||
hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
|
||||
hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
|
||||
|
||||
hws[IMX8MP_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", ccm_base + 0x8000, 24, 3, imx8mp_a53_sels, ARRAY_SIZE(imx8mp_a53_sels));
|
||||
hws[IMX8MP_CLK_M7_SRC] = imx_clk_hw_mux2("arm_m7_src", ccm_base + 0x8080, 24, 3, imx8mp_m7_sels, ARRAY_SIZE(imx8mp_m7_sels));
|
||||
hws[IMX8MP_CLK_ML_SRC] = imx_clk_hw_mux2("ml_src", ccm_base + 0x8100, 24, 3, imx8mp_ml_sels, ARRAY_SIZE(imx8mp_ml_sels));
|
||||
hws[IMX8MP_CLK_GPU3D_CORE_SRC] = imx_clk_hw_mux2("gpu3d_core_src", ccm_base + 0x8180, 24, 3, imx8mp_gpu3d_core_sels, ARRAY_SIZE(imx8mp_gpu3d_core_sels));
|
||||
hws[IMX8MP_CLK_GPU3D_SHADER_SRC] = imx_clk_hw_mux2("gpu3d_shader_src", ccm_base + 0x8200, 24, 3, imx8mp_gpu3d_shader_sels, ARRAY_SIZE(imx8mp_gpu3d_shader_sels));
|
||||
hws[IMX8MP_CLK_GPU2D_SRC] = imx_clk_hw_mux2("gpu2d_src", ccm_base + 0x8280, 24, 3, imx8mp_gpu2d_sels, ARRAY_SIZE(imx8mp_gpu2d_sels));
|
||||
hws[IMX8MP_CLK_AUDIO_AXI_SRC] = imx_clk_hw_mux2("audio_axi_src", ccm_base + 0x8300, 24, 3, imx8mp_audio_axi_sels, ARRAY_SIZE(imx8mp_audio_axi_sels));
|
||||
hws[IMX8MP_CLK_HSIO_AXI_SRC] = imx_clk_hw_mux2("hsio_axi_src", ccm_base + 0x8380, 24, 3, imx8mp_hsio_axi_sels, ARRAY_SIZE(imx8mp_hsio_axi_sels));
|
||||
hws[IMX8MP_CLK_MEDIA_ISP_SRC] = imx_clk_hw_mux2("media_isp_src", ccm_base + 0x8400, 24, 3, imx8mp_media_isp_sels, ARRAY_SIZE(imx8mp_media_isp_sels));
|
||||
hws[IMX8MP_CLK_A53_CG] = imx_clk_hw_gate3("arm_a53_cg", "arm_a53_src", ccm_base + 0x8000, 28);
|
||||
hws[IMX8MP_CLK_M4_CG] = imx_clk_hw_gate3("arm_m7_cg", "arm_m7_src", ccm_base + 0x8080, 28);
|
||||
hws[IMX8MP_CLK_ML_CG] = imx_clk_hw_gate3("ml_cg", "ml_src", ccm_base + 0x8100, 28);
|
||||
hws[IMX8MP_CLK_GPU3D_CORE_CG] = imx_clk_hw_gate3("gpu3d_core_cg", "gpu3d_core_src", ccm_base + 0x8180, 28);
|
||||
hws[IMX8MP_CLK_GPU3D_SHADER_CG] = imx_clk_hw_gate3("gpu3d_shader_cg", "gpu3d_shader_src", ccm_base + 0x8200, 28);
|
||||
hws[IMX8MP_CLK_GPU2D_CG] = imx_clk_hw_gate3("gpu2d_cg", "gpu2d_src", ccm_base + 0x8280, 28);
|
||||
hws[IMX8MP_CLK_AUDIO_AXI_CG] = imx_clk_hw_gate3("audio_axi_cg", "audio_axi_src", ccm_base + 0x8300, 28);
|
||||
hws[IMX8MP_CLK_HSIO_AXI_CG] = imx_clk_hw_gate3("hsio_axi_cg", "hsio_axi_src", ccm_base + 0x8380, 28);
|
||||
hws[IMX8MP_CLK_MEDIA_ISP_CG] = imx_clk_hw_gate3("media_isp_cg", "media_isp_src", ccm_base + 0x8400, 28);
|
||||
hws[IMX8MP_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", ccm_base + 0x8000, 0, 3);
|
||||
hws[IMX8MP_CLK_M7_DIV] = imx_clk_hw_divider2("arm_m7_div", "arm_m7_cg", ccm_base + 0x8080, 0, 3);
|
||||
hws[IMX8MP_CLK_ML_DIV] = imx_clk_hw_divider2("ml_div", "ml_cg", ccm_base + 0x8100, 0, 3);
|
||||
hws[IMX8MP_CLK_GPU3D_CORE_DIV] = imx_clk_hw_divider2("gpu3d_core_div", "gpu3d_core_cg", ccm_base + 0x8180, 0, 3);
|
||||
hws[IMX8MP_CLK_GPU3D_SHADER_DIV] = imx_clk_hw_divider2("gpu3d_shader_div", "gpu3d_shader_cg", ccm_base + 0x8200, 0, 3);
|
||||
hws[IMX8MP_CLK_GPU2D_DIV] = imx_clk_hw_divider2("gpu2d_div", "gpu2d_cg", ccm_base + 0x8280, 0, 3);
|
||||
hws[IMX8MP_CLK_AUDIO_AXI_DIV] = imx_clk_hw_divider2("audio_axi_div", "audio_axi_cg", ccm_base + 0x8300, 0, 3);
|
||||
hws[IMX8MP_CLK_HSIO_AXI_DIV] = imx_clk_hw_divider2("hsio_axi_div", "hsio_axi_cg", ccm_base + 0x8380, 0, 3);
|
||||
hws[IMX8MP_CLK_MEDIA_ISP_DIV] = imx_clk_hw_divider2("media_isp_div", "media_isp_cg", ccm_base + 0x8400, 0, 3);
|
||||
hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000);
|
||||
hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV];
|
||||
hws[IMX8MP_CLK_A53_CG] = hws[IMX8MP_CLK_A53_DIV];
|
||||
hws[IMX8MP_CLK_M7_CORE] = imx8m_clk_hw_composite_core("m7_core", imx8mp_m7_sels, ccm_base + 0x8080);
|
||||
hws[IMX8MP_CLK_ML_CORE] = imx8m_clk_hw_composite_core("ml_core", imx8mp_ml_sels, ccm_base + 0x8100);
|
||||
hws[IMX8MP_CLK_GPU3D_CORE] = imx8m_clk_hw_composite_core("gpu3d_core", imx8mp_gpu3d_core_sels, ccm_base + 0x8180);
|
||||
hws[IMX8MP_CLK_GPU3D_SHADER_CORE] = imx8m_clk_hw_composite("gpu3d_shader_core", imx8mp_gpu3d_shader_sels, ccm_base + 0x8200);
|
||||
hws[IMX8MP_CLK_GPU2D_CORE] = imx8m_clk_hw_composite("gpu2d_core", imx8mp_gpu2d_sels, ccm_base + 0x8280);
|
||||
hws[IMX8MP_CLK_AUDIO_AXI] = imx8m_clk_hw_composite("audio_axi", imx8mp_audio_axi_sels, ccm_base + 0x8300);
|
||||
hws[IMX8MP_CLK_AUDIO_AXI_SRC] = hws[IMX8MP_CLK_AUDIO_AXI];
|
||||
hws[IMX8MP_CLK_HSIO_AXI] = imx8m_clk_hw_composite("hsio_axi", imx8mp_hsio_axi_sels, ccm_base + 0x8380);
|
||||
hws[IMX8MP_CLK_MEDIA_ISP] = imx8m_clk_hw_composite("media_isp", imx8mp_media_isp_sels, ccm_base + 0x8400);
|
||||
|
||||
/* CORE SEL */
|
||||
hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
|
||||
|
||||
hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
|
||||
hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
|
||||
hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
|
||||
hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
|
||||
hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
|
||||
hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
|
||||
hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
|
||||
hws[IMX8MP_CLK_HDMI_APB] = imx8m_clk_hw_composite("hdmi_apb", imx8mp_media_apb_sels, ccm_base + 0x8b00);
|
||||
hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
|
||||
hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
|
||||
hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
|
||||
hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
|
||||
hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
|
||||
hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
|
||||
hws[IMX8MP_CLK_HDMI_APB] = imx8m_clk_hw_composite_bus("hdmi_apb", imx8mp_media_apb_sels, ccm_base + 0x8b00);
|
||||
hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
|
||||
hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
|
||||
hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
|
||||
hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
|
||||
hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
|
||||
hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
|
||||
hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
|
||||
hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
|
||||
hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
|
||||
|
||||
hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
|
||||
hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
|
||||
hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
|
||||
hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
|
||||
hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
|
||||
|
||||
hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1);
|
||||
hws[IMX8MP_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", ccm_base + 0x9180, 0, 1);
|
||||
@ -695,8 +698,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_CLK_SDMA1_ROOT] = imx_clk_hw_gate4("sdma1_root_clk", "ipg_root", ccm_base + 0x43a0, 0);
|
||||
hws[IMX8MP_CLK_ENET_QOS_ROOT] = imx_clk_hw_gate4("enet_qos_root_clk", "sim_enet_root_clk", ccm_base + 0x43b0, 0);
|
||||
hws[IMX8MP_CLK_SIM_ENET_ROOT] = imx_clk_hw_gate4("sim_enet_root_clk", "enet_axi", ccm_base + 0x4400, 0);
|
||||
hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_div", ccm_base + 0x4450, 0);
|
||||
hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core_div", ccm_base + 0x4460, 0);
|
||||
hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", ccm_base + 0x4450, 0);
|
||||
hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", ccm_base + 0x4460, 0);
|
||||
hws[IMX8MP_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", ccm_base + 0x4470, 0);
|
||||
hws[IMX8MP_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", ccm_base + 0x4490, 0);
|
||||
hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
|
||||
@ -713,7 +716,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_axi", ccm_base + 0x4570, 0);
|
||||
hws[IMX8MP_CLK_VPU_VC8KE_ROOT] = imx_clk_hw_gate4("vpu_vc8ke_root_clk", "vpu_vc8000e", ccm_base + 0x4590, 0);
|
||||
hws[IMX8MP_CLK_VPU_G2_ROOT] = imx_clk_hw_gate4("vpu_g2_root_clk", "vpu_g2", ccm_base + 0x45a0, 0);
|
||||
hws[IMX8MP_CLK_NPU_ROOT] = imx_clk_hw_gate4("npu_root_clk", "ml_div", ccm_base + 0x45b0, 0);
|
||||
hws[IMX8MP_CLK_NPU_ROOT] = imx_clk_hw_gate4("npu_root_clk", "ml_core", ccm_base + 0x45b0, 0);
|
||||
hws[IMX8MP_CLK_HSIO_ROOT] = imx_clk_hw_gate4("hsio_root_clk", "ipg_root", ccm_base + 0x45c0, 0);
|
||||
hws[IMX8MP_CLK_MEDIA_APB_ROOT] = imx_clk_hw_gate2_shared2("media_apb_root_clk", "media_apb", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
hws[IMX8MP_CLK_MEDIA_AXI_ROOT] = imx_clk_hw_gate2_shared2("media_axi_root_clk", "media_axi", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
@ -721,7 +724,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam2_pix_root_clk", "media_cam2_pix", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp_div", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", ccm_base + 0x45d0, 0, &share_count_media);
|
||||
|
||||
hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", ccm_base + 0x45e0, 0);
|
||||
hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
|
||||
@ -735,9 +738,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MP_ARM_PLL_OUT]->clk,
|
||||
hws[IMX8MP_CLK_A53_DIV]->clk);
|
||||
|
||||
clk_hw_set_parent(hws[IMX8MP_CLK_A53_SRC], hws[IMX8MP_SYS_PLL1_800M]);
|
||||
clk_hw_set_parent(hws[IMX8MP_CLK_A53_CORE], hws[IMX8MP_ARM_PLL_OUT]);
|
||||
|
||||
imx_check_clk_hws(hws, IMX8MP_CLK_END);
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
|
||||
|
@ -405,9 +405,9 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(base);
|
||||
|
||||
/* CORE */
|
||||
hws[IMX8MQ_CLK_A53_SRC] = imx_clk_hw_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels));
|
||||
hws[IMX8MQ_CLK_A53_CG] = imx_clk_hw_gate3_flags("arm_a53_cg", "arm_a53_src", base + 0x8000, 28, CLK_IS_CRITICAL);
|
||||
hws[IMX8MQ_CLK_A53_DIV] = imx_clk_hw_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
|
||||
hws[IMX8MQ_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mq_a53_sels, base + 0x8000);
|
||||
hws[IMX8MQ_CLK_A53_CG] = hws[IMX8MQ_CLK_A53_DIV];
|
||||
hws[IMX8MQ_CLK_A53_SRC] = hws[IMX8MQ_CLK_A53_DIV];
|
||||
|
||||
hws[IMX8MQ_CLK_M4_CORE] = imx8m_clk_hw_composite_core("arm_m4_core", imx8mq_arm_m4_sels, base + 0x8080);
|
||||
hws[IMX8MQ_CLK_VPU_CORE] = imx8m_clk_hw_composite_core("vpu_core", imx8mq_vpu_sels, base + 0x8100);
|
||||
@ -432,22 +432,22 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
||||
|
||||
/* BUS */
|
||||
hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800);
|
||||
hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite("enet_axi", imx8mq_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900);
|
||||
hws[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_hw_composite("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980);
|
||||
hws[IMX8MQ_CLK_DISP_AXI] = imx8m_clk_hw_composite("disp_axi", imx8mq_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MQ_CLK_DISP_APB] = imx8m_clk_hw_composite("disp_apb", imx8mq_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MQ_CLK_DISP_RTRM] = imx8m_clk_hw_composite("disp_rtrm", imx8mq_disp_rtrm_sels, base + 0x8b00);
|
||||
hws[IMX8MQ_CLK_USB_BUS] = imx8m_clk_hw_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_hw_composite("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_hw_composite("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mq_enet_axi_sels, base + 0x8880);
|
||||
hws[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900);
|
||||
hws[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980);
|
||||
hws[IMX8MQ_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mq_disp_axi_sels, base + 0x8a00);
|
||||
hws[IMX8MQ_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mq_disp_apb_sels, base + 0x8a80);
|
||||
hws[IMX8MQ_CLK_DISP_RTRM] = imx8m_clk_hw_composite_bus("disp_rtrm", imx8mq_disp_rtrm_sels, base + 0x8b00);
|
||||
hws[IMX8MQ_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80);
|
||||
hws[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00);
|
||||
hws[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80);
|
||||
hws[IMX8MQ_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mq_noc_sels, base + 0x8d00);
|
||||
hws[IMX8MQ_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
|
||||
|
||||
/* AHB */
|
||||
/* AHB clock is used by the AHB bus therefore marked as critical */
|
||||
hws[IMX8MQ_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
|
||||
hws[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_hw_composite("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
|
||||
hws[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
|
||||
|
||||
/* IPG */
|
||||
hws[IMX8MQ_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
|
||||
@ -599,9 +599,6 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
||||
hws[IMX8MQ_ARM_PLL_OUT]->clk,
|
||||
hws[IMX8MQ_CLK_A53_DIV]->clk);
|
||||
|
||||
clk_hw_set_parent(hws[IMX8MQ_CLK_A53_SRC], hws[IMX8MQ_SYS1_PLL_800M]);
|
||||
clk_hw_set_parent(hws[IMX8MQ_CLK_A53_CORE], hws[IMX8MQ_ARM_PLL_OUT]);
|
||||
|
||||
imx_check_clk_hws(hws, IMX8MQ_CLK_END);
|
||||
|
||||
err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
|
||||
|
@ -378,9 +378,9 @@ static const struct clk_ops clk_pll1443x_ops = {
|
||||
.set_rate = clk_pll1443x_set_rate,
|
||||
};
|
||||
|
||||
struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name,
|
||||
void __iomem *base,
|
||||
const struct imx_pll14xx_clk *pll_clk)
|
||||
struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
|
||||
const char *parent_name, void __iomem *base,
|
||||
const struct imx_pll14xx_clk *pll_clk)
|
||||
{
|
||||
struct clk_pll14xx *pll;
|
||||
struct clk_hw *hw;
|
||||
@ -426,7 +426,7 @@ struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name,
|
||||
|
||||
hw = &pll->hw;
|
||||
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register pll %s %d\n",
|
||||
__func__, name, ret);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/err.h>
|
||||
@ -25,6 +26,8 @@
|
||||
#define IMX7_ENET_PLL_POWER (0x1 << 5)
|
||||
#define IMX7_DDR_PLL_POWER (0x1 << 20)
|
||||
|
||||
#define PLL_LOCK_TIMEOUT 10000
|
||||
|
||||
/**
|
||||
* struct clk_pllv3 - IMX PLL clock version 3
|
||||
* @clk_hw: clock source
|
||||
@ -53,23 +56,14 @@ struct clk_pllv3 {
|
||||
|
||||
static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(10);
|
||||
u32 val = readl_relaxed(pll->base) & pll->power_bit;
|
||||
|
||||
/* No need to wait for lock when pll is not powered up */
|
||||
if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
|
||||
return 0;
|
||||
|
||||
/* Wait for PLL to lock */
|
||||
do {
|
||||
if (readl_relaxed(pll->base) & BM_PLL_LOCK)
|
||||
break;
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
usleep_range(50, 500);
|
||||
} while (1);
|
||||
|
||||
return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT;
|
||||
return readl_relaxed_poll_timeout(pll->base, val, val & BM_PLL_LOCK,
|
||||
500, PLL_LOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
static int clk_pllv3_prepare(struct clk_hw *hw)
|
||||
|
@ -72,7 +72,6 @@ struct clk_sscg_pll_setup {
|
||||
int divr2, divf2;
|
||||
int divq;
|
||||
int bypass;
|
||||
|
||||
uint64_t vco1;
|
||||
uint64_t vco2;
|
||||
uint64_t fout;
|
||||
@ -86,11 +85,8 @@ struct clk_sscg_pll_setup {
|
||||
struct clk_sscg_pll {
|
||||
struct clk_hw hw;
|
||||
const struct clk_ops ops;
|
||||
|
||||
void __iomem *base;
|
||||
|
||||
struct clk_sscg_pll_setup setup;
|
||||
|
||||
u8 parent;
|
||||
u8 bypass1;
|
||||
u8 bypass2;
|
||||
@ -194,7 +190,6 @@ static int clk_sscg_pll2_find_setup(struct clk_sscg_pll_setup *setup,
|
||||
struct clk_sscg_pll_setup *temp_setup,
|
||||
uint64_t ref)
|
||||
{
|
||||
|
||||
int ret;
|
||||
|
||||
if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ)
|
||||
@ -253,7 +248,6 @@ static int clk_sscg_pll1_find_setup(struct clk_sscg_pll_setup *setup,
|
||||
struct clk_sscg_pll_setup *temp_setup,
|
||||
uint64_t ref)
|
||||
{
|
||||
|
||||
int ret;
|
||||
|
||||
if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ)
|
||||
@ -280,7 +274,6 @@ static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup,
|
||||
temp_setup.fout_request = rate;
|
||||
|
||||
switch (try_bypass) {
|
||||
|
||||
case PLL_BYPASS2:
|
||||
if (prate == rate) {
|
||||
setup->bypass = PLL_BYPASS2;
|
||||
@ -288,11 +281,9 @@ static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup,
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case PLL_BYPASS1:
|
||||
ret = clk_sscg_pll2_find_setup(setup, &temp_setup, prate);
|
||||
break;
|
||||
|
||||
case PLL_BYPASS_NONE:
|
||||
ret = clk_sscg_pll1_find_setup(setup, &temp_setup, prate);
|
||||
break;
|
||||
@ -301,7 +292,6 @@ static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int clk_sscg_pll_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#define IMX_CLK_GATE2_SINGLE_BIT 1
|
||||
|
||||
extern spinlock_t imx_ccm_lock;
|
||||
|
||||
void imx_check_clocks(struct clk *clks[], unsigned int count);
|
||||
@ -131,9 +133,9 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
|
||||
#define imx_clk_pll14xx(name, parent_name, base, pll_clk) \
|
||||
to_clk(imx_clk_hw_pll14xx(name, parent_name, base, pll_clk))
|
||||
|
||||
struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name,
|
||||
void __iomem *base,
|
||||
const struct imx_pll14xx_clk *pll_clk);
|
||||
struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
|
||||
const char *parent_name, void __iomem *base,
|
||||
const struct imx_pll14xx_clk *pll_clk);
|
||||
|
||||
struct clk_hw *imx_clk_hw_pllv1(enum imx_pllv1_type type, const char *name,
|
||||
const char *parent, void __iomem *base);
|
||||
@ -240,6 +242,13 @@ static inline struct clk *to_clk(struct clk_hw *hw)
|
||||
return hw->clk;
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_pll14xx(const char *name, const char *parent_name,
|
||||
void __iomem *base,
|
||||
const struct imx_pll14xx_clk *pll_clk)
|
||||
{
|
||||
return imx_dev_clk_hw_pll14xx(NULL, name, parent_name, base, pll_clk);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_fixed(const char *name, int rate)
|
||||
{
|
||||
return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
|
||||
@ -310,6 +319,13 @@ static inline struct clk_hw *imx_clk_hw_gate(const char *name, const char *paren
|
||||
shift, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_dev_clk_hw_gate(struct device *dev, const char *name,
|
||||
const char *parent, void __iomem *reg, u8 shift)
|
||||
{
|
||||
return clk_hw_register_gate(dev, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_clk_hw_gate_dis(const char *name, const char *parent,
|
||||
void __iomem *reg, u8 shift)
|
||||
{
|
||||
@ -355,6 +371,17 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
|
||||
&imx_ccm_lock, share_count);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev,
|
||||
const char *name, const char *parent,
|
||||
void __iomem *reg, u8 shift,
|
||||
unsigned int *share_count)
|
||||
{
|
||||
return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
|
||||
CLK_OPS_PARENT_ENABLE, reg, shift, 0x3,
|
||||
IMX_CLK_GATE2_SINGLE_BIT,
|
||||
&imx_ccm_lock, share_count);
|
||||
}
|
||||
|
||||
static inline struct clk *imx_clk_gate2_cgr(const char *name,
|
||||
const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
|
||||
{
|
||||
@ -411,6 +438,15 @@ static inline struct clk_hw *imx_clk_hw_mux(const char *name, void __iomem *reg,
|
||||
width, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_dev_clk_hw_mux(struct device *dev,
|
||||
const char *name, void __iomem *reg, u8 shift,
|
||||
u8 width, const char * const *parents, int num_parents)
|
||||
{
|
||||
return clk_hw_register_mux(dev, name, parents, num_parents,
|
||||
CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE,
|
||||
reg, shift, width, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
|
||||
u8 shift, u8 width, const char * const *parents,
|
||||
int num_parents)
|
||||
@ -473,11 +509,25 @@ static inline struct clk_hw *imx_clk_hw_mux_flags(const char *name,
|
||||
reg, shift, width, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk_hw *imx_dev_clk_hw_mux_flags(struct device *dev,
|
||||
const char *name,
|
||||
void __iomem *reg, u8 shift,
|
||||
u8 width,
|
||||
const char * const *parents,
|
||||
int num_parents,
|
||||
unsigned long flags)
|
||||
{
|
||||
return clk_hw_register_mux(dev, name, parents, num_parents,
|
||||
flags | CLK_SET_RATE_NO_REPARENT,
|
||||
reg, shift, width, 0, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
|
||||
struct clk *div, struct clk *mux, struct clk *pll,
|
||||
struct clk *step);
|
||||
|
||||
#define IMX_COMPOSITE_CORE BIT(0)
|
||||
#define IMX_COMPOSITE_BUS BIT(1)
|
||||
|
||||
struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
const char * const *parent_names,
|
||||
@ -486,6 +536,12 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
||||
u32 composite_flags,
|
||||
unsigned long flags);
|
||||
|
||||
#define imx8m_clk_hw_composite_bus(name, parent_names, reg) \
|
||||
imx8m_clk_hw_composite_flags(name, parent_names, \
|
||||
ARRAY_SIZE(parent_names), reg, \
|
||||
IMX_COMPOSITE_BUS, \
|
||||
CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
|
||||
|
||||
#define imx8m_clk_hw_composite_core(name, parent_names, reg) \
|
||||
imx8m_clk_hw_composite_flags(name, parent_names, \
|
||||
ARRAY_SIZE(parent_names), reg, \
|
||||
|
@ -3,3 +3,5 @@ obj-$(CONFIG_ARCH_SOCFPGA) += clk.o clk-gate.o clk-pll.o clk-periph.o
|
||||
obj-$(CONFIG_ARCH_SOCFPGA) += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
|
||||
obj-$(CONFIG_ARCH_STRATIX10) += clk-s10.o
|
||||
obj-$(CONFIG_ARCH_STRATIX10) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
|
||||
obj-$(CONFIG_ARCH_AGILEX) += clk-agilex.o
|
||||
obj-$(CONFIG_ARCH_AGILEX) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
|
||||
|
454
drivers/clk/socfpga/clk-agilex.c
Normal file
454
drivers/clk/socfpga/clk-agilex.c
Normal file
@ -0,0 +1,454 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2019, Intel Corporation
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <dt-bindings/clock/agilex-clock.h>
|
||||
|
||||
#include "stratix10-clk.h"
|
||||
|
||||
static const struct clk_parent_data pll_mux[] = {
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data cntr_mux[] = {
|
||||
{ .fw_name = "main_pll",
|
||||
.name = "main_pll", },
|
||||
{ .fw_name = "periph_pll",
|
||||
.name = "periph_pll", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data boot_mux[] = {
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mpu_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c0",
|
||||
.name = "main_pll_c0", },
|
||||
{ .fw_name = "peri_pll_c0",
|
||||
.name = "peri_pll_c0", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data noc_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c1",
|
||||
.name = "main_pll_c1", },
|
||||
{ .fw_name = "peri_pll_c1",
|
||||
.name = "peri_pll_c1", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emaca_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c2",
|
||||
.name = "main_pll_c2", },
|
||||
{ .fw_name = "peri_pll_c2",
|
||||
.name = "peri_pll_c2", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emacb_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c3",
|
||||
.name = "main_pll_c3", },
|
||||
{ .fw_name = "peri_pll_c3",
|
||||
.name = "peri_pll_c3", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emac_ptp_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c3",
|
||||
.name = "main_pll_c3", },
|
||||
{ .fw_name = "peri_pll_c3",
|
||||
.name = "peri_pll_c3", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data gpio_db_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c3",
|
||||
.name = "main_pll_c3", },
|
||||
{ .fw_name = "peri_pll_c3",
|
||||
.name = "peri_pll_c3", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data psi_ref_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c3",
|
||||
.name = "main_pll_c3", },
|
||||
{ .fw_name = "peri_pll_c3",
|
||||
.name = "peri_pll_c3", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data sdmmc_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c3",
|
||||
.name = "main_pll_c3", },
|
||||
{ .fw_name = "peri_pll_c3",
|
||||
.name = "peri_pll_c3", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data s2f_usr0_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c2",
|
||||
.name = "main_pll_c2", },
|
||||
{ .fw_name = "peri_pll_c2",
|
||||
.name = "peri_pll_c2", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data s2f_usr1_free_mux[] = {
|
||||
{ .fw_name = "main_pll_c2",
|
||||
.name = "main_pll_c2", },
|
||||
{ .fw_name = "peri_pll_c2",
|
||||
.name = "peri_pll_c2", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mpu_mux[] = {
|
||||
{ .fw_name = "mpu_free_clk",
|
||||
.name = "mpu_free_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data s2f_usr0_mux[] = {
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emac_mux[] = {
|
||||
{ .fw_name = "emaca_free_clk",
|
||||
.name = "emaca_free_clk", },
|
||||
{ .fw_name = "emacb_free_clk",
|
||||
.name = "emacb_free_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data noc_mux[] = {
|
||||
{ .fw_name = "noc_free_clk",
|
||||
.name = "noc_free_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
/* clocks in AO (always on) controller */
|
||||
static const struct stratix10_pll_clock agilex_pll_clks[] = {
|
||||
{ AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
|
||||
0x0},
|
||||
{ AGILEX_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
|
||||
0, 0x48},
|
||||
{ AGILEX_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
|
||||
0, 0x9c},
|
||||
};
|
||||
|
||||
static const struct stratix10_perip_c_clock agilex_main_perip_c_clks[] = {
|
||||
{ AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x58},
|
||||
{ AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x5C},
|
||||
{ AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x64},
|
||||
{ AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x68},
|
||||
{ AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xAC},
|
||||
{ AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xB0},
|
||||
{ AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xB8},
|
||||
{ AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xBC},
|
||||
};
|
||||
|
||||
static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
|
||||
{ AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
|
||||
0, 0x3C, 0, 0, 0},
|
||||
{ AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
|
||||
0, 0x40, 0, 0, 1},
|
||||
{ AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
|
||||
0, 4, 0, 0},
|
||||
{ AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
|
||||
0, 0, 0, 0x30, 1},
|
||||
{ AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
|
||||
0, 0xD4, 0, 0x88, 0},
|
||||
{ AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
|
||||
0, 0xD8, 0, 0x88, 1},
|
||||
{ AGILEX_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
|
||||
ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2},
|
||||
{ AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
|
||||
ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3},
|
||||
{ AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
|
||||
ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4},
|
||||
{ AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux,
|
||||
ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0},
|
||||
{ AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
|
||||
ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88, 5},
|
||||
{ AGILEX_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
|
||||
ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6},
|
||||
};
|
||||
|
||||
static const struct stratix10_gate_clock agilex_gate_clks[] = {
|
||||
{ AGILEX_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x24,
|
||||
0, 0, 0, 0, 0x30, 0, 0},
|
||||
{ AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24,
|
||||
0, 0, 0, 0, 0, 0, 4},
|
||||
{ AGILEX_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x24,
|
||||
0, 0, 0, 0, 0, 0, 2},
|
||||
{ AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24,
|
||||
1, 0x44, 0, 2, 0, 0, 0},
|
||||
{ AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24,
|
||||
2, 0x44, 8, 2, 0, 0, 0},
|
||||
/*
|
||||
* The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them
|
||||
* being the SP timers, thus cannot get gated.
|
||||
*/
|
||||
{ AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24,
|
||||
3, 0x44, 16, 2, 0, 0, 0},
|
||||
{ AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24,
|
||||
4, 0x44, 24, 2, 0, 0, 0},
|
||||
{ AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24,
|
||||
4, 0x44, 26, 2, 0, 0, 0},
|
||||
{ AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24,
|
||||
4, 0x44, 28, 1, 0, 0, 0},
|
||||
{ AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24,
|
||||
5, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24,
|
||||
6, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
|
||||
0, 0, 0, 0, 0x94, 26, 0},
|
||||
{ AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
|
||||
1, 0, 0, 0, 0x94, 27, 0},
|
||||
{ AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
|
||||
2, 0, 0, 0, 0x94, 28, 0},
|
||||
{ AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C,
|
||||
3, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C,
|
||||
4, 0x98, 0, 16, 0, 0, 0},
|
||||
{ AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C,
|
||||
5, 0, 0, 0, 0, 0, 4},
|
||||
{ AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C,
|
||||
6, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C,
|
||||
7, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
|
||||
8, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
|
||||
9, 0, 0, 0, 0, 0, 0},
|
||||
{ AGILEX_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0x7C,
|
||||
10, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
|
||||
int nums, struct stratix10_clock_data *data)
|
||||
{
|
||||
struct clk *clk;
|
||||
void __iomem *base = data->base;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
clk = s10_register_periph(&clks[i], base);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
data->clk_data.clks[clks[i].id] = clk;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agilex_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
|
||||
int nums, struct stratix10_clock_data *data)
|
||||
{
|
||||
struct clk *clk;
|
||||
void __iomem *base = data->base;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
clk = s10_register_cnt_periph(&clks[i], base);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
data->clk_data.clks[clks[i].id] = clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks, int nums, struct stratix10_clock_data *data)
|
||||
{
|
||||
struct clk *clk;
|
||||
void __iomem *base = data->base;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
clk = s10_register_gate(&clks[i], base);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
data->clk_data.clks[clks[i].id] = clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agilex_clk_register_pll(const struct stratix10_pll_clock *clks,
|
||||
int nums, struct stratix10_clock_data *data)
|
||||
{
|
||||
struct clk *clk;
|
||||
void __iomem *base = data->base;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
clk = agilex_register_pll(&clks[i], base);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n",
|
||||
__func__, clks[i].name);
|
||||
continue;
|
||||
}
|
||||
data->clk_data.clks[clks[i].id] = clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct stratix10_clock_data *__socfpga_agilex_clk_init(struct platform_device *pdev,
|
||||
int nr_clks)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct stratix10_clock_data *clk_data;
|
||||
struct clk **clk_table;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
return ERR_CAST(base);
|
||||
|
||||
clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_data->base = base;
|
||||
clk_table = devm_kcalloc(dev, nr_clks, sizeof(*clk_table), GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_data->clk_data.clks = clk_table;
|
||||
clk_data->clk_data.clk_num = nr_clks;
|
||||
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return clk_data;
|
||||
}
|
||||
|
||||
static int agilex_clkmgr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct stratix10_clock_data *clk_data;
|
||||
|
||||
clk_data = __socfpga_agilex_clk_init(pdev, AGILEX_NUM_CLKS);
|
||||
if (IS_ERR(clk_data))
|
||||
return PTR_ERR(clk_data);
|
||||
|
||||
agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data);
|
||||
|
||||
agilex_clk_register_c_perip(agilex_main_perip_c_clks,
|
||||
ARRAY_SIZE(agilex_main_perip_c_clks), clk_data);
|
||||
|
||||
agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks,
|
||||
ARRAY_SIZE(agilex_main_perip_cnt_clks),
|
||||
clk_data);
|
||||
|
||||
agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks),
|
||||
clk_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id agilex_clkmgr_match_table[] = {
|
||||
{ .compatible = "intel,agilex-clkmgr",
|
||||
.data = agilex_clkmgr_probe },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver agilex_clkmgr_driver = {
|
||||
.probe = agilex_clkmgr_probe,
|
||||
.driver = {
|
||||
.name = "agilex-clkmgr",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = agilex_clkmgr_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init agilex_clk_init(void)
|
||||
{
|
||||
return platform_driver_register(&agilex_clkmgr_driver);
|
||||
}
|
||||
core_initcall(agilex_clk_init);
|
@ -70,7 +70,6 @@ struct clk *s10_register_gate(const struct stratix10_gate_clock *clks, void __io
|
||||
struct clk *clk;
|
||||
struct socfpga_gate_clk *socfpga_clk;
|
||||
struct clk_init_data init;
|
||||
const char * const *parent_names = clks->parent_names;
|
||||
const char *parent_name = clks->parent_name;
|
||||
|
||||
socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
|
||||
@ -108,7 +107,9 @@ struct clk *s10_register_gate(const struct stratix10_gate_clock *clks, void __io
|
||||
init.flags = clks->flags;
|
||||
|
||||
init.num_parents = clks->num_parents;
|
||||
init.parent_names = parent_names ? parent_names : &parent_name;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
if (init.parent_names == NULL)
|
||||
init.parent_data = clks->parent_data;
|
||||
socfpga_clk->hw.hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &socfpga_clk->hw.hw);
|
||||
|
@ -81,7 +81,6 @@ struct clk *s10_register_periph(const struct stratix10_perip_c_clock *clks,
|
||||
struct clk_init_data init;
|
||||
const char *name = clks->name;
|
||||
const char *parent_name = clks->parent_name;
|
||||
const char * const *parent_names = clks->parent_names;
|
||||
|
||||
periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
|
||||
if (WARN_ON(!periph_clk))
|
||||
@ -94,7 +93,9 @@ struct clk *s10_register_periph(const struct stratix10_perip_c_clock *clks,
|
||||
init.flags = clks->flags;
|
||||
|
||||
init.num_parents = clks->num_parents;
|
||||
init.parent_names = parent_names ? parent_names : &parent_name;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
if (init.parent_names == NULL)
|
||||
init.parent_data = clks->parent_data;
|
||||
|
||||
periph_clk->hw.hw.init = &init;
|
||||
|
||||
@ -114,7 +115,6 @@ struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks
|
||||
struct clk_init_data init;
|
||||
const char *name = clks->name;
|
||||
const char *parent_name = clks->parent_name;
|
||||
const char * const *parent_names = clks->parent_names;
|
||||
|
||||
periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
|
||||
if (WARN_ON(!periph_clk))
|
||||
@ -137,7 +137,9 @@ struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks
|
||||
init.flags = clks->flags;
|
||||
|
||||
init.num_parents = clks->num_parents;
|
||||
init.parent_names = parent_names ? parent_names : &parent_name;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
if (init.parent_names == NULL)
|
||||
init.parent_data = clks->parent_data;
|
||||
|
||||
periph_clk->hw.hw.init = &init;
|
||||
|
||||
|
@ -58,7 +58,7 @@ static u8 clk_pll_get_parent(struct clk_hw *hwclk)
|
||||
CLK_MGR_PLL_CLK_SRC_MASK;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_pll_ops = {
|
||||
static const struct clk_ops clk_pll_ops = {
|
||||
.recalc_rate = clk_pll_recalc_rate,
|
||||
.get_parent = clk_pll_get_parent,
|
||||
};
|
||||
@ -102,8 +102,6 @@ static struct clk * __init __socfpga_pll_init(struct device_node *node,
|
||||
pll_clk->hw.hw.init = &init;
|
||||
|
||||
pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
|
||||
clk_pll_ops.enable = clk_gate_ops.enable;
|
||||
clk_pll_ops.disable = clk_gate_ops.disable;
|
||||
|
||||
clk = clk_register(NULL, &pll_clk->hw.hw);
|
||||
if (WARN_ON(IS_ERR(clk))) {
|
||||
|
@ -18,8 +18,12 @@
|
||||
#define SOCFPGA_PLL_RESET_MASK 0x2
|
||||
#define SOCFPGA_PLL_REFDIV_MASK 0x00003F00
|
||||
#define SOCFPGA_PLL_REFDIV_SHIFT 8
|
||||
#define SOCFPGA_PLL_AREFDIV_MASK 0x00000F00
|
||||
#define SOCFPGA_PLL_DREFDIV_MASK 0x00003000
|
||||
#define SOCFPGA_PLL_DREFDIV_SHIFT 12
|
||||
#define SOCFPGA_PLL_MDIV_MASK 0xFF000000
|
||||
#define SOCFPGA_PLL_MDIV_SHIFT 24
|
||||
#define SOCFPGA_AGILEX_PLL_MDIV_MASK 0x000003FF
|
||||
#define SWCTRLBTCLKSEL_MASK 0x200
|
||||
#define SWCTRLBTCLKSEL_SHIFT 9
|
||||
|
||||
@ -27,6 +31,27 @@
|
||||
|
||||
#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
|
||||
|
||||
static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
|
||||
unsigned long arefdiv, reg, mdiv;
|
||||
unsigned long long vco_freq;
|
||||
|
||||
/* read VCO1 reg for numerator and denominator */
|
||||
reg = readl(socfpgaclk->hw.reg);
|
||||
arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
|
||||
|
||||
vco_freq = (unsigned long long)parent_rate / arefdiv;
|
||||
|
||||
/* Read mdiv and fdiv from the fdbck register */
|
||||
reg = readl(socfpgaclk->hw.reg + 0x24);
|
||||
mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK;
|
||||
|
||||
vco_freq = (unsigned long long)vco_freq * mdiv;
|
||||
return (unsigned long)vco_freq;
|
||||
}
|
||||
|
||||
static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@ -98,13 +123,19 @@ static int clk_pll_prepare(struct clk_hw *hwclk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_pll_ops = {
|
||||
static const struct clk_ops agilex_clk_pll_ops = {
|
||||
.recalc_rate = agilex_clk_pll_recalc_rate,
|
||||
.get_parent = clk_pll_get_parent,
|
||||
.prepare = clk_pll_prepare,
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_pll_ops = {
|
||||
.recalc_rate = clk_pll_recalc_rate,
|
||||
.get_parent = clk_pll_get_parent,
|
||||
.prepare = clk_pll_prepare,
|
||||
};
|
||||
|
||||
static struct clk_ops clk_boot_ops = {
|
||||
static const struct clk_ops clk_boot_ops = {
|
||||
.recalc_rate = clk_boot_clk_recalc_rate,
|
||||
.get_parent = clk_boot_get_parent,
|
||||
.prepare = clk_pll_prepare,
|
||||
@ -117,7 +148,6 @@ struct clk *s10_register_pll(const struct stratix10_pll_clock *clks,
|
||||
struct socfpga_pll *pll_clk;
|
||||
struct clk_init_data init;
|
||||
const char *name = clks->name;
|
||||
const char * const *parent_names = clks->parent_names;
|
||||
|
||||
pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
|
||||
if (WARN_ON(!pll_clk))
|
||||
@ -134,12 +164,48 @@ struct clk *s10_register_pll(const struct stratix10_pll_clock *clks,
|
||||
init.flags = clks->flags;
|
||||
|
||||
init.num_parents = clks->num_parents;
|
||||
init.parent_names = parent_names;
|
||||
init.parent_names = NULL;
|
||||
init.parent_data = clks->parent_data;
|
||||
pll_clk->hw.hw.init = &init;
|
||||
|
||||
pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
|
||||
|
||||
clk = clk_register(NULL, &pll_clk->hw.hw);
|
||||
if (WARN_ON(IS_ERR(clk))) {
|
||||
kfree(pll_clk);
|
||||
return NULL;
|
||||
}
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct clk *agilex_register_pll(const struct stratix10_pll_clock *clks,
|
||||
void __iomem *reg)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct socfpga_pll *pll_clk;
|
||||
struct clk_init_data init;
|
||||
const char *name = clks->name;
|
||||
|
||||
pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
|
||||
if (WARN_ON(!pll_clk))
|
||||
return NULL;
|
||||
|
||||
pll_clk->hw.reg = reg + clks->offset;
|
||||
|
||||
if (streq(name, SOCFPGA_BOOT_CLK))
|
||||
init.ops = &clk_boot_ops;
|
||||
else
|
||||
init.ops = &agilex_clk_pll_ops;
|
||||
|
||||
init.name = name;
|
||||
init.flags = clks->flags;
|
||||
|
||||
init.num_parents = clks->num_parents;
|
||||
init.parent_names = NULL;
|
||||
init.parent_data = clks->parent_data;
|
||||
pll_clk->hw.hw.init = &init;
|
||||
|
||||
pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
|
||||
clk_pll_ops.enable = clk_gate_ops.enable;
|
||||
clk_pll_ops.disable = clk_gate_ops.disable;
|
||||
|
||||
clk = clk_register(NULL, &pll_clk->hw.hw);
|
||||
if (WARN_ON(IS_ERR(clk))) {
|
||||
|
@ -65,7 +65,7 @@ static u8 clk_pll_get_parent(struct clk_hw *hwclk)
|
||||
CLK_MGR_PLL_CLK_SRC_MASK;
|
||||
}
|
||||
|
||||
static struct clk_ops clk_pll_ops = {
|
||||
static const struct clk_ops clk_pll_ops = {
|
||||
.recalc_rate = clk_pll_recalc_rate,
|
||||
.get_parent = clk_pll_get_parent,
|
||||
};
|
||||
@ -105,8 +105,6 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
|
||||
pll_clk->hw.hw.init = &init;
|
||||
|
||||
pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
|
||||
clk_pll_ops.enable = clk_gate_ops.enable;
|
||||
clk_pll_ops.disable = clk_gate_ops.disable;
|
||||
|
||||
clk = clk_register(NULL, &pll_clk->hw.hw);
|
||||
if (WARN_ON(IS_ERR(clk))) {
|
||||
|
@ -12,35 +12,137 @@
|
||||
|
||||
#include "stratix10-clk.h"
|
||||
|
||||
static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
|
||||
"f2s-free-clk",};
|
||||
static const char * const cntr_mux[] = { "main_pll", "periph_pll",
|
||||
"osc1", "cb-intosc-hs-div2-clk",
|
||||
"f2s-free-clk"};
|
||||
static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
|
||||
static const struct clk_parent_data pll_mux[] = {
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1" },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk" },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk" },
|
||||
};
|
||||
|
||||
static const char * const noc_free_mux[] = {"main_noc_base_clk",
|
||||
"peri_noc_base_clk",
|
||||
"osc1", "cb-intosc-hs-div2-clk",
|
||||
"f2s-free-clk"};
|
||||
static const struct clk_parent_data cntr_mux[] = {
|
||||
{ .fw_name = "main_pll",
|
||||
.name = "main_pll", },
|
||||
{ .fw_name = "periph_pll",
|
||||
.name = "periph_pll", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
|
||||
static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
|
||||
static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
|
||||
static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
|
||||
static const char * const sdmmc_free_mux[] = {"main_sdmmc_clk", "boot_clk"};
|
||||
static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
|
||||
static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
|
||||
static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
|
||||
static const struct clk_parent_data boot_mux[] = {
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1" },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk" },
|
||||
};
|
||||
|
||||
static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
|
||||
static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
|
||||
static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
|
||||
static const struct clk_parent_data noc_free_mux[] = {
|
||||
{ .fw_name = "main_noc_base_clk",
|
||||
.name = "main_noc_base_clk", },
|
||||
{ .fw_name = "peri_noc_base_clk",
|
||||
.name = "peri_noc_base_clk", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
|
||||
"peri_mpu_base_clk",
|
||||
"osc1", "cb-intosc-hs-div2-clk",
|
||||
"f2s-free-clk"};
|
||||
static const struct clk_parent_data emaca_free_mux[] = {
|
||||
{ .fw_name = "peri_emaca_clk",
|
||||
.name = "peri_emaca_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emacb_free_mux[] = {
|
||||
{ .fw_name = "peri_emacb_clk",
|
||||
.name = "peri_emacb_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emac_ptp_free_mux[] = {
|
||||
{ .fw_name = "peri_emac_ptp_clk",
|
||||
.name = "peri_emac_ptp_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data gpio_db_free_mux[] = {
|
||||
{ .fw_name = "peri_gpio_db_clk",
|
||||
.name = "peri_gpio_db_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data sdmmc_free_mux[] = {
|
||||
{ .fw_name = "main_sdmmc_clk",
|
||||
.name = "main_sdmmc_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data s2f_usr1_free_mux[] = {
|
||||
{ .fw_name = "peri_s2f_usr1_clk",
|
||||
.name = "peri_s2f_usr1_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data psi_ref_free_mux[] = {
|
||||
{ .fw_name = "peri_psi_ref_clk",
|
||||
.name = "peri_psi_ref_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mpu_mux[] = {
|
||||
{ .fw_name = "mpu_free_clk",
|
||||
.name = "mpu_free_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data s2f_usr0_mux[] = {
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data emac_mux[] = {
|
||||
{ .fw_name = "emaca_free_clk",
|
||||
.name = "emaca_free_clk", },
|
||||
{ .fw_name = "emacb_free_clk",
|
||||
.name = "emacb_free_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data noc_mux[] = {
|
||||
{ .fw_name = "noc_free_clk",
|
||||
.name = "noc_free_clk", },
|
||||
{ .fw_name = "boot_clk",
|
||||
.name = "boot_clk", },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mpu_free_mux[] = {
|
||||
{ .fw_name = "main_mpu_base_clk",
|
||||
.name = "main_mpu_base_clk", },
|
||||
{ .fw_name = "peri_mpu_base_clk",
|
||||
.name = "peri_mpu_base_clk", },
|
||||
{ .fw_name = "osc1",
|
||||
.name = "osc1", },
|
||||
{ .fw_name = "cb-intosc-hs-div2-clk",
|
||||
.name = "cb-intosc-hs-div2-clk", },
|
||||
{ .fw_name = "f2s-free-clk",
|
||||
.name = "f2s-free-clk", },
|
||||
};
|
||||
|
||||
/* clocks in AO (always on) controller */
|
||||
static const struct stratix10_pll_clock s10_pll_clks[] = {
|
||||
|
@ -14,7 +14,7 @@ struct stratix10_clock_data {
|
||||
struct stratix10_pll_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *const *parent_names;
|
||||
const struct clk_parent_data *parent_data;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
@ -24,7 +24,7 @@ struct stratix10_perip_c_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const char *const *parent_names;
|
||||
const struct clk_parent_data *parent_data;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
@ -34,7 +34,7 @@ struct stratix10_perip_cnt_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const char *const *parent_names;
|
||||
const struct clk_parent_data *parent_data;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
@ -47,7 +47,7 @@ struct stratix10_gate_clock {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const char *const *parent_names;
|
||||
const struct clk_parent_data *parent_data;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long gate_reg;
|
||||
@ -62,6 +62,8 @@ struct stratix10_gate_clock {
|
||||
|
||||
struct clk *s10_register_pll(const struct stratix10_pll_clock *,
|
||||
void __iomem *);
|
||||
struct clk *agilex_register_pll(const struct stratix10_pll_clock *,
|
||||
void __iomem *);
|
||||
struct clk *s10_register_periph(const struct stratix10_perip_c_clock *,
|
||||
void __iomem *);
|
||||
struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *,
|
||||
|
@ -1,8 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config TEGRA_CLK_EMC
|
||||
def_bool y
|
||||
depends on TEGRA124_EMC
|
||||
|
||||
config CLK_TEGRA_BPMP
|
||||
def_bool y
|
||||
depends on TEGRA_BPMP
|
||||
|
@ -13,8 +13,8 @@ obj-y += clk-super.o
|
||||
obj-y += clk-tegra-audio.o
|
||||
obj-y += clk-tegra-periph.o
|
||||
obj-y += clk-tegra-fixed.o
|
||||
obj-y += clk-tegra-super-cclk.o
|
||||
obj-y += clk-tegra-super-gen4.o
|
||||
obj-$(CONFIG_TEGRA_CLK_EMC) += clk-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
|
||||
@ -22,8 +22,10 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra20-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
|
||||
obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
|
||||
obj-$(CONFIG_TEGRA124_EMC) += clk-tegra124-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
|
||||
obj-y += cvb.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210-emc.o
|
||||
obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o
|
||||
obj-y += clk-utils.o
|
||||
|
@ -744,13 +744,19 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
||||
|
||||
state = clk_pll_is_enabled(hw);
|
||||
|
||||
if (state && pll->params->pre_rate_change) {
|
||||
ret = pll->params->pre_rate_change();
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
_get_pll_mnp(pll, &old_cfg);
|
||||
|
||||
if (state && pll->params->defaults_set && pll->params->dyn_ramp &&
|
||||
(cfg->m == old_cfg.m) && (cfg->p == old_cfg.p)) {
|
||||
ret = pll->params->dyn_ramp(pll, cfg);
|
||||
if (!ret)
|
||||
return 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (state) {
|
||||
@ -772,6 +778,10 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
||||
pll_clk_start_ss(pll);
|
||||
}
|
||||
|
||||
done:
|
||||
if (state && pll->params->post_rate_change)
|
||||
pll->params->post_rate_change();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
212
drivers/clk/tegra/clk-tegra-super-cclk.c
Normal file
212
drivers/clk/tegra/clk-tegra-super-cclk.c
Normal file
@ -0,0 +1,212 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Based on clk-super.c
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Based on older tegra20-cpufreq driver by Colin Cross <ccross@google.com>
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
*
|
||||
* Author: Dmitry Osipenko <digetx@gmail.com>
|
||||
* Copyright (C) 2019 GRATE-DRIVER project
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
#define PLLP_INDEX 4
|
||||
#define PLLX_INDEX 8
|
||||
|
||||
#define SUPER_CDIV_ENB BIT(31)
|
||||
|
||||
static struct tegra_clk_super_mux *cclk_super;
|
||||
static bool cclk_on_pllx;
|
||||
|
||||
static u8 cclk_super_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
return tegra_clk_super_ops.get_parent(hw);
|
||||
}
|
||||
|
||||
static int cclk_super_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
return tegra_clk_super_ops.set_parent(hw, index);
|
||||
}
|
||||
|
||||
static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
return tegra_clk_super_ops.set_rate(hw, rate, parent_rate);
|
||||
}
|
||||
|
||||
static unsigned long cclk_super_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
if (cclk_super_get_parent(hw) == PLLX_INDEX)
|
||||
return parent_rate;
|
||||
|
||||
return tegra_clk_super_ops.recalc_rate(hw, parent_rate);
|
||||
}
|
||||
|
||||
static int cclk_super_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_hw *pllp_hw = clk_hw_get_parent_by_index(hw, PLLP_INDEX);
|
||||
struct clk_hw *pllx_hw = clk_hw_get_parent_by_index(hw, PLLX_INDEX);
|
||||
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||
unsigned long pllp_rate;
|
||||
long rate = req->rate;
|
||||
|
||||
if (WARN_ON_ONCE(!pllp_hw || !pllx_hw))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Switch parent to PLLP for all CCLK rates that are suitable for PLLP.
|
||||
* PLLX will be disabled in this case, saving some power.
|
||||
*/
|
||||
pllp_rate = clk_hw_get_rate(pllp_hw);
|
||||
|
||||
if (rate <= pllp_rate) {
|
||||
if (super->flags & TEGRA20_SUPER_CLK)
|
||||
rate = pllp_rate;
|
||||
else
|
||||
rate = tegra_clk_super_ops.round_rate(hw, rate,
|
||||
&pllp_rate);
|
||||
|
||||
req->best_parent_rate = pllp_rate;
|
||||
req->best_parent_hw = pllp_hw;
|
||||
req->rate = rate;
|
||||
} else {
|
||||
rate = clk_hw_round_rate(pllx_hw, rate);
|
||||
req->best_parent_rate = rate;
|
||||
req->best_parent_hw = pllx_hw;
|
||||
req->rate = rate;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(rate <= 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops tegra_cclk_super_ops = {
|
||||
.get_parent = cclk_super_get_parent,
|
||||
.set_parent = cclk_super_set_parent,
|
||||
.set_rate = cclk_super_set_rate,
|
||||
.recalc_rate = cclk_super_recalc_rate,
|
||||
.determine_rate = cclk_super_determine_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops tegra_cclk_super_mux_ops = {
|
||||
.get_parent = cclk_super_get_parent,
|
||||
.set_parent = cclk_super_set_parent,
|
||||
.determine_rate = cclk_super_determine_rate,
|
||||
};
|
||||
|
||||
struct clk *tegra_clk_register_super_cclk(const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct tegra_clk_super_mux *super;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
u32 val;
|
||||
|
||||
if (WARN_ON(cclk_super))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
||||
if (!super)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.flags = flags;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
|
||||
super->reg = reg;
|
||||
super->lock = lock;
|
||||
super->width = 4;
|
||||
super->flags = clk_super_flags;
|
||||
super->hw.init = &init;
|
||||
|
||||
if (super->flags & TEGRA20_SUPER_CLK) {
|
||||
init.ops = &tegra_cclk_super_mux_ops;
|
||||
} else {
|
||||
init.ops = &tegra_cclk_super_ops;
|
||||
|
||||
super->frac_div.reg = reg + 4;
|
||||
super->frac_div.shift = 16;
|
||||
super->frac_div.width = 8;
|
||||
super->frac_div.frac_width = 1;
|
||||
super->frac_div.lock = lock;
|
||||
super->div_ops = &tegra_clk_frac_div_ops;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tegra30+ has the following CPUG clock topology:
|
||||
*
|
||||
* +---+ +-------+ +-+ +-+ +-+
|
||||
* PLLP+->+ +->+DIVIDER+->+0| +-------->+0| ------------->+0|
|
||||
* | | +-------+ | | | +---+ | | | | |
|
||||
* PLLC+->+MUX| | +->+ | S | | +->+ | +->+CPU
|
||||
* ... | | | | | | K | | | | +-------+ | |
|
||||
* PLLX+->+-->+------------>+1| +->+ I +->+1| +->+ DIV2 +->+1|
|
||||
* +---+ +++ | P | +++ |SKIPPER| +++
|
||||
* ^ | P | ^ +-------+ ^
|
||||
* | | E | | |
|
||||
* PLLX_SEL+--+ | R | | OVERHEAT+--+
|
||||
* +---+ |
|
||||
* |
|
||||
* SUPER_CDIV_ENB+--+
|
||||
*
|
||||
* Tegra20 is similar, but simpler. It doesn't have the divider and
|
||||
* thermal DIV2 skipper.
|
||||
*
|
||||
* At least for now we're not going to use clock-skipper, hence let's
|
||||
* ensure that it is disabled.
|
||||
*/
|
||||
val = readl_relaxed(reg + 4);
|
||||
val &= ~SUPER_CDIV_ENB;
|
||||
writel_relaxed(val, reg + 4);
|
||||
|
||||
clk = clk_register(NULL, &super->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(super);
|
||||
else
|
||||
cclk_super = super;
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
int tegra_cclk_pre_pllx_rate_change(void)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(cclk_super))
|
||||
return -EINVAL;
|
||||
|
||||
if (cclk_super_get_parent(&cclk_super->hw) == PLLX_INDEX)
|
||||
cclk_on_pllx = true;
|
||||
else
|
||||
cclk_on_pllx = false;
|
||||
|
||||
/*
|
||||
* CPU needs to be temporarily re-parented away from PLLX if PLLX
|
||||
* changes its rate. PLLP is a safe parent for CPU on all Tegra SoCs.
|
||||
*/
|
||||
if (cclk_on_pllx)
|
||||
cclk_super_set_parent(&cclk_super->hw, PLLP_INDEX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tegra_cclk_post_pllx_rate_change(void)
|
||||
{
|
||||
if (cclk_on_pllx)
|
||||
cclk_super_set_parent(&cclk_super->hw, PLLX_INDEX);
|
||||
}
|
@ -391,6 +391,8 @@ static struct tegra_clk_pll_params pll_x_params = {
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_x_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.pre_rate_change = tegra_cclk_pre_pllx_rate_change,
|
||||
.post_rate_change = tegra_cclk_post_pllx_rate_change,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_e_params = {
|
||||
@ -702,9 +704,10 @@ static void tegra20_super_clk_init(void)
|
||||
struct clk *clk;
|
||||
|
||||
/* CCLK */
|
||||
clk = tegra_clk_register_super_mux("cclk", cclk_parents,
|
||||
clk = tegra_clk_register_super_cclk("cclk", cclk_parents,
|
||||
ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
|
||||
clk_base + CCLK_BURST_POLICY, TEGRA20_SUPER_CLK,
|
||||
NULL);
|
||||
clks[TEGRA20_CLK_CCLK] = clk;
|
||||
|
||||
/* SCLK */
|
||||
|
369
drivers/clk/tegra/clk-tegra210-emc.c
Normal file
369
drivers/clk/tegra/clk-tegra210-emc.c
Normal file
@ -0,0 +1,369 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2015-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define CLK_SOURCE_EMC 0x19c
|
||||
#define CLK_SOURCE_EMC_2X_CLK_SRC GENMASK(31, 29)
|
||||
#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ BIT(16)
|
||||
#define CLK_SOURCE_EMC_2X_CLK_DIVISOR GENMASK(7, 0)
|
||||
|
||||
#define CLK_SRC_PLLM 0
|
||||
#define CLK_SRC_PLLC 1
|
||||
#define CLK_SRC_PLLP 2
|
||||
#define CLK_SRC_CLK_M 3
|
||||
#define CLK_SRC_PLLM_UD 4
|
||||
#define CLK_SRC_PLLMB_UD 5
|
||||
#define CLK_SRC_PLLMB 6
|
||||
#define CLK_SRC_PLLP_UD 7
|
||||
|
||||
struct tegra210_clk_emc {
|
||||
struct clk_hw hw;
|
||||
void __iomem *regs;
|
||||
|
||||
struct tegra210_clk_emc_provider *provider;
|
||||
|
||||
struct clk *parents[8];
|
||||
};
|
||||
|
||||
static inline struct tegra210_clk_emc *
|
||||
to_tegra210_clk_emc(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct tegra210_clk_emc, hw);
|
||||
}
|
||||
|
||||
static const char *tegra210_clk_emc_parents[] = {
|
||||
"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb_ud",
|
||||
"pll_mb", "pll_p_ud",
|
||||
};
|
||||
|
||||
static u8 tegra210_clk_emc_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
|
||||
u32 value;
|
||||
u8 src;
|
||||
|
||||
value = readl_relaxed(emc->regs + CLK_SOURCE_EMC);
|
||||
src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, value);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static unsigned long tegra210_clk_emc_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
|
||||
u32 value, div;
|
||||
|
||||
/*
|
||||
* CCF assumes that neither the parent nor its rate will change during
|
||||
* ->set_rate(), so the parent rate passed in here was cached from the
|
||||
* parent before the ->set_rate() call.
|
||||
*
|
||||
* This can lead to wrong results being reported for the EMC clock if
|
||||
* the parent and/or parent rate have changed as part of the EMC rate
|
||||
* change sequence. Fix this by overriding the parent clock with what
|
||||
* we know to be the correct value after the rate change.
|
||||
*/
|
||||
parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
|
||||
|
||||
value = readl_relaxed(emc->regs + CLK_SOURCE_EMC);
|
||||
|
||||
div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, value);
|
||||
div += 2;
|
||||
|
||||
return DIV_ROUND_UP(parent_rate * 2, div);
|
||||
}
|
||||
|
||||
static long tegra210_clk_emc_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
|
||||
struct tegra210_clk_emc_provider *provider = emc->provider;
|
||||
unsigned int i;
|
||||
|
||||
if (!provider || !provider->configs || provider->num_configs == 0)
|
||||
return clk_hw_get_rate(hw);
|
||||
|
||||
for (i = 0; i < provider->num_configs; i++) {
|
||||
if (provider->configs[i].rate >= rate)
|
||||
return provider->configs[i].rate;
|
||||
}
|
||||
|
||||
return provider->configs[i - 1].rate;
|
||||
}
|
||||
|
||||
static struct clk *tegra210_clk_emc_find_parent(struct tegra210_clk_emc *emc,
|
||||
u8 index)
|
||||
{
|
||||
struct clk_hw *parent = clk_hw_get_parent_by_index(&emc->hw, index);
|
||||
const char *name = clk_hw_get_name(parent);
|
||||
|
||||
/* XXX implement cache? */
|
||||
|
||||
return __clk_lookup(name);
|
||||
}
|
||||
|
||||
static int tegra210_clk_emc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
|
||||
struct tegra210_clk_emc_provider *provider = emc->provider;
|
||||
struct tegra210_clk_emc_config *config;
|
||||
struct device *dev = provider->dev;
|
||||
struct clk_hw *old, *new, *parent;
|
||||
u8 old_idx, new_idx, index;
|
||||
struct clk *clk;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if (!provider || !provider->configs || provider->num_configs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < provider->num_configs; i++) {
|
||||
if (provider->configs[i].rate >= rate) {
|
||||
config = &provider->configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == provider->num_configs)
|
||||
config = &provider->configs[i - 1];
|
||||
|
||||
old_idx = tegra210_clk_emc_get_parent(hw);
|
||||
new_idx = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value);
|
||||
|
||||
old = clk_hw_get_parent_by_index(hw, old_idx);
|
||||
new = clk_hw_get_parent_by_index(hw, new_idx);
|
||||
|
||||
/* if the rate has changed... */
|
||||
if (config->parent_rate != clk_hw_get_rate(old)) {
|
||||
/* ... but the clock source remains the same ... */
|
||||
if (new_idx == old_idx) {
|
||||
/* ... switch to the alternative clock source. */
|
||||
switch (new_idx) {
|
||||
case CLK_SRC_PLLM:
|
||||
new_idx = CLK_SRC_PLLMB;
|
||||
break;
|
||||
|
||||
case CLK_SRC_PLLM_UD:
|
||||
new_idx = CLK_SRC_PLLMB_UD;
|
||||
break;
|
||||
|
||||
case CLK_SRC_PLLMB_UD:
|
||||
new_idx = CLK_SRC_PLLM_UD;
|
||||
break;
|
||||
|
||||
case CLK_SRC_PLLMB:
|
||||
new_idx = CLK_SRC_PLLM;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This should never happen because we can't deal with
|
||||
* it.
|
||||
*/
|
||||
if (WARN_ON(new_idx == old_idx))
|
||||
return -EINVAL;
|
||||
|
||||
new = clk_hw_get_parent_by_index(hw, new_idx);
|
||||
}
|
||||
|
||||
index = new_idx;
|
||||
parent = new;
|
||||
} else {
|
||||
index = old_idx;
|
||||
parent = old;
|
||||
}
|
||||
|
||||
clk = tegra210_clk_emc_find_parent(emc, index);
|
||||
if (IS_ERR(clk)) {
|
||||
err = PTR_ERR(clk);
|
||||
dev_err(dev, "failed to get parent clock for index %u: %d\n",
|
||||
index, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the new parent clock to the required rate */
|
||||
if (clk_get_rate(clk) != config->parent_rate) {
|
||||
err = clk_set_rate(clk, config->parent_rate);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to set rate %lu Hz for %pC: %d\n",
|
||||
config->parent_rate, clk, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable the new parent clock */
|
||||
if (parent != old) {
|
||||
err = clk_prepare_enable(clk);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to enable parent clock %pC: %d\n",
|
||||
clk, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* update the EMC source configuration to reflect the new parent */
|
||||
config->value &= ~CLK_SOURCE_EMC_2X_CLK_SRC;
|
||||
config->value |= FIELD_PREP(CLK_SOURCE_EMC_2X_CLK_SRC, index);
|
||||
|
||||
/*
|
||||
* Finally, switch the EMC programming with both old and new parent
|
||||
* clocks enabled.
|
||||
*/
|
||||
err = provider->set_rate(dev, config);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to set EMC rate to %lu Hz: %d\n", rate,
|
||||
err);
|
||||
|
||||
/*
|
||||
* If we're unable to switch to the new EMC frequency, we no
|
||||
* longer need the new parent to be enabled.
|
||||
*/
|
||||
if (parent != old)
|
||||
clk_disable_unprepare(clk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* reparent to new parent clock and disable the old parent clock */
|
||||
if (parent != old) {
|
||||
clk = tegra210_clk_emc_find_parent(emc, old_idx);
|
||||
if (IS_ERR(clk)) {
|
||||
err = PTR_ERR(clk);
|
||||
dev_err(dev,
|
||||
"failed to get parent clock for index %u: %d\n",
|
||||
old_idx, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
clk_hw_reparent(hw, parent);
|
||||
clk_disable_unprepare(clk);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct clk_ops tegra210_clk_emc_ops = {
|
||||
.get_parent = tegra210_clk_emc_get_parent,
|
||||
.recalc_rate = tegra210_clk_emc_recalc_rate,
|
||||
.round_rate = tegra210_clk_emc_round_rate,
|
||||
.set_rate = tegra210_clk_emc_set_rate,
|
||||
};
|
||||
|
||||
struct clk *tegra210_clk_register_emc(struct device_node *np,
|
||||
void __iomem *regs)
|
||||
{
|
||||
struct tegra210_clk_emc *emc;
|
||||
struct clk_init_data init;
|
||||
struct clk *clk;
|
||||
|
||||
emc = kzalloc(sizeof(*emc), GFP_KERNEL);
|
||||
if (!emc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
emc->regs = regs;
|
||||
|
||||
init.name = "emc";
|
||||
init.ops = &tegra210_clk_emc_ops;
|
||||
init.flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = tegra210_clk_emc_parents;
|
||||
init.num_parents = ARRAY_SIZE(tegra210_clk_emc_parents);
|
||||
emc->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &emc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(emc);
|
||||
return clk;
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
int tegra210_clk_emc_attach(struct clk *clk,
|
||||
struct tegra210_clk_emc_provider *provider)
|
||||
{
|
||||
struct clk_hw *hw = __clk_get_hw(clk);
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
|
||||
struct device *dev = provider->dev;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if (!try_module_get(provider->owner))
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < provider->num_configs; i++) {
|
||||
struct tegra210_clk_emc_config *config = &provider->configs[i];
|
||||
struct clk_hw *parent;
|
||||
bool same_freq;
|
||||
u8 div, src;
|
||||
|
||||
div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, config->value);
|
||||
src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value);
|
||||
|
||||
/* do basic sanity checking on the EMC timings */
|
||||
if (div & 0x1) {
|
||||
dev_err(dev, "invalid odd divider %u for rate %lu Hz\n",
|
||||
div, config->rate);
|
||||
err = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
same_freq = config->value & CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
|
||||
|
||||
if (same_freq != config->same_freq) {
|
||||
dev_err(dev,
|
||||
"ambiguous EMC to MC ratio for rate %lu Hz\n",
|
||||
config->rate);
|
||||
err = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
parent = clk_hw_get_parent_by_index(hw, src);
|
||||
config->parent = src;
|
||||
|
||||
if (src == CLK_SRC_PLLM || src == CLK_SRC_PLLM_UD) {
|
||||
config->parent_rate = config->rate * (1 + div / 2);
|
||||
} else {
|
||||
unsigned long rate = config->rate * (1 + div / 2);
|
||||
|
||||
config->parent_rate = clk_hw_get_rate(parent);
|
||||
|
||||
if (config->parent_rate != rate) {
|
||||
dev_err(dev,
|
||||
"rate %lu Hz does not match input\n",
|
||||
config->rate);
|
||||
err = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emc->provider = provider;
|
||||
|
||||
return 0;
|
||||
|
||||
put:
|
||||
module_put(provider->owner);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_clk_emc_attach);
|
||||
|
||||
void tegra210_clk_emc_detach(struct clk *clk)
|
||||
{
|
||||
struct tegra210_clk_emc *emc = to_tegra210_clk_emc(__clk_get_hw(clk));
|
||||
|
||||
module_put(emc->provider->owner);
|
||||
emc->provider = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_clk_emc_detach);
|
@ -37,6 +37,7 @@
|
||||
#define CLK_SOURCE_LA 0x1f8
|
||||
#define CLK_SOURCE_SDMMC2 0x154
|
||||
#define CLK_SOURCE_SDMMC4 0x164
|
||||
#define CLK_SOURCE_EMC_DLL 0x664
|
||||
|
||||
#define PLLC_BASE 0x80
|
||||
#define PLLC_OUT 0x84
|
||||
@ -227,6 +228,10 @@
|
||||
#define RST_DFLL_DVCO 0x2f4
|
||||
#define DVFS_DFLL_RESET_SHIFT 0
|
||||
|
||||
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X_SET 0x284
|
||||
#define CLK_RST_CONTROLLER_CLK_OUT_ENB_X_CLR 0x288
|
||||
#define CLK_OUT_ENB_X_CLK_ENB_EMC_DLL BIT(14)
|
||||
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
|
||||
#define CPU_SOFTRST_CTRL 0x380
|
||||
@ -314,12 +319,6 @@ static unsigned long tegra210_input_freq[] = {
|
||||
[8] = 12000000,
|
||||
};
|
||||
|
||||
static const char *mux_pllmcp_clkm[] = {
|
||||
"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb", "pll_mb",
|
||||
"pll_p",
|
||||
};
|
||||
#define mux_pllmcp_clkm_idx NULL
|
||||
|
||||
#define PLL_ENABLE (1 << 30)
|
||||
|
||||
#define PLLCX_MISC1_IDDQ (1 << 27)
|
||||
@ -555,6 +554,27 @@ void tegra210_set_sata_pll_seq_sw(bool state)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw);
|
||||
|
||||
void tegra210_clk_emc_dll_enable(bool flag)
|
||||
{
|
||||
u32 offset = flag ? CLK_RST_CONTROLLER_CLK_OUT_ENB_X_SET :
|
||||
CLK_RST_CONTROLLER_CLK_OUT_ENB_X_CLR;
|
||||
|
||||
writel_relaxed(CLK_OUT_ENB_X_CLK_ENB_EMC_DLL, clk_base + offset);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_clk_emc_dll_enable);
|
||||
|
||||
void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value)
|
||||
{
|
||||
writel_relaxed(emc_dll_src_value, clk_base + CLK_SOURCE_EMC_DLL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_clk_emc_dll_update_setting);
|
||||
|
||||
void tegra210_clk_emc_update_setting(u32 emc_src_value)
|
||||
{
|
||||
writel_relaxed(emc_src_value, clk_base + CLK_SOURCE_EMC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra210_clk_emc_update_setting);
|
||||
|
||||
static void tegra210_generic_mbist_war(struct tegra210_domain_mbist_war *mbist)
|
||||
{
|
||||
u32 val;
|
||||
@ -2310,7 +2330,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_i2c2] = { .dt_id = TEGRA210_CLK_I2C2, .present = true },
|
||||
[tegra_clk_uartc_8] = { .dt_id = TEGRA210_CLK_UARTC, .present = true },
|
||||
[tegra_clk_mipi_cal] = { .dt_id = TEGRA210_CLK_MIPI_CAL, .present = true },
|
||||
[tegra_clk_emc] = { .dt_id = TEGRA210_CLK_EMC, .present = true },
|
||||
[tegra_clk_usb2] = { .dt_id = TEGRA210_CLK_USB2, .present = true },
|
||||
[tegra_clk_bsev] = { .dt_id = TEGRA210_CLK_BSEV, .present = true },
|
||||
[tegra_clk_uartd_8] = { .dt_id = TEGRA210_CLK_UARTD, .present = true },
|
||||
@ -2953,6 +2972,27 @@ static const char * const sor1_parents[] = {
|
||||
|
||||
static u32 sor1_parents_idx[] = { 0, 2, 5, 6 };
|
||||
|
||||
static const struct clk_div_table mc_div_table_tegra210[] = {
|
||||
{ .val = 0, .div = 2 },
|
||||
{ .val = 1, .div = 4 },
|
||||
{ .val = 2, .div = 1 },
|
||||
{ .val = 3, .div = 2 },
|
||||
{ .val = 0, .div = 0 },
|
||||
};
|
||||
|
||||
static void tegra210_clk_register_mc(const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_register_divider_table(NULL, name, parent_name,
|
||||
CLK_IS_CRITICAL,
|
||||
clk_base + CLK_SOURCE_EMC,
|
||||
15, 2, CLK_DIVIDER_READ_ONLY,
|
||||
mc_div_table_tegra210, &emc_lock);
|
||||
clks[TEGRA210_CLK_MC] = clk;
|
||||
}
|
||||
|
||||
static const char * const sor1_out_parents[] = {
|
||||
/*
|
||||
* Bit 0 of the mux selects sor1_pad_clkout, irrespective of bit 1, so
|
||||
@ -2995,7 +3035,8 @@ static const char * const la_parents[] = {
|
||||
static struct tegra_clk_periph tegra210_la =
|
||||
TEGRA_CLK_PERIPH(29, 7, 9, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, 76, 0, NULL, NULL);
|
||||
|
||||
static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
||||
static __init void tegra210_periph_clk_init(struct device_node *np,
|
||||
void __iomem *clk_base,
|
||||
void __iomem *pmc_base)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -3035,22 +3076,19 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
||||
periph_clk_enb_refcnt);
|
||||
clks[TEGRA210_CLK_DSIB] = clk;
|
||||
|
||||
/* csi_tpg */
|
||||
clk = clk_register_gate(NULL, "csi_tpg", "pll_d",
|
||||
CLK_SET_RATE_PARENT, clk_base + PLLD_BASE,
|
||||
23, 0, &pll_d_lock);
|
||||
clk_register_clkdev(clk, "csi_tpg", NULL);
|
||||
clks[TEGRA210_CLK_CSI_TPG] = clk;
|
||||
|
||||
/* la */
|
||||
clk = tegra_clk_register_periph("la", la_parents,
|
||||
ARRAY_SIZE(la_parents), &tegra210_la, clk_base,
|
||||
CLK_SOURCE_LA, 0);
|
||||
clks[TEGRA210_CLK_LA] = clk;
|
||||
|
||||
/* emc mux */
|
||||
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
|
||||
ARRAY_SIZE(mux_pllmcp_clkm), 0,
|
||||
clk_base + CLK_SOURCE_EMC,
|
||||
29, 3, 0, &emc_lock);
|
||||
|
||||
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
|
||||
&emc_lock);
|
||||
clks[TEGRA210_CLK_MC] = clk;
|
||||
|
||||
/* cml0 */
|
||||
clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
|
||||
0, 0, &pll_e_lock);
|
||||
@ -3093,6 +3131,13 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
||||
}
|
||||
|
||||
tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params);
|
||||
|
||||
/* emc */
|
||||
clk = tegra210_clk_register_emc(np, clk_base);
|
||||
clks[TEGRA210_CLK_EMC] = clk;
|
||||
|
||||
/* mc */
|
||||
tegra210_clk_register_mc("mc", "emc");
|
||||
}
|
||||
|
||||
static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
@ -3153,6 +3198,17 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
clk_register_clkdev(clk, "pll_m_ud", NULL);
|
||||
clks[TEGRA210_CLK_PLL_M_UD] = clk;
|
||||
|
||||
/* PLLMB_UD */
|
||||
clk = clk_register_fixed_factor(NULL, "pll_mb_ud", "pll_mb",
|
||||
CLK_SET_RATE_PARENT, 1, 1);
|
||||
clk_register_clkdev(clk, "pll_mb_ud", NULL);
|
||||
clks[TEGRA210_CLK_PLL_MB_UD] = clk;
|
||||
|
||||
/* PLLP_UD */
|
||||
clk = clk_register_fixed_factor(NULL, "pll_p_ud", "pll_p",
|
||||
0, 1, 1);
|
||||
clks[TEGRA210_CLK_PLL_P_UD] = clk;
|
||||
|
||||
/* PLLU_VCO */
|
||||
if (!tegra210_init_pllu()) {
|
||||
clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0,
|
||||
@ -3680,7 +3736,7 @@ static void __init tegra210_clock_init(struct device_node *np)
|
||||
|
||||
tegra_fixed_clk_init(tegra210_clks);
|
||||
tegra210_pll_init(clk_base, pmc_base);
|
||||
tegra210_periph_clk_init(clk_base, pmc_base);
|
||||
tegra210_periph_clk_init(np, clk_base, pmc_base);
|
||||
tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks,
|
||||
tegra210_audio_plls,
|
||||
ARRAY_SIZE(tegra210_audio_plls), 24576000);
|
||||
|
@ -499,6 +499,8 @@ static struct tegra_clk_pll_params pll_x_params __ro_after_init = {
|
||||
.freq_table = pll_x_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON |
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.pre_rate_change = tegra_cclk_pre_pllx_rate_change,
|
||||
.post_rate_change = tegra_cclk_post_pllx_rate_change,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_e_params __ro_after_init = {
|
||||
@ -926,11 +928,11 @@ static void __init tegra30_super_clk_init(void)
|
||||
clk_register_clkdev(clk, "pll_p_out4_cclkg", NULL);
|
||||
|
||||
/* CCLKG */
|
||||
clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
|
||||
clk = tegra_clk_register_super_cclk("cclk_g", cclk_g_parents,
|
||||
ARRAY_SIZE(cclk_g_parents),
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLKG_BURST_POLICY,
|
||||
0, 4, 0, 0, NULL);
|
||||
0, NULL);
|
||||
clks[TEGRA30_CLK_CCLK_G] = clk;
|
||||
|
||||
/*
|
||||
|
@ -266,6 +266,10 @@ struct tegra_clk_pll;
|
||||
* disabled.
|
||||
* @dyn_ramp: Callback which can be used to define a custom
|
||||
* dynamic ramp function for a given PLL.
|
||||
* @pre_rate_change: Callback which is invoked just before changing
|
||||
* PLL's rate.
|
||||
* @post_rate_change: Callback which is invoked right after changing
|
||||
* PLL's rate.
|
||||
*
|
||||
* Flags:
|
||||
* TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
|
||||
@ -342,6 +346,8 @@ struct tegra_clk_pll_params {
|
||||
void (*set_defaults)(struct tegra_clk_pll *pll);
|
||||
int (*dyn_ramp)(struct tegra_clk_pll *pll,
|
||||
struct tegra_clk_pll_freq_table *cfg);
|
||||
int (*pre_rate_change)(void);
|
||||
void (*post_rate_change)(void);
|
||||
};
|
||||
|
||||
#define TEGRA_PLL_USE_LOCK BIT(0)
|
||||
@ -729,8 +735,10 @@ struct clk *tegra_clk_register_periph_data(void __iomem *clk_base,
|
||||
* TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
|
||||
* that this is LP cluster clock.
|
||||
* TEGRA210_CPU_CLK - This flag is used to identify CPU cluster for gen5
|
||||
* super mux parent using PLLP branches. To use PLLP branches to CPU, need
|
||||
* to configure additional bit PLLP_OUT_CPU in the clock registers.
|
||||
* super mux parent using PLLP branches. To use PLLP branches to CPU, need
|
||||
* to configure additional bit PLLP_OUT_CPU in the clock registers.
|
||||
* TEGRA20_SUPER_CLK - Tegra20 doesn't have a dedicated divider for Super
|
||||
* clocks, it only has a clock-skipper.
|
||||
*/
|
||||
struct tegra_clk_super_mux {
|
||||
struct clk_hw hw;
|
||||
@ -748,6 +756,7 @@ struct tegra_clk_super_mux {
|
||||
|
||||
#define TEGRA_DIVIDER_2 BIT(0)
|
||||
#define TEGRA210_CPU_CLK BIT(1)
|
||||
#define TEGRA20_SUPER_CLK BIT(2)
|
||||
|
||||
extern const struct clk_ops tegra_clk_super_ops;
|
||||
struct clk *tegra_clk_register_super_mux(const char *name,
|
||||
@ -758,6 +767,12 @@ struct clk *tegra_clk_register_super_clk(const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||
spinlock_t *lock);
|
||||
struct clk *tegra_clk_register_super_cclk(const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||
spinlock_t *lock);
|
||||
int tegra_cclk_pre_pllx_rate_change(void);
|
||||
void tegra_cclk_post_pllx_rate_change(void);
|
||||
|
||||
/**
|
||||
* struct tegra_sdmmc_mux - switch divider with Low Jitter inputs for SDMMC
|
||||
@ -866,7 +881,7 @@ void tegra_super_clk_gen5_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *pll_params);
|
||||
|
||||
#ifdef CONFIG_TEGRA_CLK_EMC
|
||||
#ifdef CONFIG_TEGRA124_EMC
|
||||
struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
|
||||
spinlock_t *lock);
|
||||
#else
|
||||
@ -907,4 +922,7 @@ void tegra_clk_periph_resume(void);
|
||||
bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw);
|
||||
struct clk *tegra20_clk_register_emc(void __iomem *ioaddr, bool low_jitter);
|
||||
|
||||
struct clk *tegra210_clk_register_emc(struct device_node *np,
|
||||
void __iomem *regs);
|
||||
|
||||
#endif /* TEGRA_CLK_H */
|
||||
|
@ -606,13 +606,13 @@ static const struct omap_clkctrl_reg_data omap4_l4_per_clkctrl_regs[] __initcons
|
||||
|
||||
static const struct
|
||||
omap_clkctrl_reg_data omap4_l4_secure_clkctrl_regs[] __initconst = {
|
||||
{ OMAP4_AES1_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP4_AES2_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP4_DES3DES_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP4_PKA_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP4_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
|
||||
{ OMAP4_SHA2MD5_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP4_CRYPTODMA_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
|
||||
{ OMAP4_AES1_CLKCTRL, NULL, CLKF_SW_SUP, "l3_div_ck" },
|
||||
{ OMAP4_AES2_CLKCTRL, NULL, CLKF_SW_SUP, "l3_div_ck" },
|
||||
{ OMAP4_DES3DES_CLKCTRL, NULL, CLKF_SW_SUP, "l4_div_ck" },
|
||||
{ OMAP4_PKA_CLKCTRL, NULL, CLKF_SW_SUP, "l4_div_ck" },
|
||||
{ OMAP4_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l4_div_ck" },
|
||||
{ OMAP4_SHA2MD5_CLKCTRL, NULL, CLKF_SW_SUP, "l3_div_ck" },
|
||||
{ OMAP4_CRYPTODMA_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l3_div_ck" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
@ -303,13 +303,13 @@ static const struct omap_clkctrl_reg_data omap5_l4per_clkctrl_regs[] __initconst
|
||||
|
||||
static const struct
|
||||
omap_clkctrl_reg_data omap5_l4_secure_clkctrl_regs[] __initconst = {
|
||||
{ OMAP5_AES1_CLKCTRL, NULL, CLKF_HW_SUP, "" },
|
||||
{ OMAP5_AES2_CLKCTRL, NULL, CLKF_HW_SUP, "" },
|
||||
{ OMAP5_DES3DES_CLKCTRL, NULL, CLKF_HW_SUP, "" },
|
||||
{ OMAP5_FPKA_CLKCTRL, NULL, CLKF_SW_SUP, "" },
|
||||
{ OMAP5_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
|
||||
{ OMAP5_SHA2MD5_CLKCTRL, NULL, CLKF_HW_SUP, "" },
|
||||
{ OMAP5_DMA_CRYPTO_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
|
||||
{ OMAP5_AES1_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ OMAP5_AES2_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ OMAP5_DES3DES_CLKCTRL, NULL, CLKF_HW_SUP, "l4_root_clk_div" },
|
||||
{ OMAP5_FPKA_CLKCTRL, NULL, CLKF_SW_SUP, "l4_root_clk_div" },
|
||||
{ OMAP5_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l4_root_clk_div" },
|
||||
{ OMAP5_SHA2MD5_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ OMAP5_DMA_CRYPTO_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l3_iclk_div" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
@ -312,15 +312,6 @@ static const char * const dra7_gpu_hyd_mux_parents[] __initconst = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const char * const dra7_gpu_sys_clk_parents[] __initconst = {
|
||||
"sys_clkin",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct omap_clkctrl_div_data dra7_gpu_sys_clk_data __initconst = {
|
||||
.max_div = 2,
|
||||
};
|
||||
|
||||
static const struct omap_clkctrl_bit_data dra7_gpu_core_bit_data[] __initconst = {
|
||||
{ 24, TI_CLK_MUX, dra7_gpu_core_mux_parents, NULL, },
|
||||
{ 26, TI_CLK_MUX, dra7_gpu_hyd_mux_parents, NULL, },
|
||||
@ -328,7 +319,7 @@ static const struct omap_clkctrl_bit_data dra7_gpu_core_bit_data[] __initconst =
|
||||
};
|
||||
|
||||
static const struct omap_clkctrl_reg_data dra7_gpu_clkctrl_regs[] __initconst = {
|
||||
{ DRA7_GPU_CLKCTRL, dra7_gpu_core_bit_data, CLKF_SW_SUP, "gpu_cm:clk:0000:24", },
|
||||
{ DRA7_GPU_CLKCTRL, dra7_gpu_core_bit_data, CLKF_SW_SUP, "gpu-clkctrl:0000:24", },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
@ -644,7 +635,7 @@ static const struct omap_clkctrl_reg_data dra7_l4sec_clkctrl_regs[] __initconst
|
||||
{ DRA7_L4SEC_AES1_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ DRA7_L4SEC_AES2_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ DRA7_L4SEC_DES_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ DRA7_L4SEC_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
|
||||
{ DRA7_L4SEC_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l4_root_clk_div" },
|
||||
{ DRA7_L4SEC_SHAM_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
|
||||
{ 0 },
|
||||
};
|
||||
@ -815,7 +806,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
|
||||
{ DRA7_WKUPAON_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
|
||||
{ DRA7_WKUPAON_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon-clkctrl:0060:24" },
|
||||
{ DRA7_WKUPAON_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon-clkctrl:0068:24" },
|
||||
{ DRA7_WKUPAON_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk" },
|
||||
{ DRA7_WKUPAON_ADC_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_SOC_DRA76, "mcan_clk" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
@ -196,6 +196,7 @@ static void __init _register_composite(void *user,
|
||||
if (!cclk->comp_clks[i])
|
||||
continue;
|
||||
list_del(&cclk->comp_clks[i]->link);
|
||||
kfree(cclk->comp_clks[i]->parent_names);
|
||||
kfree(cclk->comp_clks[i]);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ struct clock_topology {
|
||||
u32 type;
|
||||
u32 flag;
|
||||
u32 type_flag;
|
||||
u8 custom_type_flag;
|
||||
};
|
||||
|
||||
struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
|
||||
|
@ -84,6 +84,7 @@ struct name_resp {
|
||||
|
||||
struct topology_resp {
|
||||
#define CLK_TOPOLOGY_TYPE GENMASK(3, 0)
|
||||
#define CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS GENMASK(7, 4)
|
||||
#define CLK_TOPOLOGY_FLAGS GENMASK(23, 8)
|
||||
#define CLK_TOPOLOGY_TYPE_FLAGS GENMASK(31, 24)
|
||||
u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS];
|
||||
@ -396,6 +397,9 @@ static int __zynqmp_clock_get_topology(struct clock_topology *topology,
|
||||
topology[*nnodes].type_flag =
|
||||
FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS,
|
||||
response->topology[i]);
|
||||
topology[*nnodes].custom_type_flag =
|
||||
FIELD_GET(CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS,
|
||||
response->topology[i]);
|
||||
(*nnodes)++;
|
||||
}
|
||||
|
||||
@ -558,7 +562,7 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
|
||||
{
|
||||
int j;
|
||||
u32 num_nodes, clk_dev_id;
|
||||
char *clk_out = NULL;
|
||||
char *clk_out[MAX_NODES];
|
||||
struct clock_topology *nodes;
|
||||
struct clk_hw *hw = NULL;
|
||||
|
||||
@ -572,16 +576,16 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
|
||||
* Intermediate clock names are postfixed with type of clock.
|
||||
*/
|
||||
if (j != (num_nodes - 1)) {
|
||||
clk_out = kasprintf(GFP_KERNEL, "%s%s", clk_name,
|
||||
clk_out[j] = kasprintf(GFP_KERNEL, "%s%s", clk_name,
|
||||
clk_type_postfix[nodes[j].type]);
|
||||
} else {
|
||||
clk_out = kasprintf(GFP_KERNEL, "%s", clk_name);
|
||||
clk_out[j] = kasprintf(GFP_KERNEL, "%s", clk_name);
|
||||
}
|
||||
|
||||
if (!clk_topology[nodes[j].type])
|
||||
continue;
|
||||
|
||||
hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id,
|
||||
hw = (*clk_topology[nodes[j].type])(clk_out[j], clk_dev_id,
|
||||
parent_names,
|
||||
num_parents,
|
||||
&nodes[j]);
|
||||
@ -590,9 +594,12 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
|
||||
__func__, clk_dev_id, clk_name,
|
||||
PTR_ERR(hw));
|
||||
|
||||
parent_names[0] = clk_out;
|
||||
parent_names[0] = clk_out[j];
|
||||
}
|
||||
kfree(clk_out);
|
||||
|
||||
for (j = 0; j < num_nodes; j++)
|
||||
kfree(clk_out[j]);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
@ -663,6 +670,11 @@ static void zynqmp_get_clock_info(void)
|
||||
continue;
|
||||
|
||||
clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]);
|
||||
/* skip query for Invalid clock */
|
||||
ret = zynqmp_is_valid_clock(i);
|
||||
if (ret != CLK_ATTR_VALID)
|
||||
continue;
|
||||
|
||||
clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ?
|
||||
CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;
|
||||
|
||||
|
@ -25,7 +25,8 @@
|
||||
#define to_zynqmp_clk_divider(_hw) \
|
||||
container_of(_hw, struct zynqmp_clk_divider, hw)
|
||||
|
||||
#define CLK_FRAC BIT(13) /* has a fractional parent */
|
||||
#define CLK_FRAC BIT(13) /* has a fractional parent */
|
||||
#define CUSTOM_FLAG_CLK_FRAC BIT(0) /* has a fractional parent in custom type flag */
|
||||
|
||||
/**
|
||||
* struct zynqmp_clk_divider - adjustable divider clock
|
||||
@ -111,23 +112,30 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
|
||||
|
||||
static void zynqmp_get_divider2_val(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate,
|
||||
struct zynqmp_clk_divider *divider,
|
||||
int *bestdiv)
|
||||
{
|
||||
int div1;
|
||||
int div2;
|
||||
long error = LONG_MAX;
|
||||
struct clk_hw *parent_hw = clk_hw_get_parent(hw);
|
||||
struct zynqmp_clk_divider *pdivider = to_zynqmp_clk_divider(parent_hw);
|
||||
unsigned long div1_prate;
|
||||
struct clk_hw *div1_parent_hw;
|
||||
struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw);
|
||||
struct zynqmp_clk_divider *pdivider =
|
||||
to_zynqmp_clk_divider(div2_parent_hw);
|
||||
|
||||
if (!pdivider)
|
||||
return;
|
||||
|
||||
div1_parent_hw = clk_hw_get_parent(div2_parent_hw);
|
||||
if (!div1_parent_hw)
|
||||
return;
|
||||
|
||||
div1_prate = clk_hw_get_rate(div1_parent_hw);
|
||||
*bestdiv = 1;
|
||||
for (div1 = 1; div1 <= pdivider->max_div;) {
|
||||
for (div2 = 1; div2 <= divider->max_div;) {
|
||||
long new_error = ((parent_rate / div1) / div2) - rate;
|
||||
long new_error = ((div1_prate / div1) / div2) - rate;
|
||||
|
||||
if (abs(new_error) < abs(error)) {
|
||||
*bestdiv = div2;
|
||||
@ -192,11 +200,13 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw,
|
||||
*/
|
||||
if (div_type == TYPE_DIV2 &&
|
||||
(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
|
||||
zynqmp_get_divider2_val(hw, rate, *prate, divider, &bestdiv);
|
||||
zynqmp_get_divider2_val(hw, rate, divider, &bestdiv);
|
||||
}
|
||||
|
||||
if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac)
|
||||
bestdiv = rate % *prate ? 1 : bestdiv;
|
||||
|
||||
bestdiv = min_t(u32, bestdiv, divider->max_div);
|
||||
*prate = rate * bestdiv;
|
||||
|
||||
return rate;
|
||||
@ -256,7 +266,7 @@ static const struct clk_ops zynqmp_clk_divider_ops = {
|
||||
* Return: Maximum divisor of a clock if query data is successful
|
||||
* U16_MAX in case of query data is not success
|
||||
*/
|
||||
u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
|
||||
static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
|
||||
{
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
struct zynqmp_pm_query_data qdata = {0};
|
||||
@ -311,7 +321,8 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name,
|
||||
init.num_parents = 1;
|
||||
|
||||
/* struct clk_divider assignments */
|
||||
div->is_frac = !!(nodes->flag & CLK_FRAC);
|
||||
div->is_frac = !!((nodes->flag & CLK_FRAC) |
|
||||
(nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC));
|
||||
div->flags = nodes->type_flag;
|
||||
div->hw.init = &init;
|
||||
div->clk_id = clk_id;
|
||||
|
70
include/dt-bindings/clock/agilex-clock.h
Normal file
70
include/dt-bindings/clock/agilex-clock.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2019, Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __AGILEX_CLOCK_H
|
||||
#define __AGILEX_CLOCK_H
|
||||
|
||||
/* fixed rate clocks */
|
||||
#define AGILEX_OSC1 0
|
||||
#define AGILEX_CB_INTOSC_HS_DIV2_CLK 1
|
||||
#define AGILEX_CB_INTOSC_LS_CLK 2
|
||||
#define AGILEX_L4_SYS_FREE_CLK 3
|
||||
#define AGILEX_F2S_FREE_CLK 4
|
||||
|
||||
/* PLL clocks */
|
||||
#define AGILEX_MAIN_PLL_CLK 5
|
||||
#define AGILEX_MAIN_PLL_C0_CLK 6
|
||||
#define AGILEX_MAIN_PLL_C1_CLK 7
|
||||
#define AGILEX_MAIN_PLL_C2_CLK 8
|
||||
#define AGILEX_MAIN_PLL_C3_CLK 9
|
||||
#define AGILEX_PERIPH_PLL_CLK 10
|
||||
#define AGILEX_PERIPH_PLL_C0_CLK 11
|
||||
#define AGILEX_PERIPH_PLL_C1_CLK 12
|
||||
#define AGILEX_PERIPH_PLL_C2_CLK 13
|
||||
#define AGILEX_PERIPH_PLL_C3_CLK 14
|
||||
#define AGILEX_MPU_FREE_CLK 15
|
||||
#define AGILEX_MPU_CCU_CLK 16
|
||||
#define AGILEX_BOOT_CLK 17
|
||||
|
||||
/* fixed factor clocks */
|
||||
#define AGILEX_L3_MAIN_FREE_CLK 18
|
||||
#define AGILEX_NOC_FREE_CLK 19
|
||||
#define AGILEX_S2F_USR0_CLK 20
|
||||
#define AGILEX_NOC_CLK 21
|
||||
#define AGILEX_EMAC_A_FREE_CLK 22
|
||||
#define AGILEX_EMAC_B_FREE_CLK 23
|
||||
#define AGILEX_EMAC_PTP_FREE_CLK 24
|
||||
#define AGILEX_GPIO_DB_FREE_CLK 25
|
||||
#define AGILEX_SDMMC_FREE_CLK 26
|
||||
#define AGILEX_S2F_USER0_FREE_CLK 27
|
||||
#define AGILEX_S2F_USER1_FREE_CLK 28
|
||||
#define AGILEX_PSI_REF_FREE_CLK 29
|
||||
|
||||
/* Gate clocks */
|
||||
#define AGILEX_MPU_CLK 30
|
||||
#define AGILEX_MPU_L2RAM_CLK 31
|
||||
#define AGILEX_MPU_PERIPH_CLK 32
|
||||
#define AGILEX_L4_MAIN_CLK 33
|
||||
#define AGILEX_L4_MP_CLK 34
|
||||
#define AGILEX_L4_SP_CLK 35
|
||||
#define AGILEX_CS_AT_CLK 36
|
||||
#define AGILEX_CS_TRACE_CLK 37
|
||||
#define AGILEX_CS_PDBG_CLK 38
|
||||
#define AGILEX_CS_TIMER_CLK 39
|
||||
#define AGILEX_S2F_USER0_CLK 40
|
||||
#define AGILEX_EMAC0_CLK 41
|
||||
#define AGILEX_EMAC1_CLK 43
|
||||
#define AGILEX_EMAC2_CLK 44
|
||||
#define AGILEX_EMAC_PTP_CLK 45
|
||||
#define AGILEX_GPIO_DB_CLK 46
|
||||
#define AGILEX_NAND_CLK 47
|
||||
#define AGILEX_PSI_REF_CLK 48
|
||||
#define AGILEX_S2F_USER1_CLK 49
|
||||
#define AGILEX_SDMMC_CLK 50
|
||||
#define AGILEX_SPI_M_CLK 51
|
||||
#define AGILEX_USB_CLK 52
|
||||
#define AGILEX_NUM_CLKS 53
|
||||
|
||||
#endif /* __AGILEX_CLOCK_H */
|
@ -12,6 +12,7 @@
|
||||
#define PMC_TYPE_SYSTEM 1
|
||||
#define PMC_TYPE_PERIPHERAL 2
|
||||
#define PMC_TYPE_GCK 3
|
||||
#define PMC_TYPE_PROGRAMMABLE 4
|
||||
|
||||
#define PMC_SLOW 0
|
||||
#define PMC_MCK 1
|
||||
@ -20,6 +21,9 @@
|
||||
#define PMC_MCK2 4
|
||||
#define PMC_I2S0_MUX 5
|
||||
#define PMC_I2S1_MUX 6
|
||||
#define PMC_PLLACK 7
|
||||
#define PMC_PLLBCK 8
|
||||
#define PMC_AUDIOPLLCK 9
|
||||
|
||||
#ifndef AT91_PMC_MOSCS
|
||||
#define AT91_PMC_MOSCS 0 /* MOSCS Flag */
|
||||
|
@ -58,7 +58,10 @@
|
||||
#define IMX7ULP_CLK_HSRUN_SYS_SEL 44
|
||||
#define IMX7ULP_CLK_HSRUN_CORE_DIV 45
|
||||
|
||||
#define IMX7ULP_CLK_SCG1_END 46
|
||||
#define IMX7ULP_CLK_CORE 46
|
||||
#define IMX7ULP_CLK_HSRUN_CORE 47
|
||||
|
||||
#define IMX7ULP_CLK_SCG1_END 48
|
||||
|
||||
/* PCC2 */
|
||||
#define IMX7ULP_CLK_DMA1 0
|
||||
|
@ -296,6 +296,94 @@
|
||||
#define IMX8MP_CLK_ARM 287
|
||||
#define IMX8MP_CLK_A53_CORE 288
|
||||
|
||||
#define IMX8MP_CLK_END 289
|
||||
#define IMX8MP_SYS_PLL1_40M_CG 289
|
||||
#define IMX8MP_SYS_PLL1_80M_CG 290
|
||||
#define IMX8MP_SYS_PLL1_100M_CG 291
|
||||
#define IMX8MP_SYS_PLL1_133M_CG 292
|
||||
#define IMX8MP_SYS_PLL1_160M_CG 293
|
||||
#define IMX8MP_SYS_PLL1_200M_CG 294
|
||||
#define IMX8MP_SYS_PLL1_266M_CG 295
|
||||
#define IMX8MP_SYS_PLL1_400M_CG 296
|
||||
#define IMX8MP_SYS_PLL2_50M_CG 297
|
||||
#define IMX8MP_SYS_PLL2_100M_CG 298
|
||||
#define IMX8MP_SYS_PLL2_125M_CG 299
|
||||
#define IMX8MP_SYS_PLL2_166M_CG 300
|
||||
#define IMX8MP_SYS_PLL2_200M_CG 301
|
||||
#define IMX8MP_SYS_PLL2_250M_CG 302
|
||||
#define IMX8MP_SYS_PLL2_333M_CG 303
|
||||
#define IMX8MP_SYS_PLL2_500M_CG 304
|
||||
|
||||
#define IMX8MP_CLK_M7_CORE 305
|
||||
#define IMX8MP_CLK_ML_CORE 306
|
||||
#define IMX8MP_CLK_GPU3D_CORE 307
|
||||
#define IMX8MP_CLK_GPU3D_SHADER_CORE 308
|
||||
#define IMX8MP_CLK_GPU2D_CORE 309
|
||||
#define IMX8MP_CLK_AUDIO_AXI 310
|
||||
#define IMX8MP_CLK_HSIO_AXI 311
|
||||
#define IMX8MP_CLK_MEDIA_ISP 312
|
||||
|
||||
#define IMX8MP_CLK_END 313
|
||||
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK2 2
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK3 3
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_IPG 4
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK1 5
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK2 6
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK3 7
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_IPG 8
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1 9
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_MCLK2 10
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_MCLK3 11
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_IPG 12
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1 13
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_MCLK2 14
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_MCLK3 15
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_IPG 16
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_MCLK1 17
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_MCLK2 18
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_MCLK3 19
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_IPG 20
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_MCLK1 21
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_MCLK2 22
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_MCLK3 23
|
||||
#define IMX8MP_CLK_AUDIOMIX_ASRC_IPG 24
|
||||
#define IMX8MP_CLK_AUDIOMIX_PDM_IPG 25
|
||||
#define IMX8MP_CLK_AUDIOMIX_SDMA2_ROOT 26
|
||||
#define IMX8MP_CLK_AUDIOMIX_SDMA3_ROOT 27
|
||||
#define IMX8MP_CLK_AUDIOMIX_SPBA2_ROOT 28
|
||||
#define IMX8MP_CLK_AUDIOMIX_DSP_ROOT 29
|
||||
#define IMX8MP_CLK_AUDIOMIX_DSPDBG_ROOT 30
|
||||
#define IMX8MP_CLK_AUDIOMIX_EARC_IPG 31
|
||||
#define IMX8MP_CLK_AUDIOMIX_OCRAMA_IPG 32
|
||||
#define IMX8MP_CLK_AUDIOMIX_AUD2HTX_IPG 33
|
||||
#define IMX8MP_CLK_AUDIOMIX_EDMA_ROOT 34
|
||||
#define IMX8MP_CLK_AUDIOMIX_AUDPLL_ROOT 35
|
||||
#define IMX8MP_CLK_AUDIOMIX_MU2_ROOT 36
|
||||
#define IMX8MP_CLK_AUDIOMIX_MU3_ROOT 37
|
||||
#define IMX8MP_CLK_AUDIOMIX_EARC_PHY 38
|
||||
#define IMX8MP_CLK_AUDIOMIX_PDM_ROOT 39
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1_SEL 40
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK2_SEL 41
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK1_SEL 42
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK2_SEL 43
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_MCLK1_SEL 44
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI3_MCLK2_SEL 45
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI4_MCLK1_SEL 46
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI4_MCLK2_SEL 47
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1_SEL 48
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI5_MCLK2_SEL 49
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_MCLK1_SEL 50
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI6_MCLK2_SEL 51
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_MCLK1_SEL 52
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI7_MCLK2_SEL 53
|
||||
#define IMX8MP_CLK_AUDIOMIX_PDM_SEL 54
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL 55
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI_PLL 56
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS 57
|
||||
#define IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT 58
|
||||
|
||||
#define IMX8MP_CLK_AUDIOMIX_END 59
|
||||
|
||||
#endif
|
||||
|
@ -351,14 +351,14 @@
|
||||
#define TEGRA210_CLK_PLL_P_OUT_XUSB 317
|
||||
#define TEGRA210_CLK_XUSB_SSP_SRC 318
|
||||
#define TEGRA210_CLK_PLL_RE_OUT1 319
|
||||
/* 320 */
|
||||
/* 321 */
|
||||
#define TEGRA210_CLK_PLL_MB_UD 320
|
||||
#define TEGRA210_CLK_PLL_P_UD 321
|
||||
#define TEGRA210_CLK_ISP 322
|
||||
#define TEGRA210_CLK_PLL_A_OUT_ADSP 323
|
||||
#define TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP 324
|
||||
/* 325 */
|
||||
#define TEGRA210_CLK_OSC 326
|
||||
/* 327 */
|
||||
#define TEGRA210_CLK_CSI_TPG 327
|
||||
/* 328 */
|
||||
/* 329 */
|
||||
/* 330 */
|
||||
|
@ -131,6 +131,9 @@ extern void tegra210_set_sata_pll_seq_sw(bool state);
|
||||
extern void tegra210_put_utmipll_in_iddq(void);
|
||||
extern void tegra210_put_utmipll_out_iddq(void);
|
||||
extern int tegra210_clk_handle_mbist_war(unsigned int id);
|
||||
extern void tegra210_clk_emc_dll_enable(bool flag);
|
||||
extern void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value);
|
||||
extern void tegra210_clk_emc_update_setting(u32 emc_src_value);
|
||||
|
||||
struct clk;
|
||||
|
||||
@ -143,4 +146,28 @@ void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
|
||||
void *cb_arg);
|
||||
int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same);
|
||||
|
||||
struct tegra210_clk_emc_config {
|
||||
unsigned long rate;
|
||||
bool same_freq;
|
||||
u32 value;
|
||||
|
||||
unsigned long parent_rate;
|
||||
u8 parent;
|
||||
};
|
||||
|
||||
struct tegra210_clk_emc_provider {
|
||||
struct module *owner;
|
||||
struct device *dev;
|
||||
|
||||
struct tegra210_clk_emc_config *configs;
|
||||
unsigned int num_configs;
|
||||
|
||||
int (*set_rate)(struct device *dev,
|
||||
const struct tegra210_clk_emc_config *config);
|
||||
};
|
||||
|
||||
int tegra210_clk_emc_attach(struct clk *clk,
|
||||
struct tegra210_clk_emc_provider *provider);
|
||||
void tegra210_clk_emc_detach(struct clk *clk);
|
||||
|
||||
#endif /* __LINUX_CLK_TEGRA_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user