From: chenxing Date: Fri, 11 Jan 2013 09:34:09 +0000 (+0800) Subject: rk3188: add clock_data, but do not compiled X-Git-Tag: firefly_0821_release~7960 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0104b7a12a74ae89b0a11107e127872e0527d3f3;p=firefly-linux-kernel-4.4.55.git rk3188: add clock_data, but do not compiled --- diff --git a/arch/arm/mach-rk3188/clock_data.c b/arch/arm/mach-rk3188/clock_data.c new file mode 100644 index 000000000000..7295827c5c90 --- /dev/null +++ b/arch/arm/mach-rk3188/clock_data.c @@ -0,0 +1,3697 @@ +/* linux/arch/arm/mach-rk30/clock_data.c + * + * Copyright (C) 2012 ROCKCHIP, Inc. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHZ (1000UL * 1000UL) +#define KHZ (1000UL) +#define CLK_LOOPS_JIFFY_REF 11996091ULL +#define CLK_LOOPS_RATE_REF (1200UL) //Mhz +#define CLK_LOOPS_RECALC(new_rate) div_u64(CLK_LOOPS_JIFFY_REF*(new_rate),CLK_LOOPS_RATE_REF*MHZ) +void rk30_clk_dump_regs(void); + +//flags bit +//has extern 27mhz +#define CLK_FLG_EXT_27MHZ (1<<0) +//max i2s rate +#define CLK_FLG_MAX_I2S_12288KHZ (1<<1) +#define CLK_FLG_MAX_I2S_22579_2KHZ (1<<2) +#define CLK_FLG_MAX_I2S_24576KHZ (1<<3) +#define CLK_FLG_MAX_I2S_49152KHZ (1<<4) +//uart 1m\3m +#define CLK_FLG_UART_1_3M (1<<5) + +#define ARCH_RK31 + +struct apll_clk_set { + unsigned long rate; + u32 pllcon0; + u32 pllcon1; + u32 pllcon2; //nb=bwadj+1;0:11;nb=nf/2 + u32 rst_dly;//us + u32 clksel0; + u32 clksel1; + unsigned long lpj; +}; +struct pll_clk_set { + unsigned long rate; + u32 pllcon0; + u32 pllcon1; + u32 pllcon2; //nb=bwadj+1;0:11;nb=nf/2 + unsigned long rst_dly;//us +}; + +#define SET_PLL_DATA(_pll_id,_table) \ +{\ + .id=(_pll_id),\ + .table=(_table),\ +} + + +#define _PLL_SET_CLKS(_mhz, nr, nf, no) \ +{ \ + .rate = (_mhz) * KHZ, \ + .pllcon0 = PLL_CLKR_SET(nr)|PLL_CLKOD_SET(no), \ + .pllcon1 = PLL_CLKF_SET(nf),\ + .rst_dly=((nr*500)/24+1),\ +} + + +#define _APLL_SET_LPJ(_mhz) \ + .lpj= (CLK_LOOPS_JIFFY_REF * _mhz)/CLK_LOOPS_RATE_REF + + +#define _APLL_SET_CLKS(_mhz, nr, nf, no, _periph_div, _axi_core_div,\ + _axi_div,_ahb_div, _apb_div,_ahb2apb) \ +{ \ + .rate = _mhz * MHZ, \ + .pllcon0 = PLL_CLKR_SET(nr) | PLL_CLKOD_SET(no), \ + .pllcon1 = PLL_CLKF_SET(nf),\ + .clksel0 = CORE_PERIPH_W_MSK | CORE_PERIPH_##_periph_div,\ + .clksel1 = CORE_ACLK_W_MSK | CORE_ACLK_##_axi_core_div,\ + _APLL_SET_LPJ(_mhz),\ + .rst_dly=((nr*500)/24+1),\ +} + +#define CRU_DIV_SET(mask,shift,max) \ + .div_mask=(mask),\ +.div_shift=(shift),\ +.div_max=(max) + + +#define CRU_SRC_SET(mask,shift ) \ + .src_mask=(mask),\ +.src_shift=(shift) + +#define CRU_PARENTS_SET(parents_array) \ + .parents=(parents_array),\ +.parents_num=ARRAY_SIZE((parents_array)) + +#define CRU_GATE_MODE_SET(_func,_IDX) \ + .mode=_func,\ +.gate_idx=(_IDX) + +struct clk_src_sel { + struct clk *parent; + u8 value;//crt bit + u8 flag; + //selgate +}; + +#define GATE_CLK(NAME,PARENT,ID) \ + static struct clk clk_##NAME = { \ + .name = #NAME, \ + .parent = &PARENT, \ + .mode = gate_mode, \ + .gate_idx = CLK_GATE_##ID, \ + } +#ifdef RK30_CLK_OFFBOARD_TEST +u32 TEST_GRF_REG[0x240]; +u32 TEST_CRU_REG[0x240]; +#define cru_readl(offset) (TEST_CRU_REG[offset/4]) + +u32 cru_writel_is_pr(u32 offset) +{ + return (offset == 0x4000); +} +void cru_writel(u32 v, u32 offset) +{ + + u32 mask_v = v >> 16; + TEST_CRU_REG[offset/4] &= (~mask_v); + + v &= (mask_v); + + TEST_CRU_REG[offset/4] |= v; + TEST_CRU_REG[offset/4] &= 0x0000ffff; + + if(cru_writel_is_pr(offset)) { + CLKDATA_DBG("cru w offset=%d,set=%x,reg=%x\n", offset, v, TEST_CRU_REG[offset/4]); + + } + +} +void cru_writel_i2s(u32 v, u32 offset) +{ + TEST_CRU_REG[offset/4] = v; +} +#define cru_writel_frac(v,offset) cru_writel_i2s((v),(offset)) + +#define regfile_readl(offset) (0xffffffff) +//#define pmu_readl(offset) readl(RK30_GRF_BASE + offset) +void rk30_clkdev_add(struct clk_lookup *cl); +#else +#define regfile_readl(offset) readl_relaxed(RK30_GRF_BASE + offset) +#define regfile_writel(v, offset) do { writel_relaxed(v, RK30_GRF_BASE + offset); dsb(); } while (0) +#define cru_readl(offset) readl_relaxed(RK30_CRU_BASE + offset) +#define cru_writel(v, offset) do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0) + +#define cru_writel_frac(v,offset) cru_writel((v),(offset)) +#endif + +#define DEBUG +#ifdef DEBUG +//#define CLKDATA_DBG(fmt, args...) printk(KERN_DEBUG "CLKDATA_DBG:\t"fmt, ##args) +//#define CLKDATA_LOG(fmt, args...) printk(KERN_INFO "CLKDATA_LOG:\t"fmt, ##args) +#define CLKDATA_DBG(fmt, args...) printk("CLKDATA_DBG:\t"fmt, ##args) +#define CLKDATA_LOG(fmt, args...) printk("CLKDATA_LOG:\t"fmt, ##args) +#else +#define CLKDATA_DBG(fmt, args...) do {} while(0) +#define CLKDATA_LOG(fmt, args...) do {} while(0) +#endif +#define CLKDATA_ERR(fmt, args...) printk(KERN_ERR "CLKDATA_ERR:\t"fmt, ##args) +#define CLKDATA_WARNNING(fmt, args...) printk("CLKDATA_WANNING:\t"fmt, ##args) + + +#define get_cru_bits(con,mask,shift)\ + ((cru_readl((con)) >> (shift)) & (mask)) + +#define set_cru_bits_w_msk(val,mask,shift,con)\ + cru_writel(((mask)<<(shift+16))|((val)<<(shift)),(con)) + + +#define PLLS_IN_NORM(pll_id) (((cru_readl(CRU_MODE_CON)&PLL_MODE_MSK(pll_id))==(PLL_MODE_NORM(pll_id)&PLL_MODE_MSK(pll_id)))\ + &&!(cru_readl(PLL_CONS(pll_id,3))&PLL_BYPASS)) + + +static u32 rk30_clock_flags = 0; +static struct clk codec_pll_clk; +static struct clk general_pll_clk; +static struct clk arm_pll_clk; +static unsigned long lpj_gpll; +static unsigned int __initdata armclk = 504 * MHZ; + + +/************************clk recalc div rate*********************************/ + +//for free div +static unsigned long clksel_recalc_div(struct clk *clk) +{ + u32 div = get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift) + 1; + + unsigned long rate = clk->parent->rate / div; + pr_debug("%s new clock rate is %lu (div %u)\n", clk->name, rate, div); + return rate; +} + +//for div 1 2 4 2^n +static unsigned long clksel_recalc_shift(struct clk *clk) +{ + u32 shift = get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift); + unsigned long rate = clk->parent->rate >> shift; + pr_debug("%s new clock rate is %lu (shift %u)\n", clk->name, rate, shift); + return rate; +} + + +static unsigned long clksel_recalc_shift_2(struct clk *clk) +{ + u32 shift = get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift) + 1; + unsigned long rate = clk->parent->rate >> shift; + pr_debug("%s new clock rate is %lu (shift %u)\n", clk->name, rate, shift); + return rate; +} + +static unsigned long clksel_recalc_parent_rate(struct clk *clk) +{ + unsigned long rate = clk->parent->rate; + pr_debug("%s new clock rate is %lu\n", clk->name, rate); + return rate; +} +/********************************set div rate***********************************/ + +//for free div +static int clksel_set_rate_freediv(struct clk *clk, unsigned long rate) +{ + u32 div; + for (div = 0; div < clk->div_max; div++) { + u32 new_rate = clk->parent->rate / (div + 1); + if (new_rate <= rate) { + set_cru_bits_w_msk(div, clk->div_mask, clk->div_shift, clk->clksel_con); + //clk->rate = new_rate; + pr_debug("clksel_set_rate_freediv for clock %s to rate %ld (div %d)\n", + clk->name, rate, div + 1); + return 0; + } + } + return -ENOENT; +} + +//for div 1 2 4 2^n +static int clksel_set_rate_shift(struct clk *clk, unsigned long rate) +{ + u32 shift; + for (shift = 0; (1 << shift) < clk->div_max; shift++) { + u32 new_rate = clk->parent->rate >> shift; + if (new_rate <= rate) { + set_cru_bits_w_msk(shift, clk->div_mask, clk->div_shift, clk->clksel_con); + clk->rate = new_rate; + pr_debug("clksel_set_rate_shift for clock %s to rate %ld (shift %d)\n", + clk->name, rate, shift); + return 0; + } + } + return -ENOENT; +} + +//for div 2 4 2^n +static int clksel_set_rate_shift_2(struct clk *clk, unsigned long rate) +{ + u32 shift; + + for (shift = 1; (1 << shift) < clk->div_max; shift++) { + u32 new_rate = clk->parent->rate >> shift; + if (new_rate <= rate) { + set_cru_bits_w_msk(shift - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + clk->rate = new_rate; + pr_debug("clksel_set_rate_shift for clock %s to rate %ld (shift %d)\n", + clk->name, rate, shift); + return 0; + } + } + return -ENOENT; +} +static u32 clk_get_freediv(unsigned long rate_out, unsigned long rate , u32 div_max) +{ + u32 div; + unsigned long new_rate; + for (div = 0; div < div_max; div++) { + new_rate = rate / (div + 1); + if (new_rate <= rate_out) { + return div + 1; + } + } + return div_max ? div_max : 1; +} +struct clk *get_freediv_parents_div(struct clk *clk, unsigned long rate, u32 *div_out) { + u32 div[2] = {0, 0}; + unsigned long new_rate[2] = {0, 0}; + u32 i; + + if(clk->rate == rate) + return clk->parent; + for(i = 0; i < 2; i++) { + div[i] = clk_get_freediv(rate, clk->parents[i]->rate, clk->div_max); + new_rate[i] = clk->parents[i]->rate / div[i]; + if(new_rate[i] == rate) { + *div_out = div[i]; + return clk->parents[i]; + } + } + if(new_rate[0] < new_rate[1]) + i = 1; + else + i = 0; + *div_out = div[i]; + return clk->parents[i]; +} + +static int clkset_rate_freediv_autosel_parents(struct clk *clk, unsigned long rate) +{ + struct clk *p_clk; + u32 div, old_div; + int ret = 0; + if(clk->rate == rate) + return 0; + p_clk = get_freediv_parents_div(clk, rate, &div); + + if(!p_clk) + return -ENOENT; + + CLKDATA_DBG("%s %lu,form %s\n", clk->name, rate, p_clk->name); + if (clk->parent != p_clk) { + old_div = CRU_GET_REG_BITS_VAL(cru_readl(clk->clksel_con), clk->div_shift, clk->div_mask) + 1; + + if(div > old_div) { + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + } + ret = clk_set_parent_nolock(clk, p_clk); + if(ret) { + CLKDATA_ERR("%s can't set %lu,reparent err\n", clk->name, rate); + return -ENOENT; + } + } + //set div + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + return 0; +} + +//rate==div rate //hdmi +static int clk_freediv_autosel_parents_set_fixed_rate(struct clk *clk, unsigned long rate) +{ + struct clk *p_clk; + u32 div, old_div; + int ret; + p_clk = get_freediv_parents_div(clk, rate, &div); + + if(!p_clk) + return -ENOENT; + + if((p_clk->rate / div) != rate || (p_clk->rate % div)) + return -ENOENT; + + if (clk->parent != p_clk) { + old_div = CRU_GET_REG_BITS_VAL(cru_readl(clk->clksel_con), + clk->div_shift, clk->div_mask) + 1; + if(div > old_div) { + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + } + ret = clk_set_parent_nolock(clk, p_clk); + if (ret) { + CLKDATA_DBG("%s can't get rate%lu,reparent err\n", clk->name, rate); + return ret; + } + } + //set div + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + return 0; +} + +/***************************round********************************/ + +static long clksel_freediv_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->rate / clk_get_freediv(rate, clk->parent->rate, clk->div_max); +} + +static long clk_freediv_round_autosel_parents_rate(struct clk *clk, unsigned long rate) +{ + u32 div; + struct clk *p_clk; + if(clk->rate == rate) + return clk->rate; + p_clk = get_freediv_parents_div(clk, rate, &div); + if(!p_clk) + return 0; + return p_clk->rate / div; +} + +/**************************************others seting************************************/ + +static struct clk *clksel_get_parent(struct clk *clk) { + return clk->parents[(cru_readl(clk->clksel_con) >> clk->src_shift) & clk->src_mask]; +} +static int clksel_set_parent(struct clk *clk, struct clk *parent) +{ + u32 i; + if (unlikely(!clk->parents)) + return -EINVAL; + for (i = 0; (i < clk->parents_num); i++) { + if (clk->parents[i] != parent) + continue; + set_cru_bits_w_msk(i, clk->src_mask, clk->src_shift, clk->clksel_con); + return 0; + } + return -EINVAL; +} + +static int gate_mode(struct clk *clk, int on) +{ + int idx = clk->gate_idx; + if (idx >= CLK_GATE_MAX) + return -EINVAL; + if(on) { + cru_writel(CLK_GATE_W_MSK(idx) | CLK_UN_GATE(idx), CLK_GATE_CLKID_CONS(idx)); + //CLKDATA_DBG("un gate id=%d %s(%x),con %x\n",idx,clk->name, + // CLK_GATE_W_MSK(idx)|CLK_UN_GATE(idx),CLK_GATE_CLKID_CONS(idx)); + } else { + cru_writel(CLK_GATE_W_MSK(idx) | CLK_GATE(idx), CLK_GATE_CLKID_CONS(idx)); + // CLKDATA_DBG("gate id=%d %s(%x),con%x\n",idx,clk->name, + // CLK_GATE_W_MSK(idx)|CLK_GATE(idx),CLK_GATE_CLKID_CONS(idx)); + } + return 0; +} +/*****************************frac set******************************************/ + +static unsigned long clksel_recalc_frac(struct clk *clk) +{ + unsigned long rate; + u64 rate64; + u32 r = cru_readl(clk->clksel_con), numerator, denominator; + if (r == 0) // FPGA ? + return clk->parent->rate; + numerator = r >> 16; + denominator = r & 0xFFFF; + rate64 = (u64)clk->parent->rate * numerator; + do_div(rate64, denominator); + rate = rate64; + pr_debug("%s new clock rate is %lu (frac %u/%u)\n", clk->name, rate, numerator, denominator); + return rate; +} + +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 frac_div_get_seting(unsigned long rate_out, unsigned long rate, + u32 *numerator, u32 *denominator) +{ + u32 gcd_vl; + gcd_vl = clk_gcd(rate, rate_out); + CLKDATA_DBG("frac_get_seting rate=%lu,parent=%lu,gcd=%d\n", rate_out, rate, gcd_vl); + + if (!gcd_vl) { + CLKDATA_ERR("gcd=0, i2s frac div is not be supported\n"); + return -ENOENT; + } + + *numerator = rate_out / gcd_vl; + *denominator = rate / gcd_vl; + + CLKDATA_DBG("frac_get_seting numerator=%d,denominator=%d,times=%d\n", + *numerator, *denominator, *denominator / *numerator); + + if (*numerator > 0xffff || *denominator > 0xffff || + (*denominator / (*numerator)) < 20) { + CLKDATA_ERR("can't get a available nume and deno\n"); + return -ENOENT; + } + + return 0; + +} +/* *********************pll **************************/ + +#define rk30_clock_udelay(a) udelay(a); + +/*********************pll lock status**********************************/ +//#define GRF_SOC_CON0 0x15c +static void pll_wait_lock(int pll_idx) +{ + u32 pll_state[4] = {1, 0, 2, 3}; + u32 bit = 0x20u << pll_state[pll_idx]; + int delay = 24000000; + while (delay > 0) { + if (regfile_readl(GRF_SOC_STATUS0) & bit) + break; + delay--; + } + if (delay == 0) { + CLKDATA_ERR("wait pll bit 0x%x time out!\n", bit); + while(1); + } +} + + + +/***************************pll function**********************************/ +static unsigned long pll_clk_recalc(u32 pll_id, unsigned long parent_rate) +{ + unsigned long rate; + + if (PLLS_IN_NORM(pll_id)) { + u32 pll_con0 = cru_readl(PLL_CONS(pll_id, 0)); + u32 pll_con1 = cru_readl(PLL_CONS(pll_id, 1)); + + + u64 rate64 = (u64)parent_rate * PLL_NF(pll_con1); + + /* + CLKDATA_DBG("selcon con0(%x) %x,con1(%x)%x, rate64 %llu\n",PLL_CONS(pll_id,0),pll_con0 + ,PLL_CONS(pll_id,1),pll_con1, rate64); + */ + + + //CLKDATA_DBG("pll id=%d con0=%x,con1=%x,parent=%lu\n",pll_id,pll_con0,pll_con1,parent_rate); + //CLKDATA_DBG("first pll id=%d rate is %lu (NF %d NR %d NO %d)\n", + //pll_id, rate, PLL_NF(pll_con1), PLL_NR(pll_con0), 1 << PLL_NO(pll_con0)); + + do_div(rate64, PLL_NR(pll_con0)); + do_div(rate64, PLL_NO(pll_con0)); + + rate = rate64; + /* + CLKDATA_DBG("pll_clk_recalc id=%d rate=%lu (NF %d NR %d NO %d) rate64=%llu\n", + pll_id, rate, PLL_NF(pll_con1), PLL_NR(pll_con0),PLL_NO(pll_con0), rate64); + */ + } else { + rate = parent_rate; + CLKDATA_DBG("pll_clk_recalc id=%d rate=%lu by pass mode\n", pll_id, rate); + } + return rate; +} +static unsigned long plls_clk_recalc(struct clk *clk) +{ + return pll_clk_recalc(clk->pll->id, clk->parent->rate); +} + +static int pll_clk_set_rate(struct pll_clk_set *clk_set, u8 pll_id) +{ + //enter slowmode + cru_writel(PLL_MODE_SLOW(pll_id), CRU_MODE_CON); + cru_writel((0x1<<(16+1))|(0x1<<1), PLL_CONS(pll_id, 3)); + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + cru_writel(clk_set->pllcon0, PLL_CONS(pll_id, 0)); + cru_writel(clk_set->pllcon1, PLL_CONS(pll_id, 1)); + + rk30_clock_udelay(1); + cru_writel((0x1<<(16+1)), PLL_CONS(pll_id, 3)); + + pll_wait_lock(pll_id); + + //return form slow + cru_writel(PLL_MODE_NORM(pll_id), CRU_MODE_CON); + + /* + CLKDATA_ERR("pll reg id=%d,con0=%x,con1=%x,mode=%x\n",pll_id, + cru_readl(PLL_CONS(pll_id,0)),(PLL_CONS(pll_id,1)),cru_readl(CRU_MODE_CON)); + */ + + return 0; +} +static int gpll_clk_set_rate(struct clk *c, unsigned long rate) +{ + struct _pll_data *pll_data = c->pll; + struct pll_clk_set *clk_set = (struct pll_clk_set *)pll_data->table; + + while(clk_set->rate) { + if (clk_set->rate == rate) { + break; + } + clk_set++; + } + if(clk_set->rate == rate) { + pll_clk_set_rate(clk_set, pll_data->id); + lpj_gpll = CLK_LOOPS_RECALC(rate); + } else { + CLKDATA_ERR("gpll is no corresponding rate=%lu\n", rate); + return -1; + } + return 0; +} + +#define PLL_FREF_MIN (183*KHZ) +#define PLL_FREF_MAX (1500*MHZ) + +#define PLL_FVCO_MIN (300*MHZ) +#define PLL_FVCO_MAX (1500*MHZ) + +#define PLL_FOUT_MIN (18750*KHZ) +#define PLL_FOUT_MAX (1500*MHZ) + +#define PLL_NF_MAX (65536) +#define PLL_NR_MAX (64) +#define PLL_NO_MAX (64) + +static int pll_clk_get_set(unsigned long fin_hz, unsigned long fout_hz, u32 *clk_nr, u32 *clk_nf, u32 *clk_no) +{ + u32 nr, nf, no, nonr; + u32 n; + u32 YFfenzi; + u32 YFfenmu; + unsigned long fref, fvco, fout; + u32 gcd_val = 0; + + CLKDATA_DBG("pll_clk_get_set fin=%lu,fout=%lu\n", fin_hz, fout_hz); + if(!fin_hz || !fout_hz || fout_hz == fin_hz) + return 0; + 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) //PLL_NR_MAX + continue; + + fref = fin_hz / nr; + if(fref < PLL_FREF_MIN || fref > PLL_FREF_MAX) + continue; + + fvco = (fin_hz / nr) * nf; + if(fvco < PLL_FVCO_MIN || fvco > PLL_FVCO_MAX) + continue; + fout = fvco / no; + if(fout < PLL_FOUT_MIN || fout > PLL_FOUT_MAX) + continue; + *clk_nr = nr; + *clk_no = no; + *clk_nf = nf; + return 1; + + } + + } + return 0; +} + +static int pll_clk_mode(struct clk *clk, int on) +{ + u8 pll_id = clk->pll->id; + u32 nr = PLL_NR(cru_readl(PLL_CONS(pll_id, 0))); + u32 dly = (nr * 500) / 24 + 1; + CLKDATA_DBG("pll_mode %s(%d)\n", clk->name, on); + if (on) { + cru_writel(PLL_PWR_ON | PLL_PWR_DN_W_MSK, PLL_CONS(pll_id, 3)); + rk30_clock_udelay(dly); + pll_wait_lock(pll_id); + cru_writel(PLL_MODE_NORM(pll_id), CRU_MODE_CON); + } else { + cru_writel(PLL_MODE_SLOW(pll_id), CRU_MODE_CON); + cru_writel(PLL_PWR_DN | PLL_PWR_DN_W_MSK, PLL_CONS(pll_id, 3)); + } + return 0; +} + +static int cpll_clk_set_rate(struct clk *c, unsigned long rate) +{ + struct _pll_data *pll_data = c->pll; + struct pll_clk_set *clk_set = (struct pll_clk_set *)pll_data->table; + struct pll_clk_set temp_clk_set; + u32 clk_nr, clk_nf, clk_no; + + + while(clk_set->rate) { + if (clk_set->rate == rate) { + break; + } + clk_set++; + } + if(clk_set->rate == rate) { + CLKDATA_DBG("cpll get a rate\n"); + pll_clk_set_rate(clk_set, pll_data->id); + + } else { + CLKDATA_DBG("cpll get auto calc a rate\n"); + if(pll_clk_get_set(c->parent->rate, rate, &clk_nr, &clk_nf, &clk_no) == 0) { + pr_err("cpll auto set rate error\n"); + return -ENOENT; + } + CLKDATA_DBG("cpll auto ger rate set nr=%d,nf=%d,no=%d\n", clk_nr, clk_nf, clk_no); + temp_clk_set.pllcon0 = PLL_CLKR_SET(clk_nr) | PLL_CLKOD_SET(clk_no); + temp_clk_set.pllcon1 = PLL_CLKF_SET(clk_nf); + temp_clk_set.rst_dly = (clk_nr * 500) / 24 + 1; + pll_clk_set_rate(&temp_clk_set, pll_data->id); + + } + return 0; +} + + +/* ******************fixed input clk ***********************************************/ +static struct clk xin24m = { + .name = "xin24m", + .rate = 24 * MHZ, + .flags = RATE_FIXED, +}; + +static struct clk clk_12m = { + .name = "clk_12m", + .parent = &xin24m, + .rate = 12 * MHZ, + .flags = RATE_FIXED, +}; + +/************************************pll func***************************/ +static const struct apll_clk_set *arm_pll_clk_get_best_pll_set(unsigned long rate, + struct apll_clk_set *tables) { + const struct apll_clk_set *ps, *pt; + + /* find the arm_pll we want. */ + ps = pt = tables; + while (pt->rate) { + if (pt->rate == rate) { + ps = pt; + break; + } + // we are sorted, and ps->rate > pt->rate. + if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate))) + ps = pt; + if (pt->rate < rate) + break; + pt++; + } + //CLKDATA_DBG("arm pll best rate=%lu\n",ps->rate); + return ps; +} +static long arm_pll_clk_round_rate(struct clk *clk, unsigned long rate) +{ + return arm_pll_clk_get_best_pll_set(rate, clk->pll->table)->rate; +} +#if 1 +struct arm_clks_div_set { + u32 rate; + u32 clksel0; + u32 clksel1; +}; + +#define _arm_clks_div_set(_mhz,_periph_div,_axi_div,_ahb_div, _apb_div,_ahb2apb) \ +{ \ + .rate =_mhz,\ + .clksel0 = CORE_PERIPH_W_MSK|CORE_PERIPH_##_periph_div,\ + .clksel1 = CORE_ACLK_W_MSK|CORE_ACLK_##_axi_div\ + |ACLK_HCLK_W_MSK|ACLK_HCLK_##_ahb_div\ + |ACLK_PCLK_W_MSK|ACLK_PCLK_##_apb_div\ + |AHB2APB_W_MSK |AHB2APB_##_ahb2apb,\ +} +struct arm_clks_div_set arm_clk_div_tlb[] = { + _arm_clks_div_set(50 , 2, 11, 11, 11, 11),//25,50,50,50,50 + _arm_clks_div_set(100 , 4, 11, 21, 21, 11),//25,100,50,50,50 + _arm_clks_div_set(150 , 4, 11, 21, 21, 11),//37,150,75,75,75 + _arm_clks_div_set(200 , 8, 21, 21, 21, 11),//25,100,50,50,50 + _arm_clks_div_set(300 , 8, 21, 21, 21, 11),//37,150,75,75,75 + _arm_clks_div_set(400 , 8, 21, 21, 41, 21),//50,200,100,50,50 + _arm_clks_div_set(0 , 2, 11, 11, 11, 11),//25,50,50,50,50 +}; +struct arm_clks_div_set *arm_clks_get_div(u32 rate) { + int i = 0; + for(i = 0; arm_clk_div_tlb[i].rate != 0; i++) { + if(arm_clk_div_tlb[i].rate >= rate) + return &arm_clk_div_tlb[i]; + } + return NULL; +} + +#endif + +static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + const struct apll_clk_set *ps; + u32 pll_id = clk->pll->id; + u32 temp_div; + u32 old_aclk_div = 0, new_aclk_div; + + ps = arm_pll_clk_get_best_pll_set(rate, (struct apll_clk_set *)clk->pll->table); + + old_aclk_div = GET_CORE_ACLK_VAL(cru_readl(CRU_CLKSELS_CON(1))&CORE_ACLK_MSK); + new_aclk_div = GET_CORE_ACLK_VAL(ps->clksel1 & CORE_ACLK_MSK); + + CLKDATA_LOG("apll will set rate(%lu) tlb con(%x,%x,%x),sel(%x,%x)\n", + ps->rate, ps->pllcon0, ps->pllcon1, ps->pllcon2, ps->clksel0, ps->clksel1); + + if(general_pll_clk.rate > clk->rate) { + temp_div = clk_get_freediv(clk->rate, general_pll_clk.rate, 10); + } else { + temp_div = 1; + } + + // ungating cpu gpll path + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_CPU_GPLL_PATH) | CLK_UN_GATE(CLK_GATE_CPU_GPLL_PATH), + // CLK_GATE_CLKID_CONS(CLK_GATE_CPU_GPLL_PATH)); + + local_irq_save(flags); + //div arm clk for gpll + + cru_writel(CORE_CLK_DIV_W_MSK|CORE_CLK_DIV(temp_div), CRU_CLKSELS_CON(0)); + cru_writel(CORE_SEL_PLL_W_MSK|CORE_SEL_GPLL, CRU_CLKSELS_CON(0)); + + loops_per_jiffy = lpj_gpll / temp_div; + smp_wmb(); + + /*if core src don't select gpll ,apll neet to enter slow mode */ + //cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON); + + + cru_writel((0x1<<(16+1))|(0x1<<1), PLL_CONS(pll_id, 3)); + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + dsb(); + cru_writel(ps->pllcon0, PLL_CONS(pll_id, 0)); + cru_writel(ps->pllcon1, PLL_CONS(pll_id, 1)); + + rk30_clock_udelay(1); + cru_writel((0x1<<(16+1)), PLL_CONS(pll_id, 3)); + + pll_wait_lock(pll_id); + + //return form slow + //cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON); + //reparent to apll + + if(new_aclk_div>=old_aclk_div) { + cru_writel(ps->clksel0, CRU_CLKSELS_CON(0)); + cru_writel(ps->clksel1, CRU_CLKSELS_CON(1)); + } + + cru_writel(CORE_SEL_PLL_W_MSK | CORE_SEL_APLL, CRU_CLKSELS_CON(0)); + if(old_aclk_div>new_aclk_div) { + cru_writel(ps->clksel0, CRU_CLKSELS_CON(0)); + cru_writel(ps->clksel1, CRU_CLKSELS_CON(1)); + } + + cru_writel(CORE_CLK_DIV_W_MSK|CORE_CLK_DIV(1), CRU_CLKSELS_CON(0)); + + loops_per_jiffy = ps->lpj; + smp_wmb(); + + //CLKDATA_DBG("apll set loops_per_jiffy =%lu,rate(%lu)\n",loops_per_jiffy,ps->rate); + + local_irq_restore(flags); + + //gate gpll path + // FIXME + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_CPU_GPLL_PATH) | CLK_GATE(CLK_GATE_CPU_GPLL_PATH) + // , CLK_GATE_CLKID_CONS(CLK_GATE_CPU_GPLL_PATH)); + + CLKDATA_LOG("apll set over con(%x,%x,%x,%x),sel(%x,%x)\n", cru_readl(PLL_CONS(pll_id, 0)), + cru_readl(PLL_CONS(pll_id, 1)), cru_readl(PLL_CONS(pll_id, 2)), + cru_readl(PLL_CONS(pll_id, 3)), cru_readl(CRU_CLKSELS_CON(0)), + cru_readl(CRU_CLKSELS_CON(1))); + return 0; +} + + +/************************************pll clocks***************************/ + +static const struct apll_clk_set apll_clks[] = { + //_APLL_SET_CLKS(_mhz, nr, nf, no, _periph_div, + // _axi_core_div, _axi_div, _ahb_div, _apb_div, _ahb2apb) + _APLL_SET_CLKS(2208, 1, 92, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2184, 1, 91, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2160, 1, 90, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2136, 1, 89, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2112, 1, 88, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2088, 1, 87, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2064, 1, 86, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2040, 1, 85, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(2016, 1, 84, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1992, 1, 83, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1968, 1, 82, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1944, 1, 81, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1920, 1, 80, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1896, 1, 79, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1872, 1, 78, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1848, 1, 77, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1824, 1, 76, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1800, 1, 75, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1776, 1, 74, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1752, 1, 73, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1728, 1, 72, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1704, 1, 71, 1, 8, 81, 81, 21, 41, 21), + _APLL_SET_CLKS(1680, 1, 70, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1656, 1, 69, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1632, 1, 68, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1608, 1, 67, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1560, 1, 65, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1512, 1, 63, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1488, 1, 62, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1464, 1, 61, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1440, 1, 60, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1416, 1, 59, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1392, 1, 58, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1368, 1, 57, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1344, 1, 56, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1320, 1, 55, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1296, 1, 54, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1272, 1, 53, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1248, 1, 52, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1224, 1, 51, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1200, 1, 50, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1176, 1, 49, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1128, 1, 47, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1104, 1, 46, 1, 8, 41, 41, 21, 41, 21), + _APLL_SET_CLKS(1008, 1, 84, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(912, 1, 76, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(888, 1, 74, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(816 , 1, 68, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(792 , 1, 66, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(696 , 1, 58, 2, 8, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(600 , 1, 50, 2, 4, 41, 31, 21, 41, 21), + _APLL_SET_CLKS(504 , 1, 84, 4, 4, 41, 21, 21, 41, 21), + _APLL_SET_CLKS(408 , 1, 68, 4, 4, 21, 21, 21, 41, 21), + _APLL_SET_CLKS(312 , 1, 52, 4, 2, 21, 21, 21, 21, 11), + _APLL_SET_CLKS(252 , 1, 84, 8, 2, 21, 21, 21, 21, 11), + _APLL_SET_CLKS(216 , 1, 72, 8, 2, 21, 21, 21, 21, 11), + _APLL_SET_CLKS(126 , 1, 84, 16, 2, 11, 21, 11, 11, 11), + _APLL_SET_CLKS(48 , 1, 64, 32, 2, 11, 11, 11, 11, 11), + _APLL_SET_CLKS(0 , 1, 21, 4, 2, 11, 11, 11, 11, 11), + +}; +static struct _pll_data apll_data = SET_PLL_DATA(APLL_ID, (void *)apll_clks); +static struct clk arm_pll_clk = { + .name = "arm_pll", + .parent = &xin24m, + .mode = pll_clk_mode, + .recalc = plls_clk_recalc, + .set_rate = arm_pll_clk_set_rate, + .round_rate = arm_pll_clk_round_rate, + .pll = &apll_data, +}; + +static int ddr_pll_clk_set_rate(struct clk *clk, unsigned long rate) +{ + /* do nothing here */ + return 0; +} +static struct _pll_data dpll_data = SET_PLL_DATA(DPLL_ID, NULL); +static struct clk ddr_pll_clk = { + .name = "ddr_pll", + .parent = &xin24m, + .recalc = plls_clk_recalc, + .set_rate = ddr_pll_clk_set_rate, + .pll = &dpll_data, +}; + +static const struct pll_clk_set cpll_clks[] = { + _PLL_SET_CLKS(360000, 1, 60, 4), + _PLL_SET_CLKS(408000, 1, 68, 4), + _PLL_SET_CLKS(456000, 1, 76, 4), + _PLL_SET_CLKS(504000, 1, 84, 4), + _PLL_SET_CLKS(552000, 1, 46, 2), + _PLL_SET_CLKS(600000, 1, 50, 2), + _PLL_SET_CLKS(742500, 8, 495, 2), + _PLL_SET_CLKS(768000, 1, 64, 2), + _PLL_SET_CLKS(798000, 2, 133, 2), + _PLL_SET_CLKS(1188000, 2, 99, 1), + _PLL_SET_CLKS( 0, 4, 133, 1), +}; +static struct _pll_data cpll_data = SET_PLL_DATA(CPLL_ID, (void *)cpll_clks); +static struct clk codec_pll_clk = { + .name = "codec_pll", + .parent = &xin24m, + .mode = pll_clk_mode, + .recalc = plls_clk_recalc, + .set_rate = cpll_clk_set_rate, + .pll = &cpll_data, +}; + +static const struct pll_clk_set gpll_clks[] = { + _PLL_SET_CLKS(148500, 2, 99, 8), + _PLL_SET_CLKS(297000, 2, 198, 8), + _PLL_SET_CLKS(300000, 1, 50, 4), + _PLL_SET_CLKS(594000, 2, 198, 4), + _PLL_SET_CLKS(1188000, 2, 99, 1), + _PLL_SET_CLKS(1200000, 1, 50, 1), + _PLL_SET_CLKS(0, 0, 0, 0), +}; +static struct _pll_data gpll_data = SET_PLL_DATA(GPLL_ID, (void *)gpll_clks); +static struct clk general_pll_clk = { + .name = "general_pll", + .parent = &xin24m, + .recalc = plls_clk_recalc, + .set_rate = gpll_clk_set_rate, + .pll = &gpll_data +}; +/********************************clocks***********************************/ +GATE_CLK(ddr_gpll_path, general_pll_clk, DDR_GPLL); + +/* core and cpu setting */ +static int ddr_clk_set_rate(struct clk *c, unsigned long rate) +{ + CLKDATA_DBG("%s do nothing for ddr set rate\n", __func__); + return 0; +} + +static long ddr_clk_round_rate(struct clk *clk, unsigned long rate) +{ + CLKDATA_DBG("%s do nothing for ddr round rate\n", __func__); + return ddr_set_pll(rate / MHZ, 0) * MHZ; +} +static unsigned long ddr_clk_recalc_rate(struct clk *clk) +{ + u32 shift = get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift); + unsigned long rate = clk->parent->recalc(clk->parent) >> shift; + //CLKDATA_DBG("%s new clock rate is %lu (shift %u)\n", clk->name, rate, shift); + return rate; +} +static struct clk *clk_ddr_parents[2] = {&ddr_pll_clk, &clk_ddr_gpll_path}; +static struct clk clk_ddr = { + .name = "ddr", + .parent = &ddr_pll_clk, + .recalc = ddr_clk_recalc_rate, + .set_rate = ddr_clk_set_rate, + .round_rate = ddr_clk_round_rate, + .gate_idx = CLK_GATE_DDRPHY, + .clksel_con = CRU_CLKSELS_CON(26), + CRU_DIV_SET(0x3, 0, 4), + CRU_SRC_SET(1, 8), + CRU_PARENTS_SET(clk_ddr_parents), +}; +static int clk_core_set_rate(struct clk *c, unsigned long rate) +{ + int ret; + + ret = clk_set_rate_nolock(c->parent, rate); + if (ret) { + CLKDATA_ERR("Failed to change clk pll %s to %lu\n", c->name, rate); + return ret; + } + //set arm pll div 1 + set_cru_bits_w_msk(0, c->div_mask, c->div_shift, c->clksel_con); + return 0; +} +static unsigned long clk_core_get_rate(struct clk *c) +{ + u32 div = (get_cru_bits(c->clksel_con, c->div_mask, c->div_shift) + 1); + //c->parent->rate=c->parent->recalc(c->parent); + return c->parent->rate / div; +} +static long core_clk_round_rate(struct clk *clk, unsigned long rate) +{ + u32 div = (get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift) + 1); + return clk_round_rate_nolock(clk->parent, rate) / div; +} + +static int core_clksel_set_parent(struct clk *clk, struct clk *new_prt) +{ + + u32 temp_div; + struct clk *old_prt; + + if(clk->parent == new_prt) + return 0; + if (unlikely(!clk->parents)) + return -EINVAL; + CLKDATA_DBG("%s,reparent %s\n", clk->name, new_prt->name); + //arm + old_prt = clk->parent; + + if(clk->parents[0] == new_prt) { + new_prt->set_rate(new_prt, 300 * MHZ); + set_cru_bits_w_msk(0, clk->div_mask, clk->div_shift, clk->clksel_con); + } else if(clk->parents[1] == new_prt) { + + if(new_prt->rate > old_prt->rate) { + temp_div = clk_get_freediv(old_prt->rate, new_prt->rate, clk->div_max); + set_cru_bits_w_msk(temp_div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + } + set_cru_bits_w_msk(1, clk->src_mask, clk->src_shift, clk->clksel_con); + new_prt->set_rate(new_prt, 300 * MHZ); + } else + return -1; + + + return 0; + +} + +static int core_gpll_clk_set_rate(struct clk *c, unsigned long rate) +{ + u32 temp_div; + u32 old_aclk_div = 0, new_aclk_div; + struct arm_clks_div_set *temp_clk_div; + unsigned long arm_gpll_rate, arm_gpll_lpj; + temp_div = clk_get_freediv(rate, c->parent->rate, c->div_max); + arm_gpll_rate = c->parent->rate / temp_div; + + temp_clk_div = arm_clks_get_div(arm_gpll_rate / MHZ); + if(!temp_clk_div) + temp_clk_div = &arm_clk_div_tlb[4]; + + old_aclk_div = GET_CORE_ACLK_VAL(cru_readl(CRU_CLKSELS_CON(1))&CORE_ACLK_MSK); + new_aclk_div = GET_CORE_ACLK_VAL(temp_clk_div->clksel1 & CORE_ACLK_MSK); + if(c->rate >= rate) { + arm_gpll_lpj = lpj_gpll / temp_div; + set_cru_bits_w_msk(temp_div - 1, c->div_mask, c->div_shift, c->clksel_con); + } + + cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1)); + cru_writel((temp_clk_div->clksel0) | CORE_CLK_DIV(temp_div) | CORE_CLK_DIV_W_MSK, + CRU_CLKSELS_CON(0)); + if((c->rate < rate)) { + arm_gpll_lpj = lpj_gpll / temp_div; + set_cru_bits_w_msk(temp_div - 1, c->div_mask, c->div_shift, c->clksel_con); + } + return 0; +} +static unsigned long arm_core_gpll_clk_get_rate(struct clk *c) +{ + return c->parent->rate; +} +static struct clk clk_core_gpll_path = { + .name = "cpu_gpll_path", + .parent = &general_pll_clk, + .recalc = arm_core_gpll_clk_get_rate, + .set_rate = core_gpll_clk_set_rate, + CRU_GATE_MODE_SET(gate_mode, CLK_GATE_CPU_GPLL_PATH), +}; + + +static struct clk *clk_core_parents[2] = {&arm_pll_clk, &clk_core_gpll_path}; + +static struct clk clk_core = { + .name = "core", + .parent = &arm_pll_clk, + .set_rate = clk_core_set_rate, + .recalc = clk_core_get_rate, + .round_rate = core_clk_round_rate, + .set_parent = core_clksel_set_parent, + .clksel_con = CRU_CLKSELS_CON(0), + CRU_DIV_SET(0x1f, 9, 32), + CRU_SRC_SET(1, 8), + CRU_PARENTS_SET(clk_core_parents), +}; +GATE_CLK(l2c, clk_core, CLK_L2C); +GATE_CLK(core_dbg, clk_core, CLK_CORE_DBG); +static unsigned long aclk_recalc(struct clk *clk) +{ + unsigned long rate; + u32 div = get_cru_bits(clk->clksel_con, clk->div_mask, clk->div_shift) + 1; + + BUG_ON(div > 5); + if (div >= 5) + div = 8; + rate = clk->parent->rate / div; + pr_debug("%s new clock rate is %ld (div %d)\n", clk->name, rate, div); + + return rate; +}; +static struct clk core_periph = { + .name = "core_periph", + .parent = &clk_core, + .gate_idx = CLK_GATE_CORE_PERIPH, + .recalc = clksel_recalc_shift_2, + .clksel_con = CRU_CLKSELS_CON(0), + CRU_DIV_SET(0x3, 6, 16), +}; +static struct clk aclk_core = { + .name = "aclk_core", + .parent = &clk_core, + .gate_idx = CLK_GATE_ACLK_CORE, + .recalc = aclk_recalc, + .clksel_con = CRU_CLKSELS_CON(1), + CRU_DIV_SET(0x7, 3, 8), +}; + +static struct clk *clk_cpu_div_parents[2] = {&arm_pll_clk, &clk_core_gpll_path}; +static struct clk clk_cpu_div = { + .name = "cpu_div", + .parent = &arm_pll_clk, + .set_rate = clksel_set_rate_freediv, + .recalc = clksel_recalc_div, + .clksel_con = CRU_CLKSELS_CON(0), + CRU_DIV_SET(0x1f, 0, 32), + CRU_SRC_SET(1, 5), + CRU_PARENTS_SET(clk_cpu_div_parents), +}; + +static struct clk aclk_cpu = { + .name = "aclk_cpu", + .parent = &clk_cpu_div, + .gate_idx = CLK_GATE_ACLK_CPU, +}; + +static struct clk hclk_cpu = { + .name = "hclk_cpu", + .parent = &aclk_cpu, + .gate_idx = CLK_GATE_HCLK_CPU, + .recalc = clksel_recalc_shift, + .set_rate = clksel_set_rate_shift, + .clksel_con = CRU_CLKSELS_CON(1), + CRU_DIV_SET(0x3, 8, 4), + +}; + +static struct clk pclk_cpu = { + .name = "pclk_cpu", + .parent = &aclk_cpu, + .gate_idx = CLK_GATE_PCLK_CPU, + .recalc = clksel_recalc_shift, + .set_rate = clksel_set_rate_shift, + .clksel_con = CRU_CLKSELS_CON(1), + CRU_DIV_SET(0x3, 12, 8), +}; + +static struct clk ahb2apb_cpu = { + .name = "ahb2apb", + .parent = &hclk_cpu, + .recalc = clksel_recalc_shift, + .set_rate = clksel_set_rate_shift, + .clksel_con = CRU_CLKSELS_CON(1), + CRU_DIV_SET(0x3, 14, 4), +}; + + +static struct clk atclk_cpu = { + .name = "atclk_cpu", + .parent = &pclk_cpu, + .gate_idx = CLK_GATE_ATCLK_CPU, +}; + +/* GPU setting */ +static int clk_gpu_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long max_rate = rate / 100 * 105; /* +5% */ + return clkset_rate_freediv_autosel_parents(clk, max_rate); +}; + +static struct clk *aclk_gpu_parents[2] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_gpu = { + .name = "aclk_gpu", + .mode = gate_mode, + .recalc = clksel_recalc_div, + .round_rate = clk_freediv_round_autosel_parents_rate, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(34), + .gate_idx = CLK_GATE_ACLK_GPU, + CRU_DIV_SET(0x1f, 0, 32), + CRU_SRC_SET(0x1, 7), + CRU_PARENTS_SET(aclk_gpu_parents), +}; + +/* vcodec setting */ +static unsigned long clksel_recalc_vpu_hclk(struct clk *clk) +{ + unsigned long rate = clk->parent->rate / 4; + pr_debug("%s new clock rate is %lu (div %u)\n", clk->name, rate, 4); + return rate; +} + +static struct clk *aclk_vepu_parents[2] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_vepu = { + .name = "aclk_vepu", + .parent = &codec_pll_clk, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clkset_rate_freediv_autosel_parents, + .clksel_con = CRU_CLKSELS_CON(32), + .gate_idx = CLK_GATE_ACLK_VEPU, + CRU_DIV_SET(0x1f, 0, 32), + CRU_SRC_SET(0x1, 7), + CRU_PARENTS_SET(aclk_vepu_parents), +}; + +static struct clk *aclk_vdpu_parents[2] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_vdpu = { + .name = "aclk_vdpu", + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clkset_rate_freediv_autosel_parents, + .clksel_con = CRU_CLKSELS_CON(32), + .gate_idx = CLK_GATE_ACLK_VDPU, + CRU_DIV_SET(0x1f, 8, 32), + CRU_SRC_SET(0x1, 15), + CRU_PARENTS_SET(aclk_vdpu_parents), +}; +static struct clk hclk_vepu = { + .name = "hclk_vepu", + .parent = &aclk_vepu, + .mode = gate_mode, + .recalc = clksel_recalc_vpu_hclk, + .gate_idx = CLK_GATE_HCLK_VEPU, +}; + +static struct clk hclk_vdpu = { + .name = "hclk_vdpu", + .parent = &aclk_vdpu, + .mode = gate_mode, + .recalc = clksel_recalc_vpu_hclk, + .gate_idx = CLK_GATE_HCLK_VDPU, +}; + +/* aclk lcdc setting */ +static struct clk *aclk_lcdc0_parents[] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_lcdc0_pre = { + .name = "aclk_lcdc0_pre", + .parent = &codec_pll_clk, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clkset_rate_freediv_autosel_parents, + .gate_idx = CLK_GATE_ACLK_LCDC0_SRC, + .clksel_con = CRU_CLKSELS_CON(31), + CRU_DIV_SET(0x1f, 0, 32), + CRU_SRC_SET(0x1, 7), + CRU_PARENTS_SET(aclk_lcdc0_parents), +}; + +static struct clk *aclk_lcdc1_parents[] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_lcdc1_pre = { + .name = "aclk_lcdc1_pre", + .parent = &codec_pll_clk, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clkset_rate_freediv_autosel_parents, + .gate_idx = CLK_GATE_ACLK_LCDC1_SRC, + .clksel_con = CRU_CLKSELS_CON(31), + CRU_DIV_SET(0x1f, 8, 32), + CRU_SRC_SET(0x1, 15), + CRU_PARENTS_SET(aclk_lcdc1_parents), +}; + +/* aclk/hclk/pclk periph setting */ +static struct clk *aclk_periph_parents[2] = {&codec_pll_clk, &general_pll_clk}; + +static struct clk aclk_periph = { + .name = "aclk_periph", + .parent = &general_pll_clk, + .mode = gate_mode, + .gate_idx = CLK_GATE_ACLK_PERIPH, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(10), + CRU_DIV_SET(0x1f, 0, 32), + CRU_SRC_SET(1, 15), + CRU_PARENTS_SET(aclk_periph_parents), +}; +GATE_CLK(periph_src, aclk_periph, PERIPH_SRC); + +static struct clk pclk_periph = { + .name = "pclk_periph", + .parent = &aclk_periph, + .mode = gate_mode, + .gate_idx = CLK_GATE_PCLK_PERIPH, + .recalc = clksel_recalc_shift, + .set_rate = clksel_set_rate_shift, + .clksel_con = CRU_CLKSELS_CON(10), + CRU_DIV_SET(0x3, 12, 8), +}; + +static struct clk hclk_periph = { + .name = "hclk_periph", + .parent = &aclk_periph, + .mode = gate_mode, + .gate_idx = CLK_GATE_HCLK_PERIPH, + .recalc = clksel_recalc_shift, + .set_rate = clksel_set_rate_shift, + .clksel_con = CRU_CLKSELS_CON(10), + CRU_DIV_SET(0x3, 8, 4), +}; +/* dclk lcdc setting */ +// FIXME +static int clksel_set_rate_hdmi(struct clk *clk, unsigned long rate) +{ + u32 div, old_div; + int i; + unsigned long new_rate; + int ret = 0; + + if(clk->rate == rate) + return 0; + for(i = 0; i < 2; i++) { + div = clk_get_freediv(rate, clk->parents[i]->rate, clk->div_max); + new_rate = clk->parents[i]->rate / div; + if((rate == new_rate) && !(clk->parents[i]->rate % div)) { + break; + } + } + if(i >= 2) { + CLKDATA_ERR("%s can't set fixed rate%lu\n", clk->name, rate); + return -1; + } + + //CLKDATA_DBG("%s set rate %lu(from %s)\n",clk->name,rate,clk->parents[i]->name); + + old_div = CRU_GET_REG_BITS_VAL(cru_readl(clk->clksel_con), + clk->div_shift, clk->div_mask) + 1; + if(div > old_div) + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + + if(clk->parents[i] != clk->parent) { + ret = clk_set_parent_nolock(clk, clk->parents[i]); + } + + if (ret) { + CLKDATA_ERR("lcdc1 %s can't get rate%lu,reparent%s(now %s) err\n", + clk->name, rate, clk->parents[i]->name, clk->parent->name); + return ret; + } + set_cru_bits_w_msk(div - 1, clk->div_mask, clk->div_shift, clk->clksel_con); + return 0; +} + +static int dclk_lcdc_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + struct clk *parent; + + if (rate == 27 * MHZ && (rk30_clock_flags & CLK_FLG_EXT_27MHZ)) { + parent = clk->parents[1]; + //CLKDATA_DBG(" %s from=%s\n",clk->name,parent->name); + } else { + parent = clk->parents[0]; + } + //CLKDATA_DBG(" %s set rate=%lu parent %s(old %s)\n", + //clk->name,rate,parent->name,clk->parent->name); + + if(parent != clk->parents[1]) { + ret = clk_set_rate_nolock(parent, rate); //div 1:1 + if (ret) { + CLKDATA_DBG("%s set rate=%lu err\n", clk->name, rate); + return ret; + } + } + if (clk->parent != parent) { + ret = clk_set_parent_nolock(clk, parent); + if (ret) { + CLKDATA_DBG("%s can't get rate%lu,reparent err\n", clk->name, rate); + return ret; + } + } + return ret; +} + +static struct clk *dclk_lcdc0_parents[2] = {&codec_pll_clk, &general_pll_clk}; +static struct clk dclk_lcdc0 = { + .name = "dclk_lcdc0", + .mode = gate_mode, + .set_rate = clkset_rate_freediv_autosel_parents, + .recalc = clksel_recalc_div, + .gate_idx = CLK_GATE_DCLK_LCDC0_SRC, + .clksel_con = CRU_CLKSELS_CON(27), + CRU_SRC_SET(0x1, 0), + CRU_DIV_SET(0xff, 8, 256), + CRU_PARENTS_SET(dclk_lcdc0_parents), +}; + +static struct clk *dclk_lcdc1_parents[2] = {&codec_pll_clk, &general_pll_clk}; +static struct clk dclk_lcdc1 = { + .name = "dclk_lcdc1", + .mode = gate_mode, + .set_rate = clkset_rate_freediv_autosel_parents, + .recalc = clksel_recalc_div, + .gate_idx = CLK_GATE_DCLK_LCDC1_SRC, + .clksel_con = CRU_CLKSELS_CON(28), + CRU_SRC_SET(0x1, 0), + CRU_DIV_SET(0xff, 8, 256), + CRU_PARENTS_SET(dclk_lcdc1_parents), +}; + +/* cif setting */ +// FIXME +static struct clk *cifout_sel_pll_parents[2] = {&codec_pll_clk, &general_pll_clk}; +static struct clk cif_out_pll = { + .name = "cif_out_pll", + .parent = &general_pll_clk, + .clksel_con = CRU_CLKSELS_CON(29), + CRU_SRC_SET(0x1, 0), + CRU_PARENTS_SET(cifout_sel_pll_parents), +}; + +static struct clk cif0_out_div = { + .name = "cif0_out_div", + .parent = &cif_out_pll, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_CIF0_OUT, + .clksel_con = CRU_CLKSELS_CON(29), + CRU_DIV_SET(0x1f, 1, 32), +}; + +static int cif_out_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + struct clk *parent; + + if (rate == 24 * MHZ) { + parent = clk->parents[1]; + } else { + parent = clk->parents[0]; + ret = clk_set_rate_nolock(parent, rate); + if (ret) + return ret; + } + if (clk->parent != parent) + ret = clk_set_parent_nolock(clk, parent); + + return ret; +} + +static struct clk *cif0_out_parents[2] = {&cif0_out_div, &xin24m}; +static struct clk cif0_out = { + .name = "cif0_out", + .parent = &cif0_out_div, + .set_rate = cif_out_set_rate, + .clksel_con = CRU_CLKSELS_CON(29), + CRU_SRC_SET(0x1, 7), + CRU_PARENTS_SET(cif0_out_parents), +}; + +static struct clk pclkin_cif0 = { + .name = "pclkin_cif0", + .mode = gate_mode, + .gate_idx = CLK_GATE_PCLKIN_CIF0, +}; + +static struct clk inv_cif0 = { + .name = "inv_cif0", + .parent = &pclkin_cif0, +}; + +static struct clk *cif0_in_parents[2] = {&pclkin_cif0, &inv_cif0}; +static struct clk cif0_in = { + .name = "cif0_in", + .parent = &pclkin_cif0, + .clksel_con = CRU_CLKSELS_CON(30), + CRU_SRC_SET(0x1, 8), + CRU_PARENTS_SET(cif0_in_parents), +}; + +/* i2s/spdif setting */ +static struct clk *clk_i2s_div_parents[] = {&general_pll_clk, &codec_pll_clk}; +static struct clk clk_i2s_pll = { + .name = "i2s_pll", + .parent = &general_pll_clk, + .clksel_con = CRU_CLKSELS_CON(2), + CRU_SRC_SET(0x1, 15), + CRU_PARENTS_SET(clk_i2s_div_parents), +}; + +static struct clk clk_i2s0_div = { + .name = "i2s0_div", + .parent = &clk_i2s_pll, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .round_rate = clksel_freediv_round_rate, + .gate_idx = CLK_GATE_I2S0_SRC, + .clksel_con = CRU_CLKSELS_CON(3), + CRU_DIV_SET(0x7f, 0, 64), +}; + +static struct clk clk_spdif_div = { + .name = "spdif_div", + .parent = &clk_i2s_pll, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .round_rate = clksel_freediv_round_rate, + .mode = gate_mode, + .gate_idx = CLK_GATE_SPDIF_SRC, + .clksel_con = CRU_CLKSELS_CON(5), + CRU_DIV_SET(0x7f, 0, 64), +}; +static int clk_i2s_fracdiv_set_rate(struct clk *clk, unsigned long rate) +{ + u32 numerator, denominator; + //clk_i2s_div->clk_i2s_pll->gpll/cpll + //clk->parent->parent + if(frac_div_get_seting(rate, clk->parent->parent->rate, + &numerator, &denominator) == 0) { + clk_set_rate_nolock(clk->parent, clk->parent->parent->rate); //PLL:DIV 1: + cru_writel_frac(numerator << 16 | denominator, clk->clksel_con); + CLKDATA_DBG("%s set rate=%lu,is ok\n", clk->name, rate); + } else { + CLKDATA_ERR("clk_frac_div can't get rate=%lu,%s\n", rate, clk->name); + return -ENOENT; + } + return 0; +} + +static struct clk clk_i2s0_frac_div = { + .name = "i2s0_frac_div", + .parent = &clk_i2s0_div, + .mode = gate_mode, + .gate_idx = CLK_GATE_I2S0_FRAC, + .recalc = clksel_recalc_frac, + .set_rate = clk_i2s_fracdiv_set_rate, + .clksel_con = CRU_CLKSELS_CON(7), +}; + +static struct clk clk_spdif_frac_div = { + .name = "spdif_frac_div", + .parent = &clk_spdif_div, + .mode = gate_mode, + .gate_idx = CLK_GATE_SPDIF_FRAC, + .recalc = clksel_recalc_frac, + .set_rate = clk_i2s_fracdiv_set_rate, + .clksel_con = CRU_CLKSELS_CON(9), +}; + +#define I2S_SRC_DIV (0x0) +#define I2S_SRC_FRAC (0x1) +#define I2S_SRC_12M (0x2) + +static int i2s_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + struct clk *parent; + + if (rate == clk->parents[I2S_SRC_12M]->rate) { + parent = clk->parents[I2S_SRC_12M]; + } else if((long)clk_round_rate_nolock(clk->parents[I2S_SRC_DIV], rate) == rate) { + parent = clk->parents[I2S_SRC_DIV]; + } else { + parent = clk->parents[I2S_SRC_FRAC]; + } + + CLKDATA_DBG(" %s set rate=%lu parent %s(old %s)\n", + clk->name, rate, parent->name, clk->parent->name); + + if(parent != clk->parents[I2S_SRC_12M]) { + ret = clk_set_rate_nolock(parent, rate); //div 1:1 + if (ret) { + CLKDATA_DBG("%s set rate%lu err\n", clk->name, rate); + return ret; + } + } + + if (clk->parent != parent) { + ret = clk_set_parent_nolock(clk, parent); + if (ret) { + CLKDATA_DBG("%s can't get rate%lu,reparent err\n", clk->name, rate); + return ret; + } + } + + return ret; +}; + +static struct clk *clk_i2s0_parents[3] = {&clk_i2s0_div, &clk_i2s0_frac_div, &clk_12m}; + +static struct clk clk_i2s0 = { + .name = "i2s0", + .set_rate = i2s_set_rate, + .clksel_con = CRU_CLKSELS_CON(3), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_i2s0_parents), +}; + +static struct clk *clk_spdif_parents[3] = {&clk_spdif_div, &clk_spdif_frac_div, &clk_12m}; + +static struct clk clk_spdif = { + .name = "spdif", + .parent = &clk_spdif_frac_div, + .set_rate = i2s_set_rate, + .clksel_con = CRU_CLKSELS_CON(5), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_spdif_parents), +}; + +/* otgphy setting */ +GATE_CLK(otgphy0, xin24m, OTGPHY0); +GATE_CLK(otgphy1, xin24m, OTGPHY1); + +static struct clk clk_otgphy0_480m = { + .name = "otgphy0_480m", + .parent = &clk_otgphy0, +}; +static struct clk clk_otgphy1_480m = { + .name = "otgphy1_480m", + .parent = &clk_otgphy1, +}; + +/* hsicphy setting */ +#ifdef ARCH_RK31 +static struct clk *clk_hsicphy_parents[4] = {&clk_otgphy0_480m, &clk_otgphy1_480m, &general_pll_clk, &codec_pll_clk}; +static struct clk clk_hsicphy_480m = { + .name = "hsicphy_480m", + .parent = &clk_otgphy0_480m, + .clksel_con = CRU_CLKSELS_CON(30), + CRU_SRC_SET(0x3, 0), + CRU_PARENTS_SET(clk_hsicphy_parents), +}; +static struct clk clk_hsicphy_12m = { + .name = "hsicphy_12m", + .parent = &clk_hsicphy_480m, + .clksel_con = CRU_CLKSELS_CON(11), + CRU_DIV_SET(0x3f, 8, 64), +}; +#endif + +/* mac and rmii setting */ +// FIXME +static struct clk rmii_clkin = { + .name = "rmii_clkin", +}; +static struct clk *clk_mac_ref_div_parents[2] = {&general_pll_clk, &ddr_pll_clk}; +static struct clk clk_mac_pll_div = { + .name = "mac_pll_div", + .parent = &general_pll_clk, + .mode = gate_mode, + .gate_idx = CLK_GATE_MAC_SRC, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(21), + CRU_DIV_SET(0x1f, 8, 32), + CRU_SRC_SET(0x1, 0), + CRU_PARENTS_SET(clk_mac_ref_div_parents), +}; + +static int clksel_mac_ref_set_rate(struct clk *clk, unsigned long rate) +{ + if(clk->parent == clk->parents[1]) { + CLKDATA_DBG("mac_ref clk is form mii clkin,can't set it\n" ); + return -ENOENT; + } else if(clk->parent == clk->parents[0]) { + return clk_set_rate_nolock(clk->parents[0], rate); + } + return -ENOENT; +} + +static struct clk *clk_mac_ref_parents[2] = {&clk_mac_pll_div, &rmii_clkin}; + +static struct clk clk_mac_ref = { + .name = "mac_ref", + .parent = &clk_mac_pll_div, + .set_rate = clksel_mac_ref_set_rate, + .clksel_con = CRU_CLKSELS_CON(21), + CRU_SRC_SET(0x1, 4), + CRU_PARENTS_SET(clk_mac_ref_parents), +}; + +static int clk_set_mii_tx_parent(struct clk *clk, struct clk *parent) +{ + return clk_set_parent_nolock(clk->parent, parent); +} + +static struct clk clk_mii_tx = { + .name = "mii_tx", + .parent = &clk_mac_ref, + //.set_parent = clk_set_mii_tx_parent, + .mode = gate_mode, + .gate_idx = CLK_GATE_MAC_LBTEST, +}; + +/* hsadc and saradc */ +static struct clk *clk_hsadc_pll_parents[2] = {&general_pll_clk, &codec_pll_clk}; +static struct clk clk_hsadc_pll_div = { + .name = "hsadc_pll_div", + .parent = &general_pll_clk, + .mode = gate_mode, + .gate_idx = CLK_GATE_HSADC_SRC, + .recalc = clksel_recalc_div, + .round_rate = clk_freediv_round_autosel_parents_rate, + .set_rate = clkset_rate_freediv_autosel_parents, + //.round_rate = clksel_freediv_round_rate, + //.set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(22), + CRU_DIV_SET(0xff, 8, 256), + CRU_SRC_SET(0x1, 0), + CRU_PARENTS_SET(clk_hsadc_pll_parents), +}; +static int clk_hsadc_fracdiv_set_rate_fixed_parent(struct clk *clk, unsigned long rate) +{ + u32 numerator, denominator; + // clk_hsadc_pll_div->gpll/cpll + //clk->parent->parent + if(frac_div_get_seting(rate, clk->parent->parent->rate, + &numerator, &denominator) == 0) { + clk_set_rate_nolock(clk->parent, clk->parent->parent->rate); //PLL:DIV 1: + + cru_writel_frac(numerator << 16 | denominator, clk->clksel_con); + + CLKDATA_DBG("%s set rate=%lu,is ok\n", clk->name, rate); + } else { + CLKDATA_ERR("clk_frac_div can't get rate=%lu,%s\n", rate, clk->name); + return -ENOENT; + } + return 0; +} +static int clk_hsadc_fracdiv_set_rate_auto_parents(struct clk *clk, unsigned long rate) +{ + u32 numerator, denominator; + u32 i, ret = 0; + // clk_hsadc_pll_div->gpll/cpll + //clk->parent->parent + for(i = 0; i < 2; i++) { + if(frac_div_get_seting(rate, clk->parent->parents[i]->rate, + &numerator, &denominator) == 0) + break; + } + if(i >= 2) + return -ENOENT; + + if(clk->parent->parent != clk->parent->parents[i]) + ret = clk_set_parent_nolock(clk->parent, clk->parent->parents[i]); + if(ret == 0) { + clk_set_rate_nolock(clk->parent, clk->parent->parents[i]->rate); //PLL:DIV 1: + + cru_writel_frac(numerator << 16 | denominator, clk->clksel_con); + + CLKDATA_DBG("clk_frac_div %s, rate=%lu\n", clk->name, rate); + } else { + CLKDATA_ERR("clk_frac_div can't get rate=%lu,%s\n", rate, clk->name); + return -ENOENT; + } + return 0; +} + +static long clk_hsadc_fracdiv_round_rate(struct clk *clk, unsigned long rate) +{ + u32 numerator, denominator; + + CLKDATA_ERR("clk_hsadc_fracdiv_round_rate\n"); + if(frac_div_get_seting(rate, clk->parent->parent->rate, + &numerator, &denominator) == 0) + return rate; + + return 0; +} +static struct clk clk_hsadc_frac_div = { + .name = "hsadc_frac_div", + .parent = &clk_hsadc_pll_div, + .mode = gate_mode, + .recalc = clksel_recalc_frac, + .set_rate = clk_hsadc_fracdiv_set_rate_auto_parents, + .round_rate = clk_hsadc_fracdiv_round_rate, + .gate_idx = CLK_GATE_HSADC_FRAC_SRC, + .clksel_con = CRU_CLKSELS_CON(23), +}; + +#define HSADC_SRC_DIV 0x0 +#define HSADC_SRC_FRAC 0x1 +#define HSADC_SRC_EXT 0x2 +static int clk_hsadc_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + struct clk *parent; + + if(clk->parent == clk->parents[HSADC_SRC_EXT]) { + CLKDATA_DBG("hsadc clk is form ext\n"); + return 0; + } else if((long)clk_round_rate_nolock(clk->parents[HSADC_SRC_DIV], rate) == rate) { + parent = clk->parents[HSADC_SRC_DIV]; + } else if((long)clk_round_rate_nolock(clk->parents[HSADC_SRC_FRAC], rate) == rate) { + parent = clk->parents[HSADC_SRC_FRAC]; + } else + parent = clk->parents[HSADC_SRC_DIV]; + + CLKDATA_DBG(" %s set rate=%lu parent %s(old %s)\n", + clk->name, rate, parent->name, clk->parent->name); + + ret = clk_set_rate_nolock(parent, rate); + if (ret) { + CLKDATA_ERR("%s set rate%lu err\n", clk->name, rate); + return ret; + } + if (clk->parent != parent) { + ret = clk_set_parent_nolock(clk, parent); + if (ret) { + CLKDATA_ERR("%s can't get rate%lu,reparent err\n", clk->name, rate); + return ret; + } + } + return ret; +} + +static struct clk clk_hsadc_ext = { + .name = "hsadc_ext", +}; + +static struct clk *clk_hsadc_out_parents[3] = {&clk_hsadc_pll_div, &clk_hsadc_frac_div, &clk_hsadc_ext}; +static struct clk clk_hsadc_out = { + .name = "hsadc_out", + .parent = &clk_hsadc_pll_div, + .set_rate = clk_hsadc_set_rate, + .clksel_con = CRU_CLKSELS_CON(22), + CRU_SRC_SET(0x3, 4), + CRU_PARENTS_SET(clk_hsadc_out_parents), +}; +static struct clk clk_hsadc_out_inv = { + .name = "hsadc_out_inv", + .parent = &clk_hsadc_out, +}; + +static struct clk *clk_hsadc_parents[3] = {&clk_hsadc_out, &clk_hsadc_out_inv}; +static struct clk clk_hsadc = { + .name = "hsadc", + .parent = &clk_hsadc_out, + .clksel_con = CRU_CLKSELS_CON(22), + CRU_SRC_SET(0x1, 7), + CRU_PARENTS_SET(clk_hsadc_parents), +}; + +static struct clk clk_saradc = { + .name = "saradc", + .parent = &xin24m, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_SARADC_SRC, + .clksel_con = CRU_CLKSELS_CON(24), + CRU_DIV_SET(0xff, 8, 256), +}; + +/* smc setting */ +GATE_CLK(smc, hclk_periph, SMC_SRC);//smc +static struct clk clkn_smc = { + .name = "smc_inv", + .parent = &clk_smc, +}; + +/* spi setting */ +static struct clk clk_spi0 = { + .name = "spi0", + .parent = &pclk_periph, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_SPI0_SRC, + .clksel_con = CRU_CLKSELS_CON(25), + CRU_DIV_SET(0x7f, 0, 128), +}; + +static struct clk clk_spi1 = { + .name = "spi1", + .parent = &pclk_periph, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_SPI1_SRC, + .clksel_con = CRU_CLKSELS_CON(25), + CRU_DIV_SET(0x7f, 8, 128), +}; + +/* sdmmc/sdio/emmc setting */ +static struct clk clk_sdmmc = { + .name = "sdmmc", + .parent = &hclk_periph, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_MMC0_SRC, + .clksel_con = CRU_CLKSELS_CON(11), + CRU_DIV_SET(0x3f, 0, 64), +}; + +static struct clk clk_sdio = { + .name = "sdio", + .parent = &hclk_periph, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_SDIO_SRC, + .clksel_con = CRU_CLKSELS_CON(12), + CRU_DIV_SET(0x3f, 0, 64), + +}; + +static struct clk clk_emmc = { + .name = "emmc", + .parent = &hclk_periph, + .mode = gate_mode, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .gate_idx = CLK_GATE_EMMC_SRC, + .clksel_con = CRU_CLKSELS_CON(12), + CRU_DIV_SET(0x3f, 8, 64), +}; + +/* uart setting */ +static struct clk *clk_uart_src_parents[2] = {&general_pll_clk, &codec_pll_clk}; +static struct clk clk_uart_pll = { + .name = "uart_pll", + .parent = &general_pll_clk, + .clksel_con = CRU_CLKSELS_CON(12), + CRU_SRC_SET(0x1, 15), + CRU_PARENTS_SET(clk_uart_src_parents), +}; +static struct clk clk_uart0_div = { + .name = "uart0_div", + .parent = &clk_uart_pll, + .mode = gate_mode, + .gate_idx = CLK_GATE_UART0_SRC, + .recalc = clksel_recalc_div, + .set_rate = clksel_set_rate_freediv, + .round_rate = clksel_freediv_round_rate, + .clksel_con = CRU_CLKSELS_CON(13), + CRU_DIV_SET(0x7f, 0, 64), +}; +static struct clk clk_uart1_div = { + .name = "uart1_div", + .parent = &clk_uart_pll, + .mode = gate_mode, + .gate_idx = CLK_GATE_UART1_SRC, + .recalc = clksel_recalc_div, + .round_rate = clksel_freediv_round_rate, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(14), + CRU_DIV_SET(0x7f, 0, 64), +}; + +static struct clk clk_uart2_div = { + .name = "uart2_div", + .parent = &clk_uart_pll, + .mode = gate_mode, + .gate_idx = CLK_GATE_UART2_SRC, + .recalc = clksel_recalc_div, + .round_rate = clksel_freediv_round_rate, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(15), + CRU_DIV_SET(0x7f, 0, 64), +}; + +static struct clk clk_uart3_div = { + .name = "uart3_div", + .parent = &clk_uart_pll, + .mode = gate_mode, + .gate_idx = CLK_GATE_UART3_SRC, + .recalc = clksel_recalc_div, + .round_rate = clksel_freediv_round_rate, + .set_rate = clksel_set_rate_freediv, + .clksel_con = CRU_CLKSELS_CON(16), + CRU_DIV_SET(0x7f, 0, 64), +}; +static int clk_uart_fracdiv_set_rate(struct clk *clk, unsigned long rate) +{ + u32 numerator, denominator; + //clk_uart0_div->clk_uart_pll->gpll/cpll + //clk->parent->parent + if(frac_div_get_seting(rate, clk->parent->parent->rate, + &numerator, &denominator) == 0) { + clk_set_rate_nolock(clk->parent, clk->parent->parent->rate); //PLL:DIV 1: + + cru_writel_frac(numerator << 16 | denominator, clk->clksel_con); + + CLKDATA_DBG("%s set rate=%lu,is ok\n", clk->name, rate); + } else { + CLKDATA_ERR("clk_frac_div can't get rate=%lu,%s\n", rate, clk->name); + return -ENOENT; + } + return 0; +} + +static struct clk clk_uart0_frac_div = { + .name = "uart0_frac_div", + .parent = &clk_uart0_div, + .mode = gate_mode, + .recalc = clksel_recalc_frac, + .set_rate = clk_uart_fracdiv_set_rate, + .gate_idx = CLK_GATE_UART0_FRAC_SRC, + .clksel_con = CRU_CLKSELS_CON(17), +}; +static struct clk clk_uart1_frac_div = { + .name = "uart1_frac_div", + .parent = &clk_uart1_div, + .mode = gate_mode, + .recalc = clksel_recalc_frac, + .set_rate = clk_uart_fracdiv_set_rate, + .gate_idx = CLK_GATE_UART1_FRAC_SRC, + .clksel_con = CRU_CLKSELS_CON(18), +}; +static struct clk clk_uart2_frac_div = { + .name = "uart2_frac_div", + .mode = gate_mode, + .parent = &clk_uart2_div, + .recalc = clksel_recalc_frac, + .set_rate = clk_uart_fracdiv_set_rate, + .gate_idx = CLK_GATE_UART2_FRAC_SRC, + .clksel_con = CRU_CLKSELS_CON(19), +}; +static struct clk clk_uart3_frac_div = { + .name = "uart3_frac_div", + .parent = &clk_uart3_div, + .mode = gate_mode, + .recalc = clksel_recalc_frac, + .set_rate = clk_uart_fracdiv_set_rate, + .gate_idx = CLK_GATE_UART3_FRAC_SRC, + .clksel_con = CRU_CLKSELS_CON(20), +}; + +#define UART_SRC_DIV 0 +#define UART_SRC_FRAC 1 +#define UART_SRC_24M 2 + +static int clk_uart_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + struct clk *parent; + + if(rate == clk->parents[UART_SRC_24M]->rate) { //24m + parent = clk->parents[UART_SRC_24M]; + } else if((long)clk_round_rate_nolock(clk->parents[UART_SRC_DIV], rate) == rate) { + parent = clk->parents[UART_SRC_DIV]; + } else { + parent = clk->parents[UART_SRC_FRAC]; + } + + CLKDATA_DBG(" %s set rate=%lu parent %s(old %s)\n", + clk->name, rate, parent->name, clk->parent->name); + + if(parent != clk->parents[UART_SRC_24M]) { + ret = clk_set_rate_nolock(parent, rate); + if (ret) { + CLKDATA_DBG("%s set rate%lu err\n", clk->name, rate); + return ret; + } + } + + if (clk->parent != parent) { + ret = clk_set_parent_nolock(clk, parent); + if (ret) { + CLKDATA_DBG("%s can't get rate%lu,reparent err\n", clk->name, rate); + return ret; + } + } + + return ret; +} + +static struct clk *clk_uart0_parents[3] = {&clk_uart0_div, &clk_uart0_frac_div, &xin24m}; +static struct clk clk_uart0 = { + .name = "uart0", + .set_rate = clk_uart_set_rate, + .clksel_con = CRU_CLKSELS_CON(13), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_uart0_parents), +}; + +static struct clk *clk_uart1_parents[3] = {&clk_uart1_div, &clk_uart1_frac_div, &xin24m}; +static struct clk clk_uart1 = { + .name = "uart1", + .set_rate = clk_uart_set_rate, + .clksel_con = CRU_CLKSELS_CON(14), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_uart1_parents), +}; + +static struct clk *clk_uart2_parents[3] = {&clk_uart2_div, &clk_uart2_frac_div, &xin24m}; +static struct clk clk_uart2 = { + .name = "uart2", + .set_rate = clk_uart_set_rate, + .clksel_con = CRU_CLKSELS_CON(15), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_uart2_parents), +}; +static struct clk *clk_uart3_parents[3] = {&clk_uart3_div, &clk_uart3_frac_div, &xin24m}; +static struct clk clk_uart3 = { + .name = "uart3", + .set_rate = clk_uart_set_rate, + .clksel_con = CRU_CLKSELS_CON(16), + CRU_SRC_SET(0x3, 8), + CRU_PARENTS_SET(clk_uart3_parents), +}; + +/* timer setting */ +GATE_CLK(timer0, xin24m, TIMER0); +GATE_CLK(timer1, xin24m, TIMER1); +GATE_CLK(timer2, xin24m, TIMER2); +GATE_CLK(timer3, xin24m, TIMER3); +GATE_CLK(timer4, xin24m, TIMER4); +GATE_CLK(timer5, xin24m, TIMER5); +GATE_CLK(timer6, xin24m, TIMER6); + +/*********************power domain*******************************/ +#if 1 +#ifdef RK30_CLK_OFFBOARD_TEST +void pmu_set_power_domain_test(enum pmu_power_domain pd, bool on) {}; +#define _pmu_set_power_domain pmu_set_power_domain_test//rk30_pmu_set_power_domain +#else +void pmu_set_power_domain(enum pmu_power_domain pd, bool on); +#define _pmu_set_power_domain pmu_set_power_domain +#endif + +static int pd_video_mode(struct clk *clk, int on) +{ + u32 gate[3]; + gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU)); + gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU)); + //gate[2] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VEPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VDPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU)); + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VCODEC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC)); + pmu_set_power_domain(PD_VIDEO, on); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VEPU) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VEPU)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VDPU) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VDPU)); + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VCODEC) | gate[2], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VCODEC)); + return 0; +} + +static struct clk pd_video = { + .name = "pd_video", + .flags = IS_PD, + .mode = pd_video_mode, + .gate_idx = PD_VIDEO, +}; +static int pd_display_mode(struct clk *clk, int on) +{ + u32 gate[10]; + gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC)); + gate[1] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC)); + gate[2] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0)); + gate[3] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1)); + gate[4] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0)); + //gate[5] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1)); + gate[6] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0)); + gate[7] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1)); + gate[8] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP)); + gate[9] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0_SRC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1_SRC), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0)); + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO0), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO1), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_IPP), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_RGA), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA)); + pmu_set_power_domain(PD_VIO, on); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0_SRC) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0_SRC)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1_SRC) | gate[1], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1_SRC)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC0) | gate[2], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC0)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_LCDC1) | gate[3], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_LCDC1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF0) | gate[4], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF0)); + //cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_CIF1) | gate[5], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_CIF1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO0) | gate[6], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO0)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_VIO1) | gate[7], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_VIO1)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_IPP) | gate[8], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_IPP)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_RGA) | gate[9], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_RGA)); + return 0; +} + +static struct clk pd_display = { + .name = "pd_vio", + .flags = IS_PD, + .mode = pd_display_mode, + .gate_idx = PD_VIO, +}; +static struct clk pd_lcdc0 = { + .parent = &pd_display, + .name = "pd_lcdc0", +}; +static struct clk pd_lcdc1 = { + .parent = &pd_display, + .name = "pd_lcdc1", +}; +static struct clk pd_cif0 = { + .parent = &pd_display, + .name = "pd_cif0", +}; +static struct clk pd_rga = { + .parent = &pd_display, + .name = "pd_rga", +}; +static struct clk pd_ipp = { + .parent = &pd_display, + .name = "pd_ipp", +}; +static struct clk pd_hdmi = { + .parent = &pd_display, + .name = "pd_hdmi", +}; + + +static int pd_gpu_mode(struct clk *clk, int on) +{ + u32 gate[3]; + gate[0] = cru_readl(CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU)); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_GPU), CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU)); + pmu_set_power_domain(PD_GPU, on); + cru_writel(CLK_GATE_W_MSK(CLK_GATE_ACLK_GPU) | gate[0], CLK_GATE_CLKID_CONS(CLK_GATE_ACLK_GPU)); + return 0; +} + +static struct clk pd_gpu = { + .name = "pd_gpu", + .flags = IS_PD, + .mode = pd_gpu_mode, + .gate_idx = PD_GPU, +}; + +static int pm_off_mode(struct clk *clk, int on) +{ + _pmu_set_power_domain(clk->gate_idx, on); //on 1 + return 0; +} +static struct clk pd_peri = { + .name = "pd_peri", + .flags = IS_PD, + .mode = pm_off_mode, + .gate_idx = PD_PERI, +}; + + +#define PD_CLK(name) \ +{\ + .dev_id = NULL,\ + .con_id = #name,\ + .clk = &name,\ +} + +#endif +/************************rk30 fixed div clock****************************************/ + +/*************************aclk_cpu***********************/ + +GATE_CLK(dma1, aclk_cpu, ACLK_DMAC1); +GATE_CLK(intmem, aclk_cpu, ACLK_INTMEM); +GATE_CLK(aclk_strc_sys, aclk_cpu, ACLK_STRC_SYS); + +/*************************hclk_cpu***********************/ + +GATE_CLK(rom, hclk_cpu, HCLK_ROM); +GATE_CLK(hclk_i2s0_2ch, hclk_cpu, HCLK_I2S0_2CH); +GATE_CLK(hclk_spdif, hclk_cpu, HCLK_SPDIF); +GATE_CLK(hclk_cpubus, hclk_cpu, HCLK_CPUBUS); +GATE_CLK(hclk_ahb2apb, hclk_cpu, HCLK_AHB2APB); +GATE_CLK(hclk_vio_bus, hclk_cpu, HCLK_VIO_BUS); +GATE_CLK(hclk_lcdc0, hclk_cpu, HCLK_LCDC0); +GATE_CLK(hclk_lcdc1, hclk_cpu, HCLK_LCDC1); +GATE_CLK(hclk_cif0, hclk_cpu, HCLK_CIF0); +GATE_CLK(hclk_ipp, hclk_cpu, HCLK_IPP); +GATE_CLK(hclk_rga, hclk_cpu, HCLK_RGA); +GATE_CLK(hclk_imem0, hclk_cpu, HCLK_IMEM0); +GATE_CLK(hclk_imem1, hclk_cpu, HCLK_IMEM1); + +/*************************ahb2apb_cpu(pclk_cpu_h2p)***********************/ +GATE_CLK(pclk_uart0, ahb2apb_cpu, PCLK_UART0); +GATE_CLK(pclk_uart1, ahb2apb_cpu, PCLK_UART1); +/*************************pclk_cpu***********************/ +GATE_CLK(pwm01, pclk_cpu, PCLK_PWM01);//pwm 0¡¢1 +GATE_CLK(pclk_timer0, pclk_cpu, PCLK_TIMER0); +GATE_CLK(pclk_timer2, pclk_cpu, PCLK_TIMER2); +GATE_CLK(i2c0, pclk_cpu, PCLK_I2C0); +GATE_CLK(i2c1, pclk_cpu, PCLK_I2C1); +GATE_CLK(gpio0, pclk_cpu, PCLK_GPIO0); +GATE_CLK(gpio1, pclk_cpu, PCLK_GPIO1); +GATE_CLK(gpio2, pclk_cpu, PCLK_GPIO2); +GATE_CLK(efuse, pclk_cpu, PCLK_EFUSE); +GATE_CLK(tzpc, pclk_cpu, PCLK_TZPC); +GATE_CLK(pclk_ddrupctl, pclk_cpu, PCLK_DDRUPCTL); +GATE_CLK(pclk_ddrpubl, pclk_cpu, PCLK_PUBL); +GATE_CLK(dbg, pclk_cpu, PCLK_DBG); +GATE_CLK(grf, pclk_cpu, PCLK_GRF); +GATE_CLK(pmu, pclk_cpu, PCLK_PMU); + +/*************************aclk_periph***********************/ + +GATE_CLK(dma2, aclk_periph, ACLK_DMAC2); +GATE_CLK(aclk_smc, aclk_periph, ACLK_SMC); +GATE_CLK(aclk_gps, aclk_periph, ACLK_GPS); +GATE_CLK(aclk_peri_niu, aclk_periph, ACLK_PEI_NIU); +GATE_CLK(aclk_cpu_peri, aclk_periph, ACLK_CPU_PERI); +GATE_CLK(aclk_peri_axi_matrix, aclk_periph, ACLK_PERI_AXI_MATRIX); + +/*************************hclk_periph***********************/ +GATE_CLK(hclk_peri_axi_matrix, hclk_periph, HCLK_PERI_AXI_MATRIX); +GATE_CLK(hclk_peri_ahb_arbi, hclk_periph, HCLK_PERI_AHB_ARBI); +GATE_CLK(hclk_emem_peri, hclk_periph, HCLK_EMEM_PERI); +GATE_CLK(hclk_mac, hclk_periph, HCLK_EMAC); +GATE_CLK(nandc, hclk_periph, HCLK_NANDC); +GATE_CLK(hclk_usb_peri, hclk_periph, HCLK_USB_PERI); +GATE_CLK(hclk_otg0, clk_hclk_usb_peri, HCLK_OTG0); +GATE_CLK(hclk_otg1, clk_hclk_usb_peri, HCLK_OTG1); +GATE_CLK(hclk_hsic, hclk_periph, HCLK_HSIC); +GATE_CLK(hclk_hsadc, hclk_periph, HCLK_HSADC); +GATE_CLK(hclk_pidfilter, hclk_periph, HCLK_PIDF); +GATE_CLK(hclk_sdmmc, hclk_periph, HCLK_SDMMC0); +GATE_CLK(hclk_sdio, hclk_periph, HCLK_SDIO); +GATE_CLK(hclk_emmc, hclk_periph, HCLK_EMMC); +/*************************pclk_periph***********************/ +GATE_CLK(pclk_peri_axi_matrix, pclk_periph, PCLK_PERI_AXI_MATRIX); +GATE_CLK(pwm23, pclk_periph, PCLK_PWM23); +GATE_CLK(wdt, pclk_periph, PCLK_WDT); +GATE_CLK(pclk_spi0, pclk_periph, PCLK_SPI0); +GATE_CLK(pclk_spi1, pclk_periph, PCLK_SPI1); +GATE_CLK(pclk_uart2, pclk_periph, PCLK_UART2); +GATE_CLK(pclk_uart3, pclk_periph, PCLK_UART3); +GATE_CLK(i2c2, pclk_periph, PCLK_I2C2); +GATE_CLK(i2c3, pclk_periph, PCLK_I2C3); +GATE_CLK(i2c4, pclk_periph, PCLK_I2C4); +GATE_CLK(gpio3, pclk_periph, PCLK_GPIO3); +GATE_CLK(pclk_saradc, pclk_periph, PCLK_SARADC); +/*************************aclk_lcdc0***********************/ + +GATE_CLK(aclk_vio0, aclk_lcdc0_pre, ACLK_VIO0); +GATE_CLK(aclk_lcdc0, clk_aclk_vio0, ACLK_LCDC0); +GATE_CLK(aclk_cif0, clk_aclk_vio0, ACLK_CIF0); +GATE_CLK(aclk_ipp, clk_aclk_vio0, ACLK_IPP); + +/*************************aclk_lcdc0***********************/ + +GATE_CLK(aclk_vio1, aclk_lcdc1_pre, ACLK_VIO1); +GATE_CLK(aclk_lcdc1, clk_aclk_vio1, ACLK_LCDC1); +GATE_CLK(aclk_rga, clk_aclk_vio1, ACLK_RGA); + + +#if 1 +#define CLK(dev, con, ck) \ +{\ + .dev_id = dev,\ + .con_id = con,\ + .clk = ck,\ +} + + +#define CLK1(name) \ +{\ + .dev_id = NULL,\ + .con_id = #name,\ + .clk = &clk_##name,\ +} + +#endif + +static struct clk_lookup clks[] = { + CLK(NULL, "xin24m", &xin24m), + //CLK(NULL, "xin27m", &xin27m), + CLK(NULL, "xin12m", &clk_12m), + CLK(NULL, "arm_pll", &arm_pll_clk), + CLK(NULL, "ddr_pll", &ddr_pll_clk), + CLK(NULL, "codec_pll", &codec_pll_clk), + CLK(NULL, "general_pll", &general_pll_clk), + + CLK(NULL, "arm_gpll", &clk_core_gpll_path), + CLK(NULL, "ddr_gpll", &clk_ddr_gpll_path), + + CLK(NULL, "ddr", &clk_ddr), + CLK(NULL, "cpu", &clk_core), + CLK1(l2c), + CLK1(core_dbg), + CLK("smp_twd", NULL, &core_periph), + CLK(NULL, "aclk_core", &aclk_core), + + CLK(NULL, "logic", &clk_cpu_div), + CLK(NULL, "aclk_cpu", &aclk_cpu), + CLK(NULL, "pclk_cpu", &pclk_cpu), + CLK(NULL, "atclk_cpu", &atclk_cpu), + CLK(NULL, "hclk_cpu", &hclk_cpu), + CLK(NULL, "ahb2apb_cpu", &ahb2apb_cpu), + + CLK(NULL, "gpu", &aclk_gpu), + + CLK(NULL, "aclk_vepu", &aclk_vepu), + CLK(NULL, "hclk_vepu", &hclk_vepu), + CLK(NULL, "aclk_vdpu", &aclk_vdpu), + CLK(NULL, "hclk_vdpu", &hclk_vdpu), + + CLK(NULL, "aclk_lcdc0_pre", &aclk_lcdc0_pre), + CLK(NULL, "aclk_lcdc1_pre", &aclk_lcdc1_pre), + + CLK(NULL, "aclk_periph", &aclk_periph), + CLK(NULL, "pclk_periph", &pclk_periph), + CLK(NULL, "hclk_periph", &hclk_periph), + + CLK(NULL, "dclk_lcdc0", &dclk_lcdc0), + CLK(NULL, "dclk_lcdc1", &dclk_lcdc1), + + CLK(NULL, "cif_out_pll", &cif_out_pll), + CLK(NULL, "cif0_out_div", &cif0_out_div), + CLK(NULL, "cif0_out", &cif0_out), + + CLK(NULL, "pclkin_cif0", &pclkin_cif0), + CLK(NULL, "inv_cif0", &inv_cif0), + CLK(NULL, "cif0_in", &cif0_in), + + CLK1(i2s_pll), + CLK("rk29_i2s.0", "i2s_div", &clk_i2s0_div), + CLK("rk29_i2s.0", "i2s_frac_div", &clk_i2s0_frac_div), + CLK("rk29_i2s.0", "i2s", &clk_i2s0), + + // actually no i2s1 + CLK("rk29_i2s.1", "i2s_div", &clk_i2s0_div), + CLK("rk29_i2s.1", "i2s_frac_div", &clk_i2s0_frac_div), + CLK("rk29_i2s.1", "i2s", &clk_i2s0), + + + CLK1(spdif_div), + CLK1(spdif_frac_div), + CLK1(spdif), + + CLK1(otgphy0), + CLK1(otgphy1), + CLK1(otgphy0_480m), + CLK1(otgphy1_480m), + CLK1(hsicphy_480m), + CLK1(hsicphy_12m), + + CLK(NULL, "rmii_clkin", &rmii_clkin), + CLK(NULL, "mac_ref_div", &clk_mac_pll_div), // compatible with rk29 + CLK1(mac_ref), + CLK1(mii_tx), + + CLK1(hsadc_pll_div), + CLK1(hsadc_frac_div), + CLK1(hsadc_ext), + CLK1(hsadc_out), + CLK1(hsadc_out_inv), + CLK1(hsadc), + + CLK1(saradc), + + CLK1(smc), + CLK(NULL, "smc_inv", &clkn_smc), + + CLK("rk29xx_spim.0", "spi", &clk_spi0), + CLK("rk29xx_spim.1", "spi", &clk_spi1), + + CLK("rk29_sdmmc.0", "mmc", &clk_sdmmc), + CLK("rk29_sdmmc.1", "mmc", &clk_sdio), + CLK1(emmc), + + CLK1(uart_pll), + CLK("rk_serial.0", "uart_div", &clk_uart0_div), + CLK("rk_serial.0", "uart_frac_div", &clk_uart0_frac_div), + CLK("rk_serial.0", "uart", &clk_uart0), + CLK("rk_serial.1", "uart_div", &clk_uart1_div), + CLK("rk_serial.1", "uart_frac_div", &clk_uart1_frac_div), + CLK("rk_serial.1", "uart", &clk_uart1), + CLK("rk_serial.2", "uart_div", &clk_uart2_div), + CLK("rk_serial.2", "uart_frac_div", &clk_uart2_frac_div), + CLK("rk_serial.2", "uart", &clk_uart2), + CLK("rk_serial.3", "uart_div", &clk_uart3_div), + CLK("rk_serial.3", "uart_frac_div", &clk_uart3_frac_div), + CLK("rk_serial.3", "uart", &clk_uart3), + + CLK1(timer0), + CLK1(timer1), + CLK1(timer2), + CLK1(timer3), + CLK1(timer4), + CLK1(timer5), + CLK1(timer6), + + /*************************aclk_cpu***********************/ + CLK1(dma1), + CLK1(intmem), + CLK1(aclk_strc_sys), + + /*************************hclk_cpu***********************/ + CLK1(rom), + CLK("rk29_i2s.0", "hclk_i2s", &clk_hclk_i2s0_2ch), + // actually no i2s1 + CLK("rk29_i2s.1", "hclk_i2s", &clk_hclk_i2s0_2ch), + CLK1(hclk_spdif), + CLK1(hclk_cpubus), + CLK1(hclk_ahb2apb), + CLK1(hclk_vio_bus), + CLK1(hclk_lcdc0), + CLK1(hclk_lcdc1), + CLK1(hclk_cif0), + CLK1(hclk_ipp), + CLK1(hclk_rga), + CLK1(hclk_imem0), + CLK1(hclk_imem1), + + /*************************pclk_cpu***********************/ + CLK1(pwm01), + CLK1(pclk_timer0), + CLK1(pclk_timer2), + CLK("rk30_i2c.0", "i2c", &clk_i2c0), + CLK("rk30_i2c.1", "i2c", &clk_i2c1), + CLK1(gpio0), + CLK1(gpio1), + CLK1(gpio2), + CLK1(efuse), + CLK1(tzpc), + CLK("rk_serial.0", "pclk_uart", &clk_pclk_uart0), + CLK("rk_serial.1", "pclk_uart", &clk_pclk_uart1), + CLK1(pclk_ddrupctl), + CLK1(pclk_ddrpubl), + CLK1(dbg), + CLK1(grf), + CLK1(pmu), + + /*************************aclk_periph***********************/ + CLK1(dma2), + CLK1(aclk_smc), + CLK1(aclk_gps), + CLK1(aclk_peri_niu), + CLK1(aclk_cpu_peri), + CLK1(aclk_peri_axi_matrix), + + /*************************hclk_periph***********************/ + CLK1(hclk_peri_axi_matrix), + CLK1(hclk_peri_ahb_arbi), + CLK1(hclk_emem_peri), + CLK1(hclk_mac), + CLK1(nandc), + CLK1(hclk_usb_peri), + CLK1(hclk_otg0), + CLK1(hclk_otg1), + CLK1(hclk_hsic), + CLK1(hclk_hsadc), + CLK1(hclk_pidfilter), + CLK("rk29_sdmmc.0", "hclk_mmc", &clk_hclk_sdmmc), + CLK("rk29_sdmmc.1", "hclk_mmc", &clk_hclk_sdio), + CLK1(hclk_emmc), + + /*************************pclk_periph***********************/ + CLK1(pclk_peri_axi_matrix), + CLK1(pwm23), + CLK1(wdt), + CLK("rk29xx_spim.0", "pclk_spi", &clk_pclk_spi0), + CLK("rk29xx_spim.1", "pclk_spi", &clk_pclk_spi1), + CLK("rk_serial.2", "pclk_uart", &clk_pclk_uart2), + CLK("rk_serial.3", "pclk_uart", &clk_pclk_uart3), + CLK("rk30_i2c.2", "i2c", &clk_i2c2), + CLK("rk30_i2c.3", "i2c", &clk_i2c3), + CLK("rk30_i2c.4", "i2c", &clk_i2c4), + CLK1(gpio3), + CLK1(pclk_saradc), + + /*************************aclk_lcdc0***********************/ + CLK1(aclk_vio0), + CLK(NULL, "aclk_lcdc0", &clk_aclk_lcdc0), + CLK1(aclk_cif0), + CLK1(aclk_ipp), + + /*************************aclk_lcdc1***********************/ + CLK1(aclk_vio1), + CLK(NULL, "aclk_lcdc1", &clk_aclk_lcdc1), + CLK1(aclk_rga), + /************************power domain**********************/ + + PD_CLK(pd_peri), + PD_CLK(pd_display), + PD_CLK(pd_lcdc0), + PD_CLK(pd_lcdc1), + PD_CLK(pd_cif0), + //PD_CLK(pd_cif1), + PD_CLK(pd_rga), + PD_CLK(pd_ipp), + //PD_CLK(pd_video), + PD_CLK(pd_gpu), + //PD_CLK(pd_dbg), +}; +static void __init rk30_init_enable_clocks(void) +{ + #if 0 + //clk_enable_nolock(&xin24m); + //clk_enable_nolock(&clk_12m); + //clk_enable_nolock(&arm_pll_clk); + //clk_enable_nolock(&ddr_pll_clk); + //clk_enable_nolock(&codec_pll_clk); + //clk_enable_nolock(&general_pll_clk); + #endif + clk_enable_nolock(&clk_ddr); + //clk_enable_nolock(&clk_core); + clk_enable_nolock(&clk_cpu_div); + clk_enable_nolock(&clk_core_gpll_path); + clk_enable_nolock(&clk_l2c); + clk_enable_nolock(&clk_core_dbg); + clk_enable_nolock(&core_periph); + clk_enable_nolock(&aclk_core); + //clk_enable_nolock(&aclk_cpu); + //clk_enable_nolock(&pclk_cpu); + clk_enable_nolock(&atclk_cpu); + //clk_enable_nolock(&hclk_cpu); + clk_enable_nolock(&ahb2apb_cpu); + #if 0 + clk_enable_nolock(&clk_gpu); + clk_enable_nolock(&aclk_gpu); + clk_enable_nolock(&aclk_gpu_slv); + clk_enable_nolock(&aclk_gpu_mst); + + clk_enable_nolock(&aclk_vepu); + clk_enable_nolock(&hclk_vepu); + clk_enable_nolock(&aclk_vdpu); + clk_enable_nolock(&hclk_vdpu); + + clk_enable_nolock(&aclk_lcdc0_pre); + clk_enable_nolock(&aclk_lcdc1_pre); + + clk_enable_nolock(&aclk_periph); + clk_enable_nolock(&pclk_periph); + clk_enable_nolock(&hclk_periph); + #endif + #if 0 + clk_enable_nolock(&dclk_lcdc0); + clk_enable_nolock(&dclk_lcdc1); + + clk_enable_nolock(&cif_out_pll); + clk_enable_nolock(&cif0_out_div); + + clk_enable_nolock(&cif0_out); + clk_enable_nolock(&pclkin_cif0); + clk_enable_nolock(&inv_cif0); + clk_enable_nolock(&cif0_in); + + clk_enable_nolock(&clk_i2s_pll); + clk_enable_nolock(&clk_i2s0_div); + clk_enable_nolock(&clk_i2s0_frac_div); + clk_enable_nolock(&clk_i2s0); + + actually no i2s1 + clk_enable_nolock(&clk_i2s0_div); + clk_enable_nolock(&clk_i2s0_frac_div); + clk_enable_nolock(&clk_i2s0); + + clk_enable_nolock(&clk_spdif_div); + clk_enable_nolock(&clk_spdif_frac_div); + clk_enable_nolock(&clk_spdif); + #endif + #if 0 + clk_enable_nolock(&clk_otgphy0); + clk_enable_nolock(&clk_otgphy1); + clk_enable_nolock(&clk_otgphy0_480m); + clk_enable_nolock(&clk_otgphy1_480m); + clk_enable_nolock(&clk_hsicphy_480m); + clk_enable_nolock(&clk_hsicphy_12m); + #endif + + #if 0 + clk_enable_nolock(&rmii_clkin); + clk_enable_nolock(&clk_mac_pll_div); // compatible with rk29 + clk_enable_nolock(&clk_mac_ref); + clk_enable_nolock(&clk_mii_tx); + #endif + + #if 0 + clk_enable_nolock(&clk_hsadc_pll_div); + clk_enable_nolock(&clk_hsadc_frac_div); + clk_enable_nolock(&clk_hsadc_ext); + clk_enable_nolock(&clk_hsadc_out); + clk_enable_nolock(&clk_hsadc_out_inv); + clk_enable_nolock(&clk_hsadc); + + clk_enable_nolock(&clk_saradc); + #endif + /* + clk_enable_nolock(&clk_smc); + clk_enable_nolock(&clkn_smc); + */ + /* + clk_enable_nolock(&clk_spi0); + clk_enable_nolock(&clk_spi1); + */ + /* + clk_enable_nolock(&clk_sdmmc); + clk_enable_nolock(&clk_sdio); + clk_enable_nolock(&clk_emmc); + */ + #if 0 + clk_enable_nolock(&clk_uart_pll); + clk_enable_nolock(&clk_uart0_div); + clk_enable_nolock(&clk_uart0_frac_div); + clk_enable_nolock(&clk_uart0); + clk_enable_nolock(&clk_uart1_div); + clk_enable_nolock(&clk_uart1_frac_div); + clk_enable_nolock(&clk_uart1); + clk_enable_nolock(&clk_uart2_div); + clk_enable_nolock(&clk_uart2_frac_div); + clk_enable_nolock(&clk_uart2); + clk_enable_nolock(&clk_uart3_div); + clk_enable_nolock(&clk_uart3_frac_div); + clk_enable_nolock(&clk_uart3); + #endif + #if CONFIG_RK_DEBUG_UART == 0 + clk_enable_nolock(&clk_uart0); + clk_enable_nolock(&clk_pclk_uart0); + #elif CONFIG_RK_DEBUG_UART == 1 + clk_enable_nolock(&clk_uart1); + clk_enable_nolock(&clk_pclk_uart1); + + #elif CONFIG_RK_DEBUG_UART == 2 + clk_enable_nolock(&clk_uart2); + clk_enable_nolock(&clk_pclk_uart2); + + #elif CONFIG_RK_DEBUG_UART == 3 + clk_enable_nolock(&clk_uart3); + clk_enable_nolock(&clk_pclk_uart3); + + #endif + #if 0 + clk_enable_nolock(&clk_timer0); + clk_enable_nolock(&clk_timer1); + clk_enable_nolock(&clk_timer2); + #endif + + /*************************aclk_cpu***********************/ + clk_enable_nolock(&clk_dma1); + clk_enable_nolock(&clk_intmem); + clk_enable_nolock(&clk_aclk_strc_sys); + + /*************************hclk_cpu***********************/ + clk_enable_nolock(&clk_rom); + #if 0 + clk_enable_nolock(&clk_hclk_i2s0_2ch); + // actually no i2s1 + clk_enable_nolock(&clk_hclk_i2s0_2ch); + clk_enable_nolock(&clk_hclk_spdif); + #endif + clk_enable_nolock(&clk_hclk_cpubus); + clk_enable_nolock(&clk_hclk_ahb2apb); + clk_enable_nolock(&clk_hclk_vio_bus); + #if 0 + clk_enable_nolock(&clk_hclk_lcdc0); + clk_enable_nolock(&clk_hclk_lcdc1); + clk_enable_nolock(&clk_hclk_cif0); + clk_enable_nolock(&clk_hclk_ipp); + clk_enable_nolock(&clk_hclk_rga); + #endif + clk_enable_nolock(&clk_hclk_imem0); + clk_enable_nolock(&clk_hclk_imem1); + + /*************************pclk_cpu***********************/ + #if 0 + clk_enable_nolock(&clk_pwm01); + clk_enable_nolock(&clk_pclk_timer0); + clk_enable_nolock(&clk_pclk_timer1); + clk_enable_nolock(&clk_pclk_timer2); + clk_enable_nolock(&clk_i2c0); + clk_enable_nolock(&clk_i2c1); + clk_enable_nolock(&clk_gpio0); + clk_enable_nolock(&clk_gpio1); + clk_enable_nolock(&clk_gpio2); + clk_enable_nolock(&clk_efuse); + #endif + clk_enable_nolock(&clk_tzpc); + //clk_enable_nolock(&clk_pclk_uart0); + //clk_enable_nolock(&clk_pclk_uart1); + clk_enable_nolock(&clk_pclk_ddrupctl); + clk_enable_nolock(&clk_pclk_ddrpubl); + clk_enable_nolock(&clk_dbg); + clk_enable_nolock(&clk_grf); + clk_enable_nolock(&clk_pmu); + + /*************************aclk_periph***********************/ + clk_enable_nolock(&clk_dma2); + clk_enable_nolock(&clk_aclk_smc); + clk_enable_nolock(&clk_aclk_peri_niu); + clk_enable_nolock(&clk_aclk_cpu_peri); + clk_enable_nolock(&clk_aclk_peri_axi_matrix); + + /*************************hclk_periph***********************/ + clk_enable_nolock(&clk_hclk_peri_axi_matrix); + clk_enable_nolock(&clk_hclk_peri_ahb_arbi); + clk_enable_nolock(&clk_hclk_emem_peri); + //clk_enable_nolock(&clk_hclk_mac); + //clk_enable_nolock(&clk_nandc); + clk_enable_nolock(&clk_hclk_usb_peri); + #if 0 + clk_enable_nolock(&clk_hclk_otg0); + clk_enable_nolock(&clk_hclk_otg1); + clk_enable_nolock(&clk_hclk_hsic); + clk_enable_nolock(&clk_hclk_gps); + clk_enable_nolock(&clk_hclk_hsadc); + clk_enable_nolock(&clk_hclk_pidfilter); + clk_enable_nolock(&clk_hclk_sdmmc); + clk_enable_nolock(&clk_hclk_sdio); + clk_enable_nolock(&clk_hclk_emmc); + #endif + + /*************************pclk_periph***********************/ + clk_enable_nolock(&clk_pclk_peri_axi_matrix); + #if 0 + clk_enable_nolock(&clk_pwm23); + clk_enable_nolock(&clk_wdt); + clk_enable_nolock(&clk_pclk_spi0); + clk_enable_nolock(&clk_pclk_spi1); + clk_enable_nolock(&clk_pclk_uart2); + clk_enable_nolock(&clk_pclk_uart3); + #endif + #if 0 + clk_enable_nolock(&clk_i2c2); + clk_enable_nolock(&clk_i2c3); + clk_enable_nolock(&clk_i2c4); + clk_enable_nolock(&clk_gpio3); + clk_enable_nolock(&clk_pclk_saradc); + #endif + /*************************aclk_lcdc0***********************/ +#if 1 + //clk_enable_nolock(&clk_aclk_vio0); + //clk_enable_nolock(&clk_aclk_lcdc0); + //clk_enable_nolock(&clk_aclk_cif0); + //clk_enable_nolock(&clk_aclk_ipp); +#endif + /*************************aclk_lcdc1***********************/ +#if 1 + //clk_enable_nolock(&clk_aclk_vio1); + //clk_enable_nolock(&clk_aclk_lcdc1); + //clk_enable_nolock(&clk_aclk_rga); +#endif + /************************power domain**********************/ + +} +static void periph_clk_set_init(void) +{ + unsigned long aclk_p, hclk_p, pclk_p; + unsigned long ppll_rate = general_pll_clk.rate; + //aclk 148.5 + + /* general pll */ + switch (ppll_rate) { + case 148500* KHZ: + aclk_p = 148500 * KHZ; + hclk_p = aclk_p >> 1; + pclk_p = aclk_p >> 2; + break; + case 1188*MHZ: + aclk_p = aclk_p >> 3; // 0 + hclk_p = aclk_p >> 1; + pclk_p = aclk_p >> 2; + + case 297 * MHZ: + aclk_p = ppll_rate >> 1; + hclk_p = aclk_p >> 0; + pclk_p = aclk_p >> 1; + break; + + case 300 * MHZ: + aclk_p = ppll_rate >> 1; + hclk_p = aclk_p >> 0; + pclk_p = aclk_p >> 1; + break; + case 594 * MHZ: + aclk_p = ppll_rate >> 2; + hclk_p = aclk_p >> 0; + pclk_p = aclk_p >> 1; + break; + default: + aclk_p = 150 * MHZ; + hclk_p = 150 * MHZ; + pclk_p = 75 * MHZ; + break; + } + clk_set_parent_nolock(&aclk_periph, &general_pll_clk); + clk_set_rate_nolock(&aclk_periph, aclk_p); + clk_set_rate_nolock(&hclk_periph, hclk_p); + clk_set_rate_nolock(&pclk_periph, pclk_p); +} + +static void cpu_axi_init(void) +{ + unsigned long cpu_div_rate, aclk_cpu_rate, hclk_cpu_rate, pclk_cpu_rate, ahb2apb_cpu_rate; + unsigned long gpll_rate = general_pll_clk.rate; + + switch (gpll_rate) { + case 297 * MHZ: + cpu_div_rate = gpll_rate; + aclk_cpu_rate = cpu_div_rate >> 0; + hclk_cpu_rate = aclk_cpu_rate >> 1; + pclk_cpu_rate = aclk_cpu_rate >> 2; + break; + + case 594 * MHZ: + cpu_div_rate = gpll_rate >> 1; + aclk_cpu_rate = cpu_div_rate >> 0; + hclk_cpu_rate = aclk_cpu_rate >> 1; + pclk_cpu_rate = aclk_cpu_rate >> 2; + break; + default: + aclk_cpu_rate = 150 * MHZ; + hclk_cpu_rate = 150 * MHZ; + pclk_cpu_rate = 75 * MHZ; + break; + } + ahb2apb_cpu_rate = pclk_cpu_rate; + + clk_set_parent_nolock(&clk_cpu_div, &general_pll_clk); + clk_set_rate_nolock(&clk_cpu_div, cpu_div_rate); + clk_set_rate_nolock(&aclk_cpu, aclk_cpu_rate); + clk_set_rate_nolock(&hclk_cpu, hclk_cpu_rate); + clk_set_rate_nolock(&pclk_cpu, pclk_cpu_rate); + clk_set_rate_nolock(&ahb2apb_cpu, ahb2apb_cpu_rate); +} + +void rk30_clock_common_i2s_init(void) +{ + unsigned long i2s_rate; + //20 times + if(rk30_clock_flags & CLK_FLG_MAX_I2S_49152KHZ) { + i2s_rate = 49152000; + } else if(rk30_clock_flags & CLK_FLG_MAX_I2S_24576KHZ) { + i2s_rate = 24576000; + } else if(rk30_clock_flags & CLK_FLG_MAX_I2S_22579_2KHZ) { + i2s_rate = 22579000; + } else if(rk30_clock_flags & CLK_FLG_MAX_I2S_12288KHZ) { + i2s_rate = 12288000; + } else { + i2s_rate = 49152000; + } + + if(((i2s_rate * 20) <= general_pll_clk.rate) || !(general_pll_clk.rate % i2s_rate)) { + clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk); + } else if(((i2s_rate * 20) <= codec_pll_clk.rate) || !(codec_pll_clk.rate % i2s_rate)) { + clk_set_parent_nolock(&clk_i2s_pll, &codec_pll_clk); + } else { + if(general_pll_clk.rate > codec_pll_clk.rate) + clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk); + else + clk_set_parent_nolock(&clk_i2s_pll, &codec_pll_clk); + } +} + +static void __init rk30_clock_common_init(unsigned long gpll_rate, unsigned long cpll_rate) +{ + + //general + clk_set_rate_nolock(&general_pll_clk, gpll_rate); + //code pll + clk_set_rate_nolock(&codec_pll_clk, cpll_rate); + + cpu_axi_init(); + clk_set_rate_nolock(&clk_core, 312 * MHZ); + //periph clk + periph_clk_set_init(); + + //i2s + rk30_clock_common_i2s_init(); + + // spi + clk_set_rate_nolock(&clk_spi0, clk_spi0.parent->rate); + clk_set_rate_nolock(&clk_spi1, clk_spi1.parent->rate); + + // uart + if(rk30_clock_flags & CLK_FLG_UART_1_3M) + clk_set_parent_nolock(&clk_uart_pll, &codec_pll_clk); + else + clk_set_parent_nolock(&clk_uart_pll, &general_pll_clk); + //mac + if(!(gpll_rate % (50 * MHZ))) + clk_set_parent_nolock(&clk_mac_pll_div, &general_pll_clk); + else if(!(ddr_pll_clk.rate % (50 * MHZ))) + clk_set_parent_nolock(&clk_mac_pll_div, &ddr_pll_clk); + else + CLKDATA_ERR("mac can't get 50mhz\n"); + + //hsadc + //auto pll sel + //clk_set_parent_nolock(&clk_hsadc_pll_div, &general_pll_clk); + + //lcdc0 lcd auto sel pll + clk_set_parent_nolock(&dclk_lcdc0, &general_pll_clk); + clk_set_parent_nolock(&dclk_lcdc1, &general_pll_clk); + + //cif + clk_set_parent_nolock(&cif_out_pll, &general_pll_clk); + + //axi lcdc auto sel + clk_set_parent_nolock(&aclk_lcdc0_pre, &general_pll_clk); + clk_set_parent_nolock(&aclk_lcdc1_pre, &general_pll_clk); + clk_set_rate_nolock(&aclk_lcdc0_pre, 300 * MHZ); + clk_set_rate_nolock(&aclk_lcdc1_pre, 300 * MHZ); + + //axi vepu auto sel + //clk_set_parent_nolock(&aclk_vepu, &general_pll_clk); + //clk_set_parent_nolock(&aclk_vdpu, &general_pll_clk); + + clk_set_rate_nolock(&aclk_vepu, 300 * MHZ); + clk_set_rate_nolock(&aclk_vdpu, 300 * MHZ); + //gpu auto sel + clk_set_parent_nolock(&aclk_gpu, &codec_pll_clk); + clk_set_rate_nolock(&aclk_gpu, 200 * MHZ); + + clk_set_rate_nolock(&clk_uart0, 49500000); + +} + +static struct clk def_ops_clk = { + .get_parent = clksel_get_parent, + .set_parent = clksel_set_parent, +}; + +#ifdef CONFIG_PROC_FS +struct clk_dump_ops dump_ops; +#endif +void rk_dump_clock_info(void); + +void __init _rk30_clock_data_init(unsigned long gpll, unsigned long cpll, int flags) +{ + struct clk_lookup *lk; + + clk_register_dump_ops(&dump_ops); + clk_register_default_ops_clk(&def_ops_clk); + rk30_clock_flags = flags; + for (lk = clks; lk < clks + ARRAY_SIZE(clks); lk++) { +#ifdef RK30_CLK_OFFBOARD_TEST + rk30_clkdev_add(lk); +#else + clkdev_add(lk); +#endif + clk_register(lk->clk); + } + clk_recalculate_root_clocks_nolock(); + + loops_per_jiffy = CLK_LOOPS_RECALC(arm_pll_clk.rate); + + /* + * Only enable those clocks we will need, let the drivers + * enable other clocks as necessary + */ + rk30_init_enable_clocks(); +#if 1 + // print loader config + CLKDATA_DBG("%s clks register dbg start\n", __func__); + rk_dump_clock_info(); + rk30_clk_dump_regs(); + + CLKDATA_DBG("%s clks register dbg end\n", __func__); + while(1); +#endif + /* + * Disable any unused clocks left on by the bootloader + */ + //clk_disable_unused(); + rk30_clock_common_init(gpll, cpll); + preset_lpj = loops_per_jiffy; + + //gpio6_b7 + //regfile_writel(0xc0004000,0x10c); + //cru_writel(0x07000000,CRU_MISC_CON); + +} + +void __init rk30_clock_data_init(unsigned long gpll, unsigned long cpll, u32 flags) +{ + _rk30_clock_data_init(gpll, cpll, flags); + rk30_dvfs_init(); +} + +/* + * You can override arm_clk rate with armclk= cmdline option. + */ +static int __init armclk_setup(char *str) +{ + get_option(&str, &armclk); + + if (!armclk) + return 0; + if (armclk < 10000) + armclk *= MHZ; + //clk_set_rate_nolock(&arm_pll_clk, armclk); + return 0; +} +#ifndef RK30_CLK_OFFBOARD_TEST +early_param("armclk", armclk_setup); +#endif + + +static void rk_dump_clock(struct clk *clk, int deep, const struct list_head *root_clocks) +{ + struct clk *ck; + int i; + unsigned long rate = clk->rate; + //CLKDATA_DBG("dump_clock %s\n",clk->name); + for (i = 0; i < deep; i++) + printk(" "); + + printk("%-11s ", clk->name); +#ifndef RK30_CLK_OFFBOARD_TEST + if (clk->flags & IS_PD) { + printk("%s ", pmu_power_domain_is_on(clk->gate_idx) ? "on " : "off"); + } +#endif + if ((clk->mode == gate_mode) && (clk->gate_idx < CLK_GATE_MAX)) { + int idx = clk->gate_idx; + u32 v; + v = cru_readl(CLK_GATE_CLKID_CONS(idx)) & ((0x1) << (idx % 16)); + printk("%s ", v ? "off" : "on "); + } + + if (clk->pll) { + u32 pll_mode; + u32 pll_id = clk->pll->id; + pll_mode = cru_readl(CRU_MODE_CON)&PLL_MODE_MSK(pll_id); + if (pll_mode == (PLL_MODE_SLOW(pll_id) & PLL_MODE_MSK(pll_id))) + printk("slow "); + else if (pll_mode == (PLL_MODE_NORM(pll_id) & PLL_MODE_MSK(pll_id))) + printk("normal "); + else if (pll_mode == (PLL_MODE_DEEP(pll_id) & PLL_MODE_MSK(pll_id))) + printk("deep "); + + if(cru_readl(PLL_CONS(pll_id, 3)) & PLL_BYPASS) + printk("bypass "); + } else if(clk == &clk_ddr) { + rate = clk->recalc(clk); + } + + if (rate >= MHZ) { + if (rate % MHZ) + printk("%ld.%06ld MHz", rate / MHZ, rate % MHZ); + else + printk("%ld MHz", rate / MHZ); + } else if (rate >= KHZ) { + if (rate % KHZ) + printk("%ld.%03ld KHz", rate / KHZ, rate % KHZ); + else + printk("%ld KHz", rate / KHZ); + } else { + printk("%ld Hz", rate); + } + + printk(" usecount = %d", clk->usecount); + + if (clk->parent) + printk(" parent = %s", clk->parent->name); + + printk("\n"); + + list_for_each_entry(ck, root_clocks, node) { + if (ck->parent == clk) + rk_dump_clock(ck, deep + 1, root_clocks); + } +} + +#if 1 +struct list_head *get_rk_clocks_head(void); + +void rk_dump_clock_info(void) +{ + struct clk* clk; + list_for_each_entry(clk, get_rk_clocks_head(), node) { + if (!clk->parent) + rk_dump_clock(clk, 0,get_rk_clocks_head()); + } +} +#endif + +#ifdef CONFIG_PROC_FS + +static void dump_clock(struct seq_file *s, struct clk *clk, int deep, const struct list_head *root_clocks) +{ + struct clk *ck; + int i; + unsigned long rate = clk->rate; + //CLKDATA_DBG("dump_clock %s\n",clk->name); + for (i = 0; i < deep; i++) + seq_printf(s, " "); + + seq_printf(s, "%-11s ", clk->name); +#ifndef RK30_CLK_OFFBOARD_TEST + if (clk->flags & IS_PD) { + seq_printf(s, "%s ", pmu_power_domain_is_on(clk->gate_idx) ? "on " : "off"); + } +#endif + if ((clk->mode == gate_mode) && (clk->gate_idx < CLK_GATE_MAX)) { + int idx = clk->gate_idx; + u32 v; + v = cru_readl(CLK_GATE_CLKID_CONS(idx)) & ((0x1) << (idx % 16)); + seq_printf(s, "%s ", v ? "off" : "on "); + } + + if (clk->pll) { + u32 pll_mode; + u32 pll_id = clk->pll->id; + pll_mode = cru_readl(CRU_MODE_CON)&PLL_MODE_MSK(pll_id); + if (pll_mode == (PLL_MODE_SLOW(pll_id) & PLL_MODE_MSK(pll_id))) + seq_printf(s, "slow "); + else if (pll_mode == (PLL_MODE_NORM(pll_id) & PLL_MODE_MSK(pll_id))) + seq_printf(s, "normal "); + else if (pll_mode == (PLL_MODE_DEEP(pll_id) & PLL_MODE_MSK(pll_id))) + seq_printf(s, "deep "); + + if(cru_readl(PLL_CONS(pll_id, 3)) & PLL_BYPASS) + seq_printf(s, "bypass "); + } else if(clk == &clk_ddr) { + rate = clk->recalc(clk); + } + + if (rate >= MHZ) { + if (rate % MHZ) + seq_printf(s, "%ld.%06ld MHz", rate / MHZ, rate % MHZ); + else + seq_printf(s, "%ld MHz", rate / MHZ); + } else if (rate >= KHZ) { + if (rate % KHZ) + seq_printf(s, "%ld.%03ld KHz", rate / KHZ, rate % KHZ); + else + seq_printf(s, "%ld KHz", rate / KHZ); + } else { + seq_printf(s, "%ld Hz", rate); + } + + seq_printf(s, " usecount = %d", clk->usecount); + + if (clk->parent) + seq_printf(s, " parent = %s", clk->parent->name); + + seq_printf(s, "\n"); + + list_for_each_entry(ck, root_clocks, node) { + if (ck->parent == clk) + dump_clock(s, ck, deep + 1, root_clocks); + } +} + +static void dump_regs(struct seq_file *s) +{ + int i = 0; + seq_printf(s, "\nPLL(id=0 apll,id=1,dpll,id=2,cpll,id=3 cpll)\n"); + seq_printf(s, "\nPLLRegisters:\n"); + for(i = 0; i < END_PLL_ID; i++) { + seq_printf(s, "pll%d :cons:%x,%x,%x,%x\n", i, + cru_readl(PLL_CONS(i, 0)), + cru_readl(PLL_CONS(i, 1)), + cru_readl(PLL_CONS(i, 2)), + cru_readl(PLL_CONS(i, 3)) + ); + } + seq_printf(s, "MODE :%x\n", cru_readl(CRU_MODE_CON)); + + for(i = 0; i < CRU_CLKSELS_CON_CNT; i++) { + seq_printf(s, "CLKSEL%d :%x\n", i, cru_readl(CRU_CLKSELS_CON(i))); + } + for(i = 0; i < CRU_CLKGATES_CON_CNT; i++) { + seq_printf(s, "CLKGATE%d :%x\n", i, cru_readl(CRU_CLKGATES_CON(i))); + } + seq_printf(s, "GLB_SRST_FST:%x\n", cru_readl(CRU_GLB_SRST_FST)); + seq_printf(s, "GLB_SRST_SND:%x\n", cru_readl(CRU_GLB_SRST_SND)); + + for(i = 0; i < CRU_SOFTRSTS_CON_CNT; i++) { + seq_printf(s, "CLKGATE%d :%x\n", i, cru_readl(CRU_SOFTRSTS_CON(i))); + } + seq_printf(s, "CRU MISC :%x\n", cru_readl(CRU_MISC_CON)); + seq_printf(s, "GLB_CNT_TH :%x\n", cru_readl(CRU_GLB_CNT_TH)); + +} + +void rk30_clk_dump_regs(void) +{ + int i = 0; + printk("\nPLL(id=0 apll,id=1,dpll,id=2,cpll,id=3 cpll)\n"); + printk("\nPLLRegisters:\n"); + for(i = 0; i < END_PLL_ID; i++) { + printk("pll%d :cons:%x,%x,%x,%x\n", i, + cru_readl(PLL_CONS(i, 0)), + cru_readl(PLL_CONS(i, 1)), + cru_readl(PLL_CONS(i, 2)), + cru_readl(PLL_CONS(i, 3)) + ); + } + printk("MODE :%x\n", cru_readl(CRU_MODE_CON)); + + for(i = 0; i < CRU_CLKSELS_CON_CNT; i++) { + printk("CLKSEL%d :%x\n", i, cru_readl(CRU_CLKSELS_CON(i))); + } + for(i = 0; i < CRU_CLKGATES_CON_CNT; i++) { + printk("CLKGATE%d :%x\n", i, cru_readl(CRU_CLKGATES_CON(i))); + } + printk("GLB_SRST_FST:%x\n", cru_readl(CRU_GLB_SRST_FST)); + printk("GLB_SRST_SND:%x\n", cru_readl(CRU_GLB_SRST_SND)); + + for(i = 0; i < CRU_SOFTRSTS_CON_CNT; i++) { + printk("SOFTRST%d :%x\n", i, cru_readl(CRU_SOFTRSTS_CON(i))); + } + printk("CRU MISC :%x\n", cru_readl(CRU_MISC_CON)); + printk("GLB_CNT_TH :%x\n", cru_readl(CRU_GLB_CNT_TH)); + +} + + +#ifdef CONFIG_PROC_FS +static void dump_clock(struct seq_file *s, struct clk *clk, int deep, const struct list_head *root_clocks); +struct clk_dump_ops dump_ops = { + .dump_clk = dump_clock, + .dump_regs = dump_regs, +}; +#endif + + +#endif /* CONFIG_PROC_FS */ + + + + +#ifdef RK30_CLK_OFFBOARD_TEST +struct clk *test_get_parent(struct clk *clk) { + return clk->parent; +} + +void i2s_test(void) +{ + struct clk *i2s_clk = &clk_i2s0; + + clk_enable_nolock(i2s_clk); + + clk_set_rate_nolock(i2s_clk, 12288000); + printk("int %s parent is %s\n", i2s_clk->name, test_get_parent(i2s_clk)->name); + clk_set_rate_nolock(i2s_clk, 297 * MHZ / 2); + printk("int%s parent is %s\n", i2s_clk->name, test_get_parent(i2s_clk)->name); + clk_set_rate_nolock(i2s_clk, 12 * MHZ); + printk("int%s parent is %s\n", i2s_clk->name, test_get_parent(i2s_clk)->name); + +} + +void uart_test(void) +{ + struct clk *uart_clk = &clk_uart0; + + clk_enable_nolock(uart_clk); + + clk_set_rate_nolock(uart_clk, 12288000); + printk("int %s parent is %s\n", uart_clk->name, test_get_parent(uart_clk)->name); + clk_set_rate_nolock(uart_clk, 297 * MHZ / 2); + printk("int%s parent is %s\n", uart_clk->name, test_get_parent(uart_clk)->name); + clk_set_rate_nolock(uart_clk, 12 * MHZ); + printk("int%s parent is %s\n", uart_clk->name, test_get_parent(uart_clk)->name); + +} +void hsadc_test(void) +{ + struct clk *hsadc_clk = &clk_hsadc; + + printk("******************hsadc_test**********************\n"); + clk_enable_nolock(hsadc_clk); + + clk_set_rate_nolock(hsadc_clk, 12288000); + printk("****end %s parent is %s\n", hsadc_clk->name, test_get_parent(hsadc_clk)->name); + + + clk_set_rate_nolock(hsadc_clk, 297 * MHZ / 2); + printk("****end %s parent is %s\n", hsadc_clk->name, test_get_parent(hsadc_clk)->name); + + clk_set_rate_nolock(hsadc_clk, 300 * MHZ / 2); + + clk_set_rate_nolock(hsadc_clk, 296 * MHZ / 2); + + printk("******************hsadc out clock**********************\n"); + + clk_set_parent_nolock(hsadc_clk, &clk_hsadc_ext); + printk("****end %s parent is %s\n", hsadc_clk->name, test_get_parent(hsadc_clk)->name); + clk_set_rate_nolock(hsadc_clk, 297 * MHZ / 2); + printk("****end %s parent is %s\n", hsadc_clk->name, test_get_parent(hsadc_clk)->name); + + + +} + +static void __init rk30_clock_test_init(unsigned long ppll_rate) +{ + //arm + printk("*********arm_pll_clk***********\n"); + clk_set_rate_nolock(&arm_pll_clk, 816 * MHZ); + + printk("*********set clk_core parent***********\n"); + clk_set_parent_nolock(&clk_core, &arm_pll_clk); + clk_set_rate_nolock(&clk_core, 504 * MHZ); + + //general + printk("*********general_pll_clk***********\n"); + clk_set_rate_nolock(&general_pll_clk, ppll_rate); + + //code pll + printk("*********codec_pll_clk***********\n"); + clk_set_rate_nolock(&codec_pll_clk, 600 * MHZ); + + + printk("*********periph_clk_set_init***********\n"); + clk_set_parent_nolock(&aclk_periph, &general_pll_clk); + periph_clk_set_init(); + +#if 0 // + clk_set_parent_nolock(&clk_i2s_pll, &codec_pll_clk); +#else + printk("*********clk i2s***********\n"); + clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk); + printk("common %s parent is %s\n", clk_i2s_pll.name, test_get_parent(&clk_i2s_pll)->name); + i2s_test(); +#endif + // spi + clk_enable_nolock(&clk_spi0); + clk_set_rate_nolock(&clk_spi0, 30 * MHZ); + printk("common %s parent is %s\n", clk_spi0.name, test_get_parent(&clk_spi0)->name); + //saradc + clk_enable_nolock(&clk_saradc); + clk_set_rate_nolock(&clk_saradc, 6 * MHZ); + printk("common %s parent is %s\n", clk_saradc.name, test_get_parent(&clk_saradc)->name); + //sdio + clk_enable_nolock(&clk_sdio); + clk_set_rate_nolock(&clk_sdio, 50 * MHZ); + printk("common %s parent is %s\n", clk_sdio.name, test_get_parent(&clk_sdio)->name); + // uart + clk_set_parent_nolock(&clk_uart_pll, &general_pll_clk); + uart_test(); + //mac + printk("*********mac***********\n"); + + clk_set_parent_nolock(&clk_mac_pll_div, &general_pll_clk); + printk("common %s parent is %s\n", clk_mac_pll_div.name, test_get_parent(&clk_mac_pll_div)->name); + + //clk_set_parent_nolock(&clk_mac_ref, &clk_mac_pll_div); + clk_set_rate_nolock(&clk_mac_ref, 50 * MHZ); + printk("common %s parent is %s\n", clk_mac_ref.name, test_get_parent(&clk_mac_ref)->name); + + printk("*********mac mii set***********\n"); + clk_set_parent_nolock(&clk_mac_ref, &rmii_clkin); + clk_set_rate_nolock(&clk_mac_ref, 20 * MHZ); + printk("common %s parent is %s\n", clk_mac_ref.name, test_get_parent(&clk_mac_ref)->name); + //hsadc + printk("*********hsadc 1***********\n"); + //auto pll + hsadc_test(); + //lcdc + clk_enable_nolock(&dclk_lcdc0); + + clk_set_rate_nolock(&dclk_lcdc0, 60 * MHZ); + clk_set_rate_nolock(&dclk_lcdc0, 27 * MHZ); + + //cif + clk_enable_nolock(&cif0_out); + + clk_set_parent_nolock(&cif_out_pll, &general_pll_clk); + printk("common %s parent is %s\n", cif_out_pll.name, test_get_parent(&cif_out_pll)->name); + + clk_set_rate_nolock(&cif0_out, 60 * MHZ); + printk("common %s parent is %s\n", cif0_out.name, test_get_parent(&cif0_out)->name); + + clk_set_rate_nolock(&cif0_out, 24 * MHZ); + printk("common %s parent is %s\n", cif0_out.name, test_get_parent(&cif0_out)->name); + //cif_in + clk_enable_nolock(&cif0_in); + clk_set_rate_nolock(&cif0_in, 24 * MHZ); + //axi lcdc + clk_enable_nolock(&aclk_lcdc0); + clk_set_rate_nolock(&aclk_lcdc0, 150 * MHZ); + printk("common %s parent is %s\n", aclk_lcdc0.name, test_get_parent(&aclk_lcdc0)->name); + //axi vepu + clk_enable_nolock(&aclk_vepu); + clk_set_rate_nolock(&aclk_vepu, 300 * MHZ); + printk("common %s parent is %s\n", aclk_vepu.name, test_get_parent(&aclk_vepu)->name); + + clk_set_rate_nolock(&hclk_vepu, 300 * MHZ); + printk("common %s parent is %s\n", hclk_vepu.name, test_get_parent(&hclk_vepu)->name); + + printk("test end\n"); + + /* arm pll + clk_set_rate_nolock(&arm_pll_clk, armclk); + clk_set_rate_nolock(&clk_core, armclk);//pll:core =1:1 + */ + // + //clk_set_rate_nolock(&codec_pll_clk, ppll_rate*2); + // + //clk_set_rate_nolock(&aclk_vepu, 300 * MHZ); + //clk_set_rate_nolock(&clk_gpu, 300 * MHZ); + +} + + + + + +static LIST_HEAD(rk30_clocks); +static DEFINE_MUTEX(rk30_clocks_mutex); + +static inline int __rk30clk_get(struct clk *clk) +{ + return 1; +} +void rk30_clkdev_add(struct clk_lookup *cl) +{ + mutex_lock(&rk30_clocks_mutex); + list_add_tail(&cl->node, &rk30_clocks); + mutex_unlock(&rk30_clocks_mutex); +} +static struct clk_lookup *rk30_clk_find(const char *dev_id, const char *con_id) { + struct clk_lookup *p, *cl = NULL; + int match, best = 0; + + list_for_each_entry(p, &rk30_clocks, node) { + match = 0; + if (p->dev_id) { + if (!dev_id || strcmp(p->dev_id, dev_id)) + continue; + match += 2; + } + if (p->con_id) { + if (!con_id || strcmp(p->con_id, con_id)) + continue; + match += 1; + } + + if (match > best) { + cl = p; + if (match != 3) + best = match; + else + break; + } + } + return cl; +} + +struct clk *rk30_clk_get_sys(const char *dev_id, const char *con_id) { + struct clk_lookup *cl; + + mutex_lock(&rk30_clocks_mutex); + cl = rk30_clk_find(dev_id, con_id); + if (cl && !__rk30clk_get(cl->clk)) + cl = NULL; + mutex_unlock(&rk30_clocks_mutex); + + return cl ? cl->clk : ERR_PTR(-ENOENT); +} +//EXPORT_SYMBOL(rk30_clk_get_sys); + +struct clk *rk30_clk_get(struct device *dev, const char *con_id) { + const char *dev_id = dev ? dev_name(dev) : NULL; + return rk30_clk_get_sys(dev_id, con_id); +} +//EXPORT_SYMBOL(rk30_clk_get); + + +int rk30_clk_set_rate(struct clk *clk, unsigned long rate); + +void rk30_clocks_test(void) +{ + struct clk *test_gpll; + test_gpll = rk30_clk_get(NULL, "general_pll"); + if(test_gpll) { + rk30_clk_set_rate(test_gpll, 297 * 2 * MHZ); + printk("gpll rate=%lu\n", test_gpll->rate); + } + //while(1); +} + +void __init rk30_clock_init_test(void) +{ + + rk30_clock_init(periph_pll_297mhz, codec_pll_360mhz, max_i2s_12288khz); + //while(1); +} + + +#endif + + diff --git a/arch/arm/mach-rk3188/include/mach/cru-rk3188.h b/arch/arm/mach-rk3188/include/mach/cru-rk3188.h new file mode 100755 index 000000000000..4f54b18e67f8 --- /dev/null +++ b/arch/arm/mach-rk3188/include/mach/cru-rk3188.h @@ -0,0 +1,602 @@ +enum rk_plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + GPLL_ID, + END_PLL_ID, +}; + +/*****cru reg offset*****/ + +#define CRU_MODE_CON 0x40 +#define CRU_CLKSEL_CON 0x44 +#define CRU_CLKGATE_CON 0xd0 +#define CRU_GLB_SRST_FST 0x100 +#define CRU_GLB_SRST_SND 0x104 +#define CRU_SOFTRST_CON 0x110 + +#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) + +#define CRU_CLKSELS_CON_CNT (35) +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4)) + +#define CRU_CLKGATES_CON_CNT (10) +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4)) + +#define CRU_SOFTRSTS_CON_CNT (9) +#define CRU_SOFTRSTS_CON(i) (CRU_SOFTRST_CON + ((i) * 4)) + +#define CRU_MISC_CON (0x134) +#define CRU_GLB_CNT_TH (0x140) + +/********************************************************************/ +#define CRU_GET_REG_BITS_VAL(reg,bits_shift, msk) (((reg) >> (bits_shift))&(msk)) +#define CRU_W_MSK(bits_shift, msk) ((msk) << ((bits_shift) + 16)) +#define CRU_SET_BITS(val,bits_shift, msk) (((val)&(msk)) << (bits_shift)) + +#define CRU_W_MSK_SETBITS(val,bits_shift,msk) (CRU_W_MSK(bits_shift, msk)|CRU_SET_BITS(val,bits_shift, msk)) + +/*******************PLL CON0 BITS***************************/ + +#define PLL_CLKFACTOR_SET(val, shift, msk) \ + ((((val) - 1) & (msk)) << (shift)) + +#define PLL_CLKFACTOR_GET(reg, shift, msk) \ + ((((reg) >> (shift)) & (msk)) + 1) + +#define PLL_OD_MSK (0x3f) +#define PLL_OD_SHIFT (0x0) + +#define PLL_CLKOD(val) PLL_CLKFACTOR_SET(val, PLL_OD_SHIFT, PLL_OD_MSK) +#define PLL_NO(reg) PLL_CLKFACTOR_GET(reg, PLL_OD_SHIFT, PLL_OD_MSK) + +#define PLL_NO_SHIFT(reg) PLL_CLKFACTOR_GET(reg, PLL_OD_SHIFT, PLL_OD_MSK) + +#define PLL_CLKOD_SET(val) (PLL_CLKOD(val) | CRU_W_MSK(PLL_OD_SHIFT, PLL_OD_MSK)) + +#define PLL_NR_MSK (0x3f) +#define PLL_NR_SHIFT (8) +#define PLL_CLKR(val) PLL_CLKFACTOR_SET(val, PLL_NR_SHIFT, PLL_NR_MSK) +#define PLL_NR(reg) PLL_CLKFACTOR_GET(reg, PLL_NR_SHIFT, PLL_NR_MSK) + +#define PLL_CLKR_SET(val) (PLL_CLKR(val) | CRU_W_MSK(PLL_NR_SHIFT, PLL_NR_MSK)) + +/*******************PLL CON1 BITS***************************/ + +#define PLL_NF_MSK (0xffff) +#define PLL_NF_SHIFT (0) +#define PLL_CLKF(val) PLL_CLKFACTOR_SET(val, PLL_NF_SHIFT, PLL_NF_MSK) +#define PLL_NF(reg) PLL_CLKFACTOR_GET(reg, PLL_NF_SHIFT, PLL_NF_MSK) + +#define PLL_CLKF_SET(val) (PLL_CLKF(val) | CRU_W_MSK(PLL_NF_SHIFT, PLL_NF_MSK)) + +/*******************PLL CON2 BITS***************************/ +#if 0 +#define PLL_BWADJ_MSK (0xfff) +#define PLL_BWADJ_SHIFT (0) +#define PLL_CLK_BWADJ_SET(val) ((val) | CRU_W_MSK(PLL_BWADJ_SHIFT, PLL_BWADJ_MSK)) +#endif +/*******************PLL CON3 BITS***************************/ + +#if 0 +#define PLL_REST_MSK (1 << 5) +#define PLL_REST_W_MSK (PLL_REST_MSK << 16) +#define PLL_REST (1 << 5) +#define PLL_REST_RESM (0 << 5) +#endif + +#define PLL_BYPASS_MSK (1 << 0) +#define PLL_BYPASS (1 << 0) +#define PLL_NO_BYPASS (0 << 0) + +#define PLL_PWR_DN_MSK (1 << 1) +#define PLL_PWR_DN_W_MSK (PLL_PWR_DN_MSK << 16) +#define PLL_PWR_DN (1 << 1) +#define PLL_PWR_ON (0 << 1) + +#define PLL_STANDBY_MSK (1 << 2) +#define PLL_STANDBY (1 << 2) +#define PLL_NO_STANDBY (0 << 2) +/*******************CLKSEL0 BITS***************************/ +//core preiph div +#define CORE_PERIPH_W_MSK (3 << 22) +#define CORE_PERIPH_MSK (3 << 6) +#define CORE_PERIPH_2 (0 << 6) +#define CORE_PERIPH_4 (1 << 6) +#define CORE_PERIPH_8 (2 << 6) +#define CORE_PERIPH_16 (3 << 6) +//arm clk pll sel +#define CORE_SEL_PLL_MSK (1 << 8) +#define CORE_SEL_PLL_W_MSK (1 << 24) +#define CORE_SEL_APLL (0 << 8) +#define CORE_SEL_GPLL (1 << 8) + +#define CORE_CLK_DIV_W_MSK (0x1F << 25) +#define CORE_CLK_DIV_MSK (0x1F << 9) +#define CORE_CLK_DIV(i) (((i) - 1) & 0x1F) + +#define CPU_SEL_PLL_MSK (1 << 5) +#define CPU_SEL_PLL_W_MSK (1 << 21) +#define CPU_SEL_APLL (0 << 5) +#define CPU_SEL_GPLL (1 << 5) + +#define CPU_CLK_DIV_W_MSK (0x1F << 16) +#define CPU_CLK_DIV_MSK (0x1F) +#define CPU_CLK_DIV(i) (((i) - 1) & 0x1F) + +/*******************CLKSEL1 BITS***************************/ +//aclk div +#define GET_CORE_ACLK_VAL(reg) ((reg)>=4 ?8:((reg)+1)) + +#define CPU_ACLK_W_MSK (7 << 16) +#define CPU_ACLK_MSK (7 << 0) +#define CPU_ACLK_11 (0 << 0) +#define CPU_ACLK_21 (1 << 0) +#define CPU_ACLK_31 (2 << 0) +#define CPU_ACLK_41 (3 << 0) +#define CPU_ACLK_81 (4 << 0) + +#define CORE_ACLK_W_MSK (7 << 19) +#define CORE_ACLK_MSK (7 << 3) +#define CORE_ACLK_11 (0 << 3) +#define CORE_ACLK_21 (1 << 3) +#define CORE_ACLK_31 (2 << 3) +#define CORE_ACLK_41 (3 << 3) +#define CORE_ACLK_81 (4 << 3) +//hclk div +#define ACLK_HCLK_W_MSK (3 << 24) +#define ACLK_HCLK_MSK (3 << 8) +#define ACLK_HCLK_11 (0 << 8) +#define ACLK_HCLK_21 (1 << 8) +#define ACLK_HCLK_41 (2 << 8) +// pclk div +#define ACLK_PCLK_W_MSK (3 << 28) +#define ACLK_PCLK_MSK (3 << 12) +#define ACLK_PCLK_11 (0 << 12) +#define ACLK_PCLK_21 (1 << 12) +#define ACLK_PCLK_41 (2 << 12) +#define ACLK_PCLK_81 (3 << 12) +// ahb2apb div +#define AHB2APB_W_MSK (3 << 30) +#define AHB2APB_MSK (3 << 14) +#define AHB2APB_11 (0 << 14) +#define AHB2APB_21 (1 << 14) +#define AHB2APB_41 (2 << 14) + +/*******************MODE BITS***************************/ + +#define PLL_MODE_MSK(id) (0x3 << ((id) * 4)) +#define PLL_MODE_SLOW(id) ((0x0<<((id)*4))|(0x3<<(16+(id)*4))) +#define PLL_MODE_NORM(id) ((0x1<<((id)*4))|(0x3<<(16+(id)*4))) +#define PLL_MODE_DEEP(id) ((0x2<<((id)*4))|(0x3<<(16+(id)*4))) + +/*******************clksel10***************************/ + +#define PERI_ACLK_DIV_MASK 0x1f +#define PERI_ACLK_DIV_W_MSK (PERI_ACLK_DIV_MASK << 16) +#define PERI_ACLK_DIV(i) (((i) - 1) & PERI_ACLK_DIV_MASK) +#define PERI_ACLK_DIV_OFF 0 + +#define PERI_HCLK_DIV_MASK 0x3 +#define PERI_HCLK_DIV_OFF 8 + +#define PERI_PCLK_DIV_MASK 0x3 +#define PERI_PCLK_DIV_OFF 12 + +/*******************gate BITS***************************/ + +#define CLK_GATE_CLKID(i) (16 * (i)) +#define CLK_GATE_CLKID_CONS(i) CRU_CLKGATES_CON((i) / 16) + +#define CLK_GATE(i) (1 << ((i)%16)) +#define CLK_UN_GATE(i) (0) + +#define CLK_GATE_W_MSK(i) (1 << (((i) % 16) + 16)) + +enum cru_clk_gate { + /* SCU CLK GATE 0 CON */ + CLK_GATE_CORE_PERIPH = CLK_GATE_CLKID(0), + CLK_GATE_CPU_GPLL_PATH, + CLK_GATE_DDRPHY, + CLK_GATE_ACLK_CPU, + + CLK_GATE_HCLK_CPU, + CLK_GATE_PCLK_CPU, + CLK_GATE_ATCLK_CPU, + CLK_GATE_ACLK_CORE, + + CLK_GATE_0RES8, + CLK_GATE_I2S0_SRC, + CLK_GATE_I2S0_FRAC, + CLK_GATE_0RES11, + + CLK_GATE_0RES12, + CLK_GATE_SPDIF_SRC, + CLK_GATE_SPDIF_FRAC, + CLK_GATE_TESTCLK, + + CLK_GATE_TIMER0 = CLK_GATE_CLKID(1), + CLK_GATE_TIMER1, + CLK_GATE_TIMER3, + CLK_GATE_JTAG, + + CLK_GATE_ACLK_LCDC1_SRC, + CLK_GATE_OTGPHY0, + CLK_GATE_OTGPHY1, + CLK_GATE_DDR_GPLL, + + CLK_GATE_UART0_SRC, + CLK_GATE_UART0_FRAC_SRC, + CLK_GATE_UART1_SRC, + CLK_GATE_UART1_FRAC_SRC, + + CLK_GATE_UART2_SRC, + CLK_GATE_UART2_FRAC_SRC, + CLK_GATE_UART3_SRC, + CLK_GATE_UART3_FRAC_SRC, + + CLK_GATE_PERIPH_SRC = CLK_GATE_CLKID(2), + CLK_GATE_ACLK_PERIPH, + CLK_GATE_HCLK_PERIPH, + CLK_GATE_PCLK_PERIPH, + + CLK_GATE_SMC_SRC, + CLK_GATE_MAC_SRC, + CLK_GATE_HSADC_SRC, + CLK_GATE_HSADC_FRAC_SRC, + + CLK_GATE_SARADC_SRC, + CLK_GATE_SPI0_SRC, + CLK_GATE_SPI1_SRC, + CLK_GATE_MMC0_SRC, + + CLK_GATE_MAC_LBTEST, + CLK_GATE_SDIO_SRC, + CLK_GATE_EMMC_SRC, + CLK_GATE_2RES15, + + CLK_GATE_ACLK_LCDC0_SRC = CLK_GATE_CLKID(3), + CLK_GATE_DCLK_LCDC0_SRC, + CLK_GATE_DCLK_LCDC1_SRC, + CLK_GATE_PCLKIN_CIF0, + + CLK_GATE_TIMER2, + CLK_GATE_TIMER4, + CLK_GATE_HSICPHY_SRC, + CLK_GATE_CIF0_OUT, + + CLK_GATE_TIMER5, + CLK_GATE_ACLK_VEPU, + CLK_GATE_HCLK_VEPU, + CLK_GATE_ACLK_VDPU, + + CLK_GATE_HCLK_VDPU, + CLK_GATE_3RES13, + CLK_GATE_TIMER6, + CLK_GATE_ACLK_GPU_SRC, + + CLK_GATE_HCLK_PERI_AXI_MATRIX = CLK_GATE_CLKID(4), + CLK_GATE_PCLK_PERI_AXI_MATRIX, + CLK_GATE_ACLK_CPU_PERI, + CLK_GATE_ACLK_PERI_AXI_MATRIX, + + CLK_GATE_ACLK_PEI_NIU, + CLK_GATE_HCLK_USB_PERI, + CLK_GATE_HCLK_PERI_AHB_ARBI, + CLK_GATE_HCLK_EMEM_PERI, + + CLK_GATE_HCLK_CPUBUS, + CLK_GATE_HCLK_AHB2APB, + CLK_GATE_ACLK_STRC_SYS, + CLK_GATE_4RES11, + + CLK_GATE_ACLK_INTMEM, + CLK_GATE_4RES13, + CLK_GATE_HCLK_IMEM1, + CLK_GATE_HCLK_IMEM0, + + CLK_GATE_ACLK_DMAC1 = CLK_GATE_CLKID(5), + CLK_GATE_ACLK_DMAC2, + CLK_GATE_PCLK_EFUSE, + CLK_GATE_PCLK_TZPC, + + CLK_GATE_PCLK_GRF, + CLK_GATE_PCLK_PMU, + CLK_GATE_HCLK_ROM, + CLK_GATE_PCLK_DDRUPCTL, + + CLK_GATE_ACLK_SMC, + CLK_GATE_HCLK_NANDC, + CLK_GATE_HCLK_SDMMC0, + CLK_GATE_HCLK_SDIO, + + CLK_GATE_HCLK_EMMC, + CLK_GATE_HCLK_OTG0, + CLK_GATE_5RES14, + CLK_GATE_5RES15, + + CLK_GATE_ACLK_LCDC0 = CLK_GATE_CLKID(6), + CLK_GATE_HCLK_LCDC0, + CLK_GATE_HCLK_LCDC1, + CLK_GATE_ACLK_LCDC1, + + CLK_GATE_HCLK_CIF0, + CLK_GATE_ACLK_CIF0, + CLK_GATE_6RES6, + CLK_GATE_6RES7, + + CLK_GATE_ACLK_IPP, + CLK_GATE_HCLK_IPP, + CLK_GATE_HCLK_RGA, + CLK_GATE_ACLK_RGA, + + CLK_GATE_HCLK_VIO_BUS, + CLK_GATE_ACLK_VIO0, + CLK_GATE_6RES14, + CLK_GATE_6RES15, + + CLK_GATE_HCLK_EMAC = CLK_GATE_CLKID(7), + CLK_GATE_HCLK_SPDIF, + CLK_GATE_HCLK_I2S0_2CH, + CLK_GATE_HCLK_OTG1, + + CLK_GATE_HCLK_HSIC, + CLK_GATE_HCLK_HSADC, + CLK_GATE_HCLK_PIDF, + CLK_GATE_PCLK_TIMER0, + + CLK_GATE_7RES8, + CLK_GATE_PCLK_TIMER2, //same as RK3066B, diff list's mistake + CLK_GATE_PCLK_PWM01, + CLK_GATE_PCLK_PWM23, + + CLK_GATE_PCLK_SPI0, + CLK_GATE_PCLK_SPI1, + CLK_GATE_PCLK_SARADC, + CLK_GATE_PCLK_WDT, + + CLK_GATE_PCLK_UART0 = CLK_GATE_CLKID(8), + CLK_GATE_PCLK_UART1, + CLK_GATE_PCLK_UART2, + CLK_GATE_PCLK_UART3, + + CLK_GATE_PCLK_I2C0, + CLK_GATE_PCLK_I2C1, + CLK_GATE_PCLK_I2C2, + CLK_GATE_PCLK_I2C3, + + CLK_GATE_PCLK_I2C4, + CLK_GATE_PCLK_GPIO0, + CLK_GATE_PCLK_GPIO1, + CLK_GATE_PCLK_GPIO2, + + CLK_GATE_PCLK_GPIO3, + CLK_GATE_ACLK_GPS, + CLK_GATE_8RES14, + CLK_GATE_8RES15, + + CLK_GATE_CLK_CORE_DBG = CLK_GATE_CLKID(9), + CLK_GATE_PCLK_DBG, + CLK_GATE_CLK_TRACE, + CLK_GATE_ATCLK, + + CLK_GATE_CLK_L2C, + CLK_GATE_ACLK_VIO1, + CLK_GATE_PCLK_PUBL, + CLK_GATE_ACLK_GPU, + + CLK_GATE_9RES8, + CLK_GATE_9RES9, + CLK_GATE_9RES10, + CLK_GATE_9RES11, + + CLK_GATE_9RES12, + CLK_GATE_9RES13, + CLK_GATE_9RES14, + CLK_GATE_9RES15, + + CLK_GATE_MAX, +}; + +/* for compatible with rk30xx */ +#define CLK_GATE_ACLK_CIF1 CLK_GATE_ACLK_CIF0 +#define CLK_GATE_ACLK_INTMEM0 CLK_GATE_CLK_L2C +#define CLK_GATE_ACLK_INTMEM1 CLK_GATE_ACLK_INTMEM0 +#define CLK_GATE_ACLK_INTMEM2 CLK_GATE_ACLK_INTMEM0 +#define CLK_GATE_ACLK_INTMEM3 CLK_GATE_ACLK_INTMEM0 + +#define SOFT_RST_ID(i) (16 * (i)) + +enum cru_soft_reset { + SOFT_RST_0RES0 = SOFT_RST_ID(0), + SOFT_RST_0RES1, + SOFT_RST_MCORE, + SOFT_RST_CORE0, + + SOFT_RST_CORE1, + SOFT_RST_0RES5, + SOFT_RST_0RES6, + SOFT_RST_MCORE_DBG, + + SOFT_RST_CORE0_DBG, + SOFT_RST_CORE1_DBG, + SOFT_RST_0RES10, + SOFT_RST_0RES11, + + SOFT_RST_CORE0_WDT, + SOFT_RST_CORE1_WDT, + SOFT_RST_STRC_SYS_AXI, + SOFT_RST_L2C, + + SOFT_RST_1RES0 = SOFT_RST_ID(1), + SOFT_RST_CPUSYS_AHB, + SOFT_RST_L2MEM_CON_AXI, + SOFT_RST_AHB2APB, + + SOFT_RST_DMA1, + SOFT_RST_INTMEM, + SOFT_RST_ROM, + SOFT_RST_1RES7, + + SOFT_RST_I2S, + SOFT_RST_1RES9, + SOFT_RST_SPDIF, + SOFT_RST_TIMER0, + + SOFT_RST_TIMER1, + SOFT_RST_TIMER2, + SOFT_RST_EFUSE_APB, + SOFT_RST_1RES15, + + SOFT_RST_GPIO0 = SOFT_RST_ID(2), + SOFT_RST_GPIO1, + SOFT_RST_GPIO2, + SOFT_RST_GPIO3, + + SOFT_RST_2RES4, + SOFT_RST_2RES5, + SOFT_RST_2RES6, + SOFT_RST_UART0, + + SOFT_RST_UART1, + SOFT_RST_UART2, + SOFT_RST_UART3, + SOFT_RST_I2C0, + + SOFT_RST_I2C1, + SOFT_RST_I2C2, + SOFT_RST_I2C3, + SOFT_RST_I2C4, + + SOFT_RST_PWM0 = SOFT_RST_ID(3), + SOFT_RST_PWM1, + SOFT_RST_DAP_PO, + SOFT_RST_DAP, + + SOFT_RST_DAP_SYS, + SOFT_RST_TPIU_ATB, + SOFT_RST_PMU_APB, + SOFT_RST_GRF, + + SOFT_RST_PMU, + SOFT_RST_PERIPHSYS_AXI, + SOFT_RST_PERIPHSYS_AHB, + SOFT_RST_PERIPHSYS_APB, + + SOFT_RST_PERIPH_NIU, + SOFT_RST_CPU_PERI, + SOFT_RST_EMEM_PERI, + SOFT_RST_USB_PERI, + + SOFT_RST_DMA2 = SOFT_RST_ID(4), + SOFT_RST_SMC, + SOFT_RST_MAC, + SOFT_RST_GPS, + + SOFT_RST_NANDC, + SOFT_RST_USBOTG0, + SOFT_RST_USBPHY0, + SOFT_RST_OTGC0, + + SOFT_RST_USBOTG1, + SOFT_RST_USBPHY1, + SOFT_RST_OTGC1, + SOFT_RST_HSICPHY, + + SOFT_RST_HSADC, + SOFT_RST_PIDFILTER, + SOFT_RST_4RES14, + SOFT_RST_DDRMSCH, + + SOFT_RST_TZPC = SOFT_RST_ID(5), + SOFT_RST_MMC0, + SOFT_RST_SDIO, + SOFT_RST_EMMC, + + SOFT_RST_SPI0, + SOFT_RST_SPI1, + SOFT_RST_WDT, + SOFT_RST_SARADC, + + SOFT_RST_DDRPHY, + SOFT_RST_DDRPHY_APB, + SOFT_RST_DDRCTRL, + SOFT_RST_DDRCTRL_APB, + + SOFT_RST_5RES12, + SOFT_RST_DDRPHY_CTL, + SOFT_RST_5RES14, + SOFT_RST_5RES15, + + SOFT_RST_6RES0 = SOFT_RST_ID(6), + SOFT_RST_6RES1, + SOFT_RST_VIO0_AXI, + SOFT_RST_VIO_BUS_AHB, + + SOFT_RST_LCDC0_AXI, + SOFT_RST_LCDC0_AHB, + SOFT_RST_LCDC0_DCLK, + SOFT_RST_LCDC1_AXI, + + SOFT_RST_LCDC1_AHB, + SOFT_RST_LCDC1_DCLK, + SOFT_RST_IPP_AXI, + SOFT_RST_IPP_AHB, + + SOFT_RST_RGA_AXI, + SOFT_RST_RGA_AHB, + SOFT_RST_CIF0, + SOFT_RST_CIF1,//SOFT_RST_6RES15, + + SOFT_RST_VCODEC_AXI = SOFT_RST_ID(7), + SOFT_RST_VCODEC_AHB, + SOFT_RST_VIO1_AXI, + SOFT_RST_CPU_VCODEC, + + SOFT_RST_VCODEC_NIU_AXI, + SOFT_RST_HSIC_AHB, + SOFT_RST_7RES6, + SOFT_RST_7RES7, + + SOFT_RST_GPU_CORE, + SOFT_RST_7RES9, + SOFT_RST_GPU_NIU_AXI, + SOFT_RST_7RES11, + + SOFT_RST_7RES12, + SOFT_RST_TFUN_ATB, + SOFT_RST_TFUN_APB, + SOFT_RST_CTI4_APB, + + SOFT_RST_TPIU_APB = SOFT_RST_ID(8), + SOFT_RST_TRACE, + SOFT_RST_CORE_DBG, + SOFT_RST_DBG_APB, + + SOFT_RST_CTI0, + SOFT_RST_CTI0_APB, + SOFT_RST_CTI1, + SOFT_RST_CTI1_APB, + + SOFT_RST_PTM_CORE0, + SOFT_RST_PTM_CORE1, + SOFT_RST_PTM0, + SOFT_RST_PTM0_ATB, + + SOFT_RST_PTM1, + SOFT_RST_PTM1_ATB, + SOFT_RST_CTM, + SOFT_RST_TS, + + SOFT_RST_MAX, +}; + +/*****cru reg end*****/ + +static inline void cru_set_soft_reset(enum cru_soft_reset idx, bool on) +{ + const void __iomem *reg = RK30_CRU_BASE + CRU_SOFTRSTS_CON(idx >> 4); + u32 val = on ? 0x10001U << (idx & 0xf) : 0x10000U << (idx & 0xf); + writel_relaxed(val, reg); + dsb(); +} diff --git a/arch/arm/mach-rk3188/include/mach/cru.h b/arch/arm/mach-rk3188/include/mach/cru.h index f37a897bb419..4739b0172f3b 100644 --- a/arch/arm/mach-rk3188/include/mach/cru.h +++ b/arch/arm/mach-rk3188/include/mach/cru.h @@ -1,4 +1,4 @@ #ifndef __MACH_CRU_H #define __MACH_CRU_H - +#include #endif