2 * OpenBIOS Sparc OBIO driver
4 * (C) 2004 Stefan Reinauer <stepan@openbios.org>
5 * (C) 2005 Ed Schouten <ed@fxq.nl>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
14 #include "libopenbios/bindings.h"
15 #include "kernel/kernel.h"
16 #include "libc/byteorder.h"
17 #include "libc/vsprintf.h"
19 #include "drivers/drivers.h"
20 #include "arch/common/nvram.h"
21 #include "libopenbios/ofmem.h"
25 #define PROMDEV_KBD 0 /* input from keyboard */
26 #define PROMDEV_SCREEN 0 /* output to screen */
27 #define PROMDEV_TTYA 1 /* in/out to ttya */
29 /* DECLARE data structures for the nodes. */
30 DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) );
33 ob_new_obio_device(const char *name, const char *type)
49 map_reg(uint64_t base, uint64_t offset, unsigned long size, int map,
66 addr = (unsigned long)ofmem_map_io(base + offset, size);
78 ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map)
80 return map_reg(base, offset, size, map, 0);
96 ob_eccmemctl_init(uint64_t base)
98 uint32_t version, *regs;
102 fword("find-device");
105 push_str("eccmemctl");
106 fword("device-name");
113 regs = (uint32_t *)map_reg(ECC_BASE, 0, ECC_SIZE, 1, ECC_BASE >> 32);
129 fword("encode-string");
133 fword("finish-device");
136 static unsigned char *nvram;
138 #define NVRAM_OB_START (0)
139 #define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15)
142 arch_nvram_get(char *data)
144 memcpy(data, &nvram[NVRAM_OB_START], NVRAM_OB_SIZE);
148 arch_nvram_put(char *data)
150 memcpy(&nvram[NVRAM_OB_START], data, NVRAM_OB_SIZE);
154 arch_nvram_size(void)
156 return NVRAM_OB_SIZE;
160 ss5_init(uint64_t base)
162 ob_new_obio_device("slavioconfig", NULL);
164 ob_reg(base, SLAVIO_SCONFIG, SCONFIG_REGS, 0);
166 fword("finish-device");
170 ob_nvram_init(uint64_t base, uint64_t offset)
172 ob_new_obio_device("eeprom", NULL);
174 nvram = (unsigned char *)ob_reg(base, offset, NVRAM_SIZE, 1);
176 PUSH((unsigned long)nvram);
184 fword("finish-device");
188 fword("find-device");
190 PUSH((long)&nvram[NVRAM_IDPROM]);
192 fword("encode-bytes");
198 ob_fd_init(uint64_t base, uint64_t offset, int intr)
202 ob_new_obio_device("SUNW,fdtwo", "block");
204 addr = ob_reg(base, offset, FD_REGS, 1);
208 fword("is-deblocker");
210 ob_floppy_init("/obio", "SUNW,fdtwo", 0, addr);
212 fword("finish-device");
216 ob_auxio_init(uint64_t base, uint64_t offset)
218 ob_new_obio_device("auxio", NULL);
220 ob_reg(base, offset, AUXIO_REGS, 1);
222 fword("finish-device");
225 volatile unsigned char *power_reg;
226 volatile unsigned int *reset_reg;
229 sparc32_reset_all(void)
234 // AUX 2 (Software Powerdown Control) and reset
236 ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr)
238 ob_new_obio_device("power", NULL);
240 power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1);
242 // Not in device tree
243 reset_reg = (unsigned int *)ofmem_map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS);
245 bind_func("sparc32-reset-all", sparc32_reset_all);
246 push_str("' sparc32-reset-all to reset-all");
251 fword("finish-device");
254 volatile struct sun4m_timer_regs *counter_regs;
257 ob_counter_init(uint64_t base, unsigned long offset, int ncpu)
261 ob_new_obio_device("counter", NULL);
263 for (i = 0; i < ncpu; i++) {
266 if (i != 0) fword("encode+");
267 PUSH(offset + (i * PAGE_SIZE));
278 PUSH(offset + 0x10000);
289 counter_regs = (struct sun4m_timer_regs *)ofmem_map_io(base + (uint64_t)offset, sizeof(*counter_regs));
290 counter_regs->cfg = 0xfffffffe;
291 counter_regs->l10_timer_limit = 0;
292 counter_regs->cpu_timers[0].l14_timer_limit = 0x9c4000; /* see comment in obio.h */
293 counter_regs->cpu_timers[0].cntrl = 1;
295 for (i = 0; i < ncpu; i++) {
296 PUSH((unsigned long)&counter_regs->cpu_timers[i]);
301 PUSH((unsigned long)&counter_regs->l10_timer_limit);
307 fword("finish-device");
310 static volatile struct sun4m_intregs *intregs;
313 ob_interrupt_init(uint64_t base, unsigned long offset, int ncpu)
317 ob_new_obio_device("interrupt", NULL);
319 for (i = 0; i < ncpu; i++) {
322 if (i != 0) fword("encode+");
323 PUSH(offset + (i * PAGE_SIZE));
326 PUSH(INTERRUPT_REGS);
334 PUSH(offset + 0x10000);
337 PUSH(INTERRUPT_REGS);
344 intregs = (struct sun4m_intregs *)ofmem_map_io(base | (uint64_t)offset, sizeof(*intregs));
345 intregs->clear = ~SUN4M_INT_MASKALL;
346 intregs->cpu_intregs[0].clear = ~0x17fff;
348 for (i = 0; i < ncpu; i++) {
349 PUSH((unsigned long)&intregs->cpu_intregs[i]);
354 PUSH((unsigned long)&intregs->tbt);
360 fword("finish-device");
363 /* SMP CPU boot structure */
371 static struct smp_cfg *smp_header;
374 start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu)
381 smp_header->smp_entry = pc;
382 smp_header->smp_ctxtbl = context_ptr;
383 smp_header->smp_ctx = context;
384 smp_header->valid = cpu;
386 intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14);
392 ob_smp_init(unsigned long mem_size)
394 // See arch/sparc32/entry.S for memory layout
395 smp_header = (struct smp_cfg *)ofmem_map_io((uint64_t)(mem_size - 0x100),
396 sizeof(struct smp_cfg));
400 ob_obio_open(__attribute__((unused))int *idx)
407 ob_obio_close(__attribute__((unused))int *idx)
409 selfword("close-deblocker");
413 ob_obio_initialize(__attribute__((unused))int *idx)
416 fword("find-device");
420 fword("device-name");
422 push_str("hierarchical");
423 fword("device-type");
427 push_str("#address-cells");
432 push_str("#size-cells");
435 fword("finish-device");
439 ob_set_obio_ranges(uint64_t base)
442 fword("find-device");
451 PUSH(base & 0xffffffff);
462 ob_obio_decodeunit(__attribute__((unused)) int *idx)
464 fword("decode-unit-sbus");
469 ob_obio_encodeunit(__attribute__((unused)) int *idx)
471 fword("encode-unit-sbus");
474 NODE_METHODS(ob_obio) = {
475 { NULL, ob_obio_initialize },
476 { "open", ob_obio_open },
477 { "close", ob_obio_close },
478 { "encode-unit", ob_obio_encodeunit },
479 { "decode-unit", ob_obio_decodeunit },
484 ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
485 unsigned long counter_offset, unsigned long intr_offset,
486 int intr_ncpu, unsigned long aux1_offset, unsigned long aux2_offset,
487 unsigned long mem_size)
490 // All devices were integrated to NCR89C105, see
491 // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
493 //printk("Initializing OBIO devices...\n");
495 REGISTER_NAMED_NODE(ob_obio, "/obio");
498 ob_set_obio_ranges(slavio_base);
500 // Zilog Z8530 serial ports, see http://www.zilog.com
501 // Must be before zs@0,0 or Linux won't boot
502 ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0);
504 ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1);
506 // M48T08 NVRAM, see http://www.st.com
507 ob_nvram_init(slavio_base, SLAVIO_NVRAM);
510 if (fd_offset != (unsigned long) -1)
511 ob_fd_init(slavio_base, fd_offset, FD_INTR);
513 ob_auxio_init(slavio_base, aux1_offset);
515 if (aux2_offset != (unsigned long) -1)
516 ob_aux2_reset_init(slavio_base, aux2_offset, AUXIO2_INTR);
518 ob_counter_init(slavio_base, counter_offset, intr_ncpu);
520 ob_interrupt_init(slavio_base, intr_offset, intr_ncpu);
522 ob_smp_init(mem_size);