rk_clk: modify clk-ops.c to reuse and fit the common clk framework.

After the .determine_rate operation was introduced, many ops and
clocks can be implemented more easily by the common clock framework,
and many unnessary old codes can be removed as a result.
This commit is contained in:
dkl
2014-01-17 17:52:17 +08:00
parent 342b0a63bd
commit c37288b6f4
6 changed files with 294 additions and 744 deletions

View File

@@ -276,6 +276,7 @@
clocks = <&clk_i2s_div>, <&clk_i2s_frac>, <&xin12m>;
clock-output-names = "clk_i2s";
rockchip,clkops-idx = <CLKOPS_RATE_I2S>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
#clock-cells = <0>;
};
@@ -308,6 +309,7 @@
clocks = <&clk_spdif_div>, <&clk_spdif_frac>, <&xin12m>;
clock-output-names = "clk_spdif";
rockchip,clkops-idx = <CLKOPS_RATE_I2S>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
#clock-cells = <0>;
};
@@ -496,6 +498,7 @@
<&xin24m>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_uart0";
#clock-cells = <0>;
};
@@ -528,6 +531,7 @@
<&xin24m>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_uart1";
#clock-cells = <0>;
};
@@ -560,6 +564,7 @@
<&xin24m>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_uart2";
#clock-cells = <0>;
};
@@ -592,6 +597,7 @@
<&xin24m>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_uart3";
#clock-cells = <0>;
};
@@ -612,7 +618,7 @@
/* numerator denominator */
rockchip,bits = <0 32>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART_FRAC>;
<CLKOPS_RATE_FRAC>;
#clock-cells = <0>;
};
};
@@ -628,7 +634,7 @@
/* numerator denominator */
rockchip,bits = <0 32>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART_FRAC>;
<CLKOPS_RATE_FRAC>;
#clock-cells = <0>;
};
};
@@ -644,7 +650,7 @@
/* numerator denominator */
rockchip,bits = <0 32>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART_FRAC>;
<CLKOPS_RATE_FRAC>;
#clock-cells = <0>;
};
};
@@ -660,7 +666,7 @@
/* numerator denominator */
rockchip,bits = <0 32>;
rockchip,clkops-idx =
<CLKOPS_RATE_UART_FRAC>;
<CLKOPS_RATE_FRAC>;
#clock-cells = <0>;
};
};
@@ -687,6 +693,7 @@
clocks = <&clk_mac_pll_mux>, <&rmii_clkin>;
rockchip,clkops-idx =
<CLKOPS_RATE_MAC_REF>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_mac";
#clock-cells = <0>;
};
@@ -697,6 +704,8 @@
compatible = "rockchip,rk3188-div-con";
rockchip,bits = <8 5>;
clocks = <&clk_mac_pll_mux>;
rockchip,clkops-idx =
<CLKOPS_RATE_MUX_DIV>;
rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
};
@@ -727,6 +736,7 @@
<&clk_hsadc_ext>;
rockchip,clkops-idx =
<CLKOPS_RATE_HSADC>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_hsadc";
#clock-cells = <0>;
};
@@ -762,7 +772,7 @@
/* numerator denominator */
rockchip,bits = <0 32>;
rockchip,clkops-idx =
<CLKOPS_RATE_HSADC_FRAC>;
<CLKOPS_RATE_FRAC>;
#clock-cells = <0>;
};
};
@@ -907,6 +917,8 @@
rockchip,bits = <1 5>;
clocks = <&cif_out_pll_mux>;
rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
rockchip,clkops-idx =
<CLKOPS_RATE_MUX_DIV>;
};
/* reg[6]: reserved */
@@ -917,6 +929,7 @@
clocks = <&cif_out_pll_mux>, <&xin24m>;
rockchip,clkops-idx =
<CLKOPS_RATE_CIFOUT>;
rockchip,flags = <CLK_SET_RATE_PARENT>;
clock-output-names = "clk_cif0";
#clock-cells = <0>;
};

View File

