Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / drivers / macio.c
1 /*
2  *   derived from mol/mol.c,
3  *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
4  *
5  *   This program is free software; you can redistribute it and/or
6  *   modify it under the terms of the GNU General Public License
7  *   version 2
8  *
9  */
10
11 #include "config.h"
12 #include "arch/common/nvram.h"
13 #include "packages/nvram.h"
14 #include "libopenbios/bindings.h"
15 #include "libc/byteorder.h"
16 #include "libc/vsprintf.h"
17
18 #include "drivers/drivers.h"
19 #include "macio.h"
20 #include "cuda.h"
21 #include "escc.h"
22 #include "drivers/pci.h"
23
24 #define OW_IO_NVRAM_SIZE   0x00020000
25 #define OW_IO_NVRAM_OFFSET 0x00060000
26 #define OW_IO_NVRAM_SHIFT  4
27
28 #define NW_IO_NVRAM_SIZE   0x00004000
29 #define NW_IO_NVRAM_OFFSET 0xfff04000
30
31 #define IO_OPENPIC_SIZE    0x00040000
32 #define IO_OPENPIC_OFFSET  0x00040000
33
34 static char *nvram;
35
36 static int macio_nvram_shift(void)
37 {
38         int nvram_flat;
39
40         if (is_oldworld())
41                 return OW_IO_NVRAM_SHIFT;
42
43         nvram_flat = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_FLAT);
44         return nvram_flat ? 0 : 1;
45 }
46
47 int
48 macio_get_nvram_size(void)
49 {
50         int shift = macio_nvram_shift();
51         if (is_oldworld())
52                 return OW_IO_NVRAM_SIZE >> shift;
53         else
54                 return NW_IO_NVRAM_SIZE >> shift;
55 }
56
57 static unsigned long macio_nvram_offset(void)
58 {
59         unsigned long r;
60
61         /* Hypervisor tells us where NVRAM lies */
62         r = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_ADDR);
63         if (r)
64                 return r;
65
66         /* Fall back to hardcoded addresses */
67         if (is_oldworld())
68                 return OW_IO_NVRAM_OFFSET;
69
70         return NW_IO_NVRAM_OFFSET;
71 }
72
73 static unsigned long macio_nvram_size(void)
74 {
75         if (is_oldworld())
76                 return OW_IO_NVRAM_SIZE;
77         else
78                 return NW_IO_NVRAM_SIZE;
79 }
80
81 void macio_nvram_init(const char *path, phys_addr_t addr)
82 {
83         phandle_t chosen, aliases;
84         phandle_t dnode;
85         int props[2];
86         char buf[64];
87         unsigned long nvram_size, nvram_offset;
88
89         nvram_offset = macio_nvram_offset();
90         nvram_size = macio_nvram_size();
91
92         nvram = (char*)addr + nvram_offset;
93         snprintf(buf, sizeof(buf), "%s/nvram", path);
94         nvram_init(buf);
95         dnode = find_dev(buf);
96         set_int_property(dnode, "#bytes", arch_nvram_size() );
97         props[0] = __cpu_to_be32(nvram_offset);
98         props[1] = __cpu_to_be32(nvram_size);
99         set_property(dnode, "reg", (char *)&props, sizeof(props));
100         set_property(dnode, "device_type", "nvram", 6);
101         NEWWORLD(set_property(dnode, "compatible", "nvram,flash", 12));
102
103         chosen = find_dev("/chosen");
104         push_str(buf);
105         fword("open-dev");
106         set_int_property(chosen, "nvram", POP());
107
108         aliases = find_dev("/aliases");
109         set_property(aliases, "nvram", buf, strlen(buf) + 1);
110 }
111
112 #ifdef DUMP_NVRAM
113 static void
114 dump_nvram(void)
115 {
116   int i, j;
117   for (i = 0; i < 10; i++)
118     {
119       for (j = 0; j < 16; j++)
120       printk ("%02x ", nvram[(i*16+j)<<4]);
121       printk (" ");
122       for (j = 0; j < 16; j++)
123         if (isprint(nvram[(i*16+j)<<4]))
124             printk("%c", nvram[(i*16+j)<<4]);
125         else
126           printk(".");
127       printk ("\n");
128       }
129 }
130 #endif
131
132
133 void
134 macio_nvram_put(char *buf)
135 {
136         int i;
137         unsigned int it_shift = macio_nvram_shift();
138
139         for (i=0; i < arch_nvram_size(); i++)
140                 nvram[i << it_shift] = buf[i];
141 #ifdef DUMP_NVRAM
142         printk("new nvram:\n");
143         dump_nvram();
144 #endif
145 }
146
147 void
148 macio_nvram_get(char *buf)
149 {
150         int i;
151         unsigned int it_shift = macio_nvram_shift();
152
153         for (i=0; i< arch_nvram_size(); i++)
154                 buf[i] = nvram[i << it_shift];
155
156 #ifdef DUMP_NVRAM
157         printk("current nvram:\n");
158         dump_nvram();
159 #endif
160 }
161
162 static void
163 openpic_init(const char *path, phys_addr_t addr)
164 {
165         phandle_t dnode;
166         int props[2];
167         char buf[128];
168
169         push_str(path);
170         fword("find-device");
171         fword("new-device");
172         push_str("interrupt-controller");
173         fword("device-name");
174
175         snprintf(buf, sizeof(buf), "%s/interrupt-controller", path);
176         dnode = find_dev(buf);
177         set_property(dnode, "device_type", "open-pic", 9);
178         set_property(dnode, "compatible", "chrp,open-pic", 14);
179         set_property(dnode, "built-in", "", 0);
180         props[0] = __cpu_to_be32(IO_OPENPIC_OFFSET);
181         props[1] = __cpu_to_be32(IO_OPENPIC_SIZE);
182         set_property(dnode, "reg", (char *)&props, sizeof(props));
183         set_int_property(dnode, "#interrupt-cells", 2);
184         set_int_property(dnode, "#address-cells", 0);
185         set_property(dnode, "interrupt-controller", "", 0);
186         set_int_property(dnode, "clock-frequency", 4166666);
187
188         fword("finish-device");
189 }
190
191 DECLARE_NODE(ob_macio, INSTALL_OPEN, sizeof(int), "Tmac-io");
192
193 /* ( str len -- addr ) */
194
195 static void
196 ob_macio_decode_unit(void *private)
197 {
198         ucell addr;
199
200         const char *arg = pop_fstr_copy();
201
202         addr = strtol(arg, NULL, 16);
203
204         free((char*)arg);
205
206         PUSH(addr);
207 }
208
209 /*  ( addr -- str len ) */
210
211 static void
212 ob_macio_encode_unit(void *private)
213 {
214         char buf[8];
215
216         ucell addr = POP();
217
218         snprintf(buf, sizeof(buf), "%x", addr);
219
220         push_str(buf);
221 }
222
223 NODE_METHODS(ob_macio) = {
224         { "decode-unit",        ob_macio_decode_unit    },
225         { "encode-unit",        ob_macio_encode_unit    },
226 };
227
228 static void
229 ob_unin_init(void)
230 {
231         phandle_t dnode;
232         int props[2];
233
234         push_str("/");
235         fword("find-device");
236         fword("new-device");
237         push_str("uni-n");
238         fword("device-name");
239
240         dnode = find_dev("/uni-n");
241         set_property(dnode, "device_type", "memory-controller", 18);
242         set_property(dnode, "compatible", "uni-north", 10);
243         set_int_property(dnode, "device-rev", 0);
244         props[0] = __cpu_to_be32(0xf8000000);
245         props[1] = __cpu_to_be32(0x1000000);
246         set_property(dnode, "reg", (char *)&props, sizeof(props));
247
248         fword("finish-device");
249 }
250
251 void
252 ob_macio_heathrow_init(const char *path, phys_addr_t addr)
253 {
254         phandle_t aliases;
255
256         REGISTER_NODE(ob_macio);
257         aliases = find_dev("/aliases");
258         set_property(aliases, "mac-io", path, strlen(path) + 1);
259
260         cuda_init(path, addr);
261         macio_nvram_init(path, addr);
262         escc_init(path, addr);
263         macio_ide_init(path, addr, 2);
264 }
265
266 void
267 ob_macio_keylargo_init(const char *path, phys_addr_t addr)
268 {
269         phandle_t aliases;
270
271         aliases = find_dev("/aliases");
272         set_property(aliases, "mac-io", path, strlen(path) + 1);
273
274         cuda_init(path, addr);
275         /* The NewWorld NVRAM is not located in the MacIO device */
276         macio_nvram_init("", 0);
277         escc_init(path, addr);
278         macio_ide_init(path, addr, 2);
279         openpic_init(path, addr);
280         ob_unin_init();
281 }