Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a575b807 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

powerpc: Run on old powermacs.



Old powermacs have a number of differences from current machines:
- there is no interrupt tree in the device tree, just interrupt
  or AAPL,interrupt properties
- the chosen node in the device tree is called /chosen@0
- the OF claim method doesn't map the memory, so we have to do
  an explicit map call as well
- there is no /chosen/cpu property on SMP machines
- the NVRAM isn't structured as a set of partitions.

This adapts the merged powermac support code to cope with these
issues.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 96c44507
Loading
Loading
Loading
Loading
+35 −1
Original line number Original line Diff line number Diff line
@@ -309,6 +309,37 @@ static int __devinit finish_node_interrupts(struct device_node *np,
	unsigned int *irq, virq;
	unsigned int *irq, virq;
	struct device_node *ic;
	struct device_node *ic;


	if (num_interrupt_controllers == 0) {
		/*
		 * Old machines just have a list of interrupt numbers
		 * and no interrupt-controller nodes.
		 */
		ints = (unsigned int *) get_property(np, "AAPL,interrupts",
						     &intlen);
		/* XXX old interpret_pci_props looked in parent too */
		/* XXX old interpret_macio_props looked for interrupts
		   before AAPL,interrupts */
		if (ints == NULL)
			ints = (unsigned int *) get_property(np, "interrupts",
							     &intlen);
		if (ints == NULL)
			return 0;

		np->n_intrs = intlen / sizeof(unsigned int);
		np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
				       mem_start);
		if (!np->intrs)
			return -ENOMEM;
		if (measure_only)
			return 0;

		for (i = 0; i < np->n_intrs; ++i) {
			np->intrs[i].line = *ints++;
			np->intrs[i].sense = 1;
		}
		return 0;
	}

	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
	if (ints == NULL)
	if (ints == NULL)
		return 0;
		return 0;
@@ -1024,6 +1055,8 @@ void __init unflatten_device_tree(void)


	/* Get pointer to OF "/chosen" node for use everywhere */
	/* Get pointer to OF "/chosen" node for use everywhere */
	of_chosen = of_find_node_by_path("/chosen");
	of_chosen = of_find_node_by_path("/chosen");
	if (of_chosen == NULL)
		of_chosen = of_find_node_by_path("/chosen@0");


	/* Retreive command line */
	/* Retreive command line */
	if (of_chosen != NULL) {
	if (of_chosen != NULL) {
@@ -1123,7 +1156,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,


	DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
	DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);


	if (depth != 1 || strcmp(uname, "chosen") != 0)
	if (depth != 1 ||
	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
		return 0;
		return 0;


	/* get platform type */
	/* get platform type */
+63 −24
Original line number Original line Diff line number Diff line
@@ -132,6 +132,7 @@ struct prom_t {
	ihandle chosen;
	ihandle chosen;
	int cpu;
	int cpu;
	ihandle stdout;
	ihandle stdout;
	ihandle mmumap;
};
};


struct mem_map_entry {
struct mem_map_entry {
@@ -274,14 +275,6 @@ static int __init call_prom_ret(const char *service, int nargs, int nret,
}
}




static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
				unsigned long align)
{
	return (unsigned int)call_prom("claim", 3, 1,
				       (prom_arg_t)virt, (prom_arg_t)size,
				       (prom_arg_t)align);
}

static void __init prom_print(const char *msg)
static void __init prom_print(const char *msg)
{
{
	const char *p, *q;
	const char *p, *q;
@@ -363,6 +356,21 @@ static void __init prom_printf(const char *format, ...)
}
}




static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
				unsigned long align)
{
	int ret;
	struct prom_t *_prom = &RELOC(prom);

	ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
			(prom_arg_t)align);
	if (ret != -1 && _prom->mmumap != 0)
		/* old pmacs need us to map as well */
		call_prom("call-method", 6, 1,
			  ADDR("map"), _prom->mmumap, 0, size, virt, virt);
	return ret;
}

