* | |-->|CGU_TUN_IDIV_ROM|----------->
* | |-->|CGU_TUN_IDIV_PWM|----------->
* |
- * | ------------
- * |-->| HDMI PLL |
- * | ------------
- * | |
- * | |-->|CGU_HDMI_IDIV_APB|------>
- * |
* | -----------
* |-->| DDR PLL |
* -----------
* |
* |---------------------------->
+ *
+ * ------------------
+ * | 27.00 MHz xtal |
+ * ------------------
+ * |
+ * | ------------
+ * |-->| HDMI PLL |
+ * ------------
+ * |
+ * |-->|CGU_HDMI_IDIV_APB|------>
*/
-DECLARE_GLOBAL_DATA_PTR;
-
#define CGU_ARC_IDIV 0x080
#define CGU_TUN_IDIV_TUN 0x380
#define CGU_TUN_IDIV_ROM 0x390
#define CGU_TUN_IDIV_PWM 0x3A0
+#define CGU_TUN_IDIV_TIMER 0x3B0
#define CGU_HDMI_IDIV_APB 0x480
#define CGU_SYS_IDIV_APB 0x180
#define CGU_SYS_IDIV_AXI 0x190
#define CREG_CORE_IF_CLK_DIV_2 0x1
#define MIN_PLL_RATE 100000000 /* 100 MHz */
-#define PARENT_RATE 33333333 /* fixed clock - xtal */
-#define CGU_MAX_CLOCKS 26
+#define PARENT_RATE_33 33333333 /* fixed clock - xtal */
+#define PARENT_RATE_27 27000000 /* fixed clock - xtal */
+#define CGU_MAX_CLOCKS 27
#define CGU_SYS_CLOCKS 16
#define MAX_AXI_CLOCKS 4
-#define CGU_TUN_CLOCKS 3
+#define CGU_TUN_CLOCKS 4
#define MAX_TUN_CLOCKS 6
struct hsdk_tun_idiv_cfg {
static const struct hsdk_tun_clk_cfg tun_clk_cfg = {
{ 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 },
- { 600000000, 600000000, 600000000, 600000000, 700000000, 600000000 }, {
+ { 600000000, 600000000, 600000000, 600000000, 750000000, 600000000 }, {
{ CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } },
{ CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } },
- { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } }
+ { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } },
+ { CGU_TUN_IDIV_TIMER, { 12, 12, 12, 12, 15, 12 } }
}
};
{ 500000000, 0, 14, 1, 0 },
{ 600000000, 0, 17, 1, 0 },
{ 700000000, 0, 20, 1, 0 },
+ { 750000000, 1, 44, 1, 0 },
{ 800000000, 0, 23, 1, 0 },
{ 900000000, 1, 26, 0, 0 },
{ 1000000000, 1, 29, 0, 0 },
};
struct hsdk_pll_devdata {
+ const u32 parent_rate;
const struct hsdk_pll_cfg *pll_cfg;
int (*update_rate)(struct hsdk_cgu_clk *clk, unsigned long rate,
const struct hsdk_pll_cfg *cfg);
const struct hsdk_pll_cfg *);
static const struct hsdk_pll_devdata core_pll_dat = {
+ .parent_rate = PARENT_RATE_33,
.pll_cfg = asdt_pll_cfg,
.update_rate = hsdk_pll_core_update_rate,
};
static const struct hsdk_pll_devdata sdt_pll_dat = {
+ .parent_rate = PARENT_RATE_33,
.pll_cfg = asdt_pll_cfg,
.update_rate = hsdk_pll_comm_update_rate,
};
static const struct hsdk_pll_devdata hdmi_pll_dat = {
+ .parent_rate = PARENT_RATE_27,
.pll_cfg = hdmi_pll_cfg,
.update_rate = hsdk_pll_comm_update_rate,
};
{ CGU_TUN_PLL, 0, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off },
{ CGU_TUN_PLL, 0, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_TUN_PLL, 0, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
+ { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TIMER, &sdt_pll_dat, idiv_get, idiv_set, idiv_off },
{ CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL },
{ CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off }
};
u64 rate;
u32 idiv, fbdiv, odiv;
struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev);
+ u32 parent_rate = clk->pll_devdata->parent_rate;
val = hsdk_pll_read(clk, CGU_PLL_CTRL);
pr_debug("current configurarion: %#x\n", val);
+ /* Check if PLL is bypassed */
+ if (val & CGU_PLL_CTRL_BYPASS)
+ return parent_rate;
+
/* Check if PLL is disabled */
if (val & CGU_PLL_CTRL_PD)
return 0;
- /* Check if PLL is bypassed */
- if (val & CGU_PLL_CTRL_BYPASS)
- return PARENT_RATE;
-
/* input divider = reg.idiv + 1 */
idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT);
/* fb divider = 2*(reg.fbdiv + 1) */
/* output divider = 2^(reg.odiv) */
odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT);
- rate = (u64)PARENT_RATE * fbdiv;
+ rate = (u64)parent_rate * fbdiv;
do_div(rate, idiv * odiv);
return rate;
}
}
- pr_err("invalid rate=%ld, parent_rate=%d\n", best_rate, PARENT_RATE);
+ pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate,
+ clk->pll_devdata->parent_rate);
return -EINVAL;
}
}
if (div_factor & ~CGU_IDIV_MASK) {
- pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: max divider valie is%d\n",
+ pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n",
rate, parent_rate, div_factor, CGU_IDIV_MASK);
div_factor = CGU_IDIV_MASK;
}
if (div_factor == 0) {
- pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: min divider valie is 1\n",
+ pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n",
rate, parent_rate, div_factor);
div_factor = 1;