@@ -5,18 +5,22 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/clk-private.h>
#include "clk-ops.h"
#include <linux/delay.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)
#define MHZ (1000 * 1000)
static u32 clk_gcd(u32 numerator, u32 denominator)
{
u32 a, b;
@@ -48,7 +52,7 @@ static int clk_fracdiv_get_config(unsigned long rate_out, unsigned long rate,
__func__, rate_out, rate, gcd_val);
if (!gcd_val) {
clk_err("gcd=0, i2s frac div is not be supported\n");
clk_err("gcd=0, frac div is not be supported\n");
return -EINVAL;
}
@@ -75,21 +79,17 @@ static int clk_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
u32 numerator, denominator;
struct clk_divider *div = to_clk_divider(hw);
struct clk *clk_parent = hw->clk->parent;
if(clk_fracdiv_get_config(rate, parent_rate,
&numerator, &denominator) == 0) {
clk_parent->ops->set_rate(clk_parent->hw,
clk_parent->parent->rate,
clk_parent->parent->rate);
writel(numerator << 16 | denominator, div->reg);
clk_err("%s set rate=%lu,is ok\n", hw->clk->name, rate);
clk_debug("%s set rate=%lu,is ok\n", hw->clk->name, rate);
} else {
clk_err("clk_frac_div can't get rate=%lu,%s\n",
rate, hw->clk->name);
return -ENOENT;
clk_err("clk_frac_div name=%s can't get rate=%lu\n",
hw->clk->name, rate);
return -EINVAL;
}
return 0;
}
@@ -100,9 +100,11 @@ static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
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;
@@ -113,172 +115,102 @@ static unsigned long clk_fracdiv_recalc(struct clk_hw *hw,
numerator, denominator);
return rate;
}
static long clk_fracdiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
/*************************************************************************/
/* rate_ops */
#define PARENTS_NUM_MAX 3
/*
* get the best rate from array of available rates, regarding rate which is smaller than
* and most close to the set_rate as the best.
*/
static long get_best_rate(unsigned long array[],unsigned int num, int *n, long rate)
{
int i = 0;
unsigned long best_rate = 0;
for(i = 0; i < num; i++){
if(array[i] == rate){
*n = i;
return array[i];
}else if((array[i] < rate) && (array[i] > best_rate)){
best_rate = array[i];
*n = i;
}
}
if(best_rate == 0){
clk_err("NOT array rate is <= %lu\n", rate);
}else{
clk_debug("get the best available rate,but it != %lu you want to set!\n", rate);
}
return best_rate;
}
static struct clk *clk_get_best_parent(struct clk_hw *hw, unsigned long rate,
unsigned int *div_out)
{
struct clk *clk = hw->clk;
u32 div[PARENTS_NUM_MAX] = {0};
unsigned long new_rate[PARENTS_NUM_MAX] = {0};
unsigned long best_rate;
u32 i;
struct clk *parent = clk->parent;
long rate_out;
memset(div, 0, sizeof(div));
memset(new_rate, 0, sizeof(new_rate));
//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;
if(clk->rate == rate)
return clk->parent;
for(i = 0; i < clk->num_parents; i++) {
new_rate[i] = clk_divider_ops.round_rate(hw, rate,
&(clk->parents[i]->rate));
div[i] = (clk->parents[i]->rate)/new_rate[i];
if(new_rate[i] == rate) {
*div_out = div[i];
return clk->parents[i];
}
}
best_rate = get_best_rate(new_rate, PARENTS_NUM_MAX, &i, rate);
if(best_rate == 0){
clk_err("NOT rate is good!\n");
return NULL;
}
*div_out = div[i];
return clk->parents[i];
}
static long clk_div_round_rate_autosel_parents(struct clk_hw *hw,
unsigned long rate, unsigned long *prate)
{
struct clk *clk = hw->clk;
struct clk *new_parent;
int new_div;
if(clk->rate == rate)
return rate;
new_parent = clk_get_best_parent(hw, rate, &new_div);
if(!new_parent || (new_div <= 0)){
clk_err("%s: clk %s could not get new_parent or new_div\n",
__func__,clk->name);
return -EINVAL;
}
return (new_parent->rate)/new_div;
}
static int clk_div_set_rate_autosel_parents(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
//struct clk_divider *divider = to_clk_divider(hw);
struct clk *clk = hw->clk;
struct clk *new_parent;
unsigned int new_div,old_div;
unsigned long new_rate;
int ret = 0;
u8 index;
int i;
if(clk->rate == rate)
goto out;
new_parent = clk_get_best_parent(hw, rate, &new_div);
if(!new_parent || (new_div == 0)){
clk_err("%s: clk %s could not get new_parent or get "
"new_div = 0\n", __func__,clk->name);
ret = -EINVAL;
goto out;
}
old_div = (clk->parent->rate)/(clk->rate);
clk_debug("%s:%d: %s: %lu\n", __func__, __LINE__,
clk->parent->name, new_parent->rate);
if(new_div > old_div){
new_rate = (clk->parent->rate)/new_div;
ret = clk_divider_ops.set_rate(hw, new_rate,
(clk->parent->rate));
if(ret)
goto out;
}
if(clk->parent != new_parent){
for(i=0; i<clk->num_parents; i++){
if(new_parent == clk->parents[i]){
index = i;
break;
}
}
/*
* ret = clk->ops->set_parent(clk->hw, index);
* if(ret)
* goto out;
*/
clk_set_parent(clk, new_parent);
clk->ops->recalc_rate(clk->hw, clk->parent->rate);
}
if(new_div <= old_div){
new_rate = (clk->parent->rate)/new_div;
ret = clk_divider_ops.set_rate(hw, new_rate,
(clk->parent->rate));
if(ret)
goto out;
}
out:
return ret;
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, hw->clk->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_div_round_rate_autosel_parents,
.set_rate = clk_div_set_rate_autosel_parents,
.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,
@@ -300,7 +232,7 @@ static long clk_div_round_rate_even(struct clk_hw *hw, unsigned long rate,
static int clk_div_set_rate_even(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return clk_divider_ops.set_rate(hw, rate, hw->clk->parent->rate);
return clk_divider_ops.set_rate(hw, rate, parent_rate);
}
const struct clk_ops clkops_rate_evendiv = {
@@ -314,9 +246,9 @@ static long dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
{
long ret = 0;
if (rate == 27 * MHZ) {
ret = clk_div_round_rate_autosel_parents(hw, rate, prate);
ret = clk_divider_round_rate(hw, rate, prate);
} else {
ret = clk_div_round_rate_autosel_parents(hw, rate, prate);
ret = clk_divider_round_rate(hw, rate, prate);
}
return ret;
}
@@ -324,81 +256,17 @@ static long dclk_lcdc_round_rate(struct clk_hw *hw, unsigned long rate,
static int dclk_lcdc_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return clk_div_set_rate_autosel_parents(hw, rate, parent_rate);
return clk_divider_set_rate(hw, rate, parent_rate);
}
const struct clk_ops clkops_rate_dclk_lcdc = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = dclk_lcdc_round_rate,
.set_rate = dclk_lcdc_set_rate,
.determine_rate = clk_mux_with_div_determine_rate,
};
#define CIF_OUT_SRC_DIV (0x0)
#define CIF_OUT_SRC_24M (0x1)
static unsigned long cif_out_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return hw->clk->parent->rate;
}
static long cif_out_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk *clk = hw->clk;
struct clk *parent;
if (rate == clk->parents[CIF_OUT_SRC_24M]->rate) {
return rate;
} else {
parent = clk->parents[CIF_OUT_SRC_DIV];
return parent->ops->round_rate(parent->hw, rate,
&(parent->parent->rate));
}
}
static int cif_out_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk *clk = hw->clk;
struct clk *parent;
int ret = 0;
if (rate == clk->parents[CIF_OUT_SRC_24M]->rate) {
parent = clk->parents[CIF_OUT_SRC_24M];
} else {
parent = clk->parents[CIF_OUT_SRC_DIV];
ret = parent->ops->set_rate(parent->hw, rate,
parent->parent->rate);
if (ret)
goto out;
else
parent->rate = rate;
}
if(clk->parent != parent){
ret = clk_set_parent(clk, parent);
#if 0
for(i=0; i<clk->num_parents; i++){
if(parent == clk->parents[i]){
index = i;
break;
}
}
ret = clk->ops->set_parent(clk->hw, index);
#endif
if(ret)
goto out;
}
out:
return ret;
}
const struct clk_ops clkops_rate_cif_out = {
.recalc_rate = cif_out_recalc_rate,
.round_rate = cif_out_round_rate,
.set_rate = cif_out_set_rate,
};
static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@@ -428,387 +296,46 @@ static int clk_i2s_fracdiv_set_rate(struct clk_hw *hw, unsigned long rate,
}
return 0;
}
#endif
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_i2s_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return hw->clk->parent->rate;
}
static long clk_i2s_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
#define I2S_SRC_DIV (0x0)
#define I2S_SRC_FRAC (0x1)
#define I2S_SRC_12M (0x2)
static int clk_i2s_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int ret = -EINVAL;
u8 p_index = 0;
struct clk *parent_tmp, *parent;
struct clk *clk = hw->clk;
if (rate == clk->parents[I2S_SRC_12M]->rate) {
parent = clk->parents[I2S_SRC_12M];
p_index = I2S_SRC_12M;
goto set_parent;
}
parent_tmp = clk->parents[I2S_SRC_DIV];
if(parent_tmp->ops->round_rate(parent_tmp->hw, rate,
&parent_tmp->parent->rate) == rate) {
parent = clk->parents[I2S_SRC_DIV];
p_index = I2S_SRC_DIV;
goto set;
}
parent = clk->parents[I2S_SRC_FRAC];
p_index = I2S_SRC_FRAC;
//ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate);
ret = parent_tmp->ops->set_rate(parent_tmp->hw,
parent_tmp->parent->rate,
parent_tmp->parent->rate);
parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw,
parent_tmp->parent->rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set:
clk_debug(" %s set rate=%lu parent %s(old %s)\n",
clk->name, rate, parent->name, clk->parent->name);
ret = clk_set_rate(parent, rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set_parent:
clk_debug("%s: set parent\n", __func__);
if (clk->parent != parent) {
ret = clk_set_parent(clk, parent);
/*
* clk->ops->set_parent(hw, p_index);
*/
if (ret) {
clk_debug("%s can't get rate%lu,reparent err\n",
clk->name, rate);
return ret;
}
}
return ret;
}
const struct clk_ops clkops_rate_i2s = {
.recalc_rate = clk_i2s_recalc_rate,
.round_rate = clk_i2s_round_rate,
.set_rate = clk_i2s_set_rate,
};
const struct clk_ops clkops_rate_hsadc_frac = {
.recalc_rate = clk_fracdiv_recalc,
.round_rate = clk_fracdiv_round_rate,
.set_rate = clk_fracdiv_set_rate,
};
const struct clk_ops clkops_rate_uart_frac = {
.recalc_rate = clk_fracdiv_recalc,
.round_rate = clk_fracdiv_round_rate,
.set_rate = clk_fracdiv_set_rate,
};
static unsigned long clk_uart_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return hw->clk->parent->rate;
}
static long clk_uart_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
#define UART_SRC_DIV (0x0)
#define UART_SRC_FRAC (0x1)
#define UART_SRC_24M (0x2)
static int clk_uart_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int ret = -EINVAL;
u8 p_index = 0;
struct clk *parent_tmp, *parent;
struct clk *clk = hw->clk;
if (rate == clk->parents[UART_SRC_24M]->rate) {
parent = clk->parents[UART_SRC_24M];
p_index = UART_SRC_24M;
goto set_parent;
}
parent_tmp = clk->parents[UART_SRC_DIV];
if(parent_tmp->ops->round_rate(parent_tmp->hw, rate,
&parent_tmp->parent->rate) == rate) {
parent = clk->parents[UART_SRC_DIV];
p_index = UART_SRC_DIV;
goto set;
}
parent = clk->parents[UART_SRC_FRAC];
p_index = UART_SRC_FRAC;
/*
* ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate);
*/
ret = parent_tmp->ops->set_rate(parent_tmp->hw,
parent_tmp->parent->rate,
parent_tmp->parent->rate);
parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw,
parent_tmp->parent->rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set:
clk_debug(" %s set rate=%lu parent %s(old %s)\n",
clk->name, rate, parent->name, clk->parent->name);
ret = clk_set_rate(parent, rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set_parent:
clk_debug("%s: set parent\n", __func__);
if (clk->parent != parent) {
ret = clk_set_parent(clk, parent);
/*
* clk->ops->set_parent(hw, p_index);
*/
if (ret) {
clk_debug("%s can't get rate%lu,reparent err\n",
clk->name, rate);
return ret;
}
}
return ret;
}
const struct clk_ops clkops_rate_uart = {
.recalc_rate = clk_uart_recalc_rate,
.round_rate = clk_uart_round_rate,
.set_rate = clk_uart_set_rate,
};
static unsigned long clk_hsadc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return hw->clk->parent->rate;
}
static long clk_hsadc_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
#define HSADC_SRC_DIV (0x0)
#define HSADC_SRC_FRAC (0x1)
#define HSADC_SRC_EXT (0x2)
static int clk_hsadc_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int ret = -EINVAL;
u8 p_index = 0;
struct clk *parent_tmp, *parent;
struct clk *clk = hw->clk;
if (rate == clk->parents[HSADC_SRC_EXT]->rate) {
parent = clk->parents[HSADC_SRC_EXT];
p_index = HSADC_SRC_EXT;
goto set_parent;
}
parent_tmp = clk->parents[HSADC_SRC_DIV];
if(parent_tmp->ops->round_rate(parent_tmp->hw, rate,
&parent_tmp->parent->rate) == rate) {
parent = clk->parents[HSADC_SRC_DIV];
p_index = HSADC_SRC_DIV;
goto set;
}
parent = clk->parents[HSADC_SRC_FRAC];
p_index = HSADC_SRC_FRAC;
/*
* ret = clk_set_rate(parent_tmp, parent_tmp->parent->rate);
*/
ret = parent_tmp->ops->set_rate(parent_tmp->hw,
parent_tmp->parent->rate,
parent_tmp->parent->rate);
parent_tmp->rate = parent_tmp->ops->recalc_rate(parent_tmp->hw,
parent_tmp->parent->rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set:
clk_debug(" %s set rate=%lu parent %s(old %s)\n",
clk->name, rate, parent->name, clk->parent->name);
ret = clk_set_rate(parent, rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set_parent:
clk_debug("%s: set parent\n", __func__);
if (clk->parent != parent) {
ret = clk_set_parent(clk, parent);
/*
* clk->ops->set_parent(hw, p_index);
*/
if (ret) {
clk_debug("%s can't get rate%lu,reparent err\n",
clk->name, rate);
return ret;
}
}
return ret;
}
const struct clk_ops clkops_rate_hsadc = {
.recalc_rate = clk_hsadc_recalc_rate,
.round_rate = clk_hsadc_round_rate,
.set_rate = clk_hsadc_set_rate,
};
static unsigned long clk_mac_ref_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return hw->clk->parent->rate;
}
static long clk_mac_ref_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
#define MAC_SRC_DIV (0x0)
#define RMII_CLKIN (0x1)
static int clk_mac_ref_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int ret = -EINVAL;
u8 p_index = 0;
struct clk *parent;
struct clk *clk = hw->clk;
clk_debug("%s: rate %lu\n", __func__, rate);
if (rate == clk->parents[RMII_CLKIN]->rate) {
parent = clk->parents[RMII_CLKIN];
p_index = RMII_CLKIN;
goto set_parent;
}
parent = clk->parents[MAC_SRC_DIV];
p_index = MAC_SRC_DIV;
clk_debug(" %s set rate=%lu parent %s(old %s)\n",
clk->name, rate, parent->name, clk->parent->name);
/*
* ret = clk_set_rate(parent, rate);
*/
ret = parent->ops->set_rate(parent->hw,
rate,
parent->parent->rate);
parent->rate = parent->ops->recalc_rate(parent->hw,
parent->parent->rate);
//ret = parent->ops->set_rate(parent->hw, rate, parent->parent->rate);
if (ret) {
clk_debug("%s set rate%lu err\n", clk->name, rate);
return ret;
}
set_parent:
clk_debug("%s: set parent\n", __func__);
if (clk->parent != parent) {
ret = clk_set_parent(clk, parent);
/*
* clk->ops->set_parent(hw, p_index);
*/
if (ret) {
clk_debug("%s can't get rate%lu,reparent err\n",
clk->name, rate);
return ret;
}
}
return ret;
}
const struct clk_ops clkops_rate_mac_ref = {
.recalc_rate = clk_mac_ref_recalc_rate,
.round_rate = clk_mac_ref_round_rate,
.set_rate = clk_mac_ref_set_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_DCLK_LCDC, .clk_ops = &clkops_rate_dclk_lcdc},
{.index = CLKOPS_RATE_CIFOUT, .clk_ops = &clkops_rate_cif_out},
{.index = CLKOPS_RATE_I2S_FRAC, .clk_ops = &clkops_rate_i2s_frac},
{.index = CLKOPS_RATE_I2S, .clk_ops = &clkops_rate_i2s},
{.index = CLKOPS_RATE_HSADC_FRAC, .clk_ops = &clkops_rate_hsadc_frac},
{.index = CLKOPS_RATE_UART_FRAC, .clk_ops = &clkops_rate_uart_frac},
{.index = CLKOPS_RATE_UART, .clk_ops = &clkops_rate_uart},
{.index = CLKOPS_RATE_HSADC, .clk_ops = &clkops_rate_hsadc},
{.index = CLKOPS_RATE_MAC_REF, .clk_ops = &clkops_rate_mac_ref},
{.index = CLKOPS_TABLE_END},
{.index = CLKOPS_RATE_FRAC, .clk_ops = &clkops_rate_frac},
{.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(u32 idx)
const struct clk_ops *rk_get_clkops(unsigned int idx)
{
return rk_clkops_rate_table[idx].clk_ops;
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);

View File

@@ -1,12 +1,19 @@
#ifndef __RK_CLK_OPS_H
#define __RK_CLK_OPS_H
#include "clkops-dtsi.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(u32 idx);
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)

