void debug_clk_set_parent(unsigned int num, unsigned int parent_num)
{
        const char *clk_name = NULL;
        const char *parent_name = NULL;
        struct clk *clk = NULL;
        struct clk *parent_clk = NULL;
        unsigned long ret = 0;
        clk_name = hi6930_clk_lookup[num].con_id;
        clk = clk_get(NULL, clk_name);

        parent_name = hi6930_clk_lookup[parent_num].con_id;
        parent_clk = clk_get(NULL, parent_name);
        if(IS_ERR(clk)){
                clk_printf("clk:%s is NULL, can't find it,please check!!\n", clk_name);
                return;
        }
        if(IS_ERR(parent_clk)){
                clk_printf("clk:%s is NULL, can't find it,please check!!\n", parent_name);
                return;
        }
        ret = (unsigned long)clk_set_parent(clk, parent_clk);
        if (ret){
                clk_printf("clk:%s set parent clk :%s, failure!!\n", clk_name, parent_name);
                return;
        }
        parent_clk = clk_get_parent(clk);
		if(parent_clk == NULL)
			return;
        clk_printf("clk:%s ---parent is :%s\n\n", clk_name, parent_clk->name);
        return;
}
void debug_clk_get_rate(unsigned int num)
{
        const char *clk_name = NULL;
        struct clk *clk = NULL;
        unsigned long ret = 0;
        clk_name = hi6930_clk_lookup[num].con_id;
        clk = clk_get(NULL, clk_name);
        if(IS_ERR(clk)){
                clk_printf("clk:%s is NULL, can't find it,please check!!\n", clk_name);
                return;
        }
        ret = clk_get_rate(clk);
        clk_printf("clk:%s ---rate is :%ld\n\n", clk_name, ret);
        return;
}
int clk_set_rate_test_case0(void)
{
    struct clk *sio_bclk = clk_get(NULL,"sio_bclk");
    int ret = 0;
    ret = clk_set_rate(sio_bclk, TCXO/4);
    if (ret){
            clk_printf("sio_bclk set rate TCXO/4,failure\n");
            return CLK_TEST_ERROR;
   }
    clk_set_rate(sio_bclk, TCXO);
	debug_clock();
	debug_clk_enable(30);
	debug_clk_disable(30);
	debug_clk_set_rate(30,100);
	debug_clk_get_rate(30);
	debug_clk_set_parent(30,31);
	debug_clk_status(30);
	
	debug_clk_enable(14);
	debug_clk_disable(14);
	debug_clk_set_rate(14,100);
	debug_clk_get_rate(14);
	debug_clk_set_parent(14,15);
	debug_clk_status(14);
         return CLK_TEST_OK;
}
int clk_disable_test_case1(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_clk");
   struct clk *apb_pclk = clk_get(NULL,"sleep_clk");
	int ret = 0;
    clk_disable(sio_clk);
    if (reg_message[sio_clk->clkid].enable_flag){
                ret = sio_clk->ops->isenable(sio_clk);
    }
    if(ret){
            clk_printf("can't disable sio_clk\n");
            return CLK_TEST_ERROR;
    }
	ret =  clk_enable(apb_pclk);
	clk_disable(apb_pclk);
	ret |= clk_round_rate(apb_pclk,100);
	ret |= clk_set_rate(apb_pclk,100);
	ret |= clk_set_parent(apb_pclk,sio_clk);
	ret |= clk_status(apb_pclk);
	if(ret)
		return CLK_TEST_OK;
	if(!ret)
		return CLK_TEST_ERROR;
    return CLK_TEST_OK;
}
int __init clock_debug_init(void)
{
	debugfs_base = debugfs_create_dir("clk", NULL);
	if (!debugfs_base){
	      clk_printf("@@@@@@@@clock_debug_init_failure");
		return -ENOMEM;
	}
	return 0;
}
/*for clock div N + 1*/
int hi6930_clk_set_rate(struct clk *clk, unsigned long rate)
{
        struct clk *clkparent = NULL;
        unsigned int div = 0;
        unsigned int clkid = 0;
        unsigned int regvalue = 0;
        int ret = 0;
        clkid = clk->clkid;
        if (!clk->parent){
                 clk_printf("clock: %s has no parent,can't set rate!!!\n", clk->name);
                 return -1;
        }
         /*find the right rate from its mulparent*/
        if (NULL != clk->sel_parents){
                clkparent = hi6930_clk_find_parent_from_selparents(clk, rate);
                if (clkparent == clk->parent)
                         return 0;
                if (!clk->ops || !clk->ops->set_parent){
                         clk_printf("clock: %s has no ops or ops->set_parent!!!\n", clk->name);
                         return -1;
                }
                ret = clk->ops->set_parent(clk, clkparent);
                clk->rate = clk->parent->rate;
                return ret;
        }

        /*set clock div by register,div must in the range of bits*/
        if (reg_message[clkid].div_reg){
                div = clk->parent->rate / rate;
                if(clk->parent->rate % rate)
                    div = div + 1;
                if (div >= REG_MIN_VALUE && div <= reg_message[clkid].div){
                        regvalue = readl(HI_SYSCRG_BASE_ADDR_VIRT + reg_message[clkid].div_reg);
                        regvalue &= (~(reg_message[clkid].div << reg_message[clkid].div_bit));
                        regvalue |= ((div - 0x1) << reg_message[clkid].div_bit);/* [false alarm]:误报 */
                        writel(regvalue, HI_SYSCRG_BASE_ADDR_VIRT + reg_message[clkid].div_reg);
                        clk->rate = clk->parent->rate / div;
                        return 0;
                }
        }
        clk_printf("clock: %s clk_set_rate failure!!!\n", clk->name);
        return -1;
}
int clk_get_rate_test_case1(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_clk");
    unsigned long rate = clk_get_rate(sio_clk);
    if (rate != TCXO){
            clk_printf("sio_clk rate is not 19.2M\n");
            return CLK_TEST_ERROR;
    }
    return CLK_TEST_OK;
}
int clk_set_rate_test_case1(void)
{
    struct clk *sio_bclk = clk_get(NULL,"sio_bclk");
   struct clk *cipher_clk = clk_get(NULL,"cipher_clk");
    int ret = 0;
    clk_set_rate(sio_bclk, TCXO/4);
    if (ret){
            clk_printf("sio_bclk set rate TCXO/4,failure\n");
            return CLK_TEST_ERROR;
   }
    ret = clk_set_rate(sio_bclk, TCXO);
    ret = clk_set_rate(cipher_clk, PERIPLL_FOUNTPOST/5);
    if (ret){
            clk_printf("cipher_clk PERIPLL_FOUNTPOST/5,failure\n");
            return CLK_TEST_ERROR;
   }
   clk_round_rate(cipher_clk, PERIPLL_FOUNTPOST/5);
    return CLK_TEST_OK;
}
void debug_clk_enable(unsigned int num)
{
        int ret = 0;
        const char *clk_name = NULL;
        struct clk *clk = NULL;
        clk_name = hi6930_clk_lookup[num].con_id;
        clk = clk_get(NULL, clk_name);
        if(IS_ERR(clk)){
                clk_printf("clk:%s is NULL, can't find it,please check!!\n", clk_name);
                return;
        }
        ret = clk_enable(clk);
        if(!ret){
                clk_printf("clk:%s enable OK!!\n", clk_name);
                return;
         }
        clk_printf("clk:%s enable failure!!\n", clk_name);
        return;
}
int clk_get_parent_test_case1(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_clk");
    struct clk *tcxo = clk_get(NULL, "tcxo");
    struct clk *parent = clk_get_parent(sio_clk);
    if (parent != tcxo){
            clk_printf("sio_clk parent is not tcxo\n");
            return CLK_TEST_ERROR;
    }
    return CLK_TEST_OK;
}
void debug_clk_status(unsigned int num)
{
        const char *clk_name = NULL;
        struct clk *clk = NULL;
        int ret = 0;
        clk_name = hi6930_clk_lookup[num].con_id;
        clk = clk_get(NULL, clk_name);
        ret = clk_status(clk);
        clk_printf("clk:%s status = %d\n", clk_name, ret);
        return;
}
/*for debugfs ---begin*/
static int clock_debug_rate_set(void *data, u64 val)
{
	struct clk *clock = data;
	int ret;

	/* Only increases to max rate will succeed, but that's actually good
	 * for debugging purposes so we don't check for error. */
		ret = clk_set_rate(clock, val);
	if (ret != 0)
		clk_printf("%s clk_set_rate %ld failed\n",clock->name, val);
	return ret;
}
int hi6930_clk_set_parent(struct clk *clk, struct clk *parent)
{
        struct clksel *clks = NULL;
        unsigned int clkid = 0;
        unsigned int regvalue = 0;
        clkid = clk->clkid;

        if (clk->parent == NULL){
                clk_printf("clock: %s parent is NULL,so can't set parent!!!\n", clk->name);
                return -1;
         }
         /*the future parent is its current parent,oprate sucess*/
        if (!reg_message[clkid].sel_reg) {
                if (clk->parent == parent) {
                        return 0;
                }
                clk_printf("clock: %s has no multiparent!!!\n", clk->name);
                return -1;
        }

        /*search input parent from array*/
        clks = hi6930_getclksel_by_parent(clk, parent);
        if (!clks){
                clk_printf("parent: %s,is no the parent of %s!!!\n", parent->name, clk->name);
                return -1;
        }

        /* set the register's bit to get the clock source */
        if(!reg_message[clkid].sel_reg){
                clk_printf("clock: %s has no set parent register!!!\n", clk->name);
                return -1;
        }
        regvalue = readl(HI_SYSCRG_BASE_ADDR_VIRT + reg_message[clkid].sel_reg);
        regvalue &= (~(reg_message[clkid].sel << reg_message[clkid].sel_bit));
        regvalue |= ((unsigned int)clks->sel_val << reg_message[clkid].sel_bit);/* [false alarm]:误报 */
        writel(regvalue, HI_SYSCRG_BASE_ADDR_VIRT + reg_message[clkid].sel_reg);
        clk->parent = parent;
        clk->rate = parent->rate;
        return 0;
}
int clk_disable_test_case0(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_clk");
    int ret = 0;
    clk_disable(sio_clk);
    if (reg_message[sio_clk->clkid].enable_flag){
                ret = sio_clk->ops->isenable(sio_clk);
    }
    if(ret){
            clk_printf("can't disable sio_clk\n");
            return CLK_TEST_ERROR;
    }
    return CLK_TEST_OK;
}
int clk_set_parent_test_case1(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_outer_clk");
    struct clk *peripll_fout4 = clk_get(NULL, "reverse_sio_clk");
    struct clk *tcxo = clk_get(NULL, "sio_clk");
    int ret = 0;
    ret = clk_set_parent(sio_clk, peripll_fout4);
    if (ret){
            clk_printf("sio_clk set parent reverse_sio_clk,failure\n");
            return CLK_TEST_ERROR;
    }
   clk_set_parent(sio_clk, tcxo);
    return CLK_TEST_OK;
}
void hi6930_clk_disable (struct clk *clk)
{
        unsigned int clkid = 0;
        unsigned int clkcon = 0;
        clkid = clk->clkid;

        /*disable clk*/
        if (!reg_message[clkid].enable_flag){
                clk_printf("clock: %s has no disable register!!!\n", clk->name);
                return;
        }
        clkcon = ((unsigned int)0x1 << reg_message[clkid].enable_bit);/* [false alarm]:误报 */
        writel(clkcon, HI_SYSCRG_BASE_ADDR_VIRT + 0x4 + reg_message[clkid].enable_reg);
         return;
}
void clock_debug(void)
{
      int i = 0;
      unsigned int clkid = 0;

      unsigned int status_value = 0;
	struct clk_lookup *cl_lookups = &hi6930_clk_lookup[0];
	struct clk *clk = NULL;
       clk_printf ("name            rate           refcnt          status           enable reg        bit\n");
	while((cl_lookups[i].clk != NULL) ) {
		clk = cl_lookups[i].clk;
		clkid = clk->clkid;
             if (reg_message[clkid].enable_flag){
                 status_value = (unsigned int)clk->ops->isenable(clk);
                 clk_printf("%-15s %-15ld %-15d %-15x 0x%-15x %-15d\n",clk->name,clk->rate,clk->refcnt,status_value,reg_message[clkid].enable_reg,reg_message[clkid].enable_bit);
              }
             else{
                 status_value = 0;
                 clk_printf("%-15s %-15ld %-15d %-15d 0x%-15x %-15d\n",clk->name,clk->rate,clk->refcnt,status_value,reg_message[clkid].enable_reg,reg_message[clkid].enable_bit);
             }
		i++;
	}
      return;
}
int hi6930_clk_isenable(struct clk *clk)
{
        unsigned int clkid = 0;
        unsigned int clkcon = 0;
        clkid = clk->clkid;
        if (reg_message[clkid].enable_flag){
            clkcon = readl(HI_SYSCRG_BASE_ADDR_VIRT + 0x8 + reg_message[clkid].enable_reg);
            if (clkcon &((unsigned int)(0x1) << reg_message[clkid].enable_bit)) {
                return 1;
            }
            else{
                return 0;
            }
        }
        clk_printf("clock: %s has no status register!!!\n", clk->name);
        return -1;
}
int hi6930_clk_enable (struct clk *clk)
{
       /*lint -e550*/
        unsigned int clkid = 0;
        unsigned int clkcon = 0;
        clkid = clk->clkid;

        /*enable clk*/
        if (!reg_message[clkid].enable_flag){
                clk_printf("clock: %s has no enable register!!!\n", clk->name);
                return 0;
        }
        if (clk->ops->isenable(clk) == 1){
                return 0;
        }
        clkcon = ((unsigned int)0x1 << reg_message[clkid].enable_bit);/* [false alarm]:误报 */
        writel(clkcon, HI_SYSCRG_BASE_ADDR_VIRT + reg_message[clkid].enable_reg);
         return 0;
}
void debug_clock(void)
{
	  struct clk *clk = NULL;
         struct clk_lookup *cl_lookups = &hi6930_clk_lookup[0];
         int i = 0;
	  while((cl_lookups[i].clk != NULL) ) {
		clk = cl_lookups[i].clk;
		clk_printf("clk_name:%-20s num: %-15d\n", clk->name, i);
		i++;
	  }
        clk_printf("enable:          void debug_clk_enable(unsigned int num)\n");
        clk_printf("disable:         void debug_clk_disable(unsigned int num)\n");
        clk_printf("check status:    void debug_clk_status(unsigned int num)\n");
        clk_printf("set rate :       void debug_clk_set_rate(unsigned int num, unsigned long rate)\n");
	 clk_printf("get rate :       void debug_clk_get_rate(unsigned int num)\n");
        clk_printf("set parent :     void debug_clk_set_parent(unsigned int num, unsigned int parent_num)\n");
        return;
}
int clk_enable_test_case1(void)
{
    struct clk *sio_clk = clk_get(NULL,"sio_clk");
	
    struct clk *apb_pclk = clk_get(NULL,"apb_pclk");
    int ret = 0;
    ret =  clk_enable(sio_clk);
    if(ret){
            clk_printf("can't enable sio_clk\n");
            return CLK_TEST_ERROR;
    }
	ret =  clk_enable(apb_pclk);
	clk_disable(apb_pclk);
	ret |= clk_round_rate(apb_pclk,100);
	ret |= clk_set_rate(apb_pclk,100);
	ret |= clk_set_parent(apb_pclk,sio_clk);
	ret |= clk_status(apb_pclk);

	debug_clock();
	debug_clk_enable(30);
	debug_clk_disable(30);
	debug_clk_set_rate(30,100);
	debug_clk_get_rate(30);
	debug_clk_set_parent(30,31);
	debug_clk_status(30);
	
	debug_clk_enable(14);
	debug_clk_disable(14);
	debug_clk_set_rate(14,100);
	debug_clk_get_rate(14);
	debug_clk_set_parent(14,15);
	debug_clk_status(14);
	if(ret)
		return CLK_TEST_OK;
    return CLK_TEST_OK;
}