From e29b72f5e129b4dd4b77dc01dba340006bb103f8 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:55:57 +0200 Subject: MIPS: Lantiq: Fix interface clock and PCI control register offset The XRX200 based SoC have a different register offset for the interface clock and PCI control registers. This patch detects the SoC and sets the register offset at runtime. This make PCI work on the VR9 SoC. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4113/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 83780f7..befbb76 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -20,10 +20,12 @@ /* clock control register */ #define CGU_IFCCR 0x0018 +#define CGU_IFCCR_VR9 0x0024 /* system clock register */ #define CGU_SYS 0x0010 /* pci control register */ #define CGU_PCICR 0x0034 +#define CGU_PCICR_VR9 0x0038 /* ephy configuration register */ #define CGU_EPHY 0x10 /* power control register */ @@ -80,6 +82,9 @@ static void __iomem *pmu_membase; void __iomem *ltq_cgu_membase; void __iomem *ltq_ebu_membase; +static u32 ifccr = CGU_IFCCR; +static u32 pcicr = CGU_PCICR; + /* legacy function kept alive to ease clkdev transition */ void ltq_pmu_enable(unsigned int module) { @@ -103,14 +108,14 @@ EXPORT_SYMBOL(ltq_pmu_disable); /* enable a hw clock */ static int cgu_enable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) | clk->bits, ifccr); return 0; } /* disable a hw clock */ static void cgu_disable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) & ~clk->bits, ifccr); } /* enable a clock gate */ @@ -138,22 +143,22 @@ static void pmu_disable(struct clk *clk) /* the pci enable helper */ static int pci_enable(struct clk *clk) { - unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + unsigned int val = ltq_cgu_r32(ifccr); /* set bus clock speed */ if (of_machine_is_compatible("lantiq,ar9")) { - ifccr &= ~0x1f00000; + val &= ~0x1f00000; if (clk->rate == CLOCK_33M) - ifccr |= 0xe00000; + val |= 0xe00000; else - ifccr |= 0x700000; /* 62.5M */ + val |= 0x700000; /* 62.5M */ } else { - ifccr &= ~0xf00000; + val &= ~0xf00000; if (clk->rate == CLOCK_33M) - ifccr |= 0x800000; + val |= 0x800000; else - ifccr |= 0x400000; /* 62.5M */ + val |= 0x400000; /* 62.5M */ } - ltq_cgu_w32(ifccr, CGU_IFCCR); + ltq_cgu_w32(val, ifccr); pmu_enable(clk); return 0; } @@ -161,18 +166,16 @@ static int pci_enable(struct clk *clk) /* enable the external clock as a source */ static int pci_ext_enable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16), - CGU_IFCCR); - ltq_cgu_w32((1 << 30), CGU_PCICR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) & ~(1 << 16), ifccr); + ltq_cgu_w32((1 << 30), pcicr); return 0; } /* disable the external clock as a source */ static void pci_ext_disable(struct clk *clk) { - ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16), - CGU_IFCCR); - ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR); + ltq_cgu_w32(ltq_cgu_r32(ifccr) | (1 << 16), ifccr); + ltq_cgu_w32((1 << 31) | (1 << 30), pcicr); } /* enable a clockout source */ @@ -184,11 +187,11 @@ static int clkout_enable(struct clk *clk) for (i = 0; i < 4; i++) { if (clk->rates[i] == clk->rate) { int shift = 14 - (2 * clk->module); - unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + unsigned int val = ltq_cgu_r32(ifccr); - ifccr &= ~(3 << shift); - ifccr |= i << shift; - ltq_cgu_w32(ifccr, CGU_IFCCR); + val &= ~(3 << shift); + val |= i << shift; + ltq_cgu_w32(val, ifccr); return 0; } } @@ -336,8 +339,12 @@ void __init ltq_soc_init(void) clkdev_add_clkout(); /* add the soc dependent clocks */ - if (!of_machine_is_compatible("lantiq,vr9")) + if (of_machine_is_compatible("lantiq,vr9")) { + ifccr = CGU_IFCCR_VR9; + pcicr = CGU_PCICR_VR9; + } else { clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE); + } if (!of_machine_is_compatible("lantiq,ase")) { clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1); -- cgit v0.10.2 From a9188bc1628366bea7157209df93acc0f74625cc Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:56:00 +0200 Subject: MIPS: Lantiq: Add device_tree_init function Add a lantiq specific version of device_tree_init. The generic MIPS version was removed by. commit 594e966bc412d64eec9282d28ce511bdd62fea39 Author: David Daney Date: Thu Jul 5 18:12:38 2012 +0200 MIPS: Prune some target specific code out of prom.c Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4116/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index d185e84..6cfd611 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -8,7 +8,10 @@ #include #include +#include #include +#include + #include #include @@ -70,6 +73,25 @@ void __init plat_mem_setup(void) __dt_setup_arch(&__dtb_start); } +void __init device_tree_init(void) +{ + unsigned long base, size; + + if (!initial_boot_params) + return; + + base = virt_to_phys((void *)initial_boot_params); + size = be32_to_cpu(initial_boot_params->totalsize); + + /* Before we do anything, lets reserve the dt blob */ + reserve_bootmem(base, size, BOOTMEM_DEFAULT); + + unflatten_device_tree(); + + /* free the space reserved for the dt blob */ + free_bootmem(base, size); +} + void __init prom_init(void) { /* call the soc specific detetcion code and get it to fill soc_info */ -- cgit v0.10.2 From b902d9a98e2bd0d3a2b7ddf7bca850b7f853569a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 22 Jul 2012 08:56:01 +0200 Subject: MIPS: Lantiq: Platform specific CLK fixup As we use CLKDEV_LOOKUP but dont have support for COMMON_CLK yet, we need to provide our own version of of_clk_get_from_provider(). Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/4117/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index d3bcc33..ce2f129 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -135,6 +135,11 @@ void clk_deactivate(struct clk *clk) } EXPORT_SYMBOL(clk_deactivate); +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +{ + return NULL; +} + static inline u32 get_counter_resolution(void) { u32 res; -- cgit v0.10.2 From 8551fb643ad6fe07f16d0825c8b6d99246024b9a Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:38:00 +0900 Subject: MIPS: AR7: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/ar7/clock.c:420:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/ar7/clock.c:426:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/ar7/clock.c:431:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/ar7/clock.c:437:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/ar7/clock.c:454:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[2]: *** [arch/mips/ar7/clock.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Acked-by: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/4140/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e3efc06..45fdad4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -77,6 +77,7 @@ config AR7 select SYS_SUPPORTS_ZBOOT_UART16550 select ARCH_REQUIRE_GPIOLIB select VLYNQ + select HAVE_CLK help Support for the Texas Instruments AR7 System-on-a-Chip family: TNETD7100, 7200 and 7300. -- cgit v0.10.2 From 3e82eeebad58a8bd9d263236ead0a0734e752792 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:39:52 +0900 Subject: MIPS: BCM63xx: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/bcm63xx/clk.c:249:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/bcm63xx/clk.c:259:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/bcm63xx/clk.c:268:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/bcm63xx/clk.c:275:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/bcm63xx/clk.c:302:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[2]: *** [arch/mips/bcm63xx/clk.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Patchwork: https://patchwork.linux-mips.org/patch/4141/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 45fdad4..331d574 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -125,6 +125,7 @@ config BCM63XX select SYS_HAS_EARLY_PRINTK select SWAP_IO_SPACE select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK help Support for BCM63XX based boards -- cgit v0.10.2 From 47cd7343f5467bf38d17a78eb99eaa8019e17007 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:41:06 +0900 Subject: MIPS: txx9: Fix redefinition of clk_* by adding select HAVE_CLK arch/mips/txx9/generic/setup.c:87:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/txx9/generic/setup.c:97:5: error: redefinition of 'clk_enable' include/linux/clk.h:295:19: note: previous definition of 'clk_enable' was here arch/mips/txx9/generic/setup.c:103:6: error: redefinition of 'clk_disable' include/linux/clk.h:300:20: note: previous definition of 'clk_disable' was here arch/mips/txx9/generic/setup.c:108:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here arch/mips/txx9/generic/setup.c:114:6: error: redefinition of 'clk_put' include/linux/clk.h:291:20: note: previous definition of 'clk_put' was here make[3]: *** [arch/mips/txx9/generic/setup.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Patchwork: https://patchwork.linux-mips.org/patch/4142/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig index 852ae4b..6d40bc7 100644 --- a/arch/mips/txx9/Kconfig +++ b/arch/mips/txx9/Kconfig @@ -20,6 +20,7 @@ config MACH_TXX9 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN + select HAVE_CLK config TOSHIBA_JMR3927 bool "Toshiba JMR-TX3927 board" -- cgit v0.10.2 From 4b00951f6f2fd335f063e553b474fe4648b3307d Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Wed, 1 Aug 2012 15:42:16 +0900 Subject: MIPS: Loongson 1: more clk support and add select HAVE_CLK This fixes a redefinition of clk_*: arch/mips/loongson1/common/clock.c:23:13: error: redefinition of 'clk_get' include/linux/clk.h:281:27: note: previous definition of 'clk_get' was here arch/mips/loongson1/common/clock.c:41:15: error: redefinition of 'clk_get_rate' include/linux/clk.h:302:29: note: previous definition of 'clk_get_rate' was here make[3]: *** [arch/mips/loongson1/common/clock.o] Error 1 Signed-off-by: Yoichi Yuasa Cc: linux-mips@linux-mips.org Reviewed-by: John Crispin Acked-by: Kelvin Cheung Patchwork: https://patchwork.linux-mips.org/patch/4143/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig index 237fa21..a9a14d6 100644 --- a/arch/mips/loongson1/Kconfig +++ b/arch/mips/loongson1/Kconfig @@ -15,6 +15,7 @@ config LOONGSON1_LS1B select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_HAS_EARLY_PRINTK + select HAVE_CLK endchoice diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c index 2d98fb0..1bbbbec 100644 --- a/arch/mips/loongson1/common/clock.c +++ b/arch/mips/loongson1/common/clock.c @@ -38,12 +38,28 @@ struct clk *clk_get(struct device *dev, const char *name) } EXPORT_SYMBOL(clk_get); +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); +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + static void pll_clk_init(struct clk *clk) { u32 pll; -- cgit v0.10.2 From 95cf1468f712df516cc471adcd1c861df4e3d371 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 1 Aug 2012 17:15:32 +0200 Subject: MIPS: Loongson 2: Sort out clock managment. For unexplainable reasons the Loongson 2 clock API was implemented in a module so fixing this involved shifting large amounts of code around. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h index 83894aa..c9456e7 100644 --- a/arch/mips/include/asm/clock.h +++ b/arch/mips/include/asm/clock.h @@ -50,15 +50,4 @@ void clk_recalc_rate(struct clk *); int clk_register(struct clk *); void clk_unregister(struct clk *); -/* the exported API, in addition to clk_set_rate */ -/** - * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter - * @clk: clock source - * @rate: desired clock rate in Hz - * @algo_id: algorithm id to be passed down to ops->set_rate - * - * Returns success (0) or negative errno. - */ -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); - #endif /* __ASM_MIPS_CLOCK_H */ diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 06367c3..5222a00 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -245,7 +245,6 @@ static inline void do_perfcnt_IRQ(void) #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ #include -extern void loongson2_cpu_wait(void); extern struct cpufreq_frequency_table loongson2_clockmod_table[]; /* Chip Config */ diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile index c3479a43..05a5715 100644 --- a/arch/mips/kernel/cpufreq/Makefile +++ b/arch/mips/kernel/cpufreq/Makefile @@ -2,4 +2,4 @@ # Makefile for the Linux/MIPS cpufreq. # -obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o +obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c deleted file mode 100644 index 5426779..0000000 --- a/arch/mips/kernel/cpufreq/loongson2_clock.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology - * Author: Yanhua, yanh@lemote.com - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include - -#include - -#include - -static LIST_HEAD(clock_list); -static DEFINE_SPINLOCK(clock_lock); -static DEFINE_MUTEX(clock_list_sem); - -/* Minimum CLK support */ -enum { - DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT, - DC_87PT, DC_DISABLE, DC_RESV -}; - -struct cpufreq_frequency_table loongson2_clockmod_table[] = { - {DC_RESV, CPUFREQ_ENTRY_INVALID}, - {DC_ZERO, CPUFREQ_ENTRY_INVALID}, - {DC_25PT, 0}, - {DC_37PT, 0}, - {DC_50PT, 0}, - {DC_62PT, 0}, - {DC_75PT, 0}, - {DC_87PT, 0}, - {DC_DISABLE, 0}, - {DC_RESV, CPUFREQ_TABLE_END}, -}; -EXPORT_SYMBOL_GPL(loongson2_clockmod_table); - -static struct clk cpu_clk = { - .name = "cpu_clk", - .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, - .rate = 800000000, -}; - -struct clk *clk_get(struct device *dev, const char *id) -{ - return &cpu_clk; -} -EXPORT_SYMBOL(clk_get); - -static void propagate_rate(struct clk *clk) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->parent != clk)) - continue; - if (likely(clkp->ops && clkp->ops->recalc)) - clkp->ops->recalc(clkp); - if (unlikely(clkp->flags & CLK_RATE_PROPAGATES)) - propagate_rate(clkp); - } -} - -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 (unsigned long)clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return clk_set_rate_ex(clk, rate, 0); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) -{ - int ret = 0; - int regval; - int i; - - if (likely(clk->ops && clk->ops->set_rate)) { - unsigned long flags; - - spin_lock_irqsave(&clock_lock, flags); - ret = clk->ops->set_rate(clk, rate, algo_id); - spin_unlock_irqrestore(&clock_lock, flags); - } - - if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) - propagate_rate(clk); - - for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END; - i++) { - if (loongson2_clockmod_table[i].frequency == - CPUFREQ_ENTRY_INVALID) - continue; - if (rate == loongson2_clockmod_table[i].frequency) - break; - } - if (rate != loongson2_clockmod_table[i].frequency) - return -ENOTSUPP; - - clk->rate = rate; - - regval = LOONGSON_CHIPCFG0; - regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1); - LOONGSON_CHIPCFG0 = regval; - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate_ex); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (likely(clk->ops && clk->ops->round_rate)) { - unsigned long flags, rounded; - - spin_lock_irqsave(&clock_lock, flags); - rounded = clk->ops->round_rate(clk, rate); - spin_unlock_irqrestore(&clock_lock, flags); - - return rounded; - } - - return rate; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -/* - * This is the simple version of Loongson-2 wait, Maybe we need do this in - * interrupt disabled content - */ - -DEFINE_SPINLOCK(loongson2_wait_lock); -void loongson2_cpu_wait(void) -{ - u32 cpu_freq; - unsigned long flags; - - spin_lock_irqsave(&loongson2_wait_lock, flags); - cpu_freq = LOONGSON_CHIPCFG0; - LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ - LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ - spin_unlock_irqrestore(&loongson2_wait_lock, flags); -} -EXPORT_SYMBOL_GPL(loongson2_cpu_wait); - -MODULE_AUTHOR("Yanhua "); -MODULE_DESCRIPTION("cpufreq driver for Loongson 2F"); -MODULE_LICENSE("GPL"); diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c index ae5db20..e7c98e2 100644 --- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c +++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c @@ -19,7 +19,7 @@ #include -#include +#include static uint nowait; @@ -181,6 +181,25 @@ static struct platform_driver platform_driver = { .id_table = platform_device_ids, }; +/* + * This is the simple version of Loongson-2 wait, Maybe we need do this in + * interrupt disabled context. + */ + +static DEFINE_SPINLOCK(loongson2_wait_lock); + +static void loongson2_cpu_wait(void) +{ + unsigned long flags; + u32 cpu_freq; + + spin_lock_irqsave(&loongson2_wait_lock, flags); + cpu_freq = LOONGSON_CHIPCFG0; + LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ + LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ + spin_unlock_irqrestore(&loongson2_wait_lock, flags); +} + static int __init cpufreq_init(void) { int ret; diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index aca93ee..263beb9 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -41,6 +41,7 @@ config LEMOTE_MACH2F select CSRC_R4K if ! MIPS_EXTERNAL_TIMER select DMA_NONCOHERENT select GENERIC_ISA_DMA_SUPPORT_BROKEN + select HAVE_CLK select HW_HAS_PCI select I8259 select IRQ_CPU diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index 8699a53..4f9eaa3 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -2,7 +2,7 @@ # Makefile for lemote loongson2f family machines # -obj-y += machtype.o irq.o reset.o ec_kb3310b.o +obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o # # Suspend Support diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c new file mode 100644 index 0000000..bc739d4 --- /dev/null +++ b/arch/mips/loongson/lemote-2f/clock.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Author: Yanhua, yanh@lemote.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DEFINE_MUTEX(clock_list_sem); + +/* Minimum CLK support */ +enum { + DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT, + DC_87PT, DC_DISABLE, DC_RESV +}; + +struct cpufreq_frequency_table loongson2_clockmod_table[] = { + {DC_RESV, CPUFREQ_ENTRY_INVALID}, + {DC_ZERO, CPUFREQ_ENTRY_INVALID}, + {DC_25PT, 0}, + {DC_37PT, 0}, + {DC_50PT, 0}, + {DC_62PT, 0}, + {DC_75PT, 0}, + {DC_87PT, 0}, + {DC_DISABLE, 0}, + {DC_RESV, CPUFREQ_TABLE_END}, +}; +EXPORT_SYMBOL_GPL(loongson2_clockmod_table); + +static struct clk cpu_clk = { + .name = "cpu_clk", + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, + .rate = 800000000, +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + return &cpu_clk; +} +EXPORT_SYMBOL(clk_get); + +static void propagate_rate(struct clk *clk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->parent != clk)) + continue; + if (likely(clkp->ops && clkp->ops->recalc)) + clkp->ops->recalc(clkp); + if (unlikely(clkp->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clkp); + } +} + +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 (unsigned long)clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + int regval; + int i; + + if (likely(clk->ops && clk->ops->set_rate)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_rate(clk, rate, 0); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + + for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END; + i++) { + if (loongson2_clockmod_table[i].frequency == + CPUFREQ_ENTRY_INVALID) + continue; + if (rate == loongson2_clockmod_table[i].frequency) + break; + } + if (rate != loongson2_clockmod_table[i].frequency) + return -ENOTSUPP; + + clk->rate = rate; + + regval = LOONGSON_CHIPCFG0; + regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1); + LOONGSON_CHIPCFG0 = regval; + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (likely(clk->ops && clk->ops->round_rate)) { + unsigned long flags, rounded; + + spin_lock_irqsave(&clock_lock, flags); + rounded = clk->ops->round_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + + return rounded; + } + + return rate; +} +EXPORT_SYMBOL_GPL(clk_round_rate); -- cgit v0.10.2