dect
/
linux-2.6
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
linux-2.6/arch/arm/mach-bcm2835/bcm2835.c

111 lines
2.6 KiB
C
Raw Normal View History

/*
* Copyright (C) 2010 Broadcom
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/init.h>
ARM: bcm2835: add interrupt controller driver The BCM2835 contains a custom interrupt controller, which supports 72 interrupt sources using a 2-level register scheme. The interrupt controller, or the HW block containing it, is referred to occasionally as "armctrl" in the SoC documentation, hence the symbol naming in the code. This patch was extracted from git://github.com/lp0/linux.git branch rpi-split as of 2012/09/08, and modified as follows: * s/bcm2708/bcm2835/. * Modified device tree vendor prefix. * Moved implementation to drivers/irchip/. * Added devicetree documentation, and hence removed list of IRQs from bcm2835.dtsi. * Changed shift in MAKE_HWIRQ() and HWIRQ_BANK() from 8 to 5 to reduce the size of the hwirq space, and pass the total size of the hwirq space to irq_domain_add_linear(), rather than just the number of valid hwirqs; the two are different due to the hwirq space being sparse. * Added the interrupt controller DT node to the top-level of the DT, rather than nesting it inside a /axi node. Hence, changed the reg value since /axi had a ranges property. This seems simpler to me, but I'm not sure if everyone will like this change or not. * Don't set struct irq_domain_ops.map = irq_domain_simple_map, hence removing the need to patch include/linux/irqdomain.h or kernel/irq/irqdomain.c. * Simplified armctrl_of_init() using of_iomap(). * Removed unused IS_VALID_BANK()/IS_VALID_IRQ() macros. * Renamed armctrl_handle_irq() to prevent possible symbol clashes. * Made armctrl_of_init() static. * Removed comment "Each bank is registered as a separate interrupt controller" since this is no longer true. * Removed FSF address from license header. * Added my name to copyright header. Signed-off-by: Chris Boot <bootc@bootc.net> Signed-off-by: Simon Arlott <simon@fire.lp0.eu> Signed-off-by: Dom Cobley <popcornmix@gmail.com> Signed-off-by: Dom Cobley <dc4@broadcom.com> Signed-off-by: Stephen Warren <swarren@wwwdotorg.org> Acked-by: Arnd Bergmann <arnd@arndb.de>
2012-09-13 01:57:26 +00:00
#include <linux/irqchip/bcm2835.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
ARM: bcm2835: add system timer The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. Each channel has an output compare register, which is compared against the 32 least significant bits of the free running counter values, and generates an interrupt. Timer 3 is used as the Linux timer. The BCM2835 also contains an SP804-based timer module. However, it apparently has significant differences from the standard SP804 IP block, and Broadcom's documentation recommends using the system timer instead. This patch was extracted from git://github.com/lp0/linux.git branch rpi-split as of 2012/09/08, and modified as follows: * s/bcm2708/bcm2835/. * Modified device tree vendor prefix. * Moved to drivers/clocksource/. This looks like the desired location for such code now. * Added DT binding docs. * Moved struct sys_timer bcm2835_timer into time.c to encapsulate it more. * Simplified bcm2835_time_init() to find one matching node and operate on it, rather than looping over all matching nodes. This seems more consistent with other clocksource code. * Simplified bcm2835_time_init() using of_iomap(). * Renamed struct bcm2835_timer.index to match_mask to better represent its purpose. * s/printk(PR_INFO/pr_info(/ Signed-off-by: Chris Boot <bootc@bootc.net> Signed-off-by: Simon Arlott <simon@fire.lp0.eu> Signed-off-by: Dom Cobley <popcornmix@gmail.com> Signed-off-by: Dom Cobley <dc4@broadcom.com> Signed-off-by: Stephen Warren <swarren@wwwdotorg.org> Acked-by: Arnd Bergmann <arnd@arndb.de>
2012-09-11 04:38:35 +00:00
#include <linux/bcm2835_timer.h>
#include <linux/clk/bcm2835.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/bcm2835_soc.h>
#define PM_RSTC 0x1c
#define PM_WDOG 0x24
#define PM_PASSWORD 0x5a000000
#define PM_RSTC_WRCFG_MASK 0x00000030
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
static void __iomem *wdt_regs;
/*
* The machine restart method can be called from an atomic context so we won't
* be able to ioremap the regs then.
*/
static void bcm2835_setup_restart(void)
{
struct device_node *np = of_find_compatible_node(NULL, NULL,
"brcm,bcm2835-pm-wdt");
if (WARN(!np, "unable to setup watchdog restart"))
return;
wdt_regs = of_iomap(np, 0);
WARN(!wdt_regs, "failed to remap watchdog regs");
}
static void bcm2835_restart(char mode, const char *cmd)
{
u32 val;
if (!wdt_regs)
return;
/* use a timeout of 10 ticks (~150us) */
writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG);
val = readl_relaxed(wdt_regs + PM_RSTC);
val &= ~PM_RSTC_WRCFG_MASK;
val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
writel_relaxed(val, wdt_regs + PM_RSTC);
/* No sleeping, possibly atomic. */
mdelay(1);
}
static struct map_desc io_map __initdata = {
.virtual = BCM2835_PERIPH_VIRT,
.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
.length = BCM2835_PERIPH_SIZE,
.type = MT_DEVICE
};
static void __init bcm2835_map_io(void)
{
iotable_init(&io_map, 1);
}
static void __init bcm2835_init(void)
{
int ret;
bcm2835_setup_restart();
bcm2835_init_clocks();
ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
NULL);
if (ret) {
pr_err("of_platform_populate failed: %d\n", ret);
BUG();
}
}
static const char * const bcm2835_compat[] = {
"brcm,bcm2835",
NULL
};
DT_MACHINE_START(BCM2835, "BCM2835")
.map_io = bcm2835_map_io,
.init_irq = bcm2835_init_irq,
.handle_irq = bcm2835_handle_irq,
.init_machine = bcm2835_init,
.timer = &bcm2835_timer,
.restart = bcm2835_restart,
.dt_compat = bcm2835_compat
MACHINE_END