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

Pull clk updates from Stephen Boyd:
 "This time around we have four lines of diff in the core framework,
  removing a function that isn't used anymore. Otherwise the main new
  thing for the common clk framework is that it is selectable in the
  Kconfig language now. Hopefully this will let clk drivers and clk
  consumers be testable on more than the architectures that support the
  clk framework. The goal is to introduce some Kunit tests for the
  framework.

  Outside of the core framework we have the usual set of various driver
  updates and non-critical fixes. The dirstat shows that the new
  Baikal-T1 driver is the largest addition this time around in terms of
  lines of code. After that the x86 (Intel), Qualcomm, and Mediatek
  drivers introduce many lines to support new or upcoming SoCs. After
  that the dirstat shows the usual suspects working on their SoC support
  by fixing minor bugs, correcting data and converting some of their DT
  bindings to YAML.

  Core:
   - Allow the COMMON_CLK config to be selectable

  New Drivers:
   - Clk driver for Baikal-T1 SoCs
   - Mediatek MT6765 clock support
   - Support for Intel Agilex clks
   - Add support for X1830 and X1000 Ingenic SoC clk controllers
   - Add support for the new Renesas RZ/G1H (R8A7742) SoC
   - Add support for Qualcomm's MSM8939 Generic Clock Controller

  Updates:
   - Support IDT VersaClock 5P49V5925
   - Bunch of updates for HSDK clock generation unit (CGU) driver
   - Start making audio and GPU clks work on Marvell MMP2/MMP3 SoCs
   - Add some GPU, NPU, and UFS clks to Qualcomm SM8150 driver
   - Enable supply regulators for GPU gdscs on Qualcomm SoCs
   - Add support for Si5342, Si5344 and Si5345 chips
   - Support custom flags in Xilinx zynq firmware
   - Various small fixes to the Xilinx clk driver
   - A single minor rounding fix for the legacy Allwinner clock support
   - A few patches from Abel Vesa as preparation of adding audiomix
     clock support on i.MX
   - A couple of cleanups from Anson Huang for i.MX clk-sscg-pll and
     clk-pllv3 drivers
   - Drop dependency on ARM64 for i.MX8M clock driver, to support
     aarch32 mode on aarch64 hardware
   - A series from Peng Fan to improve i.MX8M clock drivers, using
     composite clock for core and bus clk slice
   - Set a better parent clock for flexcan on i.MX6UL to support CiA102
     defined bit rates
   - A couple changes for EMC frequency scaling on Tegra210
   - Support for CPU frequency scaling on Tegra20/Tegra30
   - New clk gate for CSI test pattern generator on Tegra210
   - Regression fixes for Samsung exynos542x and exynos5433 SoCs
   - Use of fallthrough; attribute for Samsung s3c24xx
   - Updates and fixup HDMI and video clocks on Meson8b
   - Fixup reset polarity on Meson8b
   - Fix GPU glitch free mux switch on Meson gx and g12
   - A minor fix for the currently unused suspend/resume handling on
     Renesas RZ/A1 and RZ/A2
   - Two more conversions of Renesas DT bindings to json-schema
   - Add support for the USB 2.0 clock selector on Renesas R-Car M3-W+"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (155 commits)
  clk: mediatek: Remove ifr{0,1}_cfg_regs structures
  clk: baikal-t1: remove redundant assignment to variable 'divider'
  clk: baikal-t1: fix spelling mistake "Uncompatible" -> "Incompatible"
  dt-bindings: clock: Add a missing include to MMP Audio Clock binding
  dt: Add bindings for IDT VersaClock 5P49V5925
  clk: vc5: Add support for IDT VersaClock 5P49V6965
  clk: Add Baikal-T1 CCU Dividers driver
  clk: Add Baikal-T1 CCU PLLs driver
  dt-bindings: clk: Add Baikal-T1 CCU Dividers binding
  dt-bindings: clk: Add Baikal-T1 CCU PLLs binding
  clk: mediatek: assign the initial value to clk_init_data of mtk_mux
  clk: mediatek: Add MT6765 clock support
  clk: mediatek: add mt6765 clock IDs
  dt-bindings: clock: mediatek: document clk bindings vcodecsys for Mediatek MT6765 SoC
  dt-bindings: clock: mediatek: document clk bindings mipi0a for Mediatek MT6765 SoC
  dt-bindings: clock: mediatek: document clk bindings for Mediatek MT6765 SoC
  CLK: HSDK: CGU: add support for 148.5MHz clock
  CLK: HSDK: CGU: support PLL bypassing
  CLK: HSDK: CGU: check if PLL is bypassed first
  clk: clk-si5341: Add support for the Si5345 series
  ...
This commit is contained in:
Linus Torvalds
2020-06-10 11:42:19 -07:00
203 fájl változott, egészen pontosan 15224 új sor hozzáadva és 1241 régi sor törölve

Fájl megtekintése

@@ -1,5 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
config HAVE_CLK
bool
help
The <linux/clk.h> calls support software clock gating and
thus are a key power management tool on many systems.
config CLKDEV_LOOKUP
bool
select HAVE_CLK
@@ -7,8 +13,18 @@ config CLKDEV_LOOKUP
config HAVE_CLK_PREPARE
bool
config COMMON_CLK
config HAVE_LEGACY_CLK # TODO: Remove once all legacy users are migrated
bool
select HAVE_CLK
help
Select this option when the clock API in <linux/clk.h> is implemented
by platform/architecture code. This method is deprecated. Modern
code should select COMMON_CLK instead and not define a custom
'struct clk'.
menuconfig COMMON_CLK
bool "Common Clock Framework"
depends on !HAVE_LEGACY_CLK
select HAVE_CLK_PREPARE
select CLKDEV_LOOKUP
select SRCU
@@ -20,8 +36,7 @@ config COMMON_CLK
Architectures utilizing the common struct clk should select
this option.
menu "Common Clock Framework"
depends on COMMON_CLK
if COMMON_CLK
config COMMON_CLK_WM831X
tristate "Clock driver for WM831x/2x PMICs"
@@ -252,7 +267,7 @@ config COMMON_CLK_XGENE
default ARCH_XGENE
depends on ARM64 || COMPILE_TEST
---help---
Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
Support for the APM X-Gene SoC reference, PLL, and device clocks.
config COMMON_CLK_LOCHNAGAR
tristate "Cirrus Logic Lochnagar clock driver"
@@ -326,6 +341,12 @@ config COMMON_CLK_MMP2
help
Support for Marvell MMP2 and MMP3 SoC clocks
config COMMON_CLK_MMP2_AUDIO
tristate "Clock driver for MMP2 Audio subsystem"
depends on COMMON_CLK_MMP2 || COMPILE_TEST
help
This driver supports clocks for Audio subsystem on MMP2 SoC.
config COMMON_CLK_BD718XX
tristate "Clock driver for 32K clk gates on ROHM PMICs"
depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828
@@ -341,6 +362,7 @@ config COMMON_CLK_FIXED_MMIO
source "drivers/clk/actions/Kconfig"
source "drivers/clk/analogbits/Kconfig"
source "drivers/clk/baikal-t1/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
@@ -360,6 +382,7 @@ source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
source "drivers/clk/uniphier/Kconfig"
source "drivers/clk/x86/Kconfig"
source "drivers/clk/zynqmp/Kconfig"
endmenu
endif

Fájl megtekintése

@@ -75,6 +75,7 @@ obj-y += analogbits/
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_ARTPEC) += axis/
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
obj-$(CONFIG_CLK_BAIKAL_T1) += baikal-t1/
obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
@@ -104,10 +105,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-y += 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/

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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)

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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)

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0-only
config CLK_BAIKAL_T1
bool "Baikal-T1 Clocks Control Unit interface"
depends on (MIPS_BAIKAL_T1 && OF) || COMPILE_TEST
default MIPS_BAIKAL_T1
help
Clocks Control Unit is the core of Baikal-T1 SoC System Controller
responsible for the chip subsystems clocking and resetting. It
consists of multiple global clock domains, which can be reset by
means of the CCU control registers. These domains and devices placed
in them are fed with clocks generated by a hierarchy of PLLs,
configurable and fixed clock dividers. Enable this option to be able
to select Baikal-T1 CCU PLLs and Dividers drivers.
if CLK_BAIKAL_T1
config CLK_BT1_CCU_PLL
bool "Baikal-T1 CCU PLLs support"
select MFD_SYSCON
default MIPS_BAIKAL_T1
help
Enable this to support the PLLs embedded into the Baikal-T1 SoC
System Controller. These are five PLLs placed at the root of the
clocks hierarchy, right after an external reference oscillator
(normally of 25MHz). They are used to generate high frequency
signals, which are either directly wired to the consumers (like
CPUs, DDR, etc.) or passed over the clock dividers to be only
then used as an individual reference clock of a target device.
config CLK_BT1_CCU_DIV
bool "Baikal-T1 CCU Dividers support"
select RESET_CONTROLLER
select MFD_SYSCON
default MIPS_BAIKAL_T1
help
Enable this to support the CCU dividers used to distribute clocks
between AXI-bus and system devices coming from CCU PLLs of Baikal-T1
SoC. CCU dividers can be either configurable or with fixed divider,
either gateable or ungateable. Some of the CCU dividers can be as well
used to reset the domains they're supplying clock to.
endif

Fájl megtekintése

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CLK_BT1_CCU_PLL) += ccu-pll.o clk-ccu-pll.o
obj-$(CONFIG_CLK_BT1_CCU_DIV) += ccu-div.o clk-ccu-div.o

Fájl megtekintése

@@ -0,0 +1,602 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Authors:
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
* Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
*
* Baikal-T1 CCU Dividers interface driver
*/
#define pr_fmt(fmt) "bt1-ccu-div: " fmt
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/time64.h>
#include <linux/debugfs.h>
#include "ccu-div.h"
#define CCU_DIV_CTL 0x00
#define CCU_DIV_CTL_EN BIT(0)
#define CCU_DIV_CTL_RST BIT(1)
#define CCU_DIV_CTL_SET_CLKDIV BIT(2)
#define CCU_DIV_CTL_CLKDIV_FLD 4
#define CCU_DIV_CTL_CLKDIV_MASK(_width) \
GENMASK((_width) + CCU_DIV_CTL_CLKDIV_FLD - 1, CCU_DIV_CTL_CLKDIV_FLD)
#define CCU_DIV_CTL_LOCK_SHIFTED BIT(27)
#define CCU_DIV_CTL_LOCK_NORMAL BIT(31)
#define CCU_DIV_RST_DELAY_US 1
#define CCU_DIV_LOCK_CHECK_RETRIES 50
#define CCU_DIV_CLKDIV_MIN 0
#define CCU_DIV_CLKDIV_MAX(_mask) \
((_mask) >> CCU_DIV_CTL_CLKDIV_FLD)
/*
* Use the next two methods until there are generic field setter and
* getter available with non-constant mask support.
*/
static inline u32 ccu_div_get(u32 mask, u32 val)
{
return (val & mask) >> CCU_DIV_CTL_CLKDIV_FLD;
}
static inline u32 ccu_div_prep(u32 mask, u32 val)
{
return (val << CCU_DIV_CTL_CLKDIV_FLD) & mask;
}
static inline unsigned long ccu_div_lock_delay_ns(unsigned long ref_clk,
unsigned long div)
{
u64 ns = 4ULL * (div ?: 1) * NSEC_PER_SEC;
do_div(ns, ref_clk);
return ns;
}
static inline unsigned long ccu_div_calc_freq(unsigned long ref_clk,
unsigned long div)
{
return ref_clk / (div ?: 1);
}
static int ccu_div_var_update_clkdiv(struct ccu_div *div,
unsigned long parent_rate,
unsigned long divider)
{
unsigned long nd;
u32 val = 0;
u32 lock;
int count;
nd = ccu_div_lock_delay_ns(parent_rate, divider);
if (div->features & CCU_DIV_LOCK_SHIFTED)
lock = CCU_DIV_CTL_LOCK_SHIFTED;
else
lock = CCU_DIV_CTL_LOCK_NORMAL;
regmap_update_bits(div->sys_regs, div->reg_ctl,
CCU_DIV_CTL_SET_CLKDIV, CCU_DIV_CTL_SET_CLKDIV);
/*
* Until there is nsec-version of readl_poll_timeout() is available
* we have to implement the next polling loop.
*/
count = CCU_DIV_LOCK_CHECK_RETRIES;
do {
ndelay(nd);
regmap_read(div->sys_regs, div->reg_ctl, &val);
if (val & lock)
return 0;
} while (--count);
return -ETIMEDOUT;
}
static int ccu_div_var_enable(struct clk_hw *hw)
{
struct clk_hw *parent_hw = clk_hw_get_parent(hw);
struct ccu_div *div = to_ccu_div(hw);
unsigned long flags;
u32 val = 0;
int ret;
if (!parent_hw) {
pr_err("Can't enable '%s' with no parent", clk_hw_get_name(hw));
return -EINVAL;
}
regmap_read(div->sys_regs, div->reg_ctl, &val);
if (val & CCU_DIV_CTL_EN)
return 0;
spin_lock_irqsave(&div->lock, flags);
ret = ccu_div_var_update_clkdiv(div, clk_hw_get_rate(parent_hw),
ccu_div_get(div->mask, val));
if (!ret)
regmap_update_bits(div->sys_regs, div->reg_ctl,
CCU_DIV_CTL_EN, CCU_DIV_CTL_EN);
spin_unlock_irqrestore(&div->lock, flags);
if (ret)
pr_err("Divider '%s' lock timed out\n", clk_hw_get_name(hw));
return ret;
}
static int ccu_div_gate_enable(struct clk_hw *hw)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long flags;
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl,
CCU_DIV_CTL_EN, CCU_DIV_CTL_EN);
spin_unlock_irqrestore(&div->lock, flags);
return 0;
}
static void ccu_div_gate_disable(struct clk_hw *hw)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long flags;
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl, CCU_DIV_CTL_EN, 0);
spin_unlock_irqrestore(&div->lock, flags);
}
static int ccu_div_gate_is_enabled(struct clk_hw *hw)
{
struct ccu_div *div = to_ccu_div(hw);
u32 val = 0;
regmap_read(div->sys_regs, div->reg_ctl, &val);
return !!(val & CCU_DIV_CTL_EN);
}
static unsigned long ccu_div_var_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long divider;
u32 val = 0;
regmap_read(div->sys_regs, div->reg_ctl, &val);
divider = ccu_div_get(div->mask, val);
return ccu_div_calc_freq(parent_rate, divider);
}
static inline unsigned long ccu_div_var_calc_divider(unsigned long rate,
unsigned long parent_rate,
unsigned int mask)
{
unsigned long divider;
divider = parent_rate / rate;
return clamp_t(unsigned long, divider, CCU_DIV_CLKDIV_MIN,
CCU_DIV_CLKDIV_MAX(mask));
}
static long ccu_div_var_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long divider;
divider = ccu_div_var_calc_divider(rate, *parent_rate, div->mask);
return ccu_div_calc_freq(*parent_rate, divider);
}
/*
* This method is used for the clock divider blocks, which support the
* on-the-fly rate change. So due to lacking the EN bit functionality
* they can't be gated before the rate adjustment.
*/
static int ccu_div_var_set_rate_slow(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long flags, divider;
u32 val;
int ret;
divider = ccu_div_var_calc_divider(rate, parent_rate, div->mask);
if (divider == 1 && div->features & CCU_DIV_SKIP_ONE) {
divider = 0;
} else if (div->features & CCU_DIV_SKIP_ONE_TO_THREE) {
if (divider == 1 || divider == 2)
divider = 0;
else if (divider == 3)
divider = 4;
}
val = ccu_div_prep(div->mask, divider);
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl, div->mask, val);
ret = ccu_div_var_update_clkdiv(div, parent_rate, divider);
spin_unlock_irqrestore(&div->lock, flags);
if (ret)
pr_err("Divider '%s' lock timed out\n", clk_hw_get_name(hw));
return ret;
}
/*
* This method is used for the clock divider blocks, which don't support
* the on-the-fly rate change.
*/
static int ccu_div_var_set_rate_fast(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long flags, divider;
u32 val;
divider = ccu_div_var_calc_divider(rate, parent_rate, div->mask);
val = ccu_div_prep(div->mask, divider);
/*
* Also disable the clock divider block if it was enabled by default
* or by the bootloader.
*/
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl,
div->mask | CCU_DIV_CTL_EN, val);
spin_unlock_irqrestore(&div->lock, flags);
return 0;
}
static unsigned long ccu_div_fixed_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
return ccu_div_calc_freq(parent_rate, div->divider);
}
static long ccu_div_fixed_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct ccu_div *div = to_ccu_div(hw);
return ccu_div_calc_freq(*parent_rate, div->divider);
}
static int ccu_div_fixed_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return 0;
}
int ccu_div_reset_domain(struct ccu_div *div)
{
unsigned long flags;
if (!div || !(div->features & CCU_DIV_RESET_DOMAIN))
return -EINVAL;
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl,
CCU_DIV_CTL_RST, CCU_DIV_CTL_RST);
spin_unlock_irqrestore(&div->lock, flags);
/* The next delay must be enough to cover all the resets. */
udelay(CCU_DIV_RST_DELAY_US);
return 0;
}
#ifdef CONFIG_DEBUG_FS
struct ccu_div_dbgfs_bit {
struct ccu_div *div;
const char *name;
u32 mask;
};
#define CCU_DIV_DBGFS_BIT_ATTR(_name, _mask) { \
.name = _name, \
.mask = _mask \
}
static const struct ccu_div_dbgfs_bit ccu_div_bits[] = {
CCU_DIV_DBGFS_BIT_ATTR("div_en", CCU_DIV_CTL_EN),
CCU_DIV_DBGFS_BIT_ATTR("div_rst", CCU_DIV_CTL_RST),
CCU_DIV_DBGFS_BIT_ATTR("div_bypass", CCU_DIV_CTL_SET_CLKDIV),
CCU_DIV_DBGFS_BIT_ATTR("div_lock", CCU_DIV_CTL_LOCK_NORMAL)
};
#define CCU_DIV_DBGFS_BIT_NUM ARRAY_SIZE(ccu_div_bits)
/*
* It can be dangerous to change the Divider settings behind clock framework
* back, therefore we don't provide any kernel config based compile time option
* for this feature to enable.
*/
#undef CCU_DIV_ALLOW_WRITE_DEBUGFS
#ifdef CCU_DIV_ALLOW_WRITE_DEBUGFS
static int ccu_div_dbgfs_bit_set(void *priv, u64 val)
{
const struct ccu_div_dbgfs_bit *bit = priv;
struct ccu_div *div = bit->div;
unsigned long flags;
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl,
bit->mask, val ? bit->mask : 0);
spin_unlock_irqrestore(&div->lock, flags);
return 0;
}
static int ccu_div_dbgfs_var_clkdiv_set(void *priv, u64 val)
{
struct ccu_div *div = priv;
unsigned long flags;
u32 data;
val = clamp_t(u64, val, CCU_DIV_CLKDIV_MIN,
CCU_DIV_CLKDIV_MAX(div->mask));
data = ccu_div_prep(div->mask, val);
spin_lock_irqsave(&div->lock, flags);
regmap_update_bits(div->sys_regs, div->reg_ctl, div->mask, data);
spin_unlock_irqrestore(&div->lock, flags);
return 0;
}
#define ccu_div_dbgfs_mode 0644
#else /* !CCU_DIV_ALLOW_WRITE_DEBUGFS */
#define ccu_div_dbgfs_bit_set NULL
#define ccu_div_dbgfs_var_clkdiv_set NULL
#define ccu_div_dbgfs_mode 0444
#endif /* !CCU_DIV_ALLOW_WRITE_DEBUGFS */
static int ccu_div_dbgfs_bit_get(void *priv, u64 *val)
{
const struct ccu_div_dbgfs_bit *bit = priv;
struct ccu_div *div = bit->div;
u32 data = 0;
regmap_read(div->sys_regs, div->reg_ctl, &data);
*val = !!(data & bit->mask);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(ccu_div_dbgfs_bit_fops,
ccu_div_dbgfs_bit_get, ccu_div_dbgfs_bit_set, "%llu\n");
static int ccu_div_dbgfs_var_clkdiv_get(void *priv, u64 *val)
{
struct ccu_div *div = priv;
u32 data = 0;
regmap_read(div->sys_regs, div->reg_ctl, &data);
*val = ccu_div_get(div->mask, data);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(ccu_div_dbgfs_var_clkdiv_fops,
ccu_div_dbgfs_var_clkdiv_get, ccu_div_dbgfs_var_clkdiv_set, "%llu\n");
static int ccu_div_dbgfs_fixed_clkdiv_get(void *priv, u64 *val)
{
struct ccu_div *div = priv;
*val = div->divider;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(ccu_div_dbgfs_fixed_clkdiv_fops,
ccu_div_dbgfs_fixed_clkdiv_get, NULL, "%llu\n");
static void ccu_div_var_debug_init(struct clk_hw *hw, struct dentry *dentry)
{
struct ccu_div *div = to_ccu_div(hw);
struct ccu_div_dbgfs_bit *bits;
int didx, bidx, num = 2;
const char *name;
num += !!(div->flags & CLK_SET_RATE_GATE) +
!!(div->features & CCU_DIV_RESET_DOMAIN);
bits = kcalloc(num, sizeof(*bits), GFP_KERNEL);
if (!bits)
return;
for (didx = 0, bidx = 0; bidx < CCU_DIV_DBGFS_BIT_NUM; ++bidx) {
name = ccu_div_bits[bidx].name;
if (!(div->flags & CLK_SET_RATE_GATE) &&
!strcmp("div_en", name)) {
continue;
}
if (!(div->features & CCU_DIV_RESET_DOMAIN) &&
!strcmp("div_rst", name)) {
continue;
}
bits[didx] = ccu_div_bits[bidx];
bits[didx].div = div;
if (div->features & CCU_DIV_LOCK_SHIFTED &&
!strcmp("div_lock", name)) {
bits[didx].mask = CCU_DIV_CTL_LOCK_SHIFTED;
}
debugfs_create_file_unsafe(bits[didx].name, ccu_div_dbgfs_mode,
dentry, &bits[didx],
&ccu_div_dbgfs_bit_fops);
++didx;
}
debugfs_create_file_unsafe("div_clkdiv", ccu_div_dbgfs_mode, dentry,
div, &ccu_div_dbgfs_var_clkdiv_fops);
}
static void ccu_div_gate_debug_init(struct clk_hw *hw, struct dentry *dentry)
{
struct ccu_div *div = to_ccu_div(hw);
struct ccu_div_dbgfs_bit *bit;
bit = kmalloc(sizeof(*bit), GFP_KERNEL);
if (!bit)
return;
*bit = ccu_div_bits[0];
bit->div = div;
debugfs_create_file_unsafe(bit->name, ccu_div_dbgfs_mode, dentry, bit,
&ccu_div_dbgfs_bit_fops);
debugfs_create_file_unsafe("div_clkdiv", 0400, dentry, div,
&ccu_div_dbgfs_fixed_clkdiv_fops);
}
static void ccu_div_fixed_debug_init(struct clk_hw *hw, struct dentry *dentry)
{
struct ccu_div *div = to_ccu_div(hw);
debugfs_create_file_unsafe("div_clkdiv", 0400, dentry, div,
&ccu_div_dbgfs_fixed_clkdiv_fops);
}
#else /* !CONFIG_DEBUG_FS */
#define ccu_div_var_debug_init NULL
#define ccu_div_gate_debug_init NULL
#define ccu_div_fixed_debug_init NULL
#endif /* !CONFIG_DEBUG_FS */
static const struct clk_ops ccu_div_var_gate_to_set_ops = {
.enable = ccu_div_var_enable,
.disable = ccu_div_gate_disable,
.is_enabled = ccu_div_gate_is_enabled,
.recalc_rate = ccu_div_var_recalc_rate,
.round_rate = ccu_div_var_round_rate,
.set_rate = ccu_div_var_set_rate_fast,
.debug_init = ccu_div_var_debug_init
};
static const struct clk_ops ccu_div_var_nogate_ops = {
.recalc_rate = ccu_div_var_recalc_rate,
.round_rate = ccu_div_var_round_rate,
.set_rate = ccu_div_var_set_rate_slow,
.debug_init = ccu_div_var_debug_init
};
static const struct clk_ops ccu_div_gate_ops = {
.enable = ccu_div_gate_enable,
.disable = ccu_div_gate_disable,
.is_enabled = ccu_div_gate_is_enabled,
.recalc_rate = ccu_div_fixed_recalc_rate,
.round_rate = ccu_div_fixed_round_rate,
.set_rate = ccu_div_fixed_set_rate,
.debug_init = ccu_div_gate_debug_init
};
static const struct clk_ops ccu_div_fixed_ops = {
.recalc_rate = ccu_div_fixed_recalc_rate,
.round_rate = ccu_div_fixed_round_rate,
.set_rate = ccu_div_fixed_set_rate,
.debug_init = ccu_div_fixed_debug_init
};
struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *div_init)
{
struct clk_parent_data parent_data = { };
struct clk_init_data hw_init = { };
struct ccu_div *div;
int ret;
if (!div_init)
return ERR_PTR(-EINVAL);
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
/*
* Note since Baikal-T1 System Controller registers are MMIO-backed
* we won't check the regmap IO operations return status, because it
* must be zero anyway.
*/
div->hw.init = &hw_init;
div->id = div_init->id;
div->reg_ctl = div_init->base + CCU_DIV_CTL;
div->sys_regs = div_init->sys_regs;
div->flags = div_init->flags;
div->features = div_init->features;
spin_lock_init(&div->lock);
hw_init.name = div_init->name;
hw_init.flags = div_init->flags;
if (div_init->type == CCU_DIV_VAR) {
if (hw_init.flags & CLK_SET_RATE_GATE)
hw_init.ops = &ccu_div_var_gate_to_set_ops;
else
hw_init.ops = &ccu_div_var_nogate_ops;
div->mask = CCU_DIV_CTL_CLKDIV_MASK(div_init->width);
} else if (div_init->type == CCU_DIV_GATE) {
hw_init.ops = &ccu_div_gate_ops;
div->divider = div_init->divider;
} else if (div_init->type == CCU_DIV_FIXED) {
hw_init.ops = &ccu_div_fixed_ops;
div->divider = div_init->divider;
} else {
ret = -EINVAL;
goto err_free_div;
}
if (!div_init->parent_name) {
ret = -EINVAL;
goto err_free_div;
}
parent_data.fw_name = div_init->parent_name;
hw_init.parent_data = &parent_data;
hw_init.num_parents = 1;
ret = of_clk_hw_register(div_init->np, &div->hw);
if (ret)
goto err_free_div;
return div;
err_free_div:
kfree(div);
return ERR_PTR(ret);
}
void ccu_div_hw_unregister(struct ccu_div *div)
{
clk_hw_unregister(&div->hw);
kfree(div);
}

Fájl megtekintése

@@ -0,0 +1,110 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Baikal-T1 CCU Dividers interface driver
*/
#ifndef __CLK_BT1_CCU_DIV_H__
#define __CLK_BT1_CCU_DIV_H__
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/bits.h>
#include <linux/of.h>
/*
* CCU Divider private flags
* @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1.
* It can be 0 though, which is functionally the same.
* @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3].
* It can be either 0 or greater than 3.
* @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position.
* @CCU_DIV_RESET_DOMAIN: Provide reset clock domain method.
*/
#define CCU_DIV_SKIP_ONE BIT(1)
#define CCU_DIV_SKIP_ONE_TO_THREE BIT(2)
#define CCU_DIV_LOCK_SHIFTED BIT(3)
#define CCU_DIV_RESET_DOMAIN BIT(4)
/*
* enum ccu_div_type - CCU Divider types
* @CCU_DIV_VAR: Clocks gate with variable divider.
* @CCU_DIV_GATE: Clocks gate with fixed divider.
* @CCU_DIV_FIXED: Ungateable clock with fixed divider.
*/
enum ccu_div_type {
CCU_DIV_VAR,
CCU_DIV_GATE,
CCU_DIV_FIXED
};
/*
* struct ccu_div_init_data - CCU Divider initialization data
* @id: Clocks private identifier.
* @name: Clocks name.
* @parent_name: Parent clocks name in a fw node.
* @base: Divider register base address with respect to the sys_regs base.
* @sys_regs: Baikal-T1 System Controller registers map.
* @np: Pointer to the node describing the CCU Dividers.
* @type: CCU divider type (variable, fixed with and without gate).
* @width: Divider width if it's variable.
* @divider: Divider fixed value.
* @flags: CCU Divider clock flags.
* @features: CCU Divider private features.
*/
struct ccu_div_init_data {
unsigned int id;
const char *name;
const char *parent_name;
unsigned int base;
struct regmap *sys_regs;
struct device_node *np;
enum ccu_div_type type;
union {
unsigned int width;
unsigned int divider;
};
unsigned long flags;
unsigned long features;
};
/*
* struct ccu_div - CCU Divider descriptor
* @hw: clk_hw of the divider.
* @id: Clock private identifier.
* @reg_ctl: Divider control register base address.
* @sys_regs: Baikal-T1 System Controller registers map.
* @lock: Divider state change spin-lock.
* @mask: Divider field mask.
* @divider: Divider fixed value.
* @flags: Divider clock flags.
* @features: CCU Divider private features.
*/
struct ccu_div {
struct clk_hw hw;
unsigned int id;
unsigned int reg_ctl;
struct regmap *sys_regs;
spinlock_t lock;
union {
u32 mask;
unsigned int divider;
};
unsigned long flags;
unsigned long features;
};
#define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw)
static inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)
{
return div ? &div->hw : NULL;
}
struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);
void ccu_div_hw_unregister(struct ccu_div *div);
int ccu_div_reset_domain(struct ccu_div *div);
#endif /* __CLK_BT1_CCU_DIV_H__ */

