diff options
Diffstat (limited to 'arch/mips/ar7/clock.c')
| -rw-r--r-- | arch/mips/ar7/clock.c | 109 | 
1 files changed, 80 insertions, 29 deletions
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index cc65c8eb391..fc0e7154e8d 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -1,6 +1,7 @@  /*   * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>   * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org> + * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -24,6 +25,8 @@  #include <linux/delay.h>  #include <linux/gcd.h>  #include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h>  #include <asm/addrspace.h>  #include <asm/mach-ar7/ar7.h> @@ -94,12 +97,16 @@ struct tnetd7200_clocks {  	struct tnetd7200_clock usb;  }; -int ar7_cpu_clock = 150000000; -EXPORT_SYMBOL(ar7_cpu_clock); -int ar7_bus_clock = 125000000; -EXPORT_SYMBOL(ar7_bus_clock); -int ar7_dsp_clock; -EXPORT_SYMBOL(ar7_dsp_clock); +static struct clk bus_clk = { +	.rate	= 125000000, +}; + +static struct clk cpu_clk = { +	.rate	= 150000000, +}; + +static struct clk dsp_clk; +static struct clk vbus_clk;  static void approximate(int base, int target, int *prediv,  			int *postdiv, int *mul) @@ -185,7 +192,7 @@ static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,  		base_clock = AR7_XTAL_CLOCK;  		break;  	case BOOT_PLL_SOURCE_CPU: -		base_clock = ar7_cpu_clock; +		base_clock = cpu_clk.rate;  		break;  	} @@ -212,11 +219,11 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,  	u32 *bootcr, u32 frequency)  {  	int prediv, postdiv, mul; -	int base_clock = ar7_bus_clock; +	int base_clock = bus_clk.rate;  	switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {  	case BOOT_PLL_SOURCE_BUS: -		base_clock = ar7_bus_clock; +		base_clock = bus_clk.rate;  		break;  	case BOOT_PLL_SOURCE_REF:  		base_clock = AR7_REF_CLOCK; @@ -225,7 +232,7 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,  		base_clock = AR7_XTAL_CLOCK;  		break;  	case BOOT_PLL_SOURCE_CPU: -		base_clock = ar7_cpu_clock; +		base_clock = cpu_clk.rate;  		break;  	} @@ -247,18 +254,18 @@ static void __init tnetd7300_init_clocks(void)  					ioremap_nocache(UR8_REGS_CLOCKS,  					sizeof(struct tnetd7300_clocks)); -	ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, +	bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,  		&clocks->bus, bootcr, AR7_AFE_CLOCK);  	if (*bootcr & BOOT_PLL_ASYNC_MODE) -		ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT, +		cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,  			&clocks->cpu, bootcr, AR7_AFE_CLOCK);  	else -		ar7_cpu_clock = ar7_bus_clock; +		cpu_clk.rate = bus_clk.rate; -	if (ar7_dsp_clock == 250000000) +	if (dsp_clk.rate == 250000000)  		tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, -			bootcr, ar7_dsp_clock); +			bootcr, dsp_clk.rate);  	iounmap(clocks);  	iounmap(bootcr); @@ -343,20 +350,20 @@ static void __init tnetd7200_init_clocks(void)  		printk(KERN_INFO "Clocks: Setting DSP clock\n");  		calculate(dsp_base, TNETD7200_DEF_DSP_CLK,  			&dsp_prediv, &dsp_postdiv, &dsp_mul); -		ar7_bus_clock = +		bus_clk.rate =  			((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;  		tnetd7200_set_clock(dsp_base, &clocks->dsp,  			dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2, -			ar7_bus_clock); +			bus_clk.rate);  		printk(KERN_INFO "Clocks: Setting CPU clock\n");  		calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,  			&cpu_postdiv, &cpu_mul); -		ar7_cpu_clock = +		cpu_clk.rate =  			((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;  		tnetd7200_set_clock(cpu_base, &clocks->cpu,  			cpu_prediv, cpu_postdiv, -1, cpu_mul, -			ar7_cpu_clock); +			cpu_clk.rate);  	} else  		if (*bootcr & BOOT_PLL_2TO1_MODE) { @@ -365,48 +372,90 @@ static void __init tnetd7200_init_clocks(void)  			printk(KERN_INFO "Clocks: Setting CPU clock\n");  			calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,  				&cpu_postdiv, &cpu_mul); -			ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul) +			cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)  								/ cpu_postdiv;  			tnetd7200_set_clock(cpu_base, &clocks->cpu,  				cpu_prediv, cpu_postdiv, -1, cpu_mul, -				ar7_cpu_clock); +				cpu_clk.rate);  			printk(KERN_INFO "Clocks: Setting DSP clock\n");  			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,  				&dsp_postdiv, &dsp_mul); -			ar7_bus_clock = ar7_cpu_clock / 2; +			bus_clk.rate = cpu_clk.rate / 2;  			tnetd7200_set_clock(dsp_base, &clocks->dsp,  				dsp_prediv, dsp_postdiv * 2, dsp_postdiv, -				dsp_mul * 2, ar7_bus_clock); +				dsp_mul * 2, bus_clk.rate);  		} else {  			printk(KERN_INFO "Clocks: Sync 1:1 mode\n");  			printk(KERN_INFO "Clocks: Setting DSP clock\n");  			calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,  				&dsp_postdiv, &dsp_mul); -			ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul) +			bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)  								/ dsp_postdiv;  			tnetd7200_set_clock(dsp_base, &clocks->dsp,  				dsp_prediv, dsp_postdiv * 2, dsp_postdiv, -				dsp_mul * 2, ar7_bus_clock); +				dsp_mul * 2, bus_clk.rate); -			ar7_cpu_clock = ar7_bus_clock; +			cpu_clk.rate = bus_clk.rate;  		}  	printk(KERN_INFO "Clocks: Setting USB clock\n"); -	usb_base = ar7_bus_clock; +	usb_base = bus_clk.rate;  	calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,  		&usb_postdiv, &usb_mul);  	tnetd7200_set_clock(usb_base, &clocks->usb,  		usb_prediv, usb_postdiv, -1, usb_mul,  		TNETD7200_DEF_USB_CLK); -	ar7_dsp_clock = ar7_cpu_clock; +	dsp_clk.rate = cpu_clk.rate;  	iounmap(clocks);  	iounmap(bootcr);  } +/* + * Linux clock API + */ +int clk_enable(struct clk *clk) +{ +	return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ +	return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +struct clk *clk_get(struct device *dev, const char *id) +{ +	if (!strcmp(id, "bus")) +		return &bus_clk; +	/* cpmac and vbus share the same rate */ +	if (!strcmp(id, "cpmac")) +		return &vbus_clk; +	if (!strcmp(id, "cpu")) +		return &cpu_clk; +	if (!strcmp(id, "dsp")); +		return &dsp_clk; +	if (!strcmp(id, "vbus")) +		return &vbus_clk; +	return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); +  int __init ar7_init_clocks(void)  {  	switch (ar7_chip_id()) { @@ -415,12 +464,14 @@ int __init ar7_init_clocks(void)  		tnetd7200_init_clocks();  		break;  	case AR7_CHIP_7300: -		ar7_dsp_clock = tnetd7300_dsp_clock(); +		dsp_clk.rate = tnetd7300_dsp_clock();  		tnetd7300_init_clocks();  		break;  	default:  		break;  	} +	/* adjust vbus clock rate */ +	vbus_clk.rate = bus_clk.rate / 2;  	return 0;  }  |