Commit 43b1bb4a authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Stephen Boyd

clk: at91: clk-sam9x60-pll: re-factor to support plls with multiple outputs

Some of the SAMA7G5 PLLs support multiple outputs (e.g. AUDIO PLL).
For these, split the PLL clock in two: fractional clock and
divider clock. In case PLLs supports multiple outputs (since these
outputs are dividers (with different settings) sharing the same
fractional part), it will register one fractional clock and multiple
divider clocks (dividers sharing the fractional clock).
Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Link: https://lore.kernel.org/r/1595403506-8209-17-git-send-email-claudiu.beznea@microchip.comSigned-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 0416824e
This diff is collapsed.
...@@ -54,8 +54,14 @@ struct clk_master_characteristics { ...@@ -54,8 +54,14 @@ struct clk_master_characteristics {
struct clk_pll_layout { struct clk_pll_layout {
u32 pllr_mask; u32 pllr_mask;
u16 mul_mask; u32 mul_mask;
u32 frac_mask;
u32 div_mask;
u32 endiv_mask;
u8 mul_shift; u8 mul_shift;
u8 frac_shift;
u8 div_shift;
u8 endiv_shift;
}; };
extern const struct clk_pll_layout at91rm9200_pll_layout; extern const struct clk_pll_layout at91rm9200_pll_layout;
...@@ -181,9 +187,17 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name, ...@@ -181,9 +187,17 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name); const char *parent_name);
struct clk_hw * __init struct clk_hw * __init
sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock, sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name, u8 id, const char *name, const char *parent_name, u8 id,
const struct clk_pll_characteristics *characteristics); const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical);
struct clk_hw * __init
sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
struct clk_hw *parent_hw, u8 id,
const struct clk_pll_characteristics *characteristics,
const struct clk_pll_layout *layout, bool critical);
struct clk_hw * __init struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name, at91_clk_register_programmable(struct regmap *regmap, const char *name,
......
...@@ -42,6 +42,20 @@ static const struct clk_pll_characteristics upll_characteristics = { ...@@ -42,6 +42,20 @@ static const struct clk_pll_characteristics upll_characteristics = {
.upll = true, .upll = true,
}; };
static const struct clk_pll_layout pll_frac_layout = {
.mul_mask = GENMASK(31, 24),
.frac_mask = GENMASK(21, 0),
.mul_shift = 24,
.frac_shift = 0,
};
static const struct clk_pll_layout pll_div_layout = {
.div_mask = GENMASK(7, 0),
.endiv_mask = BIT(29),
.div_shift = 0,
.endiv_shift = 29,
};
static const struct clk_programmable_layout sam9x60_programmable_layout = { static const struct clk_programmable_layout sam9x60_programmable_layout = {
.pres_mask = 0xff, .pres_mask = 0xff,
.pres_shift = 8, .pres_shift = 8,
...@@ -156,6 +170,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -156,6 +170,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
const char *td_slck_name, *md_slck_name, *mainxtal_name; const char *td_slck_name, *md_slck_name, *mainxtal_name;
struct pmc_data *sam9x60_pmc; struct pmc_data *sam9x60_pmc;
const char *parent_names[6]; const char *parent_names[6];
struct clk_hw *main_osc_hw;
struct regmap *regmap; struct regmap *regmap;
struct clk_hw *hw; struct clk_hw *hw;
int i; int i;
...@@ -200,6 +215,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -200,6 +215,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
bypass); bypass);
if (IS_ERR(hw)) if (IS_ERR(hw))
goto err_free; goto err_free;
main_osc_hw = hw;
parent_names[0] = "main_rc_osc"; parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc"; parent_names[1] = "main_osc";
...@@ -209,15 +225,31 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -209,15 +225,31 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
sam9x60_pmc->chws[PMC_MAIN] = hw; sam9x60_pmc->chws[PMC_MAIN] = hw;
hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "pllack", hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
"mainck", 0, &plla_characteristics); "mainck", sam9x60_pmc->chws[PMC_MAIN],
0, &plla_characteristics,
&pll_frac_layout, true);
if (IS_ERR(hw))
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
"pllack_fracck", 0, &plla_characteristics,
&pll_div_layout, true);
if (IS_ERR(hw)) if (IS_ERR(hw))
goto err_free; goto err_free;
sam9x60_pmc->chws[PMC_PLLACK] = hw; sam9x60_pmc->chws[PMC_PLLACK] = hw;
hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck", hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
"main_osc", 1, &upll_characteristics); "main_osc", main_osc_hw, 1,
&upll_characteristics,
&pll_frac_layout, false);
if (IS_ERR(hw))
goto err_free;
hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
"upllck_fracck", 1, &upll_characteristics,
&pll_div_layout, false);
if (IS_ERR(hw)) if (IS_ERR(hw))
goto err_free; goto err_free;
...@@ -225,7 +257,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -225,7 +257,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[0] = md_slck_name; parent_names[0] = md_slck_name;
parent_names[1] = "mainck"; parent_names[1] = "mainck";
parent_names[2] = "pllack"; parent_names[2] = "pllack_divck";
hw = at91_clk_register_master(regmap, "masterck", 3, parent_names, hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
&sam9x60_master_layout, &sam9x60_master_layout,
&mck_characteristics); &mck_characteristics);
...@@ -234,8 +266,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -234,8 +266,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
sam9x60_pmc->chws[PMC_MCK] = hw; sam9x60_pmc->chws[PMC_MCK] = hw;
parent_names[0] = "pllack"; parent_names[0] = "pllack_divck";
parent_names[1] = "upllck"; parent_names[1] = "upllck_divck";
parent_names[2] = "main_osc"; parent_names[2] = "main_osc";
hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3); hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
if (IS_ERR(hw)) if (IS_ERR(hw))
...@@ -245,8 +277,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) ...@@ -245,8 +277,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[1] = td_slck_name; parent_names[1] = td_slck_name;
parent_names[2] = "mainck"; parent_names[2] = "mainck";
parent_names[3] = "masterck"; parent_names[3] = "masterck";
parent_names[4] = "pllack"; parent_names[4] = "pllack_divck";
parent_names[5] = "upllck"; parent_names[5] = "upllck_divck";
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
char name[6]; char name[6];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment