diff options
Diffstat (limited to 'target/linux/at91/patches-5.10/110-clk-at91-clk-master-re-factor-master-clock.patch')
-rw-r--r-- | target/linux/at91/patches-5.10/110-clk-at91-clk-master-re-factor-master-clock.patch | 1230 |
1 files changed, 0 insertions, 1230 deletions
diff --git a/target/linux/at91/patches-5.10/110-clk-at91-clk-master-re-factor-master-clock.patch b/target/linux/at91/patches-5.10/110-clk-at91-clk-master-re-factor-master-clock.patch deleted file mode 100644 index a0eadd8886..0000000000 --- a/target/linux/at91/patches-5.10/110-clk-at91-clk-master-re-factor-master-clock.patch +++ /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; - |