mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.1 KiB
171 lines
4.1 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* AmigaOne platform setup |
|
* |
|
* Copyright 2008 Gerhard Pircher ([email protected]) |
|
* |
|
* Based on original amigaone_setup.c source code |
|
* Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden |
|
*/ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/of.h> |
|
#include <linux/of_address.h> |
|
#include <linux/seq_file.h> |
|
#include <generated/utsrelease.h> |
|
|
|
#include <asm/machdep.h> |
|
#include <asm/cputable.h> |
|
#include <asm/pci-bridge.h> |
|
#include <asm/i8259.h> |
|
#include <asm/time.h> |
|
#include <asm/udbg.h> |
|
#include <asm/dma.h> |
|
|
|
extern void __flush_disable_L1(void); |
|
|
|
void amigaone_show_cpuinfo(struct seq_file *m) |
|
{ |
|
seq_printf(m, "vendor\t\t: Eyetech Ltd.\n"); |
|
} |
|
|
|
static int __init amigaone_add_bridge(struct device_node *dev) |
|
{ |
|
const u32 *cfg_addr, *cfg_data; |
|
int len; |
|
const int *bus_range; |
|
struct pci_controller *hose; |
|
|
|
printk(KERN_INFO "Adding PCI host bridge %pOF\n", dev); |
|
|
|
cfg_addr = of_get_address(dev, 0, NULL, NULL); |
|
cfg_data = of_get_address(dev, 1, NULL, NULL); |
|
if ((cfg_addr == NULL) || (cfg_data == NULL)) |
|
return -ENODEV; |
|
|
|
bus_range = of_get_property(dev, "bus-range", &len); |
|
if ((bus_range == NULL) || (len < 2 * sizeof(int))) |
|
printk(KERN_WARNING "Can't get bus-range for %pOF, assume" |
|
" bus 0\n", dev); |
|
|
|
hose = pcibios_alloc_controller(dev); |
|
if (hose == NULL) |
|
return -ENOMEM; |
|
|
|
hose->first_busno = bus_range ? bus_range[0] : 0; |
|
hose->last_busno = bus_range ? bus_range[1] : 0xff; |
|
|
|
setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0); |
|
|
|
/* Interpret the "ranges" property */ |
|
/* This also maps the I/O region and sets isa_io/mem_base */ |
|
pci_process_bridge_OF_ranges(hose, dev, 1); |
|
|
|
return 0; |
|
} |
|
|
|
void __init amigaone_setup_arch(void) |
|
{ |
|
if (ppc_md.progress) |
|
ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0); |
|
} |
|
|
|
static void __init amigaone_discover_phbs(void) |
|
{ |
|
struct device_node *np; |
|
int phb = -ENODEV; |
|
|
|
/* Lookup PCI host bridges. */ |
|
for_each_compatible_node(np, "pci", "mai-logic,articia-s") |
|
phb = amigaone_add_bridge(np); |
|
|
|
BUG_ON(phb != 0); |
|
} |
|
|
|
void __init amigaone_init_IRQ(void) |
|
{ |
|
struct device_node *pic, *np = NULL; |
|
const unsigned long *prop = NULL; |
|
unsigned long int_ack = 0; |
|
|
|
/* Search for ISA interrupt controller. */ |
|
pic = of_find_compatible_node(NULL, "interrupt-controller", |
|
"pnpPNP,000"); |
|
BUG_ON(pic == NULL); |
|
|
|
/* Look for interrupt acknowledge address in the PCI root node. */ |
|
np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s"); |
|
if (np) { |
|
prop = of_get_property(np, "8259-interrupt-acknowledge", NULL); |
|
if (prop) |
|
int_ack = prop[0]; |
|
of_node_put(np); |
|
} |
|
|
|
if (int_ack == 0) |
|
printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" |
|
" address, polling\n"); |
|
|
|
i8259_init(pic, int_ack); |
|
ppc_md.get_irq = i8259_irq; |
|
irq_set_default_host(i8259_get_host()); |
|
} |
|
|
|
static int __init request_isa_regions(void) |
|
{ |
|
request_region(0x00, 0x20, "dma1"); |
|
request_region(0x40, 0x20, "timer"); |
|
request_region(0x80, 0x10, "dma page reg"); |
|
request_region(0xc0, 0x20, "dma2"); |
|
|
|
return 0; |
|
} |
|
machine_device_initcall(amigaone, request_isa_regions); |
|
|
|
void __noreturn amigaone_restart(char *cmd) |
|
{ |
|
local_irq_disable(); |
|
|
|
/* Flush and disable caches. */ |
|
__flush_disable_L1(); |
|
|
|
/* Set SRR0 to the reset vector and turn on MSR_IP. */ |
|
mtspr(SPRN_SRR0, 0xfff00100); |
|
mtspr(SPRN_SRR1, MSR_IP); |
|
|
|
/* Do an rfi to jump back to firmware. */ |
|
__asm__ __volatile__("rfi" : : : "memory"); |
|
|
|
/* Not reached. */ |
|
while (1); |
|
} |
|
|
|
static int __init amigaone_probe(void) |
|
{ |
|
if (of_machine_is_compatible("eyetech,amigaone")) { |
|
/* |
|
* Coherent memory access cause complete system lockup! Thus |
|
* disable this CPU feature, even if the CPU needs it. |
|
*/ |
|
cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT; |
|
|
|
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, |
|
.discover_phbs = amigaone_discover_phbs, |
|
.show_cpuinfo = amigaone_show_cpuinfo, |
|
.init_IRQ = amigaone_init_IRQ, |
|
.restart = amigaone_restart, |
|
.calibrate_decr = generic_calibrate_decr, |
|
.progress = udbg_progress, |
|
};
|
|
|