Fájl megtekintése

@@ -0,0 +1,558 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Authors:
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
* Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
*
* Baikal-T1 CCU PLL interface driver
*/
#define pr_fmt(fmt) "bt1-ccu-pll: " fmt
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/limits.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/iopoll.h>
#include <linux/time64.h>
#include <linux/rational.h>
#include <linux/debugfs.h>
#include "ccu-pll.h"
#define CCU_PLL_CTL 0x000
#define CCU_PLL_CTL_EN BIT(0)
#define CCU_PLL_CTL_RST BIT(1)
#define CCU_PLL_CTL_CLKR_FLD 2
#define CCU_PLL_CTL_CLKR_MASK GENMASK(7, CCU_PLL_CTL_CLKR_FLD)
#define CCU_PLL_CTL_CLKF_FLD 8
#define CCU_PLL_CTL_CLKF_MASK GENMASK(20, CCU_PLL_CTL_CLKF_FLD)
#define CCU_PLL_CTL_CLKOD_FLD 21
#define CCU_PLL_CTL_CLKOD_MASK GENMASK(24, CCU_PLL_CTL_CLKOD_FLD)
#define CCU_PLL_CTL_BYPASS BIT(30)
#define CCU_PLL_CTL_LOCK BIT(31)
#define CCU_PLL_CTL1 0x004
#define CCU_PLL_CTL1_BWADJ_FLD 3
#define CCU_PLL_CTL1_BWADJ_MASK GENMASK(14, CCU_PLL_CTL1_BWADJ_FLD)
#define CCU_PLL_LOCK_CHECK_RETRIES 50
#define CCU_PLL_NR_MAX \
((CCU_PLL_CTL_CLKR_MASK >> CCU_PLL_CTL_CLKR_FLD) + 1)
#define CCU_PLL_NF_MAX \
((CCU_PLL_CTL_CLKF_MASK >> (CCU_PLL_CTL_CLKF_FLD + 1)) + 1)
#define CCU_PLL_OD_MAX \
((CCU_PLL_CTL_CLKOD_MASK >> CCU_PLL_CTL_CLKOD_FLD) + 1)
#define CCU_PLL_NB_MAX \
((CCU_PLL_CTL1_BWADJ_MASK >> CCU_PLL_CTL1_BWADJ_FLD) + 1)
#define CCU_PLL_FDIV_MIN 427000UL
#define CCU_PLL_FDIV_MAX 3500000000UL
#define CCU_PLL_FOUT_MIN 200000000UL
#define CCU_PLL_FOUT_MAX 2500000000UL
#define CCU_PLL_FVCO_MIN 700000000UL
#define CCU_PLL_FVCO_MAX 3500000000UL
#define CCU_PLL_CLKOD_FACTOR 2
static inline unsigned long ccu_pll_lock_delay_us(unsigned long ref_clk,
unsigned long nr)
{
u64 us = 500ULL * nr * USEC_PER_SEC;
do_div(us, ref_clk);
return us;
}
static inline unsigned long ccu_pll_calc_freq(unsigned long ref_clk,
unsigned long nr,
unsigned long nf,
unsigned long od)
{
u64 tmp = ref_clk;
do_div(tmp, nr);
tmp *= nf;
do_div(tmp, od);
return tmp;
}
static int ccu_pll_reset(struct ccu_pll *pll, unsigned long ref_clk,
unsigned long nr)
{
unsigned long ud, ut;
u32 val;
ud = ccu_pll_lock_delay_us(ref_clk, nr);
ut = ud * CCU_PLL_LOCK_CHECK_RETRIES;
regmap_update_bits(pll->sys_regs, pll->reg_ctl,
CCU_PLL_CTL_RST, CCU_PLL_CTL_RST);
return regmap_read_poll_timeout_atomic(pll->sys_regs, pll->reg_ctl, val,
val & CCU_PLL_CTL_LOCK, ud, ut);
}
static int ccu_pll_enable(struct clk_hw *hw)
{
struct clk_hw *parent_hw = clk_hw_get_parent(hw);
struct ccu_pll *pll = to_ccu_pll(hw);
unsigned long flags;
u32 val = 0;
int ret;
if (!parent_hw) {
pr_err("Can't enable '%s' with no parent", clk_hw_get_name(hw));
return -EINVAL;
}
regmap_read(pll->sys_regs, pll->reg_ctl, &val);
if (val & CCU_PLL_CTL_EN)
return 0;
spin_lock_irqsave(&pll->lock, flags);
regmap_write(pll->sys_regs, pll->reg_ctl, val | CCU_PLL_CTL_EN);
ret = ccu_pll_reset(pll, clk_hw_get_rate(parent_hw),
FIELD_GET(CCU_PLL_CTL_CLKR_MASK, val) + 1);
spin_unlock_irqrestore(&pll->lock, flags);
if (ret)
pr_err("PLL '%s' reset timed out\n", clk_hw_get_name(hw));
return ret;
}
static void ccu_pll_disable(struct clk_hw *hw)
{
struct ccu_pll *pll = to_ccu_pll(hw);
unsigned long flags;
spin_lock_irqsave(&pll->lock, flags);
regmap_update_bits(pll->sys_regs, pll->reg_ctl, CCU_PLL_CTL_EN, 0);
spin_unlock_irqrestore(&pll->lock, flags);
}
static int ccu_pll_is_enabled(struct clk_hw *hw)
{
struct ccu_pll *pll = to_ccu_pll(hw);
u32 val = 0;
regmap_read(pll->sys_regs, pll->reg_ctl, &val);
return !!(val & CCU_PLL_CTL_EN);
}
static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_pll *pll = to_ccu_pll(hw);
unsigned long nr, nf, od;
u32 val = 0;
regmap_read(pll->sys_regs, pll->reg_ctl, &val);
nr = FIELD_GET(CCU_PLL_CTL_CLKR_MASK, val) + 1;
nf = FIELD_GET(CCU_PLL_CTL_CLKF_MASK, val) + 1;
od = FIELD_GET(CCU_PLL_CTL_CLKOD_MASK, val) + 1;
return ccu_pll_calc_freq(parent_rate, nr, nf, od);
}
static void ccu_pll_calc_factors(unsigned long rate, unsigned long parent_rate,
unsigned long *nr, unsigned long *nf,
unsigned long *od)
{
unsigned long err, freq, min_err = ULONG_MAX;
unsigned long num, denom, n1, d1, nri;
unsigned long nr_max, nf_max, od_max;
/*
* Make sure PLL is working with valid input signal (Fdiv). If
* you want to speed the function up just reduce CCU_PLL_NR_MAX.
* This will cause a worse approximation though.
*/
nri = (parent_rate / CCU_PLL_FDIV_MAX) + 1;
nr_max = min(parent_rate / CCU_PLL_FDIV_MIN, CCU_PLL_NR_MAX);
/*
* Find a closest [nr;nf;od] vector taking into account the
* limitations like: 1) 700MHz <= Fvco <= 3.5GHz, 2) PLL Od is
* either 1 or even number within the acceptable range (alas 1s
* is also excluded by the next loop).
*/
for (; nri <= nr_max; ++nri) {
/* Use Od factor to fulfill the limitation 2). */
num = CCU_PLL_CLKOD_FACTOR * rate;
denom = parent_rate / nri;
/*
* Make sure Fvco is within the acceptable range to fulfill
* the condition 1). Note due to the CCU_PLL_CLKOD_FACTOR value
* the actual upper limit is also divided by that factor.
* It's not big problem for us since practically there is no
* need in clocks with that high frequency.
*/
nf_max = min(CCU_PLL_FVCO_MAX / denom, CCU_PLL_NF_MAX);
od_max = CCU_PLL_OD_MAX / CCU_PLL_CLKOD_FACTOR;
/*
* Bypass the out-of-bound values, which can't be properly
* handled by the rational fraction approximation algorithm.
*/
if (num / denom >= nf_max) {
n1 = nf_max;
d1 = 1;
} else if (denom / num >= od_max) {
n1 = 1;
d1 = od_max;
} else {
rational_best_approximation(num, denom, nf_max, od_max,
&n1, &d1);
}
/* Select the best approximation of the target rate. */
freq = ccu_pll_calc_freq(parent_rate, nri, n1, d1);
err = abs((int64_t)freq - num);
if (err < min_err) {
min_err = err;
*nr = nri;
*nf = n1;
*od = CCU_PLL_CLKOD_FACTOR * d1;
}
}
}
static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long nr = 1, nf = 1, od = 1;
ccu_pll_calc_factors(rate, *parent_rate, &nr, &nf, &od);
return ccu_pll_calc_freq(*parent_rate, nr, nf, od);
}
/*
* This method is used for PLLs, which support the on-the-fly dividers
* adjustment. So there is no need in gating such clocks.
*/
static int ccu_pll_set_rate_reset(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_pll *pll = to_ccu_pll(hw);
unsigned long nr, nf, od;
unsigned long flags;
u32 mask, val;
int ret;
ccu_pll_calc_factors(rate, parent_rate, &nr, &nf, &od);
mask = CCU_PLL_CTL_CLKR_MASK | CCU_PLL_CTL_CLKF_MASK |
CCU_PLL_CTL_CLKOD_MASK;
val = FIELD_PREP(CCU_PLL_CTL_CLKR_MASK, nr - 1) |
FIELD_PREP(CCU_PLL_CTL_CLKF_MASK, nf - 1) |
FIELD_PREP(CCU_PLL_CTL_CLKOD_MASK, od - 1);
spin_lock_irqsave(&pll->lock, flags);
regmap_update_bits(pll->sys_regs, pll->reg_ctl, mask, val);
ret = ccu_pll_reset(pll, parent_rate, nr);
spin_unlock_irqrestore(&pll->lock, flags);
if (ret)
pr_err("PLL '%s' reset timed out\n", clk_hw_get_name(hw));
return ret;
}
/*
* This method is used for PLLs, which don't support the on-the-fly dividers
* adjustment. So the corresponding clocks are supposed to be gated first.
*/
static int ccu_pll_set_rate_norst(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ccu_pll *pll = to_ccu_pll(hw);
unsigned long nr, nf, od;
unsigned long flags;
u32 mask, val;
ccu_pll_calc_factors(rate, parent_rate, &nr, &nf, &od);
/*
* Disable PLL if it was enabled by default or left enabled by the
* system bootloader.
*/
mask = CCU_PLL_CTL_CLKR_MASK | CCU_PLL_CTL_CLKF_MASK |
CCU_PLL_CTL_CLKOD_MASK | CCU_PLL_CTL_EN;
val = FIELD_PREP(CCU_PLL_CTL_CLKR_MASK, nr - 1) |
FIELD_PREP(CCU_PLL_CTL_CLKF_MASK, nf - 1) |
FIELD_PREP(CCU_PLL_CTL_CLKOD_MASK, od - 1);
spin_lock_irqsave(&pll->lock, flags);
regmap_update_bits(pll->sys_regs, pll->reg_ctl, mask, val);
spin_unlock_irqrestore(&pll->lock, flags);
return 0;
}
#ifdef CONFIG_DEBUG_FS
struct ccu_pll_dbgfs_bit {
struct ccu_pll *pll;
const char *name;
unsigned int reg;
u32 mask;
};
struct ccu_pll_dbgfs_fld {
struct ccu_pll *pll;
const char *name;
unsigned int reg;
unsigned int lsb;
u32 mask;
u32 min;
u32 max;
};
#define CCU_PLL_DBGFS_BIT_ATTR(_name, _reg, _mask) \
{ \
.name = _name, \
.reg = _reg, \
.mask = _mask \
}
#define CCU_PLL_DBGFS_FLD_ATTR(_name, _reg, _lsb, _mask, _min, _max) \
{ \
.name = _name, \
.reg = _reg, \
.lsb = _lsb, \
.mask = _mask, \
.min = _min, \
.max = _max \
}
static const struct ccu_pll_dbgfs_bit ccu_pll_bits[] = {
CCU_PLL_DBGFS_BIT_ATTR("pll_en", CCU_PLL_CTL, CCU_PLL_CTL_EN),
CCU_PLL_DBGFS_BIT_ATTR("pll_rst", CCU_PLL_CTL, CCU_PLL_CTL_RST),
CCU_PLL_DBGFS_BIT_ATTR("pll_bypass", CCU_PLL_CTL, CCU_PLL_CTL_BYPASS),
CCU_PLL_DBGFS_BIT_ATTR("pll_lock", CCU_PLL_CTL, CCU_PLL_CTL_LOCK)
};
#define CCU_PLL_DBGFS_BIT_NUM ARRAY_SIZE(ccu_pll_bits)
static const struct ccu_pll_dbgfs_fld ccu_pll_flds[] = {
CCU_PLL_DBGFS_FLD_ATTR("pll_nr", CCU_PLL_CTL, CCU_PLL_CTL_CLKR_FLD,
CCU_PLL_CTL_CLKR_MASK, 1, CCU_PLL_NR_MAX),
CCU_PLL_DBGFS_FLD_ATTR("pll_nf", CCU_PLL_CTL, CCU_PLL_CTL_CLKF_FLD,
CCU_PLL_CTL_CLKF_MASK, 1, CCU_PLL_NF_MAX),
CCU_PLL_DBGFS_FLD_ATTR("pll_od", CCU_PLL_CTL, CCU_PLL_CTL_CLKOD_FLD,
CCU_PLL_CTL_CLKOD_MASK, 1, CCU_PLL_OD_MAX),
CCU_PLL_DBGFS_FLD_ATTR("pll_nb", CCU_PLL_CTL1, CCU_PLL_CTL1_BWADJ_FLD,
CCU_PLL_CTL1_BWADJ_MASK, 1, CCU_PLL_NB_MAX)
};
#define CCU_PLL_DBGFS_FLD_NUM ARRAY_SIZE(ccu_pll_flds)
/*
* It can be dangerous to change the PLL settings behind clock framework back,
* therefore we don't provide any kernel config based compile time option for
* this feature to enable.
*/
#undef CCU_PLL_ALLOW_WRITE_DEBUGFS
#ifdef CCU_PLL_ALLOW_WRITE_DEBUGFS
static int ccu_pll_dbgfs_bit_set(void *priv, u64 val)
{
const struct ccu_pll_dbgfs_bit *bit = priv;
struct ccu_pll *pll = bit->pll;
unsigned long flags;
spin_lock_irqsave(&pll->lock, flags);
regmap_update_bits(pll->sys_regs, pll->reg_ctl + bit->reg,
bit->mask, val ? bit->mask : 0);
spin_unlock_irqrestore(&pll->lock, flags);
return 0;
}
static int ccu_pll_dbgfs_fld_set(void *priv, u64 val)
{
struct ccu_pll_dbgfs_fld *fld = priv;
struct ccu_pll *pll = fld->pll;
unsigned long flags;
u32 data;
val = clamp_t(u64, val, fld->min, fld->max);
data = ((val - 1) << fld->lsb) & fld->mask;
spin_lock_irqsave(&pll->lock, flags);
regmap_update_bits(pll->sys_regs, pll->reg_ctl + fld->reg, fld->mask,
data);
spin_unlock_irqrestore(&pll->lock, flags);
return 0;
}
#define ccu_pll_dbgfs_mode 0644
#else /* !CCU_PLL_ALLOW_WRITE_DEBUGFS */
#define ccu_pll_dbgfs_bit_set NULL
#define ccu_pll_dbgfs_fld_set NULL
#define ccu_pll_dbgfs_mode 0444
#endif /* !CCU_PLL_ALLOW_WRITE_DEBUGFS */
static int ccu_pll_dbgfs_bit_get(void *priv, u64 *val)
{
struct ccu_pll_dbgfs_bit *bit = priv;
struct ccu_pll *pll = bit->pll;
u32 data = 0;
regmap_read(pll->sys_regs, pll->reg_ctl + bit->reg, &data);
*val = !!(data & bit->mask);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(ccu_pll_dbgfs_bit_fops,
ccu_pll_dbgfs_bit_get, ccu_pll_dbgfs_bit_set, "%llu\n");
static int ccu_pll_dbgfs_fld_get(void *priv, u64 *val)
{
struct ccu_pll_dbgfs_fld *fld = priv;
struct ccu_pll *pll = fld->pll;
u32 data = 0;
regmap_read(pll->sys_regs, pll->reg_ctl + fld->reg, &data);
*val = ((data & fld->mask) >> fld->lsb) + 1;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(ccu_pll_dbgfs_fld_fops,
ccu_pll_dbgfs_fld_get, ccu_pll_dbgfs_fld_set, "%llu\n");
static void ccu_pll_debug_init(struct clk_hw *hw, struct dentry *dentry)
{
struct ccu_pll *pll = to_ccu_pll(hw);
struct ccu_pll_dbgfs_bit *bits;
struct ccu_pll_dbgfs_fld *flds;
int idx;
bits = kcalloc(CCU_PLL_DBGFS_BIT_NUM, sizeof(*bits), GFP_KERNEL);
if (!bits)
return;
for (idx = 0; idx < CCU_PLL_DBGFS_BIT_NUM; ++idx) {
bits[idx] = ccu_pll_bits[idx];
bits[idx].pll = pll;
debugfs_create_file_unsafe(bits[idx].name, ccu_pll_dbgfs_mode,
dentry, &bits[idx],
&ccu_pll_dbgfs_bit_fops);
}
flds = kcalloc(CCU_PLL_DBGFS_FLD_NUM, sizeof(*flds), GFP_KERNEL);
if (!flds)
return;
for (idx = 0; idx < CCU_PLL_DBGFS_FLD_NUM; ++idx) {
flds[idx] = ccu_pll_flds[idx];
flds[idx].pll = pll;
debugfs_create_file_unsafe(flds[idx].name, ccu_pll_dbgfs_mode,
dentry, &flds[idx],
&ccu_pll_dbgfs_fld_fops);
}
}
#else /* !CONFIG_DEBUG_FS */
#define ccu_pll_debug_init NULL
#endif /* !CONFIG_DEBUG_FS */
static const struct clk_ops ccu_pll_gate_to_set_ops = {
.enable = ccu_pll_enable,
.disable = ccu_pll_disable,
.is_enabled = ccu_pll_is_enabled,
.recalc_rate = ccu_pll_recalc_rate,
.round_rate = ccu_pll_round_rate,
.set_rate = ccu_pll_set_rate_norst,
.debug_init = ccu_pll_debug_init
};
static const struct clk_ops ccu_pll_straight_set_ops = {
.enable = ccu_pll_enable,
.disable = ccu_pll_disable,
.is_enabled = ccu_pll_is_enabled,
.recalc_rate = ccu_pll_recalc_rate,
.round_rate = ccu_pll_round_rate,
.set_rate = ccu_pll_set_rate_reset,
.debug_init = ccu_pll_debug_init
};
struct ccu_pll *ccu_pll_hw_register(const struct ccu_pll_init_data *pll_init)
{
struct clk_parent_data parent_data = { };
struct clk_init_data hw_init = { };
struct ccu_pll *pll;
int ret;
if (!pll_init)
return ERR_PTR(-EINVAL);
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
/*
* Note since Baikal-T1 System Controller registers are MMIO-backed
* we won't check the regmap IO operations return status, because it
* must be zero anyway.
*/
pll->hw.init = &hw_init;
pll->reg_ctl = pll_init->base + CCU_PLL_CTL;
pll->reg_ctl1 = pll_init->base + CCU_PLL_CTL1;
pll->sys_regs = pll_init->sys_regs;
pll->id = pll_init->id;
spin_lock_init(&pll->lock);
hw_init.name = pll_init->name;
hw_init.flags = pll_init->flags;
if (hw_init.flags & CLK_SET_RATE_GATE)
hw_init.ops = &ccu_pll_gate_to_set_ops;
else
hw_init.ops = &ccu_pll_straight_set_ops;
if (!pll_init->parent_name) {
ret = -EINVAL;
goto err_free_pll;
}
parent_data.fw_name = pll_init->parent_name;
hw_init.parent_data = &parent_data;
hw_init.num_parents = 1;
ret = of_clk_hw_register(pll_init->np, &pll->hw);
if (ret)
goto err_free_pll;
return pll;
err_free_pll:
kfree(pll);
return ERR_PTR(ret);
}
void ccu_pll_hw_unregister(struct ccu_pll *pll)
{
clk_hw_unregister(&pll->hw);
kfree(pll);
}

Fájl megtekintése

@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Baikal-T1 CCU PLL interface driver
*/
#ifndef __CLK_BT1_CCU_PLL_H__
#define __CLK_BT1_CCU_PLL_H__
#include <linux/clk-provider.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/bits.h>
#include <linux/of.h>
/*
* struct ccu_pll_init_data - CCU PLL initialization data
* @id: Clock private identifier.
* @name: Clocks name.
* @parent_name: Clocks parent name in a fw node.
* @base: PLL registers base address with respect to the sys_regs base.
* @sys_regs: Baikal-T1 System Controller registers map.
* @np: Pointer to the node describing the CCU PLLs.
* @flags: PLL clock flags.
*/
struct ccu_pll_init_data {
unsigned int id;
const char *name;
const char *parent_name;
unsigned int base;
struct regmap *sys_regs;
struct device_node *np;
unsigned long flags;
};
/*
* struct ccu_pll - CCU PLL descriptor
* @hw: clk_hw of the PLL.
* @id: Clock private identifier.
* @reg_ctl: PLL control register base.
* @reg_ctl1: PLL control1 register base.
* @sys_regs: Baikal-T1 System Controller registers map.
* @lock: PLL state change spin-lock.
*/
struct ccu_pll {
struct clk_hw hw;
unsigned int id;
unsigned int reg_ctl;
unsigned int reg_ctl1;
struct regmap *sys_regs;
spinlock_t lock;
};
#define to_ccu_pll(_hw) container_of(_hw, struct ccu_pll, hw)
static inline struct clk_hw *ccu_pll_get_clk_hw(struct ccu_pll *pll)
{
return pll ? &pll->hw : NULL;
}
struct ccu_pll *ccu_pll_hw_register(const struct ccu_pll_init_data *init);
void ccu_pll_hw_unregister(struct ccu_pll *pll);
#endif /* __CLK_BT1_CCU_PLL_H__ */

Fájl megtekintése

@@ -0,0 +1,485 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Authors:
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
* Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
*
* Baikal-T1 CCU Dividers clock driver
*/
#define pr_fmt(fmt) "bt1-ccu-div: " fmt
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include <linux/reset-controller.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/ioport.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/bt1-ccu.h>
#include <dt-bindings/reset/bt1-ccu.h>
#include "ccu-div.h"
#define CCU_AXI_MAIN_BASE 0x030
#define CCU_AXI_DDR_BASE 0x034
#define CCU_AXI_SATA_BASE 0x038
#define CCU_AXI_GMAC0_BASE 0x03C
#define CCU_AXI_GMAC1_BASE 0x040
#define CCU_AXI_XGMAC_BASE 0x044
#define CCU_AXI_PCIE_M_BASE 0x048
#define CCU_AXI_PCIE_S_BASE 0x04C
#define CCU_AXI_USB_BASE 0x050
#define CCU_AXI_HWA_BASE 0x054
#define CCU_AXI_SRAM_BASE 0x058
#define CCU_SYS_SATA_REF_BASE 0x060
#define CCU_SYS_APB_BASE 0x064
#define CCU_SYS_GMAC0_BASE 0x068
#define CCU_SYS_GMAC1_BASE 0x06C
#define CCU_SYS_XGMAC_BASE 0x070
#define CCU_SYS_USB_BASE 0x074
#define CCU_SYS_PVT_BASE 0x078
#define CCU_SYS_HWA_BASE 0x07C
#define CCU_SYS_UART_BASE 0x084
#define CCU_SYS_TIMER0_BASE 0x088
#define CCU_SYS_TIMER1_BASE 0x08C
#define CCU_SYS_TIMER2_BASE 0x090
#define CCU_SYS_WDT_BASE 0x150
#define CCU_DIV_VAR_INFO(_id, _name, _pname, _base, _width, _flags, _features) \
{ \
.id = _id, \
.name = _name, \
.parent_name = _pname, \
.base = _base, \
.type = CCU_DIV_VAR, \
.width = _width, \
.flags = _flags, \
.features = _features \
}
#define CCU_DIV_GATE_INFO(_id, _name, _pname, _base, _divider) \
{ \
.id = _id, \
.name = _name, \
.parent_name = _pname, \
.base = _base, \
.type = CCU_DIV_GATE, \
.divider = _divider \
}
#define CCU_DIV_FIXED_INFO(_id, _name, _pname, _divider) \
{ \
.id = _id, \
.name = _name, \
.parent_name = _pname, \
.type = CCU_DIV_FIXED, \
.divider = _divider \
}
#define CCU_DIV_RST_MAP(_rst_id, _clk_id) \
{ \
.rst_id = _rst_id, \
.clk_id = _clk_id \
}
struct ccu_div_info {
unsigned int id;
const char *name;
const char *parent_name;
unsigned int base;
enum ccu_div_type type;
union {
unsigned int width;
unsigned int divider;
};
unsigned long flags;
unsigned long features;
};
struct ccu_div_rst_map {
unsigned int rst_id;
unsigned int clk_id;
};
struct ccu_div_data {
struct device_node *np;
struct regmap *sys_regs;
unsigned int divs_num;
const struct ccu_div_info *divs_info;
struct ccu_div **divs;
unsigned int rst_num;
const struct ccu_div_rst_map *rst_map;
struct reset_controller_dev rcdev;
};
#define to_ccu_div_data(_rcdev) container_of(_rcdev, struct ccu_div_data, rcdev)
/*
* AXI Main Interconnect (axi_main_clk) and DDR AXI-bus (axi_ddr_clk) clocks
* must be left enabled in any case, since former one is responsible for
* clocking a bus between CPU cores and the rest of the SoC components, while
* the later is clocking the AXI-bus between DDR controller and the Main
* Interconnect. So should any of these clocks get to be disabled, the system
* will literally stop working. That's why we marked them as critical.
*/
static const struct ccu_div_info axi_info[] = {
CCU_DIV_VAR_INFO(CCU_AXI_MAIN_CLK, "axi_main_clk", "pcie_clk",
CCU_AXI_MAIN_BASE, 4,
CLK_IS_CRITICAL, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_DDR_CLK, "axi_ddr_clk", "sata_clk",
CCU_AXI_DDR_BASE, 4,
CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_SATA_CLK, "axi_sata_clk", "sata_clk",
CCU_AXI_SATA_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_GMAC0_CLK, "axi_gmac0_clk", "eth_clk",
CCU_AXI_GMAC0_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_GMAC1_CLK, "axi_gmac1_clk", "eth_clk",
CCU_AXI_GMAC1_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_XGMAC_CLK, "axi_xgmac_clk", "eth_clk",
CCU_AXI_XGMAC_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_PCIE_M_CLK, "axi_pcie_m_clk", "pcie_clk",
CCU_AXI_PCIE_M_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_PCIE_S_CLK, "axi_pcie_s_clk", "pcie_clk",
CCU_AXI_PCIE_S_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_USB_CLK, "axi_usb_clk", "sata_clk",
CCU_AXI_USB_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_HWA_CLK, "axi_hwa_clk", "sata_clk",
CCU_AXI_HWA_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_AXI_SRAM_CLK, "axi_sram_clk", "eth_clk",
CCU_AXI_SRAM_BASE, 4,
CLK_SET_RATE_GATE, CCU_DIV_RESET_DOMAIN)
};
static const struct ccu_div_rst_map axi_rst_map[] = {
CCU_DIV_RST_MAP(CCU_AXI_MAIN_RST, CCU_AXI_MAIN_CLK),
CCU_DIV_RST_MAP(CCU_AXI_DDR_RST, CCU_AXI_DDR_CLK),
CCU_DIV_RST_MAP(CCU_AXI_SATA_RST, CCU_AXI_SATA_CLK),
CCU_DIV_RST_MAP(CCU_AXI_GMAC0_RST, CCU_AXI_GMAC0_CLK),
CCU_DIV_RST_MAP(CCU_AXI_GMAC1_RST, CCU_AXI_GMAC1_CLK),
CCU_DIV_RST_MAP(CCU_AXI_XGMAC_RST, CCU_AXI_XGMAC_CLK),
CCU_DIV_RST_MAP(CCU_AXI_PCIE_M_RST, CCU_AXI_PCIE_M_CLK),
CCU_DIV_RST_MAP(CCU_AXI_PCIE_S_RST, CCU_AXI_PCIE_S_CLK),
CCU_DIV_RST_MAP(CCU_AXI_USB_RST, CCU_AXI_USB_CLK),
CCU_DIV_RST_MAP(CCU_AXI_HWA_RST, CCU_AXI_HWA_CLK),
CCU_DIV_RST_MAP(CCU_AXI_SRAM_RST, CCU_AXI_SRAM_CLK)
};
/*
* APB-bus clock is marked as critical since it's a main communication bus
* for the SoC devices registers IO-operations.
*/
static const struct ccu_div_info sys_info[] = {
CCU_DIV_VAR_INFO(CCU_SYS_SATA_REF_CLK, "sys_sata_ref_clk",
"sata_clk", CCU_SYS_SATA_REF_BASE, 4,
CLK_SET_RATE_GATE,
CCU_DIV_SKIP_ONE | CCU_DIV_LOCK_SHIFTED |
CCU_DIV_RESET_DOMAIN),
CCU_DIV_VAR_INFO(CCU_SYS_APB_CLK, "sys_apb_clk",
"pcie_clk", CCU_SYS_APB_BASE, 5,
CLK_IS_CRITICAL, CCU_DIV_RESET_DOMAIN),
CCU_DIV_GATE_INFO(CCU_SYS_GMAC0_TX_CLK, "sys_gmac0_tx_clk",
"eth_clk", CCU_SYS_GMAC0_BASE, 5),
CCU_DIV_FIXED_INFO(CCU_SYS_GMAC0_PTP_CLK, "sys_gmac0_ptp_clk",
"eth_clk", 10),
CCU_DIV_GATE_INFO(CCU_SYS_GMAC1_TX_CLK, "sys_gmac1_tx_clk",
"eth_clk", CCU_SYS_GMAC1_BASE, 5),
CCU_DIV_FIXED_INFO(CCU_SYS_GMAC1_PTP_CLK, "sys_gmac1_ptp_clk",
"eth_clk", 10),
CCU_DIV_GATE_INFO(CCU_SYS_XGMAC_REF_CLK, "sys_xgmac_ref_clk",
"eth_clk", CCU_SYS_XGMAC_BASE, 8),
CCU_DIV_FIXED_INFO(CCU_SYS_XGMAC_PTP_CLK, "sys_xgmac_ptp_clk",
"eth_clk", 10),
CCU_DIV_GATE_INFO(CCU_SYS_USB_CLK, "sys_usb_clk",
"eth_clk", CCU_SYS_USB_BASE, 10),
CCU_DIV_VAR_INFO(CCU_SYS_PVT_CLK, "sys_pvt_clk",
"ref_clk", CCU_SYS_PVT_BASE, 5,
CLK_SET_RATE_GATE, 0),
CCU_DIV_VAR_INFO(CCU_SYS_HWA_CLK, "sys_hwa_clk",
"sata_clk", CCU_SYS_HWA_BASE, 4,
CLK_SET_RATE_GATE, 0),
CCU_DIV_VAR_INFO(CCU_SYS_UART_CLK, "sys_uart_clk",
"eth_clk", CCU_SYS_UART_BASE, 17,
CLK_SET_RATE_GATE, 0),
CCU_DIV_FIXED_INFO(CCU_SYS_I2C1_CLK, "sys_i2c1_clk",
"eth_clk", 10),
CCU_DIV_FIXED_INFO(CCU_SYS_I2C2_CLK, "sys_i2c2_clk",
"eth_clk", 10),
CCU_DIV_FIXED_INFO(CCU_SYS_GPIO_CLK, "sys_gpio_clk",
"ref_clk", 25),
CCU_DIV_VAR_INFO(CCU_SYS_TIMER0_CLK, "sys_timer0_clk",
"ref_clk", CCU_SYS_TIMER0_BASE, 17,
CLK_SET_RATE_GATE, 0),
CCU_DIV_VAR_INFO(CCU_SYS_TIMER1_CLK, "sys_timer1_clk",
"ref_clk", CCU_SYS_TIMER1_BASE, 17,
CLK_SET_RATE_GATE, 0),
CCU_DIV_VAR_INFO(CCU_SYS_TIMER2_CLK, "sys_timer2_clk",
"ref_clk", CCU_SYS_TIMER2_BASE, 17,
CLK_SET_RATE_GATE, 0),
CCU_DIV_VAR_INFO(CCU_SYS_WDT_CLK, "sys_wdt_clk",
"eth_clk", CCU_SYS_WDT_BASE, 17,
CLK_SET_RATE_GATE, CCU_DIV_SKIP_ONE_TO_THREE)
};
static const struct ccu_div_rst_map sys_rst_map[] = {
CCU_DIV_RST_MAP(CCU_SYS_SATA_REF_RST, CCU_SYS_SATA_REF_CLK),
CCU_DIV_RST_MAP(CCU_SYS_APB_RST, CCU_SYS_APB_CLK),
};
static struct ccu_div *ccu_div_find_desc(struct ccu_div_data *data,
unsigned int clk_id)
{
struct ccu_div *div;
int idx;
for (idx = 0; idx < data->divs_num; ++idx) {
div = data->divs[idx];
if (div && div->id == clk_id)
return div;
}
return ERR_PTR(-EINVAL);
}
static int ccu_div_reset(struct reset_controller_dev *rcdev,
unsigned long rst_id)
{
struct ccu_div_data *data = to_ccu_div_data(rcdev);
const struct ccu_div_rst_map *map;
struct ccu_div *div;
int idx, ret;
for (idx = 0, map = data->rst_map; idx < data->rst_num; ++idx, ++map) {
if (map->rst_id == rst_id)
break;
}
if (idx == data->rst_num) {
pr_err("Invalid reset ID %lu specified\n", rst_id);
return -EINVAL;
}
div = ccu_div_find_desc(data, map->clk_id);
if (IS_ERR(div)) {
pr_err("Invalid clock ID %d in mapping\n", map->clk_id);
return PTR_ERR(div);
}
ret = ccu_div_reset_domain(div);
if (ret) {
pr_err("Reset isn't supported by divider %s\n",
clk_hw_get_name(ccu_div_get_clk_hw(div)));
}
return ret;
}
static const struct reset_control_ops ccu_div_rst_ops = {
.reset = ccu_div_reset,
};
static struct ccu_div_data *ccu_div_create_data(struct device_node *np)
{
struct ccu_div_data *data;
int ret;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
data->np = np;
if (of_device_is_compatible(np, "baikal,bt1-ccu-axi")) {
data->divs_num = ARRAY_SIZE(axi_info);
data->divs_info = axi_info;
data->rst_num = ARRAY_SIZE(axi_rst_map);
data->rst_map = axi_rst_map;
} else if (of_device_is_compatible(np, "baikal,bt1-ccu-sys")) {
data->divs_num = ARRAY_SIZE(sys_info);
data->divs_info = sys_info;
data->rst_num = ARRAY_SIZE(sys_rst_map);
data->rst_map = sys_rst_map;
} else {
pr_err("Incompatible DT node '%s' specified\n",
of_node_full_name(np));
ret = -EINVAL;
goto err_kfree_data;
}
data->divs = kcalloc(data->divs_num, sizeof(*data->divs), GFP_KERNEL);
if (!data->divs) {
ret = -ENOMEM;
goto err_kfree_data;
}
return data;
err_kfree_data:
kfree(data);
return ERR_PTR(ret);
}
static void ccu_div_free_data(struct ccu_div_data *data)
{
kfree(data->divs);
kfree(data);
}
static int ccu_div_find_sys_regs(struct ccu_div_data *data)
{
data->sys_regs = syscon_node_to_regmap(data->np->parent);
if (IS_ERR(data->sys_regs)) {
pr_err("Failed to find syscon regs for '%s'\n",
of_node_full_name(data->np));
return PTR_ERR(data->sys_regs);
}
return 0;
}
static struct clk_hw *ccu_div_of_clk_hw_get(struct of_phandle_args *clkspec,
void *priv)
{
struct ccu_div_data *data = priv;
struct ccu_div *div;
unsigned int clk_id;
clk_id = clkspec->args[0];
div = ccu_div_find_desc(data, clk_id);
if (IS_ERR(div)) {
pr_info("Invalid clock ID %d specified\n", clk_id);
return ERR_CAST(div);
}
return ccu_div_get_clk_hw(div);
}
static int ccu_div_clk_register(struct ccu_div_data *data)
{
int idx, ret;
for (idx = 0; idx < data->divs_num; ++idx) {
const struct ccu_div_info *info = &data->divs_info[idx];
struct ccu_div_init_data init = {0};
init.id = info->id;
init.name = info->name;
init.parent_name = info->parent_name;
init.np = data->np;
init.type = info->type;
init.flags = info->flags;
init.features = info->features;
if (init.type == CCU_DIV_VAR) {
init.base = info->base;
init.sys_regs = data->sys_regs;
init.width = info->width;
} else if (init.type == CCU_DIV_GATE) {
init.base = info->base;
init.sys_regs = data->sys_regs;
init.divider = info->divider;
} else {
init.divider = info->divider;
}
data->divs[idx] = ccu_div_hw_register(&init);
if (IS_ERR(data->divs[idx])) {
ret = PTR_ERR(data->divs[idx]);
pr_err("Couldn't register divider '%s' hw\n",
init.name);
goto err_hw_unregister;
}
}
ret = of_clk_add_hw_provider(data->np, ccu_div_of_clk_hw_get, data);
if (ret) {
pr_err("Couldn't register dividers '%s' clock provider\n",
of_node_full_name(data->np));
goto err_hw_unregister;
}
return 0;
err_hw_unregister:
for (--idx; idx >= 0; --idx)
ccu_div_hw_unregister(data->divs[idx]);
return ret;
}
static void ccu_div_clk_unregister(struct ccu_div_data *data)
{
int idx;
of_clk_del_provider(data->np);
for (idx = 0; idx < data->divs_num; ++idx)
ccu_div_hw_unregister(data->divs[idx]);
}
static int ccu_div_rst_register(struct ccu_div_data *data)
{
int ret;
data->rcdev.ops = &ccu_div_rst_ops;
data->rcdev.of_node = data->np;
data->rcdev.nr_resets = data->rst_num;
ret = reset_controller_register(&data->rcdev);
if (ret)
pr_err("Couldn't register divider '%s' reset controller\n",
of_node_full_name(data->np));
return ret;
}
static void ccu_div_init(struct device_node *np)
{
struct ccu_div_data *data;
int ret;
data = ccu_div_create_data(np);
if (IS_ERR(data))
return;
ret = ccu_div_find_sys_regs(data);
if (ret)
goto err_free_data;
ret = ccu_div_clk_register(data);
if (ret)
goto err_free_data;
ret = ccu_div_rst_register(data);
if (ret)
goto err_clk_unregister;
return;
err_clk_unregister:
ccu_div_clk_unregister(data);
err_free_data:
ccu_div_free_data(data);
}
CLK_OF_DECLARE(ccu_axi, "baikal,bt1-ccu-axi", ccu_div_init);
CLK_OF_DECLARE(ccu_sys, "baikal,bt1-ccu-sys", ccu_div_init);

Fájl megtekintése

@@ -0,0 +1,204 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
*
* Authors:
* Serge Semin <Sergey.Semin@baikalelectronics.ru>
* Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
*
* Baikal-T1 CCU PLL clocks driver
*/
#define pr_fmt(fmt) "bt1-ccu-pll: " fmt
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/ioport.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/bt1-ccu.h>
#include "ccu-pll.h"
#define CCU_CPU_PLL_BASE 0x000
#define CCU_SATA_PLL_BASE 0x008
#define CCU_DDR_PLL_BASE 0x010
#define CCU_PCIE_PLL_BASE 0x018
#define CCU_ETH_PLL_BASE 0x020
#define CCU_PLL_INFO(_id, _name, _pname, _base, _flags) \
{ \
.id = _id, \
.name = _name, \
.parent_name = _pname, \
.base = _base, \
.flags = _flags \
}
#define CCU_PLL_NUM ARRAY_SIZE(pll_info)
struct ccu_pll_info {
unsigned int id;
const char *name;
const char *parent_name;
unsigned int base;
unsigned long flags;
};
/*
* Mark as critical all PLLs except Ethernet one. CPU and DDR PLLs are sources
* of CPU cores and DDR controller reference clocks, due to which they
* obviously shouldn't be ever gated. SATA and PCIe PLLs are the parents of
* APB-bus and DDR controller AXI-bus clocks. If they are gated the system will
* be unusable.
*/
static const struct ccu_pll_info pll_info[] = {
CCU_PLL_INFO(CCU_CPU_PLL, "cpu_pll", "ref_clk", CCU_CPU_PLL_BASE,
CLK_IS_CRITICAL),
CCU_PLL_INFO(CCU_SATA_PLL, "sata_pll", "ref_clk", CCU_SATA_PLL_BASE,
CLK_IS_CRITICAL | CLK_SET_RATE_GATE),
CCU_PLL_INFO(CCU_DDR_PLL, "ddr_pll", "ref_clk", CCU_DDR_PLL_BASE,
CLK_IS_CRITICAL | CLK_SET_RATE_GATE),
CCU_PLL_INFO(CCU_PCIE_PLL, "pcie_pll", "ref_clk", CCU_PCIE_PLL_BASE,
CLK_IS_CRITICAL),
CCU_PLL_INFO(CCU_ETH_PLL, "eth_pll", "ref_clk", CCU_ETH_PLL_BASE,
CLK_SET_RATE_GATE)
};
struct ccu_pll_data {
struct device_node *np;
struct regmap *sys_regs;
struct ccu_pll *plls[CCU_PLL_NUM];
};
static struct ccu_pll *ccu_pll_find_desc(struct ccu_pll_data *data,
unsigned int clk_id)
{
struct ccu_pll *pll;
int idx;
for (idx = 0; idx < CCU_PLL_NUM; ++idx) {
pll = data->plls[idx];
if (pll && pll->id == clk_id)
return pll;
}
return ERR_PTR(-EINVAL);
}
static struct ccu_pll_data *ccu_pll_create_data(struct device_node *np)
{
struct ccu_pll_data *data;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
data->np = np;
return data;
}
static void ccu_pll_free_data(struct ccu_pll_data *data)
{
kfree(data);
}
static int ccu_pll_find_sys_regs(struct ccu_pll_data *data)
{
data->sys_regs = syscon_node_to_regmap(data->np->parent);
if (IS_ERR(data->sys_regs)) {
pr_err("Failed to find syscon regs for '%s'\n",
of_node_full_name(data->np));
return PTR_ERR(data->sys_regs);
}
return 0;
}
static struct clk_hw *ccu_pll_of_clk_hw_get(struct of_phandle_args *clkspec,
void *priv)
{
struct ccu_pll_data *data = priv;
struct ccu_pll *pll;
unsigned int clk_id;
clk_id = clkspec->args[0];
pll = ccu_pll_find_desc(data, clk_id);
if (IS_ERR(pll)) {
pr_info("Invalid PLL clock ID %d specified\n", clk_id);
return ERR_CAST(pll);
}
return ccu_pll_get_clk_hw(pll);
}
static int ccu_pll_clk_register(struct ccu_pll_data *data)
{
int idx, ret;
for (idx = 0; idx < CCU_PLL_NUM; ++idx) {
const struct ccu_pll_info *info = &pll_info[idx];
struct ccu_pll_init_data init = {0};
init.id = info->id;
init.name = info->name;
init.parent_name = info->parent_name;
init.base = info->base;
init.sys_regs = data->sys_regs;
init.np = data->np;
init.flags = info->flags;
data->plls[idx] = ccu_pll_hw_register(&init);
if (IS_ERR(data->plls[idx])) {
ret = PTR_ERR(data->plls[idx]);
pr_err("Couldn't register PLL hw '%s'\n",
init.name);
goto err_hw_unregister;
}
}
ret = of_clk_add_hw_provider(data->np, ccu_pll_of_clk_hw_get, data);
if (ret) {
pr_err("Couldn't register PLL provider of '%s'\n",
of_node_full_name(data->np));
goto err_hw_unregister;
}
return 0;
err_hw_unregister:
for (--idx; idx >= 0; --idx)
ccu_pll_hw_unregister(data->plls[idx]);
return ret;
}
static __init void ccu_pll_init(struct device_node *np)
{
struct ccu_pll_data *data;
int ret;
data = ccu_pll_create_data(np);
if (IS_ERR(data))
return;
ret = ccu_pll_find_sys_regs(data);
if (ret)
goto err_free_data;
ret = ccu_pll_clk_register(data);
if (ret)
goto err_free_data;
return;
err_free_data:
ccu_pll_free_data(data);
}
CLK_OF_DECLARE(ccu_pll, "baikal,bt1-ccu-pll", ccu_pll_init);

Fájl megtekintése

@@ -396,8 +396,8 @@ out:
}
static void bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
struct debugfs_reg32 *regs, size_t nregs,
struct dentry *dentry)
const struct debugfs_reg32 *regs,
size_t nregs, struct dentry *dentry)
{
struct debugfs_regset32 *regset;
@@ -1240,7 +1240,7 @@ static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
}
static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
static const struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
{
.name = "ctl",
.offset = 0,
@@ -1296,8 +1296,9 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
};
static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
const struct bcm2835_pll_data *data)
const void *data)
{
const struct bcm2835_pll_data *pll_data = data;
struct bcm2835_pll *pll;
struct clk_init_data init;
int ret;
@@ -1307,7 +1308,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
/* All of the PLLs derive from the external oscillator. */
init.parent_names = &cprman->real_parent_names[0];
init.num_parents = 1;
init.name = data->name;
init.name = pll_data->name;
init.ops = &bcm2835_pll_clk_ops;
init.flags = CLK_IGNORE_UNUSED;
@@ -1316,7 +1317,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
return NULL;
pll->cprman = cprman;
pll->data = data;
pll->data = pll_data;
pll->hw.init = &init;
ret = devm_clk_hw_register(cprman->dev, &pll->hw);
@@ -1327,35 +1328,36 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
static struct clk_hw *
bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
const struct bcm2835_pll_divider_data *data)
const void *data)
{
const struct bcm2835_pll_divider_data *divider_data = data;
struct bcm2835_pll_divider *divider;
struct clk_init_data init;
const char *divider_name;
int ret;
if (data->fixed_divider != 1) {
if (divider_data->fixed_divider != 1) {
divider_name = devm_kasprintf(cprman->dev, GFP_KERNEL,
"%s_prediv", data->name);
"%s_prediv", divider_data->name);
if (!divider_name)
return NULL;
} else {
divider_name = data->name;
divider_name = divider_data->name;
}
memset(&init, 0, sizeof(init));
init.parent_names = &data->source_pll;
init.parent_names = &divider_data->source_pll;
init.num_parents = 1;
init.name = divider_name;
init.ops = &bcm2835_pll_divider_clk_ops;
init.flags = data->flags | CLK_IGNORE_UNUSED;
init.flags = divider_data->flags | CLK_IGNORE_UNUSED;
divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL);
if (!divider)
return NULL;
divider->div.reg = cprman->regs + data->a2w_reg;
divider->div.reg = cprman->regs + divider_data->a2w_reg;
divider->div.shift = A2W_PLL_DIV_SHIFT;
divider->div.width = A2W_PLL_DIV_BITS;
divider->div.flags = CLK_DIVIDER_MAX_AT_ZERO;
@@ -1364,7 +1366,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
divider->div.table = NULL;
divider->cprman = cprman;
divider->data = data;
divider->data = divider_data;
ret = devm_clk_hw_register(cprman->dev, &divider->div.hw);
if (ret)
@@ -1374,20 +1376,22 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
* PLLH's channels have a fixed divide by 10 afterwards, which
* is what our consumers are actually using.
*/
if (data->fixed_divider != 1) {
return clk_hw_register_fixed_factor(cprman->dev, data->name,
if (divider_data->fixed_divider != 1) {
return clk_hw_register_fixed_factor(cprman->dev,
divider_data->name,
divider_name,
CLK_SET_RATE_PARENT,
1,
data->fixed_divider);
divider_data->fixed_divider);
}
return &divider->div.hw;
}
static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
const struct bcm2835_clock_data *data)
const void *data)
{
const struct bcm2835_clock_data *clock_data = data;
struct bcm2835_clock *clock;
struct clk_init_data init;
const char *parents[1 << CM_SRC_BITS];
@@ -1398,8 +1402,8 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
* Replace our strings referencing parent clocks with the
* actual clock-output-name of the parent.
*/
for (i = 0; i < data->num_mux_parents; i++) {
parents[i] = data->parents[i];
for (i = 0; i < clock_data->num_mux_parents; i++) {
parents[i] = clock_data->parents[i];
ret = match_string(cprman_parent_names,
ARRAY_SIZE(cprman_parent_names),
@@ -1410,18 +1414,18 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
memset(&init, 0, sizeof(init));
init.parent_names = parents;
init.num_parents = data->num_mux_parents;
init.name = data->name;
init.flags = data->flags | CLK_IGNORE_UNUSED;
init.num_parents = clock_data->num_mux_parents;
init.name = clock_data->name;
init.flags = clock_data->flags | CLK_IGNORE_UNUSED;
/*
* Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
* rate changes on at least of the parents.
*/
if (data->set_rate_parent)
if (clock_data->set_rate_parent)
init.flags |= CLK_SET_RATE_PARENT;
if (data->is_vpu_clock) {
if (clock_data->is_vpu_clock) {
init.ops = &bcm2835_vpu_clock_clk_ops;
} else {
init.ops = &bcm2835_clock_clk_ops;
@@ -1430,7 +1434,7 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
/* If the clock wasn't actually enabled at boot, it's not
* critical.
*/
if (!(cprman_read(cprman, data->ctl_reg) & CM_ENABLE))
if (!(cprman_read(cprman, clock_data->ctl_reg) & CM_ENABLE))
init.flags &= ~CLK_IS_CRITICAL;
}
@@ -1439,7 +1443,7 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
return NULL;
clock->cprman = cprman;
clock->data = data;
clock->data = clock_data;
clock->hw.init = &init;
ret = devm_clk_hw_register(cprman->dev, &clock->hw);
@@ -1448,25 +1452,27 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
return &clock->hw;
}
static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
const struct bcm2835_gate_data *data)
static struct clk_hw *bcm2835_register_gate(struct bcm2835_cprman *cprman,
const void *data)
{
return clk_register_gate(cprman->dev, data->name, data->parent,
CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
cprman->regs + data->ctl_reg,
CM_GATE_BIT, 0, &cprman->regs_lock);
const struct bcm2835_gate_data *gate_data = data;
return clk_hw_register_gate(cprman->dev, gate_data->name,
gate_data->parent,
CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
cprman->regs + gate_data->ctl_reg,
CM_GATE_BIT, 0, &cprman->regs_lock);
}
typedef struct clk_hw *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
const void *data);
struct bcm2835_clk_desc {
bcm2835_clk_register clk_register;
struct clk_hw *(*clk_register)(struct bcm2835_cprman *cprman,
const void *data);
unsigned int supported;
const void *data;
};
/* assignment helper macros for different clock types */
#define _REGISTER(f, s, ...) { .clk_register = (bcm2835_clk_register)f, \
#define _REGISTER(f, s, ...) { .clk_register = f, \
.supported = s, \
.data = __VA_ARGS__ }
#define REGISTER_PLL(s, ...) _REGISTER(&bcm2835_register_pll, \

Fájl megtekintése

@@ -642,14 +642,22 @@ static const u32 ast2600_a0_axi_ahb_div_table[] = {
2, 2, 3, 5,
};
static const u32 ast2600_a1_axi_ahb_div_table[] = {
4, 6, 2, 4,
static const u32 ast2600_a1_axi_ahb_div0_tbl[] = {
3, 2, 3, 4,
};
static const u32 ast2600_a1_axi_ahb_div1_tbl[] = {
3, 4, 6, 8,
};
static const u32 ast2600_a1_axi_ahb200_tbl[] = {
3, 4, 3, 4, 2, 2, 2, 2,
};
static void __init aspeed_g6_cc(struct regmap *map)
{
struct clk_hw *hw;
u32 val, div, chip_id, axi_div, ahb_div;
u32 val, div, divbits, chip_id, axi_div, ahb_div;
clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, 25000000);
@@ -679,11 +687,22 @@ static void __init aspeed_g6_cc(struct regmap *map)
else
axi_div = 2;
divbits = (val >> 11) & 0x3;
regmap_read(map, ASPEED_G6_SILICON_REV, &chip_id);
if (chip_id & BIT(16))
ahb_div = ast2600_a1_axi_ahb_div_table[(val >> 11) & 0x3];
else
if (chip_id & BIT(16)) {
if (!divbits) {
ahb_div = ast2600_a1_axi_ahb200_tbl[(val >> 8) & 0x3];
if (val & BIT(16))
ahb_div *= 2;
} else {
if (val & BIT(16))
ahb_div = ast2600_a1_axi_ahb_div1_tbl[divbits];
else
ahb_div = ast2600_a1_axi_ahb_div0_tbl[divbits];
}
} else {
ahb_div = ast2600_a0_axi_ahb_div_table[(val >> 11) & 0x3];
}
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, axi_div * ahb_div);
aspeed_g6_clk_data->hws[ASPEED_CLK_AHB] = hw;

Fájl megtekintése

@@ -53,35 +53,38 @@ struct hsdk_pll_cfg {
u32 fbdiv;
u32 odiv;
u32 band;
u32 bypass;
};
static const struct hsdk_pll_cfg asdt_pll_cfg[] = {
{ 100000000, 0, 11, 3, 0 },
{ 133000000, 0, 15, 3, 0 },
{ 200000000, 1, 47, 3, 0 },
{ 233000000, 1, 27, 2, 0 },
{ 300000000, 1, 35, 2, 0 },
{ 333000000, 1, 39, 2, 0 },
{ 400000000, 1, 47, 2, 0 },
{ 500000000, 0, 14, 1, 0 },
{ 600000000, 0, 17, 1, 0 },
{ 700000000, 0, 20, 1, 0 },
{ 800000000, 0, 23, 1, 0 },
{ 900000000, 1, 26, 0, 0 },
{ 1000000000, 1, 29, 0, 0 },
{ 1100000000, 1, 32, 0, 0 },
{ 1200000000, 1, 35, 0, 0 },
{ 1300000000, 1, 38, 0, 0 },
{ 1400000000, 1, 41, 0, 0 },
{ 1500000000, 1, 44, 0, 0 },
{ 1600000000, 1, 47, 0, 0 },
{ 100000000, 0, 11, 3, 0, 0 },
{ 133000000, 0, 15, 3, 0, 0 },
{ 200000000, 1, 47, 3, 0, 0 },
{ 233000000, 1, 27, 2, 0, 0 },
{ 300000000, 1, 35, 2, 0, 0 },
{ 333000000, 1, 39, 2, 0, 0 },
{ 400000000, 1, 47, 2, 0, 0 },
{ 500000000, 0, 14, 1, 0, 0 },
{ 600000000, 0, 17, 1, 0, 0 },
{ 700000000, 0, 20, 1, 0, 0 },
{ 800000000, 0, 23, 1, 0, 0 },
{ 900000000, 1, 26, 0, 0, 0 },
{ 1000000000, 1, 29, 0, 0, 0 },
{ 1100000000, 1, 32, 0, 0, 0 },
{ 1200000000, 1, 35, 0, 0, 0 },
{ 1300000000, 1, 38, 0, 0, 0 },
{ 1400000000, 1, 41, 0, 0, 0 },
{ 1500000000, 1, 44, 0, 0, 0 },
{ 1600000000, 1, 47, 0, 0, 0 },
{}
};
static const struct hsdk_pll_cfg hdmi_pll_cfg[] = {
{ 297000000, 0, 21, 2, 0 },
{ 540000000, 0, 19, 1, 0 },
{ 594000000, 0, 21, 1, 0 },
{ 27000000, 0, 0, 0, 0, 1 },
{ 148500000, 0, 21, 3, 0, 0 },
{ 297000000, 0, 21, 2, 0, 0 },
{ 540000000, 0, 19, 1, 0, 0 },
{ 594000000, 0, 21, 1, 0, 0 },
{}
};
@@ -134,11 +137,16 @@ static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk,
{
u32 val = 0;
/* Powerdown and Bypass bits should be cleared */
val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT;
val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT;
val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
if (cfg->bypass) {
val = hsdk_pll_read(clk, CGU_PLL_CTRL);
val |= CGU_PLL_CTRL_BYPASS;
} else {
/* Powerdown and Bypass bits should be cleared */
val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT;
val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT;
val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
}
dev_dbg(clk->dev, "write configuration: %#x\n", val);
@@ -172,14 +180,14 @@ static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw,
dev_dbg(clk->dev, "current configuration: %#x\n", val);
/* Check if PLL is disabled */
if (val & CGU_PLL_CTRL_PD)
return 0;
/* Check if PLL is bypassed */
if (val & CGU_PLL_CTRL_BYPASS)
return parent_rate;
/* Check if PLL is disabled */
if (val & CGU_PLL_CTRL_PD)
return 0;
/* input divider = reg.idiv + 1 */
idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT);
/* fb divider = 2*(reg.fbdiv + 1) */

Fájl megtekintése

@@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Silicon Labs Si5341/Si5340 Clock generator
* Driver for Silicon Labs Si5340, Si5341, Si5342, Si5344 and Si5345
* Copyright (C) 2019 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*
* The Si5341 has 10 outputs and 5 synthesizers.
* The Si5340 is a smaller version of the Si5341 with only 4 outputs.
* The Si5345 is similar to the Si5341, with the addition of fractional input
* dividers and automatic input selection.
* The Si5342 and Si5344 are smaller versions of the Si5345.
*/
#include <linux/clk.h>
@@ -18,11 +24,17 @@
#define SI5341_NUM_INPUTS 4
#define SI5341_MAX_NUM_OUTPUTS 10
#define SI5340_MAX_NUM_OUTPUTS 4
#define SI5341_MAX_NUM_OUTPUTS 10
#define SI5342_MAX_NUM_OUTPUTS 2
#define SI5344_MAX_NUM_OUTPUTS 4
#define SI5345_MAX_NUM_OUTPUTS 10
#define SI5341_NUM_SYNTH 5
#define SI5340_NUM_SYNTH 4
#define SI5341_NUM_SYNTH 5
#define SI5342_NUM_SYNTH 2
#define SI5344_NUM_SYNTH 4
#define SI5345_NUM_SYNTH 5
/* Range of the synthesizer fractional divider */
#define SI5341_SYNTH_N_MIN 10
@@ -65,6 +77,7 @@ struct clk_si5341 {
u64 freq_vco; /* 1350014256 MHz */
u8 num_outputs;
u8 num_synth;
u16 chip_id;
};
#define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw)
@@ -142,6 +155,7 @@ static const char * const si5341_input_clock_names[] = {
};
/* Output configuration registers 0..9 are not quite logically organized */
/* Also for si5345 */
static const u16 si5341_reg_output_offset[] = {
0x0108,
0x010D,
@@ -155,6 +169,7 @@ static const u16 si5341_reg_output_offset[] = {
0x013A,
};
/* for si5340, si5342 and si5344 */
static const u16 si5340_reg_output_offset[] = {
0x0112,
0x0117,
@@ -974,12 +989,32 @@ static int si5341_probe_chip_id(struct clk_si5341 *data)
data->reg_output_offset = si5341_reg_output_offset;
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
break;
case 0x5342:
data->num_outputs = SI5342_MAX_NUM_OUTPUTS;
data->num_synth = SI5342_NUM_SYNTH;
data->reg_output_offset = si5340_reg_output_offset;
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
break;
case 0x5344:
data->num_outputs = SI5344_MAX_NUM_OUTPUTS;
data->num_synth = SI5344_NUM_SYNTH;
data->reg_output_offset = si5340_reg_output_offset;
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
break;
case 0x5345:
data->num_outputs = SI5345_MAX_NUM_OUTPUTS;
data->num_synth = SI5345_NUM_SYNTH;
data->reg_output_offset = si5341_reg_output_offset;
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
break;
default:
dev_err(&data->i2c_client->dev, "Model '%x' not supported\n",
model);
return -EINVAL;
}
data->chip_id = model;
return 0;
}
@@ -1054,6 +1089,11 @@ static const struct si5341_reg_default si5341_preamble[] = {
{ 0x0B4E, 0x1A },
};
static const struct si5341_reg_default si5345_preamble[] = {
{ 0x0B25, 0x00 },
{ 0x0540, 0x01 },
};
static int si5341_send_preamble(struct clk_si5341 *data)
{
int res;
@@ -1068,8 +1108,14 @@ static int si5341_send_preamble(struct clk_si5341 *data)
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xD8 : 0xC0);
if (res < 0)
return res;
res = si5341_write_multiple(data,
si5341_preamble, ARRAY_SIZE(si5341_preamble));
/* The si5342..si5345 require a different preamble */
if (data->chip_id > 0x5341)
res = si5341_write_multiple(data,
si5345_preamble, ARRAY_SIZE(si5345_preamble));
else
res = si5341_write_multiple(data,
si5341_preamble, ARRAY_SIZE(si5341_preamble));
if (res < 0)
return res;
@@ -1095,6 +1141,13 @@ static int si5341_finalize_defaults(struct clk_si5341 *data)
if (res < 0)
return res;
/* The si5342..si5345 have an additional post-amble */
if (data->chip_id > 0x5341) {
res = regmap_write(data->regmap, 0x540, 0x0);
if (res < 0)
return res;
}
/* Datasheet does not explain these nameless registers */
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xDB : 0xC3);
if (res < 0)
@@ -1499,6 +1552,9 @@ static int si5341_probe(struct i2c_client *client,
static const struct i2c_device_id si5341_id[] = {
{ "si5340", 0 },
{ "si5341", 1 },
{ "si5342", 2 },
{ "si5344", 4 },
{ "si5345", 5 },
{ }
};
MODULE_DEVICE_TABLE(i2c, si5341_id);
@@ -1506,6 +1562,9 @@ MODULE_DEVICE_TABLE(i2c, si5341_id);
static const struct of_device_id clk_si5341_of_match[] = {
{ .compatible = "silabs,si5340" },
{ .compatible = "silabs,si5341" },
{ .compatible = "silabs,si5342" },
{ .compatible = "silabs,si5344" },
{ .compatible = "silabs,si5345" },
{ }
};
MODULE_DEVICE_TABLE(of, clk_si5341_of_match);

Fájl megtekintése

@@ -124,6 +124,7 @@ enum vc5_model {
IDT_VC5_5P49V5933,
IDT_VC5_5P49V5935,
IDT_VC6_5P49V6901,
IDT_VC6_5P49V6965,
};
/* Structure to describe features of a particular VC5 model */
@@ -683,6 +684,7 @@ static int vc5_map_index_to_output(const enum vc5_model model,
case IDT_VC5_5P49V5925:
case IDT_VC5_5P49V5935:
case IDT_VC6_5P49V6901:
case IDT_VC6_5P49V6965:
default:
return n;
}
@@ -956,12 +958,20 @@ static const struct vc5_chip_info idt_5p49v6901_info = {
.flags = VC5_HAS_PFD_FREQ_DBL,
};
static const struct vc5_chip_info idt_5p49v6965_info = {
.model = IDT_VC6_5P49V6965,
.clk_fod_cnt = 4,
.clk_out_cnt = 5,
.flags = 0,
};
static const struct i2c_device_id vc5_id[] = {
{ "5p49v5923", .driver_data = IDT_VC5_5P49V5923 },
{ "5p49v5925", .driver_data = IDT_VC5_5P49V5925 },
{ "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
{ "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
{ "5p49v6901", .driver_data = IDT_VC6_5P49V6901 },
{ "5p49v6965", .driver_data = IDT_VC6_5P49V6965 },
{ }
};
MODULE_DEVICE_TABLE(i2c, vc5_id);
@@ -972,6 +982,7 @@ static const struct of_device_id clk_vc5_of_match[] = {
{ .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info },
{ .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info },
{ .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info },
{ .compatible = "idt,5p49v6965", .data = &idt_5p49v6965_info },
{ },
};
MODULE_DEVICE_TABLE(of, clk_vc5_of_match);

Fájl megtekintése

@@ -3299,10 +3299,6 @@ static int __init clk_debug_init(void)
late_initcall(clk_debug_init);
#else
static inline void clk_debug_register(struct clk_core *core) { }
static inline void clk_debug_reparent(struct clk_core *core,
struct clk_core *new_parent)
{
}
static inline void clk_debug_unregister(struct clk_core *core)
{
}

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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;

Fájl megtekintése

@@ -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) {

Fájl megtekintése

@@ -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())

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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)

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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, \

Fájl megtekintése

@@ -55,6 +55,16 @@ config INGENIC_CGU_X1000
If building for a X1000 SoC, you want to say Y here.
config INGENIC_CGU_X1830
bool "Ingenic X1830 CGU driver"
default MACH_X1830
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic X1830
and compatible SoCs.
If building for a X1830 SoC, you want to say Y here.
config INGENIC_TCU_CLK
bool "Ingenic JZ47xx TCU clocks driver"
default MACH_INGENIC

Fájl megtekintése

@@ -5,4 +5,5 @@ obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o
obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o
obj-$(CONFIG_INGENIC_CGU_X1830) += x1830-cgu.o
obj-$(CONFIG_INGENIC_TCU_CLK) += tcu.o

Fájl megtekintése

@@ -76,16 +76,13 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
const struct ingenic_cgu_pll_info *pll_info;
unsigned m, n, od_enc, od;
bool bypass;
unsigned long flags;
u32 ctl;
clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);
pll_info = &clk_info->pll;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
spin_unlock_irqrestore(&cgu->lock, flags);
m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0);
m += pll_info->m_offset;
@@ -93,6 +90,9 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
ctl = readl(cgu->base + pll_info->bypass_reg);
bypass = !pll_info->no_bypass_bit &&
!!(ctl & BIT(pll_info->bypass_bit));
@@ -106,7 +106,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
BUG_ON(od == pll_info->od_max);
od++;
return div_u64((u64)parent_rate * m, n * od);
return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
n * od);
}
static unsigned long
@@ -139,7 +140,8 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
if (pod)
*pod = od;
return div_u64((u64)parent_rate * m, n * od);
return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
n * od);
}
static inline const struct ingenic_cgu_clk_info *to_clk_info(
@@ -212,9 +214,14 @@ static int ingenic_pll_enable(struct clk_hw *hw)
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
ctl = readl(cgu->base + pll_info->bypass_reg);
ctl &= ~BIT(pll_info->bypass_bit);
writel(ctl, cgu->base + pll_info->bypass_reg);
ctl = readl(cgu->base + pll_info->reg);
ctl |= BIT(pll_info->enable_bit);
writel(ctl, cgu->base + pll_info->reg);
@@ -259,12 +266,9 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long flags;
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
spin_unlock_irqrestore(&cgu->lock, flags);
return !!(ctl & BIT(pll_info->enable_bit));
}
@@ -562,16 +566,12 @@ static int ingenic_clk_is_enabled(struct clk_hw *hw)
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long flags;
int enabled = 1;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_GATE) {
spin_lock_irqsave(&cgu->lock, flags);
if (clk_info->type & CGU_CLK_GATE)
enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
spin_unlock_irqrestore(&cgu->lock, flags);
}
return enabled;
}

