summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/meson/axg-audio.c5
-rw-r--r--drivers/clk/meson/clk-pll.c26
-rw-r--r--drivers/clk/meson/g12a.c8
-rw-r--r--drivers/clk/rockchip/clk-rk3036.c2
-rw-r--r--drivers/clk/rockchip/clk-rk3568.c10
-rw-r--r--drivers/clk/rockchip/clk.h29
-rw-r--r--drivers/clk/socfpga/clk-agilex.c93
-rw-r--r--drivers/clk/socfpga/clk-gate-s10.c119
-rw-r--r--drivers/clk/socfpga/clk-periph-s10.c11
-rw-r--r--drivers/clk/socfpga/clk-pll.c3
-rw-r--r--drivers/clk/socfpga/clk-s10.c87
-rw-r--r--drivers/clk/socfpga/stratix10-clk.h2
-rw-r--r--drivers/clk/zynqmp/clk-gate-zynqmp.c4
-rw-r--r--drivers/clk/zynqmp/clk-mux-zynqmp.c37
-rw-r--r--drivers/clk/zynqmp/clk-zynqmp.h33
-rw-r--r--drivers/clk/zynqmp/clkc.c25
-rw-r--r--drivers/clk/zynqmp/divider.c40
-rw-r--r--drivers/clk/zynqmp/pll.c28
18 files changed, 449 insertions, 113 deletions
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 7c8d02164443..bfe36bd41339 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -1665,8 +1665,7 @@ static int devm_clk_get_enable(struct device *dev, char *id)
clk = devm_clk_get(dev, id);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to get %s", id);
+ dev_err_probe(dev, ret, "failed to get %s", id);
return ret;
}
@@ -1811,7 +1810,7 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
ret = device_reset(dev);
if (ret) {
- dev_err(dev, "failed to reset device\n");
+ dev_err_probe(dev, ret, "failed to reset device\n");
return ret;
}
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 49f27fe53213..9e55617bc3b4 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -242,8 +242,8 @@ static int meson_clk_get_pll_settings(unsigned long rate,
return best ? 0 : -EINVAL;
}
-static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int meson_clk_pll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
@@ -251,22 +251,26 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long round;
int ret;
- ret = meson_clk_get_pll_settings(rate, *parent_rate, &m, &n, pll);
+ ret = meson_clk_get_pll_settings(req->rate, req->best_parent_rate,
+ &m, &n, pll);
if (ret)
- return meson_clk_pll_recalc_rate(hw, *parent_rate);
+ return ret;
- round = __pll_params_to_rate(*parent_rate, m, n, 0, pll);
+ round = __pll_params_to_rate(req->best_parent_rate, m, n, 0, pll);
- if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
- return round;
+ if (!MESON_PARM_APPLICABLE(&pll->frac) || req->rate == round) {
+ req->rate = round;
+ return 0;
+ }
/*
* The rate provided by the setting is not an exact match, let's
* try to improve the result using the fractional parameter
*/
- frac = __pll_params_with_frac(rate, *parent_rate, m, n, pll);
+ frac = __pll_params_with_frac(req->rate, req->best_parent_rate, m, n, pll);
+ req->rate = __pll_params_to_rate(req->best_parent_rate, m, n, frac, pll);
- return __pll_params_to_rate(*parent_rate, m, n, frac, pll);
+ return 0;
}
static int meson_clk_pll_wait_lock(struct clk_hw *hw)
@@ -419,7 +423,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
*/
const struct clk_ops meson_clk_pcie_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
- .round_rate = meson_clk_pll_round_rate,
+ .determine_rate = meson_clk_pll_determine_rate,
.is_enabled = meson_clk_pll_is_enabled,
.enable = meson_clk_pcie_pll_enable,
.disable = meson_clk_pll_disable
@@ -429,7 +433,7 @@ EXPORT_SYMBOL_GPL(meson_clk_pcie_pll_ops);
const struct clk_ops meson_clk_pll_ops = {
.init = meson_clk_pll_init,
.recalc_rate = meson_clk_pll_recalc_rate,
- .round_rate = meson_clk_pll_round_rate,
+ .determine_rate = meson_clk_pll_determine_rate,
.set_rate = meson_clk_pll_set_rate,
.is_enabled = meson_clk_pll_is_enabled,
.enable = meson_clk_pll_enable,
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index b080359b4645..310accf94830 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -1603,7 +1603,7 @@ static struct clk_regmap g12b_cpub_clk_trace = {
};
static const struct pll_mult_range g12a_gp0_pll_mult_range = {
- .min = 55,
+ .min = 125,
.max = 255,
};
@@ -4723,6 +4723,12 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = {
[CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw,
[CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw,
[CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw,
+ [CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel.hw,
+ [CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div.hw,
+ [CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk.hw,
+ [CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw,
+ [CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw,
+ [CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw,
[CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw,
[CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw,
[CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw,
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
index 91d56ad45817..614845cc5b4a 100644
--- a/drivers/clk/rockchip/clk-rk3036.c
+++ b/drivers/clk/rockchip/clk-rk3036.c
@@ -259,7 +259,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
RK2928_CLKGATE_CON(1), 13, GFLAGS,
&rk3036_uart2_fracmux),
- COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
+ COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0,
RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
RK2928_CLKGATE_CON(3), 11, GFLAGS),
FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4,
diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
index 946ea2f45bf3..75ca855e720d 100644
--- a/drivers/clk/rockchip/clk-rk3568.c
+++ b/drivers/clk/rockchip/clk-rk3568.c
@@ -454,17 +454,17 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
COMPOSITE_NOMUX(CPLL_125M, "cpll_125m", "cpll", CLK_IGNORE_UNUSED,
RK3568_CLKSEL_CON(80), 0, 5, DFLAGS,
RK3568_CLKGATE_CON(35), 10, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(82), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 11, GFLAGS),
COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED,
RK3568_CLKSEL_CON(80), 8, 5, DFLAGS,
- RK3568_CLKGATE_CON(35), 11, GFLAGS),
+ RK3568_CLKGATE_CON(35), 12, GFLAGS),
COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED,
RK3568_CLKSEL_CON(81), 0, 5, DFLAGS,
- RK3568_CLKGATE_CON(35), 12, GFLAGS),
+ RK3568_CLKGATE_CON(35), 13, GFLAGS),
COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED,
RK3568_CLKSEL_CON(81), 8, 6, DFLAGS,
- RK3568_CLKGATE_CON(35), 13, GFLAGS),
- COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED,
- RK3568_CLKSEL_CON(82), 0, 5, DFLAGS,
RK3568_CLKGATE_CON(35), 14, GFLAGS),
COMPOSITE_NOMUX(0, "clk_osc0_div_750k", "xin24m", CLK_IGNORE_UNUSED,
RK3568_CLKSEL_CON(82), 8, 6, DFLAGS,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 571cee7bbfdc..7aa45cc70287 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -271,17 +271,24 @@ struct rockchip_clk_provider {
struct rockchip_pll_rate_table {
unsigned long rate;
- unsigned int nr;
- unsigned int nf;
- unsigned int no;
- unsigned int nb;
- /* for RK3036/RK3399 */
- unsigned int fbdiv;
- unsigned int postdiv1;
- unsigned int refdiv;
- unsigned int postdiv2;
- unsigned int dsmpd;
- unsigned int frac;
+ union {
+ struct {
+ /* for RK3066 */
+ unsigned int nr;
+ unsigned int nf;
+ unsigned int no;
+ unsigned int nb;
+ };
+ struct {
+ /* for RK3036/RK3399 */
+ unsigned int fbdiv;
+ unsigned int postdiv1;
+ unsigned int refdiv;
+ unsigned int postdiv2;
+ unsigned int dsmpd;
+ unsigned int frac;
+ };
+ };
};
/**
diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c
index 92a6d740a799..1cb21ea79c64 100644
--- a/drivers/clk/socfpga/clk-agilex.c
+++ b/drivers/clk/socfpga/clk-agilex.c
@@ -177,6 +177,8 @@ static const struct clk_parent_data emac_mux[] = {
.name = "emaca_free_clk", },
{ .fw_name = "emacb_free_clk",
.name = "emacb_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
};
static const struct clk_parent_data noc_mux[] = {
@@ -186,6 +188,41 @@ static const struct clk_parent_data noc_mux[] = {
.name = "boot_clk", },
};
+static const struct clk_parent_data sdmmc_mux[] = {
+ { .fw_name = "sdmmc_free_clk",
+ .name = "sdmmc_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data s2f_user1_mux[] = {
+ { .fw_name = "s2f_user1_free_clk",
+ .name = "s2f_user1_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data psi_mux[] = {
+ { .fw_name = "psi_ref_free_clk",
+ .name = "psi_ref_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data gpio_db_mux[] = {
+ { .fw_name = "gpio_db_free_clk",
+ .name = "gpio_db_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data emac_ptp_mux[] = {
+ { .fw_name = "emac_ptp_free_clk",
+ .name = "emac_ptp_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,
@@ -222,11 +259,9 @@ 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},
+ 0, 0x40, 0, 0, 0},
+ { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
+ 0, 4, 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),
@@ -236,7 +271,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
{ 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},
+ ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0},
{ 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,
@@ -252,24 +287,24 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
0, 0, 0, 0, 0, 0, 4},
{ AGILEX_MPU_CCU_CLK, "mpu_ccu_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},
+ { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
+ 1, 0x44, 0, 2, 0x30, 1, 0},
+ { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
+ 2, 0x44, 8, 2, 0x30, 1, 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_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24,
+ 3, 0x44, 16, 2, 0x30, 1, 0},
+ { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
+ 4, 0x44, 24, 2, 0x30, 1, 0},
+ { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
+ 4, 0x44, 26, 2, 0x30, 1, 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_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
+ 5, 0, 0, 0, 0x30, 1, 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,
@@ -278,16 +313,16 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
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_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C,
+ 3, 0, 0, 0, 0x88, 2, 0},
+ { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C,
+ 4, 0x98, 0, 16, 0x88, 3, 0},
+ { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C,
+ 5, 0, 0, 0, 0x88, 4, 4},
+ { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C,
+ 6, 0, 0, 0, 0x88, 5, 0},
+ { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C,
+ 7, 0, 0, 0, 0x88, 6, 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,
@@ -366,7 +401,7 @@ static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks,
int i;
for (i = 0; i < nums; i++) {
- hw_clk = s10_register_gate(&clks[i], base);
+ hw_clk = agilex_register_gate(&clks[i], base);
if (IS_ERR(hw_clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
index b84f2627551e..32567795765f 100644
--- a/drivers/clk/socfpga/clk-gate-s10.c
+++ b/drivers/clk/socfpga/clk-gate-s10.c
@@ -11,6 +11,13 @@
#define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk"
#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+#define SOCFPGA_EMAC0_CLK "emac0_clk"
+#define SOCFPGA_EMAC1_CLK "emac1_clk"
+#define SOCFPGA_EMAC2_CLK "emac2_clk"
+#define AGILEX_BYPASS_OFFSET 0xC
+#define STRATIX10_BYPASS_OFFSET 0x2C
+#define BOOTCLK_BYPASS 2
+
static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
unsigned long parent_rate)
{
@@ -44,14 +51,61 @@ static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
{
struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
- u32 mask;
+ u32 mask, second_bypass;
+ u8 parent = 0;
+ const char *name = clk_hw_get_name(hwclk);
+
+ if (socfpgaclk->bypass_reg) {
+ mask = (0x1 << socfpgaclk->bypass_shift);
+ parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+ socfpgaclk->bypass_shift);
+ }
+
+ if (streq(name, SOCFPGA_EMAC0_CLK) ||
+ streq(name, SOCFPGA_EMAC1_CLK) ||
+ streq(name, SOCFPGA_EMAC2_CLK)) {
+ second_bypass = readl(socfpgaclk->bypass_reg -
+ STRATIX10_BYPASS_OFFSET);
+ /* EMACA bypass to bootclk @0xB0 offset */
+ if (second_bypass & 0x1)
+ if (parent == 0) /* only applicable if parent is maca */
+ parent = BOOTCLK_BYPASS;
+
+ if (second_bypass & 0x2)
+ if (parent == 1) /* only applicable if parent is macb */
+ parent = BOOTCLK_BYPASS;
+ }
+ return parent;
+}
+
+static u8 socfpga_agilex_gate_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 mask, second_bypass;
u8 parent = 0;
+ const char *name = clk_hw_get_name(hwclk);
if (socfpgaclk->bypass_reg) {
mask = (0x1 << socfpgaclk->bypass_shift);
parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
socfpgaclk->bypass_shift);
}
+
+ if (streq(name, SOCFPGA_EMAC0_CLK) ||
+ streq(name, SOCFPGA_EMAC1_CLK) ||
+ streq(name, SOCFPGA_EMAC2_CLK)) {
+ second_bypass = readl(socfpgaclk->bypass_reg -
+ AGILEX_BYPASS_OFFSET);
+ /* EMACA bypass to bootclk @0x88 offset */
+ if (second_bypass & 0x1)
+ if (parent == 0) /* only applicable if parent is maca */
+ parent = BOOTCLK_BYPASS;
+
+ if (second_bypass & 0x2)
+ if (parent == 1) /* only applicable if parent is macb */
+ parent = BOOTCLK_BYPASS;
+ }
+
return parent;
}
@@ -60,6 +114,11 @@ static struct clk_ops gateclk_ops = {
.get_parent = socfpga_gate_get_parent,
};
+static const struct clk_ops agilex_gateclk_ops = {
+ .recalc_rate = socfpga_gate_clk_recalc_rate,
+ .get_parent = socfpga_agilex_gate_get_parent,
+};
+
static const struct clk_ops dbgclk_ops = {
.recalc_rate = socfpga_dbg_clk_recalc_rate,
.get_parent = socfpga_gate_get_parent,
@@ -122,3 +181,61 @@ struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void _
}
return hw_clk;
}
+
+struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, void __iomem *regbase)
+{
+ struct clk_hw *hw_clk;
+ struct socfpga_gate_clk *socfpga_clk;
+ struct clk_init_data init;
+ const char *parent_name = clks->parent_name;
+ int ret;
+
+ socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+ if (!socfpga_clk)
+ return NULL;
+
+ socfpga_clk->hw.reg = regbase + clks->gate_reg;
+ socfpga_clk->hw.bit_idx = clks->gate_idx;
+
+ gateclk_ops.enable = clk_gate_ops.enable;
+ gateclk_ops.disable = clk_gate_ops.disable;
+
+ socfpga_clk->fixed_div = clks->fixed_div;
+
+ if (clks->div_reg)
+ socfpga_clk->div_reg = regbase + clks->div_reg;
+ else
+ socfpga_clk->div_reg = NULL;
+
+ socfpga_clk->width = clks->div_width;
+ socfpga_clk->shift = clks->div_offset;
+
+ if (clks->bypass_reg)
+ socfpga_clk->bypass_reg = regbase + clks->bypass_reg;
+ else
+ socfpga_clk->bypass_reg = NULL;
+ socfpga_clk->bypass_shift = clks->bypass_shift;
+
+ if (streq(clks->name, "cs_pdbg_clk"))
+ init.ops = &dbgclk_ops;
+ else
+ init.ops = &agilex_gateclk_ops;
+
+ init.name = clks->name;
+ init.flags = clks->flags;
+
+ init.num_parents = clks->num_parents;
+ 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;
+
+ hw_clk = &socfpga_clk->hw.hw;
+
+ ret = clk_hw_register(NULL, &socfpga_clk->hw.hw);
+ if (ret) {
+ kfree(socfpga_clk);
+ return ERR_PTR(ret);
+ }
+ return hw_clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
index e5a5fef76df7..cbabde2b476b 100644
--- a/drivers/clk/socfpga/clk-periph-s10.c
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -64,16 +64,21 @@ static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
{
struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
u32 clk_src, mask;
- u8 parent;
+ u8 parent = 0;
+ /* handle the bypass first */
if (socfpgaclk->bypass_reg) {
mask = (0x1 << socfpgaclk->bypass_shift);
parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
socfpgaclk->bypass_shift);
- } else {
+ if (parent)
+ return parent;
+ }
+
+ if (socfpgaclk->hw.reg) {
clk_src = readl(socfpgaclk->hw.reg);
parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
- CLK_MGR_FREE_MASK;
+ CLK_MGR_FREE_MASK;
}
return parent;
}
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
index dcb573d44034..127cc849c5ee 100644
--- a/drivers/clk/socfpga/clk-pll.c
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -80,7 +80,6 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node,
const char *parent_name[SOCFPGA_MAX_PARENTS];
struct clk_init_data init;
struct device_node *clkmgr_np;
- int rc;
int err;
of_property_read_u32(node, "reg", &reg);
@@ -114,7 +113,7 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node,
kfree(pll_clk);
return ERR_PTR(err);
}
- rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
+ of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
return hw_clk;
}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
index f0bd77138ecb..b532d51faaee 100644
--- a/drivers/clk/socfpga/clk-s10.c
+++ b/drivers/clk/socfpga/clk-s10.c
@@ -144,6 +144,41 @@ static const struct clk_parent_data mpu_free_mux[] = {
.name = "f2s-free-clk", },
};
+static const struct clk_parent_data sdmmc_mux[] = {
+ { .fw_name = "sdmmc_free_clk",
+ .name = "sdmmc_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data s2f_user1_mux[] = {
+ { .fw_name = "s2f_user1_free_clk",
+ .name = "s2f_user1_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data psi_mux[] = {
+ { .fw_name = "psi_ref_free_clk",
+ .name = "psi_ref_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data gpio_db_mux[] = {
+ { .fw_name = "gpio_db_free_clk",
+ .name = "gpio_db_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
+static const struct clk_parent_data emac_ptp_mux[] = {
+ { .fw_name = "emac_ptp_free_clk",
+ .name = "emac_ptp_free_clk", },
+ { .fw_name = "boot_clk",
+ .name = "boot_clk", },
+};
+
/* clocks in AO (always on) controller */
static const struct stratix10_pll_clock s10_pll_clks[] = {
{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
@@ -167,7 +202,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
0, 0x48, 0, 0, 0},
{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
- 0, 0x4C, 0, 0, 0},
+ 0, 0x4C, 0, 0x3C, 1},
{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
0x50, 0, 0, 0},
{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
@@ -200,10 +235,8 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
0, 0xD4, 0, 0, 0},
{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
0xD8, 0, 0, 0},
- { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
- 0, 4, 0, 0},
- { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
- 0, 0, 0, 0x3C, 1},
+ { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
+ 0, 4, 0x3C, 1},
{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
0, 0, 2, 0xB0, 0},
{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
@@ -227,20 +260,20 @@ static const struct stratix10_gate_clock s10_gate_clks[] = {
0, 0, 0, 0, 0, 0, 4},
{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
0, 0, 0, 0, 0, 0, 2},
- { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
- 1, 0x70, 0, 2, 0, 0, 0},
- { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
- 2, 0x70, 8, 2, 0, 0, 0},
- { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
- 3, 0x70, 16, 2, 0, 0, 0},
- { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
- 4, 0x70, 24, 2, 0, 0, 0},
- { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
- 4, 0x70, 26, 2, 0, 0, 0},
+ { STRATIX10_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
+ 1, 0x70, 0, 2, 0x3C, 1, 0},
+ { STRATIX10_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
+ 2, 0x70, 8, 2, 0x3C, 1, 0},
+ { STRATIX10_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x30,
+ 3, 0x70, 16, 2, 0x3C, 1, 0},
+ { STRATIX10_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
+ 4, 0x70, 24, 2, 0x3C, 1, 0},
+ { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
+ 4, 0x70, 26, 2, 0x3C, 1, 0},
{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
4, 0x70, 28, 1, 0, 0, 0},
- { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
- 5, 0, 0, 0, 0, 0, 0},
+ { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
+ 5, 0, 0, 0, 0x3C, 1, 0},
{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
6, 0, 0, 0, 0, 0, 0},
{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
@@ -249,16 +282,16 @@ static const struct stratix10_gate_clock s10_gate_clks[] = {
1, 0, 0, 0, 0xDC, 27, 0},
{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
2, 0, 0, 0, 0xDC, 28, 0},
- { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
- 3, 0, 0, 0, 0, 0, 0},
- { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
- 4, 0xE0, 0, 16, 0, 0, 0},
- { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
- 5, 0, 0, 0, 0, 0, 4},
- { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
- 6, 0, 0, 0, 0, 0, 0},
- { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
- 7, 0, 0, 0, 0, 0, 0},
+ { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0xA4,
+ 3, 0, 0, 0, 0xB0, 2, 0},
+ { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0xA4,
+ 4, 0xE0, 0, 16, 0xB0, 3, 0},
+ { STRATIX10_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0xA4,
+ 5, 0, 0, 0, 0xB0, 4, 4},
+ { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0xA4,
+ 6, 0, 0, 0, 0xB0, 5, 0},
+ { STRATIX10_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0xA4,
+ 7, 0, 0, 0, 0xB0, 6, 0},
{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
8, 0, 0, 0, 0, 0, 0},
{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
index 61eaf3a41fbb..75234e0783e1 100644
--- a/drivers/clk/socfpga/stratix10-clk.h
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -85,4 +85,6 @@ struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *c
void __iomem *reg);
struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks,
void __iomem *reg);
+struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks,
+ void __iomem *reg);
#endif /* __STRATIX10_CLK_H */
diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c
index 10c9b889324f..695feaa82da5 100644
--- a/drivers/clk/zynqmp/clk-gate-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c
@@ -121,7 +121,9 @@ struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id,
init.name = name;
init.ops = &zynqmp_clk_gate_ops;
- init.flags = nodes->flag;
+
+ init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
init.parent_names = parents;
init.num_parents = 1;
diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c
index 06194149be83..157d4a960bf4 100644
--- a/drivers/clk/zynqmp/clk-mux-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c
@@ -38,7 +38,7 @@ struct zynqmp_clk_mux {
* zynqmp_clk_mux_get_parent() - Get parent of clock
* @hw: handle between common and hardware-specific interfaces
*
- * Return: Parent index
+ * Return: Parent index on success or number of parents in case of error
*/
static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw)
{
@@ -50,9 +50,15 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw)
ret = zynqmp_pm_clock_getparent(clk_id, &val);
- if (ret)
+ if (ret) {
pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n",
__func__, clk_name, ret);
+ /*
+ * clk_core_get_parent_by_index() takes num_parents as incorrect
+ * index which is exactly what I want to return here
+ */
+ return clk_hw_get_num_parents(hw);
+ }
return val;
}
@@ -90,6 +96,27 @@ static const struct clk_ops zynqmp_clk_mux_ro_ops = {
.get_parent = zynqmp_clk_mux_get_parent,
};
+static inline unsigned long zynqmp_clk_map_mux_ccf_flags(
+ const u32 zynqmp_type_flag)
+{
+ unsigned long ccf_flag = 0;
+
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_ONE)
+ ccf_flag |= CLK_MUX_INDEX_ONE;
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_BIT)
+ ccf_flag |= CLK_MUX_INDEX_BIT;
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_HIWORD_MASK)
+ ccf_flag |= CLK_MUX_HIWORD_MASK;
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_READ_ONLY)
+ ccf_flag |= CLK_MUX_READ_ONLY;
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_ROUND_CLOSEST)
+ ccf_flag |= CLK_MUX_ROUND_CLOSEST;
+ if (zynqmp_type_flag & ZYNQMP_CLK_MUX_BIG_ENDIAN)
+ ccf_flag |= CLK_MUX_BIG_ENDIAN;
+
+ return ccf_flag;
+}
+
/**
* zynqmp_clk_register_mux() - Register a mux table with the clock
* framework
@@ -120,10 +147,12 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id,
init.ops = &zynqmp_clk_mux_ro_ops;
else
init.ops = &zynqmp_clk_mux_ops;
- init.flags = nodes->flag;
+
+ init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
init.parent_names = parents;
init.num_parents = num_parents;
- mux->flags = nodes->type_flag;
+ mux->flags = zynqmp_clk_map_mux_ccf_flags(nodes->type_flag);
mux->hw.init = &init;
mux->clk_id = clk_id;
diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h
index 5beeb41b29fa..84fa80a969a9 100644
--- a/drivers/clk/zynqmp/clk-zynqmp.h
+++ b/drivers/clk/zynqmp/clk-zynqmp.h
@@ -10,6 +10,37 @@
#include <linux/firmware/xlnx-zynqmp.h>
+/* Common Flags */
+/* must be gated across rate change */
+#define ZYNQMP_CLK_SET_RATE_GATE BIT(0)
+/* must be gated across re-parent */
+#define ZYNQMP_CLK_SET_PARENT_GATE BIT(1)
+/* propagate rate change up one level */
+#define ZYNQMP_CLK_SET_RATE_PARENT BIT(2)
+/* do not gate even if unused */
+#define ZYNQMP_CLK_IGNORE_UNUSED BIT(3)
+/* don't re-parent on rate change */
+#define ZYNQMP_CLK_SET_RATE_NO_REPARENT BIT(7)
+/* do not gate, ever */
+#define ZYNQMP_CLK_IS_CRITICAL BIT(11)
+
+/* Type Flags for divider clock */
+#define ZYNQMP_CLK_DIVIDER_ONE_BASED BIT(0)
+#define ZYNQMP_CLK_DIVIDER_POWER_OF_TWO BIT(1)
+#define ZYNQMP_CLK_DIVIDER_ALLOW_ZERO BIT(2)
+#define ZYNQMP_CLK_DIVIDER_HIWORD_MASK BIT(3)
+#define ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST BIT(4)
+#define ZYNQMP_CLK_DIVIDER_READ_ONLY BIT(5)
+#define ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO BIT(6)
+
+/* Type Flags for mux clock */
+#define ZYNQMP_CLK_MUX_INDEX_ONE BIT(0)
+#define ZYNQMP_CLK_MUX_INDEX_BIT BIT(1)
+#define ZYNQMP_CLK_MUX_HIWORD_MASK BIT(2)
+#define ZYNQMP_CLK_MUX_READ_ONLY BIT(3)
+#define ZYNQMP_CLK_MUX_ROUND_CLOSEST BIT(4)
+#define ZYNQMP_CLK_MUX_BIG_ENDIAN BIT(5)
+
enum topology_type {
TYPE_INVALID,
TYPE_MUX,
@@ -33,6 +64,8 @@ struct clock_topology {
u8 custom_type_flag;
};
+unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag);
+
struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
const char * const *parents,
u8 num_parents,
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index db8d0d7161ce..871184e406e1 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -271,6 +271,26 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index,
return ret;
}
+unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag)
+{
+ unsigned long ccf_flag = 0;
+
+ if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_GATE)
+ ccf_flag |= CLK_SET_RATE_GATE;
+ if (zynqmp_flag & ZYNQMP_CLK_SET_PARENT_GATE)
+ ccf_flag |= CLK_SET_PARENT_GATE;
+ if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_PARENT)
+ ccf_flag |= CLK_SET_RATE_PARENT;
+ if (zynqmp_flag & ZYNQMP_CLK_IGNORE_UNUSED)
+ ccf_flag |= CLK_IGNORE_UNUSED;
+ if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_NO_REPARENT)
+ ccf_flag |= CLK_SET_RATE_NO_REPARENT;
+ if (zynqmp_flag & ZYNQMP_CLK_IS_CRITICAL)
+ ccf_flag |= CLK_IS_CRITICAL;
+
+ return ccf_flag;
+}
+
/**
* zynqmp_clk_register_fixed_factor() - Register fixed factor with the
* clock framework
@@ -292,6 +312,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
struct zynqmp_pm_query_data qdata = {0};
u32 ret_payload[PAYLOAD_ARG_CNT];
int ret;
+ unsigned long flag;
qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS;
qdata.arg1 = clk_id;
@@ -303,9 +324,11 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
mult = ret_payload[1];
div = ret_payload[2];
+ flag = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
hw = clk_hw_register_fixed_factor(NULL, name,
parents[0],
- nodes->flag, mult,
+ flag, mult,
div);
return hw;
diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c
index e9bf7958b821..cb49281f9cf9 100644
--- a/drivers/clk/zynqmp/divider.c
+++ b/drivers/clk/zynqmp/divider.c
@@ -256,6 +256,11 @@ static const struct clk_ops zynqmp_clk_divider_ops = {
.set_rate = zynqmp_clk_divider_set_rate,
};
+static const struct clk_ops zynqmp_clk_divider_ro_ops = {
+ .recalc_rate = zynqmp_clk_divider_recalc_rate,
+ .round_rate = zynqmp_clk_divider_round_rate,
+};
+
/**
* zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware.
* @clk_id: Id of clock
@@ -284,6 +289,29 @@ static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
return ret_payload[1];
}
+static inline unsigned long zynqmp_clk_map_divider_ccf_flags(
+ const u32 zynqmp_type_flag)
+{
+ unsigned long ccf_flag = 0;
+
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED)
+ ccf_flag |= CLK_DIVIDER_ONE_BASED;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
+ ccf_flag |= CLK_DIVIDER_POWER_OF_TWO;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO)
+ ccf_flag |= CLK_DIVIDER_ALLOW_ZERO;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
+ ccf_flag |= CLK_DIVIDER_HIWORD_MASK;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST)
+ ccf_flag |= CLK_DIVIDER_ROUND_CLOSEST;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY)
+ ccf_flag |= CLK_DIVIDER_READ_ONLY;
+ if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO)
+ ccf_flag |= CLK_DIVIDER_MAX_AT_ZERO;
+
+ return ccf_flag;
+}
+
/**
* zynqmp_clk_register_divider() - Register a divider clock
* @name: Name of this clock
@@ -311,16 +339,20 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name,
return ERR_PTR(-ENOMEM);
init.name = name;
- init.ops = &zynqmp_clk_divider_ops;
- /* CLK_FRAC is not defined in the common clk framework */
- init.flags = nodes->flag & ~CLK_FRAC;
+ if (nodes->type_flag & CLK_DIVIDER_READ_ONLY)
+ init.ops = &zynqmp_clk_divider_ro_ops;
+ else
+ init.ops = &zynqmp_clk_divider_ops;
+
+ init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
init.parent_names = parents;
init.num_parents = 1;
/* struct clk_divider assignments */
div->is_frac = !!((nodes->flag & CLK_FRAC) |
(nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC));
- div->flags = nodes->type_flag;
+ div->flags = zynqmp_clk_map_divider_ccf_flags(nodes->type_flag);
div->hw.init = &init;
div->clk_id = clk_id;
div->div_type = nodes->type;
diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c
index abe6afbf3407..036e4ff64a2f 100644
--- a/drivers/clk/zynqmp/pll.c
+++ b/drivers/clk/zynqmp/pll.c
@@ -31,8 +31,9 @@ struct zynqmp_pll {
#define PS_PLL_VCO_MAX 3000000000UL
enum pll_mode {
- PLL_MODE_INT,
- PLL_MODE_FRAC,
+ PLL_MODE_INT = 0,
+ PLL_MODE_FRAC = 1,
+ PLL_MODE_ERROR = 2,
};
#define FRAC_OFFSET 0x8
@@ -54,9 +55,11 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw)
int ret;
ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload);
- if (ret)
+ if (ret) {
pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n",
__func__, clk_name, ret);
+ return PLL_MODE_ERROR;
+ }
return ret_payload[1];
}
@@ -126,7 +129,7 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
* @hw: Handle between common and hardware-specific interfaces
* @parent_rate: Clock frequency of parent clock
*
- * Return: Current clock frequency
+ * Return: Current clock frequency or 0 in case of error
*/
static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -138,14 +141,21 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
unsigned long rate, frac;
u32 ret_payload[PAYLOAD_ARG_CNT];
int ret;
+ enum pll_mode mode;
ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv);
- if (ret)
+ if (ret) {
pr_warn_once("%s() get divider failed for %s, ret = %d\n",
__func__, clk_name, ret);
+ return 0ul;
+ }
+
+ mode = zynqmp_pll_get_mode(hw);
+ if (mode == PLL_MODE_ERROR)
+ return 0ul;
rate = parent_rate * fbdiv;
- if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
+ if (mode == PLL_MODE_FRAC) {
zynqmp_pm_get_pll_frac_data(clk_id, ret_payload);
data = ret_payload[1];
frac = (parent_rate * data) / FRAC_DIV;
@@ -312,7 +322,9 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
init.name = name;
init.ops = &zynqmp_pll_ops;
- init.flags = nodes->flag;
+
+ init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
+
init.parent_names = parents;
init.num_parents = 1;
@@ -331,8 +343,6 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
}
clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX);
- if (ret < 0)
- pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret);
return hw;
}