View File

@@ -5,8 +5,6 @@
#include <linux/delay.h>
#define MHZ (1000UL * 1000UL)
#define KHZ (1000UL)
#define CLK_LOOPS_JIFFY_REF (11996091ULL)
#define CLK_LOOPS_RATE_REF (1200UL) //Mhz
#define CLK_LOOPS_RECALC(rate) \

View File

@@ -24,8 +24,6 @@
#include "clk-pll.h"
static DEFINE_SPINLOCK(clk_lock);
struct rkclk_divmap_table {
u32 reg_val;
u32 div_val;
@@ -53,6 +51,7 @@ struct rkclk_muxinfo {
u32 width;
u32 parent_num;
u32 clkops_idx;
u32 flags;
const char *clk_name;
const char **parent_names;
struct list_head node;
@@ -108,8 +107,10 @@ struct rkclk {
struct list_head node;
};
static DEFINE_SPINLOCK(clk_lock);
LIST_HEAD(rk_clks);
void __iomem *reg_start = 0;
#define RKCLK_PLL_TYPE (1 << 0)
#define RKCLK_MUX_TYPE (1 << 1)
#define RKCLK_DIV_TYPE (1 << 2)
@@ -132,6 +133,11 @@ static int rkclk_init_muxinfo(struct device_node *np,
ret = of_property_read_u32_index(np, "rockchip,bits", 0, &mux->shift);
if (ret != 0)
return -EINVAL;
ret = of_property_read_u32(np, "rockchip,flags", &mux->flags);
if (ret != 0)
mux->flags = 0;
ret = of_property_read_u32(np, "rockchip,clkops-idx", &mux->clkops_idx);
if (ret != 0)
mux->clkops_idx = CLKOPS_TABLE_END;
@@ -186,6 +192,7 @@ static int rkclk_init_muxinfo(struct device_node *np,
}
return 0;
}
static int rkclk_init_divinfo(struct device_node *np,
struct rkclk_divinfo *div, void __iomem *addr)
{
@@ -202,6 +209,7 @@ static int rkclk_init_divinfo(struct device_node *np,
div->addr = addr;
of_property_read_u32(np, "rockchip,div-type", &div->div_type);
ret = of_property_read_u32(np, "rockchip,clkops-idx", &div->clkops_idx);
if (ret != 0)
div->clkops_idx = CLKOPS_TABLE_END;
@@ -276,6 +284,7 @@ static int rkclk_init_divinfo(struct device_node *np,
}
static int rkclk_init_fracinfo(struct device_node *np,
struct rkclk_fracinfo *frac, void __iomem *addr)
{
@@ -448,6 +457,7 @@ static int __init rkclk_init_gatecon(struct device_node *np)
}
return 0;
}
static int __init rkclk_init_pllcon(struct device_node *np)
{
struct rkclk_pllinfo *pllinfo;
@@ -529,27 +539,6 @@ static int __init rkclk_init_pllcon(struct device_node *np)
return 0;
}
static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate;
}
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
return rate;
}
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
return 0;
}
const struct clk_ops clk_frac_ops = {
.recalc_rate = clk_frac_recalc_rate,
.round_rate = clk_frac_round_rate,
.set_rate = clk_frac_set_rate,
};
static unsigned long clk_div_special_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
@@ -565,12 +554,14 @@ static int clk_div_special_set_rate(struct clk_hw *hw, unsigned long rate,
{
return 0;
}
// For fixed div clks and For user defined div clk
const struct clk_ops clk_div_special_ops = {
.recalc_rate = clk_div_special_recalc_rate,
.round_rate = clk_div_special_round_rate,
.set_rate = clk_div_special_set_rate,
};
static int rkclk_register(struct rkclk *rkclk)
{
struct clk_mux *mux = NULL;
@@ -586,9 +577,11 @@ static int rkclk_register(struct rkclk *rkclk)
struct clk_hw *rate_hw;
int parent_num;
struct device_node *node = rkclk->np;
/* Single clk */
clk_debug("%s: %s clk_type=%x\n", __func__,
rkclk->clk_name, rkclk->clk_type);
unsigned long flags = 0;
clk_debug("%s >>>>>start: clk_name=%s, clk_type=%x\n",
__func__, rkclk->clk_name, rkclk->clk_type);
if (rkclk->clk_type & RKCLK_PLL_TYPE) {
pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
@@ -604,19 +597,19 @@ static int rkclk_register(struct rkclk *rkclk)
} else if (rkclk->clk_type & RKCLK_FRAC_TYPE) {
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
if (rkclk->frac_info->clkops_idx != CLKOPS_TABLE_END)
rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx);
else
rate_ops = &clk_frac_ops;
div->reg = rkclk->frac_info->addr;
div->shift = (u8)rkclk->frac_info->shift;
div->width = rkclk->frac_info->width;
div->flags = CLK_DIVIDER_HIWORD_MASK;
rate_hw = &div->hw;
rate_ops = rk_get_clkops(rkclk->frac_info->clkops_idx);
parent_num = 1;
parent_names = &rkclk->frac_info->parent_name;
flags |= CLK_SET_RATE_PARENT;
} else if (rkclk->clk_type & RKCLK_DIV_TYPE) {
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
if (rkclk->div_info->clkops_idx != CLKOPS_TABLE_END)
@@ -655,6 +648,7 @@ static int rkclk_register(struct rkclk *rkclk)
parent_num = rkclk->mux_info->parent_num;
parent_names = rkclk->mux_info->parent_names;
flags |= rkclk->mux_info->flags;
}
if (rkclk->clk_type & RKCLK_GATE_TYPE) {
@@ -668,46 +662,43 @@ static int rkclk_register(struct rkclk *rkclk)
// FIXME: flag(CLK_IGNORE_UNUSED) may need an input argument
if (rkclk->clk_type == RKCLK_MUX_TYPE
&& rkclk->mux_info->clkops_idx == CLKOPS_TABLE_END) {
clk_debug("use clk_register_mux\n");
clk = clk_register_mux(NULL, rkclk->clk_name,
rkclk->mux_info->parent_names,
(u8)rkclk->mux_info->parent_num,
CLK_SET_RATE_PARENT,
mux->reg, mux->shift, mux->mask,
flags, mux->reg, mux->shift, mux->mask,
0, &clk_lock);
} else if (rkclk->clk_type == RKCLK_DIV_TYPE) {
clk_debug("use clk_register_divider\n");
clk = clk_register_divider(NULL, rkclk->clk_name,
rkclk->div_info->parent_name,
CLK_SET_RATE_PARENT, div->reg, div->shift,
flags, div->reg, div->shift,
div->width, div->flags, &clk_lock);
} else if (rkclk->clk_type == RKCLK_GATE_TYPE) {
clk_debug("use clk_register_gate\n");
clk = clk_register_gate(NULL, rkclk->clk_name,
rkclk->gate_info->parent_name,
CLK_IGNORE_UNUSED, gate->reg,
flags, gate->reg,
gate->bit_idx,
gate->flags, &clk_lock);
} else if (rkclk->clk_type == 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,
0, pll->reg, pll->width, pll->id,
&clk_lock);
flags, pll->reg, pll->width,
pll->id, &clk_lock);
} else {
int i = 0;
clk_debug("%s: composite clk(\"%s\") parents:\n",
__func__, rkclk->clk_name);
for (i = 0; i < parent_num; i++) {
clk_debug("\t\t%s: parent[%d]=%s\n", __func__,
i, parent_names[i]);
}
clk_debug("use clk_register_composite\n");
clk = clk_register_composite(NULL, rkclk->clk_name,
parent_names, parent_num,
mux ? &mux->hw : NULL, mux ? mux_ops : NULL,
rate_hw, rate_ops,
gate ? &gate->hw : NULL, gate ? &clk_gate_ops : NULL,
CLK_IGNORE_UNUSED);
flags);
}
if (clk) {
clk_debug("clk name=%s, flags=0x%lx\n", clk->name, clk->flags);
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, rkclk->clk_name, NULL);
} else {
@@ -718,39 +709,51 @@ static int rkclk_register(struct rkclk *rkclk)
return 0;
}
#ifdef RKCLK_TEST
struct test_table {
const char *name;
u32 rate;
};
struct test_table t_table[] = {
{.name = "clk_gpu", .rate = 297000000},
{.name = "dclk_lcdc0", .rate = 297000000},
{.name = "clk_i2s", .rate = 11289600},
{.name = "clk_spdif", .rate = 11289600},
{.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_cif0", .rate = 12000000},
{.name = "aclk_lcdc0", .rate = 297000000},
{.name = "clk_apll", .rate = 600000000},
{.name = "clk_dpll", .rate = 600000000},
{.name = "clk_apll", .rate = 500000000},
{.name = "clk_dpll", .rate = 400000000},
{.name = "clk_cpll", .rate = 600000000},
{.name = "clk_gpll", .rate = 800000000},
};
#ifdef RKCLK_DEBUG
void rk_clk_test(void)
{
const char *clk_name;
struct clk *clk;
u32 rate,recalc_rate,round_rate = 0;
unsigned long rate=0, recalc_rate=0, round_rate=0, get_rate=0;
u32 i = 0, 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;
@@ -760,55 +763,50 @@ void rk_clk_test(void)
__func__, clk_name);
} else
clk_debug("%s: clk(\"%s\") \tclk_get success\n",
__func__, __clk_get_name(clk));
__func__, clk_name);
/*TEST: clk_round_rate*/
if (clk->ops->round_rate) {
round_rate = clk_round_rate(clk, rate);
clk_debug("%s: clk(\"%s\") \tclk_round_rate from %lu to %lu\n",
__func__, __clk_get_name(clk),
rate, round_rate);
} else {
clk_debug("%s: clk(\"%s\") have no round ops\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 */
if (clk->ops->set_rate) {
if (0 != clk_set_rate(clk, rate)) {
clk_err("%s: clk(\"%s\") \tclk_set_rate error\n",
__func__, clk_name);
} else {
clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n",
__func__, __clk_get_name(clk));
}
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\") have no set ops\n",
__func__, clk->name);
clk_debug("%s: clk(\"%s\") \tclk_set_rate success\n",
__func__, clk_name);
}
/*TEST: clk_recalc_rate*/
/* TEST: recalc_rate\clk_get_rate */
if (clk->ops->recalc_rate) {
recalc_rate = clk->ops->recalc_rate(clk->hw,
clk->parent->rate);
clk->parent->rate);
clk_debug("%s: clk(\"%s\") \tclk_recalc_rate %lu\n",
__func__, __clk_get_name(clk),
recalc_rate);
__func__, clk_name, recalc_rate);
} else {
clk_debug("%s: clk(\"%s\") have no recalc ops\n",
__func__, clk->name);
__func__, clk_name);
get_rate = clk_get_rate(clk);
clk_debug("%s: clk(\"%s\") \tclk_get_rate %lu\n",
__func__, clk_name, get_rate);
}
}
#if 0
printk("\n");
printk("dump cru regs:");
for (i = 0; i * 4 <= 0xf4; i++) {
if (i % 4 == 0)
printk("\n%s: \t[0x%08x]: ",
__func__, 0x20000000 + i * 4);
printk("%08x ", readl(reg_start + i * 4));
}
printk("\n\n");
printk("dump cru regs:\n");
for (i = 0; i * 4 <= 0xf4; i++) {
if (i % 4 == 0)
printk("\n%s: \t[0x%08x]: ",
__func__, 0x20000000 + i * 4);
printk("%08x ", readl(reg_start + i * 4));
#endif
}
printk("\n\n");
}
EXPORT_SYMBOL_GPL(rk_clk_test);
@@ -816,28 +814,23 @@ EXPORT_SYMBOL_GPL(rk_clk_test);
void rk_clk_test(void){};
EXPORT_SYMBOL_GPL(rk_clk_test);
#endif
extern void clk_dump_tree(void);
void rkclk_init_clks(struct device_node *node);
static void __init rk_clk_tree_init(struct device_node *np)
{
struct device_node *node;
struct device_node *node_init;
struct rkclk *rkclk;
node_init=of_find_node_by_name(NULL,"clocks-init");
if(!node_init)
{
printk("%s:can not get clocks-init node\n",__FUNCTION__);
{
printk("%s:can not get clocks-init node\n",__FUNCTION__);
return;
}
for_each_available_child_of_node(np, node) {
if (!ERR_PTR(of_property_match_string(node,
@@ -875,7 +868,6 @@ static void __init rk_clk_tree_init(struct device_node *np)
};
#if 0
list_for_each_entry(rkclk, &rk_clks, node) {
int i;
@@ -909,12 +901,13 @@ static void __init rk_clk_tree_init(struct device_node *np)
}
}
#endif
list_for_each_entry(rkclk, &rk_clks, node) {
rkclk_register(rkclk);
}
/* check clock parents init */
list_for_each_entry(rkclk, &rk_clks, node) {
struct clk *clk;
int i = 0;
const char *clk_name = rkclk->clk_name;
@@ -950,9 +943,10 @@ static void __init rk_clk_tree_init(struct device_node *np)
rkclk_init_clks(node_init);
}
CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init);
CLK_OF_DECLARE(rk_clocks, "rockchip,rk-clock-regs", rk_clk_tree_init);
/********************************** rock chip clks 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;
@@ -963,15 +957,15 @@ const char *of_clk_init_rate_get_info(struct device_node *np, int index,u32 *rat
return NULL;
rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells", index,
&clkspec);
&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;
}
@@ -988,14 +982,14 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const
return NULL;
rc = of_parse_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells", index,
&clkspec);
&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);
@@ -1006,21 +1000,21 @@ const char *of_clk_init_parent_get_info(struct device_node *np, int index,const
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;
}
void rkclk_init_clks(struct device_node *np)
{
{
//struct device_node *np;
int i,cnt_parent,cnt_rate;
u32 clk_rate;
@@ -1031,36 +1025,36 @@ void rkclk_init_clks(struct device_node *np)
cnt_parent = of_count_phandle_with_args(np, "rockchip,clocks-init-parent", "#clock-init-cells");
printk("%s:cnt_parent =%d\n",__FUNCTION__,cnt_parent);
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);
printk("%s: set parent %s=%x,%s=%x\n",__FUNCTION__,clk_name,(u32)clk_c,clk_parent_name,(u32)clk_p);
if(IS_ERR(clk_c)||IS_ERR(clk_p))
if(IS_ERR(clk_c)||IS_ERR(clk_p))
continue;
//clk_set_parent(clk_name, clk_parent_name);
}
cnt_rate = of_count_phandle_with_args(np, "rockchip,clocks-init-rate", "#clock-init-cells");
printk("%s:rate cnt=%d\n",__FUNCTION__,cnt_rate);
printk("%s:rate cnt=%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;
clk_p=clk_get(NULL,clk_name);
printk("%s: set rate %s=%x,rate=%d\n",__FUNCTION__,clk_name,(u32)clk_p,clk_rate);
@@ -1068,12 +1062,8 @@ void rkclk_init_clks(struct device_node *np)
if(IS_ERR(clk_c)||(clk_rate<1*1000*1000)||(clk_rate>2000*1000*1000))
continue;
//clk_set_rate(clk_p,clk_rate);
}
}

View File

@@ -9,20 +9,19 @@
#define GPLL_ID 3
/* rate_ops index */
#define CLKOPS_RATE_MUX_DIV 0
#define CLKOPS_RATE_EVENDIV 1
#define CLKOPS_RATE_DCLK_LCDC 2
#define CLKOPS_RATE_CIFOUT 3
#define CLKOPS_RATE_I2S_FRAC 4
#define CLKOPS_RATE_I2S_FRAC 3
#define CLKOPS_RATE_FRAC 4
#define CLKOPS_RATE_I2S 5
#define CLKOPS_RATE_HSADC_FRAC 6
#define CLKOPS_RATE_UART_FRAC 7
#define CLKOPS_RATE_UART 8
#define CLKOPS_RATE_HSADC 9
#define CLKOPS_RATE_MAC_REF 10
#define CLKOPS_TABLE_END ~0
#define CLKOPS_RATE_CIFOUT 6
#define CLKOPS_RATE_UART 7
#define CLKOPS_RATE_HSADC 8
#define CLKOPS_RATE_MAC_REF 9
#define CLKOPS_TABLE_END (~0)
#ifndef BIT
#define BIT(nr) (1 << (nr))
@@ -37,4 +36,20 @@
#define CLK_DIVIDER_USER_DEFINE BIT(7)
/* CLK_DIVIDER_MASK defined the bits been used above */
#define CLK_DIVIDER_MASK (0xFF)
/*
* flags used across common struct clk. these flags should only affect the
* top-level framework. custom flags for dealing with hardware specifics
* belong in struct clk_foo
*/
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */
#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */
#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
#endif /* __RK_CLKOPS_H */