* [PATCH V2 01/12] MIPS: Loongson: Fix the write-combine CCA value setting
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:13 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1 Huacai Chen
` (7 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
All Loongson-2/3 processors support _CACHE_UNCACHED_ACCELERATED, not
only Loongson-3A.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/kernel/cpu-probe.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 25554f2..929e524 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -825,7 +825,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
break;
case PRID_REV_LOONGSON3A:
c->cputype = CPU_LOONGSON3;
- c->writecombine = _CACHE_UNCACHED_ACCELERATED;
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3a");
break;
@@ -842,6 +841,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_FPU | MIPS_CPU_LLSC |
MIPS_CPU_32FPR;
c->tlbsize = 64;
+ c->writecombine = _CACHE_UNCACHED_ACCELERATED;
break;
case PRID_IMP_LOONGSON_32: /* Loongson-1 */
decode_configs(c);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
2014-11-04 6:13 ` [PATCH V2 01/12] MIPS: Loongson: Fix the write-combine CCA value setting Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-10 16:59 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 03/12] MIPS: Loongson-3: Add PHYS48_TO_HT40 support Huacai Chen
` (6 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
In CPU manual Loongson-3 is MIPS64R2 compatible, but during tests we
found that its EI/DI instructions have problems. So we just set the ISA
level to MIPS64R1.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
.../asm/mach-loongson/cpu-feature-overrides.h | 2 --
arch/mips/kernel/cpu-probe.c | 5 ++++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
index 7d28f95..6d69332 100644
--- a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
@@ -41,10 +41,8 @@
#define cpu_has_mcheck 0
#define cpu_has_mdmx 0
#define cpu_has_mips16 0
-#define cpu_has_mips32r1 0
#define cpu_has_mips32r2 0
#define cpu_has_mips3d 0
-#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
#define cpu_has_mipsmt 0
#define cpu_has_prefetch 0
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 929e524..b27e7ff 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -817,26 +817,29 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->cputype = CPU_LOONGSON2;
__cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2e");
+ set_isa(c, MIPS_CPU_ISA_III);
break;
case PRID_REV_LOONGSON2F:
c->cputype = CPU_LOONGSON2;
__cpu_name[cpu] = "ICT Loongson-2";
set_elf_platform(cpu, "loongson2f");
+ set_isa(c, MIPS_CPU_ISA_III);
break;
case PRID_REV_LOONGSON3A:
c->cputype = CPU_LOONGSON3;
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3a");
+ set_isa(c, MIPS_CPU_ISA_M64R1);
break;
case PRID_REV_LOONGSON3B_R1:
case PRID_REV_LOONGSON3B_R2:
c->cputype = CPU_LOONGSON3;
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3b");
+ set_isa(c, MIPS_CPU_ISA_M64R1);
break;
}
- set_isa(c, MIPS_CPU_ISA_III);
c->options = R4K_OPTS |
MIPS_CPU_FPU | MIPS_CPU_LLSC |
MIPS_CPU_32FPR;
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1
2014-11-04 6:13 ` [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1 Huacai Chen
@ 2014-11-10 16:59 ` Ralf Baechle
2014-11-11 1:14 ` Huacai Chen
0 siblings, 1 reply; 22+ messages in thread
From: Ralf Baechle @ 2014-11-10 16:59 UTC (permalink / raw)
To: Huacai Chen
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu
On Tue, Nov 04, 2014 at 02:13:23PM +0800, Huacai Chen wrote:
> In CPU manual Loongson-3 is MIPS64R2 compatible, but during tests we
> found that its EI/DI instructions have problems. So we just set the ISA
> level to MIPS64R1.
That's a bit a heavyhanded move - it will disable ALL R2 optimizations
and feature support - try running git grep -w cpu_has_mips_r2 arch/mips.
Also it will cause the kernel to missreport the CPU has R1 or as in
case of the Loongson 2 with this patch even as MIPS III which in turn
will mean certain programs will fail to detect and exploit the full
capabilities of the CPU.
Was this really intended? I doubt it.
I suggest a bit of a less heavy-handed approach as illustrated in below
incomplete patch.
Would that work for you?
Ralf
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/asmmacro.h | 3 ++-
arch/mips/include/asm/irqflags.h | 7 ++++---
arch/mips/include/asm/mach-ip22/war.h | 1 +
arch/mips/include/asm/mach-loongson/war.h | 1 +
arch/mips/include/asm/war.h | 7 +++++++
5 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 6caf876..d477c34 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -11,6 +11,7 @@
#include <asm/hazards.h>
#include <asm/asm-offsets.h>
#include <asm/msa.h>
+#include <asm/war.h>
#ifdef CONFIG_32BIT
#include <asm/asmmacro-32.h>
@@ -19,7 +20,7 @@
#include <asm/asmmacro-64.h>
#endif
-#ifdef CONFIG_CPU_MIPSR2
+#if defined(CONFIG_CPU_MIPSR2) && !LOONGSON3_EI_DI_WAR
.macro local_irq_enable reg=t0
ei
irq_enable_hazard
diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
index 0fa5fdc..fcfd371 100644
--- a/arch/mips/include/asm/irqflags.h
+++ b/arch/mips/include/asm/irqflags.h
@@ -16,6 +16,7 @@
#include <linux/compiler.h>
#include <linux/stringify.h>
#include <asm/hazards.h>
+#include <asm/war.h>
#ifdef CONFIG_CPU_MIPSR2
@@ -59,7 +60,7 @@ static inline void arch_local_irq_restore(unsigned long flags)
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU) && !LOONGSON3_EI_DI_WAR
/*
* Slow, but doesn't suffer from a relatively unlikely race
* condition we're having since days 1.
@@ -89,7 +90,7 @@ static inline void __arch_local_irq_restore(unsigned long flags)
" .set push \n"
" .set noreorder \n"
" .set noat \n"
-#if defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU) && !LOONGSON3_EI_DI_WAR
/*
* Slow, but doesn't suffer from a relatively unlikely race
* condition we're having since days 1.
@@ -126,7 +127,7 @@ static inline void arch_local_irq_enable(void)
" .set push \n"
" .set reorder \n"
" .set noat \n"
-#if defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2) && !LOONGSON3_EI_DI_WAR
" ei \n"
#else
" mfc0 $1,$12 \n"
diff --git a/arch/mips/include/asm/mach-ip22/war.h b/arch/mips/include/asm/mach-ip22/war.h
index fba6405..3520b0a 100644
--- a/arch/mips/include/asm/mach-ip22/war.h
+++ b/arch/mips/include/asm/mach-ip22/war.h
@@ -18,6 +18,7 @@
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
+#define LOONGSON3_EI_DI_WAR 0
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
diff --git a/arch/mips/include/asm/mach-loongson/war.h b/arch/mips/include/asm/mach-loongson/war.h
index f2570df..cf5385f 100644
--- a/arch/mips/include/asm/mach-loongson/war.h
+++ b/arch/mips/include/asm/mach-loongson/war.h
@@ -14,6 +14,7 @@
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
+#define LOONGSON3_EI_DI_WAR 1
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
diff --git a/arch/mips/include/asm/war.h b/arch/mips/include/asm/war.h
index 9344e24..ceb9030 100644
--- a/arch/mips/include/asm/war.h
+++ b/arch/mips/include/asm/war.h
@@ -233,4 +233,11 @@
#error Check setting of MIPS34K_MISSED_ITLB_WAR for your platform
#endif
+/*
+ * On certain Loongson 3 cores DI/EI don't work properly.
+ */
+#ifndef LOONGSON3_EI_DI_WAR
+#error Check setting of LOONGSON3_EI_DI_WAR for your platform
+#endif
+
#endif /* _ASM_WAR_H */
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1
2014-11-10 16:59 ` Ralf Baechle
@ 2014-11-11 1:14 ` Huacai Chen
2014-11-11 9:33 ` Ralf Baechle
0 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-11 1:14 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, Linux MIPS Mailing List,
Fuxin Zhang, Zhangjin Wu
Hi, Ralf,
In original code, both Loongson-2 and Loongson-3 are MIPS-III, after
my patch, Loongson-2 is still MIPS-III and Loongson-3 is upgraded to
MIPS64R1, so I think this is not "heavyhanded". Moreover, we need more
tests to assure whether Loongson-3 is compatible with MIPS64R2 (except
EI/DI), so set to MIPS64R1 is a safe way.
Huacai
On Tue, Nov 11, 2014 at 12:59 AM, Ralf Baechle <ralf@linux-mips.org> wrote:
> On Tue, Nov 04, 2014 at 02:13:23PM +0800, Huacai Chen wrote:
>
>> In CPU manual Loongson-3 is MIPS64R2 compatible, but during tests we
>> found that its EI/DI instructions have problems. So we just set the ISA
>> level to MIPS64R1.
>
> That's a bit a heavyhanded move - it will disable ALL R2 optimizations
> and feature support - try running git grep -w cpu_has_mips_r2 arch/mips.
> Also it will cause the kernel to missreport the CPU has R1 or as in
> case of the Loongson 2 with this patch even as MIPS III which in turn
> will mean certain programs will fail to detect and exploit the full
> capabilities of the CPU.
>
> Was this really intended? I doubt it.
>
> I suggest a bit of a less heavy-handed approach as illustrated in below
> incomplete patch.
>
> Would that work for you?
>
> Ralf
>
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>
> arch/mips/include/asm/asmmacro.h | 3 ++-
> arch/mips/include/asm/irqflags.h | 7 ++++---
> arch/mips/include/asm/mach-ip22/war.h | 1 +
> arch/mips/include/asm/mach-loongson/war.h | 1 +
> arch/mips/include/asm/war.h | 7 +++++++
> 5 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
> index 6caf876..d477c34 100644
> --- a/arch/mips/include/asm/asmmacro.h
> +++ b/arch/mips/include/asm/asmmacro.h
> @@ -11,6 +11,7 @@
> #include <asm/hazards.h>
> #include <asm/asm-offsets.h>
> #include <asm/msa.h>
> +#include <asm/war.h>
>
> #ifdef CONFIG_32BIT
> #include <asm/asmmacro-32.h>
> @@ -19,7 +20,7 @@
> #include <asm/asmmacro-64.h>
> #endif
>
> -#ifdef CONFIG_CPU_MIPSR2
> +#if defined(CONFIG_CPU_MIPSR2) && !LOONGSON3_EI_DI_WAR
> .macro local_irq_enable reg=t0
> ei
> irq_enable_hazard
> diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h
> index 0fa5fdc..fcfd371 100644
> --- a/arch/mips/include/asm/irqflags.h
> +++ b/arch/mips/include/asm/irqflags.h
> @@ -16,6 +16,7 @@
> #include <linux/compiler.h>
> #include <linux/stringify.h>
> #include <asm/hazards.h>
> +#include <asm/war.h>
>
> #ifdef CONFIG_CPU_MIPSR2
>
> @@ -59,7 +60,7 @@ static inline void arch_local_irq_restore(unsigned long flags)
> " .set push \n"
> " .set noreorder \n"
> " .set noat \n"
> -#if defined(CONFIG_IRQ_CPU)
> +#if defined(CONFIG_IRQ_CPU) && !LOONGSON3_EI_DI_WAR
> /*
> * Slow, but doesn't suffer from a relatively unlikely race
> * condition we're having since days 1.
> @@ -89,7 +90,7 @@ static inline void __arch_local_irq_restore(unsigned long flags)
> " .set push \n"
> " .set noreorder \n"
> " .set noat \n"
> -#if defined(CONFIG_IRQ_CPU)
> +#if defined(CONFIG_IRQ_CPU) && !LOONGSON3_EI_DI_WAR
> /*
> * Slow, but doesn't suffer from a relatively unlikely race
> * condition we're having since days 1.
> @@ -126,7 +127,7 @@ static inline void arch_local_irq_enable(void)
> " .set push \n"
> " .set reorder \n"
> " .set noat \n"
> -#if defined(CONFIG_CPU_MIPSR2)
> +#if defined(CONFIG_CPU_MIPSR2) && !LOONGSON3_EI_DI_WAR
> " ei \n"
> #else
> " mfc0 $1,$12 \n"
> diff --git a/arch/mips/include/asm/mach-ip22/war.h b/arch/mips/include/asm/mach-ip22/war.h
> index fba6405..3520b0a 100644
> --- a/arch/mips/include/asm/mach-ip22/war.h
> +++ b/arch/mips/include/asm/mach-ip22/war.h
> @@ -18,6 +18,7 @@
> #define R5432_CP0_INTERRUPT_WAR 0
> #define BCM1250_M3_WAR 0
> #define SIBYTE_1956_WAR 0
> +#define LOONGSON3_EI_DI_WAR 0
> #define MIPS4K_ICACHE_REFILL_WAR 0
> #define MIPS_CACHE_SYNC_WAR 0
> #define TX49XX_ICACHE_INDEX_INV_WAR 0
> diff --git a/arch/mips/include/asm/mach-loongson/war.h b/arch/mips/include/asm/mach-loongson/war.h
> index f2570df..cf5385f 100644
> --- a/arch/mips/include/asm/mach-loongson/war.h
> +++ b/arch/mips/include/asm/mach-loongson/war.h
> @@ -14,6 +14,7 @@
> #define R5432_CP0_INTERRUPT_WAR 0
> #define BCM1250_M3_WAR 0
> #define SIBYTE_1956_WAR 0
> +#define LOONGSON3_EI_DI_WAR 1
> #define MIPS4K_ICACHE_REFILL_WAR 0
> #define MIPS_CACHE_SYNC_WAR 0
> #define TX49XX_ICACHE_INDEX_INV_WAR 0
> diff --git a/arch/mips/include/asm/war.h b/arch/mips/include/asm/war.h
> index 9344e24..ceb9030 100644
> --- a/arch/mips/include/asm/war.h
> +++ b/arch/mips/include/asm/war.h
> @@ -233,4 +233,11 @@
> #error Check setting of MIPS34K_MISSED_ITLB_WAR for your platform
> #endif
>
> +/*
> + * On certain Loongson 3 cores DI/EI don't work properly.
> + */
> +#ifndef LOONGSON3_EI_DI_WAR
> +#error Check setting of LOONGSON3_EI_DI_WAR for your platform
> +#endif
> +
> #endif /* _ASM_WAR_H */
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1
2014-11-11 1:14 ` Huacai Chen
@ 2014-11-11 9:33 ` Ralf Baechle
0 siblings, 0 replies; 22+ messages in thread
From: Ralf Baechle @ 2014-11-11 9:33 UTC (permalink / raw)
To: Huacai Chen
Cc: John Crispin, Steven J. Hill, Linux MIPS Mailing List,
Fuxin Zhang, Zhangjin Wu
On Tue, Nov 11, 2014 at 09:14:48AM +0800, Huacai Chen wrote:
> In original code, both Loongson-2 and Loongson-3 are MIPS-III, after
> my patch, Loongson-2 is still MIPS-III and Loongson-3 is upgraded to
> MIPS64R1, so I think this is not "heavyhanded". Moreover, we need more
> tests to assure whether Loongson-3 is compatible with MIPS64R2 (except
> EI/DI), so set to MIPS64R1 is a safe way.
I see, I applied your patch. However the cpu-probe.c part did reject
and I had to apply it manually so you may want to doublecheck the result
which I'm about to push to upstream-sfr.
Thanks!
Ralf
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH V2 03/12] MIPS: Loongson-3: Add PHYS48_TO_HT40 support
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
2014-11-04 6:13 ` [PATCH V2 01/12] MIPS: Loongson: Fix the write-combine CCA value setting Huacai Chen
2014-11-04 6:13 ` [PATCH V2 02/12] MIPS: Loongson: set Loongson-3's ISA level to MIPS64R1 Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:15 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 04/12] MIPS: Loongson: Introduce and use cpu_has_coherent_cache feature Huacai Chen
` (5 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
The width of HT-bus is only 40-bit, but Loongson-3 has 48-bit physical
address. This implies only node-0's memory is DMAable because high bits
(Node ID) will lost. Fortunately, by configuring address windows in
firmware, we can extract 2bit Node ID (bit 44~47, only bit 44~45 used
now) from Loongson-3's 48-bit address space and embed it into 40-bit
(bit 37~38). Every NUMA node can do DMA now (however, maximum memory of
each node is reduced to 2^37 = 128GB).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
.../mips/include/asm/mach-loongson/dma-coherence.h | 6 +++---
arch/mips/loongson/Kconfig | 5 +++++
arch/mips/loongson/common/dma-swiotlb.c | 14 ++++++++++++++
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 6a90275..a905341 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -23,7 +23,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
#ifdef CONFIG_CPU_LOONGSON3
- return virt_to_phys(addr);
+ return phys_to_dma(dev, virt_to_phys(addr));
#else
return virt_to_phys(addr) | 0x80000000;
#endif
@@ -33,7 +33,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
struct page *page)
{
#ifdef CONFIG_CPU_LOONGSON3
- return page_to_phys(page);
+ return phys_to_dma(dev, page_to_phys(page));
#else
return page_to_phys(page) | 0x80000000;
#endif
@@ -43,7 +43,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
- return dma_addr;
+ return dma_to_phys(dev, dma_addr);
#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
#else
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 1b91fc6..72f830ac 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -86,6 +86,7 @@ config LOONGSON_MACH3X
select LOONGSON_MC146818
select ZONE_DMA32
select LEFI_FIRMWARE_INTERFACE
+ select PHYS48_TO_HT40
help
Generic Loongson 3 family machines utilize the 3A/3B revision
of Loongson processor and RS780/SBX00 chipset.
@@ -131,6 +132,10 @@ config SWIOTLB
select NEED_SG_DMA_LENGTH
select NEED_DMA_MAP_STATE
+config PHYS48_TO_HT40
+ bool
+ default y if CPU_LOONGSON3
+
config LOONGSON_MC146818
bool
default n
diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
index c2be01f..2c6b989 100644
--- a/arch/mips/loongson/common/dma-swiotlb.c
+++ b/arch/mips/loongson/common/dma-swiotlb.c
@@ -105,11 +105,25 @@ static int loongson_dma_set_mask(struct device *dev, u64 mask)
dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
+ long nid;
+#ifdef CONFIG_PHYS48_TO_HT40
+ /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
+ * Loongson-3's 48bit address space and embed it into 40bit */
+ nid = (paddr >> 44) & 0x3;
+ paddr = ((nid << 44) ^ paddr) | (nid << 37);
+#endif
return paddr;
}
phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
{
+ long nid;
+#ifdef CONFIG_PHYS48_TO_HT40
+ /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from
+ * Loongson-3's 48bit address space and embed it into 40bit */
+ nid = (daddr >> 37) & 0x3;
+ daddr = ((nid << 37) ^ daddr) | (nid << 44);
+#endif
return daddr;
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH V2 04/12] MIPS: Loongson: Introduce and use cpu_has_coherent_cache feature
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (2 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 03/12] MIPS: Loongson-3: Add PHYS48_TO_HT40 support Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:05 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 05/12] MIPS: Loongson: Allow booting from any core Huacai Chen
` (4 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen, Hongliang Tao
Loongson-3 maintains cache coherency by hardware. So we introduce a cpu
feature named cpu_has_coherent_cache and use it to modify MIPS's cache
flushing functions.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
---
arch/mips/Kconfig | 3 +++
arch/mips/include/asm/cpu-features.h | 3 +++
.../asm/mach-loongson/cpu-feature-overrides.h | 1 +
arch/mips/mm/c-r4k.c | 18 ++++++++++++++++++
4 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e0b7c20..b3dc152 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1596,6 +1596,7 @@ config CPU_BMIPS5000
config SYS_HAS_CPU_LOONGSON3
bool
select CPU_SUPPORTS_CPUFREQ
+ select CPU_SUPPORTS_COHERENT_CACHE
config SYS_HAS_CPU_LOONGSON2E
bool
@@ -1759,6 +1760,8 @@ config CPU_SUPPORTS_HUGEPAGES
bool
config CPU_SUPPORTS_UNCACHED_ACCELERATED
bool
+config CPU_SUPPORTS_COHERENT_CACHE
+ bool
config MIPS_PGD_C0_CONTEXT
bool
default y if 64BIT && CPU_MIPSR2 && !CPU_XLP
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 3325f3e..0e85d60 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -148,6 +148,9 @@
#ifndef cpu_has_pindexed_dcache
#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
#endif
+#ifndef cpu_has_coherent_cache
+#define cpu_has_coherent_cache 0
+#endif
#ifndef cpu_has_local_ebase
#define cpu_has_local_ebase 1
#endif
diff --git a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
index 6d69332..7efb191 100644
--- a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
@@ -58,5 +58,6 @@
#define cpu_has_local_ebase 0
#define cpu_has_wsbh IS_ENABLED(CONFIG_CPU_LOONGSON3)
+#define cpu_has_coherent_cache IS_ENABLED(CONFIG_CPU_SUPPORTS_COHERENT_CACHE)
#endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index fbcd867..68b3c3d 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -420,6 +420,9 @@ static void r4k_blast_scache_setup(void)
static inline void local_r4k___flush_cache_all(void * args)
{
+ if (cpu_has_coherent_cache)
+ return;
+
switch (current_cpu_type()) {
case CPU_LOONGSON2:
case CPU_LOONGSON3:
@@ -480,6 +483,9 @@ static inline void local_r4k_flush_cache_range(void * args)
struct vm_area_struct *vma = args;
int exec = vma->vm_flags & VM_EXEC;
+ if (cpu_has_coherent_cache)
+ return;
+
if (!(has_valid_asid(vma->vm_mm)))
return;
@@ -550,6 +556,9 @@ static inline void local_r4k_flush_cache_page(void *args)
pte_t *ptep;
void *vaddr;
+ if (cpu_has_coherent_cache)
+ return;
+
/*
* If ownes no valid ASID yet, cannot possibly have gotten
* this page into the cache.
@@ -625,11 +634,17 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
static inline void local_r4k_flush_data_cache_page(void * addr)
{
+ if (cpu_has_coherent_cache)
+ return;
+
r4k_blast_dcache_page((unsigned long) addr);
}
static void r4k_flush_data_cache_page(unsigned long addr)
{
+ if (cpu_has_coherent_cache)
+ return;
+
if (in_atomic())
local_r4k_flush_data_cache_page((void *)addr);
else
@@ -783,6 +798,9 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
unsigned long sc_lsize = cpu_scache_line_size();
unsigned long addr = (unsigned long) arg;
+ if (cpu_has_coherent_cache)
+ return;
+
R4600_HIT_CACHEOP_WAR_IMPL;
if (dc_lsize)
protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH V2 04/12] MIPS: Loongson: Introduce and use cpu_has_coherent_cache feature
2014-11-04 6:13 ` [PATCH V2 04/12] MIPS: Loongson: Introduce and use cpu_has_coherent_cache feature Huacai Chen
@ 2014-11-11 10:05 ` Ralf Baechle
0 siblings, 0 replies; 22+ messages in thread
From: Ralf Baechle @ 2014-11-11 10:05 UTC (permalink / raw)
To: Huacai Chen
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Hongliang Tao
On Tue, Nov 04, 2014 at 02:13:25PM +0800, Huacai Chen wrote:
> Loongson-3 maintains cache coherency by hardware. So we introduce a cpu
> feature named cpu_has_coherent_cache and use it to modify MIPS's cache
> flushing functions.
You've modified all the local_* functions which means the r4k_on_each_cpu()
in r4k___flush_cache_all(), r4k_flush_cache_sigtramp() otc. will still be
executed.
Your change is correct - but I think it can be optimized if we can assume
that all CPUs have a coherent cache by moving the check into the caller.
smp_call_function() can be fairly expensive in particular on big systems!
Ralf
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH V2 05/12] MIPS: Loongson: Allow booting from any core
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (3 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 04/12] MIPS: Loongson: Introduce and use cpu_has_coherent_cache feature Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:15 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 06/12] MIPS: Loongson: Improve LEFI firmware interface Huacai Chen
` (3 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
By offering Logical->Physical core id mapping, so as to reserve some
physical cores via mask. This allow booting from any core when core-0
has problems. Since the maximun cores supported by Loongson-3 is 16,
32-bit cpu_startup_core_id can be split to 16-bit cpu_startup_core_id
and 16-bit reserved_cores_mask for compatibility.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/mach-loongson/boot_param.h | 5 +-
arch/mips/include/asm/mach-loongson/irq.h | 3 +-
arch/mips/include/asm/mach-loongson/topology.h | 2 +-
arch/mips/loongson/common/env.c | 2 +
arch/mips/loongson/loongson-3/irq.c | 14 +++--
arch/mips/loongson/loongson-3/numa.c | 12 +++-
arch/mips/loongson/loongson-3/smp.c | 65 ++++++++++++++--------
7 files changed, 67 insertions(+), 36 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 3388fc5..11ebf4c 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -42,7 +42,8 @@ struct efi_cpuinfo_loongson {
u32 processor_id; /* PRID, e.g. 6305, 6306 */
u32 cputype; /* Loongson_3A/3B, etc. */
u32 total_node; /* num of total numa nodes */
- u32 cpu_startup_core_id; /* Core id */
+ u16 cpu_startup_core_id; /* Boot core id */
+ u16 reserved_cores_mask;
u32 cpu_clock_freq; /* cpu_clock */
u32 nr_cpus;
} __packed;
@@ -149,6 +150,8 @@ struct loongson_system_configuration {
u32 nr_nodes;
int cores_per_node;
int cores_per_package;
+ u16 boot_cpu_id;
+ u16 reserved_cpus_mask;
enum loongson_cpu_type cputype;
u64 ht_control_base;
u64 pci_mem_start_addr;
diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
index 34560bd..a281cca 100644
--- a/arch/mips/include/asm/mach-loongson/irq.h
+++ b/arch/mips/include/asm/mach-loongson/irq.h
@@ -32,8 +32,7 @@
#define LOONGSON_INT_ROUTER_LPC LOONGSON_INT_ROUTER_ENTRY(0x0a)
#define LOONGSON_INT_ROUTER_HT1(n) LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
-#define LOONGSON_INT_CORE0_INT0 0x11 /* route to int 0 of core 0 */
-#define LOONGSON_INT_CORE0_INT1 0x21 /* route to int 1 of core 0 */
+#define LOONGSON_INT_COREx_INTy(x, y) (1<<(x) | 1<<(y+4)) /* route to int y of core x */
#endif
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
index 5598ba7..0d8f3b5 100644
--- a/arch/mips/include/asm/mach-loongson/topology.h
+++ b/arch/mips/include/asm/mach-loongson/topology.h
@@ -3,7 +3,7 @@
#ifdef CONFIG_NUMA
-#define cpu_to_node(cpu) ((cpu) >> 2)
+#define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2)
#define parent_node(node) (node)
#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index f152285..d8be539 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -119,6 +119,8 @@ void __init prom_init_env(void)
}
loongson_sysconf.nr_cpus = ecpu->nr_cpus;
+ loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id;
+ loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask;
if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
loongson_sysconf.nr_cpus = NR_CPUS;
loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
index ca1c62a..5813d94 100644
--- a/arch/mips/loongson/loongson-3/irq.c
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -55,8 +55,8 @@ static inline void mask_loongson_irq(struct irq_data *d)
/* Workaround: UART IRQ may deliver to any core */
if (d->irq == LOONGSON_UART_IRQ) {
int cpu = smp_processor_id();
- int node_id = cpu / loongson_sysconf.cores_per_node;
- int core_id = cpu % loongson_sysconf.cores_per_node;
+ int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node;
+ int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node;
u64 intenclr_addr = smp_group[node_id] |
(u64)(&LOONGSON_INT_ROUTER_INTENCLR);
u64 introuter_lpc_addr = smp_group[node_id] |
@@ -72,8 +72,8 @@ static inline void unmask_loongson_irq(struct irq_data *d)
/* Workaround: UART IRQ may deliver to any core */
if (d->irq == LOONGSON_UART_IRQ) {
int cpu = smp_processor_id();
- int node_id = cpu / loongson_sysconf.cores_per_node;
- int core_id = cpu % loongson_sysconf.cores_per_node;
+ int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node;
+ int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node;
u64 intenset_addr = smp_group[node_id] |
(u64)(&LOONGSON_INT_ROUTER_INTENSET);
u64 introuter_lpc_addr = smp_group[node_id] |
@@ -102,10 +102,12 @@ void irq_router_init(void)
int i;
/* route LPC int to cpu core0 int 0 */
- LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
+ LOONGSON_INT_ROUTER_LPC =
+ LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 0);
/* route HT1 int0 ~ int7 to cpu core0 INT1*/
for (i = 0; i < 8; i++)
- LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
+ LOONGSON_INT_ROUTER_HT1(i) =
+ LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 1);
/* enable HT1 interrupt */
LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
/* enable router interrupt intenset */
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
index 37ed184..5246043 100644
--- a/arch/mips/loongson/loongson-3/numa.c
+++ b/arch/mips/loongson/loongson-3/numa.c
@@ -223,7 +223,7 @@ static void __init node_mem_init(unsigned int node)
static __init void prom_meminit(void)
{
- unsigned int node, cpu;
+ unsigned int node, cpu, active_cpu = 0;
cpu_node_probe();
init_topology_matrix();
@@ -239,8 +239,14 @@ static __init void prom_meminit(void)
node = cpu / loongson_sysconf.cores_per_node;
if (node >= num_online_nodes())
node = 0;
- pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
- cpu_set(cpu, __node_data[(node)]->cpumask);
+
+ if (loongson_sysconf.reserved_cpus_mask & (1<<cpu))
+ continue;
+
+ cpu_set(active_cpu, __node_data[(node)]->cpumask);
+ pr_info("NUMA: set cpumask cpu %d on node %d\n", active_cpu, node);
+
+ active_cpu++;
}
}
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index d8c63af..94ed8a5 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -239,7 +239,7 @@ static void ipi_mailbox_buf_init(void)
*/
static void loongson3_send_ipi_single(int cpu, unsigned int action)
{
- loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
+ loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(cpu)]);
}
static void
@@ -248,7 +248,7 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
unsigned int i;
for_each_cpu(i, mask)
- loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
+ loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(i)]);
}
void loongson3_ipi_interrupt(struct pt_regs *regs)
@@ -257,10 +257,10 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
unsigned int action, c0count;
/* Load the ipi register to figure out what we're supposed to do */
- action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
+ action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]);
/* Clear the ipi register to clear the interrupt */
- loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
+ loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]);
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
@@ -291,12 +291,14 @@ static void loongson3_init_secondary(void)
/* Set interrupt mask, but don't enable */
change_c0_status(ST0_IM, imask);
- for (i = 0; i < loongson_sysconf.nr_cpus; i++)
- loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
+ for (i = 0; i < num_possible_cpus(); i++)
+ loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(i)]);
- cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
- cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
per_cpu(cpu_state, cpu) = CPU_ONLINE;
+ cpu_data[cpu].core =
+ cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
+ cpu_data[cpu].package =
+ cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
i = 0;
__this_cpu_write(core0_c0count, 0);
@@ -314,37 +316,50 @@ static void loongson3_init_secondary(void)
static void loongson3_smp_finish(void)
{
+ int cpu = smp_processor_id();
+
write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
local_irq_enable();
loongson3_ipi_write64(0,
- (void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
+ (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
pr_info("CPU#%d finished, CP0_ST=%x\n",
smp_processor_id(), read_c0_status());
}
static void __init loongson3_smp_setup(void)
{
- int i, num;
+ int i = 0, num = 0; /* i: physical id, num: logical id */
init_cpu_possible(cpu_none_mask);
- set_cpu_possible(0, true);
-
- __cpu_number_map[0] = 0;
- __cpu_logical_map[0] = 0;
/* For unified kernel, NR_CPUS is the maximum possible value,
* loongson_sysconf.nr_cpus is the really present value */
- for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
- set_cpu_possible(i, true);
- __cpu_number_map[i] = ++num;
- __cpu_logical_map[num] = i;
+ while (i < loongson_sysconf.nr_cpus) {
+ if (loongson_sysconf.reserved_cpus_mask & (1<<i)) {
+ /* Reserved physical CPU cores */
+ __cpu_number_map[i] = -1;
+ } else {
+ __cpu_number_map[i] = num;
+ __cpu_logical_map[num] = i;
+ set_cpu_possible(num, true);
+ num++;
+ }
+ i++;
}
+ pr_info("Detected %i available CPU(s)\n", num);
+
+ while (num < loongson_sysconf.nr_cpus) {
+ __cpu_logical_map[num] = -1;
+ num++;
+ }
+
ipi_set0_regs_init();
ipi_clear0_regs_init();
ipi_status0_regs_init();
ipi_en0_regs_init();
ipi_mailbox_buf_init();
- pr_info("Detected %i available secondary CPU(s)\n", num);
+ cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package;
+ cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
}
static void __init loongson3_prepare_cpus(unsigned int max_cpus)
@@ -371,10 +386,14 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle)
pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
cpu, startargs[0], startargs[1], startargs[2]);
- loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
- loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
- loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
- loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
+ loongson3_ipi_write64(startargs[3],
+ (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x18));
+ loongson3_ipi_write64(startargs[2],
+ (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x10));
+ loongson3_ipi_write64(startargs[1],
+ (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8));
+ loongson3_ipi_write64(startargs[0],
+ (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
}
#ifdef CONFIG_HOTPLUG_CPU
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH V2 06/12] MIPS: Loongson: Improve LEFI firmware interface
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (4 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 05/12] MIPS: Loongson: Allow booting from any core Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:16 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support Huacai Chen
` (2 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
Machtypes of Loongson-3 machines become more and more, but there are
only small differences among different machtypes. Keeping a large table
of machtypes is very ugly and hard to extend. We found that the major
machtype differences are UARTs information (number of UARTs, UART IRQs,
UART clocks, etc.), platform devices (EC, temperature sensors, fan
controllers, etc.) and some workarounds (because of some CPU bugs or
mainboard bugs).
In this patch we improve the UEFI-like (LEFI) interface to make all
Loongson-3 machines use a same machtype "generic-loongson-machine".
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/bootinfo.h | 5 +--
arch/mips/include/asm/mach-loongson/boot_param.h | 44 +++++++++++++++-
arch/mips/include/asm/mach-loongson/loongson.h | 2 +-
.../include/asm/mach-loongson/loongson_hwmon.h | 55 ++++++++++++++++++++
arch/mips/include/asm/mach-loongson/machine.h | 2 +-
arch/mips/include/asm/mach-loongson/workarounds.h | 7 +++
arch/mips/loongson/common/early_printk.c | 2 +-
arch/mips/loongson/common/env.c | 26 +++++++++-
arch/mips/loongson/common/machtype.c | 5 +--
arch/mips/loongson/common/serial.c | 48 ++++++++++++++---
arch/mips/loongson/common/uart_base.c | 30 +++++------
arch/mips/loongson/loongson-3/Makefile | 2 +-
arch/mips/loongson/loongson-3/platform.c | 43 +++++++++++++++
arch/mips/loongson/loongson-3/smp.c | 5 +-
14 files changed, 234 insertions(+), 42 deletions(-)
create mode 100644 arch/mips/include/asm/mach-loongson/loongson_hwmon.h
create mode 100644 arch/mips/include/asm/mach-loongson/workarounds.h
create mode 100644 arch/mips/loongson/loongson-3/platform.c
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 1f7ca8b..8b2eaa1 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -70,10 +70,7 @@ enum loongson_machine_type {
MACH_DEXXON_GDIUM2F10,
MACH_LEMOTE_NAS,
MACH_LEMOTE_LL2F,
- MACH_LEMOTE_A1004,
- MACH_LEMOTE_A1101,
- MACH_LEMOTE_A1201,
- MACH_LEMOTE_A1205,
+ MACH_LOONGSON_GENERIC,
MACH_LOONGSON_END
};
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 11ebf4c..fa80292 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -10,7 +10,8 @@
#define VIDEO_ROM 7
#define ADAPTER_ROM 8
#define ACPI_TABLE 9
-#define MAX_MEMORY_TYPE 10
+#define SMBIOS_TABLE 10
+#define MAX_MEMORY_TYPE 11
#define LOONGSON3_BOOT_MEM_MAP_MAX 128
struct efi_memory_map_loongson {
@@ -48,10 +49,43 @@ struct efi_cpuinfo_loongson {
u32 nr_cpus;
} __packed;
+#define MAX_UARTS 64
+struct uart_device {
+ u32 iotype; /* see include/linux/serial_core.h */
+ u32 uartclk;
+ u32 int_offset;
+ u64 uart_base;
+} __packed;
+
+#define MAX_SENSORS 64
+#define SENSOR_TEMPER 0x00000001
+#define SENSOR_VOLTAGE 0x00000002
+#define SENSOR_FAN 0x00000004
+struct sensor_device {
+ char name[32]; /* a formal name */
+ char label[64]; /* a flexible description */
+ u32 type; /* SENSOR_* */
+ u32 id; /* instance id of a sensor-class */
+ u32 fan_policy; /* see loongson_hwmon.h */
+ u32 fan_percent;/* only for constant speed policy */
+ u64 base_addr; /* base address of device registers */
+} __packed;
+
struct system_loongson {
u16 vers; /* version of system_loongson */
u32 ccnuma_smp; /* 0: no numa; 1: has numa */
u32 sing_double_channel; /* 1:single; 2:double */
+ u32 nr_uarts;
+ struct uart_device uarts[MAX_UARTS];
+ u32 nr_sensors;
+ struct sensor_device sensors[MAX_SENSORS];
+ char has_ec;
+ char ec_name[32];
+ u64 ec_base_addr;
+ char has_tcm;
+ char tcm_name[32];
+ u64 tcm_base_addr;
+ u64 workarounds; /* see workarounds.h */
} __packed;
struct irq_source_routing_table {
@@ -162,9 +196,15 @@ struct loongson_system_configuration {
u64 suspend_addr;
u64 vgabios_addr;
u32 dma_mask_bits;
+ char ecname[32];
+ u32 nr_uarts;
+ struct uart_device uarts[MAX_UARTS];
+ u32 nr_sensors;
+ struct sensor_device sensors[MAX_SENSORS];
+ u64 workarounds;
};
extern struct efi_memory_map_loongson *loongson_memmap;
extern struct loongson_system_configuration loongson_sysconf;
-extern int cpuhotplug_workaround;
+
#endif
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 92bf76c..5459ac0 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -35,7 +35,7 @@ extern void __init prom_init_cmdline(void);
extern void __init prom_init_machtype(void);
extern void __init prom_init_env(void);
#ifdef CONFIG_LOONGSON_UART_BASE
-extern unsigned long _loongson_uart_base, loongson_uart_base;
+extern unsigned long _loongson_uart_base[], loongson_uart_base[];
extern void prom_init_loongson_uart_base(void);
#endif
diff --git a/arch/mips/include/asm/mach-loongson/loongson_hwmon.h b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h
new file mode 100644
index 0000000..4431fc5
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h
@@ -0,0 +1,55 @@
+#ifndef __LOONGSON_HWMON_H_
+#define __LOONGSON_HWMON_H_
+
+#include <linux/types.h>
+
+#define MIN_TEMP 0
+#define MAX_TEMP 255
+#define NOT_VALID_TEMP 999
+
+typedef int (*get_temp_fun)(int);
+extern int loongson3_cpu_temp(int);
+
+/* 0:Max speed, 1:Manual, 2:Auto */
+enum fan_control_mode {
+ FAN_FULL_MODE = 0,
+ FAN_MANUAL_MODE = 1,
+ FAN_AUTO_MODE = 2,
+ FAN_MODE_END
+};
+
+struct temp_range {
+ u8 low;
+ u8 high;
+ u8 level;
+};
+
+#define CONSTANT_SPEED_POLICY 0 /* at constent speed */
+#define STEP_SPEED_POLICY 1 /* use up/down arrays to describe policy */
+#define KERNEL_HELPER_POLICY 2 /* kernel as a helper to fan control */
+
+#define MAX_STEP_NUM 16
+#define MAX_FAN_LEVEL 255
+
+/* loongson_fan_policy works when fan work at FAN_AUTO_MODE */
+struct loongson_fan_policy {
+ u8 type;
+
+ /* percent only used when type is CONSTANT_SPEED_POLICY */
+ u8 percent;
+
+ /* period between two check. (Unit: S) */
+ u8 adjust_period;
+
+ /* fan adjust usually depend on a temprature input */
+ get_temp_fun depend_temp;
+
+ /* up_step/down_step used when type is STEP_SPEED_POLICY */
+ u8 up_step_num;
+ u8 down_step_num;
+ struct temp_range up_step[MAX_STEP_NUM];
+ struct temp_range down_step[MAX_STEP_NUM];
+ struct delayed_work work;
+};
+
+#endif /* __LOONGSON_HWMON_H_*/
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 228e3784..cb2b602 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -26,7 +26,7 @@
#ifdef CONFIG_LOONGSON_MACH3X
-#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
+#define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC
#endif /* CONFIG_LOONGSON_MACH3X */
diff --git a/arch/mips/include/asm/mach-loongson/workarounds.h b/arch/mips/include/asm/mach-loongson/workarounds.h
new file mode 100644
index 0000000..e180c14
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/workarounds.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_
+#define __ASM_MACH_LOONGSON_WORKAROUNDS_H_
+
+#define WORKAROUND_CPUFREQ 0x00000001
+#define WORKAROUND_CPUHOTPLUG 0x00000002
+
+#endif
diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c
index ced461b..6ca632e 100644
--- a/arch/mips/loongson/common/early_printk.c
+++ b/arch/mips/loongson/common/early_printk.c
@@ -30,7 +30,7 @@ void prom_putchar(char c)
int timeout;
unsigned char *uart_base;
- uart_base = (unsigned char *)_loongson_uart_base;
+ uart_base = (unsigned char *)_loongson_uart_base[0];
timeout = 1024;
while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) &&
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index d8be539..045ea3d 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -21,6 +21,7 @@
#include <asm/bootinfo.h>
#include <loongson.h>
#include <boot_param.h>
+#include <workarounds.h>
u32 cpu_clock_freq;
EXPORT_SYMBOL(cpu_clock_freq);
@@ -31,7 +32,6 @@ u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
u64 loongson_freqctrl[MAX_PACKAGES];
unsigned long long smp_group[4];
-int cpuhotplug_workaround = 0;
#define parse_even_earlier(res, option, p) \
do { \
@@ -67,6 +67,7 @@ void __init prom_init_env(void)
#else
struct boot_params *boot_p;
struct loongson_params *loongson_p;
+ struct system_loongson *esys;
struct efi_cpuinfo_loongson *ecpu;
struct irq_source_routing_table *eirq_source;
@@ -74,6 +75,8 @@ void __init prom_init_env(void)
boot_p = (struct boot_params *)fw_arg2;
loongson_p = &(boot_p->efi.smbios.lp);
+ esys = (struct system_loongson *)
+ ((u64)loongson_p + loongson_p->system_offset);
ecpu = (struct efi_cpuinfo_loongson *)
((u64)loongson_p + loongson_p->cpu_offset);
eirq_source = (struct irq_source_routing_table *)
@@ -95,6 +98,7 @@ void __init prom_init_env(void)
loongson_chipcfg[2] = 0x900020001fe00180;
loongson_chipcfg[3] = 0x900030001fe00180;
loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+ loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
} else if (ecpu->cputype == Loongson_3B) {
loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
loongson_sysconf.cores_per_package = 8;
@@ -111,7 +115,7 @@ void __init prom_init_env(void)
loongson_freqctrl[2] = 0x900040001fe001d0;
loongson_freqctrl[3] = 0x900060001fe001d0;
loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
- cpuhotplug_workaround = 1;
+ loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG;
} else {
loongson_sysconf.cores_per_node = 1;
loongson_sysconf.cores_per_package = 1;
@@ -143,6 +147,24 @@ void __init prom_init_env(void)
pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
loongson_sysconf.vgabios_addr);
+
+ memset(loongson_sysconf.ecname, 0, 32);
+ if (esys->has_ec)
+ memcpy(loongson_sysconf.ecname, esys->ec_name, 32);
+ loongson_sysconf.workarounds |= esys->workarounds;
+
+ loongson_sysconf.nr_uarts = esys->nr_uarts;
+ if (esys->nr_uarts < 1 || esys->nr_uarts > MAX_UARTS)
+ loongson_sysconf.nr_uarts = 1;
+ memcpy(loongson_sysconf.uarts, esys->uarts,
+ sizeof(struct uart_device) * loongson_sysconf.nr_uarts);
+
+ loongson_sysconf.nr_sensors = esys->nr_sensors;
+ if (loongson_sysconf.nr_sensors > MAX_SENSORS)
+ loongson_sysconf.nr_sensors = 0;
+ if (loongson_sysconf.nr_sensors)
+ memcpy(loongson_sysconf.sensors, esys->sensors,
+ sizeof(struct sensor_device) * loongson_sysconf.nr_sensors);
#endif
if (cpu_clock_freq == 0) {
processor_id = (¤t_cpu_data)->processor_id;
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 1a47979..26629ab 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -27,10 +27,7 @@ static const char *system_types[] = {
[MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f",
[MACH_LEMOTE_NAS] "lemote-nas-2f",
[MACH_LEMOTE_LL2F] "lemote-lynloong-2f",
- [MACH_LEMOTE_A1004] "lemote-3a-notebook-a1004",
- [MACH_LEMOTE_A1101] "lemote-3a-itx-a1101",
- [MACH_LEMOTE_A1201] "lemote-2gq-notebook-a1201",
- [MACH_LEMOTE_A1205] "lemote-2gq-aio-a1205",
+ [MACH_LOONGSON_GENERIC] "generic-loongson-machine",
[MACH_LOONGSON_END] NULL,
};
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
index bd2b709..d2f4817 100644
--- a/arch/mips/loongson/common/serial.c
+++ b/arch/mips/loongson/common/serial.c
@@ -38,7 +38,7 @@
.regshift = 0, \
}
-static struct plat_serial8250_port uart8250_data[][2] = {
+static struct plat_serial8250_port uart8250_data[][MAX_UARTS + 1] = {
[MACH_LOONGSON_UNKNOWN] {},
[MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} },
[MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} },
@@ -47,10 +47,7 @@ static struct plat_serial8250_port uart8250_data[][2] = {
[MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} },
[MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} },
[MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} },
- [MACH_LEMOTE_A1004] {PORT_M(2, 33177600), {} },
- [MACH_LEMOTE_A1101] {PORT_M(2, 25000000), {} },
- [MACH_LEMOTE_A1201] {PORT_M(2, 25000000), {} },
- [MACH_LEMOTE_A1205] {PORT_M(2, 25000000), {} },
+ [MACH_LOONGSON_GENERIC] {PORT_M(2, 25000000), {} },
[MACH_LOONGSON_END] {},
};
@@ -61,17 +58,52 @@ static struct platform_device uart8250_device = {
static int __init serial_init(void)
{
+ int i;
unsigned char iotype;
iotype = uart8250_data[mips_machtype][0].iotype;
- if (UPIO_MEM == iotype)
+ if (UPIO_MEM == iotype) {
+ uart8250_data[mips_machtype][0].mapbase =
+ loongson_uart_base[0];
uart8250_data[mips_machtype][0].membase =
- (void __iomem *)_loongson_uart_base;
+ (void __iomem *)_loongson_uart_base[0];
+ }
else if (UPIO_PORT == iotype)
uart8250_data[mips_machtype][0].iobase =
- loongson_uart_base - LOONGSON_PCIIO_BASE;
+ loongson_uart_base[0] - LOONGSON_PCIIO_BASE;
+ if (loongson_sysconf.uarts[0].uartclk)
+ uart8250_data[mips_machtype][0].uartclk =
+ loongson_sysconf.uarts[0].uartclk;
+
+ for (i = 1; i < loongson_sysconf.nr_uarts; i++) {
+ iotype = loongson_sysconf.uarts[i].iotype;
+ uart8250_data[mips_machtype][i].iotype = iotype;
+ loongson_uart_base[i] = loongson_sysconf.uarts[i].uart_base;
+
+ if (UPIO_MEM == iotype) {
+ uart8250_data[mips_machtype][i].irq =
+ MIPS_CPU_IRQ_BASE + loongson_sysconf.uarts[i].int_offset;
+ uart8250_data[mips_machtype][i].mapbase =
+ loongson_uart_base[i];
+ uart8250_data[mips_machtype][i].membase =
+ ioremap_nocache(loongson_uart_base[i], 8);
+ } else if (UPIO_PORT == iotype) {
+ uart8250_data[mips_machtype][i].irq =
+ loongson_sysconf.uarts[i].int_offset;
+ uart8250_data[mips_machtype][i].iobase =
+ loongson_uart_base[i] - LOONGSON_PCIIO_BASE;
+ }
+
+ uart8250_data[mips_machtype][i].uartclk =
+ loongson_sysconf.uarts[i].uartclk;
+ uart8250_data[mips_machtype][i].flags =
+ UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ }
+
+ memset(&uart8250_data[mips_machtype][loongson_sysconf.nr_uarts],
+ 0, sizeof(struct plat_serial8250_port));
uart8250_device.dev.platform_data = uart8250_data[mips_machtype];
return platform_device_register(&uart8250_device);
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
index 1e1eeea..9de559d 100644
--- a/arch/mips/loongson/common/uart_base.c
+++ b/arch/mips/loongson/common/uart_base.c
@@ -13,22 +13,27 @@
#include <loongson.h>
-/* ioremapped */
-unsigned long _loongson_uart_base;
-EXPORT_SYMBOL(_loongson_uart_base);
/* raw */
-unsigned long loongson_uart_base;
+unsigned long loongson_uart_base[MAX_UARTS] = {};
+/* ioremapped */
+unsigned long _loongson_uart_base[MAX_UARTS] = {};
+
EXPORT_SYMBOL(loongson_uart_base);
+EXPORT_SYMBOL(_loongson_uart_base);
void prom_init_loongson_uart_base(void)
{
switch (mips_machtype) {
+ case MACH_LOONGSON_GENERIC:
+ /* The CPU provided serial port (CPU) */
+ loongson_uart_base[0] = LOONGSON_REG_BASE + 0x1e0;
+ break;
case MACH_LEMOTE_FL2E:
- loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8;
+ loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x3f8;
break;
case MACH_LEMOTE_FL2F:
case MACH_LEMOTE_LL2F:
- loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8;
+ loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x2f8;
break;
case MACH_LEMOTE_ML2F7:
case MACH_LEMOTE_YL2F89:
@@ -36,17 +41,10 @@ void prom_init_loongson_uart_base(void)
case MACH_LEMOTE_NAS:
default:
/* The CPU provided serial port (LPC) */
- loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
- break;
- case MACH_LEMOTE_A1004:
- case MACH_LEMOTE_A1101:
- case MACH_LEMOTE_A1201:
- case MACH_LEMOTE_A1205:
- /* The CPU provided serial port (CPU) */
- loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
+ loongson_uart_base[0] = LOONGSON_LIO1_BASE + 0x3f8;
break;
}
- _loongson_uart_base =
- (unsigned long)ioremap_nocache(loongson_uart_base, 8);
+ _loongson_uart_base[0] =
+ (unsigned long)ioremap_nocache(loongson_uart_base[0], 8);
}
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index b4df775..69809a3 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for Loongson-3 family machines
#
-obj-y += irq.o cop2-ex.o
+obj-y += irq.o cop2-ex.o platform.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/loongson/loongson-3/platform.c b/arch/mips/loongson/loongson-3/platform.c
new file mode 100644
index 0000000..25a97cc
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/platform.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzhangjin@gmail.com
+ * Xiang Yu, xiangy@lemote.com
+ * Chen Huacai, chenhc@lemote.com
+ *
+ * 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 the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <asm/bootinfo.h>
+#include <boot_param.h>
+#include <loongson_hwmon.h>
+#include <workarounds.h>
+
+static int __init loongson3_platform_init(void)
+{
+ int i;
+ struct platform_device *pdev;
+
+ if (loongson_sysconf.ecname[0] != '\0')
+ platform_device_register_simple(loongson_sysconf.ecname, -1, NULL, 0);
+
+ for (i = 0; i < loongson_sysconf.nr_sensors; i++) {
+ if (loongson_sysconf.sensors[i].type > SENSOR_FAN)
+ continue;
+
+ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ pdev->name = loongson_sysconf.sensors[i].name;
+ pdev->id = loongson_sysconf.sensors[i].id;
+ pdev->dev.platform_data = &loongson_sysconf.sensors[i];
+ platform_device_register(pdev);
+ }
+
+ return 0;
+}
+
+arch_initcall(loongson3_platform_init);
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index 94ed8a5..e2eb688 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -25,6 +25,7 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
#include <loongson.h>
+#include <workarounds.h>
#include "smp.h"
@@ -587,7 +588,7 @@ void loongson3_disable_clock(int cpu)
if (loongson_sysconf.cputype == Loongson_3A) {
LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
} else if (loongson_sysconf.cputype == Loongson_3B) {
- if (!cpuhotplug_workaround)
+ if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
}
}
@@ -600,7 +601,7 @@ void loongson3_enable_clock(int cpu)
if (loongson_sysconf.cputype == Loongson_3A) {
LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
} else if (loongson_sysconf.cputype == Loongson_3B) {
- if (!cpuhotplug_workaround)
+ if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
}
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (5 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 06/12] MIPS: Loongson: Improve LEFI firmware interface Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:18 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver Huacai Chen
2014-11-04 6:13 ` [PATCH V2 09/12] MIPS: Loongson-3: Add chipset ACPI " Huacai Chen
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen, Hongbing Hu
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongbing Hu <huhb@lemote.com>
---
arch/mips/Kconfig | 1 +
arch/mips/loongson/common/gpio.c | 53 ++++++++++++++++++++++---------------
2 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b3dc152..2a488f4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1198,6 +1198,7 @@ config CPU_LOONGSON3
select CPU_SUPPORTS_HUGEPAGES
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
+ select ARCH_REQUIRE_GPIOLIB
help
The Loongson 3 processor implements the MIPS64R2 instruction
set with many extensions.
diff --git a/arch/mips/loongson/common/gpio.c b/arch/mips/loongson/common/gpio.c
index 29dbaa2..ecc828a 100644
--- a/arch/mips/loongson/common/gpio.c
+++ b/arch/mips/loongson/common/gpio.c
@@ -1,8 +1,9 @@
/*
- * STLS2F GPIO Support
+ * Loongson-2F/3A/3B GPIO Support
*
* Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
* Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
+ * Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
*
* 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
@@ -20,7 +21,15 @@
#include <linux/gpio.h>
#define STLS2F_N_GPIO 4
-#define STLS2F_GPIO_IN_OFFSET 16
+#define STLS3A_N_GPIO 16
+
+#ifdef CONFIG_CPU_LOONGSON3
+#define LOONGSON_N_GPIO STLS3A_N_GPIO
+#else
+#define LOONGSON_N_GPIO STLS2F_N_GPIO
+#endif
+
+#define LOONGSON_GPIO_IN_OFFSET 16
static DEFINE_SPINLOCK(gpio_lock);
@@ -29,10 +38,10 @@ int gpio_get_value(unsigned gpio)
u32 val;
u32 mask;
- if (gpio >= STLS2F_N_GPIO)
+ if (gpio >= LOONGSON_N_GPIO)
return __gpio_get_value(gpio);
- mask = 1 << (gpio + STLS2F_GPIO_IN_OFFSET);
+ mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET);
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
spin_unlock(&gpio_lock);
@@ -46,7 +55,7 @@ void gpio_set_value(unsigned gpio, int state)
u32 val;
u32 mask;
- if (gpio >= STLS2F_N_GPIO) {
+ if (gpio >= LOONGSON_N_GPIO) {
__gpio_set_value(gpio, state);
return ;
}
@@ -66,19 +75,19 @@ EXPORT_SYMBOL(gpio_set_value);
int gpio_cansleep(unsigned gpio)
{
- if (gpio < STLS2F_N_GPIO)
+ if (gpio < LOONGSON_N_GPIO)
return 0;
else
return __gpio_cansleep(gpio);
}
EXPORT_SYMBOL(gpio_cansleep);
-static int ls2f_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
u32 temp;
u32 mask;
- if (gpio >= STLS2F_N_GPIO)
+ if (gpio >= LOONGSON_N_GPIO)
return -EINVAL;
spin_lock(&gpio_lock);
@@ -91,13 +100,13 @@ static int ls2f_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
return 0;
}
-static int ls2f_gpio_direction_output(struct gpio_chip *chip,
+static int loongson_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int level)
{
u32 temp;
u32 mask;
- if (gpio >= STLS2F_N_GPIO)
+ if (gpio >= LOONGSON_N_GPIO)
return -EINVAL;
gpio_set_value(gpio, level);
@@ -111,29 +120,29 @@ static int ls2f_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
-static int ls2f_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
return gpio_get_value(gpio);
}
-static void ls2f_gpio_set_value(struct gpio_chip *chip,
+static void loongson_gpio_set_value(struct gpio_chip *chip,
unsigned gpio, int value)
{
gpio_set_value(gpio, value);
}
-static struct gpio_chip ls2f_chip = {
- .label = "ls2f",
- .direction_input = ls2f_gpio_direction_input,
- .get = ls2f_gpio_get_value,
- .direction_output = ls2f_gpio_direction_output,
- .set = ls2f_gpio_set_value,
+static struct gpio_chip loongson_chip = {
+ .label = "Loongson-gpio-chip",
+ .direction_input = loongson_gpio_direction_input,
+ .get = loongson_gpio_get_value,
+ .direction_output = loongson_gpio_direction_output,
+ .set = loongson_gpio_set_value,
.base = 0,
- .ngpio = STLS2F_N_GPIO,
+ .ngpio = LOONGSON_N_GPIO,
};
-static int __init ls2f_gpio_setup(void)
+static int __init loongson_gpio_setup(void)
{
- return gpiochip_add(&ls2f_chip);
+ return gpiochip_add(&loongson_chip);
}
-arch_initcall(ls2f_gpio_setup);
+arch_initcall(loongson_gpio_setup);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support
2014-11-04 6:13 ` [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support Huacai Chen
@ 2014-11-11 10:18 ` Ralf Baechle
2014-11-11 12:45 ` Huacai Chen
0 siblings, 1 reply; 22+ messages in thread
From: Ralf Baechle @ 2014-11-11 10:18 UTC (permalink / raw)
To: Huacai Chen
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Hongbing Hu
On Tue, Nov 04, 2014 at 02:13:28PM +0800, Huacai Chen wrote:
This looks like a full blown GPIO driver and thus should be moved to
drivers/gpio.
Ralf
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support
2014-11-11 10:18 ` Ralf Baechle
@ 2014-11-11 12:45 ` Huacai Chen
0 siblings, 0 replies; 22+ messages in thread
From: Huacai Chen @ 2014-11-11 12:45 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, Linux MIPS Mailing List,
Fuxin Zhang, Zhangjin Wu, Hongbing Hu
It seems like I should send a V3 patchset since many of them need to modify.
On Tue, Nov 11, 2014 at 6:18 PM, Ralf Baechle <ralf@linux-mips.org> wrote:
> On Tue, Nov 04, 2014 at 02:13:28PM +0800, Huacai Chen wrote:
>
> This looks like a full blown GPIO driver and thus should be moved to
> drivers/gpio.
>
> Ralf
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (6 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 07/12] MIPS: Loongson: Add Loongson-3A/3B GPIO support Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
2014-11-11 10:23 ` Ralf Baechle
2014-11-04 6:13 ` [PATCH V2 09/12] MIPS: Loongson-3: Add chipset ACPI " Huacai Chen
8 siblings, 1 reply; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
This add CPU Hwmon (temperature sensor) platform driver for Loongson-3.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/include/asm/mach-loongson/loongson.h | 4 +
arch/mips/loongson/common/env.c | 9 +
drivers/platform/Makefile | 1 +
drivers/platform/mips/Makefile | 1 +
drivers/platform/mips/cpu_hwmon.c | 206 ++++++++++++++++++++++++
5 files changed, 221 insertions(+), 0 deletions(-)
create mode 100644 drivers/platform/mips/Makefile
create mode 100644 drivers/platform/mips/cpu_hwmon.c
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 5459ac0..9783103 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -255,6 +255,10 @@ static inline void do_perfcnt_IRQ(void)
extern u64 loongson_chipcfg[MAX_PACKAGES];
#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
+/* Chip Temperature registor of each physical cpu package, PRid >= Loongson-3A */
+extern u64 loongson_chiptemp[MAX_PACKAGES];
+#define LOONGSON_CHIPTEMP(id) (*(volatile u32 *)(loongson_chiptemp[id]))
+
/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
extern u64 loongson_freqctrl[MAX_PACKAGES];
#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index 045ea3d..22f04ca 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -29,6 +29,7 @@ struct efi_memory_map_loongson *loongson_memmap;
struct loongson_system_configuration loongson_sysconf;
u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
+u64 loongson_chiptemp[MAX_PACKAGES];
u64 loongson_freqctrl[MAX_PACKAGES];
unsigned long long smp_group[4];
@@ -97,6 +98,10 @@ void __init prom_init_env(void)
loongson_chipcfg[1] = 0x900010001fe00180;
loongson_chipcfg[2] = 0x900020001fe00180;
loongson_chipcfg[3] = 0x900030001fe00180;
+ loongson_chiptemp[0] = 0x900000001fe0019c;
+ loongson_chiptemp[1] = 0x900010001fe0019c;
+ loongson_chiptemp[2] = 0x900020001fe0019c;
+ loongson_chiptemp[3] = 0x900030001fe0019c;
loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
} else if (ecpu->cputype == Loongson_3B) {
@@ -110,6 +115,10 @@ void __init prom_init_env(void)
loongson_chipcfg[1] = 0x900020001fe00180;
loongson_chipcfg[2] = 0x900040001fe00180;
loongson_chipcfg[3] = 0x900060001fe00180;
+ loongson_chiptemp[0] = 0x900000001fe0019c;
+ loongson_chiptemp[1] = 0x900020001fe0019c;
+ loongson_chiptemp[2] = 0x900040001fe0019c;
+ loongson_chiptemp[3] = 0x900060001fe0019c;
loongson_freqctrl[0] = 0x900000001fe001d0;
loongson_freqctrl[1] = 0x900020001fe001d0;
loongson_freqctrl[2] = 0x900040001fe001d0;
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index 3656b7b..f2dbc00 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_X86) += x86/
obj-$(CONFIG_OLPC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
+obj-$(CONFIG_CPU_LOONGSON3) += mips/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
new file mode 100644
index 0000000..15723a6
--- /dev/null
+++ b/drivers/platform/mips/Makefile
@@ -0,0 +1 @@
+obj-y += cpu_hwmon.o
diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c
new file mode 100644
index 0000000..529950a
--- /dev/null
+++ b/drivers/platform/mips/cpu_hwmon.c
@@ -0,0 +1,206 @@
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <loongson.h>
+#include <boot_param.h>
+#include <loongson_hwmon.h>
+
+/*
+ * Loongson-3 series cpu has two sensors inside,
+ * each of them from 0 to 255,
+ * if more than 127, that is dangerous.
+ * here only provide sensor1 data, because it always hot than sensor0
+ */
+int loongson3_cpu_temp(int cpu)
+{
+ u32 reg;
+
+ reg = LOONGSON_CHIPTEMP(cpu);
+ if (loongson_sysconf.cputype == Loongson_3A)
+ reg = (reg >> 8) & 0xff;
+ else if (loongson_sysconf.cputype == Loongson_3B)
+ reg = ((reg >> 8) & 0xff) - 100;
+
+ return (int)reg * 1000;
+}
+
+static struct device *cpu_hwmon_dev;
+
+static ssize_t get_hwmon_name(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, get_hwmon_name, NULL, 0);
+
+static struct attribute *cpu_hwmon_attributes[] = {
+ &sensor_dev_attr_name.dev_attr.attr,
+ NULL
+};
+
+/* Hwmon device attribute group */
+static struct attribute_group cpu_hwmon_attribute_group = {
+ .attrs = cpu_hwmon_attributes,
+};
+
+/* Hwmon device get name */
+static ssize_t get_hwmon_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "cpu-hwmon\n");
+}
+
+static ssize_t get_cpu0_temp(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t get_cpu1_temp(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t cpu0_temp_label(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t cpu1_temp_label(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_cpu0_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, cpu0_temp_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_cpu1_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, cpu1_temp_label, NULL, 2);
+
+static const struct attribute *hwmon_cputemp1[] = {
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_label.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute *hwmon_cputemp2[] = {
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_label.dev_attr.attr,
+ NULL
+};
+
+static ssize_t cpu0_temp_label(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "CPU 0 Temprature\n");
+}
+
+static ssize_t cpu1_temp_label(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "CPU 1 Temprature\n");
+}
+
+static ssize_t get_cpu0_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int value = loongson3_cpu_temp(0);
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t get_cpu1_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int value = loongson3_cpu_temp(1);
+ return sprintf(buf, "%d\n", value);
+}
+
+static int create_sysfs_cputemp_files(struct kobject *kobj)
+{
+ int ret;
+
+ ret = sysfs_create_files(kobj, hwmon_cputemp1);
+ if (ret)
+ goto sysfs_create_temp1_fail;
+
+ if (loongson_sysconf.nr_cpus <= loongson_sysconf.cores_per_package)
+ return 0;
+
+ ret = sysfs_create_files(kobj, hwmon_cputemp2);
+ if (ret)
+ goto sysfs_create_temp2_fail;
+
+ return 0;
+
+sysfs_create_temp2_fail:
+ sysfs_remove_files(kobj, hwmon_cputemp1);
+
+sysfs_create_temp1_fail:
+ return -1;
+}
+
+static void remove_sysfs_cputemp_files(struct kobject *kobj)
+{
+ sysfs_remove_files(&cpu_hwmon_dev->kobj, hwmon_cputemp1);
+
+ if (loongson_sysconf.nr_cpus > loongson_sysconf.cores_per_package)
+ sysfs_remove_files(&cpu_hwmon_dev->kobj, hwmon_cputemp2);
+}
+
+#define CPU_THERMAL_THRESHOLD 90000
+static struct delayed_work thermal_work;
+
+static void do_thermal_timer(struct work_struct *work)
+{
+ int value = loongson3_cpu_temp(0);
+ if (value <= CPU_THERMAL_THRESHOLD)
+ schedule_delayed_work(&thermal_work, msecs_to_jiffies(5000));
+ else
+ orderly_poweroff(true);
+}
+
+static int __init loongson_hwmon_init(void)
+{
+ int ret;
+
+ pr_info("Loongson Hwmon Enter...\n");
+
+ cpu_hwmon_dev = hwmon_device_register(NULL);
+ if (IS_ERR(cpu_hwmon_dev)) {
+ ret = -ENOMEM;
+ pr_err("hwmon_device_register fail!\n");
+ goto fail_hwmon_device_register;
+ }
+
+ ret = sysfs_create_group(&cpu_hwmon_dev->kobj,
+ &cpu_hwmon_attribute_group);
+ if (ret) {
+ pr_err("fail to create loongson hwmon!\n");
+ goto fail_sysfs_create_group_hwmon;
+ }
+
+ ret = create_sysfs_cputemp_files(&cpu_hwmon_dev->kobj);
+ if (ret) {
+ pr_err("fail to create cpu temprature interface!\n");
+ goto fail_create_sysfs_cputemp_files;
+ }
+
+ INIT_DEFERRABLE_WORK(&thermal_work, do_thermal_timer);
+ schedule_delayed_work(&thermal_work, msecs_to_jiffies(20000));
+
+ return ret;
+
+fail_create_sysfs_cputemp_files:
+ sysfs_remove_group(&cpu_hwmon_dev->kobj,
+ &cpu_hwmon_attribute_group);
+
+fail_sysfs_create_group_hwmon:
+ hwmon_device_unregister(cpu_hwmon_dev);
+
+fail_hwmon_device_register:
+ return ret;
+}
+
+static void __exit loongson_hwmon_exit(void)
+{
+ cancel_delayed_work_sync(&thermal_work);
+ remove_sysfs_cputemp_files(&cpu_hwmon_dev->kobj);
+ sysfs_remove_group(&cpu_hwmon_dev->kobj,
+ &cpu_hwmon_attribute_group);
+ hwmon_device_unregister(cpu_hwmon_dev);
+}
+
+module_init(loongson_hwmon_init);
+module_exit(loongson_hwmon_exit);
+
+MODULE_AUTHOR("Yu Xiang <xiangy@lemote.com>");
+MODULE_AUTHOR("Huacai Chen <chenhc@lemote.com>");
+MODULE_DESCRIPTION("Loongson CPU Hwmon driver");
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver
2014-11-04 6:13 ` [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver Huacai Chen
@ 2014-11-11 10:23 ` Ralf Baechle
2014-11-11 12:44 ` Huacai Chen
0 siblings, 1 reply; 22+ messages in thread
From: Ralf Baechle @ 2014-11-11 10:23 UTC (permalink / raw)
To: Huacai Chen
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu
On Tue, Nov 04, 2014 at 02:13:29PM +0800, Huacai Chen wrote:
Does it make sense to force this driver unconditionally on everybody
building a kernel for a LOONGSON3 CPU? It is generally preferred to
control drivers individually through a separate Kconfig symbol.
Ralf
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver
2014-11-11 10:23 ` Ralf Baechle
@ 2014-11-11 12:44 ` Huacai Chen
0 siblings, 0 replies; 22+ messages in thread
From: Huacai Chen @ 2014-11-11 12:44 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, Linux MIPS Mailing List,
Fuxin Zhang, Zhangjin Wu
CPU temperature is always available, not depend on machine type, so I
make it be built unconditionally.
On Tue, Nov 11, 2014 at 6:23 PM, Ralf Baechle <ralf@linux-mips.org> wrote:
> On Tue, Nov 04, 2014 at 02:13:29PM +0800, Huacai Chen wrote:
>
> Does it make sense to force this driver unconditionally on everybody
> building a kernel for a LOONGSON3 CPU? It is generally preferred to
> control drivers individually through a separate Kconfig symbol.
>
> Ralf
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH V2 09/12] MIPS: Loongson-3: Add chipset ACPI platform driver
2014-11-04 6:13 [PATCH V2 00/12] MIPS: Loongson-3: Improve kernel functionality Huacai Chen
` (7 preceding siblings ...)
2014-11-04 6:13 ` [PATCH V2 08/12] MIPS: Loongson-3: Add CPU Hwmon platform driver Huacai Chen
@ 2014-11-04 6:13 ` Huacai Chen
8 siblings, 0 replies; 22+ messages in thread
From: Huacai Chen @ 2014-11-04 6:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: John Crispin, Steven J. Hill, linux-mips, Fuxin Zhang,
Zhangjin Wu, Huacai Chen
This add south-bridge (SB700/SB710/SB800 chipset) ACPI platform driver
for Loongson-3. This will be used by EC (Embedded Controller, used by
laptops) driver and STR (Suspend To RAM).
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
arch/mips/loongson/common/pci.c | 6 ++
drivers/platform/mips/Makefile | 2 +-
drivers/platform/mips/acpi_init.c | 131 +++++++++++++++++++++++++++++++++++++
3 files changed, 138 insertions(+), 1 deletions(-)
create mode 100644 drivers/platform/mips/acpi_init.c
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index 003ab4e..4e25756 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -78,6 +78,8 @@ static void __init setup_pcimap(void)
#endif
}
+extern int sbx00_acpi_init(void);
+
static int __init pcibios_init(void)
{
setup_pcimap();
@@ -89,6 +91,10 @@ static int __init pcibios_init(void)
#endif
register_pci_controller(&loongson_pci_controller);
+#ifdef CONFIG_CPU_LOONGSON3
+ sbx00_acpi_init();
+#endif
+
return 0;
}
diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
index 15723a6..acf0084 100644
--- a/drivers/platform/mips/Makefile
+++ b/drivers/platform/mips/Makefile
@@ -1 +1 @@
-obj-y += cpu_hwmon.o
+obj-y += acpi_init.o cpu_hwmon.o
diff --git a/drivers/platform/mips/acpi_init.c b/drivers/platform/mips/acpi_init.c
new file mode 100644
index 0000000..ee2825c
--- /dev/null
+++ b/drivers/platform/mips/acpi_init.c
@@ -0,0 +1,131 @@
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/export.h>
+
+#define SBX00_ACPI_IO_BASE 0x800
+#define SBX00_ACPI_IO_SIZE 0x100
+
+#define ACPI_PM_EVT_BLK (SBX00_ACPI_IO_BASE + 0x00) /* 4 bytes */
+#define ACPI_PM1_CNT_BLK (SBX00_ACPI_IO_BASE + 0x04) /* 2 bytes */
+#define ACPI_PMA_CNT_BLK (SBX00_ACPI_IO_BASE + 0x0F) /* 1 byte */
+#define ACPI_PM_TMR_BLK (SBX00_ACPI_IO_BASE + 0x18) /* 4 bytes */
+#define ACPI_GPE0_BLK (SBX00_ACPI_IO_BASE + 0x10) /* 8 bytes */
+#define ACPI_END (SBX00_ACPI_IO_BASE + 0x80)
+
+#define PM_INDEX 0xCD6
+#define PM_DATA 0xCD7
+#define PM2_INDEX 0xCD0
+#define PM2_DATA 0xCD1
+
+/*
+ * SCI interrupt need acpi space, allocate here
+ */
+
+static int __init register_acpi_resource(void)
+{
+ request_region(SBX00_ACPI_IO_BASE, SBX00_ACPI_IO_SIZE, "acpi");
+ return 0;
+}
+
+static void pmio_write_index(u16 index, u8 reg, u8 value)
+{
+ outb(reg, index);
+ outb(value, index + 1);
+}
+
+static u8 pmio_read_index(u16 index, u8 reg)
+{
+ outb(reg, index);
+ return inb(index + 1);
+}
+
+void pm_iowrite(u8 reg, u8 value)
+{
+ pmio_write_index(PM_INDEX, reg, value);
+}
+EXPORT_SYMBOL(pm_iowrite);
+
+u8 pm_ioread(u8 reg)
+{
+ return pmio_read_index(PM_INDEX, reg);
+}
+EXPORT_SYMBOL(pm_ioread);
+
+void pm2_iowrite(u8 reg, u8 value)
+{
+ pmio_write_index(PM2_INDEX, reg, value);
+}
+EXPORT_SYMBOL(pm2_iowrite);
+
+u8 pm2_ioread(u8 reg)
+{
+ return pmio_read_index(PM2_INDEX, reg);
+}
+EXPORT_SYMBOL(pm2_ioread);
+
+void sci_interrupt_setup(void)
+{
+ u32 temp32;
+
+ /* pm1 base */
+ pm_iowrite(0x22, ACPI_PM1_CNT_BLK & 0xff);
+ pm_iowrite(0x23, ACPI_PM1_CNT_BLK >> 8);
+
+ /* gpm base */
+ pm_iowrite(0x28, ACPI_GPE0_BLK & 0xFF);
+ pm_iowrite(0x29, ACPI_GPE0_BLK >> 8);
+
+ /* gpm base */
+ pm_iowrite(0x2e, ACPI_END & 0xFF);
+ pm_iowrite(0x2f, ACPI_END >> 8);
+
+ /* io decode: When AcpiDecodeEnable set, South-Bridge uses the contents
+ * of the PM registers at index 20-2B to decode ACPI I/O address. e.g.,
+ * AcpiSmiEn & SmiCmdEn */
+ pm_iowrite(0x0E, 1<<3 | 0<<2);
+
+ /* SCI_EN set */
+ outw(1, ACPI_PM1_CNT_BLK);
+
+ /* enable to generate SCI */
+ pm_iowrite(0x10, pm_ioread(0x10) | 1);
+
+ /* gpm3/gpm9 enable */
+ temp32 = inl(ACPI_GPE0_BLK + 4);
+ outl(temp32 | (1 << 14) | (1 << 22), ACPI_GPE0_BLK + 4);
+
+ /* set gpm9 as input */
+ pm_iowrite(0x8d, pm_ioread(0x8d) & (~(1 << 1)));
+
+ /* set gpm9 as non-output */
+ pm_iowrite(0x94, pm_ioread(0x94) | (1 << 3));
+
+ /* gpm3 config ACPI trigger SCIOUT */
+ pm_iowrite(0x33, pm_ioread(0x33) & (~(3 << 4)));
+
+ /* gpm9 config ACPI trigger SCIOUT */
+ pm_iowrite(0x3d, pm_ioread(0x3d) & (~(3 << 2)));
+
+ /* gpm3 config falling edge trigger */
+ pm_iowrite(0x37, pm_ioread(0x37) & (~(1 << 6)));
+
+ /* set gpm3 pull-down enable */
+ temp32 = pm2_ioread(0xf6);
+ temp32 |= ((1 << 7) | (1 << 3));
+ pm2_iowrite(0xf6, temp32);
+
+ /* set gpm9 pull-down enable */
+ temp32 = pm2_ioread(0xf8);
+ temp32 |= ((1 << 5) | (1 << 1));
+ pm2_iowrite(0xf8, temp32);
+}
+
+int __init sbx00_acpi_init(void)
+{
+ register_acpi_resource();
+
+ sci_interrupt_setup();
+
+ return 0;
+}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 22+ messages in thread