diff for duplicates of <20121007015406.470633343@gmail.com> diff --git a/a/1.txt b/N1/1.txt index 1be3c73..e3c8192 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,3 +1,325 @@ -An embedded and charset-unspecified text was scrubbed... -Name: arm-bcm476x-add-system-timer.patch -URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121007/f50ca8e4/attachment.ksh> +From: Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org> + +System timer implementation for the BCM476x SoCs. + +Signed-off-by: Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org> +--- + Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt | 22 + + arch/arm/boot/dts/bcm476x.dtsi | 8 + + arch/arm/mach-bcm476x/bcm476x.c | 10 - + drivers/clocksource/Makefile | 1 + + drivers/clocksource/bcm476x_timer.c | 188 ++++++++++ + include/linux/bcm476x_timer.h | 24 + + 6 files changed, 244 insertions(+), 9 deletions(-) + +Index: b/Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt +=================================================================== +--- /dev/null ++++ b/Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt +@@ -0,0 +1,22 @@ ++BCM476x System Timer ++ ++The System Timer peripheral provides either two or four 32-bit timer ++channels. BCM476x has three timers at 0xba000, 0xbb000 and 0xd1000. The ++first two provide four channels, the last (in the AON - Always ON power ++domain) provides only two. ++ ++Required properties: ++ ++- compatible : should be "brcm,bcm476x-system-timer" ++- reg : Specifies base physical address and size of the registers. ++- interrupts : A list of 2 or 4 interrupt sinks; one per timer channel. ++- clock-frequency : The frequency of the clock that drives the counter, in Hz. ++ ++Example: ++ ++timer { ++ compatible = "brcm,bcm476x-system-timer"; ++ reg = <0xba000 0x1000>; ++ interrupts = <4>, <11>; ++ clock-frequency = <24000000>; ++}; +Index: b/arch/arm/boot/dts/bcm476x.dtsi +=================================================================== +--- a/arch/arm/boot/dts/bcm476x.dtsi ++++ b/arch/arm/boot/dts/bcm476x.dtsi +@@ -14,6 +14,14 @@ + #size-cells = <1>; + ranges; + ++ timer { ++ compatible = "brcm,bcm476x-system-timer"; ++ reg = <0xba000 0x1000>; ++ interrupt-parent = <&vic0>; ++ interrupts = <4>, <11>; ++ clock-frequency = <24000000>; ++ }; ++ + vic0: interrupt-controller@80000 { + compatible = "brcm,bcm476x-pl192", "arm,pl192-vic", "arm,primecell"; + reg = <0x80000 0x1000>; +Index: b/arch/arm/mach-bcm476x/bcm476x.c +=================================================================== +--- a/arch/arm/mach-bcm476x/bcm476x.c ++++ b/arch/arm/mach-bcm476x/bcm476x.c +@@ -17,11 +17,11 @@ + #include <linux/init.h> + #include <linux/of_irq.h> + #include <linux/of_platform.h> ++#include <linux/bcm476x_timer.h> + + #include <asm/hardware/vic.h> + #include <asm/mach/arch.h> + #include <asm/mach/map.h> +-#include <asm/mach/time.h> + + #define BCM476X_PERIPH_PHYS 0x00080000 + #define BCM476X_PERIPH_VIRT 0xd0080000 +@@ -60,14 +60,6 @@ static void __init bcm476x_init_irq(void + of_irq_init(vic_of_match); + } + +-static void __init bcm476x_timer_init(void) +-{ +-} +- +-struct sys_timer bcm476x_timer = { +- .init = bcm476x_timer_init +-}; +- + static const char * const bcm476x_compat[] = { + "brcm,bcm476x", + NULL +Index: b/drivers/clocksource/Makefile +=================================================================== +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -14,5 +14,6 @@ obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_ + obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o + obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o + obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o ++obj-$(CONFIG_ARCH_BCM476X) += bcm476x_timer.o + + obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o +Index: b/drivers/clocksource/bcm476x_timer.c +=================================================================== +--- /dev/null ++++ b/drivers/clocksource/bcm476x_timer.c +@@ -0,0 +1,188 @@ ++/* ++ * Broadcom BCM476x SoCs system timer ++ * ++ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org> ++ * ++ * 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/bcm476x_timer.h> ++#include <linux/bitops.h> ++#include <linux/clockchips.h> ++#include <linux/clocksource.h> ++#include <linux/interrupt.h> ++#include <linux/irqreturn.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/of_address.h> ++#include <linux/of_irq.h> ++#include <linux/of_platform.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++ ++#include <asm/sched_clock.h> ++#include <asm/irq.h> ++ ++#define TIMER_LOAD_OFFSET 0x00 /* load */ ++#define TIMER_VALUE_OFFSET 0x04 /* value */ ++#define TIMER_CONTROL_OFFSET 0x08 /* control */ ++#define TIMER_INTCLR_OFFSET 0x0c /* interrupt clear */ ++#define TIMER_RIS_OFFSET 0x10 /* raw interrupt */ ++#define TIMER_MIS_OFFSET 0x14 /* masked interrupt status */ ++#define TIMER_BGLOAD_OFFSET 0x18 /* background load */ ++ ++#define TIMER_CTRL_ONESHOTMODE BIT(0) /* One shot mode */ ++#define TIMER_CTRL_32BIT BIT(1) /* 32-bit counter mode */ ++#define TIMER_CTRL_IE BIT(5) /* Interrupt enable */ ++#define TIMER_CTRL_PERIODIC BIT(6) /* Periodic mode */ ++#define TIMER_CTRL_EN BIT(7) /* Timer enable */ ++#define TIMER_CTRL_CLK2 BIT(9) /* Clock 2 selected */ ++#define TIMER_CTRL_PREBY16 (1 << 2) /* prescale divide by 16 */ ++#define TIMER_CTRL_PREBY256 (2 << 2) /* prescale divide by 256 */ ++ ++struct bcm476x_timer { ++ void __iomem *base; ++ struct clock_event_device evt; ++ struct irqaction act; ++}; ++ ++static inline void __iomem *to_load(struct bcm476x_timer *timer) ++{ ++ return timer->base + TIMER_LOAD_OFFSET; ++} ++ ++static inline void __iomem *to_control(struct bcm476x_timer *timer) ++{ ++ return timer->base + TIMER_CONTROL_OFFSET; ++} ++ ++static inline void __iomem *to_intclr(struct bcm476x_timer *timer) ++{ ++ return timer->base + TIMER_INTCLR_OFFSET; ++} ++ ++static inline void __iomem *to_ris(struct bcm476x_timer *timer) ++{ ++ return timer->base + TIMER_RIS_OFFSET; ++} ++ ++static inline void __iomem *to_mis(struct bcm476x_timer *timer) ++{ ++ return timer->base + TIMER_MIS_OFFSET; ++} ++ ++static void bcm476x_timer_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt_dev) ++{ ++ struct bcm476x_timer *timer; ++ u32 val; ++ ++ timer = container_of(evt_dev, struct bcm476x_timer, evt); ++ val = TIMER_CTRL_CLK2 | TIMER_CTRL_32BIT | ++ TIMER_CTRL_IE | TIMER_CTRL_EN; ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ writel(val | TIMER_CTRL_ONESHOTMODE, to_control(timer)); ++ break; ++ case CLOCK_EVT_MODE_RESUME: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ break; ++ default: ++ WARN(1, "%s: unhandled event mode %d\n", __func__, mode); ++ break; ++ } ++} ++ ++static int bcm476x_timer_set_next_event(unsigned long event, ++ struct clock_event_device *evt_dev) ++{ ++ struct bcm476x_timer *timer; ++ ++ timer = container_of(evt_dev, struct bcm476x_timer, evt); ++ writel(event, to_load(timer)); ++ return 0; ++} ++ ++static irqreturn_t bcm476x_timer_interrupt(int irq, void *dev_id) ++{ ++ struct bcm476x_timer *timer = dev_id; ++ void (*event_handler)(struct clock_event_device *); ++ ++ /* check the (masked) interrupt status */ ++ if (!readl_relaxed(to_mis(timer))) ++ return IRQ_NONE; ++ ++ /* clear the timer interrupt */ ++ writel_relaxed(1, to_intclr(timer)); ++ ++ event_handler = ACCESS_ONCE(timer->evt.event_handler); ++ if (event_handler) ++ event_handler(&timer->evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct of_device_id bcm476x_timer_match[] __initconst = { ++ { .compatible = "brcm,bcm476x-system-timer" }, ++ {} ++}; ++ ++static void __init bcm476x_timer_init(void) ++{ ++ struct device_node *node; ++ void __iomem *base; ++ u32 freq; ++ int irq; ++ struct bcm476x_timer *timer; ++ ++ node = of_find_matching_node(NULL, bcm476x_timer_match); ++ if (!node) ++ panic("No bcm476x timer node"); ++ ++ base = of_iomap(node, 0); ++ if (!base) ++ panic("Can't remap timer registers"); ++ ++ if (of_property_read_u32(node, "clock-frequency", &freq)) ++ panic("Can't read timer frequency"); ++ if (freq != 32000 && freq != 24000000) ++ panic("Invalid timer frequency"); ++ ++ timer = kzalloc(sizeof(*timer), GFP_KERNEL); ++ if (!timer) ++ panic("Can't allocate timer struct\n"); ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq <= 0) ++ panic("Can't parse timer IRQ"); ++ ++ timer->base = base; ++ timer->evt.name = node->name; ++ timer->evt.rating = 300; ++ timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; ++ timer->evt.set_mode = bcm476x_timer_set_mode; ++ timer->evt.set_next_event = bcm476x_timer_set_next_event; ++ timer->evt.cpumask = cpumask_of(0); ++ timer->act.name = node->name; ++ timer->act.flags = IRQF_TIMER | IRQF_SHARED; ++ timer->act.dev_id = timer; ++ timer->act.handler = bcm476x_timer_interrupt; ++ ++ if (setup_irq(irq, &timer->act)) ++ panic("Can't set up timer IRQ\n"); ++ ++ clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff); ++} ++ ++struct sys_timer bcm476x_timer = { ++ .init = bcm476x_timer_init, ++}; +Index: b/include/linux/bcm476x_timer.h +=================================================================== +--- /dev/null ++++ b/include/linux/bcm476x_timer.h +@@ -0,0 +1,24 @@ ++/* ++ * Broadcom BCM476x SoCs system timer ++ * ++ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org> ++ * ++ * 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. ++ */ ++ ++#ifndef __BCM476X_TIMER_H ++#define __BCM476X_TIMER_H ++ ++#include <asm/mach/time.h> ++ ++extern struct sys_timer bcm476x_timer; ++ ++#endif diff --git a/a/content_digest b/N1/content_digest index 2aaca5a..a00d5e1 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,12 +1,337 @@ "ref\020121007015300.828366635@gmail.com\0" - "From\0cavokz@gmail.com (Domenico Andreoli)\0" + "From\0Domenico Andreoli <cavokz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>\0" "Subject\0[PATCH 2/6] ARM: bcm476x: Add system timer\0" "Date\0Sun, 07 Oct 2012 03:53:02 +0200\0" - "To\0linux-arm-kernel@lists.infradead.org\0" + "To\0linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org\0" + "Cc\0Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>" + " devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org\0" "\00:1\0" + "fn\0arm-bcm476x-add-system-timer.patch\0" "b\0" - "An embedded and charset-unspecified text was scrubbed...\n" - "Name: arm-bcm476x-add-system-timer.patch\n" - URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121007/f50ca8e4/attachment.ksh> + "From: Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>\n" + "\n" + "System timer implementation for the BCM476x SoCs.\n" + "\n" + "Signed-off-by: Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>\n" + "---\n" + " Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt | 22 +\n" + " arch/arm/boot/dts/bcm476x.dtsi | 8 +\n" + " arch/arm/mach-bcm476x/bcm476x.c | 10 -\n" + " drivers/clocksource/Makefile | 1 +\n" + " drivers/clocksource/bcm476x_timer.c | 188 ++++++++++\n" + " include/linux/bcm476x_timer.h | 24 +\n" + " 6 files changed, 244 insertions(+), 9 deletions(-)\n" + "\n" + "Index: b/Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt\n" + "===================================================================\n" + "--- /dev/null\n" + "+++ b/Documentation/devicetree/bindings/timer/brcm,bcm476x-system-timer.txt\n" + "@@ -0,0 +1,22 @@\n" + "+BCM476x System Timer\n" + "+\n" + "+The System Timer peripheral provides either two or four 32-bit timer\n" + "+channels. BCM476x has three timers at 0xba000, 0xbb000 and 0xd1000. The\n" + "+first two provide four channels, the last (in the AON - Always ON power\n" + "+domain) provides only two.\n" + "+\n" + "+Required properties:\n" + "+\n" + "+- compatible : should be \"brcm,bcm476x-system-timer\"\n" + "+- reg : Specifies base physical address and size of the registers.\n" + "+- interrupts : A list of 2 or 4 interrupt sinks; one per timer channel.\n" + "+- clock-frequency : The frequency of the clock that drives the counter, in Hz.\n" + "+\n" + "+Example:\n" + "+\n" + "+timer {\n" + "+\tcompatible = \"brcm,bcm476x-system-timer\";\n" + "+\treg = <0xba000 0x1000>;\n" + "+\tinterrupts = <4>, <11>;\n" + "+\tclock-frequency = <24000000>;\n" + "+};\n" + "Index: b/arch/arm/boot/dts/bcm476x.dtsi\n" + "===================================================================\n" + "--- a/arch/arm/boot/dts/bcm476x.dtsi\n" + "+++ b/arch/arm/boot/dts/bcm476x.dtsi\n" + "@@ -14,6 +14,14 @@\n" + " \t\t#size-cells = <1>;\n" + " \t\tranges;\n" + " \n" + "+\t\ttimer {\n" + "+\t\t\tcompatible = \"brcm,bcm476x-system-timer\";\n" + "+\t\t\treg = <0xba000 0x1000>;\n" + "+\t\t\tinterrupt-parent = <&vic0>;\n" + "+\t\t\tinterrupts = <4>, <11>;\n" + "+\t\t\tclock-frequency = <24000000>;\n" + "+\t\t};\n" + "+\n" + " \t\tvic0: interrupt-controller@80000 {\n" + " \t\t\tcompatible = \"brcm,bcm476x-pl192\", \"arm,pl192-vic\", \"arm,primecell\";\n" + " \t\t\treg = <0x80000 0x1000>;\n" + "Index: b/arch/arm/mach-bcm476x/bcm476x.c\n" + "===================================================================\n" + "--- a/arch/arm/mach-bcm476x/bcm476x.c\n" + "+++ b/arch/arm/mach-bcm476x/bcm476x.c\n" + "@@ -17,11 +17,11 @@\n" + " #include <linux/init.h>\n" + " #include <linux/of_irq.h>\n" + " #include <linux/of_platform.h>\n" + "+#include <linux/bcm476x_timer.h>\n" + " \n" + " #include <asm/hardware/vic.h>\n" + " #include <asm/mach/arch.h>\n" + " #include <asm/mach/map.h>\n" + "-#include <asm/mach/time.h>\n" + " \n" + " #define BCM476X_PERIPH_PHYS 0x00080000\n" + " #define BCM476X_PERIPH_VIRT 0xd0080000\n" + "@@ -60,14 +60,6 @@ static void __init bcm476x_init_irq(void\n" + " \tof_irq_init(vic_of_match);\n" + " }\n" + " \n" + "-static void __init bcm476x_timer_init(void)\n" + "-{\n" + "-}\n" + "-\n" + "-struct sys_timer bcm476x_timer = {\n" + "-\t.init = bcm476x_timer_init\n" + "-};\n" + "-\n" + " static const char * const bcm476x_compat[] = {\n" + " \t\"brcm,bcm476x\",\n" + " \tNULL\n" + "Index: b/drivers/clocksource/Makefile\n" + "===================================================================\n" + "--- a/drivers/clocksource/Makefile\n" + "+++ b/drivers/clocksource/Makefile\n" + "@@ -14,5 +14,6 @@ obj-$(CONFIG_DW_APB_TIMER_OF)\t+= dw_apb_\n" + " obj-$(CONFIG_CLKSRC_DBX500_PRCMU)\t+= clksrc-dbx500-prcmu.o\n" + " obj-$(CONFIG_ARMADA_370_XP_TIMER)\t+= time-armada-370-xp.o\n" + " obj-$(CONFIG_ARCH_BCM2835)\t+= bcm2835_timer.o\n" + "+obj-$(CONFIG_ARCH_BCM476X)\t+= bcm476x_timer.o\n" + " \n" + " obj-$(CONFIG_CLKSRC_ARM_GENERIC)\t+= arm_generic.o\n" + "Index: b/drivers/clocksource/bcm476x_timer.c\n" + "===================================================================\n" + "--- /dev/null\n" + "+++ b/drivers/clocksource/bcm476x_timer.c\n" + "@@ -0,0 +1,188 @@\n" + "+/*\n" + "+ * Broadcom BCM476x SoCs system timer\n" + "+ *\n" + "+ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>\n" + "+ *\n" + "+ * This program is free software; you can redistribute it and/or modify\n" + "+ * it under the terms of the GNU General Public License as published by\n" + "+ * the Free Software Foundation; either version 2 of the License, or\n" + "+ * (at your option) any later version.\n" + "+ *\n" + "+ * This program is distributed in the hope that it will be useful,\n" + "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "+ * GNU General Public License for more details.\n" + "+ */\n" + "+\n" + "+#include <linux/bcm476x_timer.h>\n" + "+#include <linux/bitops.h>\n" + "+#include <linux/clockchips.h>\n" + "+#include <linux/clocksource.h>\n" + "+#include <linux/interrupt.h>\n" + "+#include <linux/irqreturn.h>\n" + "+#include <linux/kernel.h>\n" + "+#include <linux/module.h>\n" + "+#include <linux/of_address.h>\n" + "+#include <linux/of_irq.h>\n" + "+#include <linux/of_platform.h>\n" + "+#include <linux/slab.h>\n" + "+#include <linux/string.h>\n" + "+\n" + "+#include <asm/sched_clock.h>\n" + "+#include <asm/irq.h>\n" + "+\n" + "+#define TIMER_LOAD_OFFSET 0x00 /* load */\n" + "+#define TIMER_VALUE_OFFSET 0x04 /* value */\n" + "+#define TIMER_CONTROL_OFFSET 0x08 /* control */\n" + "+#define TIMER_INTCLR_OFFSET 0x0c /* interrupt clear */\n" + "+#define TIMER_RIS_OFFSET 0x10 /* raw interrupt */\n" + "+#define TIMER_MIS_OFFSET 0x14 /* masked interrupt status */\n" + "+#define TIMER_BGLOAD_OFFSET 0x18 /* background load */\n" + "+\n" + "+#define TIMER_CTRL_ONESHOTMODE BIT(0) /* One shot mode */\n" + "+#define TIMER_CTRL_32BIT BIT(1) /* 32-bit counter mode */\n" + "+#define TIMER_CTRL_IE BIT(5) /* Interrupt enable */\n" + "+#define TIMER_CTRL_PERIODIC BIT(6) /* Periodic mode */\n" + "+#define TIMER_CTRL_EN BIT(7) /* Timer enable */\n" + "+#define TIMER_CTRL_CLK2 BIT(9) /* Clock 2 selected */\n" + "+#define TIMER_CTRL_PREBY16 (1 << 2) /* prescale divide by 16 */\n" + "+#define TIMER_CTRL_PREBY256 (2 << 2) /* prescale divide by 256 */\n" + "+\n" + "+struct bcm476x_timer {\n" + "+\tvoid __iomem *base;\n" + "+\tstruct clock_event_device evt;\n" + "+\tstruct irqaction act;\n" + "+};\n" + "+\n" + "+static inline void __iomem *to_load(struct bcm476x_timer *timer)\n" + "+{\n" + "+\treturn timer->base + TIMER_LOAD_OFFSET;\n" + "+}\n" + "+\n" + "+static inline void __iomem *to_control(struct bcm476x_timer *timer)\n" + "+{\n" + "+\treturn timer->base + TIMER_CONTROL_OFFSET;\n" + "+}\n" + "+\n" + "+static inline void __iomem *to_intclr(struct bcm476x_timer *timer)\n" + "+{\n" + "+\treturn timer->base + TIMER_INTCLR_OFFSET;\n" + "+}\n" + "+\n" + "+static inline void __iomem *to_ris(struct bcm476x_timer *timer)\n" + "+{\n" + "+\treturn timer->base + TIMER_RIS_OFFSET;\n" + "+}\n" + "+\n" + "+static inline void __iomem *to_mis(struct bcm476x_timer *timer)\n" + "+{\n" + "+\treturn timer->base + TIMER_MIS_OFFSET;\n" + "+}\n" + "+\n" + "+static void bcm476x_timer_set_mode(enum clock_event_mode mode,\n" + "+\tstruct clock_event_device *evt_dev)\n" + "+{\n" + "+\tstruct bcm476x_timer *timer;\n" + "+\tu32 val;\n" + "+\n" + "+\ttimer = container_of(evt_dev, struct bcm476x_timer, evt);\n" + "+\tval = TIMER_CTRL_CLK2 | TIMER_CTRL_32BIT |\n" + "+\t TIMER_CTRL_IE | TIMER_CTRL_EN;\n" + "+\n" + "+\tswitch (mode) {\n" + "+\tcase CLOCK_EVT_MODE_ONESHOT:\n" + "+\t\twritel(val | TIMER_CTRL_ONESHOTMODE, to_control(timer));\n" + "+\t\tbreak;\n" + "+\tcase CLOCK_EVT_MODE_RESUME:\n" + "+\tcase CLOCK_EVT_MODE_SHUTDOWN:\n" + "+\t\tbreak;\n" + "+\tdefault:\n" + "+\t\tWARN(1, \"%s: unhandled event mode %d\\n\", __func__, mode);\n" + "+\t\tbreak;\n" + "+\t}\n" + "+}\n" + "+\n" + "+static int bcm476x_timer_set_next_event(unsigned long event,\n" + "+\tstruct clock_event_device *evt_dev)\n" + "+{\n" + "+\tstruct bcm476x_timer *timer;\n" + "+\n" + "+\ttimer = container_of(evt_dev, struct bcm476x_timer, evt);\n" + "+\twritel(event, to_load(timer));\n" + "+\treturn 0;\n" + "+}\n" + "+\n" + "+static irqreturn_t bcm476x_timer_interrupt(int irq, void *dev_id)\n" + "+{\n" + "+\tstruct bcm476x_timer *timer = dev_id;\n" + "+\tvoid (*event_handler)(struct clock_event_device *);\n" + "+\n" + "+\t/* check the (masked) interrupt status */\n" + "+\tif (!readl_relaxed(to_mis(timer)))\n" + "+\t\treturn IRQ_NONE;\n" + "+\n" + "+\t/* clear the timer interrupt */\n" + "+\twritel_relaxed(1, to_intclr(timer));\n" + "+\n" + "+\tevent_handler = ACCESS_ONCE(timer->evt.event_handler);\n" + "+\tif (event_handler)\n" + "+\t\tevent_handler(&timer->evt);\n" + "+\n" + "+\treturn IRQ_HANDLED;\n" + "+}\n" + "+\n" + "+static struct of_device_id bcm476x_timer_match[] __initconst = {\n" + "+\t{ .compatible = \"brcm,bcm476x-system-timer\" },\n" + "+\t{}\n" + "+};\n" + "+\n" + "+static void __init bcm476x_timer_init(void)\n" + "+{\n" + "+\tstruct device_node *node;\n" + "+\tvoid __iomem *base;\n" + "+\tu32 freq;\n" + "+\tint irq;\n" + "+\tstruct bcm476x_timer *timer;\n" + "+\n" + "+\tnode = of_find_matching_node(NULL, bcm476x_timer_match);\n" + "+\tif (!node)\n" + "+\t\tpanic(\"No bcm476x timer node\");\n" + "+\n" + "+\tbase = of_iomap(node, 0);\n" + "+\tif (!base)\n" + "+\t\tpanic(\"Can't remap timer registers\");\n" + "+\n" + "+\tif (of_property_read_u32(node, \"clock-frequency\", &freq))\n" + "+\t\tpanic(\"Can't read timer frequency\");\n" + "+\tif (freq != 32000 && freq != 24000000)\n" + "+\t\tpanic(\"Invalid timer frequency\");\n" + "+\n" + "+\ttimer = kzalloc(sizeof(*timer), GFP_KERNEL);\n" + "+\tif (!timer)\n" + "+\t\tpanic(\"Can't allocate timer struct\\n\");\n" + "+\n" + "+\tirq = irq_of_parse_and_map(node, 0);\n" + "+\tif (irq <= 0)\n" + "+\t\tpanic(\"Can't parse timer IRQ\");\n" + "+\n" + "+\ttimer->base = base;\n" + "+\ttimer->evt.name = node->name;\n" + "+\ttimer->evt.rating = 300;\n" + "+\ttimer->evt.features = CLOCK_EVT_FEAT_ONESHOT;\n" + "+\ttimer->evt.set_mode = bcm476x_timer_set_mode;\n" + "+\ttimer->evt.set_next_event = bcm476x_timer_set_next_event;\n" + "+\ttimer->evt.cpumask = cpumask_of(0);\n" + "+\ttimer->act.name = node->name;\n" + "+\ttimer->act.flags = IRQF_TIMER | IRQF_SHARED;\n" + "+\ttimer->act.dev_id = timer;\n" + "+\ttimer->act.handler = bcm476x_timer_interrupt;\n" + "+\n" + "+\tif (setup_irq(irq, &timer->act))\n" + "+\t\tpanic(\"Can't set up timer IRQ\\n\");\n" + "+\n" + "+\tclockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);\n" + "+}\n" + "+\n" + "+struct sys_timer bcm476x_timer = {\n" + "+\t.init = bcm476x_timer_init,\n" + "+};\n" + "Index: b/include/linux/bcm476x_timer.h\n" + "===================================================================\n" + "--- /dev/null\n" + "+++ b/include/linux/bcm476x_timer.h\n" + "@@ -0,0 +1,24 @@\n" + "+/*\n" + "+ * Broadcom BCM476x SoCs system timer\n" + "+ *\n" + "+ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>\n" + "+ *\n" + "+ * This program is free software; you can redistribute it and/or modify\n" + "+ * it under the terms of the GNU General Public License as published by\n" + "+ * the Free Software Foundation; either version 2 of the License, or\n" + "+ * (at your option) any later version.\n" + "+ *\n" + "+ * This program is distributed in the hope that it will be useful,\n" + "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "+ * GNU General Public License for more details.\n" + "+ */\n" + "+\n" + "+#ifndef __BCM476X_TIMER_H\n" + "+#define __BCM476X_TIMER_H\n" + "+\n" + "+#include <asm/mach/time.h>\n" + "+\n" + "+extern struct sys_timer bcm476x_timer;\n" + "+\n" + +#endif -fc487edac843927d57608ce0699835e20c9793c82d11c6d2f315ea06d1d7938b +efc9651a2517dfe1b8a459d9c6bea506917457290d8f8496b84a161e8bd9957b
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.