at91: kernel v5.15: remove upstreamed patches
[openwrt/openwrt.git] / target / linux / at91 / patches-5.15 / 110-clk-at91-clk-master-re-factor-master-clock.patch
diff --git a/target/linux/at91/patches-5.15/110-clk-at91-clk-master-re-factor-master-clock.patch b/target/linux/at91/patches-5.15/110-clk-at91-clk-master-re-factor-master-clock.patch
deleted file mode 100644 (file)
index a0eadd8..0000000
+++ /dev/null
@@ -1,1230 +0,0 @@
-From 9109b768fe65994547ef464b13e508b22de3e89b Mon Sep 17 00:00:00 2001
-From: Claudiu Beznea <claudiu.beznea@microchip.com>
-Date: Thu, 19 Nov 2020 17:43:16 +0200
-Subject: [PATCH 110/247] clk: at91: clk-master: re-factor master clock
-
-Re-factor master clock driver by splitting it into 2 clocks: prescaller
-and divider clocks. Based on registered clock flags the prescaler's rate
-could be changed at runtime. This is necessary for platforms supporting
-DVFS (e.g. SAMA7G5) where master clock could be changed at run-time.
-
-Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
-Link: https://lore.kernel.org/r/1605800597-16720-11-git-send-email-claudiu.beznea@microchip.com
-Signed-off-by: Stephen Boyd <sboyd@kernel.org>
----
- drivers/clk/at91/at91rm9200.c  |  21 ++-
- drivers/clk/at91/at91sam9260.c |  26 ++-
- drivers/clk/at91/at91sam9g45.c |  32 +++-
- drivers/clk/at91/at91sam9n12.c |  36 ++--
- drivers/clk/at91/at91sam9rl.c  |  23 ++-
- drivers/clk/at91/at91sam9x5.c  |  28 ++-
- drivers/clk/at91/clk-master.c  | 335 ++++++++++++++++++++++++++++-----
- drivers/clk/at91/dt-compat.c   |  15 +-
- drivers/clk/at91/pmc.h         |  16 +-
- drivers/clk/at91/sam9x60.c     |  23 ++-
- drivers/clk/at91/sama5d2.c     |  42 +++--
- drivers/clk/at91/sama5d3.c     |  38 ++--
- drivers/clk/at91/sama5d4.c     |  40 ++--
- drivers/clk/at91/sama7g5.c     |  13 +-
- 14 files changed, 542 insertions(+), 146 deletions(-)
-
---- a/drivers/clk/at91/at91rm9200.c
-+++ b/drivers/clk/at91/at91rm9200.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(rm9200_mck_lock);
-+
- struct sck {
-       char *n;
-       char *p;
-@@ -137,9 +139,20 @@ static void __init at91rm9200_pmc_setup(
-       parent_names[1] = "mainck";
-       parent_names[2] = "pllack";
-       parent_names[3] = "pllbck";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91rm9200_master_layout,
--                                    &rm9200_mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91rm9200_master_layout,
-+                                         &rm9200_mck_characteristics,
-+                                         &rm9200_mck_lock, CLK_SET_RATE_GATE,
-+                                         INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91rm9200_master_layout,
-+                                        &rm9200_mck_characteristics,
-+                                        &rm9200_mck_lock, CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -181,7 +194,7 @@ static void __init at91rm9200_pmc_setup(
-       for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) {
-               hw = at91_clk_register_peripheral(regmap,
-                                                 at91rm9200_periphck[i].n,
--                                                "masterck",
-+                                                "masterck_div",
-                                                 at91rm9200_periphck[i].id);
-               if (IS_ERR(hw))
-                       goto err_free;
---- a/drivers/clk/at91/at91sam9260.c
-+++ b/drivers/clk/at91/at91sam9260.c
-@@ -32,6 +32,8 @@ struct at91sam926x_data {
-       bool has_slck;
- };
-+static DEFINE_SPINLOCK(at91sam9260_mck_lock);
-+
- static const struct clk_master_characteristics sam9260_mck_characteristics = {
-       .output = { .min = 0, .max = 105000000 },
-       .divisors = { 1, 2, 4, 0 },
-@@ -218,8 +220,8 @@ static const struct sck at91sam9261_syst
-       { .n = "pck1",  .p = "prog1",    .id = 9 },
-       { .n = "pck2",  .p = "prog2",    .id = 10 },
-       { .n = "pck3",  .p = "prog3",    .id = 11 },
--      { .n = "hclk0", .p = "masterck", .id = 16 },
--      { .n = "hclk1", .p = "masterck", .id = 17 },
-+      { .n = "hclk0", .p = "masterck_div", .id = 16 },
-+      { .n = "hclk1", .p = "masterck_div", .id = 17 },
- };
- static const struct pck at91sam9261_periphck[] = {
-@@ -413,9 +415,21 @@ static void __init at91sam926x_pmc_setup
-       parent_names[1] = "mainck";
-       parent_names[2] = "pllack";
-       parent_names[3] = "pllbck";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91rm9200_master_layout,
--                                    data->mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91rm9200_master_layout,
-+                                         data->mck_characteristics,
-+                                         &at91sam9260_mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91rm9200_master_layout,
-+                                        data->mck_characteristics,
-+                                        &at91sam9260_mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -457,7 +471,7 @@ static void __init at91sam926x_pmc_setup
-       for (i = 0; i < data->num_pck; i++) {
-               hw = at91_clk_register_peripheral(regmap,
-                                                 data->pck[i].n,
--                                                "masterck",
-+                                                "masterck_div",
-                                                 data->pck[i].id);
-               if (IS_ERR(hw))
-                       goto err_free;
---- a/drivers/clk/at91/at91sam9g45.c
-+++ b/drivers/clk/at91/at91sam9g45.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(at91sam9g45_mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 0, .max = 133333333 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -40,10 +42,10 @@ static const struct {
-       char *p;
-       u8 id;
- } at91sam9g45_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
--      { .n = "uhpck", .p = "usbck",    .id = 6 },
--      { .n = "pck0",  .p = "prog0",    .id = 8 },
--      { .n = "pck1",  .p = "prog1",    .id = 9 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-+      { .n = "uhpck", .p = "usbck",        .id = 6 },
-+      { .n = "pck0",  .p = "prog0",        .id = 8 },
-+      { .n = "pck1",  .p = "prog1",        .id = 9 },
- };
- struct pck {
-@@ -148,9 +150,21 @@ static void __init at91sam9g45_pmc_setup
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91rm9200_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91rm9200_master_layout,
-+                                         &mck_characteristics,
-+                                         &at91sam9g45_mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91rm9200_master_layout,
-+                                        &mck_characteristics,
-+                                        &at91sam9g45_mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -166,7 +180,7 @@ static void __init at91sam9g45_pmc_setup
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 2; i++) {
-               char name[6];
-@@ -195,7 +209,7 @@ static void __init at91sam9g45_pmc_setup
-       for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) {
-               hw = at91_clk_register_peripheral(regmap,
-                                                 at91sam9g45_periphck[i].n,
--                                                "masterck",
-+                                                "masterck_div",
-                                                 at91sam9g45_periphck[i].id);
-               if (IS_ERR(hw))
-                       goto err_free;
---- a/drivers/clk/at91/at91sam9n12.c
-+++ b/drivers/clk/at91/at91sam9n12.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(at91sam9n12_mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 0, .max = 133333333 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -54,12 +56,12 @@ static const struct {
-       char *p;
-       u8 id;
- } at91sam9n12_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
--      { .n = "lcdck", .p = "masterck", .id = 3 },
--      { .n = "uhpck", .p = "usbck",    .id = 6 },
--      { .n = "udpck", .p = "usbck",    .id = 7 },
--      { .n = "pck0",  .p = "prog0",    .id = 8 },
--      { .n = "pck1",  .p = "prog1",    .id = 9 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-+      { .n = "lcdck", .p = "masterck_div", .id = 3 },
-+      { .n = "uhpck", .p = "usbck",        .id = 6 },
-+      { .n = "udpck", .p = "usbck",        .id = 7 },
-+      { .n = "pck0",  .p = "prog0",        .id = 8 },
-+      { .n = "pck1",  .p = "prog1",        .id = 9 },
- };
- static const struct clk_pcr_layout at91sam9n12_pcr_layout = {
-@@ -175,9 +177,21 @@ static void __init at91sam9n12_pmc_setup
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "pllbck";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91sam9x5_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91sam9x5_master_layout,
-+                                         &mck_characteristics,
-+                                         &at91sam9n12_mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91sam9x5_master_layout,
-+                                        &mck_characteristics,
-+                                        &at91sam9n12_mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -191,7 +205,7 @@ static void __init at91sam9n12_pmc_setup
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "pllbck";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 2; i++) {
-               char name[6];
-@@ -221,7 +235,7 @@ static void __init at91sam9n12_pmc_setup
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &at91sam9n12_pcr_layout,
-                                                        at91sam9n12_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        at91sam9n12_periphck[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
---- a/drivers/clk/at91/at91sam9rl.c
-+++ b/drivers/clk/at91/at91sam9rl.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(sam9rl_mck_lock);
-+
- static const struct clk_master_characteristics sam9rl_mck_characteristics = {
-       .output = { .min = 0, .max = 94000000 },
-       .divisors = { 1, 2, 4, 0 },
-@@ -117,9 +119,20 @@ static void __init at91sam9rl_pmc_setup(
-       parent_names[1] = "mainck";
-       parent_names[2] = "pllack";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91rm9200_master_layout,
--                                    &sam9rl_mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91rm9200_master_layout,
-+                                         &sam9rl_mck_characteristics,
-+                                         &sam9rl_mck_lock, CLK_SET_RATE_GATE,
-+                                         INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91rm9200_master_layout,
-+                                        &sam9rl_mck_characteristics,
-+                                        &sam9rl_mck_lock, CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -129,7 +142,7 @@ static void __init at91sam9rl_pmc_setup(
-       parent_names[1] = "mainck";
-       parent_names[2] = "pllack";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 2; i++) {
-               char name[6];
-@@ -158,7 +171,7 @@ static void __init at91sam9rl_pmc_setup(
-       for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
-               hw = at91_clk_register_peripheral(regmap,
-                                                 at91sam9rl_periphck[i].n,
--                                                "masterck",
-+                                                "masterck_div",
-                                                 at91sam9rl_periphck[i].id);
-               if (IS_ERR(hw))
-                       goto err_free;
---- a/drivers/clk/at91/at91sam9x5.c
-+++ b/drivers/clk/at91/at91sam9x5.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 0, .max = 133333333 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -41,7 +43,7 @@ static const struct {
-       char *p;
-       u8 id;
- } at91sam9x5_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-       { .n = "smdck", .p = "smdclk",   .id = 4 },
-       { .n = "uhpck", .p = "usbck",    .id = 6 },
-       { .n = "udpck", .p = "usbck",    .id = 7 },
-@@ -196,9 +198,19 @@ static void __init at91sam9x5_pmc_setup(
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91sam9x5_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91sam9x5_master_layout,
-+                                         &mck_characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91sam9x5_master_layout,
-+                                        &mck_characteristics, &mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -218,7 +230,7 @@ static void __init at91sam9x5_pmc_setup(
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 2; i++) {
-               char name[6];
-@@ -245,7 +257,7 @@ static void __init at91sam9x5_pmc_setup(
-       }
-       if (has_lcdck) {
--              hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
-+              hw = at91_clk_register_system(regmap, "lcdck", "masterck_div", 3);
-               if (IS_ERR(hw))
-                       goto err_free;
-@@ -256,7 +268,7 @@ static void __init at91sam9x5_pmc_setup(
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &at91sam9x5_pcr_layout,
-                                                        at91sam9x5_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        at91sam9x5_periphck[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
-@@ -269,7 +281,7 @@ static void __init at91sam9x5_pmc_setup(
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &at91sam9x5_pcr_layout,
-                                                        extra_pcks[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        extra_pcks[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
---- a/drivers/clk/at91/clk-master.c
-+++ b/drivers/clk/at91/clk-master.c
-@@ -58,83 +58,309 @@ static inline bool clk_master_ready(stru
- static int clk_master_prepare(struct clk_hw *hw)
- {
-       struct clk_master *master = to_clk_master(hw);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(master->lock, flags);
-       while (!clk_master_ready(master))
-               cpu_relax();
-+      spin_unlock_irqrestore(master->lock, flags);
-+
-       return 0;
- }
- static int clk_master_is_prepared(struct clk_hw *hw)
- {
-       struct clk_master *master = to_clk_master(hw);
-+      unsigned long flags;
-+      bool status;
-+
-+      spin_lock_irqsave(master->lock, flags);
-+      status = clk_master_ready(master);
-+      spin_unlock_irqrestore(master->lock, flags);
--      return clk_master_ready(master);
-+      return status;
- }
--static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
--                                          unsigned long parent_rate)
-+static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
-+                                              unsigned long parent_rate)
- {
--      u8 pres;
-       u8 div;
--      unsigned long rate = parent_rate;
-+      unsigned long flags, rate = parent_rate;
-       struct clk_master *master = to_clk_master(hw);
-       const struct clk_master_layout *layout = master->layout;
-       const struct clk_master_characteristics *characteristics =
-                                               master->characteristics;
-       unsigned int mckr;
-+      spin_lock_irqsave(master->lock, flags);
-       regmap_read(master->regmap, master->layout->offset, &mckr);
-+      spin_unlock_irqrestore(master->lock, flags);
-+
-       mckr &= layout->mask;
--      pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
-       div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
--      if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
--              rate /= 3;
--      else
--              rate >>= pres;
--
-       rate /= characteristics->divisors[div];
-       if (rate < characteristics->output.min)
--              pr_warn("master clk is underclocked");
-+              pr_warn("master clk div is underclocked");
-       else if (rate > characteristics->output.max)
--              pr_warn("master clk is overclocked");
-+              pr_warn("master clk div is overclocked");
-       return rate;
- }
--static u8 clk_master_get_parent(struct clk_hw *hw)
-+static const struct clk_ops master_div_ops = {
-+      .prepare = clk_master_prepare,
-+      .is_prepared = clk_master_is_prepared,
-+      .recalc_rate = clk_master_div_recalc_rate,
-+};
-+
-+static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                 unsigned long parent_rate)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+      const struct clk_master_characteristics *characteristics =
-+                                              master->characteristics;
-+      unsigned long flags;
-+      int div, i;
-+
-+      div = DIV_ROUND_CLOSEST(parent_rate, rate);
-+      if (div > ARRAY_SIZE(characteristics->divisors))
-+              return -EINVAL;
-+
-+      for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
-+              if (!characteristics->divisors[i])
-+                      break;
-+
-+              if (div == characteristics->divisors[i]) {
-+                      div = i;
-+                      break;
-+              }
-+      }
-+
-+      if (i == ARRAY_SIZE(characteristics->divisors))
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(master->lock, flags);
-+      regmap_update_bits(master->regmap, master->layout->offset,
-+                         (MASTER_DIV_MASK << MASTER_DIV_SHIFT),
-+                         (div << MASTER_DIV_SHIFT));
-+      while (!clk_master_ready(master))
-+              cpu_relax();
-+      spin_unlock_irqrestore(master->lock, flags);
-+
-+      return 0;
-+}
-+
-+static int clk_master_div_determine_rate(struct clk_hw *hw,
-+                                       struct clk_rate_request *req)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+      const struct clk_master_characteristics *characteristics =
-+                                              master->characteristics;
-+      struct clk_hw *parent;
-+      unsigned long parent_rate, tmp_rate, best_rate = 0;
-+      int i, best_diff = INT_MIN, tmp_diff;
-+
-+      parent = clk_hw_get_parent(hw);
-+      if (!parent)
-+              return -EINVAL;
-+
-+      parent_rate = clk_hw_get_rate(parent);
-+      if (!parent_rate)
-+              return -EINVAL;
-+
-+      for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
-+              if (!characteristics->divisors[i])
-+                      break;
-+
-+              tmp_rate = DIV_ROUND_CLOSEST_ULL(parent_rate,
-+                                               characteristics->divisors[i]);
-+              tmp_diff = abs(tmp_rate - req->rate);
-+
-+              if (!best_rate || best_diff > tmp_diff) {
-+                      best_diff = tmp_diff;
-+                      best_rate = tmp_rate;
-+              }
-+
-+              if (!best_diff)
-+                      break;
-+      }
-+
-+      req->best_parent_rate = best_rate;
-+      req->best_parent_hw = parent;
-+      req->rate = best_rate;
-+
-+      return 0;
-+}
-+
-+static const struct clk_ops master_div_ops_chg = {
-+      .prepare = clk_master_prepare,
-+      .is_prepared = clk_master_is_prepared,
-+      .recalc_rate = clk_master_div_recalc_rate,
-+      .determine_rate = clk_master_div_determine_rate,
-+      .set_rate = clk_master_div_set_rate,
-+};
-+
-+static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
-+                                       struct clk_hw *parent,
-+                                       unsigned long parent_rate,
-+                                       long *best_rate,
-+                                       long *best_diff,
-+                                       u32 div)
-+{
-+      unsigned long tmp_rate, tmp_diff;
-+
-+      if (div == MASTER_PRES_MAX)
-+              tmp_rate = parent_rate / 3;
-+      else
-+              tmp_rate = parent_rate >> div;
-+
-+      tmp_diff = abs(req->rate - tmp_rate);
-+
-+      if (*best_diff < 0 || *best_diff >= tmp_diff) {
-+              *best_rate = tmp_rate;
-+              *best_diff = tmp_diff;
-+              req->best_parent_rate = parent_rate;
-+              req->best_parent_hw = parent;
-+      }
-+}
-+
-+static int clk_master_pres_determine_rate(struct clk_hw *hw,
-+                                        struct clk_rate_request *req)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+      struct clk_rate_request req_parent = *req;
-+      const struct clk_master_characteristics *characteristics =
-+                                                      master->characteristics;
-+      struct clk_hw *parent;
-+      long best_rate = LONG_MIN, best_diff = LONG_MIN;
-+      u32 pres;
-+      int i;
-+
-+      if (master->chg_pid < 0)
-+              return -EOPNOTSUPP;
-+
-+      parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
-+      if (!parent)
-+              return -EOPNOTSUPP;
-+
-+      for (i = 0; i <= MASTER_PRES_MAX; i++) {
-+              if (characteristics->have_div3_pres && i == MASTER_PRES_MAX)
-+                      pres = 3;
-+              else
-+                      pres = 1 << i;
-+
-+              req_parent.rate = req->rate * pres;
-+              if (__clk_determine_rate(parent, &req_parent))
-+                      continue;
-+
-+              clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
-+                                           &best_diff, &best_rate, pres);
-+              if (!best_diff)
-+                      break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate,
-+                                  unsigned long parent_rate)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+      unsigned long flags;
-+      unsigned int pres;
-+
-+      pres = DIV_ROUND_CLOSEST(parent_rate, rate);
-+      if (pres > MASTER_PRES_MAX)
-+              return -EINVAL;
-+
-+      else if (pres == 3)
-+              pres = MASTER_PRES_MAX;
-+      else
-+              pres = ffs(pres) - 1;
-+
-+      spin_lock_irqsave(master->lock, flags);
-+      regmap_update_bits(master->regmap, master->layout->offset,
-+                         (MASTER_PRES_MASK << master->layout->pres_shift),
-+                         (pres << master->layout->pres_shift));
-+
-+      while (!clk_master_ready(master))
-+              cpu_relax();
-+      spin_unlock_irqrestore(master->lock, flags);
-+
-+      return 0;
-+}
-+
-+static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+      const struct clk_master_characteristics *characteristics =
-+                                              master->characteristics;
-+      unsigned long flags;
-+      unsigned int val, pres;
-+
-+      spin_lock_irqsave(master->lock, flags);
-+      regmap_read(master->regmap, master->layout->offset, &val);
-+      spin_unlock_irqrestore(master->lock, flags);
-+
-+      pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
-+      if (pres == 3 && characteristics->have_div3_pres)
-+              pres = 3;
-+      else
-+              pres = (1 << pres);
-+
-+      return DIV_ROUND_CLOSEST_ULL(parent_rate, pres);
-+}
-+
-+static u8 clk_master_pres_get_parent(struct clk_hw *hw)
- {
-       struct clk_master *master = to_clk_master(hw);
-+      unsigned long flags;
-       unsigned int mckr;
-+      spin_lock_irqsave(master->lock, flags);
-       regmap_read(master->regmap, master->layout->offset, &mckr);
-+      spin_unlock_irqrestore(master->lock, flags);
-       return mckr & AT91_PMC_CSS;
- }
--static const struct clk_ops master_ops = {
-+static const struct clk_ops master_pres_ops = {
-       .prepare = clk_master_prepare,
-       .is_prepared = clk_master_is_prepared,
--      .recalc_rate = clk_master_recalc_rate,
--      .get_parent = clk_master_get_parent,
-+      .recalc_rate = clk_master_pres_recalc_rate,
-+      .get_parent = clk_master_pres_get_parent,
- };
--struct clk_hw * __init
--at91_clk_register_master(struct regmap *regmap,
-+static const struct clk_ops master_pres_ops_chg = {
-+      .prepare = clk_master_prepare,
-+      .is_prepared = clk_master_is_prepared,
-+      .determine_rate = clk_master_pres_determine_rate,
-+      .recalc_rate = clk_master_pres_recalc_rate,
-+      .get_parent = clk_master_pres_get_parent,
-+      .set_rate = clk_master_pres_set_rate,
-+};
-+
-+static struct clk_hw * __init
-+at91_clk_register_master_internal(struct regmap *regmap,
-               const char *name, int num_parents,
-               const char **parent_names,
-               const struct clk_master_layout *layout,
--              const struct clk_master_characteristics *characteristics)
-+              const struct clk_master_characteristics *characteristics,
-+              const struct clk_ops *ops, spinlock_t *lock, u32 flags,
-+              int chg_pid)
- {
-       struct clk_master *master;
-       struct clk_init_data init;
-       struct clk_hw *hw;
-       int ret;
--      if (!name || !num_parents || !parent_names)
-+      if (!name || !num_parents || !parent_names || !lock)
-               return ERR_PTR(-EINVAL);
-       master = kzalloc(sizeof(*master), GFP_KERNEL);
-@@ -142,15 +368,17 @@ at91_clk_register_master(struct regmap *
-               return ERR_PTR(-ENOMEM);
-       init.name = name;
--      init.ops = &master_ops;
-+      init.ops = ops;
-       init.parent_names = parent_names;
-       init.num_parents = num_parents;
--      init.flags = 0;
-+      init.flags = flags;
-       master->hw.init = &init;
-       master->layout = layout;
-       master->characteristics = characteristics;
-       master->regmap = regmap;
-+      master->chg_pid = chg_pid;
-+      master->lock = lock;
-       hw = &master->hw;
-       ret = clk_hw_register(NULL, &master->hw);
-@@ -162,37 +390,54 @@ at91_clk_register_master(struct regmap *
-       return hw;
- }
--static unsigned long
--clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
--                             unsigned long parent_rate)
-+struct clk_hw * __init
-+at91_clk_register_master_pres(struct regmap *regmap,
-+              const char *name, int num_parents,
-+              const char **parent_names,
-+              const struct clk_master_layout *layout,
-+              const struct clk_master_characteristics *characteristics,
-+              spinlock_t *lock, u32 flags, int chg_pid)
- {
--      struct clk_master *master = to_clk_master(hw);
-+      const struct clk_ops *ops;
--      return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
-+      if (flags & CLK_SET_RATE_GATE)
-+              ops = &master_pres_ops;
-+      else
-+              ops = &master_pres_ops_chg;
-+
-+      return at91_clk_register_master_internal(regmap, name, num_parents,
-+                                               parent_names, layout,
-+                                               characteristics, ops,
-+                                               lock, flags, chg_pid);
- }
--static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
--                                       struct clk_hw *parent,
--                                       unsigned long parent_rate,
--                                       long *best_rate,
--                                       long *best_diff,
--                                       u32 div)
-+struct clk_hw * __init
-+at91_clk_register_master_div(struct regmap *regmap,
-+              const char *name, const char *parent_name,
-+              const struct clk_master_layout *layout,
-+              const struct clk_master_characteristics *characteristics,
-+              spinlock_t *lock, u32 flags)
- {
--      unsigned long tmp_rate, tmp_diff;
-+      const struct clk_ops *ops;
--      if (div == MASTER_PRES_MAX)
--              tmp_rate = parent_rate / 3;
-+      if (flags & CLK_SET_RATE_GATE)
-+              ops = &master_div_ops;
-       else
--              tmp_rate = parent_rate >> div;
-+              ops = &master_div_ops_chg;
--      tmp_diff = abs(req->rate - tmp_rate);
-+      return at91_clk_register_master_internal(regmap, name, 1,
-+                                               &parent_name, layout,
-+                                               characteristics, ops,
-+                                               lock, flags, -EINVAL);
-+}
--      if (*best_diff < 0 || *best_diff >= tmp_diff) {
--              *best_rate = tmp_rate;
--              *best_diff = tmp_diff;
--              req->best_parent_rate = parent_rate;
--              req->best_parent_hw = parent;
--      }
-+static unsigned long
-+clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
-+                             unsigned long parent_rate)
-+{
-+      struct clk_master *master = to_clk_master(hw);
-+
-+      return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
- }
- static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
---- a/drivers/clk/at91/dt-compat.c
-+++ b/drivers/clk/at91/dt-compat.c
-@@ -24,6 +24,8 @@
- #define GCK_INDEX_DT_AUDIO_PLL        5
-+static DEFINE_SPINLOCK(mck_lock);
-+
- #ifdef CONFIG_HAVE_AT91_AUDIO_PLL
- static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
- {
-@@ -388,9 +390,16 @@ of_at91_clk_master_setup(struct device_n
-       if (IS_ERR(regmap))
-               return;
--      hw = at91_clk_register_master(regmap, name, num_parents,
--                                    parent_names, layout,
--                                    characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents,
-+                                         parent_names, layout,
-+                                         characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto out_free_characteristics;
-+
-+      hw = at91_clk_register_master_div(regmap, name, "masterck_pres",
-+                                        layout, characteristics,
-+                                        &mck_lock, CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto out_free_characteristics;
---- a/drivers/clk/at91/pmc.h
-+++ b/drivers/clk/at91/pmc.h
-@@ -155,10 +155,18 @@ at91_clk_register_sam9x5_main(struct reg
-                             const char **parent_names, int num_parents);
- struct clk_hw * __init
--at91_clk_register_master(struct regmap *regmap, const char *name,
--                       int num_parents, const char **parent_names,
--                       const struct clk_master_layout *layout,
--                       const struct clk_master_characteristics *characteristics);
-+at91_clk_register_master_pres(struct regmap *regmap, const char *name,
-+                            int num_parents, const char **parent_names,
-+                            const struct clk_master_layout *layout,
-+                            const struct clk_master_characteristics *characteristics,
-+                            spinlock_t *lock, u32 flags, int chg_pid);
-+
-+struct clk_hw * __init
-+at91_clk_register_master_div(struct regmap *regmap, const char *name,
-+                           const char *parent_names,
-+                           const struct clk_master_layout *layout,
-+                           const struct clk_master_characteristics *characteristics,
-+                           spinlock_t *lock, u32 flags);
- struct clk_hw * __init
- at91_clk_sama7g5_register_master(struct regmap *regmap,
---- a/drivers/clk/at91/sam9x60.c
-+++ b/drivers/clk/at91/sam9x60.c
-@@ -8,6 +8,7 @@
- #include "pmc.h"
- static DEFINE_SPINLOCK(pmc_pll_lock);
-+static DEFINE_SPINLOCK(mck_lock);
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 140000000, .max = 200000000 },
-@@ -76,11 +77,11 @@ static const struct {
-       char *p;
-       u8 id;
- } sam9x60_systemck[] = {
--      { .n = "ddrck",  .p = "masterck", .id = 2 },
-+      { .n = "ddrck",  .p = "masterck_div", .id = 2 },
-       { .n = "uhpck",  .p = "usbck",    .id = 6 },
-       { .n = "pck0",   .p = "prog0",    .id = 8 },
-       { .n = "pck1",   .p = "prog1",    .id = 9 },
--      { .n = "qspick", .p = "masterck", .id = 19 },
-+      { .n = "qspick", .p = "masterck_div", .id = 19 },
- };
- static const struct {
-@@ -268,9 +269,17 @@ static void __init sam9x60_pmc_setup(str
-       parent_names[0] = md_slck_name;
-       parent_names[1] = "mainck";
-       parent_names[2] = "pllack_divck";
--      hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
--                                    &sam9x60_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3,
-+                                         parent_names, &sam9x60_master_layout,
-+                                         &mck_characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres", &sam9x60_master_layout,
-+                                        &mck_characteristics, &mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -286,7 +295,7 @@ static void __init sam9x60_pmc_setup(str
-       parent_names[0] = md_slck_name;
-       parent_names[1] = td_slck_name;
-       parent_names[2] = "mainck";
--      parent_names[3] = "masterck";
-+      parent_names[3] = "masterck_div";
-       parent_names[4] = "pllack_divck";
-       parent_names[5] = "upllck_divck";
-       for (i = 0; i < 2; i++) {
-@@ -318,7 +327,7 @@ static void __init sam9x60_pmc_setup(str
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &sam9x60_pcr_layout,
-                                                        sam9x60_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        sam9x60_periphck[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
---- a/drivers/clk/at91/sama5d2.c
-+++ b/drivers/clk/at91/sama5d2.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 124000000, .max = 166000000 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -40,14 +42,14 @@ static const struct {
-       char *p;
-       u8 id;
- } sama5d2_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
--      { .n = "lcdck", .p = "masterck", .id = 3 },
--      { .n = "uhpck", .p = "usbck",    .id = 6 },
--      { .n = "udpck", .p = "usbck",    .id = 7 },
--      { .n = "pck0",  .p = "prog0",    .id = 8 },
--      { .n = "pck1",  .p = "prog1",    .id = 9 },
--      { .n = "pck2",  .p = "prog2",    .id = 10 },
--      { .n = "iscck", .p = "masterck", .id = 18 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-+      { .n = "lcdck", .p = "masterck_div", .id = 3 },
-+      { .n = "uhpck", .p = "usbck",        .id = 6 },
-+      { .n = "udpck", .p = "usbck",        .id = 7 },
-+      { .n = "pck0",  .p = "prog0",        .id = 8 },
-+      { .n = "pck1",  .p = "prog1",        .id = 9 },
-+      { .n = "pck2",  .p = "prog2",        .id = 10 },
-+      { .n = "iscck", .p = "masterck_div", .id = 18 },
- };
- static const struct {
-@@ -235,15 +237,25 @@ static void __init sama5d2_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91sam9x5_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91sam9x5_master_layout,
-+                                         &mck_characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91sam9x5_master_layout,
-+                                        &mck_characteristics, &mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-       sama5d2_pmc->chws[PMC_MCK] = hw;
--      hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
-+      hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -259,7 +271,7 @@ static void __init sama5d2_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       parent_names[5] = "audiopll_pmcck";
-       for (i = 0; i < 3; i++) {
-               char name[6];
-@@ -290,7 +302,7 @@ static void __init sama5d2_pmc_setup(str
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &sama5d2_pcr_layout,
-                                                        sama5d2_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        sama5d2_periphck[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
-@@ -317,7 +329,7 @@ static void __init sama5d2_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       parent_names[5] = "audiopll_pmcck";
-       for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
-               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
---- a/drivers/clk/at91/sama5d3.c
-+++ b/drivers/clk/at91/sama5d3.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 0, .max = 166000000 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -40,14 +42,14 @@ static const struct {
-       char *p;
-       u8 id;
- } sama5d3_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
--      { .n = "lcdck", .p = "masterck", .id = 3 },
--      { .n = "smdck", .p = "smdclk",   .id = 4 },
--      { .n = "uhpck", .p = "usbck",    .id = 6 },
--      { .n = "udpck", .p = "usbck",    .id = 7 },
--      { .n = "pck0",  .p = "prog0",    .id = 8 },
--      { .n = "pck1",  .p = "prog1",    .id = 9 },
--      { .n = "pck2",  .p = "prog2",    .id = 10 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-+      { .n = "lcdck", .p = "masterck_div", .id = 3 },
-+      { .n = "smdck", .p = "smdclk",       .id = 4 },
-+      { .n = "uhpck", .p = "usbck",        .id = 6 },
-+      { .n = "udpck", .p = "usbck",        .id = 7 },
-+      { .n = "pck0",  .p = "prog0",        .id = 8 },
-+      { .n = "pck1",  .p = "prog1",        .id = 9 },
-+      { .n = "pck2",  .p = "prog2",        .id = 10 },
- };
- static const struct {
-@@ -170,9 +172,19 @@ static void __init sama5d3_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91sam9x5_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91sam9x5_master_layout,
-+                                         &mck_characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91sam9x5_master_layout,
-+                                        &mck_characteristics, &mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -192,7 +204,7 @@ static void __init sama5d3_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 3; i++) {
-               char name[6];
-@@ -222,7 +234,7 @@ static void __init sama5d3_pmc_setup(str
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &sama5d3_pcr_layout,
-                                                        sama5d3_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        sama5d3_periphck[i].id,
-                                                        &sama5d3_periphck[i].r,
-                                                        INT_MIN);
---- a/drivers/clk/at91/sama5d4.c
-+++ b/drivers/clk/at91/sama5d4.c
-@@ -7,6 +7,8 @@
- #include "pmc.h"
-+static DEFINE_SPINLOCK(mck_lock);
-+
- static const struct clk_master_characteristics mck_characteristics = {
-       .output = { .min = 125000000, .max = 200000000 },
-       .divisors = { 1, 2, 4, 3 },
-@@ -39,14 +41,14 @@ static const struct {
-       char *p;
-       u8 id;
- } sama5d4_systemck[] = {
--      { .n = "ddrck", .p = "masterck", .id = 2 },
--      { .n = "lcdck", .p = "masterck", .id = 3 },
--      { .n = "smdck", .p = "smdclk",   .id = 4 },
--      { .n = "uhpck", .p = "usbck",    .id = 6 },
--      { .n = "udpck", .p = "usbck",    .id = 7 },
--      { .n = "pck0",  .p = "prog0",    .id = 8 },
--      { .n = "pck1",  .p = "prog1",    .id = 9 },
--      { .n = "pck2",  .p = "prog2",    .id = 10 },
-+      { .n = "ddrck", .p = "masterck_div", .id = 2 },
-+      { .n = "lcdck", .p = "masterck_div", .id = 3 },
-+      { .n = "smdck", .p = "smdclk",       .id = 4 },
-+      { .n = "uhpck", .p = "usbck",        .id = 6 },
-+      { .n = "udpck", .p = "usbck",        .id = 7 },
-+      { .n = "pck0",  .p = "prog0",        .id = 8 },
-+      { .n = "pck1",  .p = "prog1",        .id = 9 },
-+      { .n = "pck2",  .p = "prog2",        .id = 10 },
- };
- static const struct {
-@@ -185,15 +187,25 @@ static void __init sama5d4_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
--                                    &at91sam9x5_master_layout,
--                                    &mck_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
-+                                         parent_names,
-+                                         &at91sam9x5_master_layout,
-+                                         &mck_characteristics, &mck_lock,
-+                                         CLK_SET_RATE_GATE, INT_MIN);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "masterck_div",
-+                                        "masterck_pres",
-+                                        &at91sam9x5_master_layout,
-+                                        &mck_characteristics, &mck_lock,
-+                                        CLK_SET_RATE_GATE);
-       if (IS_ERR(hw))
-               goto err_free;
-       sama5d4_pmc->chws[PMC_MCK] = hw;
--      hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
-+      hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
-       if (IS_ERR(hw))
-               goto err_free;
-@@ -215,7 +227,7 @@ static void __init sama5d4_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "plladivck";
-       parent_names[3] = "utmick";
--      parent_names[4] = "masterck";
-+      parent_names[4] = "masterck_div";
-       for (i = 0; i < 3; i++) {
-               char name[6];
-@@ -245,7 +257,7 @@ static void __init sama5d4_pmc_setup(str
-               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
-                                                        &sama5d4_pcr_layout,
-                                                        sama5d4_periphck[i].n,
--                                                       "masterck",
-+                                                       "masterck_div",
-                                                        sama5d4_periphck[i].id,
-                                                        &range, INT_MIN);
-               if (IS_ERR(hw))
---- a/drivers/clk/at91/sama7g5.c
-+++ b/drivers/clk/at91/sama7g5.c
-@@ -32,6 +32,7 @@
-       } while (0)
- static DEFINE_SPINLOCK(pmc_pll_lock);
-+static DEFINE_SPINLOCK(pmc_mck0_lock);
- static DEFINE_SPINLOCK(pmc_mckX_lock);
- /**
-@@ -984,8 +985,16 @@ static void __init sama7g5_pmc_setup(str
-       parent_names[1] = "mainck";
-       parent_names[2] = "cpupll_divpmcck";
-       parent_names[3] = "syspll_divpmcck";
--      hw = at91_clk_register_master(regmap, "mck0", 4, parent_names,
--                                    &mck0_layout, &mck0_characteristics);
-+      hw = at91_clk_register_master_pres(regmap, "mck0_pres", 4, parent_names,
-+                                         &mck0_layout, &mck0_characteristics,
-+                                         &pmc_mck0_lock,
-+                                         CLK_SET_RATE_PARENT, 0);
-+      if (IS_ERR(hw))
-+              goto err_free;
-+
-+      hw = at91_clk_register_master_div(regmap, "mck0_div", "mck0_pres",
-+                                        &mck0_layout, &mck0_characteristics,
-+                                        &pmc_mck0_lock, 0);
-       if (IS_ERR(hw))
-               goto err_free;