Commit 148edd50 authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'meson-clk-4.20-1' of https://github.com/BayLibre/clk-meson into clk-meson

Pull meson clk driver updates from Jerome Brunet:

 - clk-pll driver improvements and updates
 - add axg audio controller system clocks
 - drop mpll3 from the possible pcie clock parent of the axg
 - register meson8b clock controller early

* tag 'meson-clk-4.20-1' of https://github.com/BayLibre/clk-meson:
  clk: meson: meson8b: use the regmap in the internal reset controller
  clk: meson: meson8b: register the clock controller early
  clk: meson-axg: pcie: drop the mpll3 clock parent
  clk: meson: axg: round audio system master clocks down
  clk: meson: clk-pll: drop hard-coded rates from pll tables
  clk: meson: clk-pll: remove od parameters
  clk: meson: clk-pll: drop CLK_GET_RATE_NOCACHE where unnecessary
  clk: meson: clk-pll: add enable bit
parents 5b394b2d 93c873d6
...@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = { ...@@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = {
"axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7", "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
}; };
#define AXG_MST_MCLK_MUX(_name, _reg) \ #define AXG_MST_MUX(_name, _reg, _flag) \
AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \ AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT) mst_mux_parent_names, CLK_SET_RATE_PARENT)
#define AXG_MST_MCLK_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
#define AXG_MST_SYS_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, 0)
static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL); static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL); static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL); static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
...@@ -112,13 +118,19 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL); ...@@ -112,13 +118,19 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL); static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL); static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); static AXG_MST_SYS_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_DIV(_name, _reg, _flag) \
AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
"axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
#define AXG_MST_MCLK_DIV(_name, _reg) \
AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
#define AXG_MST_MCLK_DIV(_name, _reg) \ #define AXG_MST_SYS_DIV(_name, _reg) \
AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \ AXG_MST_DIV(_name, _reg, 0)
"axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL); static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL); static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
...@@ -127,12 +139,12 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL); ...@@ -127,12 +139,12 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL); static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL); static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL); static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0); static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1); static AXG_MST_SYS_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_MCLK_GATE(_name, _reg) \ #define AXG_MST_MCLK_GATE(_name, _reg) \
AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \ AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
CLK_SET_RATE_PARENT) CLK_SET_RATE_PARENT)
static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL); static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
......
...@@ -22,8 +22,13 @@ ...@@ -22,8 +22,13 @@
static DEFINE_SPINLOCK(meson_clk_lock); static DEFINE_SPINLOCK(meson_clk_lock);
static struct clk_regmap axg_fixed_pll = { static struct clk_regmap axg_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_MPLL_CNTL, .reg_off = HHI_MPLL_CNTL,
.shift = 0, .shift = 0,
...@@ -34,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = { ...@@ -34,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_MPLL_CNTL2, .reg_off = HHI_MPLL_CNTL2,
.shift = 0, .shift = 0,
...@@ -56,15 +56,39 @@ static struct clk_regmap axg_fixed_pll = { ...@@ -56,15 +56,39 @@ static struct clk_regmap axg_fixed_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "fixed_pll", .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
}, },
}; };
static struct clk_regmap axg_sys_pll = { static struct clk_regmap axg_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
},
};
static struct clk_regmap axg_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -75,11 +99,6 @@ static struct clk_regmap axg_sys_pll = { ...@@ -75,11 +99,6 @@ static struct clk_regmap axg_sys_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -92,102 +111,59 @@ static struct clk_regmap axg_sys_pll = { ...@@ -92,102 +111,59 @@ static struct clk_regmap axg_sys_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "sys_pll", .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
}, },
}; };
static const struct pll_rate_table axg_gp0_pll_rate_table[] = { static struct clk_regmap axg_sys_pll = {
PLL_RATE(240000000, 40, 1, 2), .data = &(struct clk_regmap_div_data){
PLL_RATE(246000000, 41, 1, 2), .offset = HHI_SYS_PLL_CNTL,
PLL_RATE(252000000, 42, 1, 2), .shift = 16,
PLL_RATE(258000000, 43, 1, 2), .width = 2,
PLL_RATE(264000000, 44, 1, 2), .flags = CLK_DIVIDER_POWER_OF_TWO,
PLL_RATE(270000000, 45, 1, 2), },
PLL_RATE(276000000, 46, 1, 2), .hw.init = &(struct clk_init_data){
PLL_RATE(282000000, 47, 1, 2), .name = "sys_pll",
PLL_RATE(288000000, 48, 1, 2), .ops = &clk_regmap_divider_ro_ops,
PLL_RATE(294000000, 49, 1, 2), .parent_names = (const char *[]){ "sys_pll_dco" },
PLL_RATE(300000000, 50, 1, 2), .num_parents = 1,
PLL_RATE(306000000, 51, 1, 2), .flags = CLK_SET_RATE_PARENT,
PLL_RATE(312000000, 52, 1, 2), },
PLL_RATE(318000000, 53, 1, 2), };
PLL_RATE(324000000, 54, 1, 2),
PLL_RATE(330000000, 55, 1, 2), static const struct pll_params_table axg_gp0_pll_params_table[] = {
PLL_RATE(336000000, 56, 1, 2), PLL_PARAMS(40, 1),
PLL_RATE(342000000, 57, 1, 2), PLL_PARAMS(41, 1),
PLL_RATE(348000000, 58, 1, 2), PLL_PARAMS(42, 1),
PLL_RATE(354000000, 59, 1, 2), PLL_PARAMS(43, 1),
PLL_RATE(360000000, 60, 1, 2), PLL_PARAMS(44, 1),
PLL_RATE(366000000, 61, 1, 2), PLL_PARAMS(45, 1),
PLL_RATE(372000000, 62, 1, 2), PLL_PARAMS(46, 1),
PLL_RATE(378000000, 63, 1, 2), PLL_PARAMS(47, 1),
PLL_RATE(384000000, 64, 1, 2), PLL_PARAMS(48, 1),
PLL_RATE(390000000, 65, 1, 3), PLL_PARAMS(49, 1),
PLL_RATE(396000000, 66, 1, 3), PLL_PARAMS(50, 1),
PLL_RATE(402000000, 67, 1, 3), PLL_PARAMS(51, 1),
PLL_RATE(408000000, 68, 1, 3), PLL_PARAMS(52, 1),
PLL_RATE(480000000, 40, 1, 1), PLL_PARAMS(53, 1),
PLL_RATE(492000000, 41, 1, 1), PLL_PARAMS(54, 1),
PLL_RATE(504000000, 42, 1, 1), PLL_PARAMS(55, 1),
PLL_RATE(516000000, 43, 1, 1), PLL_PARAMS(56, 1),
PLL_RATE(528000000, 44, 1, 1), PLL_PARAMS(57, 1),
PLL_RATE(540000000, 45, 1, 1), PLL_PARAMS(58, 1),
PLL_RATE(552000000, 46, 1, 1), PLL_PARAMS(59, 1),
PLL_RATE(564000000, 47, 1, 1), PLL_PARAMS(60, 1),
PLL_RATE(576000000, 48, 1, 1), PLL_PARAMS(61, 1),
PLL_RATE(588000000, 49, 1, 1), PLL_PARAMS(62, 1),
PLL_RATE(600000000, 50, 1, 1), PLL_PARAMS(63, 1),
PLL_RATE(612000000, 51, 1, 1), PLL_PARAMS(64, 1),
PLL_RATE(624000000, 52, 1, 1), PLL_PARAMS(65, 1),
PLL_RATE(636000000, 53, 1, 1), PLL_PARAMS(66, 1),
PLL_RATE(648000000, 54, 1, 1), PLL_PARAMS(67, 1),
PLL_RATE(660000000, 55, 1, 1), PLL_PARAMS(68, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(684000000, 57, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(708000000, 59, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(732000000, 61, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(756000000, 63, 1, 1),
PLL_RATE(768000000, 64, 1, 1),
PLL_RATE(780000000, 65, 1, 1),
PLL_RATE(792000000, 66, 1, 1),
PLL_RATE(804000000, 67, 1, 1),
PLL_RATE(816000000, 68, 1, 1),
PLL_RATE(960000000, 40, 1, 0),
PLL_RATE(984000000, 41, 1, 0),
PLL_RATE(1008000000, 42, 1, 0),
PLL_RATE(1032000000, 43, 1, 0),
PLL_RATE(1056000000, 44, 1, 0),
PLL_RATE(1080000000, 45, 1, 0),
PLL_RATE(1104000000, 46, 1, 0),
PLL_RATE(1128000000, 47, 1, 0),
PLL_RATE(1152000000, 48, 1, 0),
PLL_RATE(1176000000, 49, 1, 0),
PLL_RATE(1200000000, 50, 1, 0),
PLL_RATE(1224000000, 51, 1, 0),
PLL_RATE(1248000000, 52, 1, 0),
PLL_RATE(1272000000, 53, 1, 0),
PLL_RATE(1296000000, 54, 1, 0),
PLL_RATE(1320000000, 55, 1, 0),
PLL_RATE(1344000000, 56, 1, 0),
PLL_RATE(1368000000, 57, 1, 0),
PLL_RATE(1392000000, 58, 1, 0),
PLL_RATE(1416000000, 59, 1, 0),
PLL_RATE(1440000000, 60, 1, 0),
PLL_RATE(1464000000, 61, 1, 0),
PLL_RATE(1488000000, 62, 1, 0),
PLL_RATE(1512000000, 63, 1, 0),
PLL_RATE(1536000000, 64, 1, 0),
PLL_RATE(1560000000, 65, 1, 0),
PLL_RATE(1584000000, 66, 1, 0),
PLL_RATE(1608000000, 67, 1, 0),
PLL_RATE(1632000000, 68, 1, 0),
{ /* sentinel */ }, { /* sentinel */ },
}; };
...@@ -197,11 +173,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = { ...@@ -197,11 +173,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
}; };
static struct clk_regmap axg_gp0_pll = { static struct clk_regmap axg_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_GP0_PLL_CNTL, .reg_off = HHI_GP0_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -212,11 +192,6 @@ static struct clk_regmap axg_gp0_pll = { ...@@ -212,11 +192,6 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_GP0_PLL_CNTL1, .reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0, .shift = 0,
...@@ -232,29 +207,49 @@ static struct clk_regmap axg_gp0_pll = { ...@@ -232,29 +207,49 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = axg_gp0_pll_rate_table, .table = axg_gp0_pll_params_table,
.init_regs = axg_gp0_init_regs, .init_regs = axg_gp0_init_regs,
.init_count = ARRAY_SIZE(axg_gp0_init_regs), .init_count = ARRAY_SIZE(axg_gp0_init_regs),
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "gp0_pll", .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
}, },
}; };
static struct clk_regmap axg_gp0_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct reg_sequence axg_hifi_init_regs[] = { static const struct reg_sequence axg_hifi_init_regs[] = {
{ .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 }, { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
{ .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 }, { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
{ .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 }, { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
{ .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
}; };
static struct clk_regmap axg_hifi_pll = { static struct clk_regmap axg_hifi_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_HIFI_PLL_CNTL, .reg_off = HHI_HIFI_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -265,11 +260,6 @@ static struct clk_regmap axg_hifi_pll = { ...@@ -265,11 +260,6 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_HIFI_PLL_CNTL5, .reg_off = HHI_HIFI_PLL_CNTL5,
.shift = 0, .shift = 0,
...@@ -285,19 +275,35 @@ static struct clk_regmap axg_hifi_pll = { ...@@ -285,19 +275,35 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = axg_gp0_pll_rate_table, .table = axg_gp0_pll_params_table,
.init_regs = axg_hifi_init_regs, .init_regs = axg_hifi_init_regs,
.init_count = ARRAY_SIZE(axg_hifi_init_regs), .init_count = ARRAY_SIZE(axg_hifi_init_regs),
.flags = CLK_MESON_PLL_ROUND_CLOSEST, .flags = CLK_MESON_PLL_ROUND_CLOSEST,
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "hifi_pll", .name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
}, },
}; };
static struct clk_regmap axg_hifi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HIFI_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "hifi_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor axg_fclk_div2_div = { static struct clk_fixed_factor axg_fclk_div2_div = {
.mult = 1, .mult = 1,
.div = 2, .div = 2,
...@@ -625,29 +631,31 @@ static struct clk_regmap axg_mpll3 = { ...@@ -625,29 +631,31 @@ static struct clk_regmap axg_mpll3 = {
}, },
}; };
static const struct pll_rate_table axg_pcie_pll_rate_table[] = { static const struct pll_params_table axg_pcie_pll_params_table[] = {
{ {
.rate = 100000000, .m = 200,
.m = 200, .n = 3,
.n = 3,
.od = 1,
.od2 = 3,
}, },
{ /* sentinel */ }, { /* sentinel */ },
}; };
static const struct reg_sequence axg_pcie_init_regs[] = { static const struct reg_sequence axg_pcie_init_regs[] = {
{ .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
{ .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa }, { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa },
{ .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be }, { .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e }, { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e },
{ .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 }, { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 }, { .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 },
{ .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
}; };
static struct clk_regmap axg_pcie_pll = { static struct clk_regmap axg_pcie_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_PCIE_PLL_CNTL, .reg_off = HHI_PCIE_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -658,16 +666,6 @@ static struct clk_regmap axg_pcie_pll = { ...@@ -658,16 +666,6 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 16,
.width = 2,
},
.od2 = {
.reg_off = HHI_PCIE_PLL_CNTL6,
.shift = 6,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_PCIE_PLL_CNTL1, .reg_off = HHI_PCIE_PLL_CNTL1,
.shift = 0, .shift = 0,
...@@ -683,29 +681,63 @@ static struct clk_regmap axg_pcie_pll = { ...@@ -683,29 +681,63 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = axg_pcie_pll_rate_table, .table = axg_pcie_pll_params_table,
.init_regs = axg_pcie_init_regs, .init_regs = axg_pcie_init_regs,
.init_count = ARRAY_SIZE(axg_pcie_init_regs), .init_count = ARRAY_SIZE(axg_pcie_init_regs),
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "pcie_pll", .name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
}, },
}; };
static struct clk_regmap axg_pcie_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_PCIE_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap axg_pcie_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_PCIE_PLL_CNTL6,
.shift = 6,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_od" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap axg_pcie_mux = { static struct clk_regmap axg_pcie_mux = {
.data = &(struct clk_regmap_mux_data){ .data = &(struct clk_regmap_mux_data){
.offset = HHI_PCIE_PLL_CNTL6, .offset = HHI_PCIE_PLL_CNTL6,
.mask = 0x1, .mask = 0x1,
.shift = 2, .shift = 2,
/* skip the parent mpll3, reserved for debug */
.table = (u32[]){ 1 },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "pcie_mux", .name = "pcie_mux",
.ops = &clk_regmap_mux_ops, .ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "mpll3", "pcie_pll" }, .parent_names = (const char *[]){ "pcie_pll" },
.num_parents = 2, .num_parents = 1,
.flags = CLK_SET_RATE_PARENT, .flags = CLK_SET_RATE_PARENT,
}, },
}; };
...@@ -1107,6 +1139,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { ...@@ -1107,6 +1139,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw, [CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw, [CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw,
[CLKID_GEN_CLK] = &axg_gen_clk.hw, [CLKID_GEN_CLK] = &axg_gen_clk.hw,
[CLKID_SYS_PLL_DCO] = &axg_sys_pll_dco.hw,
[CLKID_FIXED_PLL_DCO] = &axg_fixed_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &axg_gp0_pll_dco.hw,
[CLKID_HIFI_PLL_DCO] = &axg_hifi_pll_dco.hw,
[CLKID_PCIE_PLL_DCO] = &axg_pcie_pll_dco.hw,
[CLKID_PCIE_PLL_OD] = &axg_pcie_pll_od.hw,
[NR_CLKS] = NULL, [NR_CLKS] = NULL,
}, },
.num = NR_CLKS, .num = NR_CLKS,
...@@ -1185,6 +1223,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = { ...@@ -1185,6 +1223,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_fclk_div4, &axg_fclk_div4,
&axg_fclk_div5, &axg_fclk_div5,
&axg_fclk_div7, &axg_fclk_div7,
&axg_pcie_pll_dco,
&axg_pcie_pll_od,
&axg_pcie_pll, &axg_pcie_pll,
&axg_pcie_mux, &axg_pcie_mux,
&axg_pcie_ref, &axg_pcie_ref,
...@@ -1194,6 +1234,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = { ...@@ -1194,6 +1234,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_gen_clk_sel, &axg_gen_clk_sel,
&axg_gen_clk_div, &axg_gen_clk_div,
&axg_gen_clk, &axg_gen_clk,
&axg_fixed_pll_dco,
&axg_sys_pll_dco,
&axg_gp0_pll_dco,
&axg_hifi_pll_dco,
&axg_pcie_pll_dco,
&axg_pcie_pll_od,
}; };
static const struct of_device_id clkc_match_table[] = { static const struct of_device_id clkc_match_table[] = {
......
...@@ -133,8 +133,14 @@ ...@@ -133,8 +133,14 @@
#define CLKID_PCIE_REF 78 #define CLKID_PCIE_REF 78
#define CLKID_GEN_CLK_SEL 82 #define CLKID_GEN_CLK_SEL 82
#define CLKID_GEN_CLK_DIV 83 #define CLKID_GEN_CLK_DIV 83
#define CLKID_SYS_PLL_DCO 85
#define CLKID_FIXED_PLL_DCO 86
#define CLKID_GP0_PLL_DCO 87
#define CLKID_HIFI_PLL_DCO 88
#define CLKID_PCIE_PLL_DCO 89
#define CLKID_PCIE_PLL_OD 90
#define NR_CLKS 85 #define NR_CLKS 91
/* include the CLKIDs that have been made part of the DT binding */ /* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h> #include <dt-bindings/clock/axg-clkc.h>
......
...@@ -11,15 +11,19 @@ ...@@ -11,15 +11,19 @@
* In the most basic form, a Meson PLL is composed as follows: * In the most basic form, a Meson PLL is composed as follows:
* *
* PLL * PLL
* +------------------------------+ * +--------------------------------+
* | | * | |
* in -----[ /N ]---[ *M ]---[ >>OD ]----->> out * | +--+ |
* | ^ ^ | * in >>-----[ /N ]--->| | +-----+ |
* +------------------------------+ * | | |------| DCO |---->> out
* | | * | +--------->| | +--v--+ |
* FREF VCO * | | +--+ | |
* | | | |
* | +--[ *(M + (F/Fmax) ]<--+ |
* | |
* +--------------------------------+
* *
* out = in * (m + frac / frac_max) / (n << sum(ods)) * out = in * (m + frac / frac_max) / n
*/ */
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
...@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk) ...@@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk)
} }
static unsigned long __pll_params_to_rate(unsigned long parent_rate, static unsigned long __pll_params_to_rate(unsigned long parent_rate,
const struct pll_rate_table *pllt, const struct pll_params_table *pllt,
u16 frac, u16 frac,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
u64 rate = (u64)parent_rate * pllt->m; u64 rate = (u64)parent_rate * pllt->m;
unsigned int od = pllt->od + pllt->od2 + pllt->od3;
if (frac && MESON_PARM_APPLICABLE(&pll->frac)) { if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac; u64 frac_rate = (u64)parent_rate * frac;
...@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate, ...@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
(1 << pll->frac.width)); (1 << pll->frac.width));
} }
return DIV_ROUND_UP_ULL(rate, pllt->n << od); return DIV_ROUND_UP_ULL(rate, pllt->n);
} }
static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
...@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, ...@@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
struct pll_rate_table pllt; struct pll_params_table pllt;
u16 frac; u16 frac;
pllt.n = meson_parm_read(clk->map, &pll->n); pllt.n = meson_parm_read(clk->map, &pll->n);
pllt.m = meson_parm_read(clk->map, &pll->m); pllt.m = meson_parm_read(clk->map, &pll->m);
pllt.od = meson_parm_read(clk->map, &pll->od);
pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
meson_parm_read(clk->map, &pll->od2) :
0;
pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
meson_parm_read(clk->map, &pll->od3) :
0;
frac = MESON_PARM_APPLICABLE(&pll->frac) ? frac = MESON_PARM_APPLICABLE(&pll->frac) ?
meson_parm_read(clk->map, &pll->frac) : meson_parm_read(clk->map, &pll->frac) :
...@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, ...@@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
static u16 __pll_params_with_frac(unsigned long rate, static u16 __pll_params_with_frac(unsigned long rate,
unsigned long parent_rate, unsigned long parent_rate,
const struct pll_rate_table *pllt, const struct pll_params_table *pllt,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
u16 frac_max = (1 << pll->frac.width); u16 frac_max = (1 << pll->frac.width);
u64 val = (u64)rate * pllt->n; u64 val = (u64)rate * pllt->n;
val <<= pllt->od + pllt->od2 + pllt->od3;
if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
else else
...@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate, ...@@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
return min((u16)val, (u16)(frac_max - 1)); return min((u16)val, (u16)(frac_max - 1));
} }
static const struct pll_rate_table * static bool meson_clk_pll_is_better(unsigned long rate,
unsigned long best,
unsigned long now,
struct meson_clk_pll_data *pll)
{
if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
MESON_PARM_APPLICABLE(&pll->frac)) {
/* Round down */
if (now < rate && best < now)
return true;
} else {
/* Round Closest */
if (abs(now - rate) < abs(best - rate))
return true;
}
return false;
}
static const struct pll_params_table *
meson_clk_get_pll_settings(unsigned long rate, meson_clk_get_pll_settings(unsigned long rate,
unsigned long parent_rate,
struct meson_clk_pll_data *pll) struct meson_clk_pll_data *pll)
{ {
const struct pll_rate_table *table = pll->table; const struct pll_params_table *table = pll->table;
unsigned int i = 0; unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
if (!table) if (!table)
return NULL; return NULL;
/* Find the first table element exceeding rate */ for (i = 0; table[i].n; i++) {
while (table[i].rate && table[i].rate <= rate) now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
i++;
if (i != 0) { /* If we get an exact match, don't bother any further */
if (MESON_PARM_APPLICABLE(&pll->frac) || if (now == rate) {
!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) || return &table[i];
(abs(rate - table[i - 1].rate) < } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
abs(rate - table[i].rate))) best = now;
i--; best_i = i;
}
} }
return (struct pll_rate_table *)&table[i]; return (struct pll_params_table *)&table[best_i];
} }
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
...@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt = const struct pll_params_table *pllt =
meson_clk_get_pll_settings(rate, pll); meson_clk_get_pll_settings(rate, *parent_rate, pll);
unsigned long round;
u16 frac; u16 frac;
if (!pllt) if (!pllt)
return meson_clk_pll_recalc_rate(hw, *parent_rate); return meson_clk_pll_recalc_rate(hw, *parent_rate);
if (!MESON_PARM_APPLICABLE(&pll->frac) round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
|| rate == pllt->rate)
return pllt->rate; if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
return round;
/* /*
* The rate provided by the setting is not an exact match, let's * The rate provided by the setting is not an exact match, let's
...@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw) ...@@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
} }
} }
static int meson_clk_pll_enable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Make sure the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */
meson_parm_write(clk->map, &pll->rst, 0);
if (meson_clk_pll_wait_lock(hw))
return -EIO;
return 0;
}
static void meson_clk_pll_disable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Put the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Disable the pll */
meson_parm_write(clk->map, &pll->en, 0);
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt; const struct pll_params_table *pllt;
unsigned int enabled;
unsigned long old_rate; unsigned long old_rate;
u16 frac = 0; u16 frac = 0;
...@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
old_rate = rate; old_rate = rate;
pllt = meson_clk_get_pll_settings(rate, pll); pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
if (!pllt) if (!pllt)
return -EINVAL; return -EINVAL;
/* Put the pll in reset to write the params */ enabled = meson_parm_read(clk->map, &pll->en);
meson_parm_write(clk->map, &pll->rst, 1); if (enabled)
meson_clk_pll_disable(hw);
meson_parm_write(clk->map, &pll->n, pllt->n); meson_parm_write(clk->map, &pll->n, pllt->n);
meson_parm_write(clk->map, &pll->m, pllt->m); meson_parm_write(clk->map, &pll->m, pllt->m);
meson_parm_write(clk->map, &pll->od, pllt->od);
if (MESON_PARM_APPLICABLE(&pll->od2))
meson_parm_write(clk->map, &pll->od2, pllt->od2);
if (MESON_PARM_APPLICABLE(&pll->od3))
meson_parm_write(clk->map, &pll->od3, pllt->od3);
if (MESON_PARM_APPLICABLE(&pll->frac)) { if (MESON_PARM_APPLICABLE(&pll->frac)) {
frac = __pll_params_with_frac(rate, parent_rate, pllt, pll); frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
meson_parm_write(clk->map, &pll->frac, frac); meson_parm_write(clk->map, &pll->frac, frac);
} }
/* make sure the reset is cleared at this point */ /* If the pll is stopped, bail out now */
meson_parm_write(clk->map, &pll->rst, 0); if (!enabled)
return 0;
if (meson_clk_pll_wait_lock(hw)) { if (meson_clk_pll_enable(hw)) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate); __func__, old_rate);
/* /*
...@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = { ...@@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate, .recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate, .round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate, .set_rate = meson_clk_pll_set_rate,
.enable = meson_clk_pll_enable,
.disable = meson_clk_pll_disable
}; };
const struct clk_ops meson_clk_pll_ro_ops = { const struct clk_ops meson_clk_pll_ro_ops = {
......
...@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p, ...@@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
} }
struct pll_rate_table { struct pll_params_table {
unsigned long rate;
u16 m; u16 m;
u16 n; u16 n;
u16 od;
u16 od2;
u16 od3;
}; };
#define PLL_RATE(_r, _m, _n, _od) \ #define PLL_PARAMS(_m, _n) \
{ \ { \
.rate = (_r), \
.m = (_m), \ .m = (_m), \
.n = (_n), \ .n = (_n), \
.od = (_od), \
} }
#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
struct meson_clk_pll_data { struct meson_clk_pll_data {
struct parm en;
struct parm m; struct parm m;
struct parm n; struct parm n;
struct parm frac; struct parm frac;
struct parm od;
struct parm od2;
struct parm od3;
struct parm l; struct parm l;
struct parm rst; struct parm rst;
const struct reg_sequence *init_regs; const struct reg_sequence *init_regs;
unsigned int init_count; unsigned int init_count;
const struct pll_rate_table *table; const struct pll_params_table *table;
u8 flags; u8 flags;
}; };
......
...@@ -18,165 +18,77 @@ ...@@ -18,165 +18,77 @@
static DEFINE_SPINLOCK(meson_clk_lock); static DEFINE_SPINLOCK(meson_clk_lock);
static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
PLL_RATE(96000000, 32, 1, 3), PLL_PARAMS(32, 1),
PLL_RATE(99000000, 33, 1, 3), PLL_PARAMS(33, 1),
PLL_RATE(102000000, 34, 1, 3), PLL_PARAMS(34, 1),
PLL_RATE(105000000, 35, 1, 3), PLL_PARAMS(35, 1),
PLL_RATE(108000000, 36, 1, 3), PLL_PARAMS(36, 1),
PLL_RATE(111000000, 37, 1, 3), PLL_PARAMS(37, 1),
PLL_RATE(114000000, 38, 1, 3), PLL_PARAMS(38, 1),
PLL_RATE(117000000, 39, 1, 3), PLL_PARAMS(39, 1),
PLL_RATE(120000000, 40, 1, 3), PLL_PARAMS(40, 1),
PLL_RATE(123000000, 41, 1, 3), PLL_PARAMS(41, 1),
PLL_RATE(126000000, 42, 1, 3), PLL_PARAMS(42, 1),
PLL_RATE(129000000, 43, 1, 3), PLL_PARAMS(43, 1),
PLL_RATE(132000000, 44, 1, 3), PLL_PARAMS(44, 1),
PLL_RATE(135000000, 45, 1, 3), PLL_PARAMS(45, 1),
PLL_RATE(138000000, 46, 1, 3), PLL_PARAMS(46, 1),
PLL_RATE(141000000, 47, 1, 3), PLL_PARAMS(47, 1),
PLL_RATE(144000000, 48, 1, 3), PLL_PARAMS(48, 1),
PLL_RATE(147000000, 49, 1, 3), PLL_PARAMS(49, 1),
PLL_RATE(150000000, 50, 1, 3), PLL_PARAMS(50, 1),
PLL_RATE(153000000, 51, 1, 3), PLL_PARAMS(51, 1),
PLL_RATE(156000000, 52, 1, 3), PLL_PARAMS(52, 1),
PLL_RATE(159000000, 53, 1, 3), PLL_PARAMS(53, 1),
PLL_RATE(162000000, 54, 1, 3), PLL_PARAMS(54, 1),
PLL_RATE(165000000, 55, 1, 3), PLL_PARAMS(55, 1),
PLL_RATE(168000000, 56, 1, 3), PLL_PARAMS(56, 1),
PLL_RATE(171000000, 57, 1, 3), PLL_PARAMS(57, 1),
PLL_RATE(174000000, 58, 1, 3), PLL_PARAMS(58, 1),
PLL_RATE(177000000, 59, 1, 3), PLL_PARAMS(59, 1),
PLL_RATE(180000000, 60, 1, 3), PLL_PARAMS(60, 1),
PLL_RATE(183000000, 61, 1, 3), PLL_PARAMS(61, 1),
PLL_RATE(186000000, 62, 1, 3), PLL_PARAMS(62, 1),
PLL_RATE(192000000, 32, 1, 2),
PLL_RATE(198000000, 33, 1, 2),
PLL_RATE(204000000, 34, 1, 2),
PLL_RATE(210000000, 35, 1, 2),
PLL_RATE(216000000, 36, 1, 2),
PLL_RATE(222000000, 37, 1, 2),
PLL_RATE(228000000, 38, 1, 2),
PLL_RATE(234000000, 39, 1, 2),
PLL_RATE(240000000, 40, 1, 2),
PLL_RATE(246000000, 41, 1, 2),
PLL_RATE(252000000, 42, 1, 2),
PLL_RATE(258000000, 43, 1, 2),
PLL_RATE(264000000, 44, 1, 2),
PLL_RATE(270000000, 45, 1, 2),
PLL_RATE(276000000, 46, 1, 2),
PLL_RATE(282000000, 47, 1, 2),
PLL_RATE(288000000, 48, 1, 2),
PLL_RATE(294000000, 49, 1, 2),
PLL_RATE(300000000, 50, 1, 2),
PLL_RATE(306000000, 51, 1, 2),
PLL_RATE(312000000, 52, 1, 2),
PLL_RATE(318000000, 53, 1, 2),
PLL_RATE(324000000, 54, 1, 2),
PLL_RATE(330000000, 55, 1, 2),
PLL_RATE(336000000, 56, 1, 2),
PLL_RATE(342000000, 57, 1, 2),
PLL_RATE(348000000, 58, 1, 2),
PLL_RATE(354000000, 59, 1, 2),
PLL_RATE(360000000, 60, 1, 2),
PLL_RATE(366000000, 61, 1, 2),
PLL_RATE(372000000, 62, 1, 2),
PLL_RATE(384000000, 32, 1, 1),
PLL_RATE(396000000, 33, 1, 1),
PLL_RATE(408000000, 34, 1, 1),
PLL_RATE(420000000, 35, 1, 1),
PLL_RATE(432000000, 36, 1, 1),
PLL_RATE(444000000, 37, 1, 1),
PLL_RATE(456000000, 38, 1, 1),
PLL_RATE(468000000, 39, 1, 1),
PLL_RATE(480000000, 40, 1, 1),
PLL_RATE(492000000, 41, 1, 1),
PLL_RATE(504000000, 42, 1, 1),
PLL_RATE(516000000, 43, 1, 1),
PLL_RATE(528000000, 44, 1, 1),
PLL_RATE(540000000, 45, 1, 1),
PLL_RATE(552000000, 46, 1, 1),
PLL_RATE(564000000, 47, 1, 1),
PLL_RATE(576000000, 48, 1, 1),
PLL_RATE(588000000, 49, 1, 1),
PLL_RATE(600000000, 50, 1, 1),
PLL_RATE(612000000, 51, 1, 1),
PLL_RATE(624000000, 52, 1, 1),
PLL_RATE(636000000, 53, 1, 1),
PLL_RATE(648000000, 54, 1, 1),
PLL_RATE(660000000, 55, 1, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(684000000, 57, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(708000000, 59, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(732000000, 61, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(768000000, 32, 1, 0),
PLL_RATE(792000000, 33, 1, 0),
PLL_RATE(816000000, 34, 1, 0),
PLL_RATE(840000000, 35, 1, 0),
PLL_RATE(864000000, 36, 1, 0),
PLL_RATE(888000000, 37, 1, 0),
PLL_RATE(912000000, 38, 1, 0),
PLL_RATE(936000000, 39, 1, 0),
PLL_RATE(960000000, 40, 1, 0),
PLL_RATE(984000000, 41, 1, 0),
PLL_RATE(1008000000, 42, 1, 0),
PLL_RATE(1032000000, 43, 1, 0),
PLL_RATE(1056000000, 44, 1, 0),
PLL_RATE(1080000000, 45, 1, 0),
PLL_RATE(1104000000, 46, 1, 0),
PLL_RATE(1128000000, 47, 1, 0),
PLL_RATE(1152000000, 48, 1, 0),
PLL_RATE(1176000000, 49, 1, 0),
PLL_RATE(1200000000, 50, 1, 0),
PLL_RATE(1224000000, 51, 1, 0),
PLL_RATE(1248000000, 52, 1, 0),
PLL_RATE(1272000000, 53, 1, 0),
PLL_RATE(1296000000, 54, 1, 0),
PLL_RATE(1320000000, 55, 1, 0),
PLL_RATE(1344000000, 56, 1, 0),
PLL_RATE(1368000000, 57, 1, 0),
PLL_RATE(1392000000, 58, 1, 0),
PLL_RATE(1416000000, 59, 1, 0),
PLL_RATE(1440000000, 60, 1, 0),
PLL_RATE(1464000000, 61, 1, 0),
PLL_RATE(1488000000, 62, 1, 0),
{ /* sentinel */ }, { /* sentinel */ },
}; };
static const struct pll_rate_table gxl_gp0_pll_rate_table[] = { static const struct pll_params_table gxl_gp0_pll_params_table[] = {
PLL_RATE(504000000, 42, 1, 1), PLL_PARAMS(42, 1),
PLL_RATE(516000000, 43, 1, 1), PLL_PARAMS(43, 1),
PLL_RATE(528000000, 44, 1, 1), PLL_PARAMS(44, 1),
PLL_RATE(540000000, 45, 1, 1), PLL_PARAMS(45, 1),
PLL_RATE(552000000, 46, 1, 1), PLL_PARAMS(46, 1),
PLL_RATE(564000000, 47, 1, 1), PLL_PARAMS(47, 1),
PLL_RATE(576000000, 48, 1, 1), PLL_PARAMS(48, 1),
PLL_RATE(588000000, 49, 1, 1), PLL_PARAMS(49, 1),
PLL_RATE(600000000, 50, 1, 1), PLL_PARAMS(50, 1),
PLL_RATE(612000000, 51, 1, 1), PLL_PARAMS(51, 1),
PLL_RATE(624000000, 52, 1, 1), PLL_PARAMS(52, 1),
PLL_RATE(636000000, 53, 1, 1), PLL_PARAMS(53, 1),
PLL_RATE(648000000, 54, 1, 1), PLL_PARAMS(54, 1),
PLL_RATE(660000000, 55, 1, 1), PLL_PARAMS(55, 1),
PLL_RATE(672000000, 56, 1, 1), PLL_PARAMS(56, 1),
PLL_RATE(684000000, 57, 1, 1), PLL_PARAMS(57, 1),
PLL_RATE(696000000, 58, 1, 1), PLL_PARAMS(58, 1),
PLL_RATE(708000000, 59, 1, 1), PLL_PARAMS(59, 1),
PLL_RATE(720000000, 60, 1, 1), PLL_PARAMS(60, 1),
PLL_RATE(732000000, 61, 1, 1), PLL_PARAMS(61, 1),
PLL_RATE(744000000, 62, 1, 1), PLL_PARAMS(62, 1),
PLL_RATE(756000000, 63, 1, 1), PLL_PARAMS(63, 1),
PLL_RATE(768000000, 64, 1, 1), PLL_PARAMS(64, 1),
PLL_RATE(780000000, 65, 1, 1), PLL_PARAMS(65, 1),
PLL_RATE(792000000, 66, 1, 1), PLL_PARAMS(66, 1),
{ /* sentinel */ }, { /* sentinel */ },
}; };
static struct clk_regmap gxbb_fixed_pll = { static struct clk_regmap gxbb_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_MPLL_CNTL, .reg_off = HHI_MPLL_CNTL,
.shift = 0, .shift = 0,
...@@ -187,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = { ...@@ -187,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_MPLL_CNTL2, .reg_off = HHI_MPLL_CNTL2,
.shift = 0, .shift = 0,
...@@ -209,11 +116,29 @@ static struct clk_regmap gxbb_fixed_pll = { ...@@ -209,11 +116,29 @@ static struct clk_regmap gxbb_fixed_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "fixed_pll", .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE, },
};
static struct clk_regmap gxbb_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
}, },
}; };
...@@ -228,8 +153,13 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = { ...@@ -228,8 +153,13 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
}, },
}; };
static struct clk_regmap gxbb_hdmi_pll = { static struct clk_regmap gxbb_hdmi_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_HDMI_PLL_CNTL, .reg_off = HHI_HDMI_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -245,21 +175,6 @@ static struct clk_regmap gxbb_hdmi_pll = { ...@@ -245,21 +175,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
.shift = 0, .shift = 0,
.width = 12, .width = 12,
}, },
.od = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 16,
.width = 2,
},
.od2 = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 22,
.width = 2,
},
.od3 = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 18,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_HDMI_PLL_CNTL, .reg_off = HHI_HDMI_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -272,74 +187,121 @@ static struct clk_regmap gxbb_hdmi_pll = { ...@@ -272,74 +187,121 @@ static struct clk_regmap gxbb_hdmi_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "hdmi_pll", .name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_pre_mult" }, .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
.num_parents = 1, .num_parents = 1,
/*
* Display directly handle hdmi pll registers ATM, we need
* NOCACHE to keep our view of the clock as accurate as possible
*/
.flags = CLK_GET_RATE_NOCACHE, .flags = CLK_GET_RATE_NOCACHE,
}, },
}; };
static struct clk_regmap gxbb_hdmi_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxbb_hdmi_pll_od2 = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 22,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxbb_hdmi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 18,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od2" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL + 8,
.shift = 21,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll_od2 = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL + 8,
.shift = 23,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll = { static struct clk_regmap gxl_hdmi_pll = {
.data = &(struct meson_clk_pll_data){ .data = &(struct clk_regmap_div_data){
.m = { .offset = HHI_HDMI_PLL_CNTL + 8,
.reg_off = HHI_HDMI_PLL_CNTL, .shift = 19,
.shift = 0, .width = 2,
.width = 9, .flags = CLK_DIVIDER_POWER_OF_TWO,
},
.n = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 9,
.width = 5,
},
.frac = {
/*
* On gxl, there is a register shift due to
* HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
* so we compute the register offset based on the PLL
* base to get it right
*/
.reg_off = HHI_HDMI_PLL_CNTL + 4,
.shift = 0,
.width = 12,
},
.od = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 21,
.width = 2,
},
.od2 = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 23,
.width = 2,
},
.od3 = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 19,
.width = 2,
},
.l = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 29,
.width = 1,
},
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "hdmi_pll", .name = "hdmi_pll",
.ops = &meson_clk_pll_ro_ops, .ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "hdmi_pll_od2" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE, .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
}, },
}; };
static struct clk_regmap gxbb_sys_pll = { static struct clk_regmap gxbb_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -350,11 +312,6 @@ static struct clk_regmap gxbb_sys_pll = { ...@@ -350,11 +312,6 @@ static struct clk_regmap gxbb_sys_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 10,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -367,11 +324,26 @@ static struct clk_regmap gxbb_sys_pll = { ...@@ -367,11 +324,26 @@ static struct clk_regmap gxbb_sys_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "sys_pll", .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE, },
};
static struct clk_regmap gxbb_sys_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_PLL_CNTL,
.shift = 10,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}, },
}; };
...@@ -379,11 +351,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = { ...@@ -379,11 +351,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
}; };
static struct clk_regmap gxbb_gp0_pll = { static struct clk_regmap gxbb_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_GP0_PLL_CNTL, .reg_off = HHI_GP0_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -394,11 +370,6 @@ static struct clk_regmap gxbb_gp0_pll = { ...@@ -394,11 +370,6 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_GP0_PLL_CNTL, .reg_off = HHI_GP0_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -409,16 +380,15 @@ static struct clk_regmap gxbb_gp0_pll = { ...@@ -409,16 +380,15 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = gxbb_gp0_pll_rate_table, .table = gxbb_gp0_pll_params_table,
.init_regs = gxbb_gp0_init_regs, .init_regs = gxbb_gp0_init_regs,
.init_count = ARRAY_SIZE(gxbb_gp0_init_regs), .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "gp0_pll", .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
}, },
}; };
...@@ -428,11 +398,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = { ...@@ -428,11 +398,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
}; };
static struct clk_regmap gxl_gp0_pll = { static struct clk_regmap gxl_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_GP0_PLL_CNTL, .reg_off = HHI_GP0_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -443,11 +417,6 @@ static struct clk_regmap gxl_gp0_pll = { ...@@ -443,11 +417,6 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_GP0_PLL_CNTL1, .reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0, .shift = 0,
...@@ -463,16 +432,31 @@ static struct clk_regmap gxl_gp0_pll = { ...@@ -463,16 +432,31 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = gxl_gp0_pll_rate_table, .table = gxl_gp0_pll_params_table,
.init_regs = gxl_gp0_init_regs, .init_regs = gxl_gp0_init_regs,
.init_count = ARRAY_SIZE(gxl_gp0_init_regs), .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "gp0_pll", .name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops, .ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE, },
};
static struct clk_regmap gxbb_gp0_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}, },
}; };
...@@ -1933,6 +1917,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { ...@@ -1933,6 +1917,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw, [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw, [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw, [CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
[CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
[CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &gxbb_hdmi_pll_od.hw,
[CLKID_HDMI_PLL_OD2] = &gxbb_hdmi_pll_od2.hw,
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &gxbb_gp0_pll_dco.hw,
[NR_CLKS] = NULL, [NR_CLKS] = NULL,
}, },
.num = NR_CLKS, .num = NR_CLKS,
...@@ -1948,7 +1938,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { ...@@ -1948,7 +1938,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw, [CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw,
[CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw, [CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw,
[CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw, [CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw,
[CLKID_GP0_PLL] = &gxl_gp0_pll.hw, [CLKID_GP0_PLL] = &gxbb_gp0_pll.hw,
[CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw, [CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw,
[CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw, [CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw,
[CLKID_CLK81] = &gxbb_clk81.hw, [CLKID_CLK81] = &gxbb_clk81.hw,
...@@ -2098,19 +2088,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { ...@@ -2098,19 +2088,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw, [CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw, [CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw, [CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
[CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
[CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &gxl_hdmi_pll_od.hw,
[CLKID_HDMI_PLL_OD2] = &gxl_hdmi_pll_od2.hw,
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &gxl_gp0_pll_dco.hw,
[NR_CLKS] = NULL, [NR_CLKS] = NULL,
}, },
.num = NR_CLKS, .num = NR_CLKS,
}; };
static struct clk_regmap *const gxbb_clk_regmaps[] = { static struct clk_regmap *const gxbb_clk_regmaps[] = {
&gxbb_gp0_pll, &gxbb_gp0_pll_dco,
&gxbb_hdmi_pll, &gxbb_hdmi_pll,
&gxbb_hdmi_pll_od,
&gxbb_hdmi_pll_od2,
}; };
static struct clk_regmap *const gxl_clk_regmaps[] = { static struct clk_regmap *const gxl_clk_regmaps[] = {
&gxl_gp0_pll, &gxl_gp0_pll_dco,
&gxl_hdmi_pll, &gxl_hdmi_pll,
&gxl_hdmi_pll_od,
&gxl_hdmi_pll_od2,
}; };
static struct clk_regmap *const gx_clk_regmaps[] = { static struct clk_regmap *const gx_clk_regmaps[] = {
...@@ -2265,6 +2265,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = { ...@@ -2265,6 +2265,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
&gxbb_gen_clk_sel, &gxbb_gen_clk_sel,
&gxbb_gen_clk_div, &gxbb_gen_clk_div,
&gxbb_gen_clk, &gxbb_gen_clk,
&gxbb_fixed_pll_dco,
&gxbb_hdmi_pll_dco,
&gxbb_sys_pll_dco,
&gxbb_gp0_pll,
}; };
struct clkc_data { struct clkc_data {
......
...@@ -159,8 +159,14 @@ ...@@ -159,8 +159,14 @@
#define CLKID_VDEC_HEVC_DIV 155 #define CLKID_VDEC_HEVC_DIV 155
#define CLKID_GEN_CLK_SEL 157 #define CLKID_GEN_CLK_SEL 157
#define CLKID_GEN_CLK_DIV 158 #define CLKID_GEN_CLK_DIV 158
#define CLKID_FIXED_PLL_DCO 160
#define NR_CLKS 160 #define CLKID_HDMI_PLL_DCO 161
#define CLKID_HDMI_PLL_OD 162
#define CLKID_HDMI_PLL_OD2 163
#define CLKID_SYS_PLL_DCO 164
#define CLKID_GP0_PLL_DCO 165
#define NR_CLKS 166
/* include the CLKIDs that have been made part of the DT binding */ /* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h> #include <dt-bindings/clock/gxbb-clkc.h>
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h> #include <linux/reset-controller.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -22,66 +21,27 @@ ...@@ -22,66 +21,27 @@
static DEFINE_SPINLOCK(meson_clk_lock); static DEFINE_SPINLOCK(meson_clk_lock);
static void __iomem *clk_base;
struct meson8b_clk_reset { struct meson8b_clk_reset {
struct reset_controller_dev reset; struct reset_controller_dev reset;
void __iomem *base; struct regmap *regmap;
}; };
static const struct pll_rate_table sys_pll_rate_table[] = { static const struct pll_params_table sys_pll_params_table[] = {
PLL_RATE(312000000, 52, 1, 2), PLL_PARAMS(50, 1),
PLL_RATE(336000000, 56, 1, 2), PLL_PARAMS(51, 1),
PLL_RATE(360000000, 60, 1, 2), PLL_PARAMS(52, 1),
PLL_RATE(384000000, 64, 1, 2), PLL_PARAMS(53, 1),
PLL_RATE(408000000, 68, 1, 2), PLL_PARAMS(54, 1),
PLL_RATE(432000000, 72, 1, 2), PLL_PARAMS(55, 1),
PLL_RATE(456000000, 76, 1, 2), PLL_PARAMS(56, 1),
PLL_RATE(480000000, 80, 1, 2), PLL_PARAMS(57, 1),
PLL_RATE(504000000, 84, 1, 2), PLL_PARAMS(58, 1),
PLL_RATE(528000000, 88, 1, 2), PLL_PARAMS(59, 1),
PLL_RATE(552000000, 92, 1, 2), PLL_PARAMS(60, 1),
PLL_RATE(576000000, 96, 1, 2), PLL_PARAMS(61, 1),
PLL_RATE(600000000, 50, 1, 1), PLL_PARAMS(62, 1),
PLL_RATE(624000000, 52, 1, 1), PLL_PARAMS(63, 1),
PLL_RATE(648000000, 54, 1, 1), PLL_PARAMS(64, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(768000000, 64, 1, 1),
PLL_RATE(792000000, 66, 1, 1),
PLL_RATE(816000000, 68, 1, 1),
PLL_RATE(840000000, 70, 1, 1),
PLL_RATE(864000000, 72, 1, 1),
PLL_RATE(888000000, 74, 1, 1),
PLL_RATE(912000000, 76, 1, 1),
PLL_RATE(936000000, 78, 1, 1),
PLL_RATE(960000000, 80, 1, 1),
PLL_RATE(984000000, 82, 1, 1),
PLL_RATE(1008000000, 84, 1, 1),
PLL_RATE(1032000000, 86, 1, 1),
PLL_RATE(1056000000, 88, 1, 1),
PLL_RATE(1080000000, 90, 1, 1),
PLL_RATE(1104000000, 92, 1, 1),
PLL_RATE(1128000000, 94, 1, 1),
PLL_RATE(1152000000, 96, 1, 1),
PLL_RATE(1176000000, 98, 1, 1),
PLL_RATE(1200000000, 50, 1, 0),
PLL_RATE(1224000000, 51, 1, 0),
PLL_RATE(1248000000, 52, 1, 0),
PLL_RATE(1272000000, 53, 1, 0),
PLL_RATE(1296000000, 54, 1, 0),
PLL_RATE(1320000000, 55, 1, 0),
PLL_RATE(1344000000, 56, 1, 0),
PLL_RATE(1368000000, 57, 1, 0),
PLL_RATE(1392000000, 58, 1, 0),
PLL_RATE(1416000000, 59, 1, 0),
PLL_RATE(1440000000, 60, 1, 0),
PLL_RATE(1464000000, 61, 1, 0),
PLL_RATE(1488000000, 62, 1, 0),
PLL_RATE(1512000000, 63, 1, 0),
PLL_RATE(1536000000, 64, 1, 0),
{ /* sentinel */ }, { /* sentinel */ },
}; };
...@@ -94,8 +54,13 @@ static struct clk_fixed_rate meson8b_xtal = { ...@@ -94,8 +54,13 @@ static struct clk_fixed_rate meson8b_xtal = {
}, },
}; };
static struct clk_regmap meson8b_fixed_pll = { static struct clk_regmap meson8b_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_MPLL_CNTL, .reg_off = HHI_MPLL_CNTL,
.shift = 0, .shift = 0,
...@@ -106,11 +71,6 @@ static struct clk_regmap meson8b_fixed_pll = { ...@@ -106,11 +71,6 @@ static struct clk_regmap meson8b_fixed_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = { .frac = {
.reg_off = HHI_MPLL_CNTL2, .reg_off = HHI_MPLL_CNTL2,
.shift = 0, .shift = 0,
...@@ -128,16 +88,39 @@ static struct clk_regmap meson8b_fixed_pll = { ...@@ -128,16 +88,39 @@ static struct clk_regmap meson8b_fixed_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "fixed_pll", .name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
}, },
}; };
static struct clk_regmap meson8b_vid_pll = { static struct clk_regmap meson8b_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
},
};
static struct clk_regmap meson8b_vid_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_VID_PLL_CNTL, .reg_off = HHI_VID_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -148,11 +131,6 @@ static struct clk_regmap meson8b_vid_pll = { ...@@ -148,11 +131,6 @@ static struct clk_regmap meson8b_vid_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_VID_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_VID_PLL_CNTL, .reg_off = HHI_VID_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -165,16 +143,36 @@ static struct clk_regmap meson8b_vid_pll = { ...@@ -165,16 +143,36 @@ static struct clk_regmap meson8b_vid_pll = {
}, },
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "vid_pll", .name = "vid_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
}, },
}; };
static struct clk_regmap meson8b_sys_pll = { static struct clk_regmap meson8b_vid_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_VID_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "vid_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "vid_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap meson8b_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){ .data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = { .m = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 0, .shift = 0,
...@@ -185,11 +183,6 @@ static struct clk_regmap meson8b_sys_pll = { ...@@ -185,11 +183,6 @@ static struct clk_regmap meson8b_sys_pll = {
.shift = 9, .shift = 9,
.width = 5, .width = 5,
}, },
.od = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = { .l = {
.reg_off = HHI_SYS_PLL_CNTL, .reg_off = HHI_SYS_PLL_CNTL,
.shift = 31, .shift = 31,
...@@ -200,14 +193,29 @@ static struct clk_regmap meson8b_sys_pll = { ...@@ -200,14 +193,29 @@ static struct clk_regmap meson8b_sys_pll = {
.shift = 29, .shift = 29,
.width = 1, .width = 1,
}, },
.table = sys_pll_rate_table, .table = sys_pll_params_table,
}, },
.hw.init = &(struct clk_init_data){ .hw.init = &(struct clk_init_data){
.name = "sys_pll", .name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops, .ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" }, .parent_names = (const char *[]){ "xtal" },
.num_parents = 1, .num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE, },
};
static struct clk_regmap meson8b_sys_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
}, },
}; };
...@@ -879,6 +887,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { ...@@ -879,6 +887,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
[CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw, [CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw,
[CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw, [CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw,
[CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw, [CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw,
[CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
[CLKID_PLL_VID_DCO] = &meson8b_vid_pll_dco.hw,
[CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
[CLK_NR_CLKS] = NULL, [CLK_NR_CLKS] = NULL,
}, },
.num = CLK_NR_CLKS, .num = CLK_NR_CLKS,
...@@ -987,6 +998,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { ...@@ -987,6 +998,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
&meson8b_nand_clk_sel, &meson8b_nand_clk_sel,
&meson8b_nand_clk_div, &meson8b_nand_clk_div,
&meson8b_nand_clk_gate, &meson8b_nand_clk_gate,
&meson8b_fixed_pll_dco,
&meson8b_vid_pll_dco,
&meson8b_sys_pll_dco,
}; };
static const struct meson8b_clk_reset_line { static const struct meson8b_clk_reset_line {
...@@ -1050,7 +1064,6 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev, ...@@ -1050,7 +1064,6 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
container_of(rcdev, struct meson8b_clk_reset, reset); container_of(rcdev, struct meson8b_clk_reset, reset);
unsigned long flags; unsigned long flags;
const struct meson8b_clk_reset_line *reset; const struct meson8b_clk_reset_line *reset;
u32 val;
if (id >= ARRAY_SIZE(meson8b_clk_reset_bits)) if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
return -EINVAL; return -EINVAL;
...@@ -1059,12 +1072,12 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev, ...@@ -1059,12 +1072,12 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
spin_lock_irqsave(&meson_clk_lock, flags); spin_lock_irqsave(&meson_clk_lock, flags);
val = readl(meson8b_clk_reset->base + reset->reg);
if (assert) if (assert)
val |= BIT(reset->bit_idx); regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
BIT(reset->bit_idx), BIT(reset->bit_idx));
else else
val &= ~BIT(reset->bit_idx); regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
writel(val, meson8b_clk_reset->base + reset->reg); BIT(reset->bit_idx), 0);
spin_unlock_irqrestore(&meson_clk_lock, flags); spin_unlock_irqrestore(&meson_clk_lock, flags);
...@@ -1094,62 +1107,12 @@ static const struct regmap_config clkc_regmap_config = { ...@@ -1094,62 +1107,12 @@ static const struct regmap_config clkc_regmap_config = {
.reg_stride = 4, .reg_stride = 4,
}; };
static int meson8b_clkc_probe(struct platform_device *pdev) static void __init meson8b_clkc_init(struct device_node *np)
{
int ret, i;
struct device *dev = &pdev->dev;
struct regmap *map;
if (!clk_base)
return -ENXIO;
map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
if (IS_ERR(map))
return PTR_ERR(map);
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
meson8b_clk_regmaps[i]->map = map;
/*
* register all clks
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
*/
for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
/* array might be sparse */
if (!meson8b_hw_onecell_data.hws[i])
continue;
ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
if (ret)
return ret;
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
&meson8b_hw_onecell_data);
}
static const struct of_device_id meson8b_clkc_match_table[] = {
{ .compatible = "amlogic,meson8-clkc" },
{ .compatible = "amlogic,meson8b-clkc" },
{ .compatible = "amlogic,meson8m2-clkc" },
{ }
};
static struct platform_driver meson8b_driver = {
.probe = meson8b_clkc_probe,
.driver = {
.name = "meson8b-clkc",
.of_match_table = meson8b_clkc_match_table,
},
};
builtin_platform_driver(meson8b_driver);
static void __init meson8b_clkc_reset_init(struct device_node *np)
{ {
struct meson8b_clk_reset *rstc; struct meson8b_clk_reset *rstc;
int ret; void __iomem *clk_base;
struct regmap *map;
int i, ret;
/* Generic clocks, PLLs and some of the reset-bits */ /* Generic clocks, PLLs and some of the reset-bits */
clk_base = of_iomap(np, 1); clk_base = of_iomap(np, 1);
...@@ -1158,12 +1121,16 @@ static void __init meson8b_clkc_reset_init(struct device_node *np) ...@@ -1158,12 +1121,16 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
return; return;
} }
map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
if (IS_ERR(map))
return;
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
if (!rstc) if (!rstc)
return; return;
/* Reset Controller */ /* Reset Controller */
rstc->base = clk_base; rstc->regmap = map;
rstc->reset.ops = &meson8b_clk_reset_ops; rstc->reset.ops = &meson8b_clk_reset_ops;
rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits);
rstc->reset.of_node = np; rstc->reset.of_node = np;
...@@ -1173,11 +1140,34 @@ static void __init meson8b_clkc_reset_init(struct device_node *np) ...@@ -1173,11 +1140,34 @@ static void __init meson8b_clkc_reset_init(struct device_node *np)
__func__, ret); __func__, ret);
return; return;
} }
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
meson8b_clk_regmaps[i]->map = map;
/*
* register all clks
* CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
*/
for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
/* array might be sparse */
if (!meson8b_hw_onecell_data.hws[i])
continue;
ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]);
if (ret)
return;
}
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
&meson8b_hw_onecell_data);
if (ret)
pr_err("%s: failed to register clock provider\n", __func__);
} }
CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
meson8b_clkc_reset_init); meson8b_clkc_init);
CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
meson8b_clkc_reset_init); meson8b_clkc_init);
CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
meson8b_clkc_reset_init); meson8b_clkc_init);
...@@ -75,8 +75,11 @@ ...@@ -75,8 +75,11 @@
#define CLKID_FCLK_DIV7_DIV 109 #define CLKID_FCLK_DIV7_DIV 109
#define CLKID_NAND_SEL 110 #define CLKID_NAND_SEL 110
#define CLKID_NAND_DIV 111 #define CLKID_NAND_DIV 111
#define CLKID_PLL_FIXED_DCO 113
#define CLKID_PLL_VID_DCO 114
#define CLKID_PLL_SYS_DCO 115
#define CLK_NR_CLKS 113 #define CLK_NR_CLKS 116
/* /*
* include the CLKID and RESETID that have * include the CLKID and RESETID that have
......
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