Loading arch/powerpc/configs/cell_defconfig +29 −28 Original line number Diff line number Diff line # # Automatically generated make config: don't edit # Linux kernel version: 2.6.21-rc3 # Fri Mar 9 23:34:53 2007 # Linux kernel version: 2.6.21-rc6 # Mon Apr 23 20:46:48 2007 # CONFIG_PPC64=y CONFIG_64BIT=y Loading Loading @@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set # CONFIG_PPC_PASEMI is not set CONFIG_PPC_CELLEB=y CONFIG_PPC_PS3=y # # PS3 Platform Options # # CONFIG_PS3_ADVANCED is not set CONFIG_PS3_HTAB_SIZE=20 # CONFIG_PS3_DYNAMIC_DMA is not set CONFIG_PS3_USE_LPAR_ADDR=y CONFIG_PS3_VUART=y CONFIG_PS3_PS3AV=y CONFIG_PS3_SYS_MANAGER=y CONFIG_PPC_CELL=y CONFIG_PPC_CELL_NATIVE=y CONFIG_PPC_IBM_CELL_BLADE=y CONFIG_PPC_PS3=y CONFIG_PPC_CELLEB=y # # Cell Broadband Engine options # CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y CONFIG_CBE_THERM=m CONFIG_CBE_CPUFREQ=m CONFIG_PPC_NATIVE=y CONFIG_UDBG_RTAS_CONSOLE=y CONFIG_PPC_UDBG_BEAT=y Loading Loading @@ -174,26 +194,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_WANT_EARLY_SERIAL is not set CONFIG_MPIC=y # # Cell Broadband Engine options # CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y CONFIG_CBE_THERM=m CONFIG_CBE_CPUFREQ=m # # PS3 Platform Options # # CONFIG_PS3_ADVANCED is not set CONFIG_PS3_HTAB_SIZE=20 # CONFIG_PS3_DYNAMIC_DMA is not set CONFIG_PS3_USE_LPAR_ADDR=y CONFIG_PS3_VUART=y CONFIG_PS3_PS3AV=y CONFIG_PS3_SYS_MANAGER=y # # Kernel options # Loading Loading @@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_ALI15X3 is not set Loading @@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set CONFIG_BLK_DEV_IDE_CELLEB=y CONFIG_BLK_DEV_CELLEB=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # Loading Loading @@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_RTAS=y # CONFIG_HVC_BEAT is not set CONFIG_HVC_BEAT=y # # IPMI Loading Loading @@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m # Distributed Lock Manager # # CONFIG_DLM is not set # CONFIG_UCC_SLOW is not set # CONFIG_UCC_FAST is not set # # Library routines Loading Loading @@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y Loading arch/powerpc/oprofile/op_model_cell.c +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <asm/system.h> #include "../platforms/cell/interrupt.h" #include "../platforms/cell/cbe_regs.h" #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying Loading arch/powerpc/platforms/cell/cbe_cpufreq.c +80 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <asm/processor.h> #include <asm/prom.h> #include <asm/time.h> #include <asm/pmi.h> #include <asm/of_platform.h> #include "cbe_regs.h" Loading Loading @@ -68,6 +70,38 @@ static u64 MIC_Slow_Next_Timer_table[] = { * hardware specific functions */ static struct of_device *pmi_dev; static int set_pmode_pmi(int cpu, unsigned int pmode) { int ret; pmi_message_t pmi_msg; #ifdef DEBUG u64 time; #endif pmi_msg.type = PMI_TYPE_FREQ_CHANGE; pmi_msg.data1 = cbe_cpu_to_node(cpu); pmi_msg.data2 = pmode; #ifdef DEBUG time = (u64) get_cycles(); #endif pmi_send_message(pmi_dev, pmi_msg); ret = pmi_msg.data2; pr_debug("PMI returned slow mode %d\n", ret); #ifdef DEBUG time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */ time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */ pr_debug("had to wait %lu ns for a transition\n", time); #endif return ret; } static int get_pmode(int cpu) { int ret; Loading @@ -79,7 +113,7 @@ static int get_pmode(int cpu) return ret; } static int set_pmode(int cpu, unsigned int pmode) static int set_pmode_reg(int cpu, unsigned int pmode) { struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; Loading Loading @@ -120,6 +154,39 @@ static int set_pmode(int cpu, unsigned int pmode) return 0; } static int set_pmode(int cpu, unsigned int slow_mode) { if(pmi_dev) return set_pmode_pmi(cpu, slow_mode); else return set_pmode_reg(cpu, slow_mode); } static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) { struct cpufreq_policy policy; u8 cpu; u8 cbe_pmode_new; BUG_ON (pmi_msg.type != PMI_TYPE_FREQ_CHANGE); cpu = cbe_node_to_cpu(pmi_msg.data1); cbe_pmode_new = pmi_msg.data2; cpufreq_get_policy(&policy, cpu); policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); policy.min = min(policy.min, policy.max); pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); cpufreq_set_policy(&policy); } static struct pmi_handler cbe_pmi_handler = { .type = PMI_TYPE_FREQ_CHANGE, .handle_pmi_message = cbe_cpufreq_handle_pmi, }; /* * cpufreq functions */ Loading Loading @@ -234,11 +301,23 @@ static struct cpufreq_driver cbe_cpufreq_driver = { static int __init cbe_cpufreq_init(void) { struct device_node *np; np = of_find_node_by_type(NULL, "ibm,pmi"); pmi_dev = of_find_device_by_node(np); if (pmi_dev) pmi_register_handler(pmi_dev, &cbe_pmi_handler); return cpufreq_register_driver(&cbe_cpufreq_driver); } static void __exit cbe_cpufreq_exit(void) { if(pmi_dev) pmi_unregister_handler(pmi_dev, &cbe_pmi_handler); cpufreq_unregister_driver(&cbe_cpufreq_driver); } Loading arch/powerpc/platforms/cell/cbe_regs.c +124 −41 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <asm/pgtable.h> #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/of_device.h> #include <asm/of_platform.h> #include "cbe_regs.h" Loading @@ -27,6 +29,7 @@ static struct cbe_regs_map { struct device_node *cpu_node; struct device_node *be_node; struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; Loading @@ -37,30 +40,43 @@ static int cbe_regs_map_count; static struct cbe_thread_map { struct device_node *cpu_node; struct device_node *be_node; struct cbe_regs_map *regs; unsigned int thread_id; unsigned int cbe_id; } cbe_thread_map[NR_CPUS]; static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; struct device_node *tmp_np; if (strcasecmp(np->type, "spe") == 0) { if (np->data == NULL) { /* walk up path until cpu node was found */ tmp_np = np->parent; while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) if (strcasecmp(np->type, "spe")) { for (i = 0; i < cbe_regs_map_count; i++) if (cbe_regs_maps[i].cpu_node == np || cbe_regs_maps[i].be_node == np) return &cbe_regs_maps[i]; return NULL; } if (np->data) return np->data; /* walk up path until cpu or be node was found */ tmp_np = np; do { tmp_np = tmp_np->parent; /* on a correct devicetree we wont get up to root */ BUG_ON(!tmp_np); } while (strcasecmp(tmp_np->type, "cpu") && strcasecmp(tmp_np->type, "be")); np->data = cbe_find_map(tmp_np); } return np->data; } for (i = 0; i < cbe_regs_map_count; i++) if (cbe_regs_maps[i].cpu_node == np) return &cbe_regs_maps[i]; return NULL; return np->data; } struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) Loading Loading @@ -130,49 +146,69 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); /* FIXME * This is little more than a stub at the moment. It should be * fleshed out so that it works for both SMT and non-SMT, no * matter if the passed cpu is odd or even. * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. * For SMT disabled, returns 0 for all cpus. */ u32 cbe_get_hw_thread_id(int cpu) { return (cpu & 1); return cbe_thread_map[cpu].thread_id; } EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); void __init cbe_regs_init(void) u32 cbe_cpu_to_node(int cpu) { int i; struct device_node *cpu; return cbe_thread_map[cpu].cbe_id; } EXPORT_SYMBOL_GPL(cbe_cpu_to_node); /* Build local fast map of CPUs */ for_each_possible_cpu(i) cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); u32 cbe_node_to_cpu(int node) { return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); } EXPORT_SYMBOL_GPL(cbe_node_to_cpu); /* 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++]; static struct device_node *cbe_get_be_node(int cpu_id) { struct device_node *np; for_each_node_by_type (np, "be") { int len,i; const phandle *cpu_handle; cpu_handle = of_get_property(np, "cpus", &len); for (i=0; i<len; i++) if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) return np; } return NULL; } void __init cbe_fill_regs_map(struct cbe_regs_map *map) { if(map->be_node) { struct device_node *be, *np; be = map->be_node; for_each_node_by_type(np, "pervasive") if (of_get_parent(np) == be) map->pmd_regs = of_iomap(np, 0); for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") if (of_get_parent(np) == be) map->iic_regs = of_iomap(np, 2); for_each_node_by_type(np, "mic-tm") if (of_get_parent(np) == be) map->mic_tm_regs = of_iomap(np, 0); } else { struct device_node *cpu; /* That hack must die die die ! */ const 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_possible_cpu(i) if (cbe_thread_map[i].cpu_node == cpu) cbe_thread_map[i].regs = map; cpu = map->cpu_node; prop = of_get_property(cpu, "pervasive", NULL); if (prop != NULL) Loading @@ -188,3 +224,50 @@ void __init cbe_regs_init(void) } } void __init cbe_regs_init(void) { int i; unsigned int thread_id; struct device_node *cpu; /* Build local fast map of CPUs */ for_each_possible_cpu(i) { cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); cbe_thread_map[i].be_node = cbe_get_be_node(i); cbe_thread_map[i].thread_id = thread_id; } /* Find maps for each device tree CPU */ for_each_node_by_type(cpu, "cpu") { struct cbe_regs_map *map; unsigned int cbe_id; cbe_id = cbe_regs_map_count++; map = &cbe_regs_maps[cbe_id]; 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_possible_cpu(i) { struct cbe_thread_map *thread = &cbe_thread_map[i]; if (thread->cpu_node == cpu) { thread->regs = map; thread->cbe_id = cbe_id; map->be_node = thread->be_node; cpu_set(i, cbe_local_mask[cbe_id]); if(thread->thread_id == 0) cpu_set(i, cbe_first_online_cpu); } } cbe_fill_regs_map(map); } } arch/powerpc/platforms/cell/cbe_regs.h +5 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); /* some utility functions to deal with SMT */ extern u32 cbe_get_hw_thread_id(int cpu); extern u32 cbe_cpu_to_node(int cpu); extern u32 cbe_node_to_cpu(int node); /* Init this module early */ extern void cbe_regs_init(void); Loading Loading
arch/powerpc/configs/cell_defconfig +29 −28 Original line number Diff line number Diff line # # Automatically generated make config: don't edit # Linux kernel version: 2.6.21-rc3 # Fri Mar 9 23:34:53 2007 # Linux kernel version: 2.6.21-rc6 # Mon Apr 23 20:46:48 2007 # CONFIG_PPC64=y CONFIG_64BIT=y Loading Loading @@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set # CONFIG_PPC_PASEMI is not set CONFIG_PPC_CELLEB=y CONFIG_PPC_PS3=y # # PS3 Platform Options # # CONFIG_PS3_ADVANCED is not set CONFIG_PS3_HTAB_SIZE=20 # CONFIG_PS3_DYNAMIC_DMA is not set CONFIG_PS3_USE_LPAR_ADDR=y CONFIG_PS3_VUART=y CONFIG_PS3_PS3AV=y CONFIG_PS3_SYS_MANAGER=y CONFIG_PPC_CELL=y CONFIG_PPC_CELL_NATIVE=y CONFIG_PPC_IBM_CELL_BLADE=y CONFIG_PPC_PS3=y CONFIG_PPC_CELLEB=y # # Cell Broadband Engine options # CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y CONFIG_CBE_THERM=m CONFIG_CBE_CPUFREQ=m CONFIG_PPC_NATIVE=y CONFIG_UDBG_RTAS_CONSOLE=y CONFIG_PPC_UDBG_BEAT=y Loading Loading @@ -174,26 +194,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # CONFIG_WANT_EARLY_SERIAL is not set CONFIG_MPIC=y # # Cell Broadband Engine options # CONFIG_SPU_FS=m CONFIG_SPU_BASE=y CONFIG_CBE_RAS=y CONFIG_CBE_THERM=m CONFIG_CBE_CPUFREQ=m # # PS3 Platform Options # # CONFIG_PS3_ADVANCED is not set CONFIG_PS3_HTAB_SIZE=20 # CONFIG_PS3_DYNAMIC_DMA is not set CONFIG_PS3_USE_LPAR_ADDR=y CONFIG_PS3_VUART=y CONFIG_PS3_PS3AV=y CONFIG_PS3_SYS_MANAGER=y # # Kernel options # Loading Loading @@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_ALI15X3 is not set Loading @@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set CONFIG_BLK_DEV_IDE_CELLEB=y CONFIG_BLK_DEV_CELLEB=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # Loading Loading @@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_RTAS=y # CONFIG_HVC_BEAT is not set CONFIG_HVC_BEAT=y # # IPMI Loading Loading @@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m # Distributed Lock Manager # # CONFIG_DLM is not set # CONFIG_UCC_SLOW is not set # CONFIG_UCC_FAST is not set # # Library routines Loading Loading @@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y Loading
arch/powerpc/oprofile/op_model_cell.c +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <asm/system.h> #include "../platforms/cell/interrupt.h" #include "../platforms/cell/cbe_regs.h" #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying Loading
arch/powerpc/platforms/cell/cbe_cpufreq.c +80 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <asm/processor.h> #include <asm/prom.h> #include <asm/time.h> #include <asm/pmi.h> #include <asm/of_platform.h> #include "cbe_regs.h" Loading Loading @@ -68,6 +70,38 @@ static u64 MIC_Slow_Next_Timer_table[] = { * hardware specific functions */ static struct of_device *pmi_dev; static int set_pmode_pmi(int cpu, unsigned int pmode) { int ret; pmi_message_t pmi_msg; #ifdef DEBUG u64 time; #endif pmi_msg.type = PMI_TYPE_FREQ_CHANGE; pmi_msg.data1 = cbe_cpu_to_node(cpu); pmi_msg.data2 = pmode; #ifdef DEBUG time = (u64) get_cycles(); #endif pmi_send_message(pmi_dev, pmi_msg); ret = pmi_msg.data2; pr_debug("PMI returned slow mode %d\n", ret); #ifdef DEBUG time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */ time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */ pr_debug("had to wait %lu ns for a transition\n", time); #endif return ret; } static int get_pmode(int cpu) { int ret; Loading @@ -79,7 +113,7 @@ static int get_pmode(int cpu) return ret; } static int set_pmode(int cpu, unsigned int pmode) static int set_pmode_reg(int cpu, unsigned int pmode) { struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; Loading Loading @@ -120,6 +154,39 @@ static int set_pmode(int cpu, unsigned int pmode) return 0; } static int set_pmode(int cpu, unsigned int slow_mode) { if(pmi_dev) return set_pmode_pmi(cpu, slow_mode); else return set_pmode_reg(cpu, slow_mode); } static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) { struct cpufreq_policy policy; u8 cpu; u8 cbe_pmode_new; BUG_ON (pmi_msg.type != PMI_TYPE_FREQ_CHANGE); cpu = cbe_node_to_cpu(pmi_msg.data1); cbe_pmode_new = pmi_msg.data2; cpufreq_get_policy(&policy, cpu); policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); policy.min = min(policy.min, policy.max); pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); cpufreq_set_policy(&policy); } static struct pmi_handler cbe_pmi_handler = { .type = PMI_TYPE_FREQ_CHANGE, .handle_pmi_message = cbe_cpufreq_handle_pmi, }; /* * cpufreq functions */ Loading Loading @@ -234,11 +301,23 @@ static struct cpufreq_driver cbe_cpufreq_driver = { static int __init cbe_cpufreq_init(void) { struct device_node *np; np = of_find_node_by_type(NULL, "ibm,pmi"); pmi_dev = of_find_device_by_node(np); if (pmi_dev) pmi_register_handler(pmi_dev, &cbe_pmi_handler); return cpufreq_register_driver(&cbe_cpufreq_driver); } static void __exit cbe_cpufreq_exit(void) { if(pmi_dev) pmi_unregister_handler(pmi_dev, &cbe_pmi_handler); cpufreq_unregister_driver(&cbe_cpufreq_driver); } Loading
arch/powerpc/platforms/cell/cbe_regs.c +124 −41 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <asm/pgtable.h> #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/of_device.h> #include <asm/of_platform.h> #include "cbe_regs.h" Loading @@ -27,6 +29,7 @@ static struct cbe_regs_map { struct device_node *cpu_node; struct device_node *be_node; struct cbe_pmd_regs __iomem *pmd_regs; struct cbe_iic_regs __iomem *iic_regs; struct cbe_mic_tm_regs __iomem *mic_tm_regs; Loading @@ -37,30 +40,43 @@ static int cbe_regs_map_count; static struct cbe_thread_map { struct device_node *cpu_node; struct device_node *be_node; struct cbe_regs_map *regs; unsigned int thread_id; unsigned int cbe_id; } cbe_thread_map[NR_CPUS]; static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; struct device_node *tmp_np; if (strcasecmp(np->type, "spe") == 0) { if (np->data == NULL) { /* walk up path until cpu node was found */ tmp_np = np->parent; while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) if (strcasecmp(np->type, "spe")) { for (i = 0; i < cbe_regs_map_count; i++) if (cbe_regs_maps[i].cpu_node == np || cbe_regs_maps[i].be_node == np) return &cbe_regs_maps[i]; return NULL; } if (np->data) return np->data; /* walk up path until cpu or be node was found */ tmp_np = np; do { tmp_np = tmp_np->parent; /* on a correct devicetree we wont get up to root */ BUG_ON(!tmp_np); } while (strcasecmp(tmp_np->type, "cpu") && strcasecmp(tmp_np->type, "be")); np->data = cbe_find_map(tmp_np); } return np->data; } for (i = 0; i < cbe_regs_map_count; i++) if (cbe_regs_maps[i].cpu_node == np) return &cbe_regs_maps[i]; return NULL; return np->data; } struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) Loading Loading @@ -130,49 +146,69 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); /* FIXME * This is little more than a stub at the moment. It should be * fleshed out so that it works for both SMT and non-SMT, no * matter if the passed cpu is odd or even. * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. * For SMT disabled, returns 0 for all cpus. */ u32 cbe_get_hw_thread_id(int cpu) { return (cpu & 1); return cbe_thread_map[cpu].thread_id; } EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); void __init cbe_regs_init(void) u32 cbe_cpu_to_node(int cpu) { int i; struct device_node *cpu; return cbe_thread_map[cpu].cbe_id; } EXPORT_SYMBOL_GPL(cbe_cpu_to_node); /* Build local fast map of CPUs */ for_each_possible_cpu(i) cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); u32 cbe_node_to_cpu(int node) { return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); } EXPORT_SYMBOL_GPL(cbe_node_to_cpu); /* 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++]; static struct device_node *cbe_get_be_node(int cpu_id) { struct device_node *np; for_each_node_by_type (np, "be") { int len,i; const phandle *cpu_handle; cpu_handle = of_get_property(np, "cpus", &len); for (i=0; i<len; i++) if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) return np; } return NULL; } void __init cbe_fill_regs_map(struct cbe_regs_map *map) { if(map->be_node) { struct device_node *be, *np; be = map->be_node; for_each_node_by_type(np, "pervasive") if (of_get_parent(np) == be) map->pmd_regs = of_iomap(np, 0); for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") if (of_get_parent(np) == be) map->iic_regs = of_iomap(np, 2); for_each_node_by_type(np, "mic-tm") if (of_get_parent(np) == be) map->mic_tm_regs = of_iomap(np, 0); } else { struct device_node *cpu; /* That hack must die die die ! */ const 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_possible_cpu(i) if (cbe_thread_map[i].cpu_node == cpu) cbe_thread_map[i].regs = map; cpu = map->cpu_node; prop = of_get_property(cpu, "pervasive", NULL); if (prop != NULL) Loading @@ -188,3 +224,50 @@ void __init cbe_regs_init(void) } } void __init cbe_regs_init(void) { int i; unsigned int thread_id; struct device_node *cpu; /* Build local fast map of CPUs */ for_each_possible_cpu(i) { cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); cbe_thread_map[i].be_node = cbe_get_be_node(i); cbe_thread_map[i].thread_id = thread_id; } /* Find maps for each device tree CPU */ for_each_node_by_type(cpu, "cpu") { struct cbe_regs_map *map; unsigned int cbe_id; cbe_id = cbe_regs_map_count++; map = &cbe_regs_maps[cbe_id]; 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_possible_cpu(i) { struct cbe_thread_map *thread = &cbe_thread_map[i]; if (thread->cpu_node == cpu) { thread->regs = map; thread->cbe_id = cbe_id; map->be_node = thread->be_node; cpu_set(i, cbe_local_mask[cbe_id]); if(thread->thread_id == 0) cpu_set(i, cbe_first_online_cpu); } } cbe_fill_regs_map(map); } }
arch/powerpc/platforms/cell/cbe_regs.h +5 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); /* some utility functions to deal with SMT */ extern u32 cbe_get_hw_thread_id(int cpu); extern u32 cbe_cpu_to_node(int cpu); extern u32 cbe_node_to_cpu(int node); /* Init this module early */ extern void cbe_regs_init(void); Loading