Fájl megtekintése

@@ -17,6 +17,7 @@
/**
* struct ingenic_cgu_pll_info - information about a PLL
* @reg: the offset of the PLL's control register within the CGU
* @rate_multiplier: the multiplier needed by pll rate calculation
* @m_shift: the number of bits to shift the multiplier value by (ie. the
* index of the lowest bit of the multiplier value in the PLL's
* control register)
@@ -37,6 +38,7 @@
* @od_encoding: a pointer to an array mapping post-VCO divider values to
* their encoded values in the PLL control register, or -1 for
* unsupported values
* @bypass_reg: the offset of the bypass control register within the CGU
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
@@ -44,10 +46,12 @@
*/
struct ingenic_cgu_pll_info {
unsigned reg;
unsigned rate_multiplier;
const s8 *od_encoding;
u8 m_shift, m_bits, m_offset;
u8 n_shift, n_bits, n_offset;
u8 od_shift, od_bits, od_max;
unsigned bypass_reg;
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;

Fájl megtekintése

@@ -9,7 +9,9 @@
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4725b-cgu.h>
#include "cgu.h"
#include "pm.h"
@@ -54,6 +56,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
.rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
@@ -65,6 +68,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},

Fájl megtekintése

@@ -10,7 +10,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4740-cgu.h>
#include "cgu.h"
#include "pm.h"
@@ -69,6 +71,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.parents = { JZ4740_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
.rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
@@ -80,6 +83,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},

