linux/arch/powerpc/platforms/52xx/mpc52xx_common.c
Sylvain Munaut 5c334eed6e [POWERPC] 52xx: Don't use device_initcall to probe of_platform_bus
Using device_initcall makes it happen for every platform that
compiles this file in. This is really bad, for obvious reasons.

Instead, we use the .init field of the machine description. If
the platform needs the hook to do something specific it can provides
its own function and call mpc52xx_declare_of_platform_devices from
there. If not, the mpc52xx_declare_of_platform_devices function can
directly be used as the init hook.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Paul Mackerras <paulus@samba.org>
2007-01-09 17:03:02 +11:00

128 lines
2.8 KiB
C

/*
*
* Utility functions for the Freescale MPC52xx.
*
* Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#undef DEBUG
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
void __iomem *
mpc52xx_find_and_map(const char *compatible)
{
struct device_node *ofn;
const u32 *regaddr_p;
u64 regaddr64, size64;
ofn = of_find_compatible_node(NULL, NULL, compatible);
if (!ofn)
return NULL;
regaddr_p = of_get_address(ofn, 0, &size64, NULL);
if (!regaddr_p) {
of_node_put(ofn);
return NULL;
}
regaddr64 = of_translate_address(ofn, regaddr_p);
of_node_put(ofn);
return ioremap((u32)regaddr64, (u32)size64);
}
EXPORT_SYMBOL(mpc52xx_find_and_map);
/**
* mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
* @node: device node
*
* Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
*/
unsigned int
mpc52xx_find_ipb_freq(struct device_node *node)
{
struct device_node *np;
const unsigned int *p_ipb_freq = NULL;
of_node_get(node);
while (node) {
p_ipb_freq = get_property(node, "bus-frequency", NULL);
if (p_ipb_freq)
break;
np = of_get_parent(node);
of_node_put(node);
node = np;
}
if (node)
of_node_put(node);
return p_ipb_freq ? *p_ipb_freq : 0;
}
EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
void __init
mpc52xx_setup_cpu(void)
{
struct mpc52xx_cdm __iomem *cdm;
struct mpc52xx_xlb __iomem *xlb;
/* Map zones */
cdm = mpc52xx_find_and_map("mpc52xx-cdm");
xlb = mpc52xx_find_and_map("mpc52xx-xlb");
if (!cdm || !xlb) {
printk(KERN_ERR __FILE__ ": "
"Error while mapping CDM/XLB during mpc52xx_setup_cpu. "
"Expect some abnormal behavior\n");
goto unmap_regs;
}
/* Use internal 48 Mhz */
out_8(&cdm->ext_48mhz_en, 0x00);
out_8(&cdm->fd_enable, 0x01);
if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
out_be16(&cdm->fd_counters, 0x0001);
else
out_be16(&cdm->fd_counters, 0x5555);
/* Configure the XLB Arbiter priorities */
out_be32(&xlb->master_pri_enable, 0xff);
out_be32(&xlb->master_priority, 0x11111111);
/* Disable XLB pipelining */
/* (cfr errate 292. We could do this only just before ATA PIO
transaction and re-enable it afterwards ...) */
out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
/* Unmap zones */
unmap_regs:
if (cdm) iounmap(cdm);
if (xlb) iounmap(xlb);
}
void __init
mpc52xx_declare_of_platform_devices(void)
{
/* Find every child of the SOC node and add it to of_platform */
if (of_platform_bus_probe(NULL, NULL, NULL))
printk(KERN_ERR __FILE__ ": "
"Error while probing of_platform bus\n");
}