• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * AmigaOne platform setup
4   *
5   * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net)
6   *
7   *   Based on original amigaone_setup.c source code
8   * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden
9   */
10  
11  #include <linux/kernel.h>
12  #include <linux/of.h>
13  #include <linux/of_address.h>
14  #include <linux/seq_file.h>
15  #include <generated/utsrelease.h>
16  
17  #include <asm/machdep.h>
18  #include <asm/cputable.h>
19  #include <asm/pci-bridge.h>
20  #include <asm/i8259.h>
21  #include <asm/time.h>
22  #include <asm/udbg.h>
23  #include <asm/dma.h>
24  
25  extern void __flush_disable_L1(void);
26  
amigaone_show_cpuinfo(struct seq_file * m)27  void amigaone_show_cpuinfo(struct seq_file *m)
28  {
29  	seq_printf(m, "vendor\t\t: Eyetech Ltd.\n");
30  }
31  
amigaone_add_bridge(struct device_node * dev)32  static int __init amigaone_add_bridge(struct device_node *dev)
33  {
34  	const u32 *cfg_addr, *cfg_data;
35  	int len;
36  	const int *bus_range;
37  	struct pci_controller *hose;
38  
39  	printk(KERN_INFO "Adding PCI host bridge %pOF\n", dev);
40  
41  	cfg_addr = of_get_address(dev, 0, NULL, NULL);
42  	cfg_data = of_get_address(dev, 1, NULL, NULL);
43  	if ((cfg_addr == NULL) || (cfg_data == NULL))
44  		return -ENODEV;
45  
46  	bus_range = of_get_property(dev, "bus-range", &len);
47  	if ((bus_range == NULL) || (len < 2 * sizeof(int)))
48  		printk(KERN_WARNING "Can't get bus-range for %pOF, assume"
49  		       " bus 0\n", dev);
50  
51  	hose = pcibios_alloc_controller(dev);
52  	if (hose == NULL)
53  		return -ENOMEM;
54  
55  	hose->first_busno = bus_range ? bus_range[0] : 0;
56  	hose->last_busno = bus_range ? bus_range[1] : 0xff;
57  
58  	setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0);
59  
60  	/* Interpret the "ranges" property */
61  	/* This also maps the I/O region and sets isa_io/mem_base */
62  	pci_process_bridge_OF_ranges(hose, dev, 1);
63  
64  	return 0;
65  }
66  
amigaone_setup_arch(void)67  void __init amigaone_setup_arch(void)
68  {
69  	struct device_node *np;
70  	int phb = -ENODEV;
71  
72  	/* Lookup PCI host bridges. */
73  	for_each_compatible_node(np, "pci", "mai-logic,articia-s")
74  		phb = amigaone_add_bridge(np);
75  
76  	BUG_ON(phb != 0);
77  
78  	if (ppc_md.progress)
79  		ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0);
80  }
81  
amigaone_init_IRQ(void)82  void __init amigaone_init_IRQ(void)
83  {
84  	struct device_node *pic, *np = NULL;
85  	const unsigned long *prop = NULL;
86  	unsigned long int_ack = 0;
87  
88  	/* Search for ISA interrupt controller. */
89  	pic = of_find_compatible_node(NULL, "interrupt-controller",
90  	                              "pnpPNP,000");
91  	BUG_ON(pic == NULL);
92  
93  	/* Look for interrupt acknowledge address in the PCI root node. */
94  	np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s");
95  	if (np) {
96  		prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
97  		if (prop)
98  			int_ack = prop[0];
99  		of_node_put(np);
100  	}
101  
102  	if (int_ack == 0)
103  		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
104  		       " address, polling\n");
105  
106  	i8259_init(pic, int_ack);
107  	ppc_md.get_irq = i8259_irq;
108  	irq_set_default_host(i8259_get_host());
109  }
110  
request_isa_regions(void)111  static int __init request_isa_regions(void)
112  {
113  	request_region(0x00, 0x20, "dma1");
114  	request_region(0x40, 0x20, "timer");
115  	request_region(0x80, 0x10, "dma page reg");
116  	request_region(0xc0, 0x20, "dma2");
117  
118  	return 0;
119  }
120  machine_device_initcall(amigaone, request_isa_regions);
121  
amigaone_restart(char * cmd)122  void __noreturn amigaone_restart(char *cmd)
123  {
124  	local_irq_disable();
125  
126  	/* Flush and disable caches. */
127  	__flush_disable_L1();
128  
129          /* Set SRR0 to the reset vector and turn on MSR_IP. */
130  	mtspr(SPRN_SRR0, 0xfff00100);
131  	mtspr(SPRN_SRR1, MSR_IP);
132  
133  	/* Do an rfi to jump back to firmware. */
134  	__asm__ __volatile__("rfi" : : : "memory");
135  
136  	/* Not reached. */
137  	while (1);
138  }
139  
amigaone_probe(void)140  static int __init amigaone_probe(void)
141  {
142  	if (of_machine_is_compatible("eyetech,amigaone")) {
143  		/*
144  		 * Coherent memory access cause complete system lockup! Thus
145  		 * disable this CPU feature, even if the CPU needs it.
146  		 */
147  		cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT;
148  
149  		DMA_MODE_READ = 0x44;
150  		DMA_MODE_WRITE = 0x48;
151  
152  		return 1;
153  	}
154  
155  	return 0;
156  }
157  
define_machine(amigaone)158  define_machine(amigaone) {
159  	.name			= "AmigaOne",
160  	.probe			= amigaone_probe,
161  	.setup_arch		= amigaone_setup_arch,
162  	.show_cpuinfo		= amigaone_show_cpuinfo,
163  	.init_IRQ		= amigaone_init_IRQ,
164  	.restart		= amigaone_restart,
165  	.calibrate_decr		= generic_calibrate_decr,
166  	.progress		= udbg_progress,
167  };
168