static void __init __attribute__((noreturn)) prom_panic(const char *reason)
static void __init __attribute__((noreturn)) prom_panic(const char *reason)
{
{
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
@@ -1323,7 +1331,37 @@ static void __init prom_init_client_services(unsigned long pp)
	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
	if (!PHANDLE_VALID(_prom->root))
	if (!PHANDLE_VALID(_prom->root))
		prom_panic("cannot find device tree root"); /* msg won't be printed :( */
		prom_panic("cannot find device tree root"); /* msg won't be printed :( */

	_prom->mmumap = 0;
}

#ifdef CONFIG_PPC32
/*
 * For really old powermacs, we need to map things we claim.
 * For that, we need the ihandle of the mmu.
 */
static void __init prom_find_mmu(void)
{
	struct prom_t *_prom = &RELOC(prom);
	phandle oprom;
	char version[64];

	oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
	if (!PHANDLE_VALID(oprom))
		return;
	if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
		return;
	version[sizeof(version) - 1] = 0;
	prom_printf("OF version is '%s'\n", version);
	/* XXX might need to add other versions here */
	if (strcmp(version, "Open Firmware, 1.0.5") != 0)
		return;
	prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
		     sizeof(_prom->mmumap));
}
}
#else
#define prom_find_mmu()
#endif


static void __init prom_init_stdout(void)
static void __init prom_init_stdout(void)
{
{
@@ -1379,7 +1417,7 @@ static int __init prom_find_machine_type(void)
			if (sl == 0)
			if (sl == 0)
				break;
				break;
			if (strstr(p, RELOC("Power Macintosh")) ||
			if (strstr(p, RELOC("Power Macintosh")) ||
			    strstr(p, RELOC("MacRISC4")))
			    strstr(p, RELOC("MacRISC")))
				return PLATFORM_POWERMAC;
				return PLATFORM_POWERMAC;
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
			if (strstr(p, RELOC("Momentum,Maple")))
			if (strstr(p, RELOC("Momentum,Maple")))
@@ -1618,22 +1656,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
		namep[l] = '\0';
		namep[l] = '\0';


		/* Fixup an Apple bug where they have bogus \0 chars in the
		/* Fixup an Apple bug where they have bogus \0 chars in the
		 * middle of the path in some properties
		 * middle of the path in some properties, and extract
		 * the unit name (everything after the last '/').
		 */
		 */
		for (p = namep, ep = namep + l; p < ep; p++)
		for (lp = p = namep, ep = namep + l; p < ep; p++) {
			if (*p == '\0') {
				memmove(p, p+1, ep - p);
				ep--; l--; p--;
			}

		/* now try to extract the unit name in that mess */
		for (p = namep, lp = NULL; *p; p++)
			if (*p == '/')
			if (*p == '/')
				lp = p + 1;
				lp = namep;
		if (lp != NULL)
			else if (*p != 0)
			memmove(namep, lp, strlen(lp) + 1);
				*lp++ = *p;
		*mem_start = _ALIGN(((unsigned long) namep) +
		}
				    strlen(namep) + 1, 4);
		*lp = 0;
		*mem_start = _ALIGN((unsigned long)lp + 1, 4);
	}
	}


	/* get it again for debugging */
	/* get it again for debugging */
@@ -1858,8 +1891,9 @@ static void __init prom_find_boot_cpu(void)
	ihandle prom_cpu;
	ihandle prom_cpu;
	phandle cpu_pkg;
	phandle cpu_pkg;


	_prom->cpu = 0;
	if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
	if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
		prom_panic("cannot find boot cpu");
		return;


	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);


@@ -1933,6 +1967,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
	 */
	 */
	prom_init_stdout();
	prom_init_stdout();


	/*
	 * See if this OF is old enough that we need to do explicit maps
	 */
	prom_find_mmu();

	/*
	/*
	 * Check for an initrd
	 * Check for an initrd
	 */
	 */
+8 −2
Original line number Original line Diff line number Diff line
@@ -225,7 +225,7 @@ int find_via_pmu(void)
		return 0;
		return 0;
	printk("WARNING ! Your machine is PMU-based but your kernel\n");
	printk("WARNING ! Your machine is PMU-based but your kernel\n");
	printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
	printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
	return;
	return 0;
}
}
#endif
#endif


@@ -293,7 +293,7 @@ static void __init l2cr_init(void)


void __init pmac_setup_arch(void)
void __init pmac_setup_arch(void)
{
{
	struct device_node *cpu;
	struct device_node *cpu, *ic;
	int *fp;
	int *fp;
	unsigned long pvr;
	unsigned long pvr;


@@ -319,6 +319,12 @@ void __init pmac_setup_arch(void)
		of_node_put(cpu);
		of_node_put(cpu);
	}
	}


	/* See if newworld or oldworld */
	ic = of_find_node_by_name(NULL, "interrupt-controller");
	pmac_newworld = (ic != NULL);
	if (ic)
		of_node_put(ic);

	/* Lookup PCI hosts */
	/* Lookup PCI hosts */
	pmac_pci_init();
	pmac_pci_init();