Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 28782
b: refs/heads/master
c: acf7d76
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jun 21, 2006
1 parent 38e2c38 commit f14cd32
Show file tree
Hide file tree
Showing 16 changed files with 506 additions and 147 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef82a306b46dbedaecbb154b24d05dfab937df35
refs/heads/master: acf7d76827a577059636e949079021e6af6dd702
1 change: 1 addition & 0 deletions trunk/arch/powerpc/configs/cell_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ CONFIG_CELL_IIC=y
#
CONFIG_SPU_FS=m
CONFIG_SPUFS_MMAP=y
CONFIG_CBE_RAS=y

#
# Kernel options
Expand Down
29 changes: 29 additions & 0 deletions trunk/arch/powerpc/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,21 @@ label##_pSeries: \
mtspr SPRN_SPRG1,r13; /* save r13 */ \
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)

#define HSTD_EXCEPTION_PSERIES(n, label) \
. = n; \
.globl label##_pSeries; \
label##_pSeries: \
HMT_MEDIUM; \
mtspr SPRN_SPRG1,r20; /* save r20 */ \
mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \
mtspr SPRN_SRR0,r20; \
mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \
mtspr SPRN_SRR1,r20; \
mfspr r20,SPRN_SPRG1; /* restore r20 */ \
mtspr SPRN_SPRG1,r13; /* save r13 */ \
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)


#define STD_EXCEPTION_ISERIES(n, label, area) \
.globl label##_iSeries; \
label##_iSeries: \
Expand Down Expand Up @@ -544,8 +559,17 @@ system_call_pSeries:

STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)

#ifdef CONFIG_CBE_RAS
HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
#endif /* CONFIG_CBE_RAS */
STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
#ifdef CONFIG_CBE_RAS
HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
#endif /* CONFIG_CBE_RAS */
STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
#ifdef CONFIG_CBE_RAS
HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
#endif /* CONFIG_CBE_RAS */

. = 0x3000

Expand Down Expand Up @@ -827,6 +851,11 @@ machine_check_common:
#else
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
#endif
#ifdef CONFIG_CBE_RAS
STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
#endif /* CONFIG_CBE_RAS */

/*
* Here we have detected that the kernel stack pointer is bad.
Expand Down
43 changes: 43 additions & 0 deletions trunk/arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -2105,3 +2105,46 @@ int prom_update_property(struct device_node *np,
return 0;
}


/* Find the device node for a given logical cpu number, also returns the cpu
* local thread number (index in ibm,interrupt-server#s) if relevant and
* asked for (non NULL)
*/
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
{
int hardid;
struct device_node *np;

hardid = get_hard_smp_processor_id(cpu);

for_each_node_by_type(np, "cpu") {
u32 *intserv;
unsigned int plen, t;

/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
* fallback to "reg" property and assume no threads
*/
intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
&plen);
if (intserv == NULL) {
u32 *reg = (u32 *)get_property(np, "reg", NULL);
if (reg == NULL)
continue;
if (*reg == hardid) {
if (thread)
*thread = 0;
return np;
}
} else {
plen /= sizeof(u32);
for (t = 0; t < plen; t++) {
if (hardid == intserv[t]) {
if (thread)
*thread = t;
return np;
}
}
}
}
return NULL;
}
4 changes: 4 additions & 0 deletions trunk/arch/powerpc/platforms/cell/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ config SPUFS_MMAP
select MEMORY_HOTPLUG
default y

config CBE_RAS
bool "RAS features for bare metal Cell BE"
default y

endmenu
3 changes: 2 additions & 1 deletion trunk/arch/powerpc/platforms/cell/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
obj-y += interrupt.o iommu.o setup.o spider-pic.o
obj-y += pervasive.o
obj-y += cbe_regs.o pervasive.o
obj-$(CONFIG_CBE_RAS) += ras.o

obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SPU_FS) += spu-base.o spufs/
Expand Down
128 changes: 128 additions & 0 deletions trunk/arch/powerpc/platforms/cell/cbe_regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* cbe_regs.c
*
* Accessor routines for the various MMIO register blocks of the CBE
*
* (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
*/


#include <linux/config.h>
#include <linux/percpu.h>
#include <linux/types.h>

#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/ptrace.h>

#include "cbe_regs.h"

#define MAX_CBE 2

/*
* Current implementation uses "cpu" nodes. We build our own mapping
* array of cpu numbers to cpu nodes locally for now to allow interrupt
* time code to have a fast path rather than call of_get_cpu_node(). If
* we implement cpu hotplug, we'll have to install an appropriate norifier
* in order to release references to the cpu going away
*/
static struct cbe_regs_map
{
struct device_node *cpu_node;
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_iic_regs __iomem *iic_regs;
} cbe_regs_maps[MAX_CBE];
static int cbe_regs_map_count;

static struct cbe_thread_map
{
struct device_node *cpu_node;
struct cbe_regs_map *regs;
} cbe_thread_map[NR_CPUS];

static struct cbe_regs_map *cbe_find_map(struct device_node *np)
{
int i;

for (i = 0; i < cbe_regs_map_count; i++)
if (cbe_regs_maps[i].cpu_node == np)
return &cbe_regs_maps[i];
return NULL;
}

struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
{
struct cbe_regs_map *map = cbe_find_map(np);
if (map == NULL)
return NULL;
return map->pmd_regs;
}

struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
{
struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
if (map == NULL)
return NULL;
return map->pmd_regs;
}


struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
{
struct cbe_regs_map *map = cbe_find_map(np);
if (map == NULL)
return NULL;
return map->iic_regs;
}
struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
{
struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
if (map == NULL)
return NULL;
return map->iic_regs;
}

void __init cbe_regs_init(void)
{
int i;
struct device_node *cpu;

/* Build local fast map of CPUs */
for_each_cpu(i)
cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);

/* Find maps for each device tree CPU */
for_each_node_by_type(cpu, "cpu") {
struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];

/* That hack must die die die ! */
struct address_prop {
unsigned long address;
unsigned int len;
} __attribute__((packed)) *prop;


if (cbe_regs_map_count > MAX_CBE) {
printk(KERN_ERR "cbe_regs: More BE chips than supported"
"!\n");
cbe_regs_map_count--;
return;
}
map->cpu_node = cpu;
for_each_cpu(i)
if (cbe_thread_map[i].cpu_node == cpu)
cbe_thread_map[i].regs = map;

prop = (struct address_prop *)get_property(cpu, "pervasive",
NULL);
if (prop != NULL)
map->pmd_regs = ioremap(prop->address, prop->len);

prop = (struct address_prop *)get_property(cpu, "iic",
NULL);
if (prop != NULL)
map->iic_regs = ioremap(prop->address, prop->len);
}
}

129 changes: 129 additions & 0 deletions trunk/arch/powerpc/platforms/cell/cbe_regs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* cbe_regs.h
*
* This file is intended to hold the various register definitions for CBE
* on-chip system devices (memory controller, IO controller, etc...)
*
* (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
*/

#ifndef CBE_REGS_H
#define CBE_REGS_H

/*
*
* Some HID register definitions
*
*/

/* CBE specific HID0 bits */
#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul
#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul
#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul


/*
*
* Pervasive unit register definitions
*
*/

struct cbe_pmd_regs {
u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */

/* Thermal Sensor Registers */
u64 ts_ctsr1; /* 0x0800 */
u64 ts_ctsr2; /* 0x0808 */
u64 ts_mtsr1; /* 0x0810 */
u64 ts_mtsr2; /* 0x0818 */
u64 ts_itr1; /* 0x0820 */
u64 ts_itr2; /* 0x0828 */
u64 ts_gitr; /* 0x0830 */
u64 ts_isr; /* 0x0838 */
u64 ts_imr; /* 0x0840 */
u64 tm_cr1; /* 0x0848 */
u64 tm_cr2; /* 0x0850 */
u64 tm_simr; /* 0x0858 */
u64 tm_tpr; /* 0x0860 */
u64 tm_str1; /* 0x0868 */
u64 tm_str2; /* 0x0870 */
u64 tm_tsr; /* 0x0878 */

/* Power Management */
u64 pm_control; /* 0x0880 */
#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
u64 pm_status; /* 0x0888 */

/* Time Base Register */
u64 tbr; /* 0x0890 */

u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */

/* Fault Isolation Registers */
u64 checkstop_fir; /* 0x0c00 */
u64 recoverable_fir;
u64 spec_att_mchk_fir;
u64 fir_mode_reg;
u64 fir_enable_mask;

u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */
};

extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);

/*
*
* IIC unit register definitions
*
*/

struct cbe_iic_pending_bits {
u32 data;
u8 flags;
u8 class;
u8 source;
u8 prio;
};

#define CBE_IIC_IRQ_VALID 0x80
#define CBE_IIC_IRQ_IPI 0x40

struct cbe_iic_thread_regs {
struct cbe_iic_pending_bits pending;
struct cbe_iic_pending_bits pending_destr;
u64 generate;
u64 prio;
};

struct cbe_iic_regs {
u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */

/* IIC interrupt registers */
struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
u64 iic_ir; /* 0x0440 */
u64 iic_is; /* 0x0448 */

u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */

/* IOC FIR */
u64 ioc_fir_reset; /* 0x0500 */
u64 ioc_fir_set;
u64 ioc_checkstop_enable;
u64 ioc_fir_error_mask;
u64 ioc_syserr_enable;
u64 ioc_fir;

u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
};

extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);


/* Init this module early */
extern void cbe_regs_init(void);


#endif /* CBE_REGS_H */
Loading

0 comments on commit f14cd32

Please sign in to comment.