/* * AmigaOne platform setup * * Copyright 2007 Gerhard Pircher (gerhard_pircher@gmx.net) * * Based on original amigaone_setup.c source code * Copyright 2003 by Hans-Jörg and Thomas Frieden * and chrp/setup.c * Copyright 1995 by Linus Torvalds * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern void amigaone_find_bridges(void); void amigaone_set_l2cr(void) { /* This disables the L2 hardware prefetch. It is normally disabled and * enabled again within _set_L2CR(), but the L2 prefetch enable is not * compiled in for the AmigaOne. */ _set_L2CR(_get_L2CR()); if(((_get_L2CR() & L2CR_L2E) == 0) && (strstr(cmd_line, "l2cr=") == NULL)) { printk("AmigaOne l2cr : L2 cache was not active, activating.\n"); _set_L2CR(0); _set_L2CR(L2CR_L2E | L2CR_L2PE); } } int amigaone_show_cpuinfo(struct seq_file *m) { struct device_node *root; const char *model = ""; root = of_find_node_by_path("/"); if (root) model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: %s\n", model); of_node_put(root); seq_printf(m, "msscr0\t\t: 0x%08lX\n", mfspr(SPRN_MSSCR0)); return 0; } void __init amigaone_setup_arch(void) { /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000/HZ; #ifdef CONFIG_BLK_DEV_INITRD /* this is fine for chrp */ initrd_below_start_ok = 1; if (initrd_start) ROOT_DEV = Root_RAM0; else #endif ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel or OS4) */ /* Enable the L2 cache. */ amigaone_set_l2cr(); /* Lookup PCI host bridges */ /* setup PCI host bridge */ #ifdef CONFIG_PCI_HOST_DRIVER for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) articias_setup_pci(np); #else amigaone_find_bridges(); #endif /* Uncomment, when U-boot was updated. */ // pci_create_OF_bus_map(); /* vgacon.c needs to know where VGA memory is mapped. */ // vgacon_remap_base = (unsigned long) ioremap(0xfd000000, 0x01000000); // conswitchp = &vga_con; if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } void __init amigaone_init_IRQ(void) { struct device_node *np, *pic = NULL; unsigned long amigaone_int_ack = 0; /* Search for ISA interrupt controller. */ for_each_node_by_type(np, "interrupt-controller") if (of_device_is_compatible(np, "pnpPNP,000")) { pic = np; break; } BUG_ON(pic == NULL); /* Look for interrupt acknowledge address in the PCI root node. */ for_each_node_by_name(np, "pci") { const unsigned int *addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; amigaone_int_ack = addrp[of_n_addr_cells(np)-1]; break; } of_node_put(np); if (np == NULL) printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" " address, polling\n"); i8259_init(pic, amigaone_int_ack); ppc_md.get_irq = i8259_irq; irq_set_default_host(i8259_get_host()); } void __init amigaone_init(void) { #ifdef CONFIG_NVRAM // amigaone_nvram_init(); #endif request_region(0x20,0x20,"pic1"); request_region(0xa0,0x20,"pic2"); request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); } /* Copied from U-Boot. */ static inline void soft_restart(unsigned long addr) { /* SRR0 has system reset vector, SRR1 has default MSR value. * rfi restores MSR from SRR1 and sets the PC to the SRR0 value. */ __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); __asm__ __volatile__ ("mtspr 27, 4"); __asm__ __volatile__ ("rfi"); /* Not reached. */ while(1); } void amigaone_restart(char *cmd) { unsigned long addr; local_irq_disable(); /* Flush and disable I/D cache. */ __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); __asm__ __volatile__ ("sync"); __asm__ __volatile__ ("mtspr 1008, 4"); __asm__ __volatile__ ("isync"); __asm__ __volatile__ ("sync"); __asm__ __volatile__ ("mtspr 1008, 5"); __asm__ __volatile__ ("isync"); __asm__ __volatile__ ("sync"); addr = 0xfff00100; soft_restart(addr); while(1); } static int __init amigaone_probe(void) { unsigned long root = of_get_flat_dt_root(); if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) { /* Coherent memory access cause complete system lockup! Thus * remove it in any case, even if the CPU needs it. We'll * disable the L2 cache prefetch later on. */ cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT; ISA_DMA_THRESHOLD = 0x00FFFFFF; DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; return 1; } return 0; } define_machine(amigaone) { .name = "AmigaOne", .probe = amigaone_probe, .setup_arch = amigaone_setup_arch, .init = amigaone_init, .show_cpuinfo = amigaone_show_cpuinfo, .init_IRQ = amigaone_init_IRQ, .restart = amigaone_restart, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, .phys_mem_access_prot = pci_phys_mem_access_prot, };