+++ /dev/null
-obj-y += clk.o
-obj-y += clk-ops.o
-obj-y += clk-pll.o
-obj-y += clk-pd.o
-obj-y += pd-rk3368.o
+++ /dev/null
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/io.h>
-#include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/clk-private.h>
-#include <linux/delay.h>
-#include <linux/rockchip/common.h>
-#include <linux/rockchip/cpu.h>
-
-#include "clk-ops.h"
-
-/* mux_ops */
-struct clk_ops_table rk_clk_mux_ops_table[] = {
- {.index = CLKOPS_TABLE_END},
-};
-
-
-/* rate_ops */
-#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
-#define div_mask(d) ((1 << ((d)->width)) - 1)
-
-static u32 clk_gcd(u32 numerator, u32 denominator)
-{
- u32 a, b;
-
- if (!numerator || !denominator)
- return 0;
- if (numerator > denominator) {
- a = numerator;
- b = denominator;
- } else {
- a = denominator;
- b = numerator;
- }
- while (b != 0) {
- int r = b;
- b = a % b;
- a = r;
- }
-
- return a;
-}
-
-static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate,
- u32 *numerator, u32 *denominator)
-{
- u32 gcd_val;
- gcd_val = clk_gcd(rate, rate_out);
- clk_debug("%s: frac_get_seting rate=%lu, parent=%lu, gcd=%d\n",
- __func__, rate_out, rate, gcd_val);
-
- if (!gcd_val) {
- clk_err("gcd=0, frac div is not be supported\n");
- return -EINVAL;
- }
-
- *numerator = rate_out / gcd_val;
- *denominator = rate / gcd_val;
-
- clk_debug("%s: frac_get_seting numerator=%d, denominator=%d, times=%d\n",
- __func__, *numerator, *denominator,
- *denominator / *numerator);
-
- if (*numerator > 0xffff || *denominator > 0xffff ||
- (*denominator / (*numerator)) < 20) {
- clk_err("can't get a available nume and deno\n");
- return -EINVAL;
- }
-
- return 0;
-
-}
-
-static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- u32 numerator, denominator;
- struct clk_divider *div = to_clk_divider(hw);
-
-
- if(clk_fracdiv_get_config(rate, parent_rate,
- &numerator, &denominator) == 0) {
- writel(numerator << 16 | denominator, div->reg);
- clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
- } else {
- clk_err("clk_frac_div name=%s can't get rate=%lu\n",
- hw->clk->name, rate);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- unsigned long rate;
- u64 rate64;
- struct clk_divider *div = to_clk_divider(hw);
- u32 numerator, denominator, reg_val;
-
- reg_val = readl(div->reg);
- if (reg_val == 0)
- return parent_rate;
-
- numerator = reg_val >> 16;
- denominator = reg_val & 0xFFFF;
- rate64 = (u64)parent_rate * numerator;
- do_div(rate64, denominator);
- rate = rate64;
- clk_debug("%s: %s new clock rate is %lu, prate %lu (frac %u/%u)\n",
- __func__, hw->clk->name, rate, parent_rate,
- numerator, denominator);
- return rate;
-}
-
-static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *clk = hw->clk;
- struct clk *parent = clk->parent;
- long rate_out;
-
- //FIXME: now just simply return rate
- /*
- *frac_div request a big input rate, and its parent is always a div,
- *so we set parent->parent->rate as best_parent_rate.
- */
- rate_out = rate;
- *prate = parent->parent->rate;
-
- return rate_out;
-}
-
-static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return clk_divider_ops.recalc_rate(hw, parent_rate);
-}
-
-static long clk_divider_round_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long *prate)
-{
- return clk_divider_ops.round_rate(hw, rate, prate);
-}
-
-static int clk_divider_set_rate(struct clk_hw *hw,
- unsigned long rate, unsigned long parent_rate)
-{
- return clk_divider_ops.set_rate(hw, rate, parent_rate);
-}
-
-static long clk_mux_with_div_determine_rate(struct clk_hw *div_hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
- int i, num_parents;
- unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
-
-
- parent = __clk_get_parent(clk);
- if(!parent){
- best = __clk_get_rate(clk);
- goto out;
- }
-
- /* if NO_REPARENT flag set, pass through to current parent */
- if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
- best_prate = __clk_get_rate(parent);
- best = clk_divider_ops.round_rate(div_hw, rate, &best_prate);
- goto out;
- }
-
- /* find the parent that can provide the fastest rate <= rate */
- num_parents = clk->num_parents;
- for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
- if (!parent)
- continue;
-
- parent_rate = __clk_get_rate(parent);
- now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
-
- if (now <= rate && now > best) {
- best_parent = parent;
- best_prate = parent_rate;
- best = now;
- }
- }
-
-out:
- if(best_prate)
- *best_parent_rate = best_prate;
-
- if (best_parent)
- *best_parent_p = best_parent;
-
- clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
- "\tbest_parent name = %s, best_prate = %lu\n",
- clk->name, rate, best,
- __clk_get_name(*best_parent_p), *best_parent_rate);
-
- return best;
-}
-
-const struct clk_ops clkops_rate_auto_parent = {
- .recalc_rate = clk_divider_recalc_rate,
- .round_rate = clk_divider_round_rate,
- .set_rate = clk_divider_set_rate,
- .determine_rate = clk_mux_with_div_determine_rate,
-};
-
-static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- int i = 0;
- struct clk_divider *divider =to_clk_divider(hw);
- int max_div = 1 << divider->width;
-
- for (i = 1; i <= max_div; i++) {
- if (i > 1 && (i % 2 != 0))
- continue;
- if (rate >= (*prate / i))
- return *prate / i;
- }
-
- return (*prate / max_div);
-}
-
-const struct clk_ops clkops_rate_evendiv = {
- .recalc_rate = clk_divider_recalc_rate,
- .round_rate = clk_div_round_rate_even,
- .set_rate = clk_divider_set_rate,
-};
-
-static long clk_mux_with_evendiv_determine_rate(struct clk_hw *div_hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
- int i, num_parents;
- unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
-
-
- parent = __clk_get_parent(clk);
- if(!parent){
- best = __clk_get_rate(clk);
- goto out;
- }
-
- /* if NO_REPARENT flag set, pass through to current parent */
- if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
- best_prate = __clk_get_rate(parent);
- best = clk_div_round_rate_even(div_hw, rate, &best_prate);
- goto out;
- }
-
- /* find the parent that can provide the fastest rate <= rate */
- num_parents = clk->num_parents;
- for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
- if (!parent)
- continue;
-
- parent_rate = __clk_get_rate(parent);
- now = clk_div_round_rate_even(div_hw, rate, &parent_rate);
-
- if (now <= rate && now > best) {
- best_parent = parent;
- best_prate = parent_rate;
- best = now;
- }
- }
-
-out:
- if(best_prate)
- *best_parent_rate = best_prate;
-
- if (best_parent)
- *best_parent_p = best_parent;
-
- clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
- "\tbest_parent name = %s, best_prate = %lu\n",
- clk->name, rate, best,
- __clk_get_name(*best_parent_p), *best_parent_rate);
-
- return best;
-}
-
-static long clk_mux_with_evendiv_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_div_round_rate_even(hw, rate, prate);
-}
-
-const struct clk_ops clkops_rate_mux_with_evendiv = {
- .recalc_rate = clk_divider_recalc_rate,
- .set_rate = clk_divider_set_rate,
- .round_rate = clk_mux_with_evendiv_round_rate,
- .determine_rate = clk_mux_with_evendiv_determine_rate,
-};
-
-static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- u32 numerator, denominator;
- struct clk_divider *div = to_clk_divider(hw);
- int i = 10;
-
-
- if(clk_fracdiv_get_config(rate, parent_rate,
- &numerator, &denominator) == 0) {
- while (i--) {
- writel((numerator - 1) << 16 | denominator, div->reg);
- mdelay(1);
- writel(numerator << 16 | denominator, div->reg);
- mdelay(1);
- }
- clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
- } else {
- clk_err("clk_frac_div name=%s can't get rate=%lu\n",
- hw->clk->name, rate);
- return -EINVAL;
- }
-
- return 0;
-}
-
-const struct clk_ops clkops_rate_frac = {
- .recalc_rate = clk_fracdiv_recalc,
- .round_rate = clk_fracdiv_round_rate,
- .set_rate = clk_fracdiv_set_rate,
-};
-
-const struct clk_ops clkops_rate_i2s_frac = {
- .recalc_rate = clk_fracdiv_recalc,
- .round_rate = clk_fracdiv_round_rate,
- .set_rate = clk_i2s_fracdiv_set_rate,
-};
-
-static unsigned long clk_core_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- /* As parent rate could be changed in clk_core.set_rate
- * ops, the passing_in parent_rate may not be the newest
- * and we should use the parent->rate instead. As a side
- * effect, we should NOT directly set clk_core's parent
- * (apll) rate, otherwise we will get a wrong recalc rate
- * with clk_core_recalc_rate.
- */
- struct clk *parent = __clk_get_parent(hw->clk);
-
- return clk_divider_recalc_rate(hw, __clk_get_rate(parent));
-}
-
-static long clk_core_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (IS_ERR_OR_NULL(parent)) {
- clk_err("fail to get parent!\n");
- return 0;
- }
-
- return clk_round_rate(parent, rate);
-}
-
-static long clk_core_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_core_determine_rate(hw, rate, prate, NULL);
-}
-
-static int clk_core_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
- struct clk *grand_p = __clk_get_parent(parent);
- int ret;
-
- if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
- clk_err("fail to get parent or grand_parent!\n");
- return -EINVAL;
- }
-
- ret = parent->ops->set_rate(parent->hw, rate, __clk_get_rate(grand_p));
- parent->rate = parent->ops->recalc_rate(parent->hw,
- __clk_get_rate(grand_p));
-
- return ret;
-}
-
-const struct clk_ops clkops_rate_core = {
- .recalc_rate = clk_core_recalc_rate,
- .round_rate = clk_core_round_rate,
- .set_rate = clk_core_set_rate,
- .determine_rate = clk_core_determine_rate,
-};
-
-/* Clk_ops for the child clk of clk_core, for example core_periph in rk3188 */
-const struct clk_ops clkops_rate_core_peri = {
- .recalc_rate = clk_divider_recalc_rate,
- .round_rate = clk_divider_round_rate,
- .set_rate = NULL,
-};
-
-
-static unsigned long clk_ddr_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- /* Same as clk_core, we should NOT set clk_ddr's parent
- * (dpll) rate directly as a side effect.
- */
- return clk_core_recalc_rate(hw, parent_rate);
-}
-
-static long clk_ddr_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- long best = 0;
-
- if (!ddr_round_rate) {
- /* Do nothing before ddr init */
- best = rate;//__clk_get_rate(hw->clk);
- } else {
- /* Func provided by ddr driver */
- best = ddr_round_rate(rate/MHZ) * MHZ;
- }
-
- clk_debug("%s: from %lu to %lu\n", __func__, rate, best);
-
- return best;
-}
-
-static long clk_ddr_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_ddr_determine_rate(hw, rate, prate, NULL);
-}
-
-static int clk_ddr_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
- struct clk *grand_p = __clk_get_parent(parent);
-
-
- /* Do nothing before ddr init */
- if (!ddr_change_freq)
- return 0;
-
- if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
- clk_err("fail to get parent or grand_parent!\n");
- return -EINVAL;
- }
-
- clk_debug("%s: will set rate = %lu\n", __func__, rate);
-
- /* Func provided by ddr driver */
- ddr_change_freq(rate/MHZ);
-
- parent->rate = parent->ops->recalc_rate(parent->hw,
- __clk_get_rate(grand_p));
-
- return 0;
-}
-
-const struct clk_ops clkops_rate_ddr = {
- .recalc_rate = clk_ddr_recalc_rate,
- .round_rate = clk_ddr_round_rate,
- .set_rate = clk_ddr_set_rate,
- .determine_rate = clk_ddr_determine_rate,
-};
-
-static unsigned long clk_ddr_div2_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- /* Same as clk_core, we should NOT set clk_ddr's parent
- * (dpll) rate directly as a side effect.
- */
- struct clk *parent = __clk_get_parent(hw->clk);
-
- return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/2;
-}
-
-const struct clk_ops clkops_rate_ddr_div2 = {
- .recalc_rate = clk_ddr_div2_recalc_rate,
- .round_rate = clk_ddr_round_rate,
- .set_rate = clk_ddr_set_rate,
- .determine_rate = clk_ddr_determine_rate,
-};
-
-static unsigned long clk_ddr_div4_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- /* Same as clk_core, we should NOT set clk_ddr's parent
- * (dpll) rate directly as a side effect.
- */
- struct clk *parent = __clk_get_parent(hw->clk);
-
- return clk_divider_recalc_rate(hw, __clk_get_rate(parent))/4;
-}
-
-const struct clk_ops clkops_rate_ddr_div4 = {
- .recalc_rate = clk_ddr_div4_recalc_rate,
- .round_rate = clk_ddr_round_rate,
- .set_rate = clk_ddr_set_rate,
- .determine_rate = clk_ddr_determine_rate,
-};
-
-
-static unsigned long clk_3288_i2s_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return parent_rate;
-}
-
-static long clk_3288_i2s_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return rate;
-}
-
-static int clk_3288_i2s_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
- struct clk *grand_p = __clk_get_parent(parent);
-
-
- if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(grand_p)) {
- return 0;
- }
-
- if (parent->ops->set_rate) {
- parent->ops->set_rate(parent->hw, rate/2, __clk_get_rate(grand_p));
- parent->ops->set_rate(parent->hw, rate, __clk_get_rate(grand_p));
- }
-
- return 0;
-}
-
-const struct clk_ops clkops_rate_3288_i2s = {
- .recalc_rate = clk_3288_i2s_recalc_rate,
- .round_rate = clk_3288_i2s_round_rate,
- .set_rate = clk_3288_i2s_set_rate,
-};
-
-static bool usb480m_state = false;
-
-static long clk_3288_usb480m_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- if(rate == 0)
- return 0;
- else
- return 480*MHZ;
-}
-
-static long clk_3288_usb480m_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_3288_usb480m_determine_rate(hw, rate, prate, NULL);
-}
-
-static int clk_3288_usb480m_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- if(rate == 0)
- usb480m_state = false;
- else
- usb480m_state = true;
-
- return 0;
-}
-
-static unsigned long clk_3288_usb480m_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- if(usb480m_state)
- return 480*MHZ;
- else
- return 0;
-}
-
-const struct clk_ops clkops_rate_3288_usb480m = {
- .determine_rate = clk_3288_usb480m_determine_rate,
- .set_rate = clk_3288_usb480m_set_rate,
- .round_rate = clk_3288_usb480m_round_rate,
- .recalc_rate = clk_3288_usb480m_recalc_rate,
-};
-
-#define RK3288_LIMIT_PLL_VIO0 (600*MHZ)
-
-static long clk_3288_dclk_lcdc0_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *gpll = clk_get(NULL, "clk_gpll");
- struct clk *cpll = clk_get(NULL, "clk_cpll");
- unsigned long best, div, prate, gpll_rate;
-
- gpll_rate = __clk_get_rate(gpll);
-
- if ((rate <= (297*MHZ)) && (gpll_rate%rate == 0)) {
- *best_parent_p = gpll;
- best = rate;
- *best_parent_rate = gpll_rate;
- } else {
- *best_parent_p = cpll;
- div = RK3288_LIMIT_PLL_VIO0/rate;
- prate = div * rate;
- *best_parent_rate = clk_round_rate(cpll, prate);
- best = (*best_parent_rate)/div;
- }
-
- return best;
-}
-
-static long clk_3288_dclk_lcdc0_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_3288_dclk_lcdc0_determine_rate(hw, rate, prate, NULL);
-}
-
-static int clk_3288_dclk_lcdc0_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk* aclk_vio0 = clk_get(NULL, "aclk_vio0");
- struct clk* hclk_vio = clk_get(NULL, "hclk_vio");
- struct clk *aclk_vio1;
- struct clk* parent;
- struct clk *gpll = clk_get(NULL, "clk_gpll");
- struct clk *cpll = clk_get(NULL, "clk_cpll");
-
- clk_divider_ops.set_rate(hw, rate, parent_rate);
-
- /* set aclk_vio */
- if (parent_rate == __clk_get_rate(gpll)) {
- parent = clk_get(NULL, "clk_gpll");
- clk_set_parent(aclk_vio0, gpll);
- clk_set_rate(aclk_vio0, 300*MHZ);
- } else {
- parent = clk_get(NULL, "clk_cpll");
- clk_set_parent(aclk_vio0, cpll);
- clk_set_rate(aclk_vio0, __clk_get_rate(cpll));
- }
- clk_set_rate(hclk_vio, 100*MHZ);
-
- /* make aclk_isp and hclk_isp share a same pll in rk3288_eco */
- if (rockchip_get_cpu_version() > 0) {
- aclk_vio1 = clk_get(NULL, "aclk_vio1");
- clk_set_parent(aclk_vio1, parent);
- clk_set_rate(aclk_vio1, __clk_get_rate(parent));
- }
-
- return 0;
-}
-
-const struct clk_ops clkops_rate_3288_dclk_lcdc0 = {
- .determine_rate = clk_3288_dclk_lcdc0_determine_rate,
- .set_rate = clk_3288_dclk_lcdc0_set_rate,
- .round_rate = clk_3288_dclk_lcdc0_round_rate,
- .recalc_rate = clk_divider_recalc_rate,
-};
-
-#define RK3288_LIMIT_PLL_VIO1 (350*MHZ)
-
-static long clk_3288_dclk_lcdc1_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *gpll = clk_get(NULL, "clk_gpll");
- struct clk *cpll = clk_get(NULL, "clk_cpll");
- unsigned long best, div, prate, gpll_rate;
-
- gpll_rate = __clk_get_rate(gpll);
-
- if ((rate <= (297*MHZ)) && ((gpll_rate)%rate == 0)) {
- *best_parent_p = gpll;
- best = rate;
- *best_parent_rate = gpll_rate;
- } else {
- *best_parent_p = cpll;
- div = RK3288_LIMIT_PLL_VIO1/rate;
- prate = div * rate;
- *best_parent_rate = clk_round_rate(cpll, prate);
- best = (*best_parent_rate)/div;
- }
-
- return best;
-}
-
-static long clk_3288_dclk_lcdc1_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_3288_dclk_lcdc1_determine_rate(hw, rate, prate, NULL);
-}
-
-static int clk_3288_dclk_lcdc1_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk* aclk_vio1 = clk_get(NULL, "aclk_vio1");
- struct clk* parent;
- struct clk *gpll = clk_get(NULL, "clk_gpll");
- struct clk *cpll = clk_get(NULL, "clk_cpll");
-
- clk_divider_ops.set_rate(hw, rate, parent_rate);
-
- /* set aclk_vio */
- if (parent_rate == __clk_get_rate(gpll)) {
- parent = clk_get(NULL, "clk_gpll");
- clk_set_parent(aclk_vio1, gpll);
- clk_set_rate(aclk_vio1, 300*MHZ);
- } else {
- parent = clk_get(NULL, "clk_cpll");
- clk_set_parent(aclk_vio1, cpll);
- clk_set_rate(aclk_vio1, __clk_get_rate(cpll));
- }
-
- if (rockchip_get_cpu_version() == 0) {
- clk_set_parent(aclk_vio1, parent);
- clk_set_rate(aclk_vio1, __clk_get_rate(parent));
- }
-
- return 0;
-}
-
-const struct clk_ops clkops_rate_3288_dclk_lcdc1 = {
- .determine_rate = clk_3288_dclk_lcdc1_determine_rate,
- .set_rate = clk_3288_dclk_lcdc1_set_rate,
- .round_rate = clk_3288_dclk_lcdc1_round_rate,
- .recalc_rate = clk_divider_recalc_rate,
-};
-
-#define CONFIG_RK3368_MUX_NO_USE_NPLL
-
-static long clk_3368_mux_div_determine_rate(struct clk_hw *div_hw,
- unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *clk = div_hw->clk, *parent = NULL, *best_parent = NULL;
- int i, num_parents;
- unsigned long parent_rate = 0, best_prate = 0, best = 0, now = 0;
-
- parent = __clk_get_parent(clk);
- if (!parent) {
- best = __clk_get_rate(clk);
- goto out;
- }
-
- /* if NO_REPARENT flag set, pass through to current parent */
- if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
- best_prate = __clk_get_rate(parent);
- best = clk_divider_ops.round_rate(div_hw, rate, &best_prate);
- goto out;
- }
-
- /* find the parent that can provide the fastest rate <= rate */
- num_parents = clk->num_parents;
- for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
- if (!parent)
- continue;
-
-#ifdef CONFIG_RK3368_MUX_NO_USE_NPLL
- if (!strcmp(__clk_get_name(parent), "clk_npll"))
- continue;
-#endif
- parent_rate = __clk_get_rate(parent);
- now = clk_divider_ops.round_rate(div_hw, rate, &parent_rate);
-
- if (now <= rate && now > best) {
- best_parent = parent;
- best_prate = parent_rate;
- best = now;
- }
- }
-
-out:
- if (best_prate)
- *best_parent_rate = best_prate;
-
- if (best_parent)
- *best_parent_p = best_parent;
-
- clk_debug("clk name = %s, determine rate = %lu, best = %lu\n"
- "\tbest_parent name = %s, best_prate = %lu\n",
- clk->name, rate, best,
- __clk_get_name(*best_parent_p), *best_parent_rate);
-
- return best;
-}
-
-const struct clk_ops clkops_rate_3368_auto_parent = {
- .recalc_rate = clk_divider_recalc_rate,
- .round_rate = clk_divider_round_rate,
- .set_rate = clk_divider_set_rate,
- .determine_rate = clk_3368_mux_div_determine_rate,
-};
-
-#define RK3368_LIMIT_NPLL (1250*MHZ)
-
-static long clk_3368_dclk_lcdc_determine_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long *best_parent_rate,
- struct clk **best_parent_p)
-{
- struct clk *npll = clk_get(NULL, "clk_npll");
- unsigned long div, prate, best, *p_prate;
- static unsigned long rk3368_pll_rates[] = {1188*MHZ, 0};
-
- if (best_parent_p)
- *best_parent_p = npll;
-
- /* first get parent_rate from table */
- p_prate = rk3368_pll_rates;
-
- while (*p_prate) {
- if (!(*p_prate % (rate*2)) || (*p_prate == rate)) {
- clk_debug("%s: get rate from table\n", __func__);
- *best_parent_rate = *p_prate;
- best = rate;
- return best;
- }
- p_prate++;
- }
-
- /* if not suitable parent_rate found in table, then auto calc rate */
- div = RK3368_LIMIT_NPLL/rate;
- /* div should be even */
- if (div % 2)
- div = div - 1;
-
- prate = div * rate;
- *best_parent_rate = clk_round_rate(npll, prate);
- best = (*best_parent_rate)/div;
-
- return best;
-}
-
-static long clk_3368_dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_3368_dclk_lcdc_determine_rate(hw, rate, prate, NULL);
-}
-
-const struct clk_ops clkops_rate_3368_dclk_lcdc = {
- .determine_rate = clk_3368_dclk_lcdc_determine_rate,
- .set_rate = clk_divider_set_rate,
- .round_rate = clk_3368_dclk_lcdc_round_rate,
- .recalc_rate = clk_divider_recalc_rate,
-};
-
-static unsigned long clk_rk3368_ddr_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- if (!ddr_recalc_rate)
- return (clk_core_recalc_rate(hw, parent_rate)/2);
- else
- return ddr_recalc_rate();
-}
-
-const struct clk_ops clkops_rate_rk3368_ddr = {
- .recalc_rate = clk_rk3368_ddr_recalc_rate,
- .round_rate = clk_ddr_round_rate,
- .set_rate = clk_ddr_set_rate,
- .determine_rate = clk_ddr_determine_rate,
-};
-
-
-
-struct clk_ops_table rk_clkops_rate_table[] = {
- {.index = CLKOPS_RATE_MUX_DIV, .clk_ops = &clkops_rate_auto_parent},
- {.index = CLKOPS_RATE_EVENDIV, .clk_ops = &clkops_rate_evendiv},
- {.index = CLKOPS_RATE_MUX_EVENDIV, .clk_ops = &clkops_rate_mux_with_evendiv},
- {.index = CLKOPS_RATE_I2S_FRAC, .clk_ops = &clkops_rate_i2s_frac},
- {.index = CLKOPS_RATE_FRAC, .clk_ops = &clkops_rate_frac},
- {.index = CLKOPS_RATE_CORE, .clk_ops = &clkops_rate_core},
- {.index = CLKOPS_RATE_CORE_CHILD, .clk_ops = &clkops_rate_core_peri},
- {.index = CLKOPS_RATE_DDR, .clk_ops = &clkops_rate_ddr},
- {.index = CLKOPS_RATE_RK3288_I2S, .clk_ops = &clkops_rate_3288_i2s},
- {.index = CLKOPS_RATE_RK3288_USB480M, .clk_ops = &clkops_rate_3288_usb480m},
- {.index = CLKOPS_RATE_RK3288_DCLK_LCDC0,.clk_ops = &clkops_rate_3288_dclk_lcdc0},
- {.index = CLKOPS_RATE_RK3288_DCLK_LCDC1,.clk_ops = &clkops_rate_3288_dclk_lcdc1},
- {.index = CLKOPS_RATE_DDR_DIV2, .clk_ops = &clkops_rate_ddr_div2},
- {.index = CLKOPS_RATE_DDR_DIV4, .clk_ops = &clkops_rate_ddr_div4},
- {.index = CLKOPS_RATE_RK3368_MUX_DIV_NPLL, .clk_ops = &clkops_rate_3368_auto_parent},
- {.index = CLKOPS_RATE_RK3368_DCLK_LCDC, .clk_ops = &clkops_rate_3368_dclk_lcdc},
- {.index = CLKOPS_RATE_RK3368_DDR, .clk_ops = &clkops_rate_rk3368_ddr},
- {.index = CLKOPS_RATE_I2S, .clk_ops = NULL},
- {.index = CLKOPS_RATE_CIFOUT, .clk_ops = NULL},
- {.index = CLKOPS_RATE_UART, .clk_ops = NULL},
- {.index = CLKOPS_RATE_HSADC, .clk_ops = NULL},
- {.index = CLKOPS_RATE_MAC_REF, .clk_ops = NULL},
- {.index = CLKOPS_TABLE_END, .clk_ops = NULL},
-};
-
-const struct clk_ops *rk_get_clkops(unsigned int idx)
-{
- int i = 0;
- unsigned int now_idx;
-
- while(1){
- now_idx = rk_clkops_rate_table[i].index;
-
- if ((now_idx == idx) || (now_idx == CLKOPS_TABLE_END))
- return rk_clkops_rate_table[i].clk_ops;
-
- i++;
- }
-}
-EXPORT_SYMBOL_GPL(rk_get_clkops);
+++ /dev/null
-#ifndef __RK_CLK_OPS_H
-#define __RK_CLK_OPS_H
-
-#include <dt-bindings/clock/rockchip,rk3188.h>
-#include <linux/rockchip/iomap.h>
-#include <linux/rockchip/grf.h>
-
-#define MHZ (1000UL * 1000UL)
-#define KHZ (1000UL)
-
-struct clk_ops_table {
- unsigned int index;
- const struct clk_ops *clk_ops;
-};
-const struct clk_ops *rk_get_clkops(unsigned int idx);
-
-//#define RKCLK_DEBUG
-//#define RKCLK_TEST
-
-#if defined(RKCLK_DEBUG)
-#define clk_debug(fmt, args...) printk(KERN_INFO "rkclk: "fmt, ##args)
-#else
-#define clk_debug(fmt, args...) do {} while(0)
-#endif
-
-#define clk_err(fmt, args...) printk(KERN_ERR "rkclk: "fmt, ##args)
-
-u32 cru_readl(u32 offset);
-void cru_writel(u32 val, u32 offset);
-
-u32 grf_readl(u32 offset);
-
-#endif /* __RK_CLKOPS_H */
+++ /dev/null
-#include <linux/slab.h>
-
-#include "clk-ops.h"
-#include "clk-pd.h"
-
-
-static LIST_HEAD(clk_pd_notifier_list);
-
-static int __clk_pd_notify(struct clk *clk, unsigned long msg)
-{
- struct clk_pd_notifier *cn;
- int ret = NOTIFY_DONE;
-
- list_for_each_entry(cn, &clk_pd_notifier_list, node) {
- if (cn->clk == clk) {
- ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
- NULL);
- break;
- }
- }
-
- return ret;
-}
-
-int rk_clk_pd_notifier_register(struct clk *clk, struct notifier_block *nb)
-{
- struct clk_pd_notifier *cn;
- int ret = -ENOMEM;
-
- if (!clk || !nb)
- return -EINVAL;
-
- //clk_prepare_lock();
-
- /* search the list of notifiers for this clk */
- list_for_each_entry(cn, &clk_pd_notifier_list, node)
- if (cn->clk == clk)
- break;
-
- /* if clk wasn't in the notifier list, allocate new clk_notifier */
- if (cn->clk != clk) {
- cn = kzalloc(sizeof(struct clk_pd_notifier), GFP_KERNEL);
- if (!cn)
- goto out;
-
- cn->clk = clk;
- srcu_init_notifier_head(&cn->notifier_head);
-
- list_add(&cn->node, &clk_pd_notifier_list);
- }
-
- ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
-
- //clk->notifier_count++;
-
-out:
- //clk_prepare_unlock();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rk_clk_pd_notifier_register);
-
-int rk_clk_pd_notifier_unregister(struct clk *clk, struct notifier_block *nb)
-{
- struct clk_pd_notifier *cn = NULL;
- int ret = -EINVAL;
-
- if (!clk || !nb)
- return -EINVAL;
-
- //clk_prepare_lock();
-
- list_for_each_entry(cn, &clk_pd_notifier_list, node)
- if (cn->clk == clk)
- break;
-
- if (cn->clk == clk) {
- ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
-
- //clk->notifier_count--;
-
- /* XXX the notifier code should handle this better */
- if (!cn->notifier_head.head) {
- srcu_cleanup_notifier_head(&cn->notifier_head);
- list_del(&cn->node);
- kfree(cn);
- }
-
- } else {
- ret = -ENOENT;
- }
-
- //clk_prepare_unlock();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(rk_clk_pd_notifier_unregister);
-
-static int clk_pd_endisable(struct clk_hw *hw, bool enable)
-{
- struct clk_pd *pd = to_clk_pd(hw);
- unsigned long flags = 0;
- int ret = 0;
-
- if (pd->lock)
- spin_lock_irqsave(pd->lock, flags);
-
- ret = rockchip_pmu_ops.set_power_domain(pd->id, enable);
-
- if (pd->lock)
- spin_unlock_irqrestore(pd->lock, flags);
-
- return ret;
-}
-
-static int clk_pd_enable(struct clk_hw *hw)
-{
- int ret = 0;
-
- __clk_pd_notify(hw->clk, RK_CLK_PD_PRE_ENABLE);
-
- ret = clk_pd_endisable(hw, true);
-
- __clk_pd_notify(hw->clk, RK_CLK_PD_POST_ENABLE);
-
- return ret;
-}
-
-static void clk_pd_disable(struct clk_hw *hw)
-{
- __clk_pd_notify(hw->clk, RK_CLK_PD_PRE_DISABLE);
-
- clk_pd_endisable(hw, false);
-
- __clk_pd_notify(hw->clk, RK_CLK_PD_POST_DISABLE);
-}
-
-static int clk_pd_is_enabled(struct clk_hw *hw)
-{
- struct clk_pd *pd = to_clk_pd(hw);
-
- return rockchip_pmu_ops.power_domain_is_on(pd->id);
-}
-
-static int clk_pd_prepare(struct clk_hw *hw)
-{
- __clk_pd_notify(hw->clk, RK_CLK_PD_PREPARE);
-
- return 0;
-}
-
-static void clk_pd_unprepare(struct clk_hw *hw)
-{
- __clk_pd_notify(hw->clk, RK_CLK_PD_UNPREPARE);
-}
-
-const struct clk_ops clk_pd_ops = {
- .prepare = clk_pd_prepare,
- .unprepare = clk_pd_unprepare,
- .enable = clk_pd_enable,
- .disable = clk_pd_disable,
- .is_enabled = clk_pd_is_enabled,
-};
-
-static int clk_pd_virt_enable(struct clk_hw *hw)
-{
- __clk_pd_notify(hw->clk, RK_CLK_PD_PRE_ENABLE);
-
- __clk_pd_notify(hw->clk, RK_CLK_PD_POST_ENABLE);
-
- return 0;
-}
-
-static void clk_pd_virt_disable(struct clk_hw *hw)
-{
- __clk_pd_notify(hw->clk, RK_CLK_PD_PRE_DISABLE);
-
- __clk_pd_notify(hw->clk, RK_CLK_PD_POST_DISABLE);
-}
-
-const struct clk_ops clk_pd_virt_ops = {
- .prepare = clk_pd_prepare,
- .unprepare = clk_pd_unprepare,
- .enable = clk_pd_virt_enable,
- .disable = clk_pd_virt_disable,
-};
-
-
-struct clk *rk_clk_register_pd(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags,
- u32 pd_id, spinlock_t *lock)
-{
- struct clk_pd *pd;
- struct clk *clk;
- struct clk_init_data init;
-
-
- /* allocate the pd */
- pd = kzalloc(sizeof(struct clk_pd), GFP_KERNEL);
- if (!pd) {
- clk_err("%s: could not allocate pd clk\n", __func__);
- return ERR_PTR(-ENOMEM);
- }
-
- init.name = name;
- init.flags = flags | CLK_IS_BASIC;
- init.parent_names = (parent_name ? &parent_name: NULL);
- init.num_parents = (parent_name ? 1 : 0);
-
- if(pd_id == CLK_PD_VIRT)
- init.ops = &clk_pd_virt_ops;
- else
- init.ops = &clk_pd_ops;
-
- /* struct clk_pd assignments */
- pd->id= pd_id;
- pd->lock = lock;
- pd->hw.init = &init;
-
- /* register the clock */
- clk = clk_register(dev, &pd->hw);
-
- if (IS_ERR(clk))
- kfree(pd);
-
- return clk;
-}
-
+++ /dev/null
-#ifndef __RK_CLK_PD_H
-#define __RK_CLK_PD_H
-
-#include <linux/clk-provider.h>
-#include <linux/rockchip/pmu.h>
-
-
-
-#define to_clk_pd(_hw) container_of(_hw, struct clk_pd, hw)
-
-struct clk_pd {
- struct clk_hw hw;
- u32 id;
- spinlock_t *lock;
-};
-
-struct clk *rk_clk_register_pd(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags,
- u32 pd_id, spinlock_t *lock);
-
-
-#define RK_CLK_PD_PRE_ENABLE BIT(0)
-#define RK_CLK_PD_POST_ENABLE BIT(1)
-#define RK_CLK_PD_PRE_DISABLE BIT(2)
-#define RK_CLK_PD_POST_DISABLE BIT(3)
-#define RK_CLK_PD_PREPARE BIT(4)
-#define RK_CLK_PD_UNPREPARE BIT(5)
-
-
-struct clk_pd_notifier {
- struct clk *clk;
- struct srcu_notifier_head notifier_head;
- struct list_head node;
-};
-
-int rk_clk_pd_notifier_register(struct clk *clk, struct notifier_block *nb);
-
-int rk_clk_pd_notifier_unregister(struct clk *clk, struct notifier_block *nb);
-
-#endif /* __RK_CLK_PD_H */
+++ /dev/null
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/rockchip/cpu.h>
-
-#include "clk-ops.h"
-#include "clk-pll.h"
-
-
-static const struct pll_clk_set rk3188_pll_com_table[] = {
- _RK3188_PLL_SET_CLKS(1250000, 12, 625, 1),
- _RK3188_PLL_SET_CLKS(1200000, 1, 50, 1),
- _RK3188_PLL_SET_CLKS(1188000, 2, 99, 1),
- _RK3188_PLL_SET_CLKS(891000, 8, 594, 2),
- _RK3188_PLL_SET_CLKS(768000, 1, 64, 2),
- _RK3188_PLL_SET_CLKS(594000, 2, 198, 4),
- _RK3188_PLL_SET_CLKS(500000, 3, 250, 4),
- _RK3188_PLL_SET_CLKS(408000, 1, 68, 4),
- _RK3188_PLL_SET_CLKS(396000, 1, 66, 4),
- _RK3188_PLL_SET_CLKS(384000, 2, 128, 4),
- _RK3188_PLL_SET_CLKS(360000, 1, 60, 4),
- _RK3188_PLL_SET_CLKS(300000, 1, 50, 4),
- _RK3188_PLL_SET_CLKS(297000, 2, 198, 8),
- _RK3188_PLL_SET_CLKS(148500, 2, 99, 8),
- _RK3188_PLL_SET_CLKS(0, 0, 0, 0),
-};
-
-static const struct pll_clk_set rk3188plus_pll_com_table[] = {
- _RK3188PLUS_PLL_SET_CLKS(1250000, 12, 625, 1),
- _RK3188PLUS_PLL_SET_CLKS(1200000, 1, 50, 1),
- _RK3188PLUS_PLL_SET_CLKS(1188000, 2, 99, 1),
- _RK3188PLUS_PLL_SET_CLKS(891000, 8, 594, 2),
- _RK3188PLUS_PLL_SET_CLKS(768000, 1, 64, 2),
- _RK3188PLUS_PLL_SET_CLKS(594000, 2, 198, 4),
- _RK3188PLUS_PLL_SET_CLKS(576000, 1, 48, 2),
- _RK3188PLUS_PLL_SET_CLKS(500000, 3, 250, 4),
- _RK3188PLUS_PLL_SET_CLKS(408000, 1, 68, 4),
- _RK3188PLUS_PLL_SET_CLKS(400000, 3, 200, 4),
- _RK3188PLUS_PLL_SET_CLKS(396000, 1, 66, 4),
- _RK3188PLUS_PLL_SET_CLKS(384000, 2, 128, 4),
- _RK3188PLUS_PLL_SET_CLKS(360000, 1, 60, 4),
- _RK3188PLUS_PLL_SET_CLKS(300000, 1, 50, 4),
- _RK3188PLUS_PLL_SET_CLKS(297000, 2, 198, 8),
- _RK3188PLUS_PLL_SET_CLKS(148500, 2, 99, 8),
- _RK3188PLUS_PLL_SET_CLKS(0, 0, 0, 0),
-};
-
-static const struct apll_clk_set rk3188_apll_table[] = {
- // (_mhz, nr, nf, no, _periph_div, _aclk_div)
- _RK3188_APLL_SET_CLKS(2208, 1, 92, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2184, 1, 91, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2160, 1, 90, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2136, 1, 89, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2112, 1, 88, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2088, 1, 87, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2064, 1, 86, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2040, 1, 85, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(2016, 1, 84, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1992, 1, 83, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1968, 1, 82, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1944, 1, 81, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1920, 1, 80, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1896, 1, 79, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1872, 1, 78, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1848, 1, 77, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1824, 1, 76, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1800, 1, 75, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1776, 1, 74, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1752, 1, 73, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1728, 1, 72, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1704, 1, 71, 1, 8, 81),
- _RK3188_APLL_SET_CLKS(1680, 1, 70, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1656, 1, 69, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1632, 1, 68, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1608, 1, 67, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1560, 1, 65, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1512, 1, 63, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1488, 1, 62, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1464, 1, 61, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1440, 1, 60, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1416, 1, 59, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1392, 1, 58, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1368, 1, 57, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1344, 1, 56, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1320, 1, 55, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1296, 1, 54, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1272, 1, 53, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1248, 1, 52, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1224, 1, 51, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1200, 1, 50, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1176, 1, 49, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1128, 1, 47, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1104, 1, 46, 1, 8, 41),
- _RK3188_APLL_SET_CLKS(1008, 1, 84, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(912, 1, 76, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(888, 1, 74, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(816, 1, 68, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(792, 1, 66, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(696, 1, 58, 2, 8, 41),
- _RK3188_APLL_SET_CLKS(600, 1, 50, 2, 4, 41),
- _RK3188_APLL_SET_CLKS(552, 1, 92, 4, 4, 41),
- _RK3188_APLL_SET_CLKS(504, 1, 84, 4, 4, 41),
- _RK3188_APLL_SET_CLKS(408, 1, 68, 4, 4, 21),
- _RK3188_APLL_SET_CLKS(312, 1, 52, 4, 2, 21),
- _RK3188_APLL_SET_CLKS(252, 1, 84, 8, 2, 21),
- _RK3188_APLL_SET_CLKS(216, 1, 72, 8, 2, 21),
- _RK3188_APLL_SET_CLKS(126, 1, 84, 16, 2, 11),
- _RK3188_APLL_SET_CLKS(48, 1, 32, 16, 2, 11),
- _RK3188_APLL_SET_CLKS(0, 1, 32, 16, 2, 11),
-};
-
-static const struct apll_clk_set rk3288_apll_table[] = {
- // (_mhz, nr, nf, no, l2ram, m0, mp, atclk, pclk_dbg)
- _RK3288_APLL_SET_CLKS(2208, 1, 92, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2184, 1, 91, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2160, 1, 90, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2136, 1, 89, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2112, 1, 88, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2088, 1, 87, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2064, 1, 86, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2040, 1, 85, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(2016, 1, 84, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1992, 1, 83, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1968, 1, 82, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1944, 1, 81, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1920, 1, 80, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1896, 1, 79, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1872, 1, 78, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1848, 1, 77, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1824, 1, 76, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1800, 1, 75, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1776, 1, 74, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1752, 1, 73, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1728, 1, 72, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1704, 1, 71, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1680, 1, 70, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1656, 1, 69, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1632, 1, 68, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1608, 1, 67, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1560, 1, 65, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1512, 1, 63, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1488, 1, 62, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1464, 1, 61, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1440, 1, 60, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1416, 1, 59, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1392, 1, 58, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1368, 1, 57, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1344, 1, 56, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1320, 1, 55, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1296, 1, 54, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1272, 1, 53, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1248, 1, 52, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1224, 1, 51, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1200, 1, 50, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1176, 1, 49, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1128, 1, 47, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1104, 1, 46, 1, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(1008, 1, 84, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(912, 1, 76, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(888, 1, 74, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(816, 1, 68, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(792, 1, 66, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(696, 1, 58, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(672, 1, 56, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(648, 1, 54, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(624, 1, 52, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(600, 1, 50, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(576, 1, 48, 2, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(552, 1, 92, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(528, 1, 88, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(504, 1, 84, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(480, 1, 80, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(456, 1, 76, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(408, 1, 68, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(312, 1, 52, 4, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(252, 1, 84, 8, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(216, 1, 72, 8, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(126, 2, 84, 8, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(48, 2, 32, 8, 2, 2, 4, 4, 4),
- _RK3288_APLL_SET_CLKS(0, 1, 32, 16, 2, 2, 4, 4, 4),
-};
-
-static const struct apll_clk_set rk3036_apll_table[] = {
- _RK3036_APLL_SET_CLKS(1608, 1, 67, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1584, 1, 66, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1560, 1, 65, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1536, 1, 64, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1512, 1, 63, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1488, 1, 62, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1464, 1, 61, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1440, 1, 60, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1416, 1, 59, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1392, 1, 58, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1368, 1, 57, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1344, 1, 56, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1320, 1, 55, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1296, 1, 54, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1272, 1, 53, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1248, 1, 52, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1200, 1, 50, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1104, 1, 46, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1100, 12, 550, 1, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1008, 1, 84, 2, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(1000, 6, 500, 2, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(984, 1, 82, 2, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(960, 1, 80, 2, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(936, 1, 78, 2, 1, 1, 0, 81),
- _RK3036_APLL_SET_CLKS(912, 1, 76, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(900, 4, 300, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(888, 1, 74, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(864, 1, 72, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(840, 1, 70, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(816, 1, 68, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(800, 6, 400, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(700, 6, 350, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(696, 1, 58, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(600, 1, 75, 3, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(504, 1, 63, 3, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(500, 6, 250, 2, 1, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(408, 1, 68, 2, 2, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(312, 1, 52, 2, 2, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(216, 1, 72, 4, 2, 1, 0, 41),
- _RK3036_APLL_SET_CLKS(96, 1, 64, 4, 4, 1, 0, 21),
- _RK3036_APLL_SET_CLKS(0, 1, 0, 1, 1, 1, 0, 21),
-};
-
-static const struct pll_clk_set rk3036plus_pll_com_table[] = {
- _RK3036_PLL_SET_CLKS(1188000, 2, 99, 1, 1, 1, 0),
- _RK3036_PLL_SET_CLKS(594000, 2, 99, 2, 1, 1, 0),
- /*_RK3036_PLL_SET_CLKS(297000, 2, 99, 4, 1, 1, 0),*/
-};
-
-static const struct pll_clk_set rk312xplus_pll_com_table[] = {
- /*_RK3036_PLL_SET_CLKS(1064000, 3, 133, 1, 1, 1, 0),*/
- /*_RK3036_PLL_SET_CLKS(798000, 2, 133, 2, 1, 1, 0),*/
- _RK3036_PLL_SET_CLKS(1000000, 3, 125, 1, 1, 1, 0),
- _RK3036_PLL_SET_CLKS(594000, 2, 99, 2, 1, 1, 0),
- _RK3036_PLL_SET_CLKS(500000, 3, 125, 2, 1, 1, 0),
- _RK3036_PLL_SET_CLKS(400000, 3, 200, 2, 2, 1, 0),
-};
-
-static const struct apll_clk_set rk3368_apllb_table[] = {
- /*(_mhz, nr, nf, no, aclkm, atclk, pclk_dbg)*/
- _RK3368_APLL_SET_CLKS(1608, 1, 67, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1560, 1, 65, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1512, 1, 63, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1488, 1, 62, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1464, 1, 61, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1440, 1, 60, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1416, 1, 59, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1392, 1, 58, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1368, 1, 57, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1344, 1, 56, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1320, 1, 55, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1296, 1, 54, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1272, 1, 53, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1248, 1, 52, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1224, 1, 51, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1200, 1, 50, 1, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(1176, 1, 49, 1, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(1128, 1, 47, 1, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(1104, 1, 46, 1, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(1008, 1, 84, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(912, 1, 76, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(888, 1, 74, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(816, 1, 68, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(792, 1, 66, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(696, 1, 58, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(672, 1, 56, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(648, 1, 54, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(624, 1, 52, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(600, 1, 50, 2, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(576, 1, 48, 2, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(552, 1, 92, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(528, 1, 88, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(504, 1, 84, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(480, 1, 80, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(456, 1, 76, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(408, 1, 68, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(312, 1, 52, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(252, 1, 84, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(216, 1, 72, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(126, 2, 84, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(48, 2, 32, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(0, 1, 32, 16, 2, 1, 1),
-};
-
-static const struct apll_clk_set rk3368_aplll_table[] = {
- /*(_mhz, nr, nf, no, aclkm, atclk, pclk_dbg)*/
- _RK3368_APLL_SET_CLKS(1608, 1, 67, 1, 2, 7, 7),
- _RK3368_APLL_SET_CLKS(1560, 1, 65, 1, 2, 7, 7),
- _RK3368_APLL_SET_CLKS(1512, 1, 63, 1, 2, 7, 7),
- _RK3368_APLL_SET_CLKS(1488, 1, 62, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1464, 1, 61, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1440, 1, 60, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1416, 1, 59, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1392, 1, 58, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1368, 1, 57, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1344, 1, 56, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1320, 1, 55, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1296, 1, 54, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1272, 1, 53, 1, 2, 6, 6),
- _RK3368_APLL_SET_CLKS(1248, 1, 52, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1224, 1, 51, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1200, 1, 50, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1176, 1, 49, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1128, 1, 47, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1104, 1, 46, 1, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(1008, 1, 84, 2, 2, 5, 5),
- _RK3368_APLL_SET_CLKS(912, 1, 76, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(888, 1, 74, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(816, 1, 68, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(792, 1, 66, 2, 2, 4, 4),
- _RK3368_APLL_SET_CLKS(696, 1, 58, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(672, 1, 56, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(648, 1, 54, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(624, 1, 52, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(600, 1, 50, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(576, 1, 48, 2, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(552, 1, 92, 4, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(528, 1, 88, 4, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(504, 1, 84, 4, 2, 3, 3),
- _RK3368_APLL_SET_CLKS(480, 1, 80, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(456, 1, 76, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(408, 1, 68, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(312, 1, 52, 4, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(252, 1, 84, 8, 2, 2, 2),
- _RK3368_APLL_SET_CLKS(216, 1, 72, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(126, 2, 84, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(48, 2, 32, 8, 2, 1, 1),
- _RK3368_APLL_SET_CLKS(0, 1, 32, 16, 2, 1, 1),
-};
-
-static const struct pll_clk_set rk3368_pll_table_low_jitter[] = {
- /* _khz, nr, nf, no, nb */
- _RK3188PLUS_PLL_SET_CLKS_NB(1188000, 1, 99, 2, 1),
- _RK3188PLUS_PLL_SET_CLKS_NB(400000, 1, 100, 6, 1),
- _RK3188PLUS_PLL_SET_CLKS( 0, 0, 0, 0),
-};
-
-static void pll_wait_lock(struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- int delay = 24000000;
-
- while (delay > 0) {
- if (grf_readl(pll->status_offset) & (1 << pll->status_shift))
- break;
- delay--;
- }
-
- if (delay == 0) {
- clk_err("pll %s: can't lock! status_shift=%u\n"
- "pll_con0=%08x\npll_con1=%08x\n"
- "pll_con2=%08x\npll_con3=%08x\n",
- __clk_get_name(hw->clk),
- pll->status_shift,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)));
-
- while(1);
- }
-}
-
-static void rk3036_pll_wait_lock(struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- int delay = 24000000;
-
-
- while (delay > 0) {
- if (cru_readl(pll->status_offset) & (1 << pll->status_shift))
- break;
- delay--;
- }
-
- if (delay == 0) {
- clk_err("pll %s: can't lock! status_shift=%u\n"
- "pll_con0=%08x\npll_con1=%08x\n"
- "pll_con2=%08x\n",
- __clk_get_name(hw->clk),
- pll->status_shift,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)));
- while (1);
-
- }
-}
-
-
-/* get rate that is most close to target */
-static const struct apll_clk_set *apll_get_best_set(unsigned long rate,
- const struct apll_clk_set *table)
-{
- const struct apll_clk_set *ps, *pt;
-
- ps = pt = table;
- while (pt->rate) {
- if (pt->rate == rate) {
- ps = pt;
- break;
- }
-
- if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate)))
- ps = pt;
- if (pt->rate < rate)
- break;
- pt++;
- }
-
- return ps;
-}
-
-/* get rate that is most close to target */
-static const struct pll_clk_set *pll_com_get_best_set(unsigned long rate,
- const struct pll_clk_set *table)
-{
- const struct pll_clk_set *ps, *pt;
-
- ps = pt = table;
- while (pt->rate) {
- if (pt->rate == rate) {
- ps = pt;
- break;
- }
-
- if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate)))
- ps = pt;
- if (pt->rate < rate)
- break;
- pt++;
- }
-
- return ps;
-}
-
-/* CLK_PLL_3188 type ops */
-static unsigned long clk_pll_recalc_rate_3188(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long rate;
-
-
- if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
- u32 pll_con0 = cru_readl(pll->reg + RK3188_PLL_CON(0));
- u32 pll_con1 = cru_readl(pll->reg + RK3188_PLL_CON(1));
-
- u64 rate64 = (u64)parent_rate * RK3188_PLL_NF(pll_con1);
-
- do_div(rate64, RK3188_PLL_NR(pll_con0));
- do_div(rate64, RK3188_PLL_NO(pll_con0));
-
- rate = rate64;
- } else {
- /*FIXME*/
- rate = parent_rate;
- clk_debug("pll %s is in slow mode\n", __clk_get_name(hw->clk));
- }
-
- clk_debug("pll %s recalc rate =%lu\n", __clk_get_name(hw->clk), rate);
-
- return rate;
-}
-
-static long clk_pll_round_rate_3188(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate==__clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (pll_com_get_best_set(rate, rk3188_pll_com_table)->rate);
-}
-
-static int _pll_clk_set_rate_3188(struct pll_clk_set *clk_set,
- struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long flags = 0;
-
-
- clk_debug("%s start!\n", __func__);
-
- if(pll->lock)
- spin_lock_irqsave(pll->lock, flags);
-
- //enter slowmode
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
- //pll power down
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
-
- udelay(1);
-
- //pll no power down
- cru_writel((0x1<<(16+1)), pll->reg + RK3188_PLL_CON(3));
-
- pll_wait_lock(hw);
-
- //return from slow
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
-
- clk_debug("pll %s dump reg: con0=0x%08x, con1=0x%08x, mode=0x%08x\n",
- __clk_get_name(hw->clk),
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->mode_offset));
-
- clk_debug("%s end!\n", __func__);
-
- return 0;
-}
-
-static int clk_pll_set_rate_3188(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk3188_pll_com_table);
- int ret = 0;
-
-
- if (rate == parent_rate) {
- clk_debug("pll %s set rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
- /* pll power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- clk_debug("pll %s enter slow mode, set rate OK!\n",
- __clk_get_name(hw->clk));
- return 0;
- }
-
- while(clk_set->rate) {
- if (clk_set->rate == rate) {
- break;
- }
- clk_set++;
- }
-
- if (clk_set->rate == rate) {
- ret = _pll_clk_set_rate_3188(clk_set, hw);
- clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk),
- rate);
- } else {
- clk_err("pll %s is no corresponding rate=%lu\n",
- __clk_get_name(hw->clk), rate);
- return -EINVAL;
- }
-
- return ret;
-}
-
-static const struct clk_ops clk_pll_ops_3188 = {
- .recalc_rate = clk_pll_recalc_rate_3188,
- .round_rate = clk_pll_round_rate_3188,
- .set_rate = clk_pll_set_rate_3188,
-};
-
-
-/* CLK_PLL_3188_APLL type ops */
-static unsigned long clk_pll_recalc_rate_3188_apll(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return clk_pll_recalc_rate_3188(hw, parent_rate);
-}
-
-static long clk_pll_round_rate_3188_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate==__clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (apll_get_best_set(rate, rk3188_apll_table)->rate);
-}
-
-/* 1: use, 0: no use */
-#define RK3188_USE_ARM_GPLL 1
-
-static int clk_pll_set_rate_3188_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct clk *clk = hw->clk;
- struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
- unsigned long arm_gpll_rate;
- const struct apll_clk_set *ps;
- u32 old_aclk_div = 0, new_aclk_div = 0;
- u32 temp_div;
- unsigned long flags;
- int sel_gpll = 0;
-
-
- if (rate == parent_rate) {
- clk_debug("pll %s set rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
- /* pll power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- clk_debug("pll %s enter slow mode, set rate OK!\n",
- __clk_get_name(hw->clk));
- return 0;
- }
-
-
-#if !RK3188_USE_ARM_GPLL
- goto CHANGE_APLL;
-#endif
-
- /* prepare arm_gpll before reparent clk_core to it */
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- goto CHANGE_APLL;
- }
-
- /* In rk3188, arm_gpll and cpu_gpll share a same gate,
- * and aclk_cpu selects cpu_gpll as parent, thus this
- * gate must keep enabled.
- */
-#if 0
- if (clk_prepare(arm_gpll)) {
- clk_err("fail to prepare arm_gpll path\n");
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-
- if (clk_enable(arm_gpll)) {
- clk_err("fail to enable arm_gpll path\n");
- clk_disable(arm_gpll);
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-#endif
-
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk));
- temp_div = (temp_div == 0) ? 1 : temp_div;
- if (temp_div > RK3188_CORE_CLK_MAX_DIV) {
- clk_debug("temp_div %d > max_div %d\n", temp_div,
- RK3188_CORE_CLK_MAX_DIV);
- clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
- __clk_get_rate(clk), arm_gpll_rate);
- //clk_disable(arm_gpll);
- //clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-
- local_irq_save(flags);
-
- /* firstly set div, then select arm_gpll path */
- cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(temp_div),
- RK3188_CRU_CLKSELS_CON(0));
- cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_GPLL,
- RK3188_CRU_CLKSELS_CON(0));
-
- sel_gpll = 1;
- //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
- smp_wmb();
-
- local_irq_restore(flags);
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
-CHANGE_APLL:
- ps = apll_get_best_set(rate, rk3188_apll_table);
- clk_debug("apll will set rate %lu\n", ps->rate);
- clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
- ps->pllcon0, ps->pllcon1, ps->pllcon2,
- ps->clksel0, ps->clksel1);
-
- local_irq_save(flags);
-
- /* If core src don't select gpll, apll need to enter slow mode
- * before power down
- */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- /* PLL power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- dsb(sy);
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
-
- udelay(1);
-
- /* PLL power up and wait for locked */
- cru_writel((0x1<<(16+1)), pll->reg + RK3188_PLL_CON(3));
- pll_wait_lock(hw);
-
- old_aclk_div = RK3188_GET_CORE_ACLK_VAL(cru_readl(RK3188_CRU_CLKSELS_CON(1)) &
- RK3188_CORE_ACLK_MSK);
- new_aclk_div = RK3188_GET_CORE_ACLK_VAL(ps->clksel1 & RK3188_CORE_ACLK_MSK);
-
- if (new_aclk_div >= old_aclk_div) {
- cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
- }
-
- /* PLL return from slow mode */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- /* reparent to apll, and set div to 1 */
- if (sel_gpll) {
- cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_APLL,
- RK3188_CRU_CLKSELS_CON(0));
- cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(1),
- RK3188_CRU_CLKSELS_CON(0));
- }
-
- if (old_aclk_div > new_aclk_div) {
- cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
- }
-
- //loops_per_jiffy = ps->lpj;
- smp_wmb();
-
- local_irq_restore(flags);
-
- if (sel_gpll) {
- sel_gpll = 0;
- //clk_disable(arm_gpll);
- //clk_unprepare(arm_gpll);
- }
-
- //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
-
- clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
- ps->rate,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(RK3188_CRU_CLKSELS_CON(0)),
- cru_readl(RK3188_CRU_CLKSELS_CON(1)));
-
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_3188_apll = {
- .recalc_rate = clk_pll_recalc_rate_3188_apll,
- .round_rate = clk_pll_round_rate_3188_apll,
- .set_rate = clk_pll_set_rate_3188_apll,
-};
-
-
-/* CLK_PLL_3188PLUS type ops */
-static unsigned long clk_pll_recalc_rate_3188plus(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long rate;
-
-
- if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
- u32 pll_con0 = cru_readl(pll->reg + RK3188_PLL_CON(0));
- u32 pll_con1 = cru_readl(pll->reg + RK3188_PLL_CON(1));
-
- u64 rate64 = (u64)parent_rate * RK3188PLUS_PLL_NF(pll_con1);
-
- do_div(rate64, RK3188PLUS_PLL_NR(pll_con0));
- do_div(rate64, RK3188PLUS_PLL_NO(pll_con0));
-
- rate = rate64;
- } else {
- /*FIXME*/
- rate = parent_rate;
- clk_debug("pll %s is in slow mode\n", __clk_get_name(hw->clk));
- }
-
- clk_debug("pll %s recalc rate =%lu\n", __clk_get_name(hw->clk), rate);
-
- return rate;
-}
-
-static long clk_pll_round_rate_3188plus(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate==__clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (pll_com_get_best_set(rate, rk3188plus_pll_com_table)->rate);
-}
-
-static int _pll_clk_set_rate_3188plus(struct pll_clk_set *clk_set,
- struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long flags = 0;
-
-
- clk_debug("%s start!\n", __func__);
-
- if(pll->lock)
- spin_lock_irqsave(pll->lock, flags);
-
- //enter slowmode
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- //enter rest
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- //return from rest
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- //wating lock state
- udelay(clk_set->rst_dly);
-
- pll_wait_lock(hw);
-
- //return from slow
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
-
- clk_debug("pll %s dump reg: con0=0x%08x, con1=0x%08x, mode=0x%08x\n",
- __clk_get_name(hw->clk),
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->mode_offset));
-
- clk_debug("%s end!\n", __func__);
-
- return 0;
-}
-
-static int clk_pll_set_rate_3188plus(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- //struct clk_pll *pll = to_clk_pll(hw);
- struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk3188plus_pll_com_table);
- int ret = 0;
-
-#if 0
- if (rate == parent_rate) {
- clk_debug("pll %s set rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
- /* pll power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- clk_debug("pll %s enter slow mode, set rate OK!\n",
- __clk_get_name(hw->clk));
- return 0;
- }
-#endif
-
- while(clk_set->rate) {
- if (clk_set->rate == rate) {
- break;
- }
- clk_set++;
- }
-
- if (cpu_is_rk3288() && ((rate == 297*MHZ) || (rate == 594*MHZ))) {
- if((strncmp(__clk_get_name(hw->clk), "clk_gpll",
- strlen("clk_gpll")) == 0)) {
-
- printk("rk3288 set GPLL BW 20 for HDMI!\n");
- clk_set->pllcon2 = RK3188_PLL_CLK_BWADJ_SET(20);
- }
- }
-
- if (clk_set->rate == rate) {
- ret = _pll_clk_set_rate_3188plus(clk_set, hw);
- clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk),
- rate);
- } else {
- clk_err("pll %s is no corresponding rate=%lu\n",
- __clk_get_name(hw->clk), rate);
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int clk_pll_is_enabled_3188plus(struct clk_hw *hw)
-{
- unsigned long flags;
- struct clk_pll *pll = to_clk_pll(hw);
- int ret;
-
- if(pll->lock)
- spin_lock_irqsave(pll->lock, flags);
-
- if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift))
- ret = 1;
- else
- ret = 0;
-
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
-
- return ret;
-}
-
-static int clk_pll_enable_3188plus(struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long flags;
- unsigned long rst_dly;
- u32 nr;
-
- clk_debug("%s enter\n", __func__);
-
- if (clk_pll_is_enabled_3188plus(hw)) {
- clk_debug("pll has been enabled\n");
- return 0;
- }
-
- if(pll->lock)
- spin_lock_irqsave(pll->lock, flags);
-
- //enter slowmode
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- //power up
- cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- //enter reset
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- //cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
- //cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
- //cru_writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- //return from reset
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- //wating lock state
- nr = RK3188PLUS_PLL_NR(cru_readl(pll->reg + RK3188_PLL_CON(0)));
- rst_dly = ((nr*500)/24+1);
- udelay(rst_dly);
-
- pll_wait_lock(hw);
-
- //return from slow
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
-
- clk_debug("pll %s dump reg:\n con0=0x%08x,\n con1=0x%08x,\n con2=0x%08x,\n"
- "con3=0x%08x,\n mode=0x%08x\n",
- __clk_get_name(hw->clk),
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(pll->mode_offset));
-
- return 0;
-}
-
-static void clk_pll_disable_3188plus(struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long flags;
-
- clk_debug("%s enter\n", __func__);
-
- if(pll->lock)
- spin_lock_irqsave(pll->lock, flags);
-
- //enter slowmode
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- //power down
- cru_writel(_RK3188PLUS_PLL_POWERDOWN_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
-}
-
-static const struct clk_ops clk_pll_ops_3188plus = {
- .recalc_rate = clk_pll_recalc_rate_3188plus,
- .round_rate = clk_pll_round_rate_3188plus,
- .set_rate = clk_pll_set_rate_3188plus,
- .enable = clk_pll_enable_3188plus,
- .disable = clk_pll_disable_3188plus,
- .is_enabled = clk_pll_is_enabled_3188plus,
-};
-
-/* CLK_PLL_3188PLUS_AUTO type ops */
-#define PLL_FREF_MIN (269*KHZ)
-#define PLL_FREF_MAX (2200*MHZ)
-
-#define PLL_FVCO_MIN (440*MHZ)
-#define PLL_FVCO_MAX (2200*MHZ)
-
-#define PLL_FOUT_MIN (27500*KHZ)
-#define PLL_FOUT_MAX (2200*MHZ)
-
-#define PLL_NF_MAX (4096)
-#define PLL_NR_MAX (64)
-#define PLL_NO_MAX (16)
-
-static u32 clk_gcd(u32 numerator, u32 denominator)
-{
- u32 a, b;
-
- if (!numerator || !denominator)
- return 0;
- if (numerator > denominator) {
- a = numerator;
- b = denominator;
- } else {
- a = denominator;
- b = numerator;
- }
- while (b != 0) {
- int r = b;
-
- b = a % b;
- a = r;
- }
-
- return a;
-}
-
-static int pll_clk_get_best_set(unsigned long fin_hz, unsigned long fout_hz,
- u32 *best_nr, u32 *best_nf, u32 *best_no)
-{
- u32 nr, nf, no, nonr;
- u32 nr_out, nf_out, no_out;
- u32 n;
- u32 YFfenzi;
- u32 YFfenmu;
- u64 fref, fvco, fout;
- u32 gcd_val = 0;
-
- nr_out = PLL_NR_MAX + 1;
- no_out = 0;
-
- if (!fin_hz || !fout_hz || fout_hz == fin_hz)
- return -EINVAL;
- gcd_val = clk_gcd(fin_hz, fout_hz);
-
- YFfenzi = fout_hz / gcd_val;
- YFfenmu = fin_hz / gcd_val;
-
- for (n = 1;; n++) {
- nf = YFfenzi * n;
- nonr = YFfenmu * n;
- if (nf > PLL_NF_MAX || nonr > (PLL_NO_MAX * PLL_NR_MAX))
- break;
-
- for (no = 1; no <= PLL_NO_MAX; no++) {
- if (!(no == 1 || !(no % 2)))
- continue;
-
- if (nonr % no)
- continue;
- nr = nonr / no;
-
- if (nr > PLL_NR_MAX)
- continue;
-
- fref = fin_hz / nr;
- if (fref < PLL_FREF_MIN || fref > PLL_FREF_MAX)
- continue;
-
- fvco = fref * nf;
- if (fvco < PLL_FVCO_MIN || fvco > PLL_FVCO_MAX)
- continue;
-
- fout = fvco / no;
- if (fout < PLL_FOUT_MIN || fout > PLL_FOUT_MAX)
- continue;
-
- /* select the best from all available PLL settings */
- if ((no > no_out) || ((no == no_out) && (nr < nr_out))) {
- nr_out = nr;
- nf_out = nf;
- no_out = no;
- }
- }
- }
-
- /* output the best PLL setting */
- if ((nr_out <= PLL_NR_MAX) && (no_out > 0)) {
- if (best_nr && best_nf && best_no) {
- *best_nr = nr_out;
- *best_nf = nf_out;
- *best_no = no_out;
- }
- return 0;
- } else {
- return -EINVAL;
- }
-}
-
-static unsigned long clk_pll_recalc_rate_3188plus_auto(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return clk_pll_recalc_rate_3188plus(hw, parent_rate);
-}
-
-static long clk_pll_round_rate_3188plus_auto(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- unsigned long best;
-
- for(best=rate; best>0; best--){
- if(!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL))
- return best;
- }
-
- return 0;
-}
-
-static int clk_pll_set_rate_3188plus_auto(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- unsigned long best;
- u32 nr,nf,no;
- struct pll_clk_set clk_set;
- int ret;
-
-
- best = clk_pll_round_rate_3188plus_auto(hw, rate, &parent_rate);
-
- if(!best)
- return -EINVAL;
-
- pll_clk_get_best_set(parent_rate, best, &nr, &nf, &no);
-
- /* prepare clk_set */
- clk_set.rate = best;
- clk_set.pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no);
- clk_set.pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf);
- clk_set.pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1);
- clk_set.rst_dly = ((nr*500)/24+1);
-
- ret = _pll_clk_set_rate_3188plus(&clk_set, hw);
- clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk), best);
-
- return ret;
-}
-
-
-static const struct clk_ops clk_pll_ops_3188plus_auto = {
- .recalc_rate = clk_pll_recalc_rate_3188plus_auto,
- .round_rate = clk_pll_round_rate_3188plus_auto,
- .set_rate = clk_pll_set_rate_3188plus_auto,
- .enable = clk_pll_enable_3188plus,
- .disable = clk_pll_disable_3188plus,
- .is_enabled = clk_pll_is_enabled_3188plus,
-};
-
-static long clk_pll_round_rate_3368_low_jitter(struct clk_hw *hw,
- unsigned long rate,
- unsigned long *prate)
-{
- unsigned long best;
- struct pll_clk_set *p_clk_set;
-
- p_clk_set = (struct pll_clk_set *)(rk3368_pll_table_low_jitter);
-
- while (p_clk_set->rate) {
- if (p_clk_set->rate == rate)
- break;
- p_clk_set++;
- }
-
- if (p_clk_set->rate == rate) {
- clk_debug("get rate from table\n");
- return rate;
- }
-
- for (best = rate; best > 0; best--) {
- if (!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL))
- return best;
- }
-
- clk_err("%s: can't round rate %lu\n", __func__, rate);
- return 0;
-}
-
-
-static int clk_pll_set_rate_3368_low_jitter(struct clk_hw *hw,
- unsigned long rate,
- unsigned long parent_rate)
-{
- unsigned long best;
- u32 nr, nf, no;
- struct pll_clk_set clk_set, *p_clk_set;
- int ret;
-
- p_clk_set = (struct pll_clk_set *)(rk3368_pll_table_low_jitter);
-
- while (p_clk_set->rate) {
- if (p_clk_set->rate == rate)
- break;
- p_clk_set++;
- }
-
- if (p_clk_set->rate == rate) {
- clk_debug("get rate from table\n");
- goto set_rate;
- }
-
- best = clk_pll_round_rate_3188plus_auto(hw, rate, &parent_rate);
-
- if (!best)
- return -EINVAL;
-
- pll_clk_get_best_set(parent_rate, best, &nr, &nf, &no);
-
- /* prepare clk_set */
- clk_set.rate = best;
- clk_set.pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no);
- clk_set.pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf);
- clk_set.pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1);
- clk_set.rst_dly = ((nr*500)/24+1);
-
- p_clk_set = &clk_set;
-
-set_rate:
- ret = _pll_clk_set_rate_3188plus(p_clk_set, hw);
- clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk),
- p_clk_set->rate);
-
- return ret;
-}
-
-static const struct clk_ops clk_pll_ops_3368_low_jitter = {
- .recalc_rate = clk_pll_recalc_rate_3188plus_auto,
- .round_rate = clk_pll_round_rate_3368_low_jitter,
- .set_rate = clk_pll_set_rate_3368_low_jitter,
- .enable = clk_pll_enable_3188plus,
- .disable = clk_pll_disable_3188plus,
- .is_enabled = clk_pll_is_enabled_3188plus,
-};
-
-/* CLK_PLL_3188PLUS_APLL type ops */
-static unsigned long clk_pll_recalc_rate_3188plus_apll(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return clk_pll_recalc_rate_3188plus(hw, parent_rate);
-}
-
-static long clk_pll_round_rate_3188plus_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return clk_pll_round_rate_3188_apll(hw, rate, prate);
-}
-
-/* 1: use, 0: no use */
-#define RK3188PLUS_USE_ARM_GPLL 1
-
-static int clk_pll_set_rate_3188plus_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct clk *clk = hw->clk;
- struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
- unsigned long arm_gpll_rate;
- const struct apll_clk_set *ps;
- u32 old_aclk_div = 0, new_aclk_div = 0;
- u32 temp_div;
- unsigned long flags;
- int sel_gpll = 0;
-
-#if 0
- if (rate == parent_rate) {
- clk_debug("pll %s set rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
- /* pll power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- clk_debug("pll %s enter slow mode, set rate OK!\n",
- __clk_get_name(hw->clk));
- return 0;
- }
-#endif
-
-
-#if !RK3188PLUS_USE_ARM_GPLL
- goto CHANGE_APLL;
-#endif
-
- /* prepare arm_gpll before reparent clk_core to it */
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- goto CHANGE_APLL;
- }
-
- /* In rk3188plus, arm_gpll and cpu_gpll share a same gate,
- * and aclk_cpu selects cpu_gpll as parent, thus this
- * gate must keep enabled.
- */
-#if 0
- if (clk_prepare(arm_gpll)) {
- clk_err("fail to prepare arm_gpll path\n");
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-
- if (clk_enable(arm_gpll)) {
- clk_err("fail to enable arm_gpll path\n");
- clk_disable(arm_gpll);
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-#endif
-
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk));
- temp_div = (temp_div == 0) ? 1 : temp_div;
- if (temp_div > RK3188_CORE_CLK_MAX_DIV) {
- clk_debug("temp_div %d > max_div %d\n", temp_div,
- RK3188_CORE_CLK_MAX_DIV);
- clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
- __clk_get_rate(clk), arm_gpll_rate);
- //clk_disable(arm_gpll);
- //clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-
- local_irq_save(flags);
-
- /* firstly set div, then select arm_gpll path */
- cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(temp_div),
- RK3188_CRU_CLKSELS_CON(0));
- cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_GPLL,
- RK3188_CRU_CLKSELS_CON(0));
-
- sel_gpll = 1;
- //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
- smp_wmb();
-
- local_irq_restore(flags);
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
-CHANGE_APLL:
- ps = apll_get_best_set(rate, rk3188_apll_table);
- clk_debug("apll will set rate %lu\n", ps->rate);
- clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
- ps->pllcon0, ps->pllcon1, ps->pllcon2,
- ps->clksel0, ps->clksel1);
-
- local_irq_save(flags);
-
- /* If core src don't select gpll, apll need to enter slow mode
- * before reset
- */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- /* PLL enter rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- /* return from rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- //wating lock state
- udelay(ps->rst_dly);
- pll_wait_lock(hw);
-
- old_aclk_div = RK3188_GET_CORE_ACLK_VAL(cru_readl(RK3188_CRU_CLKSELS_CON(1)) &
- RK3188_CORE_ACLK_MSK);
- new_aclk_div = RK3188_GET_CORE_ACLK_VAL(ps->clksel1 & RK3188_CORE_ACLK_MSK);
-
- if (new_aclk_div >= old_aclk_div) {
- cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
- }
-
- /* PLL return from slow mode */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- /* reparent to apll, and set div to 1 */
- if (sel_gpll) {
- cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_APLL,
- RK3188_CRU_CLKSELS_CON(0));
- cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(1),
- RK3188_CRU_CLKSELS_CON(0));
- }
-
- if (old_aclk_div > new_aclk_div) {
- cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
- }
-
- //loops_per_jiffy = ps->lpj;
- smp_wmb();
-
- local_irq_restore(flags);
-
- if (sel_gpll) {
- sel_gpll = 0;
- //clk_disable(arm_gpll);
- //clk_unprepare(arm_gpll);
- }
-
- //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
-
- clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
- ps->rate,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(RK3188_CRU_CLKSELS_CON(0)),
- cru_readl(RK3188_CRU_CLKSELS_CON(1)));
-
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_3188plus_apll = {
- .recalc_rate = clk_pll_recalc_rate_3188plus_apll,
- .round_rate = clk_pll_round_rate_3188plus_apll,
- .set_rate = clk_pll_set_rate_3188plus_apll,
-};
-
-/* CLK_PLL_3288_APLL type ops */
-static unsigned long clk_pll_recalc_rate_3288_apll(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return clk_pll_recalc_rate_3188plus(hw, parent_rate);
-}
-
-static long clk_pll_round_rate_3288_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate==__clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (apll_get_best_set(rate, rk3288_apll_table)->rate);
-}
-
-/* 1: use, 0: no use */
-#define RK3288_USE_ARM_GPLL 1
-
-static int clk_pll_set_rate_3288_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct clk *clk = hw->clk;
- struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
- unsigned long arm_gpll_rate, temp_rate, old_rate;
- const struct apll_clk_set *ps;
-// u32 old_aclk_div = 0, new_aclk_div = 0;
- u32 temp_div;
- unsigned long flags;
- int sel_gpll = 0;
-
-
-#if 0
- if (rate == parent_rate) {
- clk_debug("pll %s set rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
- /* pll power down */
- cru_writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
- clk_debug("pll %s enter slow mode, set rate OK!\n",
- __clk_get_name(hw->clk));
- return 0;
- }
-#endif
-
-#if !RK3288_USE_ARM_GPLL
- goto CHANGE_APLL;
-#endif
-
- /* prepare arm_gpll before reparent clk_core to it */
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- goto CHANGE_APLL;
- }
-
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- old_rate = __clk_get_rate(clk);
-
- temp_rate = (old_rate > rate) ? old_rate : rate;
- temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate);
-
- if (temp_div > RK3288_CORE_CLK_MAX_DIV) {
- clk_debug("temp_div %d > max_div %d\n", temp_div,
- RK3288_CORE_CLK_MAX_DIV);
- clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
- __clk_get_rate(clk), arm_gpll_rate);
- goto CHANGE_APLL;
- }
-
-#if 0
- if (clk_prepare(arm_gpll)) {
- clk_err("fail to prepare arm_gpll path\n");
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-
- if (clk_enable(arm_gpll)) {
- clk_err("fail to enable arm_gpll path\n");
- clk_disable(arm_gpll);
- clk_unprepare(arm_gpll);
- goto CHANGE_APLL;
- }
-#endif
-
- local_irq_save(flags);
-
- /* select gpll */
- if (temp_div == 1) {
- /* when old_rate/2 < (old_rate-arm_gpll_rate),
- we can set div to make rate change more gently */
- if (old_rate > (2*arm_gpll_rate)) {
- cru_writel(RK3288_CORE_CLK_DIV(2), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(3), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_GPLL,
- RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(2), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(1), RK3288_CRU_CLKSELS_CON(0));
- } else {
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_GPLL,
- RK3288_CRU_CLKSELS_CON(0));
- }
- } else {
- cru_writel(RK3288_CORE_CLK_DIV(temp_div), RK3288_CRU_CLKSELS_CON(0));
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_GPLL,
- RK3288_CRU_CLKSELS_CON(0));
- }
-
- sel_gpll = 1;
- //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
- smp_wmb();
-
- local_irq_restore(flags);
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
-CHANGE_APLL:
- ps = apll_get_best_set(rate, rk3288_apll_table);
- clk_debug("apll will set rate %lu\n", ps->rate);
- clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
- ps->pllcon0, ps->pllcon1, ps->pllcon2,
- ps->clksel0, ps->clksel1);
-
- local_irq_save(flags);
-
- /* If core src don't select gpll, apll need to enter slow mode
- * before reset
- */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
-
- /* PLL enter rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- /* return from rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- //wating lock state
- udelay(ps->rst_dly);
- pll_wait_lock(hw);
-
- if (rate >= __clk_get_rate(hw->clk)) {
- cru_writel(ps->clksel0, RK3288_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3288_CRU_CLKSELS_CON(37));
- }
-
- /* PLL return from slow mode */
- //FIXME
- //if (!sel_gpll)
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- /* reparent to apll, and set div to 1 */
- if (sel_gpll) {
- if (temp_div == 1) {
- /* when rate/2 < (rate-arm_gpll_rate),
- we can set div to make rate change more gently */
- if (rate > (2*arm_gpll_rate)) {
- cru_writel(RK3288_CORE_CLK_DIV(2), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(3), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_APLL,
- RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(2), RK3288_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3288_CORE_CLK_DIV(1), RK3288_CRU_CLKSELS_CON(0));
- } else {
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_APLL,
- RK3288_CRU_CLKSELS_CON(0));
- }
- } else {
- cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_APLL,
- RK3288_CRU_CLKSELS_CON(0));
- cru_writel(RK3288_CORE_CLK_DIV(1), RK3288_CRU_CLKSELS_CON(0));
- }
- }
-
- if (rate < __clk_get_rate(hw->clk)) {
- cru_writel(ps->clksel0, RK3288_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3288_CRU_CLKSELS_CON(37));
- }
-
- //loops_per_jiffy = ps->lpj;
- smp_wmb();
-
- local_irq_restore(flags);
-
- if (sel_gpll) {
- sel_gpll = 0;
- //clk_disable(arm_gpll);
- //clk_unprepare(arm_gpll);
- }
-
- //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
-
- clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
- ps->rate,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(RK3288_CRU_CLKSELS_CON(0)),
- cru_readl(RK3288_CRU_CLKSELS_CON(1)));
-
- return 0;
-}
-
-
-static const struct clk_ops clk_pll_ops_3288_apll = {
- .recalc_rate = clk_pll_recalc_rate_3288_apll,
- .round_rate = clk_pll_round_rate_3288_apll,
- .set_rate = clk_pll_set_rate_3288_apll,
-};
-
-/* CLK_PLL_3036_APLL type ops */
-#define FRAC_MODE 0
-static unsigned long rk3036_pll_clk_recalc(struct clk_hw *hw,
-unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- unsigned long rate;
- unsigned int dsmp = 0;
- u64 rate64 = 0, frac_rate64 = 0;
-
- dsmp = RK3036_PLL_GET_DSMPD(cru_readl(pll->reg + RK3188_PLL_CON(1)));
-
- if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
- u32 pll_con0 = cru_readl(pll->reg + RK3188_PLL_CON(0));
- u32 pll_con1 = cru_readl(pll->reg + RK3188_PLL_CON(1));
- u32 pll_con2 = cru_readl(pll->reg + RK3188_PLL_CON(2));
- /*integer mode*/
- rate64 = (u64)parent_rate * RK3036_PLL_GET_FBDIV(pll_con0);
- do_div(rate64, RK3036_PLL_GET_REFDIV(pll_con1));
-
- if (FRAC_MODE == dsmp) {
- /*fractional mode*/
- frac_rate64 = (u64)parent_rate
- * RK3036_PLL_GET_FRAC(pll_con2);
- do_div(frac_rate64, RK3036_PLL_GET_REFDIV(pll_con1));
- rate64 += frac_rate64 >> 24;
- clk_debug("%s frac_rate=%llu(%08x/2^24) by pass mode\n",
- __func__, frac_rate64 >> 24,
- RK3036_PLL_GET_FRAC(pll_con2));
- }
- do_div(rate64, RK3036_PLL_GET_POSTDIV1(pll_con0));
- do_div(rate64, RK3036_PLL_GET_POSTDIV2(pll_con1));
-
- rate = rate64;
- } else {
- rate = parent_rate;
- clk_debug("pll_clk_recalc rate=%lu by pass mode\n", rate);
- }
- return rate;
-}
-
-static unsigned long clk_pll_recalc_rate_3036_apll(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- return rk3036_pll_clk_recalc(hw, parent_rate);
-}
-
-static long clk_pll_round_rate_3036_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate == __clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (apll_get_best_set(rate, rk3036_apll_table)->rate);
-}
-
-static int rk3036_pll_clk_set_rate(struct pll_clk_set *clk_set,
- struct clk_hw *hw)
-{
- struct clk_pll *pll = to_clk_pll(hw);
-
- /*enter slowmode*/
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
-
- cru_writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- clk_debug("pllcon0%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(0)));
- clk_debug("pllcon1%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(1)));
- clk_debug("pllcon2%08x\n", cru_readl(pll->reg + RK3188_PLL_CON(2)));
- /*wating lock state*/
- udelay(clk_set->rst_dly);
- rk3036_pll_wait_lock(hw);
-
- /*return form slow*/
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift),
- pll->mode_offset);
-
- return 0;
-}
-
-#define MIN_FOUTVCO_FREQ (400 * 1000 * 1000)
-#define MAX_FOUTVCO_FREQ (1600 * 1000 * 1000)
-static int rk3036_pll_clk_set_postdiv(unsigned long fout_hz,
-u32 *postdiv1, u32 *postdiv2, u32 *foutvco)
-{
- if (fout_hz < MIN_FOUTVCO_FREQ) {
- for (*postdiv1 = 1; *postdiv1 <= 7; (*postdiv1)++)
- for (*postdiv2 = 1; *postdiv2 <= 7; (*postdiv2)++) {
- if (fout_hz * (*postdiv1) * (*postdiv2)
- >= MIN_FOUTVCO_FREQ && fout_hz
- * (*postdiv1) * (*postdiv2)
- <= MAX_FOUTVCO_FREQ) {
- *foutvco = fout_hz * (*postdiv1)
- * (*postdiv2);
- return 0;
- }
- }
- clk_debug("CANNOT FINE postdiv1/2 to make fout in range from 400M to 1600M, fout = %lu\n",
- fout_hz);
- } else {
- *postdiv1 = 1;
- *postdiv2 = 1;
- }
- return 0;
-}
-
-static int rk3036_pll_clk_get_set(unsigned long fin_hz, unsigned long fout_hz,
- u32 *refdiv, u32 *fbdiv, u32 *postdiv1,
- u32 *postdiv2, u32 *frac)
-{
- /* FIXME set postdiv1/2 always 1*/
- u32 gcd, foutvco = fout_hz;
- u64 fin_64, frac_64;
- u32 f_frac;
-
- if (!fin_hz || !fout_hz || fout_hz == fin_hz)
- return -1;
-
- rk3036_pll_clk_set_postdiv(fout_hz, postdiv1, postdiv2, &foutvco);
- if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) {
- fin_hz /= MHZ;
- foutvco /= MHZ;
- gcd = clk_gcd(fin_hz, foutvco);
- *refdiv = fin_hz / gcd;
- *fbdiv = foutvco / gcd;
-
- *frac = 0;
-
- clk_debug("fin=%lu,fout=%lu,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n",
- fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac);
- } else {
- clk_debug("******frac div running, fin_hz=%lu, fout_hz=%lu,fin_INT_mhz=%lu, fout_INT_mhz=%lu\n",
- fin_hz, fout_hz, fin_hz / MHZ * MHZ, fout_hz / MHZ * MHZ);
- clk_debug("******frac get postdiv1=%u, postdiv2=%u,foutvco=%u\n",
- *postdiv1, *postdiv2, foutvco);
- gcd = clk_gcd(fin_hz / MHZ, foutvco / MHZ);
- *refdiv = fin_hz / MHZ / gcd;
- *fbdiv = foutvco / MHZ / gcd;
- clk_debug("******frac get refdiv=%u, fbdiv=%u\n", *refdiv, *fbdiv);
-
- *frac = 0;
-
- f_frac = (foutvco % MHZ);
- fin_64 = fin_hz;
- do_div(fin_64, (u64)*refdiv);
- frac_64 = (u64)f_frac << 24;
- do_div(frac_64, fin_64);
- *frac = (u32) frac_64;
- clk_debug("frac=%x\n", *frac);
- }
- return 0;
-}
-static int rk3036_pll_set_con(struct clk_hw *hw, u32 refdiv, u32 fbdiv, u32 postdiv1, u32 postdiv2, u32 frac)
-{
- struct pll_clk_set temp_clk_set;
- temp_clk_set.pllcon0 = RK3036_PLL_SET_FBDIV(fbdiv) | RK3036_PLL_SET_POSTDIV1(postdiv1);
- temp_clk_set.pllcon1 = RK3036_PLL_SET_REFDIV(refdiv) | RK3036_PLL_SET_POSTDIV2(postdiv2);
- if (frac != 0)
- temp_clk_set.pllcon1 |= RK3036_PLL_SET_DSMPD(0);
- else
- temp_clk_set.pllcon1 |= RK3036_PLL_SET_DSMPD(1);
-
- temp_clk_set.pllcon2 = RK3036_PLL_SET_FRAC(frac);
- temp_clk_set.rst_dly = 0;
- clk_debug("setting....\n");
- return rk3036_pll_clk_set_rate(&temp_clk_set, hw);
-}
-
-static int clk_pll_set_rate_3036_apll(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct apll_clk_set *ps = (struct apll_clk_set *)(rk3036_apll_table);
- struct clk *arm_gpll = __clk_lookup("clk_gpll");
- struct clk *clk = hw->clk;
- unsigned long flags, arm_gpll_rate, old_rate, temp_rate;
- u32 temp_div;
-
- while (ps->rate) {
- if (ps->rate == rate) {
- break;
- }
- ps++;
- }
-
- if (ps->rate != rate) {
- clk_err("%s: unsupport arm rate %lu\n", __func__, rate);
- return 0;
- }
-
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- return 0;
- }
-
- old_rate = __clk_get_rate(clk);
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- if (soc_is_rk3128() || soc_is_rk3126())
- arm_gpll_rate /= 2;
-
- temp_rate = (old_rate > rate) ? old_rate : rate;
- temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate);
-
- local_irq_save(flags);
-
- if (rate >= old_rate) {
- cru_writel(ps->clksel0, RK3036_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3036_CRU_CLKSELS_CON(1));
- }
-
- /* set div first, then select gpll */
- if (temp_div > 1)
- cru_writel(RK3036_CLK_CORE_DIV(temp_div), RK3036_CRU_CLKSELS_CON(0));
- cru_writel(RK3036_CORE_SEL_PLL(1), RK3036_CRU_CLKSELS_CON(0));
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
- /**************enter slow mode 24M***********/
- /*cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);*/
- loops_per_jiffy = LPJ_24M;
-
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- clk_debug("pllcon0 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(0)));
- clk_debug("pllcon1 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(1)));
- clk_debug("pllcon2 %08x\n", cru_readl(pll->reg + RK3188_PLL_CON(2)));
- clk_debug("clksel0 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(0)));
- clk_debug("clksel1 %08x\n", cru_readl(RK3036_CRU_CLKSELS_CON(1)));
-
- /*wating lock state*/
- udelay(ps->rst_dly);
- rk3036_pll_wait_lock(hw);
-
- /************select apll******************/
- cru_writel(RK3036_CORE_SEL_PLL(0), RK3036_CRU_CLKSELS_CON(0));
- /**************return slow mode***********/
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
-
- cru_writel(RK3036_CLK_CORE_DIV(1), RK3036_CRU_CLKSELS_CON(0));
-
- if (rate < old_rate) {
- cru_writel(ps->clksel0, RK3036_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3036_CRU_CLKSELS_CON(1));
- }
-
- loops_per_jiffy = ps->lpj;
- local_irq_restore(flags);
-
- return 0;
-}
-static const struct clk_ops clk_pll_ops_3036_apll = {
- .recalc_rate = clk_pll_recalc_rate_3036_apll,
- .round_rate = clk_pll_round_rate_3036_apll,
- .set_rate = clk_pll_set_rate_3036_apll,
-};
-
-
-/* CLK_PLL_3036_plus_autotype ops */
-
-static long clk_pll_round_rate_3036plus_auto(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate == __clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (pll_com_get_best_set(rate, rk3036plus_pll_com_table)->rate);
-}
-
-static int clk_pll_set_rate_3036plus_auto(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk3036plus_pll_com_table);
-
- clk_debug("******%s\n", __func__);
- while (clk_set->rate) {
- clk_debug("******%s clk_set->rate=%lu\n", __func__, clk_set->rate);
- if (clk_set->rate == rate) {
- break;
- }
- clk_set++;
- }
- if (clk_set->rate == rate) {
- rk3036_pll_clk_set_rate(clk_set, hw);
- } else {
- clk_debug("gpll is no corresponding rate=%lu\n", rate);
- return -1;
- }
- clk_debug("******%s end\n", __func__);
-
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_3036plus_auto = {
- .recalc_rate = clk_pll_recalc_rate_3036_apll,
- .round_rate = clk_pll_round_rate_3036plus_auto,
- .set_rate = clk_pll_set_rate_3036plus_auto,
-};
-
-static long clk_cpll_round_rate_312xplus(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- unsigned long best;
-
- for (best = rate; best > 0; best--) {
- if (!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL))
- return best;
- }
-
- return 0;
-}
-
-static int clk_cpll_set_rate_312xplus(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct pll_clk_set *clk_set = (struct pll_clk_set *)(rk312xplus_pll_com_table);
- u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
-
- while (clk_set->rate) {
- if (clk_set->rate == rate) {
- break;
- }
- clk_set++;
- }
-
- if (clk_set->rate == rate) {
- clk_debug("cpll get a rate %ld\n", rate);
- rk3036_pll_clk_set_rate(clk_set, hw);
-
- } else {
- clk_debug("cpll get auto calc a rate\n");
- if (rk3036_pll_clk_get_set(parent_rate, rate, &refdiv, &fbdiv, &postdiv1, &postdiv2, &frac) != 0) {
- pr_err("cpll auto set rate error\n");
- return -ENOENT;
- }
- clk_debug("%s get rate=%lu, refdiv=%u, fbdiv=%u, postdiv1=%u, postdiv2=%u",
- __func__, rate, refdiv, fbdiv, postdiv1, postdiv2);
- rk3036_pll_set_con(hw, refdiv, fbdiv, postdiv1, postdiv2, frac);
-
- }
-
- clk_debug("setting OK\n");
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_312xplus = {
- .recalc_rate = clk_pll_recalc_rate_3036_apll,
- .round_rate = clk_cpll_round_rate_312xplus,
- .set_rate = clk_cpll_set_rate_312xplus,
-};
-
-static long clk_pll_round_rate_3368_apllb(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate == __clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (apll_get_best_set(rate, rk3368_apllb_table)->rate);
-}
-
-/* 1: use, 0: no use */
-#define RK3368_APLLB_USE_GPLL 1
-
-/* when define 1, we will set div to make rate change gently, but it will cost
- more time */
-#define RK3368_APLLB_DIV_MORE 1
-
-static int clk_pll_set_rate_3368_apllb(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct clk *clk = hw->clk;
- struct clk *arm_gpll = __clk_lookup("clk_gpll");
- unsigned long arm_gpll_rate, temp_rate, old_rate;
- const struct apll_clk_set *ps;
- u32 temp_div;
- unsigned long flags;
- int sel_gpll = 0;
-
- ps = apll_get_best_set(rate, rk3368_apllb_table);
- clk_debug("apllb will set rate %lu\n", ps->rate);
- clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
- ps->pllcon0, ps->pllcon1, ps->pllcon2,
- ps->clksel0, ps->clksel1);
-
-#if !RK3368_APLLB_USE_GPLL
- goto CHANGE_APLL;
-#endif
-
- /* prepare arm_gpll before reparent clk_core to it */
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- goto CHANGE_APLL;
- }
-
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- old_rate = __clk_get_rate(clk);
-
- temp_rate = (old_rate > rate) ? old_rate : rate;
- temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate);
-
- if (temp_div > RK3368_CORE_CLK_MAX_DIV) {
- clk_debug("temp_div %d > max_div %d\n", temp_div,
- RK3368_CORE_CLK_MAX_DIV);
- clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
- __clk_get_rate(clk), arm_gpll_rate);
- goto CHANGE_APLL;
- }
-
- local_irq_save(flags);
-
- if (rate >= old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(1));
- }
-
- /* select gpll */
-#if RK3368_APLLB_DIV_MORE
- if (temp_div == 1) {
- /* when old_rate/2 < (old_rate-arm_gpll_rate),
- we can set div to make rate change more gently */
- if (old_rate > (2*arm_gpll_rate)) {
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0));
- } else {
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(0));
- }
- } else {
- cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(0));
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(0));
- }
-#else
- cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(0));
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(0));
-#endif
-
- sel_gpll = 1;
-
- smp_wmb();
-
- local_irq_restore(flags);
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
-CHANGE_APLL:
- local_irq_save(flags);
-
- /* apll enter slow mode */
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
-
- /* PLL enter reset */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- /* return from rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- /* wating lock state */
- udelay(ps->rst_dly);
- pll_wait_lock(hw);
-
- if (!sel_gpll) {
- if (rate >= old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(1));
- }
- }
-
- /* apll return from slow mode */
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift),
- pll->mode_offset);
-
- /* reparent to apll, and set div to 1 */
- if (sel_gpll) {
-#if RK3368_APLLB_DIV_MORE
- /* when rate/2 < (rate-arm_gpll_rate), we can set div to make
- rate change more gently */
- if ((temp_div == 1) && (rate > (2*arm_gpll_rate))) {
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(0));
- udelay(10);
- } else
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(0));
-#else
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(0));
-#endif
- }
-
- cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(0));
-
- if (rate < old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(0));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(1));
- }
-
- smp_wmb();
-
- local_irq_restore(flags);
-
- if (sel_gpll)
- sel_gpll = 0;
-
- clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
- ps->rate,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(RK3368_CRU_CLKSELS_CON(0)),
- cru_readl(RK3368_CRU_CLKSELS_CON(1)));
-
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_3368_apllb = {
- .recalc_rate = clk_pll_recalc_rate_3188plus,
- .round_rate = clk_pll_round_rate_3368_apllb,
- .set_rate = clk_pll_set_rate_3368_apllb,
-};
-
-static long clk_pll_round_rate_3368_aplll(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- struct clk *parent = __clk_get_parent(hw->clk);
-
- if (parent && (rate == __clk_get_rate(parent))) {
- clk_debug("pll %s round rate=%lu equal to parent rate\n",
- __clk_get_name(hw->clk), rate);
- return rate;
- }
-
- return (apll_get_best_set(rate, rk3368_aplll_table)->rate);
-}
-
-/* 1: use, 0: no use */
-#define RK3368_APLLL_USE_GPLL 1
-
-/* when define 1, we will set div to make rate change gently, but it will cost
- more time */
-#define RK3368_APLLL_DIV_MORE 1
-
-static int clk_pll_set_rate_3368_aplll(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_pll *pll = to_clk_pll(hw);
- struct clk *clk = hw->clk;
- struct clk *arm_gpll = __clk_lookup("clk_gpll");
- unsigned long arm_gpll_rate, temp_rate, old_rate;
- const struct apll_clk_set *ps;
- u32 temp_div;
- unsigned long flags;
- int sel_gpll = 0;
-
- ps = apll_get_best_set(rate, rk3368_aplll_table);
- clk_debug("aplll will set rate %lu\n", ps->rate);
- clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
- ps->pllcon0, ps->pllcon1, ps->pllcon2,
- ps->clksel0, ps->clksel1);
-
-#if !RK3368_APLLL_USE_GPLL
- goto CHANGE_APLL;
-#endif
-
- /* prepare arm_gpll before reparent clk_core to it */
- if (!arm_gpll) {
- clk_err("clk arm_gpll is NULL!\n");
- goto CHANGE_APLL;
- }
-
- arm_gpll_rate = __clk_get_rate(arm_gpll);
- old_rate = __clk_get_rate(clk);
-
- temp_rate = (old_rate > rate) ? old_rate : rate;
- temp_div = DIV_ROUND_UP(arm_gpll_rate, temp_rate);
-
- if (temp_div > RK3368_CORE_CLK_MAX_DIV) {
- clk_debug("temp_div %d > max_div %d\n", temp_div,
- RK3368_CORE_CLK_MAX_DIV);
- clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
- __clk_get_rate(clk), arm_gpll_rate);
- goto CHANGE_APLL;
- }
-
- local_irq_save(flags);
-
- if (rate >= old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(2));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(3));
- }
-
- /* select gpll */
-#if RK3368_APLLL_DIV_MORE
- if (temp_div == 1) {
- /* when old_rate/2 < (old_rate-arm_gpll_rate),
- we can set div to make rate change more gently */
- if (old_rate > (2*arm_gpll_rate)) {
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2));
- } else {
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(2));
- }
- } else {
- cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(2));
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(2));
- }
-#else
- cru_writel(RK3368_CORE_CLK_DIV(temp_div), RK3368_CRU_CLKSELS_CON(2));
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_GPLL,
- RK3368_CRU_CLKSELS_CON(2));
-#endif
-
- sel_gpll = 1;
-
- smp_wmb();
-
- local_irq_restore(flags);
-
- clk_debug("temp select arm_gpll path, get rate %lu\n",
- arm_gpll_rate/temp_div);
- clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
- temp_div);
-
-CHANGE_APLL:
- local_irq_save(flags);
-
- /* apll enter slow mode */
- cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
- pll->mode_offset);
-
- /* PLL enter reset */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
-
- cru_writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
- cru_writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
- cru_writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
-
- udelay(5);
-
- /* return from rest */
- cru_writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
-
- /* wating lock state */
- udelay(ps->rst_dly);
- pll_wait_lock(hw);
-
- if (!sel_gpll) {
- if (rate >= old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(2));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(3));
- }
- }
-
- /* apll return from slow mode */
- cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift),
- pll->mode_offset);
-
- /* reparent to apll, and set div to 1 */
- if (sel_gpll) {
-#if RK3368_APLLL_DIV_MORE
- /* when rate/2 < (rate-arm_gpll_rate), we can set div to make
- rate change more gently */
- if ((temp_div == 1) && (rate > (2*arm_gpll_rate))) {
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(3), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- cru_writel(RK3368_CORE_CLK_DIV(2), RK3368_CRU_CLKSELS_CON(2));
- udelay(10);
- } else
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(2));
-#else
- cru_writel(RK3368_CORE_SEL_PLL_W_MSK|RK3368_CORE_SEL_APLL,
- RK3368_CRU_CLKSELS_CON(2));
-#endif
- }
-
- cru_writel(RK3368_CORE_CLK_DIV(1), RK3368_CRU_CLKSELS_CON(2));
-
- if (rate < old_rate) {
- cru_writel(ps->clksel0, RK3368_CRU_CLKSELS_CON(2));
- cru_writel(ps->clksel1, RK3368_CRU_CLKSELS_CON(3));
- }
-
- smp_wmb();
-
- local_irq_restore(flags);
-
- if (sel_gpll)
- sel_gpll = 0;
-
- clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
- ps->rate,
- cru_readl(pll->reg + RK3188_PLL_CON(0)),
- cru_readl(pll->reg + RK3188_PLL_CON(1)),
- cru_readl(pll->reg + RK3188_PLL_CON(2)),
- cru_readl(pll->reg + RK3188_PLL_CON(3)),
- cru_readl(RK3368_CRU_CLKSELS_CON(2)),
- cru_readl(RK3368_CRU_CLKSELS_CON(3)));
-
- return 0;
-}
-
-static const struct clk_ops clk_pll_ops_3368_aplll = {
- .recalc_rate = clk_pll_recalc_rate_3188plus,
- .round_rate = clk_pll_round_rate_3368_aplll,
- .set_rate = clk_pll_set_rate_3368_aplll,
-};
-
-const struct clk_ops *rk_get_pll_ops(u32 pll_flags)
-{
- switch (pll_flags) {
- case CLK_PLL_3188:
- return &clk_pll_ops_3188;
-
- case CLK_PLL_3188_APLL:
- return &clk_pll_ops_3188_apll;
-
- case CLK_PLL_3188PLUS:
- return &clk_pll_ops_3188plus;
-
- case CLK_PLL_3188PLUS_APLL:
- return &clk_pll_ops_3188plus_apll;
-
- case CLK_PLL_3288_APLL:
- return &clk_pll_ops_3288_apll;
-
- case CLK_PLL_3188PLUS_AUTO:
- return &clk_pll_ops_3188plus_auto;
-
- case CLK_PLL_3036_APLL:
- return &clk_pll_ops_3036_apll;
-
- case CLK_PLL_3036PLUS_AUTO:
- return &clk_pll_ops_3036plus_auto;
-
- case CLK_PLL_312XPLUS:
- return &clk_pll_ops_312xplus;
-
- case CLK_PLL_3368_APLLB:
- return &clk_pll_ops_3368_apllb;
-
- case CLK_PLL_3368_APLLL:
- return &clk_pll_ops_3368_aplll;
-
- case CLK_PLL_3368_LOW_JITTER:
- return &clk_pll_ops_3368_low_jitter;
-
- default:
- clk_err("%s: unknown pll_flags!\n", __func__);
- return NULL;
- }
-}
-
-struct clk *rk_clk_register_pll(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags, u32 reg,
- u32 width, u32 mode_offset, u8 mode_shift,
- u32 status_offset, u8 status_shift, u32 pll_flags,
- spinlock_t *lock)
-{
- struct clk_pll *pll;
- struct clk *clk;
- struct clk_init_data init;
-
-
- clk_debug("%s: pll name = %s, pll_flags = 0x%x, register start!\n",
- __func__, name, pll_flags);
-
- /* allocate the pll */
- pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
- if (!pll) {
- clk_err("%s: could not allocate pll clk\n", __func__);
- return ERR_PTR(-ENOMEM);
- }
-
- init.name = name;
- init.flags = flags;
- init.parent_names = (parent_name ? &parent_name: NULL);
- init.num_parents = (parent_name ? 1 : 0);
- init.ops = rk_get_pll_ops(pll_flags);
-
- /* struct clk_pll assignments */
- pll->reg = reg;
- pll->width = width;
- pll->mode_offset = mode_offset;
- pll->mode_shift = mode_shift;
- pll->status_offset = status_offset;
- pll->status_shift = status_shift;
- pll->flags = pll_flags;
- pll->lock = lock;
- pll->hw.init = &init;
-
- /* register the clock */
- clk = clk_register(dev, &pll->hw);
-
- if (IS_ERR(clk))
- kfree(pll);
-
- clk_debug("%s: pll name = %s, pll_flags = 0x%x, register finish!\n",
- __func__, name, pll_flags);
-
- return clk;
-}
-
+++ /dev/null
-#ifndef __RK_CLK_PLL_H
-#define __RK_CLK_PLL_H
-
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/rockchip/cru.h>
-
-
-#define CLK_LOOPS_JIFFY_REF (11996091ULL)
-#define CLK_LOOPS_RATE_REF (1200UL) //Mhz
-#define CLK_LOOPS_RECALC(rate) \
- div_u64(CLK_LOOPS_JIFFY_REF*(rate),CLK_LOOPS_RATE_REF*MHZ)
-
-#define CLK_DIV_PLUS_ONE_SET(i, shift, width) \
- ((((i)-1) << (shift)) | (((2<<(width)) - 1) << ((shift)+16)))
-
-/*******************RK3188 PLL******************************/
-#define RK3188_PLL_CON(i) ((i) * 4)
-/*******************PLL WORK MODE*************************/
-#define _RK3188_PLL_MODE_MSK 0x3
-#define _RK3188_PLL_MODE_SLOW 0x0
-#define _RK3188_PLL_MODE_NORM 0x1
-#define _RK3188_PLL_MODE_DEEP 0x2
-
-#define _RK3188_PLL_MODE_GET(offset, shift) \
- ((cru_readl(offset) >> (shift)) & _RK3188_PLL_MODE_MSK)
-
-#define _RK3188_PLL_MODE_IS_SLOW(offset, shift) \
- (_RK3188_PLL_MODE_GET(offset, shift) == _RK3188_PLL_MODE_SLOW)
-
-#define _RK3188_PLL_MODE_IS_NORM(offset, shift) \
- (_RK3188_PLL_MODE_GET(offset, shift) == _RK3188_PLL_MODE_NORM)
-
-#define _RK3188_PLL_MODE_IS_DEEP(offset, shift) \
- (_RK3188_PLL_MODE_GET(offset, shift) == _RK3188_PLL_MODE_DEEP)
-
-#define _RK3188_PLL_MODE_SET(val, shift) \
- ((val) << (shift)) | CRU_W_MSK(shift, _RK3188_PLL_MODE_MSK)
-
-#define _RK3188_PLL_MODE_SLOW_SET(shift) \
- _RK3188_PLL_MODE_SET(_RK3188_PLL_MODE_SLOW, shift)
-
-#define _RK3188_PLL_MODE_NORM_SET(shift) \
- _RK3188_PLL_MODE_SET(_RK3188_PLL_MODE_NORM, shift)
-
-#define _RK3188_PLL_MODE_DEEP_SET(shift) \
- _RK3188_PLL_MODE_SET(_RK3188_PLL_MODE_DEEP, shift)
-
-/*******************PLL OPERATION MODE*********************/
-#define _RK3188_PLL_BYPASS_SHIFT 0
-#define _RK3188_PLL_POWERDOWN_SHIFT 1
-
-#define _RK3188PLUS_PLL_BYPASS_SHIFT 0
-#define _RK3188PLUS_PLL_POWERDOWN_SHIFT 1
-#define _RK3188PLUS_PLL_RESET_SHIFT 5
-
-#define _RK3188_PLL_OP_SET(val, shift) \
- ((val) << (shift)) | CRU_W_MSK(shift, 1)
-
-#define _RK3188_PLL_BYPASS_SET(val) \
- _RK3188_PLL_OP_SET(val, _RK3188_PLL_BYPASS_SHIFT)
-
-#define _RK3188_PLL_POWERDOWN_SET(val) \
- _RK3188_PLL_OP_SET(val, _RK3188_PLL_POWERDOWN_SHIFT)
-
-#define _RK3188PLUS_PLL_BYPASS_SET(val) \
- _RK3188_PLL_OP_SET(val, _RK3188PLUS_PLL_BYPASS_SHIFT)
-
-#define _RK3188PLUS_PLL_POWERDOWN_SET(val) \
- _RK3188_PLL_OP_SET(val, _RK3188PLUS_PLL_POWERDOWN_SHIFT)
-
-#define _RK3188PLUS_PLL_RESET_SET(val) \
- _RK3188_PLL_OP_SET(val, _RK3188PLUS_PLL_RESET_SHIFT)
-
-/*******************PLL CON0 BITS***************************/
-#define RK3188_PLL_CLKFACTOR_SET(val, shift, msk) \
- ((((val) - 1) & (msk)) << (shift))
-
-#define RK3188_PLL_CLKFACTOR_GET(reg, shift, msk) \
- ((((reg) >> (shift)) & (msk)) + 1)
-
-#define RK3188_PLL_OD_MSK (0x3f)
-#define RK3188_PLL_OD_SHIFT (0x0)
-#define RK3188_PLL_CLKOD(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188_PLL_OD_SHIFT, RK3188_PLL_OD_MSK)
-#define RK3188_PLL_NO(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188_PLL_OD_SHIFT, RK3188_PLL_OD_MSK)
-#define RK3188_PLL_CLKOD_SET(val) (RK3188_PLL_CLKOD(val) | CRU_W_MSK(RK3188_PLL_OD_SHIFT, RK3188_PLL_OD_MSK))
-
-#define RK3188_PLL_NR_MSK (0x3f)
-#define RK3188_PLL_NR_SHIFT (8)
-#define RK3188_PLL_CLKR(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188_PLL_NR_SHIFT, RK3188_PLL_NR_MSK)
-#define RK3188_PLL_NR(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188_PLL_NR_SHIFT, RK3188_PLL_NR_MSK)
-#define RK3188_PLL_CLKR_SET(val) (RK3188_PLL_CLKR(val) | CRU_W_MSK(RK3188_PLL_NR_SHIFT, RK3188_PLL_NR_MSK))
-
-#define RK3188PLUS_PLL_OD_MSK (0xf)
-#define RK3188PLUS_PLL_OD_SHIFT (0x0)
-#define RK3188PLUS_PLL_CLKOD(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188PLUS_PLL_OD_SHIFT, RK3188PLUS_PLL_OD_MSK)
-#define RK3188PLUS_PLL_NO(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188PLUS_PLL_OD_SHIFT, RK3188PLUS_PLL_OD_MSK)
-#define RK3188PLUS_PLL_CLKOD_SET(val) (RK3188PLUS_PLL_CLKOD(val) | CRU_W_MSK(RK3188PLUS_PLL_OD_SHIFT, RK3188PLUS_PLL_OD_MSK))
-
-#define RK3188PLUS_PLL_NR_MSK (0x3f)
-#define RK3188PLUS_PLL_NR_SHIFT (8)
-#define RK3188PLUS_PLL_CLKR(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188PLUS_PLL_NR_SHIFT, RK3188PLUS_PLL_NR_MSK)
-#define RK3188PLUS_PLL_NR(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188PLUS_PLL_NR_SHIFT, RK3188PLUS_PLL_NR_MSK)
-#define RK3188PLUS_PLL_CLKR_SET(val) (RK3188PLUS_PLL_CLKR(val) | CRU_W_MSK(RK3188PLUS_PLL_NR_SHIFT, RK3188PLUS_PLL_NR_MSK))
-
-/*******************PLL CON1 BITS***************************/
-#define RK3188_PLL_NF_MSK (0xffff)
-#define RK3188_PLL_NF_SHIFT (0)
-#define RK3188_PLL_CLKF(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188_PLL_NF_SHIFT, RK3188_PLL_NF_MSK)
-#define RK3188_PLL_NF(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188_PLL_NF_SHIFT, RK3188_PLL_NF_MSK)
-#define RK3188_PLL_CLKF_SET(val) (RK3188_PLL_CLKF(val) | CRU_W_MSK(RK3188_PLL_NF_SHIFT, RK3188_PLL_NF_MSK))
-
-#define RK3188PLUS_PLL_NF_MSK (0x1fff)
-#define RK3188PLUS_PLL_NF_SHIFT (0)
-#define RK3188PLUS_PLL_CLKF(val) RK3188_PLL_CLKFACTOR_SET(val, RK3188PLUS_PLL_NF_SHIFT, RK3188PLUS_PLL_NF_MSK)
-#define RK3188PLUS_PLL_NF(reg) RK3188_PLL_CLKFACTOR_GET(reg, RK3188PLUS_PLL_NF_SHIFT, RK3188PLUS_PLL_NF_MSK)
-#define RK3188PLUS_PLL_CLKF_SET(val) (RK3188PLUS_PLL_CLKF(val) | CRU_W_MSK(RK3188PLUS_PLL_NF_SHIFT, RK3188PLUS_PLL_NF_MSK))
-
-/*******************PLL CON2 BITS***************************/
-#define RK3188_PLL_BWADJ_MSK (0xfff)
-#define RK3188_PLL_BWADJ_SHIFT (0)
-#define RK3188_PLL_CLK_BWADJ_SET(val) ((val) | CRU_W_MSK(RK3188_PLL_BWADJ_SHIFT, RK3188_PLL_BWADJ_MSK))
-
-#define RK3188PLUS_PLL_BWADJ_MSK (0xfff)
-#define RK3188PLUS_PLL_BWADJ_SHIFT (0)
-#define RK3188PLUS_PLL_CLK_BWADJ_SET(val) ((val) | CRU_W_MSK(RK3188PLUS_PLL_BWADJ_SHIFT, RK3188PLUS_PLL_BWADJ_MSK))
-
-/*******************PLL CON3 BITS***************************/
-#define RK3188_PLL_RESET_MSK (1 << 5)
-#define RK3188_PLL_RESET_W_MSK (RK3188_PLL_RESET_MSK << 16)
-#define RK3188_PLL_RESET (1 << 5)
-#define RK3188_PLL_RESET_RESUME (0 << 5)
-
-#define RK3188_PLL_BYPASS_MSK (1 << 0)
-#define RK3188_PLL_BYPASS (1 << 0)
-#define RK3188_PLL_NO_BYPASS (0 << 0)
-
-#define RK3188_PLL_PWR_DN_MSK (1 << 1)
-#define RK3188_PLL_PWR_DN_W_MSK (RK3188_PLL_PWR_DN_MSK << 16)
-#define RK3188_PLL_PWR_DN (1 << 1)
-#define RK3188_PLL_PWR_ON (0 << 1)
-
-#define RK3188_PLL_STANDBY_MSK (1 << 2)
-#define RK3188_PLL_STANDBY (1 << 2)
-#define RK3188_PLL_NO_STANDBY (0 << 2)
-
-/*******************CLKSEL0 BITS***************************/
-//core_preiph div
-#define RK3188_CORE_PERIPH_W_MSK (3 << 22)
-#define RK3188_CORE_PERIPH_MSK (3 << 6)
-#define RK3188_CORE_PERIPH_2 (0 << 6)
-#define RK3188_CORE_PERIPH_4 (1 << 6)
-#define RK3188_CORE_PERIPH_8 (2 << 6)
-#define RK3188_CORE_PERIPH_16 (3 << 6)
-
-//clk_core
-#define RK3188_CORE_SEL_PLL_MSK (1 << 8)
-#define RK3188_CORE_SEL_PLL_W_MSK (1 << 24)
-#define RK3188_CORE_SEL_APLL (0 << 8)
-#define RK3188_CORE_SEL_GPLL (1 << 8)
-
-#define RK3188_CORE_CLK_DIV_W_MSK (0x1F << 25)
-#define RK3188_CORE_CLK_DIV_MSK (0x1F << 9)
-#define RK3188_CORE_CLK_DIV(i) ((((i) - 1) & 0x1F) << 9)
-#define RK3188_CORE_CLK_MAX_DIV 32
-
-/*******************CLKSEL1 BITS***************************/
-//aclk_core div
-#define RK3188_CORE_ACLK_W_MSK (7 << 19)
-#define RK3188_CORE_ACLK_MSK (7 << 3)
-#define RK3188_CORE_ACLK_11 (0 << 3)
-#define RK3188_CORE_ACLK_21 (1 << 3)
-#define RK3188_CORE_ACLK_31 (2 << 3)
-#define RK3188_CORE_ACLK_41 (3 << 3)
-#define RK3188_CORE_ACLK_81 (4 << 3)
-#define RK3188_GET_CORE_ACLK_VAL(reg) ((reg)>=4 ? 8:((reg)+1))
-
-/*******************PLL SET*********************************/
-#define _RK3188_PLL_SET_CLKS(_mhz, nr, nf, no) \
-{ \
- .rate = (_mhz) * KHZ, \
- .pllcon0 = RK3188_PLL_CLKR_SET(nr)|RK3188_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188_PLL_CLK_BWADJ_SET(nf >> 1),\
- .rst_dly = ((nr*500)/24+1),\
-}
-
-#define _RK3188PLUS_PLL_SET_CLKS(_mhz, nr, nf, no) \
-{ \
- .rate = (_mhz) * KHZ, \
- .pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1),\
- .rst_dly = ((nr*500)/24+1),\
-}
-
-#define _RK3188PLUS_PLL_SET_CLKS_NB(_mhz, nr, nf, no, nb) \
-{ \
- .rate = (_mhz) * KHZ, \
- .pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nb-1),\
- .rst_dly = ((nr*500)/24+1),\
-}
-
-#define _RK3188_APLL_SET_CLKS(_mhz, nr, nf, no, _periph_div, _aclk_div) \
-{ \
- .rate = _mhz * MHZ, \
- .pllcon0 = RK3188_PLL_CLKR_SET(nr) | RK3188_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188_PLL_CLK_BWADJ_SET(nf >> 1),\
- .rst_dly = ((nr*500)/24+1),\
- .clksel0 = RK3188_CORE_PERIPH_W_MSK | RK3188_CORE_PERIPH_##_periph_div,\
- .clksel1 = RK3188_CORE_ACLK_W_MSK | RK3188_CORE_ACLK_##_aclk_div,\
- .lpj = (CLK_LOOPS_JIFFY_REF*_mhz) / CLK_LOOPS_RATE_REF,\
-}
-
-
-/*******************RK3288 PLL***********************************/
-/*******************CLKSEL0 BITS***************************/
-#define RK3288_CORE_SEL_PLL_W_MSK (1 << 31)
-#define RK3288_CORE_SEL_APLL (0 << 15)
-#define RK3288_CORE_SEL_GPLL (1 << 15)
-
-#define RK3288_CORE_CLK_SHIFT 8
-#define RK3288_CORE_CLK_WIDTH 5
-#define RK3288_CORE_CLK_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_CORE_CLK_SHIFT, RK3288_CORE_CLK_WIDTH)
-#define RK3288_CORE_CLK_MAX_DIV (2<<RK3288_CORE_CLK_WIDTH)
-
-#define RK3288_ACLK_M0_SHIFT 0
-#define RK3288_ACLK_M0_WIDTH 4
-#define RK3288_ACLK_M0_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_ACLK_M0_SHIFT, RK3288_ACLK_M0_WIDTH)
-
-#define RK3288_ACLK_MP_SHIFT 4
-#define RK3288_ACLK_MP_WIDTH 4
-#define RK3288_ACLK_MP_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_ACLK_MP_SHIFT, RK3288_ACLK_MP_WIDTH)
-
-/*******************CLKSEL37 BITS***************************/
-#define RK3288_CLK_L2RAM_SHIFT 0
-#define RK3288_CLK_L2RAM_WIDTH 3
-#define RK3288_CLK_L2RAM_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_CLK_L2RAM_SHIFT, RK3288_CLK_L2RAM_WIDTH)
-
-#define RK3288_ATCLK_SHIFT 4
-#define RK3288_ATCLK_WIDTH 5
-#define RK3288_ATCLK_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_ATCLK_SHIFT, RK3288_ATCLK_WIDTH)
-
-#define RK3288_PCLK_DBG_SHIFT 9
-#define RK3288_PCLK_DBG_WIDTH 5
-#define RK3288_PCLK_DBG_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3288_PCLK_DBG_SHIFT, RK3288_PCLK_DBG_WIDTH)
-
-#define _RK3288_APLL_SET_CLKS(_mhz, nr, nf, no, l2_div, m0_div, mp_div, atclk_div, pclk_dbg_div) \
-{ \
- .rate = _mhz * MHZ, \
- .pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr) | RK3188PLUS_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1),\
- .rst_dly = ((nr*500)/24+1),\
- .clksel0 = RK3288_ACLK_M0_DIV(m0_div) | RK3288_ACLK_MP_DIV(mp_div),\
- .clksel1 = RK3288_CLK_L2RAM_DIV(l2_div) | RK3288_ATCLK_DIV(atclk_div) | RK3288_PCLK_DBG_DIV(pclk_dbg_div),\
- .lpj = (CLK_LOOPS_JIFFY_REF*_mhz) / CLK_LOOPS_RATE_REF,\
-}
-/***************************RK3036 PLL**************************************/
-#define LPJ_24M (CLK_LOOPS_JIFFY_REF * 24) / CLK_LOOPS_RATE_REF
-/*PLL_CON 0,1,2*/
-#define RK3036_PLL_PWR_ON (0)
-#define RK3036_PLL_PWR_DN (1)
-#define RK3036_PLL_BYPASS (1 << 15)
-#define RK3036_PLL_NO_BYPASS (0 << 15)
-/*con0*/
-#define RK3036_PLL_BYPASS_SHIFT (15)
-
-#define RK3036_PLL_POSTDIV1_MASK (0x7)
-#define RK3036_PLL_POSTDIV1_SHIFT (12)
-#define RK3036_PLL_FBDIV_MASK (0xfff)
-#define RK3036_PLL_FBDIV_SHIFT (0)
-
-/*con1*/
-#define RK3036_PLL_RSTMODE_SHIFT (15)
-#define RK3036_PLL_RST_SHIFT (14)
-#define RK3036_PLL_PWR_DN_SHIFT (13)
-#define RK3036_PLL_DSMPD_SHIFT (12)
-#define RK3036_PLL_LOCK_SHIFT (10)
-
-#define RK3036_PLL_POSTDIV2_MASK (0x7)
-#define RK3036_PLL_POSTDIV2_SHIFT (6)
-#define RK3036_PLL_REFDIV_MASK (0x3f)
-#define RK3036_PLL_REFDIV_SHIFT (0)
-
-/*con2*/
-#define RK3036_PLL_FOUT4PHASE_PWR_DN_SHIFT (27)
-#define RK3036_PLL_FOUTVCO_PWR_DN_SHIFT (26)
-#define RK3036_PLL_FOUTPOSTDIV_PWR_DN_SHIFT (25)
-#define RK3036_PLL_DAC_PWR_DN_SHIFT (24)
-
-#define RK3036_PLL_FRAC_MASK (0xffffff)
-#define RK3036_PLL_FRAC_SHIFT (0)
-
-#define CRU_GET_REG_BIT_VAL(reg, bits_shift) (((reg) >> (bits_shift)) & (0x1))
-#define CRU_GET_REG_BITS_VAL(reg, bits_shift, msk) (((reg) >> (bits_shift)) & (msk))
-#define CRU_SET_BIT(val, bits_shift) (((val) & (0x1)) << (bits_shift))
-#define CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16))
-
-#define CRU_W_MSK_SETBITS(val, bits_shift, msk) (CRU_W_MSK(bits_shift, msk) \
- | CRU_SET_BITS(val, bits_shift, msk))
-#define CRU_W_MSK_SETBIT(val, bits_shift) (CRU_W_MSK(bits_shift, 0x1) \
- | CRU_SET_BIT(val, bits_shift))
-
-#define RK3036_PLL_SET_REFDIV(val) CRU_W_MSK_SETBITS(val, RK3036_PLL_REFDIV_SHIFT, RK3036_PLL_REFDIV_MASK)
-#define RK3036_PLL_SET_FBDIV(val) CRU_W_MSK_SETBITS(val, RK3036_PLL_FBDIV_SHIFT, RK3036_PLL_FBDIV_MASK)
-#define RK3036_PLL_SET_POSTDIV1(val) CRU_W_MSK_SETBITS(val, RK3036_PLL_POSTDIV1_SHIFT, RK3036_PLL_POSTDIV1_MASK)
-#define RK3036_PLL_SET_POSTDIV2(val) CRU_W_MSK_SETBITS(val, RK3036_PLL_POSTDIV2_SHIFT, RK3036_PLL_POSTDIV2_MASK)
-#define RK3036_PLL_SET_FRAC(val) CRU_SET_BITS(val, RK3036_PLL_FRAC_SHIFT, RK3036_PLL_FRAC_MASK)
-
-#define RK3036_PLL_GET_REFDIV(reg) CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_REFDIV_SHIFT, RK3036_PLL_REFDIV_MASK)
-#define RK3036_PLL_GET_FBDIV(reg) CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_FBDIV_SHIFT, RK3036_PLL_FBDIV_MASK)
-#define RK3036_PLL_GET_POSTDIV1(reg) CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_POSTDIV1_SHIFT, RK3036_PLL_POSTDIV1_MASK)
-#define RK3036_PLL_GET_POSTDIV2(reg) CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_POSTDIV2_SHIFT, RK3036_PLL_POSTDIV2_MASK)
-#define RK3036_PLL_GET_FRAC(reg) CRU_GET_REG_BITS_VAL(reg, RK3036_PLL_FRAC_SHIFT, RK3036_PLL_FRAC_MASK)
-
-/*#define APLL_SET_BYPASS(val) CRU_SET_BIT(val, PLL_BYPASS_SHIFT)*/
-#define RK3036_PLL_SET_DSMPD(val) CRU_W_MSK_SETBIT(val, RK3036_PLL_DSMPD_SHIFT)
-#define RK3036_PLL_GET_DSMPD(reg) CRU_GET_REG_BIT_VAL(reg, RK3036_PLL_DSMPD_SHIFT)
-
-/*******************CLKSEL0 BITS***************************/
-#define RK3036_CLK_SET_DIV_CON_SUB1(val, bits_shift, msk) CRU_W_MSK_SETBITS((val - 1), bits_shift, msk)
-
-#define RK3036_CPU_CLK_PLL_SEL_SHIFT (14)
-#define RK3036_CPU_CLK_PLL_SEL_MASK (0x3)
-#define RK3036_CORE_CLK_PLL_SEL_SHIFT (7)
-#define RK3036_SEL_APLL (0)
-#define RK3036_SEL_GPLL (1)
-#define RK3036_CPU_SEL_PLL(plls) CRU_W_MSK_SETBITS(plls, RK3036_CPU_CLK_PLL_SEL_SHIFT, RK3036_CPU_CLK_PLL_SEL_MASK)
-#define RK3036_CORE_SEL_PLL(plls) CRU_W_MSK_SETBIT(plls, RK3036_CORE_CLK_PLL_SEL_SHIFT)
-
-#define RK3036_ACLK_CPU_DIV_MASK (0x1f)
-#define RK3036_ACLK_CPU_DIV_SHIFT (8)
-#define RK3036_A9_CORE_DIV_MASK (0x1f)
-#define RK3036_A9_CORE_DIV_SHIFT (0)
-
-#define RATIO_11 (1)
-#define RATIO_21 (2)
-#define RATIO_41 (4)
-#define RATIO_81 (8)
-
-#define RK3036_ACLK_CPU_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_ACLK_CPU_DIV_SHIFT, RK3036_ACLK_CPU_DIV_MASK)
-#define RK3036_CLK_CORE_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_A9_CORE_DIV_SHIFT, RK3036_A9_CORE_DIV_MASK)
-/*******************CLKSEL1 BITS***************************/
-#define RK3036_PCLK_CPU_DIV_MASK (0x7)
-#define RK3036_PCLK_CPU_DIV_SHIFT (12)
-#define RK3036_HCLK_CPU_DIV_MASK (0x3)
-#define RK3036_HCLK_CPU_DIV_SHIFT (8)
-#define RK3036_ACLK_CORE_DIV_MASK (0x7)
-#define RK3036_ACLK_CORE_DIV_SHIFT (4)
-#define RK3036_CORE_PERIPH_DIV_MASK (0xf)
-#define RK3036_CORE_PERIPH_DIV_SHIFT (0)
-
-#define RK3036_PCLK_CPU_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_PCLK_CPU_DIV_SHIFT, RK3036_PCLK_CPU_DIV_MASK)
-#define RK3036_HCLK_CPU_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_HCLK_CPU_DIV_SHIFT, RK3036_HCLK_CPU_DIV_MASK)
-#define RK3036_ACLK_CORE_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_ACLK_CORE_DIV_SHIFT, RK3036_ACLK_CORE_DIV_MASK)
-#define RK3036_CLK_CORE_PERI_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_CORE_PERIPH_DIV_SHIFT, RK3036_CORE_PERIPH_DIV_MASK)
-
-/*******************clksel10***************************/
-#define RK3036_PERI_PLL_SEL_SHIFT 14
-#define RK3036_PERI_PLL_SEL_MASK (0x3)
-#define RK3036_PERI_PCLK_DIV_MASK (0x3)
-#define RK3036_PERI_PCLK_DIV_SHIFT (12)
-#define RK3036_PERI_HCLK_DIV_MASK (0x3)
-#define RK3036_PERI_HCLK_DIV_SHIFT (8)
-#define RK3036_PERI_ACLK_DIV_MASK (0x1f)
-#define RK3036_PERI_ACLK_DIV_SHIFT (0)
-
-#define RK3036_SEL_3PLL_APLL (0)
-#define RK3036_SEL_3PLL_DPLL (1)
-#define RK3036_SEL_3PLL_GPLL (2)
-
-
-#define RK3036_PERI_CLK_SEL_PLL(plls) CRU_W_MSK_SETBITS(plls, RK3036_PERI_PLL_SEL_SHIFT, RK3036_PERI_PLL_SEL_MASK)
-#define RK3036_PERI_SET_ACLK_DIV(val) RK3036_CLK_SET_DIV_CON_SUB1(val, RK3036_PERI_ACLK_DIV_SHIFT, RK3036_PERI_ACLK_DIV_MASK)
-
-/*******************gate BITS***************************/
-#define RK3036_CLK_GATE_CLKID_CONS(i) RK3036_CRU_CLKGATES_CON((i) / 16)
-
-#define RK3036_CLK_GATE(i) (1 << ((i)%16))
-#define RK3036_CLK_UN_GATE(i) (0)
-
-#define RK3036_CLK_GATE_W_MSK(i) (1 << (((i) % 16) + 16))
-#define RK3036_CLK_GATE_CLKID(i) (16 * (i))
-
-#define _RK3036_APLL_SET_CLKS(_mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac, \
- _periph_div) \
-{ \
- .rate = (_mhz) * MHZ, \
- .pllcon0 = RK3036_PLL_SET_POSTDIV1(_postdiv1) | RK3036_PLL_SET_FBDIV(_fbdiv), \
- .pllcon1 = RK3036_PLL_SET_DSMPD(_dsmpd) | RK3036_PLL_SET_POSTDIV2(_postdiv2) | RK3036_PLL_SET_REFDIV(_refdiv), \
- .pllcon2 = RK3036_PLL_SET_FRAC(_frac), \
- .clksel1 = RK3036_CLK_CORE_PERI_DIV(RATIO_##_periph_div), \
- .lpj = (CLK_LOOPS_JIFFY_REF * _mhz) / CLK_LOOPS_RATE_REF, \
- .rst_dly = 0,\
-}
-
-#define _RK3036_PLL_SET_CLKS(_mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac) \
-{ \
- .rate = (_mhz) * KHZ, \
- .pllcon0 = RK3036_PLL_SET_POSTDIV1(_postdiv1) | RK3036_PLL_SET_FBDIV(_fbdiv), \
- .pllcon1 = RK3036_PLL_SET_DSMPD(_dsmpd) | RK3036_PLL_SET_POSTDIV2(_postdiv2) | RK3036_PLL_SET_REFDIV(_refdiv), \
- .pllcon2 = RK3036_PLL_SET_FRAC(_frac), \
-}
-
-/***************************RK3368 PLL**************************************/
-/*******************CLKSEL0/2 BITS***************************/
-#define RK3368_CORE_SEL_PLL_W_MSK (1 << 23)
-#define RK3368_CORE_SEL_APLL (0 << 7)
-#define RK3368_CORE_SEL_GPLL (1 << 7)
-
-#define RK3368_CORE_CLK_SHIFT 0
-#define RK3368_CORE_CLK_WIDTH 5
-#define RK3368_CORE_CLK_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3368_CORE_CLK_SHIFT, RK3368_CORE_CLK_WIDTH)
-#define RK3368_CORE_CLK_MAX_DIV (2<<RK3368_CORE_CLK_WIDTH)
-
-#define RK3368_ACLKM_CORE_SHIFT 8
-#define RK3368_ACLKM_CORE_WIDTH 5
-#define RK3368_ACLKM_CORE_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3368_ACLKM_CORE_SHIFT, RK3368_ACLKM_CORE_WIDTH)
-
-/*******************CLKSEL1/3 BITS***************************/
-#define RK3368_ATCLK_CORE_SHIFT 0
-#define RK3368_ATCLK_CORE_WIDTH 5
-#define RK3368_ATCLK_CORE_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3368_ATCLK_CORE_SHIFT, RK3368_ATCLK_CORE_WIDTH)
-
-#define RK3368_PCLK_DBG_SHIFT 8
-#define RK3368_PCLK_DBG_WIDTH 5
-#define RK3368_PCLK_DBG_DIV(i) \
- CLK_DIV_PLUS_ONE_SET(i, RK3368_PCLK_DBG_SHIFT, RK3368_PCLK_DBG_WIDTH)
-
-#define _RK3368_APLL_SET_CLKS(_mhz, nr, nf, no, aclkm_div, atclk_div, pclk_dbg_div) \
-{ \
- .rate = _mhz * MHZ, \
- .pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr) | RK3188PLUS_PLL_CLKOD_SET(no), \
- .pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf),\
- .pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1),\
- .rst_dly = ((nr*500)/24+1),\
- .clksel0 = RK3368_ACLKM_CORE_DIV(aclkm_div),\
- .clksel1 = RK3368_ATCLK_CORE_DIV(atclk_div) | RK3368_PCLK_DBG_DIV(pclk_dbg_div) \
-}
-
-struct pll_clk_set {
- unsigned long rate;
- u32 pllcon0;
- u32 pllcon1;
- u32 pllcon2;
- unsigned long rst_dly;//us
-};
-
-struct apll_clk_set {
- unsigned long rate;
- u32 pllcon0;
- u32 pllcon1;
- u32 pllcon2;
- u32 rst_dly;//us
- u32 clksel0;
- u32 clksel1;
- unsigned long lpj;
-};
-
-
-#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
-
-struct clk_pll {
- struct clk_hw hw;
- u32 reg;
- u32 width;
- u32 mode_offset;
- u8 mode_shift;
- u32 status_offset;
- u8 status_shift;
- u32 flags;
- const void *table;
- spinlock_t *lock;
-};
-
-const struct clk_ops *rk_get_pll_ops(u32 pll_flags);
-
-struct clk *rk_clk_register_pll(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags, u32 reg,
- u32 width, u32 mode_offset, u8 mode_shift,
- u32 status_offset, u8 status_shift, u32 pll_flags,
- spinlock_t *lock);
-
-
-#endif /* __RK_CLK_PLL_H */
+++ /dev/null
-/*
- * Copyright (C) 2013 ROCKCHIP, Inc.
- * Author: chenxing <chenxing@rock-chips.com>
- * Dai Kelin <dkl@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/clk-private.h>
-#include <asm/io.h>
-
-#include "clk-ops.h"
-#include "clk-pll.h"
-#include "clk-pd.h"
-
-static void __iomem *rk_cru_base;
-static void __iomem *rk_grf_base;
-
-u32 cru_readl(u32 offset)
-{
- return readl_relaxed(rk_cru_base + (offset));
-}
-
-void cru_writel(u32 val, u32 offset)
-{
- writel_relaxed(val, rk_cru_base + (offset));
- dsb(sy);
-}
-
-u32 grf_readl(u32 offset)
-{
- return readl_relaxed(rk_grf_base + (offset));
-}
-
-struct rkclk_muxinfo {
- const char *clk_name;
- struct device_node *np;
- struct clk_mux *mux;
- u8 parent_num;
- const char **parent_names;
- u32 clkops_idx;
-};
-
-struct rkclk_divinfo {
- const char *clk_name;
- struct device_node *np;
- struct clk_divider *div;
- u32 div_type;
- const char *parent_name;
- u32 clkops_idx;
-};
-
-struct rkclk_fracinfo {
- const char *clk_name;
- struct device_node *np;
- struct clk_divider *frac;
- u32 frac_type;
- const char *parent_name;
- u32 clkops_idx;
-};
-
-struct rkclk_gateinfo {
- const char *clk_name;
- struct device_node *np;
- struct clk_gate *gate;
- const char *parent_name;
- //u32 clkops_idx;
-};
-
-struct rkclk_pllinfo {
- const char *clk_name;
- struct device_node *np;
- struct clk_pll *pll;
- const char *parent_name;
- u32 clkops_idx;
-};
-
-struct rkclk_fixed_rate_info {
- const char *clk_name;
- struct device_node *np;
- struct clk_fixed_rate *fixed_rate;
- const char *parent_name;
-};
-
-struct rkclk_fixed_factor_info {
- const char *clk_name;
- struct device_node *np;
- struct clk_fixed_factor *fixed_factor;
- const char *parent_name;
-};
-
-struct rkclk_pd_info {
- const char *clk_name;
- struct device_node *np;
- struct clk_pd *pd;
- const char *parent_name;
-};
-
-
-struct rkclk {
- const char *clk_name;
- //struct device_node *np;
- u32 clk_type;
- u32 flags;
- struct rkclk_muxinfo *mux_info;
- struct rkclk_divinfo *div_info;
- struct rkclk_fracinfo *frac_info;
- struct rkclk_pllinfo *pll_info;
- struct rkclk_gateinfo *gate_info;
- struct rkclk_fixed_rate_info *fixed_rate_info;
- struct rkclk_fixed_factor_info *fixed_factor_info;
- struct rkclk_pd_info *pd_info;
- struct list_head node;
-};
-
-static DEFINE_SPINLOCK(clk_lock);
-LIST_HEAD(rk_clks);
-
-#define RKCLK_PLL_TYPE (1 << 0)
-#define RKCLK_MUX_TYPE (1 << 1)
-#define RKCLK_DIV_TYPE (1 << 2)
-#define RKCLK_FRAC_TYPE (1 << 3)
-#define RKCLK_GATE_TYPE (1 << 4)
-#define RKCLK_FIXED_RATE_TYPE (1 << 5)
-#define RKCLK_FIXED_FACTOR_TYPE (1 << 6)
-#define RKCLK_PD_TYPE (1 << 7)
-
-
-static int rkclk_init_muxinfo(struct device_node *np, void __iomem *addr)
-{
- struct rkclk_muxinfo *muxinfo = NULL;
- struct clk_mux *mux = NULL;
- u32 shift, width;
- u32 flags;
- int cnt, i, ret = 0;
- u8 found = 0;
- struct rkclk *rkclk = NULL;
-
-
- muxinfo = kzalloc(sizeof(struct rkclk_muxinfo), GFP_KERNEL);
- if (!muxinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- muxinfo->mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
- if (!muxinfo->mux) {
- ret = -ENOMEM;
- goto out;
- }
- mux = muxinfo->mux;
-
- ret = of_property_read_string(np, "clock-output-names",
- &muxinfo->clk_name);
- if (ret != 0)
- goto out;
-
- muxinfo->np = np;
-
- cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells");
- if (cnt < 0) {
- ret = -EINVAL;
- goto out;
- } else {
- clk_debug("%s: parent cnt = %d\n", __func__, cnt);
- muxinfo->parent_num = (u8)cnt;
- }
-
- muxinfo->parent_names = kzalloc(cnt * sizeof(char *), GFP_KERNEL);
- for (i = 0; i < cnt ; i++) {
- muxinfo->parent_names[i] = of_clk_get_parent_name(np, i);
- }
-
- mux->reg = addr;
-
- ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift);
- if (ret != 0) {
- goto out;
- } else {
- mux->shift = (u8)shift;
- }
-
- ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width);
- if (ret != 0)
- goto out;
- mux->mask = (1 << width) - 1;
-
- mux->flags = CLK_MUX_HIWORD_MASK;
-
- ret = of_property_read_u32(np, "rockchip,clkops-idx",
- &muxinfo->clkops_idx);
- if (ret != 0) {
- muxinfo->clkops_idx = CLKOPS_TABLE_END;
- ret = 0;
- }
-
- ret = of_property_read_u32(np, "rockchip,flags", &flags);
- if (ret != 0) {
- flags = 0;
- ret = 0;
- }
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(muxinfo->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->mux_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->mux_info = muxinfo;
- rkclk->clk_type |= RKCLK_MUX_TYPE;
- rkclk->flags |= flags;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = muxinfo->clk_name;
- rkclk->mux_info = muxinfo;
- rkclk->clk_type = RKCLK_MUX_TYPE;
- rkclk->flags = flags;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (muxinfo) {
- if (muxinfo->mux)
- kfree(muxinfo->mux);
- kfree(muxinfo);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int rkclk_init_divinfo(struct device_node *np, void __iomem *addr)
-{
- int cnt = 0, i = 0, ret = 0;
- struct rkclk *rkclk = NULL;
- u8 found = 0;
- u32 flags;
- u32 shift, width;
- struct rkclk_divinfo *divinfo = NULL;
- struct clk_divider *div = NULL;
- struct clk_div_table *table;
- u32 table_val, table_div;
-
-
- divinfo = kzalloc(sizeof(struct rkclk_divinfo), GFP_KERNEL);
- if (!divinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- divinfo->div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
- if (!divinfo->div) {
- ret = -ENOMEM;
- goto out;
- }
- div = divinfo->div;
-
- ret = of_property_read_string(np, "clock-output-names",
- &divinfo->clk_name);
- if (ret != 0)
- goto out;
-
- divinfo->parent_name = of_clk_get_parent_name(np, 0);
-
- divinfo->np = np;
-
- ret = of_property_read_u32(np, "rockchip,clkops-idx",
- &divinfo->clkops_idx);
- if (ret != 0) {
- divinfo->clkops_idx = CLKOPS_TABLE_END;
- ret = 0;
- }
-
- ret = of_property_read_u32(np, "rockchip,flags", &flags);
- if (ret != 0) {
- flags = 0;
- ret = 0;
- }
-
- ret = of_property_read_u32(np, "rockchip,div-type", &divinfo->div_type);
- if (ret != 0)
- goto out;
-
- switch (divinfo->div_type) {
- case CLK_DIVIDER_PLUS_ONE:
- case CLK_DIVIDER_ONE_BASED:
- case CLK_DIVIDER_POWER_OF_TWO:
- break;
- case CLK_DIVIDER_USER_DEFINE:
- of_get_property(np, "rockchip,div-relations", &cnt);
- if (cnt <= 0) {
- ret = -EINVAL;
- goto out;
- }
- cnt /= 4 * 2;
- table = kzalloc(cnt * sizeof(struct clk_div_table),
- GFP_KERNEL);
- if (!table) {
- ret = -ENOMEM;
- goto out;
- }
- for (i = 0; i < cnt; i++) {
- ret = of_property_read_u32_index(np,
- "rockchip,div-relations", i * 2,
- &table_val);
- if (ret)
- goto out;
- ret = of_property_read_u32_index(np,
- "rockchip,div-relations",
- i * 2 + 1, &table_div);
- if (ret)
- goto out;
- table[i].val = (unsigned int)table_val;
- table[i].div = (unsigned int)table_div;
- clk_debug("\tGet div table %d: val=%d, div=%d\n",
- i, table_val, table_div);
- }
- div->table = table;
- break;
- default:
- clk_err("%s: %s: unknown rockchip,div-type\n", __func__,
- divinfo->clk_name);
- ret = -EINVAL;
- goto out;
- }
-
- div->reg = addr;
- ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift);
- if (ret)
- goto out;
- ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width);
- if (ret)
- goto out;
- div->shift = (u8)shift;
- div->width = (u8)width;
- div->flags = CLK_DIVIDER_HIWORD_MASK | divinfo->div_type;
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(divinfo->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->div_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->div_info = divinfo;
- rkclk->clk_type |= RKCLK_DIV_TYPE;
- rkclk->flags |= flags;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = divinfo->clk_name;
- rkclk->div_info = divinfo;
- rkclk->clk_type = RKCLK_DIV_TYPE;
- rkclk->flags = flags;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if(table)
- kfree(table);
- if (divinfo) {
- if (divinfo->div)
- kfree(divinfo->div);
- kfree(divinfo);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int rkclk_init_fracinfo(struct device_node *np, void __iomem *addr)
-{
- struct rkclk *rkclk = NULL;
- u8 found = 0;
- int ret = 0;
- struct rkclk_fracinfo *fracinfo = NULL;
- struct clk_divider *frac = NULL;
- u32 shift, width, flags;
-
-
- fracinfo = kzalloc(sizeof(struct rkclk_fracinfo), GFP_KERNEL);
- if (!fracinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- fracinfo->frac = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
- if (!fracinfo->frac) {
- ret = -ENOMEM;
- goto out;
- }
- frac = fracinfo->frac;
-
- ret = of_property_read_string(np, "clock-output-names",
- &fracinfo->clk_name);
- if (ret != 0)
- goto out;
-
- fracinfo->parent_name = of_clk_get_parent_name(np, 0);
- fracinfo->np = np;
-
- ret = of_property_read_u32(np, "rockchip,clkops-idx",
- &fracinfo->clkops_idx);
- if (ret != 0) {
- fracinfo->clkops_idx = CLKOPS_TABLE_END;
- clk_err("frac node without specified ops!\n");
- ret = -EINVAL;
- goto out;
- }
-
- ret = of_property_read_u32(np, "rockchip,flags", &flags);
- if (ret != 0) {
- clk_debug("if not specified, frac use CLK_SET_RATE_PARENT flag "
- "as default\n");
- flags = CLK_SET_RATE_PARENT;
- ret = 0;
- }
-
- frac->reg = addr;
- ret = of_property_read_u32_index(np, "rockchip,bits", 0, &shift);
- if (ret)
- goto out;
- ret = of_property_read_u32_index(np, "rockchip,bits", 1, &width);
- if (ret)
- goto out;
- frac->shift = (u8)shift;
- frac->width = (u8)width;
- frac->flags = 0;
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(fracinfo->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->frac_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->frac_info = fracinfo;
- rkclk->clk_type |= RKCLK_FRAC_TYPE;
- rkclk->flags |= flags;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = fracinfo->clk_name;
- rkclk->frac_info = fracinfo;
- rkclk->clk_type = RKCLK_FRAC_TYPE;
- rkclk->flags = flags;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (fracinfo) {
- if (fracinfo->frac)
- kfree(fracinfo->frac);
- kfree(fracinfo);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int __init rkclk_init_selcon(struct device_node *np)
-{
- struct device_node *node_con, *node;
- void __iomem *reg = 0;
- int ret = 0;
-
-
- for_each_available_child_of_node(np, node_con) {
- reg = of_iomap(node_con, 0);
- clk_debug("\n");
- clk_debug("%s: reg = 0x%x\n", __func__, (u32)reg);
-
- for_each_available_child_of_node(node_con, node) {
- clk_debug("\n");
- if (of_device_is_compatible(node,
- "rockchip,rk3188-div-con"))
- ret = rkclk_init_divinfo(node, reg);
-
- else if (of_device_is_compatible(node,
- "rockchip,rk3188-mux-con"))
- ret = rkclk_init_muxinfo(node, reg);
-
- else if (of_device_is_compatible(node,
- "rockchip,rk3188-frac-con"))
- ret = rkclk_init_fracinfo(node, reg);
-
- else if (of_device_is_compatible(node,
- "rockchip,rk3188-inv-con"))
- clk_debug("INV clk\n");
-
- else {
- clk_err("%s: unknown controller type\n",
- __func__);
- ret = -EINVAL;
- }
- }
- }
-
- return ret;
-}
-
-static int __init rkclk_init_gatecon(struct device_node *np)
-{
- struct device_node *node;
- const char *clk_name;
- void __iomem *reg;
- int cnt;
- int i;
- struct rkclk_gateinfo *gateinfo;
- u8 found = 0;
- struct rkclk *rkclk;
- int ret = 0;
- struct clk_gate *gate = NULL;
-
-
- for_each_available_child_of_node(np, node) {
- cnt = of_property_count_strings(node, "clock-output-names");
- if (cnt < 0) {
- clk_err("%s: error in clock-output-names %d\n",
- __func__, cnt);
- continue;
- }
-
- if (cnt == 0) {
- clk_debug("%s: nothing to do\n", __func__);
- continue;
- }
-
- reg = of_iomap(node, 0);
- clk_debug("\n");
- clk_debug("%s: reg = 0x%x\n", __func__, (u32)reg);
-
- for (i = 0; i < cnt; i++) {
- ret = of_property_read_string_index(node,
- "clock-output-names", i, &clk_name);
- if (ret != 0)
- goto out;
-
- /* ignore empty slots */
- if (!strcmp("reserved", clk_name)) {
- clk_debug("do nothing for reserved clk\n");
- continue;
- }
-
- gateinfo = kzalloc(sizeof(struct rkclk_gateinfo),
- GFP_KERNEL);
- if (!gateinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- gateinfo->gate = kzalloc(sizeof(struct clk_gate),
- GFP_KERNEL);
- if (!gateinfo->gate) {
- ret = -ENOMEM;
- goto out;
- }
- gate = gateinfo->gate;
-
- gateinfo->clk_name = clk_name;
- gateinfo->parent_name = of_clk_get_parent_name(node, i);
- gateinfo->np = node;
-
- gate->reg = reg;
- gate->bit_idx = (i % 16);
- gate->flags = CLK_GATE_HIWORD_MASK |
- CLK_GATE_SET_TO_DISABLE;
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(clk_name, rkclk->clk_name) == 0) {
- if (rkclk->gate_info != NULL) {
- clk_err("%s %d:\n", __func__,
- __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n",
- __func__, rkclk->clk_name);
- found = 1;
- rkclk->gate_info = gateinfo;
- rkclk->clk_type |= RKCLK_GATE_TYPE;
- break;
- }
- }
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = gateinfo->clk_name;
- rkclk->gate_info = gateinfo;
- rkclk->clk_type = RKCLK_GATE_TYPE;
- clk_debug("%s: creat %s\n", __func__,
- rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (gateinfo) {
- if (gateinfo->gate)
- kfree(gateinfo->gate);
- kfree(gateinfo);
- }
- if (rkclk)
- kfree(rkclk);
- }
- }
-
- }
-
- return 0;
-}
-
-static int __init rkclk_init_pllcon(struct device_node *np)
-{
- struct device_node *node = NULL;
- struct rkclk_pllinfo *pllinfo = NULL;
- struct clk_pll *pll = NULL;
- u8 found = 0;
- int ret = 0;
- struct rkclk *rkclk = NULL;
- u32 flags;
- u32 mode_shift, status_shift;
-
-
- for_each_available_child_of_node(np, node) {
- pllinfo = kzalloc(sizeof(struct rkclk_pllinfo), GFP_KERNEL);
- if (!pllinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- pllinfo->pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
- if (!pllinfo->pll) {
- ret = -ENOMEM;
- goto out;
- }
- pll = pllinfo->pll;
-
- pllinfo->np = node;
-
- ret = of_property_read_string_index(node, "clock-output-names",
- 0, &pllinfo->clk_name);
- if (ret)
- goto out;
-
- pllinfo->parent_name = of_clk_get_parent_name(node, 0);
-
- ret = of_property_read_u32(np, "rockchip,flags", &flags);
- if (ret != 0) {
- flags = 0;
- ret = 0;
- }
-
- ret = of_property_read_u32_index(node, "reg", 0, &pll->reg);
- if (ret != 0) {
- clk_err("%s: can not get reg addr info\n", __func__);
- goto out;
- }
-
- ret = of_property_read_u32_index(node, "reg", 1, &pll->width);
- if (ret != 0) {
- clk_err("%s: can not get reg length info\n", __func__);
- goto out;
- }
-
- ret = of_property_read_u32_index(node, "mode-reg", 0,
- &pll->mode_offset);
- if (ret != 0) {
- clk_err("%s: can not get mode_reg offset\n", __func__);
- goto out;
- }
-
- ret = of_property_read_u32_index(node, "mode-reg", 1,
- &mode_shift);
- if (ret != 0) {
- clk_err("%s: can not get mode_reg shift\n", __func__);
- goto out;
- } else {
- pll->mode_shift = (u8)mode_shift;
- }
-
- ret = of_property_read_u32_index(node, "status-reg", 0,
- &pll->status_offset);
- if (ret != 0) {
- clk_err("%s: can not get status_reg offset\n", __func__);
- goto out;
- }
-
- ret = of_property_read_u32_index(node, "status-reg", 1,
- &status_shift);
- if (ret != 0) {
- clk_err("%s: can not get status_reg shift\n", __func__);
- goto out;
- } else {
- pll->status_shift= (u8)status_shift;
- }
-
- ret = of_property_read_u32(node, "rockchip,pll-type", &pll->flags);
- if (ret != 0) {
- clk_err("%s: can not get pll-type\n", __func__);
- goto out;
- }
-
- clk_debug("%s: pllname=%s, parent=%s, flags=0x%x\n",
- __func__, pllinfo->clk_name,
- pllinfo->parent_name, flags);
-
- clk_debug("\t\taddr=0x%x, len=0x%x, mode:offset=0x%x, shift=0x%x,"
- " status:offset=0x%x, shift=0x%x, pll->flags=0x%x\n",
- (u32)pll->reg, pll->width,
- pll->mode_offset, pll->mode_shift,
- pll->status_offset, pll->status_shift,
- pll->flags);
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(pllinfo->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->pll_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->pll_info = pllinfo;
- rkclk->clk_type |= RKCLK_PLL_TYPE;
- rkclk->flags |= flags;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = pllinfo->clk_name;
- rkclk->pll_info = pllinfo;
- rkclk->clk_type = RKCLK_PLL_TYPE;
- rkclk->flags = flags;
- list_add_tail(&rkclk->node, &rk_clks);
- }
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (pllinfo) {
- if (pllinfo->pll)
- kfree(pllinfo->pll);
- kfree(pllinfo);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int __init rkclk_init_fixed_rate(struct device_node *np)
-{
- struct device_node *node = NULL;
- struct rkclk_fixed_rate_info *fixed_rate_info = NULL;
- struct clk_fixed_rate *fixed_rate = NULL;
- u32 rate;
- int ret = 0;
- u8 found = 0;
- struct rkclk *rkclk = NULL;
-
-
- for_each_available_child_of_node(np, node) {
- fixed_rate_info = kzalloc(sizeof(struct rkclk_fixed_rate_info),
- GFP_KERNEL);
- if (!fixed_rate_info) {
- ret = -ENOMEM;
- goto out;
- }
-
- fixed_rate_info->fixed_rate = kzalloc(sizeof(struct clk_fixed_rate),
- GFP_KERNEL);
- if (!fixed_rate_info->fixed_rate) {
- ret = -ENOMEM;
- goto out;
- }
- fixed_rate = fixed_rate_info->fixed_rate;
-
- fixed_rate_info->np = node;
-
- ret = of_property_read_string_index(node, "clock-output-names",
- 0, &fixed_rate_info->clk_name);
- if (ret)
- goto out;
-
- fixed_rate_info->parent_name = of_clk_get_parent_name(node, 0);
-
- ret = of_property_read_u32(node, "clock-frequency", &rate);
- if (ret != 0) {
- clk_err("%s: can not get clock-frequency\n", __func__);
- goto out;
- }
- fixed_rate->fixed_rate = (unsigned long)rate;
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(fixed_rate_info->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->fixed_rate_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->fixed_rate_info = fixed_rate_info;
- rkclk->clk_type |= RKCLK_FIXED_RATE_TYPE;
- rkclk->flags |= CLK_IS_ROOT;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = fixed_rate_info->clk_name;
- rkclk->fixed_rate_info = fixed_rate_info;
- rkclk->clk_type = RKCLK_FIXED_RATE_TYPE;
- rkclk->flags = CLK_IS_ROOT;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (fixed_rate_info) {
- if (fixed_rate_info->fixed_rate)
- kfree(fixed_rate_info->fixed_rate);
- kfree(fixed_rate_info);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int __init rkclk_init_fixed_factor(struct device_node *np)
-{
- struct device_node *node = NULL;
- struct rkclk_fixed_factor_info *fixed_factor_info = NULL;
- struct clk_fixed_factor *fixed_factor = NULL;
- u32 flags, mult, div;
- int ret = 0;
- u8 found = 0;
- struct rkclk *rkclk = NULL;
-
-
- for_each_available_child_of_node(np, node) {
- fixed_factor_info = kzalloc(sizeof(struct rkclk_fixed_factor_info),
- GFP_KERNEL);
- if (!fixed_factor_info) {
- ret = -ENOMEM;
- goto out;
- }
-
- fixed_factor_info->fixed_factor = kzalloc(sizeof(struct clk_fixed_factor),
- GFP_KERNEL);
- if (!fixed_factor_info->fixed_factor) {
- ret = -ENOMEM;
- goto out;
- }
- fixed_factor = fixed_factor_info->fixed_factor;
-
- fixed_factor_info->np = node;
-
- ret = of_property_read_string_index(node, "clock-output-names",
- 0, &fixed_factor_info->clk_name);
- if (ret)
- goto out;
-
- fixed_factor_info->parent_name = of_clk_get_parent_name(node, 0);
-
- ret = of_property_read_u32(node, "rockchip,flags", &flags);
- if (ret != 0) {
- flags = 0;
- ret = 0;
- }
-
- ret = of_property_read_u32(node, "clock-mult", &mult);
- if (ret != 0) {
- clk_err("%s: can not get mult\n", __func__);
- goto out;
- }
- fixed_factor->mult = (unsigned int)mult;
-
- ret = of_property_read_u32(node, "clock-div", &div);
- if (ret != 0) {
- clk_err("%s: can not get div\n", __func__);
- goto out;
- }
- fixed_factor->div = (unsigned int)div;
-
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(fixed_factor_info->clk_name, rkclk->clk_name) == 0) {
- if (rkclk->fixed_factor_info != NULL) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk(%s) has been used,"
- "will be overwrited here!\n",
- rkclk->clk_name);
- }
- clk_debug("%s: find match %s\n", __func__,
- rkclk->clk_name);
- found = 1;
- rkclk->fixed_factor_info = fixed_factor_info;
- rkclk->clk_type |= RKCLK_FIXED_FACTOR_TYPE;
- rkclk->flags |= flags;
- break;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = fixed_factor_info->clk_name;
- rkclk->fixed_factor_info = fixed_factor_info;
- rkclk->clk_type = RKCLK_FIXED_FACTOR_TYPE;
- rkclk->flags = flags;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (fixed_factor_info) {
- if (fixed_factor_info->fixed_factor)
- kfree(fixed_factor_info->fixed_factor);
- kfree(fixed_factor_info);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int __init rkclk_init_regcon(struct device_node *np)
-{
- struct device_node *node;
- const char *compatible;
- int ret = 0;
-
-
- for_each_available_child_of_node(np, node) {
- clk_debug("\n");
- of_property_read_string(node, "compatible", &compatible);
-
- if (strcmp(compatible, "rockchip,rk-pll-cons") == 0) {
- ret = rkclk_init_pllcon(node);
- if (ret != 0) {
- clk_err("%s: init pll cons err\n", __func__);
- goto out;
- }
- } else if (strcmp(compatible, "rockchip,rk-sel-cons") == 0) {
- ret = rkclk_init_selcon(node);
- if (ret != 0) {
- clk_err("%s: init sel cons err\n", __func__);
- goto out;
- }
- } else if (strcmp(compatible, "rockchip,rk-gate-cons") == 0) {
- ret = rkclk_init_gatecon(node);
- if (ret != 0) {
- clk_err("%s: init gate cons err\n", __func__);
- goto out;
- }
- } else {
- clk_err("%s: unknown\n", __func__);
- ret = -EINVAL;
- goto out;
- }
- }
-out:
- return ret;
-}
-
-static int __init rkclk_init_special_regs(struct device_node *np)
-{
- struct device_node *node;
- const char *compatible;
- void __iomem *reg = 0;
- int ret = 0;
-
-
- for_each_available_child_of_node(np, node) {
- clk_debug("\n");
- of_property_read_string(node, "compatible", &compatible);
- if (strcmp(compatible, "rockchip,rk3188-mux-con") == 0) {
- reg = of_iomap(node, 0);
- ret = rkclk_init_muxinfo(node, reg);
- if (ret != 0) {
- clk_err("%s: init mux con err\n", __func__);
- goto out;
- }
- }
- }
-
-out:
- return ret;
-}
-
-static int __init rkclk_init_pd(struct device_node *np)
-{
- struct device_node *node = NULL;
- struct rkclk_pd_info *pd_info = NULL;
- struct clk_pd *pd = NULL;
- int ret = 0;
- u8 found = 0;
- struct rkclk *rkclk = NULL;
-
-
- for_each_available_child_of_node(np, node) {
- pd_info = kzalloc(sizeof(struct rkclk_pd_info), GFP_KERNEL);
- if (!pd_info) {
- ret = -ENOMEM;
- goto out;
- }
-
- pd_info->pd = kzalloc(sizeof(struct clk_pd), GFP_KERNEL);
- if (!pd_info->pd) {
- ret = -ENOMEM;
- goto out;
- }
- pd = pd_info->pd;
-
- pd_info->np = node;
-
- ret = of_property_read_string_index(node, "clock-output-names",
- 0, &pd_info->clk_name);
- if (ret)
- goto out;
-
- pd_info->parent_name = of_clk_get_parent_name(node, 0);
-
- ret = of_property_read_u32(node, "rockchip,pd-id", &pd->id);
- if (ret != 0) {
- clk_err("%s: can not get pd-id\n", __func__);
- goto out;
- }
-
- found = 0;
- list_for_each_entry(rkclk, &rk_clks, node) {
- if (strcmp(pd_info->clk_name, rkclk->clk_name) == 0) {
- clk_err("%s %d:\n", __func__, __LINE__);
- clk_err("This clk (%s) has been used, error!\n",
- rkclk->clk_name);
- goto out;
- }
- }
-
- if (!found) {
- rkclk = kzalloc(sizeof(struct rkclk), GFP_KERNEL);
- if (!rkclk) {
- ret = -ENOMEM;
- goto out;
- }
- rkclk->clk_name = pd_info->clk_name;
- rkclk->pd_info = pd_info;
- rkclk->clk_type = RKCLK_PD_TYPE;
- rkclk->flags = 0;
- clk_debug("%s: creat %s\n", __func__, rkclk->clk_name);
- list_add_tail(&rkclk->node, &rk_clks);
- }
- }
-
-out:
- if (ret) {
- clk_err("%s error, ret = %d\n", __func__, ret);
- if (pd_info) {
- if (pd_info->pd)
- kfree(pd_info->pd);
- kfree(pd_info);
- }
- if (rkclk)
- kfree(rkclk);
- }
-
- return ret;
-}
-
-static int rkclk_register(struct rkclk *rkclk)
-{
- struct clk *clk = NULL;
- struct clk_mux *mux = NULL;
- struct clk_divider *div = NULL;
- struct clk_gate *gate = NULL;
- struct clk_pll *pll = NULL;
- struct clk_divider *frac = NULL;
- struct clk_fixed_rate *fixed_rate = NULL;
- struct clk_fixed_factor *fixed_factor = NULL;
- struct clk_pd *pd = NULL;
-
- struct clk_hw *mux_hw = NULL;
- const struct clk_ops *mux_ops = NULL;
- struct clk_hw *rate_hw = NULL;
- const struct clk_ops *rate_ops = NULL;
- struct clk_hw *gate_hw = NULL;
- const struct clk_ops *gate_ops = NULL;
-
- int parent_num;
- const char **parent_names = NULL;
- u8 rate_type_count = 0;
-
-
- if (rkclk && rkclk->clk_name) {
- clk_debug("%s: clk_name=%s, clk_type=0x%x, flags=0x%x\n",
- __func__, rkclk->clk_name, rkclk->clk_type,
- rkclk->flags);
- } else {
- clk_err("%s: rkclk or clk_name is NULL!\n", __func__);
- return -EINVAL;
- }
-
- if (rkclk->mux_info && rkclk->mux_info->mux)
- mux = rkclk->mux_info->mux;
- if (rkclk->div_info && rkclk->div_info->div)
- div = rkclk->div_info->div;
- if (rkclk->gate_info && rkclk->gate_info->gate)
- gate = rkclk->gate_info->gate;
- if (rkclk->pll_info && rkclk->pll_info->pll)
- pll = rkclk->pll_info->pll;
- if (rkclk->frac_info && rkclk->frac_info->frac)
- frac = rkclk->frac_info->frac;
- if (rkclk->fixed_rate_info && rkclk->fixed_rate_info->fixed_rate)
- fixed_rate = rkclk->fixed_rate_info->fixed_rate;
- if (rkclk->fixed_factor_info && rkclk->fixed_factor_info->fixed_factor)
- fixed_factor = rkclk->fixed_factor_info->fixed_factor;
- if (rkclk->pd_info && rkclk->pd_info->pd)
- pd = rkclk->pd_info->pd;
-
-
- switch (rkclk->clk_type) {
- case RKCLK_MUX_TYPE:
- /* only mux without specified ops will be registered here */
- if (rkclk->mux_info->clkops_idx == CLKOPS_TABLE_END) {
- clk_debug("use clk_register_mux\n");
- clk = clk_register_mux_table(NULL, rkclk->clk_name,
- rkclk->mux_info->parent_names,
- rkclk->mux_info->parent_num,
- rkclk->flags, mux->reg, mux->shift,
- mux->mask, mux->flags, NULL, &clk_lock);
- goto add_lookup;
- } else
- goto rgs_comp;
- case RKCLK_PLL_TYPE:
- clk_debug("use rk_clk_register_pll\n");
- clk = rk_clk_register_pll(NULL, rkclk->clk_name,
- rkclk->pll_info->parent_name,
- rkclk->flags, pll->reg, pll->width,
- pll->mode_offset, pll->mode_shift,
- pll->status_offset, pll->status_shift,
- pll->flags, &clk_lock);
- //kfree!!!!!!!
- goto add_lookup;
- case RKCLK_DIV_TYPE:
- /* only div without specified ops will be registered here */
- if (rkclk->div_info->clkops_idx == CLKOPS_TABLE_END) {
- clk_debug("use clk_register_divider\n");
- clk = clk_register_divider(NULL, rkclk->clk_name,
- rkclk->div_info->parent_name,
- rkclk->flags, div->reg, div->shift,
- div->width, div->flags, &clk_lock);
- goto add_lookup;
- } else
- goto rgs_comp;
- case RKCLK_FRAC_TYPE:
- if (rkclk->frac_info->clkops_idx == CLKOPS_TABLE_END) {
- clk_err("frac node without specified ops!\n");
- return -EINVAL;
- } else
- goto rgs_comp;
- case RKCLK_GATE_TYPE:
- clk_debug("use clk_register_gate\n");
- clk = clk_register_gate(NULL, rkclk->clk_name,
- rkclk->gate_info->parent_name, rkclk->flags,
- gate->reg, gate->bit_idx, gate->flags,
- &clk_lock);
- goto add_lookup;
- case RKCLK_FIXED_RATE_TYPE:
- clk_debug("use clk_register_fixed_rate\n");
- clk = clk_register_fixed_rate(NULL, rkclk->clk_name,
- rkclk->fixed_rate_info->parent_name,
- rkclk->flags, fixed_rate->fixed_rate);
- goto add_lookup;
- case RKCLK_FIXED_FACTOR_TYPE:
- clk_debug("use clk_register_fixed_factor\n");
- clk = clk_register_fixed_factor(NULL, rkclk->clk_name,
- rkclk->fixed_factor_info->parent_name,
- rkclk->flags, fixed_factor->mult,
- fixed_factor->div);
- goto add_lookup;
- case RKCLK_PD_TYPE:
- clk_debug("use rk_clk_register_pd\n");
- clk = rk_clk_register_pd(NULL, rkclk->clk_name,
- rkclk->pd_info->parent_name, rkclk->flags,
- pd->id, &clk_lock);
- goto add_lookup;
- default:
- goto rgs_comp;
- }
-
-rgs_comp:
-
- if (rkclk->clk_type & RKCLK_DIV_TYPE)
- rate_type_count++;
- if (rkclk->clk_type & RKCLK_PLL_TYPE)
- rate_type_count++;
- if (rkclk->clk_type & RKCLK_FRAC_TYPE)
- rate_type_count++;
- if (rkclk->clk_type & RKCLK_FIXED_RATE_TYPE)
- rate_type_count++;
- if (rkclk->clk_type & RKCLK_FIXED_FACTOR_TYPE)
- rate_type_count++;
-
- if (rate_type_count > 1) {
- clk_err("Invalid rkclk type!\n");
- return -EINVAL;
- }
-
- clk_debug("use clk_register_composite\n");
-
- /* prepare args for clk_register_composite */
-
- /* prepare parent_num && parent_names
- * priority: MUX > DIV=PLL=FRAC=FIXED_FACTOR > GATE
- */
- if (rkclk->clk_type & RKCLK_MUX_TYPE) {
- parent_num = rkclk->mux_info->parent_num;
- parent_names = rkclk->mux_info->parent_names;
- } else if (rkclk->clk_type & RKCLK_DIV_TYPE ) {
- parent_num = 1;
- parent_names = &(rkclk->div_info->parent_name);
- } else if (rkclk->clk_type & RKCLK_PLL_TYPE) {
- parent_num = 1;
- parent_names = &(rkclk->pll_info->parent_name);
- } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) {
- parent_num = 1;
- parent_names = &(rkclk->frac_info->parent_name);
- } else if (rkclk->clk_type & RKCLK_FIXED_FACTOR_TYPE) {
- parent_num = 1;
- parent_names = &(rkclk->fixed_factor_info->parent_name);
- } else if (rkclk->clk_type & RKCLK_GATE_TYPE) {
- parent_num = 1;
- parent_names = &(rkclk->gate_info->parent_name);
- }
-
- /* prepare mux_hw && mux_ops */
- if (rkclk->clk_type & RKCLK_MUX_TYPE) {
- mux_hw = &mux->hw;
- mux_ops = &clk_mux_ops;
- }
-
- /* prepare rate_hw && rate_ops
- * priority: DIV=PLL=FRAC=FIXED_FACTOR > MUX
- */
- if (rkclk->clk_type & RKCLK_DIV_TYPE) {
- rate_hw = &div->hw;
- if (rkclk->div_info->clkops_idx != CLKOPS_TABLE_END)
- rate_ops = rk_get_clkops(rkclk->div_info->clkops_idx);
- else
- rate_ops = &clk_divider_ops;
- } else if (rkclk->clk_type & RKCLK_PLL_TYPE) {
- rate_hw = &pll->hw;
- rate_ops = rk_get_pll_ops(pll->flags);
- } else if (rkclk->clk_type & RKCLK_FRAC_TYPE) {
- rate_hw = &frac->hw;
- rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx);
- } else if (rkclk->clk_type & RKCLK_FIXED_FACTOR_TYPE) {
- rate_hw = &fixed_factor->hw;
- rate_ops = &clk_fixed_factor_ops;
- } else if ((rkclk->clk_type & RKCLK_MUX_TYPE) &&
- (rkclk->mux_info->clkops_idx != CLKOPS_TABLE_END)) {
- /* when a mux node has specified clkops_idx, prepare rate_hw &&
- * rate_ops and use clk_register_composite to register it later.
- */
- /*FIXME*/
- rate_hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
- if (!rate_hw) {
- clk_err("%s: fail to alloc rate_hw!\n", __func__);
- return -ENOMEM;
- }
- rate_ops = rk_get_clkops(rkclk->mux_info->clkops_idx);
- }
-
- if (rkclk->clk_type & RKCLK_GATE_TYPE) {
- gate_hw = &gate->hw;
- gate_ops = &clk_gate_ops;
- }
-
- clk_debug("parent_num=%d, mux_hw=%d mux_ops=%d, rate_hw=%d rate_ops=%d,"
- " gate_hw=%d gate_ops=%d\n",
- parent_num, mux_hw?1:0, mux_ops?1:0, rate_hw?1:0,
- rate_ops?1:0, gate_hw?1:0, gate_ops?1:0);
-
- clk = clk_register_composite(NULL, rkclk->clk_name, parent_names,
- parent_num, mux_hw, mux_ops, rate_hw, rate_ops,
- gate_hw, gate_ops, rkclk->flags);
-
-add_lookup:
- if (clk) {
- clk_debug("clk name=%s, flags=0x%lx\n", clk->name, clk->flags);
- clk_register_clkdev(clk, rkclk->clk_name, NULL);
- } else {
- clk_err("%s: clk(\"%s\") register clk error\n", __func__,
- rkclk->clk_name);
- }
-
- return 0;
-}
-
-static int _rkclk_add_provider(struct device_node *np)
-{
- int i, cnt, ret = 0;
- const char *name = NULL;
- struct clk *clk = NULL;
- struct clk_onecell_data *clk_data = NULL;
-
-
- clk_debug("\n");
-
- cnt = of_property_count_strings(np, "clock-output-names");
- if (cnt < 0) {
- clk_err("%s: error in clock-output-names, cnt=%d\n", __func__,
- cnt);
- return -EINVAL;
- }
-
- clk_debug("%s: cnt = %d\n", __func__, cnt);
-
- if (cnt == 0) {
- clk_debug("%s: nothing to do\n", __func__);
- return 0;
- }
-
- if (cnt == 1) {
- of_property_read_string(np, "clock-output-names", &name);
- clk_debug("clock-output-names = %s\n", name);
-
- clk = clk_get_sys(NULL, name);
- if (IS_ERR(clk)) {
- clk_err("%s: fail to get %s\n", __func__, name);
- return -EINVAL;
- }
-
- ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
- clk_debug("use of_clk_src_simple_get, ret=%d\n", ret);
- } else {
- clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
- if (!clk_data)
- return -ENOMEM;
-
- clk_data->clks = kzalloc(cnt * sizeof(struct clk *), GFP_KERNEL);
- if (!clk_data->clks) {
- kfree(clk_data);
- return -ENOMEM;
- }
-
- clk_data->clk_num = cnt;
-
- for (i=0; i<cnt; i++) {
- of_property_read_string_index(np, "clock-output-names",
- i, &name);
- clk_debug("clock-output-names[%d]=%s\n", i, name);
-
- /* ignore empty slots */
- if (!strcmp("reserved", name))
- continue;
-
- clk = clk_get_sys(NULL, name);
- if (IS_ERR(clk)) {
- clk_err("%s: fail to get %s\n", __func__, name);
- continue;
- }
-
- clk_data->clks[i] = clk;
- }
-
- ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
- clk_debug("use of_clk_src_onecell_get, ret=%d\n", ret);
- }
-
- return ret;
-}
-
-static void rkclk_add_provider(struct device_node *np)
-{
- struct device_node *node, *node_reg, *node_tmp, *node_prd;
- const char *compatible;
-
-
- for_each_available_child_of_node(np, node) {
- of_property_read_string(node, "compatible", &compatible);
-
- if (strcmp(compatible, "rockchip,rk-fixed-rate-cons") == 0) {
- for_each_available_child_of_node(node, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else if (strcmp(compatible, "rockchip,rk-fixed-factor-cons") == 0) {
- for_each_available_child_of_node(node, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else if (strcmp(compatible, "rockchip,rk-clock-regs") == 0) {
- for_each_available_child_of_node(node, node_reg) {
- of_property_read_string(node_reg, "compatible", &compatible);
-
- if (strcmp(compatible, "rockchip,rk-pll-cons") == 0) {
- for_each_available_child_of_node(node_reg, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else if (strcmp(compatible, "rockchip,rk-sel-cons") == 0) {
- for_each_available_child_of_node(node_reg, node_tmp) {
- for_each_available_child_of_node(node_tmp,
- node_prd) {
- _rkclk_add_provider(node_prd);
- }
- }
- } else if (strcmp(compatible, "rockchip,rk-gate-cons") == 0) {
- for_each_available_child_of_node(node_reg, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else {
- clk_err("%s: unknown\n", __func__);
- }
- }
- } else if (strcmp(compatible, "rockchip,rk-pd-cons") == 0) {
- for_each_available_child_of_node(node, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else if (strcmp(compatible, "rockchip,rk-clock-special-regs") == 0) {
- for_each_available_child_of_node(node, node_prd) {
- _rkclk_add_provider(node_prd);
- }
- } else {
- clk_err("%s: unknown\n", __func__);
- }
- }
-
-}
-
-static void rkclk_cache_parents(struct rkclk *rkclk)
-{
- struct clk *clk, *parent;
- u8 num_parents;
- int i;
-
-
- clk = clk_get(NULL, rkclk->clk_name);
- if (IS_ERR(clk)) {
- clk_err("%s: %s clk_get error\n",
- __func__, rkclk->clk_name);
- return;
- } else {
- clk_debug("%s: %s clk_get success\n",
- __func__, __clk_get_name(clk));
- }
-
- num_parents = __clk_get_num_parents(clk);
- clk_debug("\t\tnum_parents=%d, parent=%s\n", num_parents,
- __clk_get_name(__clk_get_parent(clk)));
-
- for (i=0; i<num_parents; i++) {
- /* parent will be cached after this func is called */
- parent = clk_get_parent_by_index(clk, i);
- if (IS_ERR(parent)) {
- clk_err("fail to get parents[%d]=%s\n", i,
- clk->parent_names[i]);
- continue;
- } else {
- clk_debug("\t\tparents[%d]: %s\n", i,
- __clk_get_name(parent));
- }
- }
-}
-
-void rk_dump_cru(void)
-{
- printk(KERN_WARNING "CRU:\n");
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 32, 4, rk_cru_base,
- 0x420, false);
-}
-EXPORT_SYMBOL_GPL(rk_dump_cru);
-
-
-#ifdef RKCLK_DEBUG
-void rkclk_dump_info(struct rkclk *rkclk)
-{
- struct clk_mux *mux = NULL;
- struct clk_divider *div = NULL;
- struct clk_gate *gate = NULL;
- struct clk_pll *pll = NULL;
- struct clk_divider *frac = NULL;
- struct clk_fixed_rate *fixed_rate = NULL;
- struct clk_fixed_factor *fixed_factor = NULL;
- struct clk_pd *pd = NULL;
- int i;
-
-
- clk_debug("%s: clkname=%s, type=0x%x, flags=0x%x\n",
- __func__, (rkclk->clk_name)?(rkclk->clk_name):NULL,
- rkclk->clk_type, rkclk->flags);
-
- if (rkclk->mux_info && rkclk->mux_info->mux)
- mux = rkclk->mux_info->mux;
- if (rkclk->div_info && rkclk->div_info->div)
- div = rkclk->div_info->div;
- if (rkclk->pll_info && rkclk->pll_info->pll)
- pll = rkclk->pll_info->pll;
- if (rkclk->frac_info && rkclk->frac_info->frac)
- frac = rkclk->frac_info->frac;
- if (rkclk->gate_info && rkclk->gate_info->gate)
- gate = rkclk->gate_info->gate;
- if (rkclk->fixed_rate_info && rkclk->fixed_rate_info->fixed_rate)
- fixed_rate = rkclk->fixed_rate_info->fixed_rate;
- if (rkclk->fixed_factor_info && rkclk->fixed_factor_info->fixed_factor)
- fixed_factor = rkclk->fixed_factor_info->fixed_factor;
- if (rkclk->pd_info && rkclk->pd_info->pd)
- pd = rkclk->pd_info->pd;
-
-
- if (rkclk->mux_info) {
- clk_debug("\t\tmux_info: name=%s, clkops_idx=%u\n",
- rkclk->mux_info->clk_name,
- rkclk->mux_info->clkops_idx);
- for (i = 0; i < rkclk->mux_info->parent_num; i++)
- clk_debug("\t\t\tparent[%d]: %s\n", i,
- rkclk->mux_info->parent_names[i]);
- if (mux) {
- clk_debug("\t\tmux: reg=0x%x, mask=0x%x, shift=0x%x, "
- "mux_flags=0x%x\n", (u32)mux->reg,
- mux->mask, mux->shift, mux->flags);
- }
- }
-
- if (rkclk->pll_info) {
- clk_debug("\t\tpll_info: name=%s, parent=%s, clkops_idx=0x%x\n",
- rkclk->pll_info->clk_name,
- rkclk->pll_info->parent_name,
- rkclk->pll_info->clkops_idx);
- if (pll) {
- clk_debug("\t\tpll: reg=0x%x, width=0x%x, "
- "mode_offset=0x%x, mode_shift=%u, "
- "status_offset=0x%x, status_shift=%u, "
- "pll->flags=%u\n",
- (u32)pll->reg, pll->width,
- pll->mode_offset, pll->mode_shift,
- pll->status_offset, pll->status_shift,
- pll->flags);
- }
- }
-
- if (rkclk->div_info) {
- clk_debug("\t\tdiv_info: name=%s, div_type=0x%x, parent=%s, "
- "clkops_idx=%d\n",
- rkclk->div_info->clk_name,
- rkclk->div_info->div_type,
- rkclk->div_info->parent_name,
- rkclk->div_info->clkops_idx);
- if (div) {
- clk_debug("\t\tdiv: reg=0x%x, shift=0x%x, width=0x%x, "
- "div_flags=0x%x\n", (u32)div->reg,
- div->shift, div->width, div->flags);
- }
- }
-
- if (rkclk->frac_info) {
- clk_debug("\t\tfrac_info: name=%s, parent=%s, clkops_idx=%d\n",
- rkclk->frac_info->clk_name,
- rkclk->frac_info->parent_name,
- rkclk->frac_info->clkops_idx);
- if (frac) {
- clk_debug("\t\tfrac: reg=0x%x, shift=0x%x, width=0x%x, "
- "div_flags=0x%x\n", (u32)frac->reg,
- frac->shift, frac->width, frac->flags);
- }
- }
-
- if (rkclk->gate_info) {
- clk_debug("\t\tgate_info: name=%s, parent=%s\n",
- rkclk->gate_info->clk_name,
- rkclk->gate_info->parent_name);
- if (gate) {
- clk_debug("\t\tgate: reg=0x%x, bit_idx=%d, "
- "gate_flags=0x%x\n", (u32)gate->reg,
- gate->bit_idx, gate->flags);
- }
- }
-
- if (rkclk->fixed_rate_info) {
- clk_debug("\t\tfixed_rate_info: name=%s\n",
- rkclk->fixed_rate_info->clk_name);
- if (fixed_rate) {
- clk_debug("\t\tfixed_rate=%lu, fixed_rate_flags=0x%x\n",
- fixed_rate->fixed_rate, fixed_rate->flags);
- }
- }
-
- if (rkclk->fixed_factor_info) {
- clk_debug("\t\tfixed_factor_info: name=%s, parent=%s\n",
- rkclk->fixed_factor_info->clk_name,
- rkclk->fixed_factor_info->parent_name);
- if (fixed_factor) {
- clk_debug("\t\tfixed_factor: mult=%u, div=%u\n",
- fixed_factor->mult, fixed_factor->div);
- }
- }
-
- if (rkclk->pd_info) {
- clk_debug("\t\tpd_info: name=%s, parent=%s\n",
- rkclk->pd_info->clk_name,
- rkclk->pd_info->parent_name);
- if (pd) {
- clk_debug("\t\tpd: id=%u\n", pd->id);
- }
- }
-}
-#else
-void rkclk_dump_info(struct rkclk *rkclk) {}
-#endif
-
-
-#ifdef RKCLK_TEST
-char* pd_table[] = {
- "pd_gpu",
- "pd_video",
- "pd_vio",
- "pd_hevc",
-};
-
-void rk_clk_pd_test(void)
-{
- struct clk *clk;
- bool state;
- int j, ret;
-
-
- for (j = 0; j < ARRAY_SIZE(pd_table); j++) {
-
- clk = clk_get(NULL, pd_table[j]);
-
- ret = clk_prepare_enable(clk);
- printk("%s: clk_prepare_enable %s, ret=%d\n", __func__,
- __clk_get_name(clk), ret);
-
- state = __clk_is_enabled(clk);
- printk("%s: clk_pd %s is %s\n", __func__, __clk_get_name(clk),
- state ? "enable" : "disable");
-
- clk_disable_unprepare(clk);
- printk("%s: clk_disable_unprepare %s\n", __func__,
- __clk_get_name(clk));
-
- state = __clk_is_enabled(clk);
- printk("%s: clk_pd %s is %s\n", __func__, __clk_get_name(clk),
- state ? "enable" : "disable");
-
- printk("\n");
- }
-}
-
-struct test_table {
- const char *name;
- u32 rate;
-};
-
-struct test_table t_table[] = {
- {.name = "clk_gpu", .rate = 297000000},
- {.name = "dclk_lcdc0", .rate = 100000000},
- {.name = "aclk_lcdc0", .rate = 297000000},
-
- {.name = "clk_sdmmc", .rate = 50000000},
- {.name = "clk_emmc", .rate = 50000000},
- {.name = "clk_sdio", .rate = 50000000},
-
- {.name = "clk_i2s_div", .rate = 300000000},
- {.name = "clk_i2s_frac",.rate = 22579200},
- {.name = "clk_i2s", .rate = 11289600},
- {.name = "clk_spdif", .rate = 11289600},
-
- {.name = "cif_out_pll", .rate = 48000000},
- {.name = "clk_cif0", .rate = 12000000},
-
- {.name = "clk_uart0", .rate = 12288000},
- {.name = "clk_uart1", .rate = 48000000},
- {.name = "clk_hsadc", .rate = 12288000},
- {.name = "clk_mac", .rate = 50000000},
-
-// {.name = "clk_apll", .rate = 500000000},
-// {.name = "clk_dpll", .rate = 400000000},
- {.name = "clk_cpll", .rate = 600000000},
- {.name = "clk_gpll", .rate = 800000000},
-
- {.name = "clk_core", .rate = 100000000},
- {.name = "clk_core", .rate = 24000000},
- {.name = "clk_core", .rate = 500000000},
-};
-
-
-void rk_clk_test(void)
-{
- const char *clk_name;
- struct clk *clk;
- unsigned long rate=0, recalc_rate=0, round_rate=0, get_rate=0;
- u32 j = 0;
- int ret;
-
- for (j = 0; j < ARRAY_SIZE(t_table); j++) {
- clk_debug(">>>>>>test %u\n", j);
-
- clk_name = t_table[j].name;
- rate = t_table[j].rate;
-
- clk = clk_get(NULL, clk_name);
- if (IS_ERR(clk)) {
- clk_err("%s: clk(\"%s\") \tclk_get error\n",
- __func__, clk_name);
- } else
- clk_debug("%s: clk(\"%s\") \tclk_get success\n",
- __func__, clk_name);
-
- /* TEST: clk_round_rate */
- round_rate = clk_round_rate(clk, rate);
- clk_debug("%s: clk(\"%s\") \tclk_round_rate from %lu to %lu\n",
- __func__, clk_name, rate, round_rate);
-
- /* TEST: clk_set_rate */
- ret = clk_set_rate(clk, rate);
- if (ret) {
- clk_err("%s: clk(\"%s\") \tclk_set_rate error, ret=%d\n",
- __func__, clk_name, ret);
- } else {
- clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n",
- __func__, clk_name);
- }
-
- /* TEST: recalc_rate\clk_get_rate */
- if (clk->ops->recalc_rate) {
- recalc_rate = clk->ops->recalc_rate(clk->hw,
- clk->parent->rate);
- clk_debug("%s: clk(\"%s\") \tclk_recalc_rate %lu\n",
- __func__, clk_name, recalc_rate);
- } else {
- clk_debug("%s: clk(\"%s\") have no recalc ops\n",
- __func__, clk_name);
- get_rate = clk_get_rate(clk);
- clk_debug("%s: clk(\"%s\") \tclk_get_rate %lu\n",
- __func__, clk_name, get_rate);
- }
-
- rk_dump_cru();
- }
-
- rk_clk_pd_test();
-}
-#else
-void rk_clk_test(void) {}
-#endif
-EXPORT_SYMBOL_GPL(rk_clk_test);
-
-static int rkclk_panic(struct notifier_block *this, unsigned long ev, void *ptr)
-{
- rk_dump_cru();
- return NOTIFY_DONE;
-}
-
-static struct notifier_block rkclk_panic_block = {
- .notifier_call = rkclk_panic,
-};
-
-void __init rkclk_init_clks(struct device_node *node);
-
-static struct device_node * clk_root_node=NULL;
-static void __init rk_clk_tree_init(struct device_node *np)
-{
- struct device_node *node, *node_init;
- struct rkclk *rkclk;
- const char *compatible;
-
- printk("%s start!\n", __func__);
-
- node_init = of_find_node_by_name(NULL, "clocks-init");
- if (!node_init) {
- clk_err("%s: can not get clocks-init node\n", __func__);
- return;
- }
-
- clk_root_node = of_find_node_by_name(NULL, "clock_regs");
- rk_cru_base = of_iomap(clk_root_node, 0);
- if (!rk_cru_base) {
- clk_err("%s: could not map cru region\n", __func__);
- return;
- }
-
- node = of_parse_phandle(np, "rockchip,grf", 0);
- if (node)
- rk_grf_base = of_iomap(node, 0);
-#ifdef CONFIG_ARM
- if (!rk_grf_base)
- rk_grf_base = RK_GRF_VIRT;
-#endif
-
- for_each_available_child_of_node(np, node) {
- clk_debug("\n");
- of_property_read_string(node, "compatible",
- &compatible);
-
- if (strcmp(compatible, "rockchip,rk-fixed-rate-cons") == 0) {
- if (rkclk_init_fixed_rate(node) != 0) {
- clk_err("%s: init fixed_rate err\n", __func__);
- return;
- }
- } else if (strcmp(compatible, "rockchip,rk-fixed-factor-cons") == 0) {
- if (rkclk_init_fixed_factor(node) != 0) {
- clk_err("%s: init fixed_factor err\n", __func__);
- return;
- }
- } else if (strcmp(compatible, "rockchip,rk-clock-regs") == 0) {
- if (rkclk_init_regcon(node) != 0) {
- clk_err("%s: init reg cons err\n", __func__);
- return;
- }
- } else if (strcmp(compatible, "rockchip,rk-pd-cons") == 0) {
- if (rkclk_init_pd(node) != 0) {
- clk_err("%s: init pd err\n", __func__);
- return;
- }
- } else if (strcmp(compatible, "rockchip,rk-clock-special-regs") == 0) {
- if (rkclk_init_special_regs(node) != 0) {
- clk_err("%s: init special reg err\n", __func__);
- return;
- }
- } else {
- clk_err("%s: unknown\n", __func__);
- }
- }
-
- list_for_each_entry(rkclk, &rk_clks, node) {
- clk_debug("\n");
- rkclk_dump_info(rkclk);
- clk_debug("\n");
- rkclk_register(rkclk);
- }
-
- rkclk_add_provider(np);
-
- /* fill clock parents cache after all clocks have been registered */
- list_for_each_entry(rkclk, &rk_clks, node) {
- clk_debug("\n");
- rkclk_cache_parents(rkclk);
- }
-
- rkclk_init_clks(node_init);
-
- rk_clk_test();
-
- atomic_notifier_chain_register(&panic_notifier_list, &rkclk_panic_block);
-}
-CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clocks", rk_clk_tree_init);
-
-
-/***************************** rockchip clks init******************************/
-const char *of_clk_init_rate_get_info(struct device_node *np,
- int index,u32 *rate)
-{
- struct of_phandle_args clkspec;
- const char *clk_name;
- int rc;
-
- if (index < 0)
- return NULL;
-
- rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate",
- "#clock-init-cells", index, &clkspec);
- if (rc)
- return NULL;
-
- if (of_property_read_string_index(clkspec.np, "clock-output-names", 0,
- &clk_name) < 0)
- return NULL;
-
- *rate= clkspec.args[0];
-
- of_node_put(clkspec.np);
- return clk_name;
-}
-
-const char *of_clk_init_parent_get_info(struct device_node *np, int index,
- const char **clk_child_name)
-{
- struct of_phandle_args clkspec;
- const char *clk_name;
- int rc;
- phandle phandle;
- struct device_node *node = NULL;
-
- if (index < 0)
- return NULL;
-
- rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent",
- "#clock-init-cells", index, &clkspec);
- if (rc)
- return NULL;
-
- if (of_property_read_string_index(clkspec.np, "clock-output-names", 0,
- &clk_name) < 0)
- return NULL;
-
-
- phandle = clkspec.args[0];
-
- of_node_put(clkspec.np);
-
- if (phandle) {
-
- node = of_find_node_by_phandle(phandle);
- if (!node) {
- return NULL;
- }
-
- if (of_property_read_string_index(node, "clock-output-names", 0,
- clk_child_name) < 0)
- return NULL;
-
- of_node_put(node);//???
- node=NULL;
- }
- else
- return NULL;
-
- return clk_name;
-}
-
-static int __init rkclk_init_enable(void)
-{
- struct device_node *node;
- int cnt, i, ret = 0;
- const char *clk_name;
- struct clk *clk;
-
-
- node = of_find_node_by_name(NULL, "clocks-enable");
- if (!node) {
- clk_err("%s: can not get clocks-enable node\n", __func__);
- return -EINVAL;
- }
-
- cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
- if (cnt < 0) {
- return -EINVAL;
- } else {
- clk_debug("%s: cnt = %d\n", __func__, cnt);
- }
-
- for (i = 0; i < cnt ; i++) {
- clk_name = of_clk_get_parent_name(node, i);
- clk = clk_get(NULL, clk_name);
- if (IS_ERR_OR_NULL(clk)) {
- clk_err("%s: fail to get %s\n", __func__, clk_name);
- return -EINVAL;
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- clk_err("%s: fail to prepare_enable %s\n", __func__,
- clk_name);
- return ret;
- } else {
- clk_debug("%s: prepare_enable %s OK\n", __func__,
- clk_name);
- }
- }
-
- return ret;
-}
-
-static int uboot_logo_on = 0;
-
-static void __init rk_get_uboot_display_flag(void)
-{
- struct device_node *node;
-
- node = of_find_node_by_name(NULL, "fb");
- if (node)
- of_property_read_u32(node, "rockchip,uboot-logo-on", &uboot_logo_on);
-
- printk("%s: uboot_logo_on = %d\n", __FUNCTION__, uboot_logo_on);
-}
-
-static const char *of_clk_uboot_has_init_get_name(struct device_node *np, int index)
-{
- struct of_phandle_args clkspec;
- const char *clk_name;
- int rc;
-
- if (index < 0)
- return NULL;
-
- rc = of_parse_phandle_with_args(np, "rockchip,clocks-uboot-has-init",
- "#clock-cells", index, &clkspec);
- if (rc)
- return NULL;
-
- if (of_property_read_string_index(clkspec.np, "clock-output-names",
- clkspec.args_count ? clkspec.args[0] : 0,
- &clk_name) < 0)
- clk_name = NULL;
-
- of_node_put(clkspec.np);
- return clk_name;
-}
-
-/* If clk has been inited, return 1; else return 0. */
-static int rkclk_uboot_has_init(struct device_node *np, const char *clk_name)
-{
- int cnt, i;
- const char *name;
-
-
- if ((!np) || (!clk_name))
- return 0;
-
- cnt = of_count_phandle_with_args(np, "rockchip,clocks-uboot-has-init",
- "#clock-cells");
- if (cnt < 0)
- return 0;
-
- for (i = 0; i < cnt ; i++) {
- name = of_clk_uboot_has_init_get_name(np, i);
- if (name && (!strcmp(clk_name, name)))
- return 1;
- }
-
- return 0;
-}
-
-void __init rkclk_init_clks(struct device_node *np)
-{
- //struct device_node *np;
- int i,cnt_parent,cnt_rate;
- u32 clk_rate;
- //int ret;
- struct clk *clk_p, *clk_c;
- const char *clk_name, *clk_parent_name;
-
-
- rk_get_uboot_display_flag();
-
- cnt_parent = of_count_phandle_with_args(np,
- "rockchip,clocks-init-parent", "#clock-init-cells");
-
- printk("%s: cnt_parent = %d\n",__FUNCTION__,cnt_parent);
-
- for (i = 0; i < cnt_parent; i++) {
- clk_parent_name=NULL;
- clk_name=of_clk_init_parent_get_info(np, i,&clk_parent_name);
-
- if(clk_name==NULL||clk_parent_name==NULL)
- continue;
-
- clk_c=clk_get(NULL,clk_name);
- clk_p=clk_get(NULL,clk_parent_name);
-
- if(IS_ERR(clk_c)||IS_ERR(clk_p))
- continue;
-
- clk_set_parent(clk_c, clk_p);
-
- clk_debug("%s: set %s parent = %s\n", __FUNCTION__, clk_name,
- clk_parent_name);
- }
-
- cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate",
- "#clock-init-cells");
-
- printk("%s: cnt_rate = %d\n",__FUNCTION__,cnt_rate);
-
- for (i = 0; i < cnt_rate; i++) {
- clk_name=of_clk_init_rate_get_info(np, i, &clk_rate);
-
- if (clk_name==NULL)
- continue;
-
- if (uboot_logo_on && rkclk_uboot_has_init(np, clk_name)) {
- printk("%s: %s has been inited in uboot, ingored\n",
- __FUNCTION__, clk_name);
- continue;
- }
-
- clk_c = clk_get(NULL, clk_name);
-
- if(IS_ERR(clk_c))
- continue;
-
- if((clk_rate<1*MHZ)||(clk_rate>2000*MHZ))
- clk_err("warning: clk_rate < 1*MHZ or > 2000*MHZ\n");
-
- clk_set_rate(clk_c, clk_rate);
-
- clk_debug("%s: set %s rate = %u\n", __FUNCTION__, clk_name,
- clk_rate);
- }
-
- rkclk_init_enable();
-
-}
-
-u32 clk_suspend_clkgt_info_get(u32 *clk_ungt_msk,u32 *clk_ungt_msk_last,u32 buf_cnt)
-{
-
- struct device_node *node,*node_gt;
- u32 temp_val[2];
- int gt_cnt;
- int ret;
- void __iomem *cru_base,*gt_base, *reg_n, *reg_p;
-
- gt_cnt=0;
- cru_base= of_iomap(clk_root_node, 0);
-
- for_each_available_child_of_node(clk_root_node, node) {
-
- if (of_device_is_compatible(node,"rockchip,rk-gate-cons"))
- {
-
- for_each_available_child_of_node(node, node_gt) {
-
- if(gt_cnt>=buf_cnt)
- {
- clk_err("%s:save buf is overflow\n",__FUNCTION__);
- return 0;
- }
-
- ret = of_property_read_u32_array(node_gt,"rockchip,suspend-clkgating-setting",temp_val,2);
- if(!ret)
- {
- clk_ungt_msk[gt_cnt]=temp_val[0];
- clk_ungt_msk_last[gt_cnt]=temp_val[1];
- }
- else
- {
- clk_ungt_msk[gt_cnt]=0xffff;
- clk_ungt_msk_last[gt_cnt]=0xffff;
- }
-
- if(gt_cnt==0)
- {
- gt_base=of_iomap(node_gt, 0);
- reg_p=gt_base;
- reg_n=gt_base;
- }
- else
- {
- reg_n=of_iomap(node_gt, 0);
-
- if(((long)reg_n-(long)reg_p)!=4)
- {
- printk("%s: gt reg is not continue\n",__FUNCTION__);
- return 0;
- }
- reg_p=reg_n;
- }
-
- clk_debug("%s:gt%d,reg=%p,val=(%x,%x)\n",__FUNCTION__,gt_cnt, reg_n,
- clk_ungt_msk[gt_cnt], clk_ungt_msk_last[gt_cnt]);
-
- gt_cnt++;
-
- }
-
- break;
- }
- }
-
- if(gt_cnt!=buf_cnt)
- {
- clk_err("%s:save buf is not Enough\n",__FUNCTION__);
- return 0;
- }
- clk_debug("%s:crubase=%x,gtbase=%x\n",__FUNCTION__,cru_base,gt_base);
-
- return (u32)(gt_base-cru_base);
-
-}
-
-
-
-
+++ /dev/null
-/*
- * Power domain support for Rockchip RK3368
- *
- * Copyright (C) 2014-2015 ROCKCHIP, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/rockchip/pmu.h>
-#include <linux/rockchip/cru.h>
-#include <linux/rockchip/cpu_axi.h>
-
-#include "clk-ops.h"
-
-static void __iomem *rk_pmu_base;
-
-static u32 pmu_readl(u32 offset)
-{
- return readl_relaxed(rk_pmu_base + (offset));
-}
-
-static void pmu_writel(u32 val, u32 offset)
-{
- writel_relaxed(val, rk_pmu_base + (offset));
- dsb(sy);
-}
-
-static const u8 pmu_pd_map[] = {
- [PD_PERI] = 13,
- [PD_VIDEO] = 14,
- [PD_VIO] = 15,
- [PD_GPU_0] = 16,
- [PD_GPU_1] = 17,
-};
-
-static const u8 pmu_st_map[] = {
- [PD_PERI] = 12,
- [PD_VIDEO] = 13,
- [PD_VIO] = 14,
- [PD_GPU_0] = 15,
- [PD_GPU_1] = 16,
-};
-
-static bool rk3368_pmu_power_domain_is_on(enum pmu_power_domain pd)
-{
- /* 1'b0: power on, 1'b1: power off */
- return !(pmu_readl(RK3368_PMU_PWRDN_ST) & BIT(pmu_st_map[pd]));
-}
-
-static DEFINE_SPINLOCK(pmu_idle_lock);
-
-static const u8 pmu_idle_map[] = {
- [IDLE_REQ_GPU] = 2,
- [IDLE_REQ_BUS] = 4,
- [IDLE_REQ_PERI] = 6,
- [IDLE_REQ_VIDEO] = 7,
- [IDLE_REQ_VIO] = 8,
-};
-
-static int rk3368_pmu_set_idle_request(enum pmu_idle_req req, bool idle)
-{
- u32 bit = pmu_idle_map[req];
- u32 idle_mask = BIT(bit) | BIT(bit + 16);
- u32 idle_target = (idle << bit) | (idle << (bit + 16));
- u32 mask = BIT(bit);
- u32 val;
- unsigned long flags;
-
- spin_lock_irqsave(&pmu_idle_lock, flags);
-
- val = pmu_readl(RK3368_PMU_IDLE_REQ);
- if (idle)
- val |= mask;
- else
- val &= ~mask;
- pmu_writel(val, RK3368_PMU_IDLE_REQ);
- dsb(sy);
-
- while ((pmu_readl(RK3368_PMU_IDLE_ST) & idle_mask) != idle_target)
- ;
-
- spin_unlock_irqrestore(&pmu_idle_lock, flags);
-
- return 0;
-}
-
-static DEFINE_SPINLOCK(pmu_pd_lock);
-
-static noinline void rk3368_do_pmu_set_power_domain
- (enum pmu_power_domain domain, bool on)
-{
- u8 pd = pmu_pd_map[domain];
- u32 val = pmu_readl(RK3368_PMU_PWRDN_CON);
-
- if (on)
- val &= ~BIT(pd);
- else
- val |= BIT(pd);
-
- pmu_writel(val, RK3368_PMU_PWRDN_CON);
- dsb(sy);
-
- while ((pmu_readl(RK3368_PMU_PWRDN_ST) & BIT(pmu_st_map[domain])) == on)
- ;
-}
-
-/* PD_VIO */
-static void __iomem *iep_qos_base;
-static u32 iep_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *isp_r0_qos_base;
-static u32 isp_r0_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *isp_r1_qos_base;
-static u32 isp_r1_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *isp_w0_qos_base;
-static u32 isp_w0_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *isp_w1_qos_base;
-static u32 isp_w1_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *vip_qos_base;
-static u32 vip_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *vop_qos_base;
-static u32 vop_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *rga_r_qos_base;
-static u32 rga_r_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *rga_w_qos_base;
-static u32 rga_w_qos[CPU_AXI_QOS_NUM_REGS];
-/* PD_VIDEO */
-static void __iomem *hevc_r_qos_base;
-static u32 hevc_r_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *vpu_r_qos_base;
-static u32 vpu_r_qos[CPU_AXI_QOS_NUM_REGS];
-static void __iomem *vpu_w_qos_base;
-static u32 vpu_w_qos[CPU_AXI_QOS_NUM_REGS];
-/* PD_GPU_0 */
-static void __iomem *gpu_qos_base;
-static u32 gpu_qos[CPU_AXI_QOS_NUM_REGS];
-/* PD_PERI */
-static void __iomem *peri_qos_base;
-static u32 peri_qos[CPU_AXI_QOS_NUM_REGS];
-
-#define PD_SAVE_QOS(name) CPU_AXI_SAVE_QOS(name##_qos, name##_qos_base)
-#define PD_RESTORE_QOS(name) CPU_AXI_RESTORE_QOS(name##_qos, name##_qos_base)
-
-static int rk3368_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&pmu_pd_lock, flags);
-
- if (rk3368_pmu_power_domain_is_on(pd) == on)
- goto out;
-
- if (!on) {
- /* if power down, idle request to NIU first */
- if (pd == PD_VIO) {
- PD_SAVE_QOS(iep);
- PD_SAVE_QOS(isp_r0);
- PD_SAVE_QOS(isp_r1);
- PD_SAVE_QOS(isp_w0);
- PD_SAVE_QOS(isp_w1);
- PD_SAVE_QOS(vip);
- PD_SAVE_QOS(vop);
- PD_SAVE_QOS(rga_r);
- PD_SAVE_QOS(rga_w);
- rk3368_pmu_set_idle_request(IDLE_REQ_VIO, true);
- } else if (pd == PD_VIDEO) {
- PD_SAVE_QOS(hevc_r);
- PD_SAVE_QOS(vpu_r);
- PD_SAVE_QOS(vpu_w);
- rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, true);
- } else if (pd == PD_GPU_0) {
- PD_SAVE_QOS(gpu);
- rk3368_pmu_set_idle_request(IDLE_REQ_GPU, true);
- } else if (pd == PD_PERI) {
- PD_SAVE_QOS(peri);
- rk3368_pmu_set_idle_request(IDLE_REQ_PERI, true);
- }
- }
-
- rk3368_do_pmu_set_power_domain(pd, on);
-
- if (on) {
- /* if power up, idle request release to NIU */
- if (pd == PD_VIO) {
- rk3368_pmu_set_idle_request(IDLE_REQ_VIO, false);
- PD_RESTORE_QOS(iep);
- PD_RESTORE_QOS(isp_r0);
- PD_RESTORE_QOS(isp_r1);
- PD_RESTORE_QOS(isp_w0);
- PD_RESTORE_QOS(isp_w1);
- PD_RESTORE_QOS(vip);
- PD_RESTORE_QOS(vop);
- PD_RESTORE_QOS(rga_r);
- PD_RESTORE_QOS(rga_w);
- } else if (pd == PD_VIDEO) {
- rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, false);
- PD_RESTORE_QOS(hevc_r);
- PD_RESTORE_QOS(vpu_r);
- PD_RESTORE_QOS(vpu_w);
- } else if (pd == PD_GPU_0) {
- rk3368_pmu_set_idle_request(IDLE_REQ_GPU, false);
- PD_RESTORE_QOS(gpu);
- } else if (pd == PD_PERI) {
- rk3368_pmu_set_idle_request(IDLE_REQ_PERI, false);
- PD_RESTORE_QOS(peri);
- }
- }
-
-out:
- spin_unlock_irqrestore(&pmu_pd_lock, flags);
- return 0;
-}
-
-static int rk3368_sys_set_power_domain(enum pmu_power_domain pd, bool on)
-{
- u32 clks_ungating[RK3368_CRU_CLKGATES_CON_CNT];
- u32 clks_save[RK3368_CRU_CLKGATES_CON_CNT];
- u32 i, ret;
-
- for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++) {
- clks_save[i] = cru_readl(RK3368_CRU_CLKGATES_CON(i));
- clks_ungating[i] = 0;
- }
-
- for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++)
- cru_writel(0xffff0000, RK3368_CRU_CLKGATES_CON(i));
-
- ret = rk3368_pmu_set_power_domain(pd, on);
-
- for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++)
- cru_writel(clks_save[i] | 0xffff0000,
- RK3368_CRU_CLKGATES_CON(i));
-
- return ret;
-}
-
-static int __init rk3368_init_rockchip_pmu_ops(void)
-{
- struct device_node *node, *gp, *cp;
-
- node = of_find_compatible_node(NULL, NULL, "rockchip,rk3368-pmu");
- if (!node) {
- pr_err("%s: could not find pmu dt node\n", __func__);
- return -ENODEV;
- }
-
- rk_pmu_base = of_iomap(node, 0);
- if (!rk_pmu_base) {
- pr_err("%s: could not map pmu registers\n", __func__);
- return -ENXIO;
- }
-
- node = of_find_compatible_node(NULL, NULL, "rockchip,cpu_axi_bus");
- if (!node)
- return -ENODEV;
-
-#define MAP(name) \
- do { \
- cp = of_get_child_by_name(gp, #name); \
- if (cp) \
- name##_qos_base = of_iomap(cp, 0); \
- if (!name##_qos_base) \
- pr_err("%s: could not map qos %s register\n", \
- __func__, #name); \
- } while (0)
-
- gp = of_get_child_by_name(node, "qos");
- if (gp) {
- MAP(peri);
- MAP(iep);
- MAP(isp_r0);
- MAP(isp_r1);
- MAP(isp_w0);
- MAP(isp_w1);
- MAP(vip);
- MAP(vop);
- MAP(rga_r);
- MAP(rga_w);
- MAP(hevc_r);
- MAP(vpu_r);
- MAP(vpu_w);
- MAP(gpu);
- }
-
-#undef MAP
-
- rockchip_pmu_ops.set_power_domain = rk3368_sys_set_power_domain;
- rockchip_pmu_ops.power_domain_is_on = rk3368_pmu_power_domain_is_on;
-
- return 0;
-}
-
-arch_initcall(rk3368_init_rockchip_pmu_ops);
+++ /dev/null
-#ifndef __CPU_AXI_H
-#define __CPU_AXI_H
-
-#define CPU_AXI_QOS_PRIORITY 0x08
-#define CPU_AXI_QOS_MODE 0x0c
-#define CPU_AXI_QOS_BANDWIDTH 0x10
-#define CPU_AXI_QOS_SATURATION 0x14
-#define CPU_AXI_QOS_EXTCONTROL 0x18
-
-#define CPU_AXI_QOS_MODE_NONE 0
-#define CPU_AXI_QOS_MODE_FIXED 1
-#define CPU_AXI_QOS_MODE_LIMITER 2
-#define CPU_AXI_QOS_MODE_REGULATOR 3
-
-#define CPU_AXI_QOS_PRIORITY_LEVEL(h, l) \
- ((((h) & 3) << 8) | (((h) & 3) << 2) | ((l) & 3))
-#define CPU_AXI_SET_QOS_PRIORITY(h, l, base) \
- writel_relaxed(CPU_AXI_QOS_PRIORITY_LEVEL(h, l), base + CPU_AXI_QOS_PRIORITY)
-
-#define CPU_AXI_SET_QOS_MODE(mode, base) \
- writel_relaxed((mode) & 3, base + CPU_AXI_QOS_MODE)
-
-#define CPU_AXI_SET_QOS_BANDWIDTH(bandwidth, base) \
- writel_relaxed((bandwidth) & 0x7ff, base + CPU_AXI_QOS_BANDWIDTH)
-
-#define CPU_AXI_SET_QOS_SATURATION(saturation, base) \
- writel_relaxed((saturation) & 0x3ff, base + CPU_AXI_QOS_SATURATION)
-
-#define CPU_AXI_SET_QOS_EXTCONTROL(extcontrol, base) \
- writel_relaxed((extcontrol) & 7, base + CPU_AXI_QOS_EXTCONTROL)
-
-#define CPU_AXI_QOS_NUM_REGS 5
-#define CPU_AXI_SAVE_QOS(array, base) do { \
- array[0] = readl_relaxed(base + CPU_AXI_QOS_PRIORITY); \
- array[1] = readl_relaxed(base + CPU_AXI_QOS_MODE); \
- array[2] = readl_relaxed(base + CPU_AXI_QOS_BANDWIDTH); \
- array[3] = readl_relaxed(base + CPU_AXI_QOS_SATURATION); \
- array[4] = readl_relaxed(base + CPU_AXI_QOS_EXTCONTROL); \
-} while (0)
-#define CPU_AXI_RESTORE_QOS(array, base) do { \
- writel_relaxed(array[0], base + CPU_AXI_QOS_PRIORITY); \
- writel_relaxed(array[1], base + CPU_AXI_QOS_MODE); \
- writel_relaxed(array[2], base + CPU_AXI_QOS_BANDWIDTH); \
- writel_relaxed(array[3], base + CPU_AXI_QOS_SATURATION); \
- writel_relaxed(array[4], base + CPU_AXI_QOS_EXTCONTROL); \
-} while (0)
-
-#define RK3188_CPU_AXI_DMAC_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x1000)
-#define RK3188_CPU_AXI_CPU0_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x2000)
-#define RK3188_CPU_AXI_CPU1R_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x2080)
-#define RK3188_CPU_AXI_CPU1W_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x2100)
-#define RK3188_CPU_AXI_PERI_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x4000)
-#define RK3188_CPU_AXI_GPU_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x5000)
-#define RK3188_CPU_AXI_VPU_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x6000)
-#define RK3188_CPU_AXI_LCDC0_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7000)
-#define RK3188_CPU_AXI_CIF0_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7080)
-#define RK3188_CPU_AXI_IPP_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7100)
-#define RK3188_CPU_AXI_LCDC1_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7180)
-#define RK3188_CPU_AXI_CIF1_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7200)
-#define RK3188_CPU_AXI_RGA_QOS_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7280)
-
-/* service core */
-#define RK3288_SERVICE_CORE_VIRT RK_CPU_AXI_BUS_VIRT
-#define RK3288_CPU_AXI_CPUM_R_QOS_VIRT (RK3288_SERVICE_CORE_VIRT + 0x80)
-#define RK3288_CPU_AXI_CPUM_W_QOS_VIRT (RK3288_SERVICE_CORE_VIRT + 0x100)
-#define RK3288_CPU_AXI_CPUP_QOS_VIRT (RK3288_SERVICE_CORE_VIRT + 0x0)
-/* service dmac */
-#define RK3288_SERVICE_DMAC_VIRT (RK3288_SERVICE_CORE_VIRT + RK3288_SERVICE_CORE_SIZE)
-#define RK3288_CPU_AXI_BUS_DMAC_QOS_VIRT (RK3288_SERVICE_DMAC_VIRT + 0x0)
-#define RK3288_CPU_AXI_CCP_QOS_VIRT (RK3288_SERVICE_DMAC_VIRT + 0x180)
-#define RK3288_CPU_AXI_CRYPTO_QOS_VIRT (RK3288_SERVICE_DMAC_VIRT + 0x100)
-#define RK3288_CPU_AXI_CCS_QOS_VIRT (RK3288_SERVICE_DMAC_VIRT + 0x200)
-#define RK3288_CPU_AXI_HOST_QOS_VIRT (RK3288_SERVICE_DMAC_VIRT + 0x80)
-/* service gpu */
-#define RK3288_SERVICE_GPU_VIRT (RK3288_SERVICE_DMAC_VIRT + RK3288_SERVICE_DMAC_SIZE)
-#define RK3288_CPU_AXI_GPU_R_QOS_VIRT (RK3288_SERVICE_GPU_VIRT + 0x0)
-#define RK3288_CPU_AXI_GPU_W_QOS_VIRT (RK3288_SERVICE_GPU_VIRT + 0x80)
-/* service peri */
-#define RK3288_SERVICE_PERI_VIRT (RK3288_SERVICE_GPU_VIRT + RK3288_SERVICE_GPU_SIZE)
-#define RK3288_CPU_AXI_PERI_QOS_VIRT (RK3288_SERVICE_PERI_VIRT + 0x0)
-/* service bus */
-#define RK3288_SERVICE_BUS_VIRT (RK3288_SERVICE_PERI_VIRT + RK3288_SERVICE_PERI_SIZE)
-/* service vio */
-#define RK3288_SERVICE_VIO_VIRT (RK3288_SERVICE_BUS_VIRT + RK3288_SERVICE_BUS_SIZE)
-#define RK3288_CPU_AXI_VIO0_IEP_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x500)
-#define RK3288_CPU_AXI_VIO0_VIP_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x480)
-#define RK3288_CPU_AXI_VIO0_VOP_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x400)
-#define RK3288_CPU_AXI_VIO1_ISP_R_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x900)
-#define RK3288_CPU_AXI_VIO1_ISP_W0_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x100)
-#define RK3288_CPU_AXI_VIO1_ISP_W1_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x180)
-#define RK3288_CPU_AXI_VIO1_VOP_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x0)
-#define RK3288_CPU_AXI_VIO2_RGA_R_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x800)
-#define RK3288_CPU_AXI_VIO2_RGA_W_QOS_VIRT (RK3288_SERVICE_VIO_VIRT + 0x880)
-/* service video */
-#define RK3288_SERVICE_VIDEO_VIRT (RK3288_SERVICE_VIO_VIRT + RK3288_SERVICE_VIO_SIZE)
-#define RK3288_CPU_AXI_VIDEO_QOS_VIRT (RK3288_SERVICE_VIDEO_VIRT + 0x0)
-/* service hevc */
-#define RK3288_SERVICE_HEVC_VIRT (RK3288_SERVICE_VIDEO_VIRT + RK3288_SERVICE_VIDEO_SIZE)
-#define RK3288_CPU_AXI_HEVC_R_QOS_VIRT (RK3288_SERVICE_HEVC_VIRT + 0x0)
-#define RK3288_CPU_AXI_HEVC_W_QOS_VIRT (RK3288_SERVICE_HEVC_VIRT + 0x100)
-
-#define RK312X_CPU_AXI_QOS_NUM_REGS 4
-#define RK312X_CPU_AXI_SAVE_QOS(array, base) do { \
- array[0] = readl_relaxed(base + CPU_AXI_QOS_PRIORITY); \
- array[1] = readl_relaxed(base + CPU_AXI_QOS_MODE); \
- array[2] = readl_relaxed(base + CPU_AXI_QOS_BANDWIDTH); \
- array[3] = readl_relaxed(base + CPU_AXI_QOS_SATURATION); \
-} while (0)
-#define RK312X_CPU_AXI_RESTORE_QOS(array, base) do { \
- writel_relaxed(array[0], base + CPU_AXI_QOS_PRIORITY); \
- writel_relaxed(array[1], base + CPU_AXI_QOS_MODE); \
- writel_relaxed(array[2], base + CPU_AXI_QOS_BANDWIDTH); \
- writel_relaxed(array[3], base + CPU_AXI_QOS_SATURATION); \
-} while (0)
-#define RK312X_SERVICE_VIO_VIRT (RK_CPU_AXI_BUS_VIRT + 0x7000)
-
-#define RK312X_CPU_AXI_VIO_RGA_QOS_VIRT (RK312X_SERVICE_VIO_VIRT)
-#define RK312X_CPU_AXI_VIO_EBC_QOS_VIRT (RK312X_SERVICE_VIO_VIRT + 0x80)
-#define RK312X_CPU_AXI_VIO_IEP_QOS_VIRT (RK312X_SERVICE_VIO_VIRT + 0x100)
-#define RK312X_CPU_AXI_VIO_LCDC0_QOS_VIRT (RK312X_SERVICE_VIO_VIRT + 0x180)
-#define RK312X_CPU_AXI_VIO_VIP0_QOS_VIRT (RK312X_SERVICE_VIO_VIRT + 0x200)
-
-#define RK312X_SERVICE_GPU_VIRT (RK_CPU_AXI_BUS_VIRT + 0x5000)
-#define RK312X_CPU_AXI_GPU_QOS_VIRT (RK312X_SERVICE_GPU_VIRT)
-
-#define RK312X_SERVICE_VIDEO_VIRT (RK_CPU_AXI_BUS_VIRT + 0x6000)
-#define RK312X_CPU_AXI_VIDEO_QOS_VIRT (RK312X_SERVICE_VIDEO_VIRT)
-#endif