Fájl megtekintése

@@ -9,7 +9,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4770-cgu.h>
#include "cgu.h"
#include "pm.h"
@@ -102,6 +104,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR0,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -112,6 +115,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR0,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
@@ -124,6 +128,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR1,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -134,9 +139,10 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR1,
.no_bypass_bit = true,
.enable_bit = 7,
.stable_bit = 6,
.no_bypass_bit = true,
},
},

Fájl megtekintése

@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <dt-bindings/clock/jz4780-cgu.h>
#include "cgu.h"
#include "pm.h"
@@ -266,6 +267,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
#define DEF_PLL(name) { \
.reg = CGU_REG_ ## name, \
.rate_multiplier = 1, \
.m_shift = 19, \
.m_bits = 13, \
.m_offset = 1, \
@@ -277,6 +279,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
.od_max = 16, \
.od_encoding = pll_od_encoding, \
.stable_bit = 6, \
.bypass_reg = CGU_REG_ ## name, \
.bypass_bit = 1, \
.enable_bit = 0, \
}

Fájl megtekintése

@@ -323,7 +323,7 @@ static const struct ingenic_soc_info x1000_soc_info = {
.has_tcu_clk = false,
};
static const struct of_device_id ingenic_tcu_of_match[] __initconst = {
static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = {
{ .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
{ .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
{ .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, },

Fájl megtekintése

@@ -1,13 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/*
* X1000 SoC CGU driver
* Copyright (c) 2019 Zhou Yanjie <zhouyanjie@zoho.com>
* Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/x1000-cgu.h>
#include "cgu.h"
#include "pm.h"
@@ -18,6 +21,9 @@
#define CGU_REG_CLKGR 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_DDRCDR 0x2c
#define CGU_REG_USBPCR 0x3c
#define CGU_REG_USBPCR1 0x48
#define CGU_REG_USBCDR 0x50
#define CGU_REG_MACCDR 0x54
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
@@ -38,8 +44,47 @@
#define OPCR_SPENDN0 BIT(7)
#define OPCR_SPENDN1 BIT(6)
/* bits within the USBPCR register */
#define USBPCR_SIDDQ BIT(21)
#define USBPCR_OTG_DISABLE BIT(20)
static struct ingenic_cgu *cgu;
static int x1000_usb_phy_enable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
return 0;
}
static void x1000_usb_phy_disable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
}
static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
return (readl(reg_opcr) & OPCR_SPENDN0) &&
!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
}
static const struct clk_ops x1000_otg_phy_ops = {
.enable = x1000_usb_phy_enable,
.disable = x1000_usb_phy_disable,
.is_enabled = x1000_usb_phy_is_enabled,
};
static const s8 pll_od_encoding[8] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
};
@@ -58,6 +103,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_APLL,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -68,6 +114,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_APLL,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
@@ -79,6 +126,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_MPLL,
.rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -89,12 +137,22 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_MPLL,
.bypass_bit = 6,
.enable_bit = 7,
.stable_bit = 0,
},
},
/* Custom (SoC-specific) OTG PHY */
[X1000_CLK_OTGPHY] = {
"otg_phy", CGU_CLK_CUSTOM,
.parents = { -1, -1, X1000_CLK_EXCLK, -1 },
.custom = { &x1000_otg_phy_ops },
},
/* Muxes & dividers */
[X1000_CLK_SCLKA] = {
@@ -110,9 +168,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_CPU] = {
"cpu", CGU_CLK_DIV,
"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR, 30 },
},
[X1000_CLK_L2CACHE] = {
@@ -141,9 +200,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_PCLK] = {
"pclk", CGU_CLK_DIV,
"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
.gate = { CGU_REG_CLKGR, 28 },
},
[X1000_CLK_DDR] = {
@@ -156,12 +216,20 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_MAC] = {
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_MACCDR, 31, 1 },
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 25 },
},
[X1000_CLK_LCD] = {
"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_LPCDR, 31, 1 },
.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
.gate = { CGU_REG_CLKGR, 23 },
},
[X1000_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
@@ -182,6 +250,15 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 5 },
},
[X1000_CLK_OTG] = {
"otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
.parents = { X1000_CLK_EXCLK, -1,
X1000_CLK_APLL, X1000_CLK_MPLL },
.mux = { CGU_REG_USBCDR, 30, 2 },
.div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 3 },
},
[X1000_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
@@ -189,14 +266,32 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
},
[X1000_CLK_SSIPLL_DIV2] = {
"ssi_pll_div2", CGU_CLK_FIXDIV,
.parents = { X1000_CLK_SSIPLL },
.fixdiv = { 2 },
},
[X1000_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL, -1, -1 },
.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
.mux = { CGU_REG_SSICDR, 30, 1 },
},
/* Gate-only clocks */
[X1000_CLK_EMC] = {
"emc", CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 0 },
},
[X1000_CLK_EFUSE] = {
"efuse", CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 1 },
},
[X1000_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
@@ -239,12 +334,24 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 16 },
},
[X1000_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 18 },
},
[X1000_CLK_SSI] = {
"ssi", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 19 },
},
[X1000_CLK_OST] = {
"ost", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 20 },
},
[X1000_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
@@ -271,4 +378,8 @@ static void __init x1000_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
/*
* CGU has some children devices, this is useful for probing children devices
* in the case where the device node is compatible with "simple-mfd".
*/
CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);

Fájl megtekintése

@@ -0,0 +1,448 @@
// SPDX-License-Identifier: GPL-2.0
/*
* X1830 SoC CGU driver
* Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <dt-bindings/clock/x1830-cgu.h>
#include "cgu.h"
#include "pm.h"
/* CGU register offsets */
#define CGU_REG_CPCCR 0x00
#define CGU_REG_CPPCR 0x0c
#define CGU_REG_APLL 0x10
#define CGU_REG_MPLL 0x14
#define CGU_REG_CLKGR0 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_CLKGR1 0x28
#define CGU_REG_DDRCDR 0x2c
#define CGU_REG_USBPCR 0x3c
#define CGU_REG_USBRDT 0x40
#define CGU_REG_USBVBFIL 0x44
#define CGU_REG_USBPCR1 0x48
#define CGU_REG_MACCDR 0x54
#define CGU_REG_EPLL 0x58
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
#define CGU_REG_MSC0CDR 0x68
#define CGU_REG_I2SCDR1 0x70
#define CGU_REG_SSICDR 0x74
#define CGU_REG_CIMCDR 0x7c
#define CGU_REG_MSC1CDR 0xa4
#define CGU_REG_CMP_INTR 0xb0
#define CGU_REG_CMP_INTRE 0xb4
#define CGU_REG_DRCG 0xd0
#define CGU_REG_CPCSR 0xd4
#define CGU_REG_VPLL 0xe0
#define CGU_REG_MACPHYC 0xe8
/* bits within the OPCR register */
#define OPCR_GATE_USBPHYCLK BIT(23)
#define OPCR_SPENDN0 BIT(7)
#define OPCR_SPENDN1 BIT(6)
/* bits within the USBPCR register */
#define USBPCR_SIDDQ BIT(21)
#define USBPCR_OTG_DISABLE BIT(20)
static struct ingenic_cgu *cgu;
static int x1830_usb_phy_enable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel((readl(reg_opcr) | OPCR_SPENDN0) & ~OPCR_GATE_USBPHYCLK, reg_opcr);
writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
return 0;
}
static void x1830_usb_phy_disable(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
writel((readl(reg_opcr) & ~OPCR_SPENDN0) | OPCR_GATE_USBPHYCLK, reg_opcr);
writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
}
static int x1830_usb_phy_is_enabled(struct clk_hw *hw)
{
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
return (readl(reg_opcr) & OPCR_SPENDN0) &&
!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
}
static const struct clk_ops x1830_otg_phy_ops = {
.enable = x1830_usb_phy_enable,
.disable = x1830_usb_phy_disable,
.is_enabled = x1830_usb_phy_is_enabled,
};
static const s8 pll_od_encoding[64] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
-1, -1, -1, -1, -1, -1, -1, 0x4,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 0x5,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 0x6,
};
static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = {
/* External clocks */
[X1830_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
[X1830_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
/* PLLs */
[X1830_CLK_APLL] = {
"apll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_APLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 30,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_MPLL] = {
"mpll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_MPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 28,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_EPLL] = {
"epll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_EPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 24,
.enable_bit = 0,
.stable_bit = 3,
},
},
[X1830_CLK_VPLL] = {
"vpll", CGU_CLK_PLL,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_VPLL,
.rate_multiplier = 2,
.m_shift = 20,
.m_bits = 9,
.m_offset = 1,
.n_shift = 14,
.n_bits = 6,
.n_offset = 1,
.od_shift = 11,
.od_bits = 3,
.od_max = 64,
.od_encoding = pll_od_encoding,
.bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 26,
.enable_bit = 0,
.stable_bit = 3,
},
},
/* Custom (SoC-specific) OTG PHY */
[X1830_CLK_OTGPHY] = {
"otg_phy", CGU_CLK_CUSTOM,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.custom = { &x1830_otg_phy_ops },
},
/* Muxes & dividers */
[X1830_CLK_SCLKA] = {
"sclk_a", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_EXCLK, X1830_CLK_APLL, -1 },
.mux = { CGU_REG_CPCCR, 30, 2 },
},
[X1830_CLK_CPUMUX] = {
"cpu_mux", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 28, 2 },
},
[X1830_CLK_CPU] = {
"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR1, 15 },
},
[X1830_CLK_L2CACHE] = {
"l2cache", CGU_CLK_DIV,
.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
},
[X1830_CLK_AHB0] = {
"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 26, 2 },
.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
},
[X1830_CLK_AHB2PMUX] = {
"ahb2_apb_mux", CGU_CLK_MUX,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_CPCCR, 24, 2 },
},
[X1830_CLK_AHB2] = {
"ahb2", CGU_CLK_DIV,
.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
},
[X1830_CLK_PCLK] = {
"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
.gate = { CGU_REG_CLKGR1, 14 },
},
[X1830_CLK_DDR] = {
"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
.mux = { CGU_REG_DDRCDR, 30, 2 },
.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 31 },
},
[X1830_CLK_MAC] = {
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_MACCDR, 30, 2 },
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR1, 4 },
},
[X1830_CLK_LCD] = {
"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_LPCDR, 30, 2 },
.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
.gate = { CGU_REG_CLKGR1, 9 },
},
[X1830_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_MSC0CDR, 30, 2 },
},
[X1830_CLK_MSC0] = {
"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 4 },
},
[X1830_CLK_MSC1] = {
"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR0, 5 },
},
[X1830_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
X1830_CLK_VPLL, X1830_CLK_EPLL },
.mux = { CGU_REG_SSICDR, 30, 2 },
.div = { CGU_REG_SSICDR, 0, 1, 8, 28, 27, 26 },
},
[X1830_CLK_SSIPLL_DIV2] = {
"ssi_pll_div2", CGU_CLK_FIXDIV,
.parents = { X1830_CLK_SSIPLL },
.fixdiv = { 2 },
},
[X1830_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
.parents = { X1830_CLK_EXCLK, X1830_CLK_SSIPLL_DIV2, -1, -1 },
.mux = { CGU_REG_SSICDR, 29, 1 },
},
/* Gate-only clocks */
[X1830_CLK_EMC] = {
"emc", CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 0 },
},
[X1830_CLK_EFUSE] = {
"efuse", CGU_CLK_GATE,
.parents = { X1830_CLK_AHB2, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 1 },
},
[X1830_CLK_OTG] = {
"otg", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 3 },
},
[X1830_CLK_SSI0] = {
"ssi0", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 6 },
},
[X1830_CLK_SMB0] = {
"smb0", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 7 },
},
[X1830_CLK_SMB1] = {
"smb1", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 8 },
},
[X1830_CLK_SMB2] = {
"smb2", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 9 },
},
[X1830_CLK_UART0] = {
"uart0", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 14 },
},
[X1830_CLK_UART1] = {
"uart1", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 15 },
},
[X1830_CLK_SSI1] = {
"ssi1", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 19 },
},
[X1830_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
.parents = { X1830_CLK_SSIPLL, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 20 },
},
[X1830_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 21 },
},
[X1830_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR0, 30 },
},
[X1830_CLK_DTRNG] = {
"dtrng", CGU_CLK_GATE,
.parents = { X1830_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR1, 1 },
},
[X1830_CLK_OST] = {
"ost", CGU_CLK_GATE,
.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR1, 11 },
},
};
static void __init x1830_cgu_init(struct device_node *np)
{
int retval;
cgu = ingenic_cgu_new(x1830_cgu_clocks,
ARRAY_SIZE(x1830_cgu_clocks), np);
if (!cgu) {
pr_err("%s: failed to initialise CGU\n", __func__);
return;
}
retval = ingenic_cgu_register_clocks(cgu);
if (retval) {
pr_err("%s: failed to register CGU Clocks\n", __func__);
return;
}
ingenic_cgu_register_syscore_ops(cgu);
}
/*
* CGU has some children devices, this is useful for probing children devices
* in the case where the device node is compatible with "simple-mfd".
*/
CLK_OF_DECLARE_DRIVER(x1830_cgu, "ingenic,x1830-cgu", x1830_cgu_init);

Fájl megtekintése

@@ -117,6 +117,92 @@ config COMMON_CLK_MT2712_VENCSYS
---help---
This driver supports MediaTek MT2712 vencsys clocks.
config COMMON_CLK_MT6765
bool "Clock driver for MediaTek MT6765"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
help
This driver supports MediaTek MT6765 basic clocks.
config COMMON_CLK_MT6765_AUDIOSYS
bool "Clock driver for MediaTek MT6765 audiosys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 audiosys clocks.
config COMMON_CLK_MT6765_CAMSYS
bool "Clock driver for MediaTek MT6765 camsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 camsys clocks.
config COMMON_CLK_MT6765_GCESYS
bool "Clock driver for MediaTek MT6765 gcesys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 gcesys clocks.
config COMMON_CLK_MT6765_MMSYS
bool "Clock driver for MediaTek MT6765 mmsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mmsys clocks.
config COMMON_CLK_MT6765_IMGSYS
bool "Clock driver for MediaTek MT6765 imgsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 imgsys clocks.
config COMMON_CLK_MT6765_VCODECSYS
bool "Clock driver for MediaTek MT6765 vcodecsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 vcodecsys clocks.
config COMMON_CLK_MT6765_MFGSYS
bool "Clock driver for MediaTek MT6765 mfgsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mfgsys clocks.
config COMMON_CLK_MT6765_MIPI0ASYS
bool "Clock driver for MediaTek MT6765 mipi0asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi0asys clocks.
config COMMON_CLK_MT6765_MIPI0BSYS
bool "Clock driver for MediaTek MT6765 mipi0bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi0bsys clocks.
config COMMON_CLK_MT6765_MIPI1ASYS
bool "Clock driver for MediaTek MT6765 mipi1asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi1asys clocks.
config COMMON_CLK_MT6765_MIPI1BSYS
bool "Clock driver for MediaTek MT6765 mipi1bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi1bsys clocks.
config COMMON_CLK_MT6765_MIPI2ASYS
bool "Clock driver for MediaTek MT6765 mipi2asys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi2asys clocks.
config COMMON_CLK_MT6765_MIPI2BSYS
bool "Clock driver for MediaTek MT6765 mipi2bsys"
depends on COMMON_CLK_MT6765
help
This driver supports MediaTek MT6765 mipi2bsys clocks.
config COMMON_CLK_MT6779
bool "Clock driver for MediaTek MT6779"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST

