2 * Board setup routines for KVME080.
4 * Copyright 2007 Sangmoon Kim <dogoil@etinsys.com>
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.
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>
20 #include <asm/i8259.h>
24 static unsigned char *nvram_base = (unsigned char *)NULL;
25 static ssize_t nvram_size = 0;
30 unsigned long root = of_get_flat_dt_root();
32 if (of_flat_dt_is_compatible(root, "kvme080"))
38 kvme080_setup_pci(struct device_node *dnp)
41 struct pci_controller *hose;
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);
49 hose = pcibios_alloc_controller();
51 printk("PCI Host bridge init failed\n");
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);
60 printk(KERN_INFO "Found PCI host bridge %s", dnp->full_name);
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);
69 kvme080_setup_arch(void)
71 struct device_node *dnp;
76 #ifdef CONFIG_BLK_DEV_INITRD
81 #ifdef CONFIG_ROOT_NFS
86 for (dnp = NULL; (dnp=of_find_node_by_type(dnp,"pci")) != NULL;)
87 kvme080_setup_pci(dnp);
89 dnp = of_find_node_by_type(NULL, "nvram");
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);
99 printk(KERN_INFO "Etin Systems KVME080 Board\n");
100 printk(KERN_INFO "Port by Sangmoon Kim (dogoil@etinsys.com)\n");
104 kvme080_init_IRQ(void)
107 struct device_node *dnp;
112 dnp = of_find_node_by_type(NULL, "open-pic");
116 prop = of_get_address(dnp, 0, NULL, NULL);
117 paddr = (phys_addr_t)of_translate_address(dnp, prop);
119 mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 0, 0,
122 prop = (u32 *)get_property(dnp, "serial-mode", &size);
124 mpic_set_serial_int(mpic, *(u32 *)prop);
126 mpic_assign_isu(mpic, 0, paddr + 0x10200);
131 kvme080_restart(char *cmd)
150 kvme080_power_off(void)
153 for(;;); /* No way to shut power off with software */
164 extern spinlock_t rtc_lock;
165 static unsigned char *rtc_base = (unsigned char*)NULL;
168 kvme080_time_init(void)
171 struct device_node *dnp;
176 dnp = of_find_node_by_type(NULL, "rtc");
180 prop = of_get_address(dnp, 0, &size, NULL);
184 paddr = (phys_addr_t)of_translate_address(dnp, prop);
185 if (paddr == (phys_addr_t)OF_BAD_ADDR)
188 rtc_base = (unsigned char *)ioremap(paddr, (ssize_t)size);
193 spin_lock(&rtc_lock);
194 val = readb(rtc_base);
196 writeb(val & 0x3f, rtc_base);
197 spin_unlock(&rtc_lock);
203 kvme080_set_rtc_time(struct rtc_time *tp)
208 spin_lock(&rtc_lock);
210 writeb(readb(rtc_base) | 0x80, rtc_base);
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);
219 writeb((readb(rtc_base) & 0x40) |
220 BIN2BCD((tp->tm_year < 100) ? 20 : 21), rtc_base);
222 spin_unlock(&rtc_lock);
228 kvme080_get_rtc_time(struct rtc_time *tp)
233 spin_lock(&rtc_lock);
235 writeb(readb(rtc_base) | 0x40, rtc_base);
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;
244 writeb(readb(rtc_base) & ~0x40, rtc_base);
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);
253 if (tp->tm_year < 80)
256 spin_unlock(&rtc_lock);
260 kvme080_nvram_read_val(int addr)
264 return readb(nvram_base + addr);
268 kvme080_nvram_write_val(int addr, unsigned char val)
272 writeb(val, nvram_base + addr);
276 kvme080_nvram_size(void)
281 define_machine(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,