6f904cabf0604bf95245471fd3b58f9019dd8bee
[powerpc.git] / arch / powerpc / platforms / embedded6xx / kvme080.c
1 /*
2  * Board setup routines for KVME080.
3  *
4  * Copyright 2007 Sangmoon Kim <dogoil@etinsys.com>
5  *
6  * This program is free software; you can redistribute  it and/or modify it
7  * under  the terms of  the GNU General  Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  */
11
12 #include <linux/initrd.h>
13 #include <linux/delay.h>
14 #include <linux/ide.h>
15 #include <linux/root_dev.h>
16 #include <linux/bcd.h>
17 #include <linux/mc146818rtc.h>
18
19 #include <asm/time.h>
20 #include <asm/i8259.h>
21 #include <asm/udbg.h>
22 #include <asm/mpic.h>
23
24 static unsigned char *nvram_base = (unsigned char *)NULL;
25 static ssize_t nvram_size = 0;
26
27 static int __init
28 kvme080_probe(void)
29 {
30         unsigned long root = of_get_flat_dt_root();
31
32         if (of_flat_dt_is_compatible(root, "kvme080"))
33                 return 1;
34         return 0;
35 }
36
37 static int __init
38 kvme080_setup_pci(struct device_node *dnp)
39 {
40         int len;
41         struct pci_controller *hose;
42         int *bus_range;
43
44         bus_range = (int *) get_property(dnp, "bus-range", &len);
45         if (bus_range == NULL || len < 2 * sizeof(int))
46                 printk(KERN_WARNING "Can't get bus-range for %s, assume"
47                                 " bus 0\n", dnp->full_name);
48
49         hose = pcibios_alloc_controller();
50         if (hose == NULL) {
51                 printk("PCI Host bridge init failed\n");
52                 return -ENOMEM;
53         }
54         hose->arch_data = dnp;
55         hose->first_busno = bus_range ? bus_range[0] : 0;
56         hose->last_busno = bus_range ? bus_range[1] : 0xff;
57         hose->set_cfg_type = 1;
58         setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
59
60         printk(KERN_INFO "Found PCI host bridge %s", dnp->full_name);
61
62         /* Interpret the "ranges" property */
63         /* This also maps the I/O region and sets isa_io/mem_base */
64         pci_process_bridge_OF_ranges(hose, dnp, 1);
65         return 0;
66 }
67
68 static void __init
69 kvme080_setup_arch(void)
70 {
71         struct device_node *dnp;
72         const u32 *prop;
73         u64 size;
74         phys_addr_t paddr;
75
76 #ifdef CONFIG_BLK_DEV_INITRD
77         if (initrd_start)
78                 ROOT_DEV = Root_RAM0;
79         else
80 #endif
81 #ifdef  CONFIG_ROOT_NFS
82                 ROOT_DEV = Root_NFS;
83 #else
84                 ROOT_DEV = Root_HDA1;
85 #endif
86         for (dnp = NULL; (dnp=of_find_node_by_type(dnp,"pci")) != NULL;)
87                 kvme080_setup_pci(dnp);
88
89         dnp = of_find_node_by_type(NULL, "nvram");
90         if (dnp) {
91                 prop = of_get_address(dnp, 0, &size, NULL);
92                 paddr = (phys_addr_t)of_translate_address(dnp, prop);
93                 if (paddr != (phys_addr_t)OF_BAD_ADDR) {
94                         nvram_size = (ssize_t) size;
95                         nvram_base = ioremap(paddr, nvram_size);
96                 }
97         }
98
99         printk(KERN_INFO "Etin Systems KVME080 Board\n");
100         printk(KERN_INFO "Port by Sangmoon Kim (dogoil@etinsys.com)\n");
101 }
102
103 static void __init
104 kvme080_init_IRQ(void)
105 {
106         struct mpic *mpic;
107         struct device_node *dnp;
108         const u32 *prop;
109         int size;
110         phys_addr_t paddr;
111
112         dnp = of_find_node_by_type(NULL, "open-pic");
113         if (dnp == NULL)
114                 return;
115
116         prop = of_get_address(dnp, 0, NULL, NULL);
117         paddr = (phys_addr_t)of_translate_address(dnp, prop);
118
119         mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 0, 0,
120                           "EPIC");
121
122         prop = (u32 *)get_property(dnp, "serial-mode", &size);
123         if (prop != NULL)
124                 mpic_set_serial_int(mpic, *(u32 *)prop);
125
126         mpic_assign_isu(mpic, 0, paddr + 0x10200);
127         mpic_init(mpic);
128 }
129
130 static void
131 kvme080_restart(char *cmd)
132 {
133         unsigned long srr;
134
135         local_irq_disable();
136         asm volatile(
137         " lis %0,0xfff0\n \
138           ori %0,%0,0x0100\n \
139           mtspr 26,%0\n \
140           sync\n \
141           lis %0,0x0000\n \
142           ori %0,%0,0x0000\n \
143           mtspr 27,%0\n \
144           sync\n \
145           rfi "
146           : "=r" (srr));
147 }
148
149 static void
150 kvme080_power_off(void)
151 {
152         local_irq_disable();
153         for(;;);        /* No way to shut power off with software */
154         /* NOTREACHED */
155 }
156
157 static void
158 kvme080_halt(void)
159 {
160         kvme080_power_off();
161         /* NOTREACHED */
162 }
163
164 extern spinlock_t rtc_lock;
165 static unsigned char *rtc_base = (unsigned char*)NULL;
166
167 static long __init
168 kvme080_time_init(void)
169 {
170         char val;
171         struct device_node *dnp;
172         const u32 *prop;
173         u64 size;
174         phys_addr_t paddr;
175
176         dnp = of_find_node_by_type(NULL, "rtc");
177         if (!dnp)
178                 return -1;
179
180         prop = of_get_address(dnp, 0, &size, NULL);
181         if (!prop)
182                 return -1;
183
184         paddr = (phys_addr_t)of_translate_address(dnp, prop);
185         if (paddr == (phys_addr_t)OF_BAD_ADDR)
186                 return -1;
187
188         rtc_base = (unsigned char *)ioremap(paddr, (ssize_t)size);
189
190         if(!rtc_base)
191                 return -1;
192
193         spin_lock(&rtc_lock);
194         val = readb(rtc_base);
195         if (val & 0xc0)
196                 writeb(val & 0x3f, rtc_base);
197         spin_unlock(&rtc_lock);
198
199         return 0;
200 }
201
202 static int
203 kvme080_set_rtc_time(struct rtc_time *tp)
204 {
205         if (!rtc_base)
206                 return -1;
207
208         spin_lock(&rtc_lock);
209
210         writeb(readb(rtc_base) | 0x80, rtc_base);
211
212         writeb(BIN2BCD(tp->tm_sec), rtc_base + 1);
213         writeb(BIN2BCD(tp->tm_min), rtc_base + 2);
214         writeb(BIN2BCD(tp->tm_hour), rtc_base + 3);
215         writeb(BIN2BCD(tp->tm_mday), rtc_base + 5);
216         writeb(BIN2BCD(tp->tm_mon), rtc_base + 6);
217         writeb(BIN2BCD(tp->tm_year % 100), rtc_base + 7);
218
219         writeb((readb(rtc_base) & 0x40) |
220                BIN2BCD((tp->tm_year < 100) ? 20 : 21), rtc_base);
221
222         spin_unlock(&rtc_lock);
223
224         return 0;
225 }
226
227 static void
228 kvme080_get_rtc_time(struct rtc_time *tp)
229 {
230         if (!rtc_base)
231                 return;
232
233         spin_lock(&rtc_lock);
234
235         writeb(readb(rtc_base) | 0x40, rtc_base);
236
237         tp->tm_sec = readb(rtc_base + 1) & 0x7f;
238         tp->tm_min = readb(rtc_base + 2) & 0x7f;
239         tp->tm_hour = readb(rtc_base + 3) & 0x3f;
240         tp->tm_mday = readb(rtc_base + 5) & 0x3f;
241         tp->tm_mon = readb(rtc_base + 6) & 0x1f;
242         tp->tm_year = readb(rtc_base + 7) & 0xff;
243
244         writeb(readb(rtc_base) & ~0x40, rtc_base);
245
246         tp->tm_sec = BCD2BIN(tp->tm_sec);
247         tp->tm_min = BCD2BIN(tp->tm_min);
248         tp->tm_hour = BCD2BIN(tp->tm_hour);
249         tp->tm_mday = BCD2BIN(tp->tm_mday);
250         tp->tm_mon = BCD2BIN(tp->tm_mon);
251         tp->tm_year = BCD2BIN(tp->tm_year);
252
253         if (tp->tm_year < 80)
254                 tp->tm_year += 100;
255
256         spin_unlock(&rtc_lock);
257 }
258
259 static unsigned char
260 kvme080_nvram_read_val(int addr)
261 {
262         if (!nvram_base)
263                 return 0;
264         return readb(nvram_base + addr);
265 }
266
267 static void
268 kvme080_nvram_write_val(int addr, unsigned char val)
269 {
270         if (!nvram_base)
271                 return;
272         writeb(val, nvram_base + addr);
273 }
274
275 static ssize_t
276 kvme080_nvram_size(void)
277 {
278         return nvram_size;
279 }
280
281 define_machine(kvme080) {
282         .name                   = "kvme080",
283         .probe                  = kvme080_probe,
284         .setup_arch             = kvme080_setup_arch,
285         .init_IRQ               = kvme080_init_IRQ,
286         .get_irq                = mpic_get_irq,
287         .restart                = kvme080_restart,
288         .power_off              = kvme080_power_off,
289         .halt                   = kvme080_halt,
290         .time_init              = kvme080_time_init,
291         .set_rtc_time           = kvme080_set_rtc_time,
292         .get_rtc_time           = kvme080_get_rtc_time,
293         .calibrate_decr         = generic_calibrate_decr,
294         .nvram_read_val         = kvme080_nvram_read_val,
295         .nvram_write_val        = kvme080_nvram_write_val,
296         .nvram_size             = kvme080_nvram_size,
297         .progress               = udbg_progress,
298 };