Fájl megtekintése

@@ -1,6 +1,13 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o
obj-$(CONFIG_COMMON_CLK_MT6765_IMGSYS) += clk-mt6765-img.o
obj-$(CONFIG_COMMON_CLK_MT6765_MIPI0ASYS) += clk-mt6765-mipi0a.o
obj-$(CONFIG_COMMON_CLK_MT6765_MMSYS) += clk-mt6765-mm.o
obj-$(CONFIG_COMMON_CLK_MT6765_VCODECSYS) += clk-mt6765-vcodec.o
obj-$(CONFIG_COMMON_CLK_MT6779) += clk-mt6779.o
obj-$(CONFIG_COMMON_CLK_MT6779_MMSYS) += clk-mt6779-mm.o
obj-$(CONFIG_COMMON_CLK_MT6779_IMGSYS) += clk-mt6779-img.o

Fájl megtekintése

@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs audio0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs audio1_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x4,
.sta_ofs = 0x4,
};
#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate audio_clks[] = {
/* AUDIO0 */
GATE_AUDIO0(CLK_AUDIO_AFE, "aud_afe", "audio_ck", 2),
GATE_AUDIO0(CLK_AUDIO_22M, "aud_22m", "aud_engen1_ck", 8),
GATE_AUDIO0(CLK_AUDIO_APLL_TUNER, "aud_apll_tuner",
"aud_engen1_ck", 19),
GATE_AUDIO0(CLK_AUDIO_ADC, "aud_adc", "audio_ck", 24),
GATE_AUDIO0(CLK_AUDIO_DAC, "aud_dac", "audio_ck", 25),
GATE_AUDIO0(CLK_AUDIO_DAC_PREDIS, "aud_dac_predis",
"audio_ck", 26),
GATE_AUDIO0(CLK_AUDIO_TML, "aud_tml", "audio_ck", 27),
/* AUDIO1 */
GATE_AUDIO1(CLK_AUDIO_I2S1_BCLK, "aud_i2s1_bclk",
"audio_ck", 4),
GATE_AUDIO1(CLK_AUDIO_I2S2_BCLK, "aud_i2s2_bclk",
"audio_ck", 5),
GATE_AUDIO1(CLK_AUDIO_I2S3_BCLK, "aud_i2s3_bclk",
"audio_ck", 6),
GATE_AUDIO1(CLK_AUDIO_I2S4_BCLK, "aud_i2s4_bclk",
"audio_ck", 7),
};
static int clk_mt6765_audio_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
mtk_clk_register_gates(node, audio_clks,
ARRAY_SIZE(audio_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_audio[] = {
{ .compatible = "mediatek,mt6765-audsys", },
{}
};
static struct platform_driver clk_mt6765_audio_drv = {
.probe = clk_mt6765_audio_probe,
.driver = {
.name = "clk-mt6765-audio",
.of_match_table = of_match_clk_mt6765_audio,
},
};
builtin_platform_driver(clk_mt6765_audio_drv);

Fájl megtekintése

@@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs cam_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_CAM(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &cam_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate cam_clks[] = {
GATE_CAM(CLK_CAM_LARB3, "cam_larb3", "mm_ck", 0),
GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "mm_ck", 1),
GATE_CAM(CLK_CAM, "cam", "mm_ck", 6),
GATE_CAM(CLK_CAMTG, "camtg", "mm_ck", 7),
GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "mm_ck", 8),
GATE_CAM(CLK_CAMSV0, "camsv0", "mm_ck", 9),
GATE_CAM(CLK_CAMSV1, "camsv1", "mm_ck", 10),
GATE_CAM(CLK_CAMSV2, "camsv2", "mm_ck", 11),
GATE_CAM(CLK_CAM_CCU, "cam_ccu", "mm_ck", 12),
};
static int clk_mt6765_cam_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK);
mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_cam[] = {
{ .compatible = "mediatek,mt6765-camsys", },
{}
};
static struct platform_driver clk_mt6765_cam_drv = {
.probe = clk_mt6765_cam_probe,
.driver = {
.name = "clk-mt6765-cam",
.of_match_table = of_match_clk_mt6765_cam,
},
};
builtin_platform_driver(clk_mt6765_cam_drv);

Fájl megtekintése

@@ -0,0 +1,70 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs img_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_IMG(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &img_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate img_clks[] = {
GATE_IMG(CLK_IMG_LARB2, "img_larb2", "mm_ck", 0),
GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_ck", 2),
GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_ck", 3),
GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_ck", 4),
GATE_IMG(CLK_IMG_RSC, "img_rsc", "mm_ck", 5),
};
static int clk_mt6765_img_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_img[] = {
{ .compatible = "mediatek,mt6765-imgsys", },
{}
};
static struct platform_driver clk_mt6765_img_drv = {
.probe = clk_mt6765_img_probe,
.driver = {
.name = "clk-mt6765-img",
.of_match_table = of_match_clk_mt6765_img,
},
};
builtin_platform_driver(clk_mt6765_img_drv);

Fájl megtekintése

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs mipi0a_cg_regs = {
.set_ofs = 0x80,
.clr_ofs = 0x80,
.sta_ofs = 0x80,
};
#define GATE_MIPI0A(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mipi0a_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate mipi0a_clks[] = {
GATE_MIPI0A(CLK_MIPI0A_CSR_CSI_EN_0A,
"mipi0a_csr_0a", "f_fseninf_ck", 1),
};
static int clk_mt6765_mipi0a_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MIPI0A_NR_CLK);
mtk_clk_register_gates(node, mipi0a_clks,
ARRAY_SIZE(mipi0a_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_mipi0a[] = {
{ .compatible = "mediatek,mt6765-mipi0a", },
{}
};
static struct platform_driver clk_mt6765_mipi0a_drv = {
.probe = clk_mt6765_mipi0a_probe,
.driver = {
.name = "clk-mt6765-mipi0a",
.of_match_table = of_match_clk_mt6765_mipi0a,
},
};
builtin_platform_driver(clk_mt6765_mipi0a_drv);

Fájl megtekintése

@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs mm_cg_regs = {
.set_ofs = 0x104,
.clr_ofs = 0x108,
.sta_ofs = 0x100,
};
#define GATE_MM(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mm_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate mm_clks[] = {
/* MM */
GATE_MM(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_ck", 0),
GATE_MM(CLK_MM_MDP_CCORR0, "mm_mdp_ccorr0", "mm_ck", 1),
GATE_MM(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_ck", 2),
GATE_MM(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_ck", 3),
GATE_MM(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_ck", 4),
GATE_MM(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_ck", 5),
GATE_MM(CLK_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_ck", 6),
GATE_MM(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_ck", 7),
GATE_MM(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_ck", 8),
GATE_MM(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "mm_ck", 9),
GATE_MM(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_ck", 10),
GATE_MM(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_ck", 11),
GATE_MM(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_ck", 12),
GATE_MM(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_ck", 13),
GATE_MM(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_ck", 14),
GATE_MM(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_ck", 15),
GATE_MM(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_ck", 16),
GATE_MM(CLK_MM_DSI0, "mm_dsi0", "mm_ck", 17),
GATE_MM(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_ck", 18),
GATE_MM(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_ck", 19),
GATE_MM(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_ck", 20),
GATE_MM(CLK_MM_SMI_COMM0, "mm_smi_comm0", "mm_ck", 21),
GATE_MM(CLK_MM_SMI_COMM1, "mm_smi_comm1", "mm_ck", 22),
GATE_MM(CLK_MM_CAM_MDP, "mm_cam_mdp_ck", "mm_ck", 23),
GATE_MM(CLK_MM_SMI_IMG, "mm_smi_img_ck", "mm_ck", 24),
GATE_MM(CLK_MM_SMI_CAM, "mm_smi_cam_ck", "mm_ck", 25),
GATE_MM(CLK_MM_IMG_DL_RELAY, "mm_img_dl_relay", "mm_ck", 26),
GATE_MM(CLK_MM_IMG_DL_ASYNC_TOP, "mm_imgdl_async", "mm_ck", 27),
GATE_MM(CLK_MM_DIG_DSI, "mm_dig_dsi_ck", "mm_ck", 28),
GATE_MM(CLK_MM_F26M_HRTWT, "mm_hrtwt", "f_f26m_ck", 29),
};
static int clk_mt6765_mm_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_mm[] = {
{ .compatible = "mediatek,mt6765-mmsys", },
{}
};
static struct platform_driver clk_mt6765_mm_drv = {
.probe = clk_mt6765_mm_probe,
.driver = {
.name = "clk-mt6765-mm",
.of_match_table = of_match_clk_mt6765_mm,
},
};
builtin_platform_driver(clk_mt6765_mm_drv);

Fájl megtekintése

@@ -0,0 +1,70 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6765-clk.h>
static const struct mtk_gate_regs venc_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_VENC(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &venc_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
static const struct mtk_gate venc_clks[] = {
GATE_VENC(CLK_VENC_SET0_LARB, "venc_set0_larb", "mm_ck", 0),
GATE_VENC(CLK_VENC_SET1_VENC, "venc_set1_venc", "mm_ck", 4),
GATE_VENC(CLK_VENC_SET2_JPGENC, "jpgenc", "mm_ck", 8),
GATE_VENC(CLK_VENC_SET3_VDEC, "venc_set3_vdec", "mm_ck", 12),
};
static int clk_mt6765_vcodec_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
mtk_clk_register_gates(node, venc_clks,
ARRAY_SIZE(venc_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765_vcodec[] = {
{ .compatible = "mediatek,mt6765-vcodecsys", },
{}
};
static struct platform_driver clk_mt6765_vcodec_drv = {
.probe = clk_mt6765_vcodec_probe,
.driver = {
.name = "clk-mt6765-vcodec",
.of_match_table = of_match_clk_mt6765_vcodec,
},
};
builtin_platform_driver(clk_mt6765_vcodec_drv);

Fájl megtekintése

@@ -0,0 +1,922 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 MediaTek Inc.
* Author: Owen Chen <owen.chen@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mt6765-clk.h>
/*fmeter div select 4*/
#define _DIV4_ 1
static DEFINE_SPINLOCK(mt6765_clk_lock);
/* Total 12 subsys */
static void __iomem *cksys_base;
static void __iomem *apmixed_base;
/* CKSYS */
#define CLK_SCP_CFG_0 (cksys_base + 0x200)
#define CLK_SCP_CFG_1 (cksys_base + 0x204)
/* CG */
#define AP_PLL_CON3 (apmixed_base + 0x0C)
#define PLLON_CON0 (apmixed_base + 0x44)
#define PLLON_CON1 (apmixed_base + 0x48)
/* clk cfg update */
#define CLK_CFG_0 0x40
#define CLK_CFG_0_SET 0x44
#define CLK_CFG_0_CLR 0x48
#define CLK_CFG_1 0x50
#define CLK_CFG_1_SET 0x54
#define CLK_CFG_1_CLR 0x58
#define CLK_CFG_2 0x60
#define CLK_CFG_2_SET 0x64
#define CLK_CFG_2_CLR 0x68
#define CLK_CFG_3 0x70
#define CLK_CFG_3_SET 0x74
#define CLK_CFG_3_CLR 0x78
#define CLK_CFG_4 0x80
#define CLK_CFG_4_SET 0x84
#define CLK_CFG_4_CLR 0x88
#define CLK_CFG_5 0x90
#define CLK_CFG_5_SET 0x94
#define CLK_CFG_5_CLR 0x98
#define CLK_CFG_6 0xa0
#define CLK_CFG_6_SET 0xa4
#define CLK_CFG_6_CLR 0xa8
#define CLK_CFG_7 0xb0
#define CLK_CFG_7_SET 0xb4
#define CLK_CFG_7_CLR 0xb8
#define CLK_CFG_8 0xc0
#define CLK_CFG_8_SET 0xc4
#define CLK_CFG_8_CLR 0xc8
#define CLK_CFG_9 0xd0
#define CLK_CFG_9_SET 0xd4
#define CLK_CFG_9_CLR 0xd8
#define CLK_CFG_10 0xe0
#define CLK_CFG_10_SET 0xe4
#define CLK_CFG_10_CLR 0xe8
#define CLK_CFG_UPDATE 0x004
static const struct mtk_fixed_clk fixed_clks[] = {
FIXED_CLK(CLK_TOP_F_FRTC, "f_frtc_ck", "clk32k", 32768),
FIXED_CLK(CLK_TOP_CLK26M, "clk_26m_ck", "clk26m", 26000000),
FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 466000000),
};
static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
FACTOR(CLK_TOP_USB20_192M, "usb20_192m_ck", "univpll", 2, 13),
FACTOR(CLK_TOP_USB20_192M_D4, "usb20_192m_d4", "usb20_192m_ck", 1, 4),
FACTOR(CLK_TOP_USB20_192M_D8, "usb20_192m_d8", "usb20_192m_ck", 1, 8),
FACTOR(CLK_TOP_USB20_192M_D16,
"usb20_192m_d16", "usb20_192m_ck", 1, 16),
FACTOR(CLK_TOP_USB20_192M_D32,
"usb20_192m_d32", "usb20_192m_ck", 1, 32),
FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, 2),
FACTOR(CLK_TOP_MPLL, "mpll_ck", "mpll", 1, 1),
FACTOR(CLK_TOP_DA_MPLL_104M_DIV, "mpll_104m_div", "mpll_ck", 1, 2),
FACTOR(CLK_TOP_DA_MPLL_52M_DIV, "mpll_52m_div", "mpll_ck", 1, 4),
FACTOR(CLK_TOP_MFGPLL, "mfgpll_ck", "mfgpll", 1, 1),
FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2),
FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, 4),
FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, 8),
FACTOR(CLK_TOP_ULPOSC1, "ulposc1_ck", "ulposc1", 1, 1),
FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1_ck", 1, 2),
FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1_ck", 1, 4),
FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1_ck", 1, 8),
FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1_ck", 1, 16),
FACTOR(CLK_TOP_ULPOSC1_D32, "ulposc1_d32", "ulposc1_ck", 1, 32),
FACTOR(CLK_TOP_F_F26M, "f_f26m_ck", "clk_26m_ck", 1, 1),
FACTOR(CLK_TOP_AXI, "axi_ck", "axi_sel", 1, 1),
FACTOR(CLK_TOP_MM, "mm_ck", "mm_sel", 1, 1),
FACTOR(CLK_TOP_SCP, "scp_ck", "scp_sel", 1, 1),
FACTOR(CLK_TOP_MFG, "mfg_ck", "mfg_sel", 1, 1),
FACTOR(CLK_TOP_F_FUART, "f_fuart_ck", "uart_sel", 1, 1),
FACTOR(CLK_TOP_SPI, "spi_ck", "spi_sel", 1, 1),
FACTOR(CLK_TOP_MSDC50_0, "msdc50_0_ck", "msdc50_0_sel", 1, 1),
FACTOR(CLK_TOP_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 1, 1),
FACTOR(CLK_TOP_AUDIO, "audio_ck", "audio_sel", 1, 1),
FACTOR(CLK_TOP_AUD_1, "aud_1_ck", "aud_1_sel", 1, 1),
FACTOR(CLK_TOP_AUD_ENGEN1, "aud_engen1_ck", "aud_engen1_sel", 1, 1),
FACTOR(CLK_TOP_F_FDISP_PWM, "f_fdisp_pwm_ck", "disp_pwm_sel", 1, 1),
FACTOR(CLK_TOP_SSPM, "sspm_ck", "sspm_sel", 1, 1),
FACTOR(CLK_TOP_DXCC, "dxcc_ck", "dxcc_sel", 1, 1),
FACTOR(CLK_TOP_I2C, "i2c_ck", "i2c_sel", 1, 1),
FACTOR(CLK_TOP_F_FPWM, "f_fpwm_ck", "pwm_sel", 1, 1),
FACTOR(CLK_TOP_F_FSENINF, "f_fseninf_ck", "seninf_sel", 1, 1),
FACTOR(CLK_TOP_AES_FDE, "aes_fde_ck", "aes_fde_sel", 1, 1),
FACTOR(CLK_TOP_F_BIST2FPC, "f_bist2fpc_ck", "univpll2_d2", 1, 1),
FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL0, "arm_div_pll0", "syspll_d2", 1, 1),
FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL1, "arm_div_pll1", "syspll_ck", 1, 1),
FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL2, "arm_div_pll2", "univpll_d2", 1, 1),
FACTOR(CLK_TOP_DA_USB20_48M_DIV,
"usb20_48m_div", "usb20_192m_d4", 1, 1),
FACTOR(CLK_TOP_DA_UNIV_48M_DIV, "univ_48m_div", "usb20_192m_d4", 1, 1),
};
static const char * const axi_parents[] = {
"clk26m",
"syspll_d7",
"syspll1_d4",
"syspll3_d2"
};
static const char * const mem_parents[] = {
"clk26m",
"dmpll_ck",
"apll1_ck"
};
static const char * const mm_parents[] = {
"clk26m",
"mmpll_ck",
"syspll1_d2",
"syspll_d5",
"syspll1_d4",
"univpll_d5",
"univpll1_d2",
"mmpll_d2"
};
static const char * const scp_parents[] = {
"clk26m",
"syspll4_d2",
"univpll2_d2",
"syspll1_d2",
"univpll1_d2",
"syspll_d3",
"univpll_d3"
};
static const char * const mfg_parents[] = {
"clk26m",
"mfgpll_ck",
"syspll_d3",
"univpll_d3"
};
static const char * const atb_parents[] = {
"clk26m",
"syspll1_d4",
"syspll1_d2"
};
static const char * const camtg_parents[] = {
"clk26m",
"usb20_192m_d8",
"univpll2_d8",
"usb20_192m_d4",
"univpll2_d32",
"usb20_192m_d16",
"usb20_192m_d32"
};
static const char * const uart_parents[] = {
"clk26m",
"univpll2_d8"
};
static const char * const spi_parents[] = {
"clk26m",
"syspll3_d2",
"syspll4_d2",
"syspll2_d4"
};
static const char * const msdc5hclk_parents[] = {
"clk26m",
"syspll1_d2",
"univpll1_d4",
"syspll2_d2"
};
static const char * const msdc50_0_parents[] = {
"clk26m",
"msdcpll_ck",
"syspll2_d2",
"syspll4_d2",
"univpll1_d2",
"syspll1_d2",
"univpll_d5",
"univpll1_d4"
};
static const char * const msdc30_1_parents[] = {
"clk26m",
"msdcpll_d2",
"univpll2_d2",
"syspll2_d2",
"syspll1_d4",
"univpll1_d4",
"usb20_192m_d4",
"syspll2_d4"
};
static const char * const audio_parents[] = {
"clk26m",
"syspll3_d4",
"syspll4_d4",
"syspll1_d16"
};
static const char * const aud_intbus_parents[] = {
"clk26m",
"syspll1_d4",
"syspll4_d2"
};
static const char * const aud_1_parents[] = {
"clk26m",
"apll1_ck"
};
static const char * const aud_engen1_parents[] = {
"clk26m",
"apll1_d2",
"apll1_d4",
"apll1_d8"
};
static const char * const disp_pwm_parents[] = {
"clk26m",
"univpll2_d4",
"ulposc1_d2",
"ulposc1_d8"
};
static const char * const sspm_parents[] = {
"clk26m",
"syspll1_d2",
"syspll_d3"
};
static const char * const dxcc_parents[] = {
"clk26m",
"syspll1_d2",
"syspll1_d4",
"syspll1_d8"
};
static const char * const usb_top_parents[] = {
"clk26m",
"univpll3_d4"
};
static const char * const spm_parents[] = {
"clk26m",
"syspll1_d8"
};
static const char * const i2c_parents[] = {
"clk26m",
"univpll3_d4",
"univpll3_d2",
"syspll1_d8",
"syspll2_d8"
};
static const char * const pwm_parents[] = {
"clk26m",
"univpll3_d4",
"syspll1_d8"
};
static const char * const seninf_parents[] = {
"clk26m",
"univpll1_d4",
"univpll1_d2",
"univpll2_d2"
};
static const char * const aes_fde_parents[] = {
"clk26m",
"msdcpll_ck",
"univpll_d3",
"univpll2_d2",
"univpll1_d2",
"syspll1_d2"
};
static const char * const ulposc_parents[] = {
"clk26m",
"ulposc1_d4",
"ulposc1_d8",
"ulposc1_d16",
"ulposc1_d32"
};
static const char * const camtm_parents[] = {
"clk26m",
"univpll1_d4",
"univpll1_d2",
"univpll2_d2"
};
#define INVALID_UPDATE_REG 0xFFFFFFFF
#define INVALID_UPDATE_SHIFT -1
#define INVALID_MUX_GATE -1
static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
0, 2, 7, CLK_CFG_UPDATE, 0, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR,
8, 2, 15, CLK_CFG_UPDATE, 1, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, CLK_CFG_0,
CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 3, 23,
CLK_CFG_UPDATE, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, CLK_CFG_0,
CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31,
CLK_CFG_UPDATE, 3),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, CLK_CFG_1,
CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7,
CLK_CFG_UPDATE, 4),
MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, CLK_CFG_1,
CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 2, 15,
CLK_CFG_UPDATE, 5),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel",
camtg_parents, CLK_CFG_1, CLK_CFG_1_SET,
CLK_CFG_1_CLR, 16, 3, 23, CLK_CFG_UPDATE, 6),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG1_SEL, "camtg1_sel", camtg_parents,
CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR,
24, 3, 31, CLK_CFG_UPDATE, 7),
/* CLK_CFG_2 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2_SEL, "camtg2_sel",
camtg_parents, CLK_CFG_2, CLK_CFG_2_SET,
CLK_CFG_2_CLR, 0, 3, 7, CLK_CFG_UPDATE, 8),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3_SEL, "camtg3_sel", camtg_parents,
CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR,
8, 3, 15, CLK_CFG_UPDATE, 9),
MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 1, 23,
CLK_CFG_UPDATE, 10),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, CLK_CFG_2,
CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 2, 31,
CLK_CFG_UPDATE, 11),
/* CLK_CFG_3 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk",
msdc5hclk_parents, CLK_CFG_3, CLK_CFG_3_SET,
CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
msdc50_0_parents, CLK_CFG_3, CLK_CFG_3_SET,
CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
msdc30_1_parents, CLK_CFG_3, CLK_CFG_3_SET,
CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR,
24, 2, 31, CLK_CFG_UPDATE, 15),
/* CLK_CFG_4 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
aud_intbus_parents, CLK_CFG_4, CLK_CFG_4_SET,
CLK_CFG_4_CLR, 0, 2, 7, CLK_CFG_UPDATE, 16),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents,
CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR,
8, 1, 15, CLK_CFG_UPDATE, 17),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel",
aud_engen1_parents, CLK_CFG_4, CLK_CFG_4_SET,
CLK_CFG_4_CLR, 16, 2, 23, CLK_CFG_UPDATE, 18),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel",
disp_pwm_parents, CLK_CFG_4, CLK_CFG_4_SET,
CLK_CFG_4_CLR, 24, 2, 31, CLK_CFG_UPDATE, 19),
/* CLK_CFG_5 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPM_SEL, "sspm_sel", sspm_parents,
CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7,
CLK_CFG_UPDATE, 20),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents,
CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 2, 15,
CLK_CFG_UPDATE, 21),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_SEL, "usb_top_sel",
usb_top_parents, CLK_CFG_5, CLK_CFG_5_SET,
CLK_CFG_5_CLR, 16, 1, 23, CLK_CFG_UPDATE, 22),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, CLK_CFG_5,
CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31,
CLK_CFG_UPDATE, 23),
/* CLK_CFG_6 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, CLK_CFG_6,
CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 3, 7, CLK_CFG_UPDATE,
24),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, CLK_CFG_6,
CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 2, 15, CLK_CFG_UPDATE,
25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel", seninf_parents,
CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 2, 23,
CLK_CFG_UPDATE, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_FDE_SEL, "aes_fde_sel",
aes_fde_parents, CLK_CFG_6, CLK_CFG_6_SET,
CLK_CFG_6_CLR, 24, 3, 31, CLK_CFG_UPDATE, 27),
/* CLK_CFG_7 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRAP_ULPOSC_SEL, "ulposc_sel",
ulposc_parents, CLK_CFG_7, CLK_CFG_7_SET,
CLK_CFG_7_CLR, 0, 3, 7, CLK_CFG_UPDATE, 28,
CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", camtm_parents,
CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 8, 2, 15,
CLK_CFG_UPDATE, 29),
};
static const struct mtk_gate_regs top0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs top1_cg_regs = {
.set_ofs = 0x104,
.clr_ofs = 0x104,
.sta_ofs = 0x104,
};
static const struct mtk_gate_regs top2_cg_regs = {
.set_ofs = 0x320,
.clr_ofs = 0x320,
.sta_ofs = 0x320,
};
#define GATE_TOP0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_TOP1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
#define GATE_TOP2(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top2_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate top_clks[] = {
/* TOP0 */
GATE_TOP0(CLK_TOP_MD_32K, "md_32k", "f_frtc_ck", 8),
GATE_TOP0(CLK_TOP_MD_26M, "md_26m", "f_f26m_ck", 9),
GATE_TOP0(CLK_TOP_MD2_32K, "md2_32k", "f_frtc_ck", 10),
GATE_TOP0(CLK_TOP_MD2_26M, "md2_26m", "f_f26m_ck", 11),
/* TOP1 */
GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL0_EN,
"arm_div_pll0_en", "arm_div_pll0", 3),
GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL1_EN,
"arm_div_pll1_en", "arm_div_pll1", 4),
GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL2_EN,
"arm_div_pll2_en", "arm_div_pll2", 5),
GATE_TOP1(CLK_TOP_FMEM_OCC_DRC_EN, "drc_en", "univpll2_d2", 6),
GATE_TOP1(CLK_TOP_USB20_48M_EN, "usb20_48m_en", "usb20_48m_div", 8),
GATE_TOP1(CLK_TOP_UNIVPLL_48M_EN, "univpll_48m_en", "univ_48m_div", 9),
GATE_TOP1(CLK_TOP_F_UFS_MP_SAP_CFG_EN, "ufs_sap", "f_f26m_ck", 12),
GATE_TOP1(CLK_TOP_F_BIST2FPC_EN, "bist2fpc", "f_bist2fpc_ck", 16),
/* TOP2 */
GATE_TOP2(CLK_TOP_APLL12_DIV0, "apll12_div0", "aud_1_ck", 2),
GATE_TOP2(CLK_TOP_APLL12_DIV1, "apll12_div1", "aud_1_ck", 3),
GATE_TOP2(CLK_TOP_APLL12_DIV2, "apll12_div2", "aud_1_ck", 4),
GATE_TOP2(CLK_TOP_APLL12_DIV3, "apll12_div3", "aud_1_ck", 5),
};
static const struct mtk_gate_regs ifr2_cg_regs = {
.set_ofs = 0x80,
.clr_ofs = 0x84,
.sta_ofs = 0x90,
};
static const struct mtk_gate_regs ifr3_cg_regs = {
.set_ofs = 0x88,
.clr_ofs = 0x8c,
.sta_ofs = 0x94,
};
static const struct mtk_gate_regs ifr4_cg_regs = {
.set_ofs = 0xa4,
.clr_ofs = 0xa8,
.sta_ofs = 0xac,
};
static const struct mtk_gate_regs ifr5_cg_regs = {
.set_ofs = 0xc0,
.clr_ofs = 0xc4,
.sta_ofs = 0xc8,
};
#define GATE_IFR2(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &ifr2_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_IFR3(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &ifr3_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_IFR4(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &ifr4_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_IFR5(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &ifr5_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate ifr_clks[] = {
/* INFRA_TOPAXI */
/* INFRA PERI */
/* INFRA mode 0 */
GATE_IFR2(CLK_IFR_ICUSB, "ifr_icusb", "axi_ck", 8),
GATE_IFR2(CLK_IFR_GCE, "ifr_gce", "axi_ck", 9),
GATE_IFR2(CLK_IFR_THERM, "ifr_therm", "axi_ck", 10),
GATE_IFR2(CLK_IFR_I2C_AP, "ifr_i2c_ap", "i2c_ck", 11),
GATE_IFR2(CLK_IFR_I2C_CCU, "ifr_i2c_ccu", "i2c_ck", 12),
GATE_IFR2(CLK_IFR_I2C_SSPM, "ifr_i2c_sspm", "i2c_ck", 13),
GATE_IFR2(CLK_IFR_I2C_RSV, "ifr_i2c_rsv", "i2c_ck", 14),
GATE_IFR2(CLK_IFR_PWM_HCLK, "ifr_pwm_hclk", "axi_ck", 15),
GATE_IFR2(CLK_IFR_PWM1, "ifr_pwm1", "f_fpwm_ck", 16),
GATE_IFR2(CLK_IFR_PWM2, "ifr_pwm2", "f_fpwm_ck", 17),
GATE_IFR2(CLK_IFR_PWM3, "ifr_pwm3", "f_fpwm_ck", 18),
GATE_IFR2(CLK_IFR_PWM4, "ifr_pwm4", "f_fpwm_ck", 19),
GATE_IFR2(CLK_IFR_PWM5, "ifr_pwm5", "f_fpwm_ck", 20),
GATE_IFR2(CLK_IFR_PWM, "ifr_pwm", "f_fpwm_ck", 21),
GATE_IFR2(CLK_IFR_UART0, "ifr_uart0", "f_fuart_ck", 22),
GATE_IFR2(CLK_IFR_UART1, "ifr_uart1", "f_fuart_ck", 23),
GATE_IFR2(CLK_IFR_GCE_26M, "ifr_gce_26m", "f_f26m_ck", 27),
GATE_IFR2(CLK_IFR_CQ_DMA_FPC, "ifr_dma", "axi_ck", 28),
GATE_IFR2(CLK_IFR_BTIF, "ifr_btif", "axi_ck", 31),
/* INFRA mode 1 */
GATE_IFR3(CLK_IFR_SPI0, "ifr_spi0", "spi_ck", 1),
GATE_IFR3(CLK_IFR_MSDC0, "ifr_msdc0", "msdc5hclk", 2),
GATE_IFR3(CLK_IFR_MSDC1, "ifr_msdc1", "axi_ck", 4),
GATE_IFR3(CLK_IFR_TRNG, "ifr_trng", "axi_ck", 9),
GATE_IFR3(CLK_IFR_AUXADC, "ifr_auxadc", "f_f26m_ck", 10),
GATE_IFR3(CLK_IFR_CCIF1_AP, "ifr_ccif1_ap", "axi_ck", 12),
GATE_IFR3(CLK_IFR_CCIF1_MD, "ifr_ccif1_md", "axi_ck", 13),
GATE_IFR3(CLK_IFR_AUXADC_MD, "ifr_auxadc_md", "f_f26m_ck", 14),
GATE_IFR3(CLK_IFR_AP_DMA, "ifr_ap_dma", "axi_ck", 18),
GATE_IFR3(CLK_IFR_DEVICE_APC, "ifr_dapc", "axi_ck", 20),
GATE_IFR3(CLK_IFR_CCIF_AP, "ifr_ccif_ap", "axi_ck", 23),
GATE_IFR3(CLK_IFR_AUDIO, "ifr_audio", "axi_ck", 25),
GATE_IFR3(CLK_IFR_CCIF_MD, "ifr_ccif_md", "axi_ck", 26),
/* INFRA mode 2 */
GATE_IFR4(CLK_IFR_RG_PWM_FBCLK6, "ifr_pwmfb", "f_f26m_ck", 0),
GATE_IFR4(CLK_IFR_DISP_PWM, "ifr_disp_pwm", "f_fdisp_pwm_ck", 2),
GATE_IFR4(CLK_IFR_CLDMA_BCLK, "ifr_cldmabclk", "axi_ck", 3),
GATE_IFR4(CLK_IFR_AUDIO_26M_BCLK, "ifr_audio26m", "f_f26m_ck", 4),
GATE_IFR4(CLK_IFR_SPI1, "ifr_spi1", "spi_ck", 6),
GATE_IFR4(CLK_IFR_I2C4, "ifr_i2c4", "i2c_ck", 7),
GATE_IFR4(CLK_IFR_SPI2, "ifr_spi2", "spi_ck", 9),
GATE_IFR4(CLK_IFR_SPI3, "ifr_spi3", "spi_ck", 10),
GATE_IFR4(CLK_IFR_I2C5, "ifr_i2c5", "i2c_ck", 18),
GATE_IFR4(CLK_IFR_I2C5_ARBITER, "ifr_i2c5a", "i2c_ck", 19),
GATE_IFR4(CLK_IFR_I2C5_IMM, "ifr_i2c5_imm", "i2c_ck", 20),
GATE_IFR4(CLK_IFR_I2C1_ARBITER, "ifr_i2c1a", "i2c_ck", 21),
GATE_IFR4(CLK_IFR_I2C1_IMM, "ifr_i2c1_imm", "i2c_ck", 22),
GATE_IFR4(CLK_IFR_I2C2_ARBITER, "ifr_i2c2a", "i2c_ck", 23),
GATE_IFR4(CLK_IFR_I2C2_IMM, "ifr_i2c2_imm", "i2c_ck", 24),
GATE_IFR4(CLK_IFR_SPI4, "ifr_spi4", "spi_ck", 25),
GATE_IFR4(CLK_IFR_SPI5, "ifr_spi5", "spi_ck", 26),
GATE_IFR4(CLK_IFR_CQ_DMA, "ifr_cq_dma", "axi_ck", 27),
GATE_IFR4(CLK_IFR_FAES_FDE, "ifr_faes_fde_ck", "aes_fde_ck", 29),
/* INFRA mode 3 */
GATE_IFR5(CLK_IFR_MSDC0_SELF, "ifr_msdc0sf", "msdc50_0_ck", 0),
GATE_IFR5(CLK_IFR_MSDC1_SELF, "ifr_msdc1sf", "msdc50_0_ck", 1),
GATE_IFR5(CLK_IFR_I2C6, "ifr_i2c6", "i2c_ck", 6),
GATE_IFR5(CLK_IFR_AP_MSDC0, "ifr_ap_msdc0", "msdc50_0_ck", 7),
GATE_IFR5(CLK_IFR_MD_MSDC0, "ifr_md_msdc0", "msdc50_0_ck", 8),
GATE_IFR5(CLK_IFR_MSDC0_SRC, "ifr_msdc0_clk", "msdc50_0_ck", 9),
GATE_IFR5(CLK_IFR_MSDC1_SRC, "ifr_msdc1_clk", "msdc30_1_ck", 10),
GATE_IFR5(CLK_IFR_MCU_PM_BCLK, "ifr_mcu_pm_bclk", "axi_ck", 17),
GATE_IFR5(CLK_IFR_CCIF2_AP, "ifr_ccif2_ap", "axi_ck", 18),
GATE_IFR5(CLK_IFR_CCIF2_MD, "ifr_ccif2_md", "axi_ck", 19),
GATE_IFR5(CLK_IFR_CCIF3_AP, "ifr_ccif3_ap", "axi_ck", 20),
GATE_IFR5(CLK_IFR_CCIF3_MD, "ifr_ccif3_md", "axi_ck", 21),
};
/* additional CCF control for mipi26M race condition(disp/camera) */
static const struct mtk_gate_regs apmixed_cg_regs = {
.set_ofs = 0x14,
.clr_ofs = 0x14,
.sta_ofs = 0x14,
};
#define GATE_APMIXED(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &apmixed_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate apmixed_clks[] = {
/* AUDIO0 */
GATE_APMIXED(CLK_APMIXED_SSUSB26M, "apmixed_ssusb26m", "f_f26m_ck",
4),
GATE_APMIXED(CLK_APMIXED_APPLL26M, "apmixed_appll26m", "f_f26m_ck",
5),
GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", "f_f26m_ck",
6),
GATE_APMIXED(CLK_APMIXED_MDPLLGP26M, "apmixed_mdpll26m", "f_f26m_ck",
7),
GATE_APMIXED(CLK_APMIXED_MMSYS_F26M, "apmixed_mmsys26m", "f_f26m_ck",
8),
GATE_APMIXED(CLK_APMIXED_UFS26M, "apmixed_ufs26m", "f_f26m_ck",
9),
GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", "f_f26m_ck",
11),
GATE_APMIXED(CLK_APMIXED_MEMPLL26M, "apmixed_mempll26m", "f_f26m_ck",
13),
GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m",
"f_f26m_ck", 14),
GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", "f_f26m_ck",
16),
};
#define MT6765_PLL_FMAX (3800UL * MHZ)
#define MT6765_PLL_FMIN (1500UL * MHZ)
#define CON0_MT6765_RST_BAR BIT(23)
#define PLL_INFO_NULL (0xFF)
#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pcwibits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,\
_tuner_en_bit, _pcw_reg, _pcw_shift, _div_table) {\
.id = _id, \
.name = _name, \
.reg = _reg, \
.pwr_reg = _pwr_reg, \
.en_mask = _en_mask, \
.flags = _flags, \
.rst_bar_mask = CON0_MT6765_RST_BAR, \
.fmax = MT6765_PLL_FMAX, \
.fmin = MT6765_PLL_FMIN, \
.pcwbits = _pcwbits, \
.pcwibits = _pcwibits, \
.pd_reg = _pd_reg, \
.pd_shift = _pd_shift, \
.tuner_reg = _tuner_reg, \
.tuner_en_reg = _tuner_en_reg, \
.tuner_en_bit = _tuner_en_bit, \
.pcw_reg = _pcw_reg, \
.pcw_shift = _pcw_shift, \
.div_table = _div_table, \
}
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pcwibits, _pd_reg, _pd_shift, _tuner_reg, \
_tuner_en_reg, _tuner_en_bit, _pcw_reg, \
_pcw_shift) \
PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \
_pcwbits, _pcwibits, _pd_reg, _pd_shift, \
_tuner_reg, _tuner_en_reg, _tuner_en_bit, \
_pcw_reg, _pcw_shift, NULL) \
static const struct mtk_pll_data plls[] = {
PLL(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x021C, 0x0228, BIT(0),
PLL_AO, 22, 8, 0x0220, 24, 0, 0, 0, 0x0220, 0),
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x020C, 0x0218, BIT(0),
PLL_AO, 22, 8, 0x0210, 24, 0, 0, 0, 0x0210, 0),
PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x022C, 0x0238, BIT(0),
PLL_AO, 22, 8, 0x0230, 24, 0, 0, 0, 0x0230, 0),
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x023C, 0x0248, BIT(0),
(HAVE_RST_BAR | PLL_AO), 22, 8, 0x0240, 24, 0, 0, 0, 0x0240,
0),
PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x024C, 0x0258, BIT(0),
0, 22, 8, 0x0250, 24, 0, 0, 0, 0x0250, 0),
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x025C, 0x0268, BIT(0),
0, 22, 8, 0x0260, 24, 0, 0, 0, 0x0260, 0),
PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x026C, 0x0278, BIT(0),
HAVE_RST_BAR, 22, 8, 0x0270, 24, 0, 0, 0, 0x0270, 0),
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x027C, 0x0288, BIT(0),
0, 22, 8, 0x0280, 24, 0, 0, 0, 0x0280, 0),
PLL(CLK_APMIXED_APLL1, "apll1", 0x028C, 0x029C, BIT(0),
0, 32, 8, 0x0290, 24, 0x0040, 0x000C, 0, 0x0294, 0),
PLL(CLK_APMIXED_MPLL, "mpll", 0x02A0, 0x02AC, BIT(0),
PLL_AO, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0),
};
static int clk_mt6765_apmixed_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
void __iomem *base;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) {
pr_err("%s(): ioremap failed\n", __func__);
return PTR_ERR(base);
}
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
mtk_clk_register_gates(node, apmixed_clks,
ARRAY_SIZE(apmixed_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
apmixed_base = base;
/* MPLL, CCIPLL, MAINPLL set HW mode, TDCLKSQ, CLKSQ1 */
writel(readl(AP_PLL_CON3) & 0xFFFFFFE1, AP_PLL_CON3);
writel(readl(PLLON_CON0) & 0x01041041, PLLON_CON0);
writel(readl(PLLON_CON1) & 0x01041041, PLLON_CON1);
return r;
}
static int clk_mt6765_top_probe(struct platform_device *pdev)
{
int r;
struct device_node *node = pdev->dev.of_node;
void __iomem *base;
struct clk_onecell_data *clk_data;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) {
pr_err("%s(): ioremap failed\n", __func__);
return PTR_ERR(base);
}
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
clk_data);
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
clk_data);
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
&mt6765_clk_lock, clk_data);
mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
cksys_base = base;
/* [4]:no need */
writel(readl(CLK_SCP_CFG_0) | 0x3EF, CLK_SCP_CFG_0);
/*[1,2,3,8]: no need*/
writel(readl(CLK_SCP_CFG_1) | 0x1, CLK_SCP_CFG_1);
return r;
}
static int clk_mt6765_ifr_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
void __iomem *base;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) {
pr_err("%s(): ioremap failed\n", __func__);
return PTR_ERR(base);
}
clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK);
mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt6765[] = {
{
.compatible = "mediatek,mt6765-apmixedsys",
.data = clk_mt6765_apmixed_probe,
}, {
.compatible = "mediatek,mt6765-topckgen",
.data = clk_mt6765_top_probe,
}, {
.compatible = "mediatek,mt6765-infracfg",
.data = clk_mt6765_ifr_probe,
}, {
/* sentinel */
}
};
static int clk_mt6765_probe(struct platform_device *pdev)
{
int (*clk_probe)(struct platform_device *d);
int r;
clk_probe = of_device_get_match_data(&pdev->dev);
if (!clk_probe)
return -EINVAL;
r = clk_probe(pdev);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static struct platform_driver clk_mt6765_drv = {
.probe = clk_mt6765_probe,
.driver = {
.name = "clk-mt6765",
.owner = THIS_MODULE,
.of_match_table = of_match_clk_mt6765,
},
};
static int __init clk_mt6765_init(void)
{
return platform_driver_register(&clk_mt6765_drv);
}
arch_initcall(clk_mt6765_init);

Fájl megtekintése

@@ -160,7 +160,7 @@ struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
spinlock_t *lock)
{
struct mtk_clk_mux *clk_mux;
struct clk_init_data init;
struct clk_init_data init = {};
struct clk *clk;
clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);

Fájl megtekintése

@@ -3702,7 +3702,9 @@ static struct clk_regmap g12a_hdmi = {
/*
* The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
* muxed by a glitch-free switch.
* muxed by a glitch-free switch. The CCF can manage this glitch-free
* mux because it does top-to-bottom updates the each clock tree and
* switches to the "inactive" one when CLK_SET_RATE_GATE is set.
*/
static const struct clk_parent_data g12a_mali_0_1_parent_data[] = {
{ .fw_name = "xtal", },
@@ -3726,7 +3728,13 @@ static struct clk_regmap g12a_mali_0_sel = {
.ops = &clk_regmap_mux_ops,
.parent_data = g12a_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
/*
* Don't request the parent to change the rate because
* all GPU frequencies can be derived from the fclk_*
* clocks and one special GP0_PLL setting. This is
* important because we need the MPLL clocks for audio.
*/
.flags = 0,
},
};
@@ -3743,7 +3751,7 @@ static struct clk_regmap g12a_mali_0_div = {
&g12a_mali_0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -3759,7 +3767,7 @@ static struct clk_regmap g12a_mali_0 = {
&g12a_mali_0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
@@ -3774,7 +3782,13 @@ static struct clk_regmap g12a_mali_1_sel = {
.ops = &clk_regmap_mux_ops,
.parent_data = g12a_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
/*
* Don't request the parent to change the rate because
* all GPU frequencies can be derived from the fclk_*
* clocks and one special GP0_PLL setting. This is
* important because we need the MPLL clocks for audio.
*/
.flags = 0,
},
};
@@ -3791,7 +3805,7 @@ static struct clk_regmap g12a_mali_1_div = {
&g12a_mali_1_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -3807,7 +3821,7 @@ static struct clk_regmap g12a_mali_1 = {
&g12a_mali_1_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
@@ -3827,7 +3841,7 @@ static struct clk_regmap g12a_mali = {
.ops = &clk_regmap_mux_ops,
.parent_hws = g12a_mali_parent_hws,
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};

Fájl megtekintése

@@ -957,7 +957,9 @@ static struct clk_regmap gxbb_sar_adc_clk = {
/*
* The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
* muxed by a glitch-free switch.
* muxed by a glitch-free switch. The CCF can manage this glitch-free
* mux because it does top-to-bottom updates the each clock tree and
* switches to the "inactive" one when CLK_SET_RATE_GATE is set.
*/
static const struct clk_parent_data gxbb_mali_0_1_parent_data[] = {
@@ -980,14 +982,15 @@ static struct clk_regmap gxbb_mali_0_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_0_sel",
.ops = &clk_regmap_mux_ops,
/*
* bits 10:9 selects from 8 possible parents:
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
* fclk_div4, fclk_div3, fclk_div5
*/
.parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
/*
* Don't request the parent to change the rate because
* all GPU frequencies can be derived from the fclk_*
* clocks and one special GP0_PLL setting. This is
* important because we need the MPLL clocks for audio.
*/
.flags = 0,
},
};
@@ -1004,7 +1007,7 @@ static struct clk_regmap gxbb_mali_0_div = {
&gxbb_mali_0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1020,7 +1023,7 @@ static struct clk_regmap gxbb_mali_0 = {
&gxbb_mali_0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
@@ -1033,14 +1036,15 @@ static struct clk_regmap gxbb_mali_1_sel = {
.hw.init = &(struct clk_init_data){
.name = "mali_1_sel",
.ops = &clk_regmap_mux_ops,
/*
* bits 10:9 selects from 8 possible parents:
* xtal, gp0_pll, mpll2, mpll1, fclk_div7,
* fclk_div4, fclk_div3, fclk_div5
*/
.parent_data = gxbb_mali_0_1_parent_data,
.num_parents = 8,
.flags = CLK_SET_RATE_NO_REPARENT,
/*
* Don't request the parent to change the rate because
* all GPU frequencies can be derived from the fclk_*
* clocks and one special GP0_PLL setting. This is
* important because we need the MPLL clocks for audio.
*/
.flags = 0,
},
};
@@ -1057,7 +1061,7 @@ static struct clk_regmap gxbb_mali_1_div = {
&gxbb_mali_1_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -1073,7 +1077,7 @@ static struct clk_regmap gxbb_mali_1 = {
&gxbb_mali_1_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
@@ -1093,7 +1097,7 @@ static struct clk_regmap gxbb_mali = {
.ops = &clk_regmap_mux_ops,
.parent_hws = gxbb_mali_parent_hws,
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};

Fájl megtekintése

@@ -1077,7 +1077,7 @@ static struct clk_regmap meson8b_vid_pll_in_sel = {
* Meson8m2: vid2_pll
*/
.parent_hws = (const struct clk_hw *[]) {
&meson8b_hdmi_pll_dco.hw
&meson8b_hdmi_pll_lvds_out.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1213,7 +1213,7 @@ static struct clk_regmap meson8b_vclk_in_en = {
static struct clk_regmap meson8b_vclk_div1_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 0,
},
.hw.init = &(struct clk_init_data){
@@ -1243,7 +1243,7 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = {
static struct clk_regmap meson8b_vclk_div2_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 1,
},
.hw.init = &(struct clk_init_data){
@@ -1273,7 +1273,7 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = {
static struct clk_regmap meson8b_vclk_div4_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 2,
},
.hw.init = &(struct clk_init_data){
@@ -1303,7 +1303,7 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = {
static struct clk_regmap meson8b_vclk_div6_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 3,
},
.hw.init = &(struct clk_init_data){
@@ -1333,7 +1333,7 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = {
static struct clk_regmap meson8b_vclk_div12_div_gate = {
.data = &(struct clk_regmap_gate_data){
.offset = HHI_VID_CLK_DIV,
.offset = HHI_VID_CLK_CNTL,
.bit_idx = 4,
},
.hw.init = &(struct clk_init_data){
@@ -1725,7 +1725,7 @@ static struct clk_regmap meson8b_hdmi_sys_sel = {
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_sys_sel",
.ops = &clk_regmap_mux_ro_ops,
.ops = &clk_regmap_mux_ops,
/* FIXME: all other parents are unknown */
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
@@ -1745,7 +1745,7 @@ static struct clk_regmap meson8b_hdmi_sys_div = {
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_sys_div",
.ops = &clk_regmap_divider_ro_ops,
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&meson8b_hdmi_sys_sel.hw
},
@@ -1761,7 +1761,7 @@ static struct clk_regmap meson8b_hdmi_sys = {
},
.hw.init = &(struct clk_init_data) {
.name = "hdmi_sys",
.ops = &clk_regmap_gate_ro_ops,
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) {
&meson8b_hdmi_sys_div.hw
},
@@ -1918,6 +1918,13 @@ static struct clk_regmap meson8b_mali = {
},
};
static const struct reg_sequence meson8m2_gp_pll_init_regs[] = {
{ .reg = HHI_GP_PLL_CNTL2, .def = 0x59c88000 },
{ .reg = HHI_GP_PLL_CNTL3, .def = 0xca463823 },
{ .reg = HHI_GP_PLL_CNTL4, .def = 0x0286a027 },
{ .reg = HHI_GP_PLL_CNTL5, .def = 0x00003000 },
};
static const struct pll_params_table meson8m2_gp_pll_params_table[] = {
PLL_PARAMS(182, 3),
{ /* sentinel */ },
@@ -1951,6 +1958,8 @@ static struct clk_regmap meson8m2_gp_pll_dco = {
.width = 1,
},
.table = meson8m2_gp_pll_params_table,
.init_regs = meson8m2_gp_pll_init_regs,
.init_count = ARRAY_SIZE(meson8m2_gp_pll_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "gp_pll_dco",
@@ -2063,7 +2072,7 @@ static struct clk_regmap meson8b_vpu_0 = {
&meson8b_vpu_0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
@@ -2134,10 +2143,18 @@ static struct clk_regmap meson8b_vpu_1 = {
&meson8b_vpu_1_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
},
};
/*
* The VPU clock has two two identical clock trees (vpu_0 and vpu_1)
* muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
* actually manage this glitch-free mux because it does top-to-bottom
* updates the each clock tree and switches to the "inactive" one when
* CLK_SET_RATE_GATE is set.
* Meson8 only has vpu_0 and no glitch-free mux.
*/
static struct clk_regmap meson8b_vpu = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_VPU_CLK_CNTL,
@@ -2152,7 +2169,7 @@ static struct clk_regmap meson8b_vpu = {
&meson8b_vpu_1.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -3506,54 +3523,87 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
static const struct meson8b_clk_reset_line {
u32 reg;
u8 bit_idx;
bool active_low;
} meson8b_clk_reset_bits[] = {
[CLKC_RESET_L2_CACHE_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 30,
.active_low = false,
},
[CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 29,
.active_low = false,
},
[CLKC_RESET_SCU_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 28,
.active_low = false,
},
[CLKC_RESET_CPU3_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 27,
.active_low = false,
},
[CLKC_RESET_CPU2_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 26,
.active_low = false,
},
[CLKC_RESET_CPU1_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 25,
.active_low = false,
},
[CLKC_RESET_CPU0_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 24,
.active_low = false,
},
[CLKC_RESET_A5_GLOBAL_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 18,
.active_low = false,
},
[CLKC_RESET_A5_AXI_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 17,
.active_low = false,
},
[CLKC_RESET_A5_ABP_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16
.reg = HHI_SYS_CPU_CLK_CNTL0,
.bit_idx = 16,
.active_low = false,
},
[CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = {
.reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30
.reg = HHI_SYS_CPU_CLK_CNTL1,
.bit_idx = 30,
.active_low = false,
},
[CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = {
.reg = HHI_VID_CLK_CNTL, .bit_idx = 15
.reg = HHI_VID_CLK_CNTL,
.bit_idx = 15,
.active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = {
.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7
.reg = HHI_VID_DIVIDER_CNTL,
.bit_idx = 7,
.active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = {
.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3
.reg = HHI_VID_DIVIDER_CNTL,
.bit_idx = 3,
.active_low = false,
},
[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = {
.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1
.reg = HHI_VID_DIVIDER_CNTL,
.bit_idx = 1,
.active_low = true,
},
[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = {
.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0
.reg = HHI_VID_DIVIDER_CNTL,
.bit_idx = 0,
.active_low = true,
},
};
@@ -3562,22 +3612,22 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
{
struct meson8b_clk_reset *meson8b_clk_reset =
container_of(rcdev, struct meson8b_clk_reset, reset);
unsigned long flags;
const struct meson8b_clk_reset_line *reset;
unsigned int value = 0;
unsigned long flags;
if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
return -EINVAL;
reset = &meson8b_clk_reset_bits[id];
if (assert != reset->active_low)
value = BIT(reset->bit_idx);
spin_lock_irqsave(&meson_clk_lock, flags);
if (assert)
regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
BIT(reset->bit_idx), BIT(reset->bit_idx));
else
regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
BIT(reset->bit_idx), 0);
regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
BIT(reset->bit_idx), value);
spin_unlock_irqrestore(&meson_clk_lock, flags);

Fájl megtekintése

@@ -20,6 +20,10 @@
* [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
*/
#define HHI_GP_PLL_CNTL 0x40 /* 0x10 offset in data sheet */
#define HHI_GP_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */
#define HHI_GP_PLL_CNTL3 0x48 /* 0x12 offset in data sheet */
#define HHI_GP_PLL_CNTL4 0x4C /* 0x13 offset in data sheet */
#define HHI_GP_PLL_CNTL5 0x50 /* 0x14 offset in data sheet */
#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
#define HHI_GCLK_MPEG0 0x140 /* 0x50 offset in data sheet */
@@ -146,7 +150,6 @@
#define CLKID_CTS_VDAC0 171
#define CLKID_HDMI_SYS_SEL 172
#define CLKID_HDMI_SYS_DIV 173
#define CLKID_HDMI_SYS 174
#define CLKID_MALI_0_SEL 175
#define CLKID_MALI_0_DIV 176
#define CLKID_MALI_0 177

Fájl megtekintése

@@ -8,7 +8,8 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o
obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o

443
drivers/clk/mmp/clk-audio.c Normal file
Fájl megtekintése

@@ -0,0 +1,443 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MMP Audio Clock Controller driver
*
* Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_clock.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <dt-bindings/clock/marvell,mmp2-audio.h>
/* Audio Controller Registers */
#define SSPA_AUD_CTRL 0x04
#define SSPA_AUD_PLL_CTRL0 0x08
#define SSPA_AUD_PLL_CTRL1 0x0c
/* SSPA Audio Control Register */
#define SSPA_AUD_CTRL_SYSCLK_SHIFT 0
#define SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT 1
#define SSPA_AUD_CTRL_SSPA0_MUX_SHIFT 7
#define SSPA_AUD_CTRL_SSPA0_SHIFT 8
#define SSPA_AUD_CTRL_SSPA0_DIV_SHIFT 9
#define SSPA_AUD_CTRL_SSPA1_SHIFT 16
#define SSPA_AUD_CTRL_SSPA1_DIV_SHIFT 17
#define SSPA_AUD_CTRL_SSPA1_MUX_SHIFT 23
#define SSPA_AUD_CTRL_DIV_MASK 0x7e
/* SSPA Audio PLL Control 0 Register */
#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK (0x7 << 28)
#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(x) ((x) << 28)
#define SSPA_AUD_PLL_CTRL0_FRACT_MASK (0xfffff << 8)
#define SSPA_AUD_PLL_CTRL0_FRACT(x) ((x) << 8)
#define SSPA_AUD_PLL_CTRL0_ENA_DITHER (1 << 7)
#define SSPA_AUD_PLL_CTRL0_ICP_2UA (0 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_5UA (1 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_7UA (2 << 5)
#define SSPA_AUD_PLL_CTRL0_ICP_10UA (3 << 5)
#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK (0x3 << 3)
#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(x) ((x) << 3)
#define SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK (0x1 << 2)
#define SSPA_AUD_PLL_CTRL0_DIV_MCLK(x) ((x) << 2)
#define SSPA_AUD_PLL_CTRL0_PD_OVPROT_DIS (1 << 1)
#define SSPA_AUD_PLL_CTRL0_PU (1 << 0)
/* SSPA Audio PLL Control 1 Register */
#define SSPA_AUD_PLL_CTRL1_SEL_FAST_CLK (1 << 24)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK (1 << 11)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL (1 << 11)
#define SSPA_AUD_PLL_CTRL1_CLK_SEL_VCXO (0 << 11)
#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK (0x7ff << 0)
#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(x) ((x) << 0)
struct mmp2_audio_clk {
void __iomem *mmio_base;
struct clk_hw audio_pll_hw;
struct clk_mux sspa_mux;
struct clk_mux sspa1_mux;
struct clk_divider sysclk_div;
struct clk_divider sspa0_div;
struct clk_divider sspa1_div;
struct clk_gate sysclk_gate;
struct clk_gate sspa0_gate;
struct clk_gate sspa1_gate;
u32 aud_ctrl;
u32 aud_pll_ctrl0;
u32 aud_pll_ctrl1;
spinlock_t lock;
/* Must be last */
struct clk_hw_onecell_data clk_data;
};
static const struct {
unsigned long parent_rate;
unsigned long freq_vco;
unsigned char mclk;
unsigned char fbcclk;
unsigned short fract;
} predivs[] = {
{ 26000000, 135475200, 0, 0, 0x8a18 },
{ 26000000, 147456000, 0, 1, 0x0da1 },
{ 38400000, 135475200, 1, 2, 0x8208 },
{ 38400000, 147456000, 1, 3, 0xaaaa },
};
static const struct {
unsigned char divisor;
unsigned char modulo;
unsigned char pattern;
} postdivs[] = {
{ 1, 3, 0, },
{ 2, 5, 0, },
{ 4, 0, 0, },
{ 6, 1, 1, },
{ 8, 1, 0, },
{ 9, 1, 2, },
{ 12, 2, 1, },
{ 16, 2, 0, },
{ 18, 2, 2, },
{ 24, 4, 1, },
{ 36, 4, 2, },
{ 48, 6, 1, },
{ 72, 6, 2, },
};
static unsigned long audio_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
unsigned int prediv;
unsigned int postdiv;
u32 aud_pll_ctrl0;
u32 aud_pll_ctrl1;
aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
aud_pll_ctrl0 &= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK |
SSPA_AUD_PLL_CTRL0_FRACT_MASK |
SSPA_AUD_PLL_CTRL0_ENA_DITHER |
SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK |
SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK |
SSPA_AUD_PLL_CTRL0_PU;
aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
aud_pll_ctrl1 &= SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK |
SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
unsigned long freq;
u32 val;
val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
val |= SSPA_AUD_PLL_CTRL0_PU;
val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
if (val != aud_pll_ctrl0)
continue;
val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
if (val != aud_pll_ctrl1)
continue;
freq = predivs[prediv].freq_vco;
freq /= postdivs[postdiv].divisor;
return freq;
}
}
return 0;
}
static long audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned int prediv;
unsigned int postdiv;
long rounded = 0;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != *parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
long freq = predivs[prediv].freq_vco;
freq /= postdivs[postdiv].divisor;
if (freq == rate)
return rate;
if (freq < rate)
continue;
if (rounded && freq > rounded)
continue;
rounded = freq;
}
}
return rounded;
}
static int audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
unsigned int prediv;
unsigned int postdiv;
unsigned long val;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
if (rate * postdivs[postdiv].divisor != predivs[prediv].freq_vco)
continue;
val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
val |= SSPA_AUD_PLL_CTRL0_PU;
val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
return 0;
}
}
return -ERANGE;
}
static const struct clk_ops audio_pll_ops = {
.recalc_rate = audio_pll_recalc_rate,
.round_rate = audio_pll_round_rate,
.set_rate = audio_pll_set_rate,
};
static int register_clocks(struct mmp2_audio_clk *priv, struct device *dev)
{
const struct clk_parent_data sspa_mux_parents[] = {
{ .hw = &priv->audio_pll_hw },
{ .fw_name = "i2s0" },
};
const struct clk_parent_data sspa1_mux_parents[] = {
{ .hw = &priv->audio_pll_hw },
{ .fw_name = "i2s1" },
};
int ret;
priv->audio_pll_hw.init = CLK_HW_INIT_FW_NAME("audio_pll",
"vctcxo", &audio_pll_ops,
CLK_SET_RATE_PARENT);
ret = devm_clk_hw_register(dev, &priv->audio_pll_hw);
if (ret)
return ret;
priv->sspa_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa_mux",
sspa_mux_parents, &clk_mux_ops,
CLK_SET_RATE_PARENT);
priv->sspa_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa_mux.mask = 1;
priv->sspa_mux.shift = SSPA_AUD_CTRL_SSPA0_MUX_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa_mux.hw);
if (ret)
return ret;
priv->sysclk_div.hw.init = CLK_HW_INIT_HW("sys_div",
&priv->sspa_mux.hw, &clk_divider_ops,
CLK_SET_RATE_PARENT);
priv->sysclk_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sysclk_div.shift = SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT;
priv->sysclk_div.width = 6;
priv->sysclk_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sysclk_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sysclk_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sysclk_div.hw);
if (ret)
return ret;
priv->sysclk_gate.hw.init = CLK_HW_INIT_HW("sys_clk",
&priv->sysclk_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sysclk_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sysclk_gate.bit_idx = SSPA_AUD_CTRL_SYSCLK_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sysclk_gate.hw);
if (ret)
return ret;
priv->sspa0_div.hw.init = CLK_HW_INIT_HW("sspa0_div",
&priv->sspa_mux.hw, &clk_divider_ops, 0);
priv->sspa0_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa0_div.shift = SSPA_AUD_CTRL_SSPA0_DIV_SHIFT;
priv->sspa0_div.width = 6;
priv->sspa0_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sspa0_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sspa0_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sspa0_div.hw);
if (ret)
return ret;
priv->sspa0_gate.hw.init = CLK_HW_INIT_HW("sspa0_clk",
&priv->sspa0_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sspa0_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa0_gate.bit_idx = SSPA_AUD_CTRL_SSPA0_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa0_gate.hw);
if (ret)
return ret;
priv->sspa1_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa1_mux",
sspa1_mux_parents, &clk_mux_ops,
CLK_SET_RATE_PARENT);
priv->sspa1_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_mux.mask = 1;
priv->sspa1_mux.shift = SSPA_AUD_CTRL_SSPA1_MUX_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa1_mux.hw);
if (ret)
return ret;
priv->sspa1_div.hw.init = CLK_HW_INIT_HW("sspa1_div",
&priv->sspa1_mux.hw, &clk_divider_ops, 0);
priv->sspa1_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_div.shift = SSPA_AUD_CTRL_SSPA1_DIV_SHIFT;
priv->sspa1_div.width = 6;
priv->sspa1_div.flags = CLK_DIVIDER_ONE_BASED;
priv->sspa1_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
priv->sspa1_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
ret = devm_clk_hw_register(dev, &priv->sspa1_div.hw);
if (ret)
return ret;
priv->sspa1_gate.hw.init = CLK_HW_INIT_HW("sspa1_clk",
&priv->sspa1_div.hw, &clk_gate_ops,
CLK_SET_RATE_PARENT);
priv->sspa1_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
priv->sspa1_gate.bit_idx = SSPA_AUD_CTRL_SSPA1_SHIFT;
ret = devm_clk_hw_register(dev, &priv->sspa1_gate.hw);
if (ret)
return ret;
priv->clk_data.hws[MMP2_CLK_AUDIO_SYSCLK] = &priv->sysclk_gate.hw;
priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA0] = &priv->sspa0_gate.hw;
priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA1] = &priv->sspa1_gate.hw;
priv->clk_data.num = MMP2_CLK_AUDIO_NR_CLKS;
return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
&priv->clk_data);
}
static int mmp2_audio_clk_probe(struct platform_device *pdev)
{
struct mmp2_audio_clk *priv;
int ret;
priv = devm_kzalloc(&pdev->dev,
struct_size(priv, clk_data.hws,
MMP2_CLK_AUDIO_NR_CLKS),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, priv);
priv->mmio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->mmio_base))
return PTR_ERR(priv->mmio_base);
pm_runtime_enable(&pdev->dev);
ret = pm_clk_create(&pdev->dev);
if (ret)
goto disable_pm_runtime;
ret = pm_clk_add(&pdev->dev, "audio");
if (ret)
goto destroy_pm_clk;
ret = register_clocks(priv, &pdev->dev);
if (ret)
goto destroy_pm_clk;
return 0;
destroy_pm_clk:
pm_clk_destroy(&pdev->dev);
disable_pm_runtime:
pm_runtime_disable(&pdev->dev);
return ret;
}
static int mmp2_audio_clk_remove(struct platform_device *pdev)
{
pm_clk_destroy(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
static int __maybe_unused mmp2_audio_clk_suspend(struct device *dev)
{
struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
priv->aud_ctrl = readl(priv->mmio_base + SSPA_AUD_CTRL);
priv->aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
priv->aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
pm_clk_suspend(dev);
return 0;
}
static int __maybe_unused mmp2_audio_clk_resume(struct device *dev)
{
struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
pm_clk_resume(dev);
writel(priv->aud_ctrl, priv->mmio_base + SSPA_AUD_CTRL);
writel(priv->aud_pll_ctrl0, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
writel(priv->aud_pll_ctrl1, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
return 0;
}
static const struct dev_pm_ops mmp2_audio_clk_pm_ops = {
SET_RUNTIME_PM_OPS(mmp2_audio_clk_suspend, mmp2_audio_clk_resume, NULL)
};
static const struct of_device_id mmp2_audio_clk_of_match[] = {
{ .compatible = "marvell,mmp2-audio-clock" },
{}
};
MODULE_DEVICE_TABLE(of, mmp2_audio_clk_of_match);
static struct platform_driver mmp2_audio_clk_driver = {
.driver = {
.name = "mmp2-audio-clock",
.of_match_table = of_match_ptr(mmp2_audio_clk_of_match),
.pm = &mmp2_audio_clk_pm_ops,
},
.probe = mmp2_audio_clk_probe,
.remove = mmp2_audio_clk_remove,
};
module_platform_driver(mmp2_audio_clk_driver);
MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
MODULE_DESCRIPTION("Clock driver for MMP2 Audio subsystem");
MODULE_LICENSE("GPL");

Fájl megtekintése

@@ -28,13 +28,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
u64 rate = 0, prev_rate;
int i;
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
rate = (((*prate / 10000) * factor->ftbl[i].den) /
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
rate = *prate;
rate *= factor->ftbl[i].den;
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
if (rate > drate)
break;
}
@@ -54,6 +56,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
u64 rate;
val = readl_relaxed(factor->base);
@@ -66,8 +69,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
if (!den)
return 0;
return (((parent_rate / 10000) * den) /
(num * factor->masks->factor)) * 10000;
rate = parent_rate;
rate *= den;
do_div(rate, num * factor->masks->factor);
return rate;
}
/* Configures new clock rate*/
@@ -78,12 +84,14 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long rate = 0;
unsigned long flags = 0;
u64 rate = 0;
for (i = 0; i < factor->ftbl_cnt; i++) {
rate = (((prate / 10000) * factor->ftbl[i].den) /
(factor->ftbl[i].num * factor->masks->factor)) * 10000;
rate = prate;
rate *= factor->ftbl[i].den;
do_div(rate, factor->ftbl[i].num * factor->masks->factor);
if (rate > drate)
break;
}
@@ -140,7 +148,10 @@ static int clk_factor_init(struct clk_hw *hw)
val &= ~(masks->den_mask << masks->den_shift);
val |= (factor->ftbl[0].den & masks->den_mask) <<
masks->den_shift;
}
if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
val |= masks->enable_mask;
writel(val, factor->base);
}

Fájl megtekintése

@@ -17,8 +17,10 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/of_address.h>
#include <linux/clk.h>
#include <dt-bindings/clock/marvell,mmp2.h>
#include <dt-bindings/power/marvell,mmp2.h>
#include "clk.h"
#include "reset.h"
@@ -45,6 +47,10 @@
#define APBC_SSP1 0x54
#define APBC_SSP2 0x58
#define APBC_SSP3 0x5c
#define APBC_THERMAL0 0x90
#define APBC_THERMAL1 0x98
#define APBC_THERMAL2 0x9c
#define APBC_THERMAL3 0xa0
#define APMU_SDH0 0x54
#define APMU_SDH1 0x58
#define APMU_SDH2 0xe8
@@ -55,18 +61,19 @@
#define APMU_DISP1 0x110
#define APMU_CCIC0 0x50
#define APMU_CCIC1 0xf4
#define APBC_THERMAL0 0x90
#define APBC_THERMAL1 0x98
#define APBC_THERMAL2 0x9c
#define APBC_THERMAL3 0xa0
#define APMU_USBHSIC0 0xf8
#define APMU_USBHSIC1 0xfc
#define APMU_GPU 0xcc
#define APMU_AUDIO 0x10c
#define APMU_CAMERA 0x1fc
#define MPMU_FCCR 0x8
#define MPMU_POSR 0x10
#define MPMU_UART_PLL 0x14
#define MPMU_PLL2_CR 0x34
#define MPMU_I2S0_PLL 0x40
#define MPMU_I2S1_PLL 0x44
#define MPMU_ACGR 0x1024
/* MMP3 specific below */
#define MPMU_PLL3_CR 0x50
#define MPMU_PLL3_CTRL1 0x58
@@ -82,6 +89,8 @@ enum mmp2_clk_model {
struct mmp2_clk_unit {
struct mmp_clk_unit unit;
enum mmp2_clk_model model;
struct genpd_onecell_data pd_data;
struct generic_pm_domain *pm_domains[MMP2_NR_POWER_DOMAINS];
void __iomem *mpmu_base;
void __iomem *apmu_base;
void __iomem *apbc_base;
@@ -91,6 +100,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{MMP2_CLK_CLK32, "clk32", NULL, 0, 32768},
{MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
{MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
{0, "i2s_pll", NULL, 0, 99666667},
};
static struct mmp_param_pll_clk pll_clks[] = {
@@ -139,7 +149,35 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 3521, .den = 689}, /*19.23MHZ */
};
static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
static struct mmp_clk_factor_masks i2s_factor_masks = {
.factor = 2,
.num_mask = 0x7fff,
.den_mask = 0x1fff,
.num_shift = 0,
.den_shift = 15,
.enable_mask = 0xd0000000,
};
static struct mmp_clk_factor_tbl i2s_factor_tbl[] = {
{.num = 24868, .den = 511}, /* 2.0480 MHz */
{.num = 28003, .den = 793}, /* 2.8224 MHz */
{.num = 24941, .den = 1025}, /* 4.0960 MHz */
{.num = 28003, .den = 1586}, /* 5.6448 MHz */
{.num = 31158, .den = 2561}, /* 8.1920 MHz */
{.num = 16288, .den = 1845}, /* 11.2896 MHz */
{.num = 20772, .den = 2561}, /* 12.2880 MHz */
{.num = 8144, .den = 1845}, /* 22.5792 MHz */
{.num = 10386, .den = 2561}, /* 24.5760 MHz */
};
static DEFINE_SPINLOCK(acgr_lock);
static struct mmp_param_gate_clk mpmu_gate_clks[] = {
{MMP2_CLK_I2S0, "i2s0_clk", "i2s0_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x200000, 0x200000, 0x0, 0, &acgr_lock},
{MMP2_CLK_I2S1, "i2s1_clk", "i2s1_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x100000, 0x100000, 0x0, 0, &acgr_lock},
};
static void mmp2_main_clk_init(struct mmp2_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
@@ -166,6 +204,20 @@ static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl), NULL);
mmp_clk_add(unit, MMP2_CLK_UART_PLL, clk);
mmp_clk_register_factor("i2s0_pll", "pll1_4",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_I2S0_PLL,
&i2s_factor_masks, i2s_factor_tbl,
ARRAY_SIZE(i2s_factor_tbl), NULL);
mmp_clk_register_factor("i2s1_pll", "pll1_4",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_I2S1_PLL,
&i2s_factor_masks, i2s_factor_tbl,
ARRAY_SIZE(i2s_factor_tbl), NULL);
mmp_register_gate_clks(unit, mpmu_gate_clks, pxa_unit->mpmu_base,
ARRAY_SIZE(mpmu_gate_clks));
}
static DEFINE_SPINLOCK(uart0_lock);
@@ -271,6 +323,8 @@ static u32 mmp2_gpu_bus_parent_table[] = { 0x0000, 0x0020, 0x0030,
static const char * const mmp3_gpu_bus_parent_names[] = {"pll1_4", "pll1_6", "pll1_2", "pll2_2"};
static const char * const mmp3_gpu_gc_parent_names[] = {"pll1", "pll2", "pll1_p", "pll2_p"};
static DEFINE_SPINLOCK(audio_lock);
static struct mmp_clk_mix_config ccic0_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(4, 17, 2, 6, 32),
};
@@ -326,6 +380,7 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
{MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
{MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
{MMP2_CLK_GPU_BUS, "gpu_bus_clk", "gpu_bus_mux", CLK_SET_RATE_PARENT, APMU_GPU, 0xa, 0xa, 0x0, MMP_CLK_GATE_NEED_DELAY, &gpu_lock},
{MMP2_CLK_AUDIO, "audio_clk", "audio_mix_clk", CLK_SET_RATE_PARENT, APMU_AUDIO, 0x12, 0x12, 0x0, 0, &audio_lock},
};
static struct mmp_param_gate_clk mmp2_apmu_gate_clks[] = {
@@ -423,6 +478,41 @@ static void mmp2_clk_reset_init(struct device_node *np,
mmp_clk_reset_register(np, cells, nr_resets);
}
static void mmp2_pm_domain_init(struct device_node *np,
struct mmp2_clk_unit *pxa_unit)
{
if (pxa_unit->model == CLK_MODEL_MMP3) {
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
= mmp_pm_domain_register("gpu",
pxa_unit->apmu_base + APMU_GPU,
0x0600, 0x40003, 0x18000c, 0, &gpu_lock);
} else {
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
= mmp_pm_domain_register("gpu",
pxa_unit->apmu_base + APMU_GPU,
0x8600, 0x00003, 0x00000c,
MMP_PM_DOMAIN_NO_DISABLE, &gpu_lock);
}
pxa_unit->pd_data.num_domains++;
pxa_unit->pm_domains[MMP2_POWER_DOMAIN_AUDIO]
= mmp_pm_domain_register("audio",
pxa_unit->apmu_base + APMU_AUDIO,
0x600, 0x2, 0, 0, &audio_lock);
pxa_unit->pd_data.num_domains++;
if (pxa_unit->model == CLK_MODEL_MMP3) {
pxa_unit->pm_domains[MMP3_POWER_DOMAIN_CAMERA]
= mmp_pm_domain_register("camera",
pxa_unit->apmu_base + APMU_CAMERA,
0x600, 0, 0, 0, NULL);
pxa_unit->pd_data.num_domains++;
}
pxa_unit->pd_data.domains = pxa_unit->pm_domains;
of_genpd_add_provider_onecell(np, &pxa_unit->pd_data);
}
static void __init mmp2_clk_init(struct device_node *np)
{
struct mmp2_clk_unit *pxa_unit;
@@ -454,9 +544,11 @@ static void __init mmp2_clk_init(struct device_node *np)
goto unmap_apmu_region;
}
mmp2_pm_domain_init(np, pxa_unit);
mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
mmp2_pll_init(pxa_unit);
mmp2_main_clk_init(pxa_unit);
mmp2_apb_periph_clk_init(pxa_unit);

Fájl megtekintése

@@ -3,6 +3,7 @@
#define __MACH_MMP_CLK_H
#include <linux/clk-provider.h>
#include <linux/pm_domain.h>
#include <linux/clkdev.h>
#define APBC_NO_BUS_CTRL BIT(0)
@@ -16,6 +17,7 @@ struct mmp_clk_factor_masks {
unsigned int den_mask;
unsigned int num_shift;
unsigned int den_shift;
unsigned int enable_mask;
};
struct mmp_clk_factor_tbl {
@@ -251,4 +253,13 @@ void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
int nr_clks);
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
struct clk *clk);
/* Power islands */
#define MMP_PM_DOMAIN_NO_DISABLE BIT(0)
struct generic_pm_domain *mmp_pm_domain_register(const char *name,
void __iomem *reg,
u32 power_on, u32 reset, u32 clock_enable,
unsigned int flags, spinlock_t *lock);
#endif

Fájl megtekintése

@@ -0,0 +1,115 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* MMP PMU power island support
*
* Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
*/
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/io.h>
#include "clk.h"
#define to_mmp_pm_domain(genpd) container_of(genpd, struct mmp_pm_domain, genpd)
struct mmp_pm_domain {
struct generic_pm_domain genpd;
void __iomem *reg;
spinlock_t *lock;
u32 power_on;
u32 reset;
u32 clock_enable;
unsigned int flags;
};
static int mmp_pm_domain_power_on(struct generic_pm_domain *genpd)
{
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
unsigned long flags = 0;
u32 val;
if (pm_domain->lock)
spin_lock_irqsave(pm_domain->lock, flags);
val = readl(pm_domain->reg);
/* Turn on the power island */
val |= pm_domain->power_on;
writel(val, pm_domain->reg);
/* Disable isolation */
val |= 0x100;
writel(val, pm_domain->reg);
/* Some blocks need to be reset after a power up */
if (pm_domain->reset || pm_domain->clock_enable) {
u32 after_power_on = val;
val &= ~pm_domain->reset;
writel(val, pm_domain->reg);
val |= pm_domain->clock_enable;
writel(val, pm_domain->reg);
val |= pm_domain->reset;
writel(val, pm_domain->reg);
writel(after_power_on, pm_domain->reg);
}
if (pm_domain->lock)
spin_unlock_irqrestore(pm_domain->lock, flags);
return 0;
}
static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd)
{
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
unsigned long flags = 0;
u32 val;
if (pm_domain->flags & MMP_PM_DOMAIN_NO_DISABLE)
return 0;
if (pm_domain->lock)
spin_lock_irqsave(pm_domain->lock, flags);
/* Turn off and isolate the the power island. */
val = readl(pm_domain->reg);
val &= ~pm_domain->power_on;
val &= ~0x100;
writel(val, pm_domain->reg);
if (pm_domain->lock)
spin_unlock_irqrestore(pm_domain->lock, flags);
return 0;
}
struct generic_pm_domain *mmp_pm_domain_register(const char *name,
void __iomem *reg,
u32 power_on, u32 reset, u32 clock_enable,
unsigned int flags, spinlock_t *lock)
{
struct mmp_pm_domain *pm_domain;
pm_domain = kzalloc(sizeof(*pm_domain), GFP_KERNEL);
if (!pm_domain)
return ERR_PTR(-ENOMEM);
pm_domain->reg = reg;
pm_domain->power_on = power_on;
pm_domain->reset = reset;
pm_domain->clock_enable = clock_enable;
pm_domain->flags = flags;
pm_domain->lock = lock;
pm_genpd_init(&pm_domain->genpd, NULL, true);
pm_domain->genpd.name = name;
pm_domain->genpd.power_on = mmp_pm_domain_power_on;
pm_domain->genpd.power_off = mmp_pm_domain_power_off;
return &pm_domain->genpd;
}

Fájl megtekintése

@@ -142,6 +142,14 @@ config MSM_GCC_8916
Say Y if you want to use devices such as UART, SPI i2c, USB,
SD/eMMC, display, graphics, camera etc.
config MSM_GCC_8939
tristate "MSM8939 Global Clock Controller"
select QCOM_GDSC
help
Support for the global clock controller on msm8939 devices.
Say Y if you want to use devices such as UART, SPI i2c, USB,
SD/eMMC, display, graphics, camera etc.
config MSM_GCC_8960
tristate "APQ8064/MSM8960 Global Clock Controller"
help

Fájl megtekintése

@@ -28,6 +28,7 @@ obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
obj-$(CONFIG_MSM_GCC_8939) += gcc-msm8939.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o

Fájl megtekintése

@@ -260,7 +260,7 @@ static struct clk_pll gpll0 = {
.l_reg = 0x21004,
.m_reg = 0x21008,
.n_reg = 0x2100c,
.config_reg = 0x21014,
.config_reg = 0x21010,
.mode_reg = 0x21000,
.status_reg = 0x2101c,
.status_bit = 17,
@@ -287,7 +287,7 @@ static struct clk_pll gpll1 = {
.l_reg = 0x20004,
.m_reg = 0x20008,
.n_reg = 0x2000c,
.config_reg = 0x20014,
.config_reg = 0x20010,
.mode_reg = 0x20000,
.status_reg = 0x2001c,
.status_bit = 17,
@@ -314,7 +314,7 @@ static struct clk_pll gpll2 = {
.l_reg = 0x4a004,
.m_reg = 0x4a008,
.n_reg = 0x4a00c,
.config_reg = 0x4a014,
.config_reg = 0x4a010,
.mode_reg = 0x4a000,
.status_reg = 0x4a01c,
.status_bit = 17,
@@ -341,7 +341,7 @@ static struct clk_pll bimc_pll = {
.l_reg = 0x23004,
.m_reg = 0x23008,
.n_reg = 0x2300c,
.config_reg = 0x23014,
.config_reg = 0x23010,
.mode_reg = 0x23000,
.status_reg = 0x2301c,
.status_bit = 17,

A különbségek nem kerülnek megjelenítésre, mivel a fájl túl nagy Load Diff

Fájl megtekintése

@@ -1110,6 +1110,27 @@ static struct clk_rcg2 ufs_axi_clk_src = {
},
};
static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
F(37500000, P_GPLL0_OUT_MAIN, 16, 0, 0),
F(75000000, P_GPLL0_OUT_MAIN, 8, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
{ }
};
static struct clk_rcg2 ufs_unipro_core_clk_src = {
.cmd_rcgr = 0x76028,
.mnd_width = 8,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.freq_tbl = ftbl_ufs_unipro_core_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "ufs_unipro_core_clk_src",
.parent_names = gcc_parent_names_0,
.num_parents = 4,
.ops = &clk_rcg2_ops,
},
};
static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
@@ -2549,6 +2570,11 @@ static struct clk_branch gcc_ufs_unipro_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_unipro_core_clk",
.parent_names = (const char *[]){
"ufs_unipro_core_clk_src",
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2904,6 +2930,7 @@ static struct clk_regmap *gcc_msm8998_clocks[] = {
[SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
[TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
[UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,

Fájl megtekintése

@@ -390,6 +390,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625),
F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75),
F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25),
F(51200000, P_GPLL6_OUT_MAIN, 7.5, 0, 0),
F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75),
F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15),
@@ -405,8 +406,8 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = {
.name = "gcc_qupv3_wrap0_s0_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -414,15 +415,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
.cmd_rcgr = 0x17034,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = {
.name = "gcc_qupv3_wrap0_s1_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -430,15 +431,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
.cmd_rcgr = 0x17164,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = {
.name = "gcc_qupv3_wrap0_s2_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -446,15 +447,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
.cmd_rcgr = 0x17294,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = {
.name = "gcc_qupv3_wrap0_s3_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -462,15 +463,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
.cmd_rcgr = 0x173c4,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = {
.name = "gcc_qupv3_wrap0_s4_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -478,15 +479,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
.cmd_rcgr = 0x174f4,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = {
.name = "gcc_qupv3_wrap0_s5_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -494,15 +495,15 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
.cmd_rcgr = 0x17624,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = {
.name = "gcc_qupv3_wrap1_s0_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -510,15 +511,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
.cmd_rcgr = 0x18018,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = {
.name = "gcc_qupv3_wrap1_s1_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -526,15 +527,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
.cmd_rcgr = 0x18148,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = {
.name = "gcc_qupv3_wrap1_s2_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -542,15 +543,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
.cmd_rcgr = 0x18278,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = {
.name = "gcc_qupv3_wrap1_s3_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -558,15 +559,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
.cmd_rcgr = 0x183a8,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = {
.name = "gcc_qupv3_wrap1_s4_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -574,15 +575,15 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
.cmd_rcgr = 0x184d8,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
};
static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = {
.name = "gcc_qupv3_wrap1_s5_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 4,
.parent_data = gcc_parent_data_1,
.num_parents = ARRAY_SIZE(gcc_parent_data_1),
.ops = &clk_rcg2_ops,
};
@@ -590,7 +591,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
.cmd_rcgr = 0x18608,
.mnd_width = 16,
.hid_width = 5,
.parent_map = gcc_parent_map_0,
.parent_map = gcc_parent_map_1,
.freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src,
.clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
};
@@ -816,6 +817,26 @@ static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
},
};
static const struct freq_tbl ftbl_gcc_sec_ctrl_clk_src[] = {
F(4800000, P_BI_TCXO, 4, 0, 0),
F(19200000, P_BI_TCXO, 1, 0, 0),
{ }
};
static struct clk_rcg2 gcc_sec_ctrl_clk_src = {
.cmd_rcgr = 0x3d030,
.mnd_width = 0,
.hid_width = 5,
.parent_map = gcc_parent_map_3,
.freq_tbl = ftbl_gcc_sec_ctrl_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_sec_ctrl_clk_src",
.parent_data = gcc_parent_data_3,
.num_parents = ARRAY_SIZE(gcc_parent_data_3),
.ops = &clk_rcg2_ops,
},
};
static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
.halt_reg = 0x82024,
.halt_check = BRANCH_HALT_DELAY,
@@ -2406,6 +2427,7 @@ static struct clk_regmap *gcc_sc7180_clocks[] = {
[GCC_MSS_NAV_AXI_CLK] = &gcc_mss_nav_axi_clk.clkr,
[GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr,
[GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
[GCC_SEC_CTRL_CLK_SRC] = &gcc_sec_ctrl_clk_src.clkr,
};
static const struct qcom_reset_map gcc_sc7180_resets[] = {

Fájl megtekintése

@@ -1616,6 +1616,36 @@ static struct clk_branch gcc_gpu_cfg_ahb_clk = {
},
};
static struct clk_branch gcc_gpu_gpll0_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(15),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gpll0.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(16),
.hw.init = &(struct clk_init_data){
.name = "gcc_gpu_gpll0_div_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gcc_gpu_gpll0_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_gpu_iref_clk = {
.halt_reg = 0x8c010,
.halt_check = BRANCH_HALT,
@@ -1698,6 +1728,36 @@ static struct clk_branch gcc_npu_cfg_ahb_clk = {
},
};
static struct clk_branch gcc_npu_gpll0_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(18),
.hw.init = &(struct clk_init_data){
.name = "gcc_npu_gpll0_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gpll0.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_npu_gpll0_div_clk_src = {
.clkr = {
.enable_reg = 0x52004,
.enable_mask = BIT(19),
.hw.init = &(struct clk_init_data){
.name = "gcc_npu_gpll0_div_clk_src",
.parent_hws = (const struct clk_hw *[]){
&gcc_npu_gpll0_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_npu_trig_clk = {
.halt_reg = 0x4d00c,
.halt_check = BRANCH_VOTED,
@@ -2812,6 +2872,45 @@ static struct clk_branch gcc_ufs_card_phy_aux_hw_ctl_clk = {
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_rx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x7501c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_rx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_rx_symbol_1_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x750ac,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_rx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_card_tx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x75018,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_card_tx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_card_unipro_core_clk = {
.halt_reg = 0x75058,
.halt_check = BRANCH_HALT,
@@ -2992,6 +3091,45 @@ static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = {
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x7701c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_rx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x770ac,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_rx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
/* external clocks so add BRANCH_HALT_SKIP */
static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
.halt_check = BRANCH_HALT_SKIP,
.clkr = {
.enable_reg = 0x77018,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ufs_phy_tx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
.halt_reg = 0x77058,
.halt_check = BRANCH_HALT,
@@ -3374,12 +3512,16 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
[GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
[GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
[GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
[GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
[GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr,
[GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
[GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
[GCC_NPU_AT_CLK] = &gcc_npu_at_clk.clkr,
[GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr,
[GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr,
[GCC_NPU_GPLL0_CLK_SRC] = &gcc_npu_gpll0_clk_src.clkr,
[GCC_NPU_GPLL0_DIV_CLK_SRC] = &gcc_npu_gpll0_div_clk_src.clkr,
[GCC_NPU_TRIG_CLK] = &gcc_npu_trig_clk.clkr,
[GCC_PCIE0_PHY_REFGEN_CLK] = &gcc_pcie0_phy_refgen_clk.clkr,
[GCC_PCIE1_PHY_REFGEN_CLK] = &gcc_pcie1_phy_refgen_clk.clkr,
@@ -3484,6 +3626,9 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_UFS_CARD_PHY_AUX_CLK_SRC] = &gcc_ufs_card_phy_aux_clk_src.clkr,
[GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK] =
&gcc_ufs_card_phy_aux_hw_ctl_clk.clkr,
[GCC_UFS_CARD_RX_SYMBOL_0_CLK] = &gcc_ufs_card_rx_symbol_0_clk.clkr,
[GCC_UFS_CARD_RX_SYMBOL_1_CLK] = &gcc_ufs_card_rx_symbol_1_clk.clkr,
[GCC_UFS_CARD_TX_SYMBOL_0_CLK] = &gcc_ufs_card_tx_symbol_0_clk.clkr,
[GCC_UFS_CARD_UNIPRO_CORE_CLK] = &gcc_ufs_card_unipro_core_clk.clkr,
[GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC] =
&gcc_ufs_card_unipro_core_clk_src.clkr,
@@ -3501,6 +3646,9 @@ static struct clk_regmap *gcc_sm8150_clocks[] = {
[GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
[GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
[GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
[GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
[GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
[GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
[GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
[GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] =
&gcc_ufs_phy_unipro_core_clk_src.clkr,

Fájl megtekintése

@@ -11,6 +11,7 @@
#include <linux/ktime.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "gdsc.h"
@@ -112,6 +113,12 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
int ret;
u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK;
if (status == GDSC_ON && sc->rsupply) {
ret = regulator_enable(sc->rsupply);
if (ret < 0)
return ret;
}
ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
if (ret)
return ret;
@@ -143,6 +150,13 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
ret = gdsc_poll_status(sc, status);
WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");
if (!ret && status == GDSC_OFF && sc->rsupply) {
ret = regulator_disable(sc->rsupply);
if (ret < 0)
return ret;
}
return ret;
}
@@ -371,6 +385,15 @@ int gdsc_register(struct gdsc_desc *desc,
if (!data->domains)
return -ENOMEM;
for (i = 0; i < num; i++) {
if (!scs[i] || !scs[i]->supply)
continue;
scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
if (IS_ERR(scs[i]->rsupply))
return PTR_ERR(scs[i]->rsupply);
}
data->num_domains = num;
for (i = 0; i < num; i++) {
if (!scs[i])

Fájl megtekintése

@@ -10,6 +10,7 @@
#include <linux/pm_domain.h>
struct regmap;
struct regulator;
struct reset_controller_dev;
/**
@@ -52,6 +53,9 @@ struct gdsc {
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
const char *supply;
struct regulator *rsupply;
};
struct gdsc_desc {

Fájl megtekintése

@@ -3064,7 +3064,9 @@ static struct gdsc gpu_gx_gdsc = {
.name = "gpu_gx",
},
.pwrsts = PWRSTS_OFF_ON,
.parent = &gpu_gdsc.pd,
.flags = CLAMP_IO,
.supply = "vdd-gfx",
};
static struct clk_regmap *mmcc_msm8996_clocks[] = {

Fájl megtekintése

@@ -8,6 +8,7 @@ config CLK_RENESAS
select CLK_R7S9210 if ARCH_R7S9210
select CLK_R8A73A4 if ARCH_R8A73A4
select CLK_R8A7740 if ARCH_R8A7740
select CLK_R8A7742 if ARCH_R8A7742
select CLK_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744
select CLK_R8A7745 if ARCH_R8A7745
select CLK_R8A77470 if ARCH_R8A77470
@@ -55,6 +56,10 @@ config CLK_R8A7740
select CLK_RENESAS_CPG_MSTP
select CLK_RENESAS_DIV6
config CLK_R8A7742
bool "RZ/G1H clock support" if COMPILE_TEST
select CLK_RCAR_GEN2_CPG
config CLK_R8A7743
bool "RZ/G1M clock support" if COMPILE_TEST
select CLK_RCAR_GEN2_CPG
@@ -90,12 +95,10 @@ config CLK_R8A7779
config CLK_R8A7790
bool "R-Car H2 clock support" if COMPILE_TEST
select CLK_RCAR_GEN2_CPG
select CLK_RENESAS_DIV6
config CLK_R8A7791
bool "R-Car M2-W/N clock support" if COMPILE_TEST
select CLK_RCAR_GEN2_CPG
select CLK_RENESAS_DIV6
config CLK_R8A7792
bool "R-Car V2H clock support" if COMPILE_TEST
@@ -104,7 +107,6 @@ config CLK_R8A7792
config CLK_R8A7794
bool "R-Car E2 clock support" if COMPILE_TEST
select CLK_RCAR_GEN2_CPG
select CLK_RENESAS_DIV6
config CLK_R8A7795
bool "R-Car H3 clock support" if COMPILE_TEST

Fájl megtekintése

@@ -5,6 +5,7 @@ obj-$(CONFIG_CLK_RZA1) += clk-rz.o
obj-$(CONFIG_CLK_R7S9210) += r7s9210-cpg-mssr.o
obj-$(CONFIG_CLK_R8A73A4) += clk-r8a73a4.o
obj-$(CONFIG_CLK_R8A7740) += clk-r8a7740.o
obj-$(CONFIG_CLK_R8A7742) += r8a7742-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7743) += r8a7743-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7745) += r8a7745-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77470) += r8a77470-cpg-mssr.o

Fájl megtekintése

@@ -0,0 +1,275 @@
// SPDX-License-Identifier: GPL-2.0
/*
* r8a7742 Clock Pulse Generator / Module Standby and Software Reset
*
* Copyright (C) 2020 Renesas Electronics Corp.
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7742-cpg-mssr.h>
#include "renesas-cpg-mssr.h"
#include "rcar-gen2-cpg.h"
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R8A7742_CLK_OSC,
/* External Input Clocks */
CLK_EXTAL,
CLK_USB_EXTAL,
/* Internal Core Clocks */
CLK_MAIN,
CLK_PLL0,
CLK_PLL1,
CLK_PLL3,
CLK_PLL1_DIV2,
/* Module Clocks */
MOD_CLK_BASE
};
static const struct cpg_core_clk r8a7742_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL),
DEF_INPUT("usb_extal", CLK_USB_EXTAL),
/* Internal Core Clocks */
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
/* Core Clock Outputs */
DEF_BASE("z", R8A7742_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0),
DEF_BASE("lb", R8A7742_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1),
DEF_BASE("sdh", R8A7742_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1),
DEF_BASE("sd0", R8A7742_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1),
DEF_BASE("sd1", R8A7742_CLK_SD1, CLK_TYPE_GEN2_SD1, CLK_PLL1),
DEF_BASE("qspi", R8A7742_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
DEF_BASE("rcan", R8A7742_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
DEF_FIXED("z2", R8A7742_CLK_Z2, CLK_PLL1, 2, 1),
DEF_FIXED("zg", R8A7742_CLK_ZG, CLK_PLL1, 3, 1),
DEF_FIXED("zx", R8A7742_CLK_ZX, CLK_PLL1, 3, 1),
DEF_FIXED("zs", R8A7742_CLK_ZS, CLK_PLL1, 6, 1),
DEF_FIXED("hp", R8A7742_CLK_HP, CLK_PLL1, 12, 1),
DEF_FIXED("b", R8A7742_CLK_B, CLK_PLL1, 12, 1),
DEF_FIXED("p", R8A7742_CLK_P, CLK_PLL1, 24, 1),
DEF_FIXED("cl", R8A7742_CLK_CL, CLK_PLL1, 48, 1),
DEF_FIXED("m2", R8A7742_CLK_M2, CLK_PLL1, 8, 1),
DEF_FIXED("zb3", R8A7742_CLK_ZB3, CLK_PLL3, 4, 1),
DEF_FIXED("zb3d2", R8A7742_CLK_ZB3D2, CLK_PLL3, 8, 1),
DEF_FIXED("ddr", R8A7742_CLK_DDR, CLK_PLL3, 8, 1),
DEF_FIXED("mp", R8A7742_CLK_MP, CLK_PLL1_DIV2, 15, 1),
DEF_FIXED("cp", R8A7742_CLK_CP, CLK_EXTAL, 2, 1),
DEF_FIXED("r", R8A7742_CLK_R, CLK_PLL1, 49152, 1),
DEF_FIXED("osc", R8A7742_CLK_OSC, CLK_PLL1, 12288, 1),
DEF_DIV6P1("sd2", R8A7742_CLK_SD2, CLK_PLL1_DIV2, 0x078),
DEF_DIV6P1("sd3", R8A7742_CLK_SD3, CLK_PLL1_DIV2, 0x26c),
DEF_DIV6P1("mmc0", R8A7742_CLK_MMC0, CLK_PLL1_DIV2, 0x240),
DEF_DIV6P1("mmc1", R8A7742_CLK_MMC1, CLK_PLL1_DIV2, 0x244),
};
static const struct mssr_mod_clk r8a7742_mod_clks[] __initconst = {
DEF_MOD("msiof0", 0, R8A7742_CLK_MP),
DEF_MOD("vcp1", 100, R8A7742_CLK_ZS),
DEF_MOD("vcp0", 101, R8A7742_CLK_ZS),
DEF_MOD("vpc1", 102, R8A7742_CLK_ZS),
DEF_MOD("vpc0", 103, R8A7742_CLK_ZS),
DEF_MOD("tmu1", 111, R8A7742_CLK_P),
DEF_MOD("3dg", 112, R8A7742_CLK_ZG),
DEF_MOD("2d-dmac", 115, R8A7742_CLK_ZS),
DEF_MOD("fdp1-2", 117, R8A7742_CLK_ZS),
DEF_MOD("fdp1-1", 118, R8A7742_CLK_ZS),
DEF_MOD("fdp1-0", 119, R8A7742_CLK_ZS),
DEF_MOD("tmu3", 121, R8A7742_CLK_P),
DEF_MOD("tmu2", 122, R8A7742_CLK_P),
DEF_MOD("cmt0", 124, R8A7742_CLK_R),
DEF_MOD("tmu0", 125, R8A7742_CLK_CP),
DEF_MOD("vsp1du1", 127, R8A7742_CLK_ZS),
DEF_MOD("vsp1du0", 128, R8A7742_CLK_ZS),
DEF_MOD("vsp1-sy", 131, R8A7742_CLK_ZS),
DEF_MOD("scifa2", 202, R8A7742_CLK_MP),
DEF_MOD("scifa1", 203, R8A7742_CLK_MP),
DEF_MOD("scifa0", 204, R8A7742_CLK_MP),
DEF_MOD("msiof2", 205, R8A7742_CLK_MP),
DEF_MOD("scifb0", 206, R8A7742_CLK_MP),
DEF_MOD("scifb1", 207, R8A7742_CLK_MP),
DEF_MOD("msiof1", 208, R8A7742_CLK_MP),
DEF_MOD("msiof3", 215, R8A7742_CLK_MP),
DEF_MOD("scifb2", 216, R8A7742_CLK_MP),
DEF_MOD("sys-dmac1", 218, R8A7742_CLK_ZS),
DEF_MOD("sys-dmac0", 219, R8A7742_CLK_ZS),
DEF_MOD("iic2", 300, R8A7742_CLK_HP),
DEF_MOD("tpu0", 304, R8A7742_CLK_CP),
DEF_MOD("mmcif1", 305, R8A7742_CLK_MMC1),
DEF_MOD("scif2", 310, R8A7742_CLK_P),
DEF_MOD("sdhi3", 311, R8A7742_CLK_SD3),
DEF_MOD("sdhi2", 312, R8A7742_CLK_SD2),
DEF_MOD("sdhi1", 313, R8A7742_CLK_SD1),
DEF_MOD("sdhi0", 314, R8A7742_CLK_SD0),
DEF_MOD("mmcif0", 315, R8A7742_CLK_MMC0),
DEF_MOD("iic0", 318, R8A7742_CLK_HP),
DEF_MOD("pciec", 319, R8A7742_CLK_MP),
DEF_MOD("iic1", 323, R8A7742_CLK_HP),
DEF_MOD("usb3.0", 328, R8A7742_CLK_MP),
DEF_MOD("cmt1", 329, R8A7742_CLK_R),
DEF_MOD("usbhs-dmac0", 330, R8A7742_CLK_HP),
DEF_MOD("usbhs-dmac1", 331, R8A7742_CLK_HP),
DEF_MOD("rwdt", 402, R8A7742_CLK_R),
DEF_MOD("irqc", 407, R8A7742_CLK_CP),
DEF_MOD("intc-sys", 408, R8A7742_CLK_ZS),
DEF_MOD("audio-dmac1", 501, R8A7742_CLK_HP),
DEF_MOD("audio-dmac0", 502, R8A7742_CLK_HP),
DEF_MOD("thermal", 522, CLK_EXTAL),
DEF_MOD("pwm", 523, R8A7742_CLK_P),
DEF_MOD("usb-ehci", 703, R8A7742_CLK_MP),
DEF_MOD("usbhs", 704, R8A7742_CLK_HP),
DEF_MOD("hscif1", 716, R8A7742_CLK_ZS),
DEF_MOD("hscif0", 717, R8A7742_CLK_ZS),
DEF_MOD("scif1", 720, R8A7742_CLK_P),
DEF_MOD("scif0", 721, R8A7742_CLK_P),
DEF_MOD("du2", 722, R8A7742_CLK_ZX),
DEF_MOD("du1", 723, R8A7742_CLK_ZX),
DEF_MOD("du0", 724, R8A7742_CLK_ZX),
DEF_MOD("lvds1", 725, R8A7742_CLK_ZX),
DEF_MOD("lvds0", 726, R8A7742_CLK_ZX),
DEF_MOD("r-gp2d", 807, R8A7742_CLK_ZX),
DEF_MOD("vin3", 808, R8A7742_CLK_ZG),
DEF_MOD("vin2", 809, R8A7742_CLK_ZG),
DEF_MOD("vin1", 810, R8A7742_CLK_ZG),
DEF_MOD("vin0", 811, R8A7742_CLK_ZG),
DEF_MOD("etheravb", 812, R8A7742_CLK_HP),
DEF_MOD("ether", 813, R8A7742_CLK_P),
DEF_MOD("sata1", 814, R8A7742_CLK_ZS),
DEF_MOD("sata0", 815, R8A7742_CLK_ZS),
DEF_MOD("imr-x2-1", 820, R8A7742_CLK_ZG),
DEF_MOD("imr-x2-0", 821, R8A7742_CLK_HP),
DEF_MOD("imr-lsx2-1", 822, R8A7742_CLK_P),
DEF_MOD("imr-lsx2-0", 823, R8A7742_CLK_ZS),
DEF_MOD("gpio5", 907, R8A7742_CLK_CP),
DEF_MOD("gpio4", 908, R8A7742_CLK_CP),
DEF_MOD("gpio3", 909, R8A7742_CLK_CP),
DEF_MOD("gpio2", 910, R8A7742_CLK_CP),
DEF_MOD("gpio1", 911, R8A7742_CLK_CP),
DEF_MOD("gpio0", 912, R8A7742_CLK_CP),
DEF_MOD("can1", 915, R8A7742_CLK_P),
DEF_MOD("can0", 916, R8A7742_CLK_P),
DEF_MOD("qspi_mod", 917, R8A7742_CLK_QSPI),
DEF_MOD("iicdvfs", 926, R8A7742_CLK_CP),
DEF_MOD("i2c3", 928, R8A7742_CLK_HP),
DEF_MOD("i2c2", 929, R8A7742_CLK_HP),
DEF_MOD("i2c1", 930, R8A7742_CLK_HP),
DEF_MOD("i2c0", 931, R8A7742_CLK_HP),
DEF_MOD("ssi-all", 1005, R8A7742_CLK_P),
DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
DEF_MOD("scu-all", 1017, R8A7742_CLK_P),
DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
};
static const unsigned int r8a7742_crit_mod_clks[] __initconst = {
MOD_CLK_ID(402), /* RWDT */
MOD_CLK_ID(408), /* INTC-SYS (GIC) */
};
/*
* CPG Clock Data
*/
/*
* MD EXTAL PLL0 PLL1 PLL3
* 14 13 19 (MHz) *1 *1
*---------------------------------------------------
* 0 0 0 15 x172/2 x208/2 x106
* 0 0 1 15 x172/2 x208/2 x88
* 0 1 0 20 x130/2 x156/2 x80
* 0 1 1 20 x130/2 x156/2 x66
* 1 0 0 26 / 2 x200/2 x240/2 x122
* 1 0 1 26 / 2 x200/2 x240/2 x102
* 1 1 0 30 / 2 x172/2 x208/2 x106
* 1 1 1 30 / 2 x172/2 x208/2 x88
*
* *1 : Table 7.5a indicates VCO output (PLLx = VCO/2)
*/
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
(((md) & BIT(13)) >> 12) | \
(((md) & BIT(19)) >> 19))
static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
/* EXTAL div PLL1 mult PLL3 mult */
{ 1, 208, 106, },
{ 1, 208, 88, },
{ 1, 156, 80, },
{ 1, 156, 66, },
{ 2, 240, 122, },
{ 2, 240, 102, },
{ 2, 208, 106, },
{ 2, 208, 88, },
};
static int __init r8a7742_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
u32 cpg_mode;
int error;
error = rcar_rst_read_mode_pins(&cpg_mode);
if (error)
return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
}
const struct cpg_mssr_info r8a7742_cpg_mssr_info __initconst = {
/* Core Clocks */
.core_clks = r8a7742_core_clks,
.num_core_clks = ARRAY_SIZE(r8a7742_core_clks),
.last_dt_core_clk = LAST_DT_CORE_CLK,
.num_total_core_clks = MOD_CLK_BASE,
/* Module Clocks */
.mod_clks = r8a7742_mod_clks,
.num_mod_clks = ARRAY_SIZE(r8a7742_mod_clks),
.num_hw_mod_clks = 12 * 32,
/* Critical Module Clocks */
.crit_mod_clks = r8a7742_crit_mod_clks,
.num_crit_mod_clks = ARRAY_SIZE(r8a7742_crit_mod_clks),
/* Callbacks */
.init = r8a7742_cpg_mssr_init,
.cpg_clk_register = rcar_gen2_cpg_clk_register,
};

Fájl megtekintése

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* R9A09G032 clock driver
* R9A06G032 clock driver
*
* Copyright (C) 2018 Renesas Electronics Europe Limited
*
@@ -338,8 +338,8 @@ clk_rdesc_get(struct r9a06g032_priv *clocks,
}
/*
* This implements the R9A09G032 clock gate 'driver'. We cannot use the system's
* clock gate framework as the gates on the R9A09G032 have a special enabling
* This implements the R9A06G032 clock gate 'driver'. We cannot use the system's
* clock gate framework as the gates on the R9A06G032 have a special enabling
* sequence, therefore we use this little proxy.
*/
struct r9a06g032_clk_gate {

Fájl megtekintése

@@ -673,6 +673,12 @@ static const struct of_device_id cpg_mssr_match[] = {
.data = &r7s9210_cpg_mssr_info,
},
#endif
#ifdef CONFIG_CLK_R8A7742
{
.compatible = "renesas,r8a7742-cpg-mssr",
.data = &r8a7742_cpg_mssr_info,
},
#endif
#ifdef CONFIG_CLK_R8A7743
{
.compatible = "renesas,r8a7743-cpg-mssr",
@@ -812,7 +818,8 @@ static int cpg_mssr_suspend_noirq(struct device *dev)
/* Save module registers with bits under our control */
for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
if (priv->smstpcr_saved[reg].mask)
priv->smstpcr_saved[reg].val =
priv->smstpcr_saved[reg].val = priv->stbyctrl ?
readb(priv->base + STBCR(reg)) :
readl(priv->base + SMSTPCR(reg));
}
@@ -872,8 +879,9 @@ static int cpg_mssr_resume_noirq(struct device *dev)
}
if (!i)
dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n",
priv->base + SMSTPCR(reg), oldval & mask);
dev_warn(dev, "Failed to enable %s%u[0x%x]\n",
priv->stbyctrl ? "STB" : "SMSTP", reg,
oldval & mask);
}
return 0;

Fájl megtekintése

@@ -155,6 +155,7 @@ struct cpg_mssr_info {
};
extern const struct cpg_mssr_info r7s9210_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7742_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
extern const struct cpg_mssr_info r8a77470_cpg_mssr_info;

Fájl megtekintése

@@ -540,7 +540,7 @@ static const struct samsung_div_clock exynos5800_div_clks[] __initconst = {
static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
GATE_BUS_TOP, 24, 0, 0),
GATE_BUS_TOP, 24, CLK_IS_CRITICAL, 0),
GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
};
@@ -943,25 +943,25 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg",
GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0),
GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0",
GATE_BUS_TOP, 5, 0, 0),
GATE_BUS_TOP, 5, CLK_IS_CRITICAL, 0),
GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl",
GATE_BUS_TOP, 6, CLK_IS_CRITICAL, 0),
GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl",
GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0),
GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp",
GATE_BUS_TOP, 8, 0, 0),
GATE_BUS_TOP, 8, CLK_IS_CRITICAL, 0),
GATE(CLK_PCLK66_GPIO, "pclk66_gpio", "mout_user_pclk66_gpio",
GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0),
GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen",
GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0),
GATE(0, "aclk266_isp", "mout_user_aclk266_isp",
GATE_BUS_TOP, 13, 0, 0),
GATE_BUS_TOP, 13, CLK_IS_CRITICAL, 0),
GATE(0, "aclk166", "mout_user_aclk166",
GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333",
GATE_BUS_TOP, 15, CLK_IS_CRITICAL, 0),
GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
GATE_BUS_TOP, 16, 0, 0),
GATE_BUS_TOP, 16, CLK_IS_CRITICAL, 0),
GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
GATE_BUS_TOP, 17, CLK_IS_CRITICAL, 0),
GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
@@ -1161,9 +1161,11 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
GATE_IP_GSCL1, 3, 0, 0),
GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333",
GATE_IP_GSCL1, 4, 0, 0),
GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0),
GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0),
GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12,
CLK_IS_CRITICAL, 0),
GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13,
CLK_IS_CRITICAL, 0),
GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3", "dout_gscl_blk_333",
GATE_IP_GSCL1, 16, 0, 0),
GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
GATE_IP_GSCL1, 17, 0, 0),

Fájl megtekintése

@@ -1706,7 +1706,8 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = {
GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric",
ENABLE_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_I2S1, "sclk_i2s1", "sclk_i2s1_peric",
ENABLE_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0),
ENABLE_SCLK_PERIC, 6,
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
GATE(CLK_SCLK_SPI2, "sclk_spi2", "sclk_spi2_peric", ENABLE_SCLK_PERIC,
5, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_SPI1, "sclk_spi1", "sclk_spi1_peric", ENABLE_SCLK_PERIC,

Fájl megtekintése

@@ -387,7 +387,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
ARRAY_SIZE(s3c2450_gates));
samsung_clk_register_alias(ctx, s3c2450_aliases,
ARRAY_SIZE(s3c2450_aliases));
/* fall through - as s3c2450 extends the s3c2416 clocks */
fallthrough; /* as s3c2450 extends the s3c2416 clocks */
case S3C2416:
samsung_clk_register_div(ctx, s3c2416_dividers,
ARRAY_SIZE(s3c2416_dividers));

Fájl megtekintése

@@ -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

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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);

Fájl megtekintése

@@ -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;

Fájl megtekintése

@@ -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))) {

Fájl megtekintése

@@ -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))) {

Fájl megtekintése

@@ -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))) {

Fájl megtekintése

@@ -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[] = {

Fájl megtekintése

@@ -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 *,

Some files were not shown because too many files have changed in this diff Show More