aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/dcr.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:24:53 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 00:08:25 -0500
commit4c75a6f441cdd1c69a6c173bc7944e12c2ba6f84 (patch)
tree260e01e5cbd46d335a3d44b60c34dee51e053774 /arch/powerpc/sysdev/dcr.c
parent69108cf00679716bcab58acb3135390654c5bb99 (diff)
[POWERPC] Generic DCR infrastructure
This patch adds new dcr_map/dcr_read/dcr_write accessors for DCRs that can be used by drivers to transparently address either native DCRs or memory mapped DCRs. The implementation for memory mapped DCRs is done after the binding being currently worked on for SLOF and the Axon chipset. This patch enables it for the cell native platform Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev/dcr.c')
-rw-r--r--arch/powerpc/sysdev/dcr.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
new file mode 100644
index 000000000000..dffeeaeca1d9
--- /dev/null
+++ b/arch/powerpc/sysdev/dcr.c
@@ -0,0 +1,137 @@
1/*
2 * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
3 * <benh@kernel.crashing.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#undef DEBUG
21
22#include <linux/kernel.h>
23#include <asm/prom.h>
24#include <asm/dcr.h>
25
26unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
27{
28 unsigned int ds;
29 const u32 *dr = get_property(np, "dcr-reg", &ds);
30
31 if (dr == NULL || ds & 1 || index >= (ds / 8))
32 return 0;
33
34 return dr[index * 2];
35}
36
37unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
38{
39 unsigned int ds;
40 const u32 *dr = get_property(np, "dcr-reg", &ds);
41
42 if (dr == NULL || ds & 1 || index >= (ds / 8))
43 return 0;
44
45 return dr[index * 2 + 1];
46}
47
48#ifndef CONFIG_PPC_DCR_NATIVE
49
50static struct device_node * find_dcr_parent(struct device_node * node)
51{
52 struct device_node *par, *tmp;
53 const u32 *p;
54
55 for (par = of_node_get(node); par;) {
56 if (get_property(par, "dcr-controller", NULL))
57 break;
58 p = get_property(par, "dcr-parent", NULL);
59 tmp = par;
60 if (p == NULL)
61 par = of_get_parent(par);
62 else
63 par = of_find_node_by_phandle(*p);
64 of_node_put(tmp);
65 }
66 return par;
67}
68
69u64 of_translate_dcr_address(struct device_node *dev,
70 unsigned int dcr_n,
71 unsigned int *out_stride)
72{
73 struct device_node *dp;
74 const u32 *p;
75 unsigned int stride;
76 u64 ret;
77
78 dp = find_dcr_parent(dev);
79 if (dp == NULL)
80 return OF_BAD_ADDR;
81
82 /* Stride is not properly defined yet, default to 0x10 for Axon */
83 p = get_property(dp, "dcr-mmio-stride", NULL);
84 stride = (p == NULL) ? 0x10 : *p;
85
86 /* XXX FIXME: Which property name is to use of the 2 following ? */
87 p = get_property(dp, "dcr-mmio-range", NULL);
88 if (p == NULL)
89 p = get_property(dp, "dcr-mmio-space", NULL);
90 if (p == NULL)
91 return OF_BAD_ADDR;
92
93 /* Maybe could do some better range checking here */
94 ret = of_translate_address(dp, p);
95 if (ret != OF_BAD_ADDR)
96 ret += (u64)(stride) * (u64)dcr_n;
97 if (out_stride)
98 *out_stride = stride;
99 return ret;
100}
101
102dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
103 unsigned int dcr_c)
104{
105 dcr_host_t ret = { .token = NULL, .stride = 0 };
106 u64 addr;
107
108 pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
109 dev->full_name, dcr_n, dcr_c);
110
111 addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
112 pr_debug("translates to addr: 0x%lx, stride: 0x%x\n",
113 addr, ret.stride);
114 if (addr == OF_BAD_ADDR)
115 return ret;
116 pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride);
117 ret.token = ioremap(addr, dcr_c * ret.stride);
118 if (ret.token == NULL)
119 return ret;
120 pr_debug("mapped at 0x%p -> base is 0x%p\n",
121 ret.token, ret.token - dcr_n * ret.stride);
122 ret.token -= dcr_n * ret.stride;
123 return ret;
124}
125
126void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
127{
128 dcr_host_t h = host;
129
130 if (h.token == NULL)
131 return;
132 h.token -= dcr_n * h.stride;
133 iounmap(h.token);
134 h.token = NULL;
135}
136
137#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */