Revision | 5046dcb5cf203f9b12f9124883a4a06e5bbd840e (tree) |
---|---|
Zeit | 2016-05-22 15:02:07 |
Autor | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
timer: Add SH4 driver.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
@@ -46,4 +46,10 @@ config OMAP_TIMER | ||
46 | 46 | help |
47 | 47 | Select this to enable an timer for Omap devices. |
48 | 48 | |
49 | +config SH4_TIMER | |
50 | + bool "SH4 timer support" | |
51 | + depends on TIMER | |
52 | + help | |
53 | + Select this to enable an timer for SH4 devices. | |
54 | + | |
49 | 55 | endmenu |
@@ -9,3 +9,4 @@ obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o | ||
9 | 9 | obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o |
10 | 10 | obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o |
11 | 11 | obj-$(CONFIG_OMAP_TIMER) += omap-timer.o |
12 | +obj-$(CONFIG_SH4_TIMER) += sh4_timer.o |
@@ -0,0 +1,89 @@ | ||
1 | +/* | |
2 | + * (C) Copyright 2009 | |
3 | + * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | |
4 | + * | |
5 | + * (C) Copyright 2007-2012 | |
6 | + * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org> | |
7 | + * | |
8 | + * (C) Copyright 2003 | |
9 | + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
10 | + * | |
11 | + * SPDX-License-Identifier: GPL-2.0+ | |
12 | + */ | |
13 | + | |
14 | +#include <common.h> | |
15 | +#include <dm.h> | |
16 | +#include <timer.h> | |
17 | +#include <asm/processor.h> | |
18 | +#include <asm/io.h> | |
19 | + | |
20 | +DECLARE_GLOBAL_DATA_PTR; | |
21 | + | |
22 | +struct sh4_timer_platdata { | |
23 | + unsigned char *regs; | |
24 | + int ch; | |
25 | +}; | |
26 | + | |
27 | +static int timer_read_counter(struct udevice *dev, u64 *count) | |
28 | +{ | |
29 | + struct sh4_timer_platdata *plat = dev_get_platdata(dev); | |
30 | + | |
31 | + *count = timer_conv_64(~readl(plat->regs + 8 + plat->ch * 12 + 4)); | |
32 | + return 0; | |
33 | +} | |
34 | + | |
35 | +static void tmu_timer_start(unsigned char *reg, unsigned int timer) | |
36 | +{ | |
37 | + if (timer > 2) | |
38 | + return; | |
39 | + writeb(readb(reg + 1) | (1 << timer), reg + 1); | |
40 | +} | |
41 | + | |
42 | +static void tmu_timer_stop(unsigned char *reg, unsigned int timer) | |
43 | +{ | |
44 | + if (timer > 2) | |
45 | + return; | |
46 | + writeb(readb(reg + 1) & ~(1 << timer), reg + 1); | |
47 | +} | |
48 | + | |
49 | +static int sh4_timer_probe(struct udevice *dev) | |
50 | +{ | |
51 | + struct sh4_timer_platdata *plat = dev_get_platdata(dev); | |
52 | + | |
53 | + writew(0, plat->regs + 8 + (plat->ch * 12)); | |
54 | + | |
55 | + tmu_timer_stop(plat->regs, plat->ch); | |
56 | + tmu_timer_start(plat->regs, plat->ch); | |
57 | + | |
58 | + return 0; | |
59 | +} | |
60 | + | |
61 | +static int sh4_timer_ofdata_to_platdata(struct udevice *dev) | |
62 | +{ | |
63 | + struct sh4_timer_platdata *plat = dev_get_platdata(dev); | |
64 | + | |
65 | + plat->regs = map_physmem(dev_get_addr(dev), 48, MAP_NOCACHE); | |
66 | + plat->ch = fdtdec_get_int(gd->fdt_blob, dev->of_offset, | |
67 | + "renesas,channel", 0); | |
68 | + return 0; | |
69 | +} | |
70 | + | |
71 | +static const struct timer_ops sh4_timer_ops = { | |
72 | + .get_count = timer_read_counter, | |
73 | +}; | |
74 | + | |
75 | +static const struct udevice_id sh4_timer_ids[] = { | |
76 | + { .compatible = "renesas,sh4-tmu" }, | |
77 | + {} | |
78 | +}; | |
79 | + | |
80 | +U_BOOT_DRIVER(sh4_timer) = { | |
81 | + .name = "sh4_timer", | |
82 | + .id = UCLASS_TIMER, | |
83 | + .of_match = of_match_ptr(sh4_timer_ids), | |
84 | + .ofdata_to_platdata = of_match_ptr(sh4_timer_ofdata_to_platdata), | |
85 | + .platdata_auto_alloc_size = sizeof(struct sh4_timer_platdata), | |
86 | + .probe = sh4_timer_probe, | |
87 | + .ops = &sh4_timer_ops, | |
88 | + .flags = DM_FLAG_PRE_RELOC, | |
89 | +}; |