118 lines
2.5 KiB
C
118 lines
2.5 KiB
C
/*
|
|
* Copyright 2008-2011, IBM Corporation
|
|
*
|
|
* 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>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/time.h>
|
|
#include <linux/of_address.h>
|
|
|
|
#include <asm/scom.h>
|
|
|
|
#include "wsp.h"
|
|
#include "ics.h"
|
|
|
|
#define WSP_SOC_COMPATIBLE "ibm,wsp-soc"
|
|
#define PBIC_COMPATIBLE "ibm,wsp-pbic"
|
|
#define COPRO_COMPATIBLE "ibm,wsp-coprocessor"
|
|
|
|
static int __init wsp_probe_buses(void)
|
|
{
|
|
static __initdata struct of_device_id bus_ids[] = {
|
|
/*
|
|
* every node in between needs to be here or you won't
|
|
* find it
|
|
*/
|
|
{ .compatible = WSP_SOC_COMPATIBLE, },
|
|
{ .compatible = PBIC_COMPATIBLE, },
|
|
{ .compatible = COPRO_COMPATIBLE, },
|
|
{},
|
|
};
|
|
of_platform_bus_probe(NULL, bus_ids, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void __init wsp_setup_arch(void)
|
|
{
|
|
/* init to some ~sane value until calibrate_delay() runs */
|
|
loops_per_jiffy = 50000000;
|
|
|
|
scom_init_wsp();
|
|
|
|
/* Setup SMP callback */
|
|
#ifdef CONFIG_SMP
|
|
a2_setup_smp();
|
|
#endif
|
|
#ifdef CONFIG_PCI
|
|
wsp_setup_pci();
|
|
#endif
|
|
}
|
|
|
|
void __init wsp_setup_irq(void)
|
|
{
|
|
wsp_init_irq();
|
|
opb_pic_init();
|
|
}
|
|
|
|
|
|
int __init wsp_probe_devices(void)
|
|
{
|
|
struct device_node *np;
|
|
|
|
/* Our RTC is a ds1500. It seems to be programatically compatible
|
|
* with the ds1511 for which we have a driver so let's use that
|
|
*/
|
|
np = of_find_compatible_node(NULL, NULL, "dallas,ds1500");
|
|
if (np != NULL) {
|
|
struct resource res;
|
|
if (of_address_to_resource(np, 0, &res) == 0)
|
|
platform_device_register_simple("ds1511", 0, &res, 1);
|
|
}
|
|
|
|
wsp_probe_buses();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void wsp_halt(void)
|
|
{
|
|
u64 val;
|
|
scom_map_t m;
|
|
struct device_node *dn;
|
|
struct device_node *mine;
|
|
struct device_node *me;
|
|
int rc;
|
|
|
|
me = of_get_cpu_node(smp_processor_id(), NULL);
|
|
mine = scom_find_parent(me);
|
|
|
|
/* This will halt all the A2s but not power off the chip */
|
|
for_each_node_with_property(dn, "scom-controller") {
|
|
if (dn == mine)
|
|
continue;
|
|
m = scom_map(dn, 0, 1);
|
|
|
|
/* read-modify-write it so the HW probe does not get
|
|
* confused */
|
|
rc = scom_read(m, 0, &val);
|
|
if (rc == 0)
|
|
scom_write(m, 0, val | 1);
|
|
scom_unmap(m);
|
|
}
|
|
m = scom_map(mine, 0, 1);
|
|
rc = scom_read(m, 0, &val);
|
|
if (rc == 0)
|
|
scom_write(m, 0, val | 1);
|
|
/* should never return */
|
|
scom_unmap(m);
|
|
}
|