linux/arch/arm/mach-prima2/rstc.c
Haojian Zhuang 7e5955db45 ARM: prima2: fix incorrect panic usage
In prima2, some functions of checking DT is registered in initcall
level. If it doesn't match the compatible name of sirf, kernel
will panic. It blocks the usage of multiplatform on other verndor.

The error message is in below.

Knic - not syncing: unable to find compatible pwrc node in dtb
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-rc3-00006-gd7f26ea-dirty #86
[<c0013adc>] (unwind_backtrace+0x0/0xf8) from [<c0011430>] (show_stack+0x10/0x1)
[<c0011430>] (show_stack+0x10/0x14) from [<c026f724>] (panic+0x90/0x1e8)
[<c026f724>] (panic+0x90/0x1e8) from [<c03267fc>] (sirfsoc_of_pwrc_init+0x24/0x)
[<c03267fc>] (sirfsoc_of_pwrc_init+0x24/0x58) from [<c0320864>] (do_one_initcal)
[<c0320864>] (do_one_initcall+0x90/0x150) from [<c0320a20>] (kernel_init_freeab)
[<c0320a20>] (kernel_init_freeable+0xfc/0x1c4) from [<c026b9e8>] (kernel_init+0)
[<c026b9e8>] (kernel_init+0x8/0xe4) from [<c000e158>] (ret_from_fork+0x14/0x3c)

Signen-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Signed-off-by: Olof Johansson <olof@lixom.net>
2013-06-11 00:11:31 -07:00

91 lines
2.3 KiB
C

/*
* reset controller for CSR SiRFprimaII
*
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2 or later.
*/
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
void __iomem *sirfsoc_rstc_base;
static DEFINE_MUTEX(rstc_lock);
static struct of_device_id rstc_ids[] = {
{ .compatible = "sirf,prima2-rstc" },
{ .compatible = "sirf,marco-rstc" },
{},
};
static int __init sirfsoc_of_rstc_init(void)
{
struct device_node *np;
np = of_find_matching_node(NULL, rstc_ids);
if (!np) {
pr_err("unable to find compatible sirf rstc node in dtb\n");
return -ENOENT;
}
sirfsoc_rstc_base = of_iomap(np, 0);
if (!sirfsoc_rstc_base)
panic("unable to map rstc cpu registers\n");
of_node_put(np);
return 0;
}
early_initcall(sirfsoc_of_rstc_init);
int sirfsoc_reset_device(struct device *dev)
{
u32 reset_bit;
if (of_property_read_u32(dev->of_node, "reset-bit", &reset_bit))
return -EINVAL;
mutex_lock(&rstc_lock);
if (of_device_is_compatible(dev->of_node, "sirf,prima2-rstc")) {
/*
* Writing 1 to this bit resets corresponding block. Writing 0 to this
* bit de-asserts reset signal of the corresponding block.
* datasheet doesn't require explicit delay between the set and clear
* of reset bit. it could be shorter if tests pass.
*/
writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
sirfsoc_rstc_base + (reset_bit / 32) * 4);
msleep(10);
writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
sirfsoc_rstc_base + (reset_bit / 32) * 4);
} else {
/*
* For MARCO and POLO
* Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR
* register de-asserts reset signal of the corresponding block.
* datasheet doesn't require explicit delay between the set and clear
* of reset bit. it could be shorter if tests pass.
*/
writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8);
msleep(10);
writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4);
}
mutex_unlock(&rstc_lock);
return 0;
}
#define SIRFSOC_SYS_RST_BIT BIT(31)
void sirfsoc_restart(char mode, const char *cmd)
{
writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
}