Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / arch / powerpc / platforms / cell / cbe_regs.c
1 /*
2  * cbe_regs.c
3  *
4  * Accessor routines for the various MMIO register blocks of the CBE
5  *
6  * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
7  */
8
9 #include <linux/percpu.h>
10 #include <linux/types.h>
11
12 #include <asm/io.h>
13 #include <asm/pgtable.h>
14 #include <asm/prom.h>
15 #include <asm/ptrace.h>
16
17 #include "cbe_regs.h"
18
19 #define MAX_CBE         2
20
21 /*
22  * Current implementation uses "cpu" nodes. We build our own mapping
23  * array of cpu numbers to cpu nodes locally for now to allow interrupt
24  * time code to have a fast path rather than call of_get_cpu_node(). If
25  * we implement cpu hotplug, we'll have to install an appropriate norifier
26  * in order to release references to the cpu going away
27  */
28 static struct cbe_regs_map
29 {
30         struct device_node *cpu_node;
31         struct cbe_pmd_regs __iomem *pmd_regs;
32         struct cbe_iic_regs __iomem *iic_regs;
33 } cbe_regs_maps[MAX_CBE];
34 static int cbe_regs_map_count;
35
36 static struct cbe_thread_map
37 {
38         struct device_node *cpu_node;
39         struct cbe_regs_map *regs;
40 } cbe_thread_map[NR_CPUS];
41
42 static struct cbe_regs_map *cbe_find_map(struct device_node *np)
43 {
44         int i;
45
46         for (i = 0; i < cbe_regs_map_count; i++)
47                 if (cbe_regs_maps[i].cpu_node == np)
48                         return &cbe_regs_maps[i];
49         return NULL;
50 }
51
52 struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
53 {
54         struct cbe_regs_map *map = cbe_find_map(np);
55         if (map == NULL)
56                 return NULL;
57         return map->pmd_regs;
58 }
59
60 struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
61 {
62         struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
63         if (map == NULL)
64                 return NULL;
65         return map->pmd_regs;
66 }
67
68
69 struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
70 {
71         struct cbe_regs_map *map = cbe_find_map(np);
72         if (map == NULL)
73                 return NULL;
74         return map->iic_regs;
75 }
76 struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
77 {
78         struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
79         if (map == NULL)
80                 return NULL;
81         return map->iic_regs;
82 }
83
84 void __init cbe_regs_init(void)
85 {
86         int i;
87         struct device_node *cpu;
88
89         /* Build local fast map of CPUs */
90         for_each_possible_cpu(i)
91                 cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
92
93         /* Find maps for each device tree CPU */
94         for_each_node_by_type(cpu, "cpu") {
95                 struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
96
97                 /* That hack must die die die ! */
98                 const struct address_prop {
99                         unsigned long address;
100                         unsigned int len;
101                 } __attribute__((packed)) *prop;
102
103
104                 if (cbe_regs_map_count > MAX_CBE) {
105                         printk(KERN_ERR "cbe_regs: More BE chips than supported"
106                                "!\n");
107                         cbe_regs_map_count--;
108                         return;
109                 }
110                 map->cpu_node = cpu;
111                 for_each_possible_cpu(i)
112                         if (cbe_thread_map[i].cpu_node == cpu)
113                                 cbe_thread_map[i].regs = map;
114
115                 prop = get_property(cpu, "pervasive", NULL);
116                 if (prop != NULL)
117                         map->pmd_regs = ioremap(prop->address, prop->len);
118
119                 prop = get_property(cpu, "iic", NULL);
120                 if (prop != NULL)
121                         map->iic_regs = ioremap(prop->address, prop->len);
122         }
123 }
124