Subject: cell: introduce unions for some special registers found in pervasive area The pervasive area contains some registers, which contain a byte for each spe. Another register contains upper half for ppe and lower half for spe. This patch adds unions, to access either the spe or ppe value easily. Signed-off-by: Christian Krafft Index: linux-2.6/arch/powerpc/platforms/cell/cbe_regs.h =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_regs.h +++ linux-2.6/arch/powerpc/platforms/cell/cbe_regs.h @@ -141,6 +141,20 @@ struct ext_tr_timer { }; }; +union spe_reg { + u64 val; + u8 spe[8]; +}; + +union ppe_spe_reg { + u64 val; + struct { + u32 ppe; + u32 spe; + }; +}; + + struct cbe_pmd_regs { /* Trace Logic Analyzer */ u64 pad_0x0000; /* 0x0000 */ @@ -172,22 +186,22 @@ struct cbe_pmd_regs { u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */ /* Thermal Sensor Registers */ - u64 ts_ctsr1; /* 0x0800 */ + union spe_reg ts_ctsr1; /* 0x0800 */ u64 ts_ctsr2; /* 0x0808 */ - u64 ts_mtsr1; /* 0x0810 */ + union spe_reg ts_mtsr1; /* 0x0810 */ u64 ts_mtsr2; /* 0x0818 */ - u64 ts_itr1; /* 0x0820 */ + union spe_reg ts_itr1; /* 0x0820 */ u64 ts_itr2; /* 0x0828 */ u64 ts_gitr; /* 0x0830 */ u64 ts_isr; /* 0x0838 */ u64 ts_imr; /* 0x0840 */ - u64 tm_cr1; /* 0x0848 */ + union spe_reg tm_cr1; /* 0x0848 */ u64 tm_cr2; /* 0x0850 */ u64 tm_simr; /* 0x0858 */ - u64 tm_tpr; /* 0x0860 */ - u64 tm_str1; /* 0x0868 */ + union ppe_spe_reg tm_tpr; /* 0x0860 */ + union spe_reg tm_str1; /* 0x0868 */ u64 tm_str2; /* 0x0870 */ - u64 tm_tsr; /* 0x0878 */ + union ppe_spe_reg tm_tsr; /* 0x0878 */ /* Power Management */ u64 pmcr; /* 0x0880 */ Index: linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/cbe_thermal.c +++ linux-2.6/arch/powerpc/platforms/cell/cbe_thermal.c @@ -30,22 +30,53 @@ #include "cbe_regs.h" -static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) +static struct cbe_pmd_regs *get_pmd_regs(struct sys_device *sysdev) +{ + struct spu *spu; + + spu = container_of(sysdev, struct spu, sysdev); + + return cbe_get_pmd_regs(spu->devnode); +} +/* returns the value for a given spu in a given register */ +static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg *reg) { - struct spu *spu = container_of(sysdev, struct spu, sysdev); - struct cbe_pmd_regs *pmd_regs; - struct device_node *devnode; - u64 value; unsigned int *id; + union spe_reg value; + struct spu *spu; + + spu = container_of(sysdev, struct spu, sysdev); + id = (unsigned int *)get_property(spu->devnode, "reg", NULL); + value.val = in_be64(®->val); - devnode = spu->devnode; - pmd_regs = cbe_get_pmd_regs(devnode); - value = in_be64(&pmd_regs->ts_ctsr1); + return value.spe[*id]; +} +/* writes the value for a given spu in a given register */ +static void spu_write_register_value(struct sys_device *sysdev, union spe_reg *reg, u8 new_value) +{ + unsigned int *id; + union spe_reg value; + struct spu *spu; + + spu = container_of(sysdev, struct spu, sysdev); id = (unsigned int *)get_property(spu->devnode, "reg", NULL); - /* access the corresponding byte */ - value >>= ((*id)*8); + value.val = in_be64(®->val); + value.spe[*id] = new_value; + + out_be64(®->val, value.val); +} + + +static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) +{ + int value; + struct cbe_pmd_regs *pmd_regs; + + pmd_regs = get_pmd_regs(sysdev); + + value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); /* clear all other bits */ value &= 0x3F; /* temp is stored in steps of 2 degrees */