| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * AmigaOne platform setup | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   Based on original amigaone_setup.c source code | 
					
						
							|  |  |  |  * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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 <linux/kernel.h>
 | 
					
						
							| 
									
										
										
										
											2010-07-29 11:49:01 -06:00
										 |  |  | #include <linux/of.h>
 | 
					
						
							|  |  |  | #include <linux/of_address.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | #include <linux/seq_file.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-18 00:52:28 +02:00
										 |  |  | #include <generated/utsrelease.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 %s\n", dev->full_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 %s, assume" | 
					
						
							|  |  |  | 		       " bus 0\n", dev->full_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ppc_md.progress) | 
					
						
							|  |  |  | 		ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 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()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-19 11:40:57 +00:00
										 |  |  | static int __init request_isa_regions(void) | 
					
						
							| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	request_region(0x00, 0x20, "dma1"); | 
					
						
							|  |  |  | 	request_region(0x40, 0x20, "timer"); | 
					
						
							|  |  |  | 	request_region(0x80, 0x10, "dma page reg"); | 
					
						
							|  |  |  | 	request_region(0xc0, 0x20, "dma2"); | 
					
						
							| 
									
										
										
										
											2009-06-19 11:40:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-19 11:40:57 +00:00
										 |  |  | machine_device_initcall(amigaone, request_isa_regions); | 
					
						
							| 
									
										
										
										
											2009-02-10 12:20:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  | 		 * disable this CPU feature, even if the CPU needs it. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		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, | 
					
						
							|  |  |  | 	.show_cpuinfo		= amigaone_show_cpuinfo, | 
					
						
							|  |  |  | 	.init_IRQ		= amigaone_init_IRQ, | 
					
						
							|  |  |  | 	.restart		= amigaone_restart, | 
					
						
							|  |  |  | 	.calibrate_decr		= generic_calibrate_decr, | 
					
						
							|  |  |  | 	.progress		= udbg_progress, | 
					
						
							|  |  |  | }; |