/** * struct clk_pll_data - pll data structure * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm * register of pll controller, else it is in the pll_ctrl0((bit 11-6) * @phy_pllm: Physical address of PLLM in pll controller. Used when * has_pllctrl is non zero. * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of * Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL * or PA PLL available on keystone2. These PLLs are controlled by * this register. Main PLL is controlled by a PLL controller. * @pllm: PLL register map address for multiplier bits * @pllod: PLL register map address for post divider bits * @pll_ctl0: PLL controller map address * @pllm_lower_mask: multiplier lower mask * @pllm_upper_mask: multiplier upper mask * @pllm_upper_shift: multiplier upper shift * @plld_mask: divider mask * @clkod_mask: output divider mask * @clkod_shift: output divider shift * @plld_mask: divider mask * @postdiv: Fixed post divider
*/ struct clk_pll_data { bool has_pllctrl;
u32 phy_pllm;
u32 phy_pll_ctl0; void __iomem *pllm; void __iomem *pllod; void __iomem *pll_ctl0;
u32 pllm_lower_mask;
u32 pllm_upper_mask;
u32 pllm_upper_shift;
u32 plld_mask;
u32 clkod_mask;
u32 clkod_shift;
u32 postdiv;
};
/** * struct clk_pll - Main pll clock * @hw: clk_hw for the pll * @pll_data: PLL driver specific data
*/ struct clk_pll { struct clk_hw hw; struct clk_pll_data *pll_data;
};
/* * get bits 0-5 of multiplier from pllctrl PLLM register * if has_pllctrl is non zero
*/ if (pll_data->has_pllctrl) {
val = readl(pll_data->pllm);
mult = (val & pll_data->pllm_lower_mask);
}
/* bit6-12 of PLLM is in Main PLL control register */
val = readl(pll_data->pll_ctl0);
mult |= ((val & pll_data->pllm_upper_mask)
>> pll_data->pllm_upper_shift);
prediv = (val & pll_data->plld_mask);
if (!pll_data->has_pllctrl) /* read post divider from od bits*/
postdiv = ((val & pll_data->clkod_mask) >>
pll_data->clkod_shift) + 1; elseif (pll_data->pllod) {
postdiv = readl(pll_data->pllod);
postdiv = ((postdiv & pll_data->clkod_mask) >>
pll_data->clkod_shift) + 1;
} else
postdiv = pll_data->postdiv;
clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) goto out;
return clk;
out:
kfree(pll); return NULL;
}
/** * _of_pll_clk_init - PLL initialisation via DT * @node: device tree node for this clock * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of * pll controller, else it is in the control register0(bit 11-6)
*/ staticvoid __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
{ struct clk_pll_data *pll_data; constchar *parent_name; struct clk *clk; int i;
pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL); if (!pll_data) {
pr_err("%s: Out of memory\n", __func__); return;
}
parent_name = of_clk_get_parent_name(node, 0); if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) { /* assume the PLL has output divider register bits */
pll_data->clkod_mask = CLKOD_MASK;
pll_data->clkod_shift = CLKOD_SHIFT;
/* * Check if there is an post-divider register. If not * assume od bits are part of control register.
*/
i = of_property_match_string(node, "reg-names", "post-divider");
pll_data->pllod = of_iomap(node, i);
}
i = of_property_match_string(node, "reg-names", "control");
pll_data->pll_ctl0 = of_iomap(node, i); if (!pll_data->pll_ctl0) {
pr_err("%s: ioremap failed\n", __func__);
iounmap(pll_data->pllod); goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.