diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 02:56:58 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 02:56:58 +0100 |
commit | 2bcc673101268dc50e52b83226c5bbf38391e16d (patch) | |
tree | 0cdaf6affa8b05d436c2e8b80ff23e8c7f03a30a /drivers/clocksource/sh_cmt.c | |
parent | Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kerne... (diff) | |
parent | timers: Add a function to start/reduce a timer (diff) | |
download | linux-2bcc673101268dc50e52b83226c5bbf38391e16d.tar.xz linux-2bcc673101268dc50e52b83226c5bbf38391e16d.zip |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner:
"Yet another big pile of changes:
- More year 2038 work from Arnd slowly reaching the point where we
need to think about the syscalls themself.
- A new timer function which allows to conditionally (re)arm a timer
only when it's either not running or the new expiry time is sooner
than the armed expiry time. This allows to use a single timer for
multiple timeout requirements w/o caring about the first expiry
time at the call site.
- A new NMI safe accessor to clock real time for the printk timestamp
work. Can be used by tracing, perf as well if required.
- A large number of timer setup conversions from Kees which got
collected here because either maintainers requested so or they
simply got ignored. As Kees pointed out already there are a few
trivial merge conflicts and some redundant commits which was
unavoidable due to the size of this conversion effort.
- Avoid a redundant iteration in the timer wheel softirq processing.
- Provide a mechanism to treat RTC implementations depending on their
hardware properties, i.e. don't inflict the write at the 0.5
seconds boundary which originates from the PC CMOS RTC to all RTCs.
No functional change as drivers need to be updated separately.
- The usual small updates to core code clocksource drivers. Nothing
really exciting"
* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (111 commits)
timers: Add a function to start/reduce a timer
pstore: Use ktime_get_real_fast_ns() instead of __getnstimeofday()
timer: Prepare to change all DEFINE_TIMER() callbacks
netfilter: ipvs: Convert timers to use timer_setup()
scsi: qla2xxx: Convert timers to use timer_setup()
block/aoe: discover_timer: Convert timers to use timer_setup()
ide: Convert timers to use timer_setup()
drbd: Convert timers to use timer_setup()
mailbox: Convert timers to use timer_setup()
crypto: Convert timers to use timer_setup()
drivers/pcmcia: omap1: Fix error in automated timer conversion
ARM: footbridge: Fix typo in timer conversion
drivers/sgi-xp: Convert timers to use timer_setup()
drivers/pcmcia: Convert timers to use timer_setup()
drivers/memstick: Convert timers to use timer_setup()
drivers/macintosh: Convert timers to use timer_setup()
hwrng/xgene-rng: Convert timers to use timer_setup()
auxdisplay: Convert timers to use timer_setup()
sparc/led: Convert timers to use timer_setup()
mips: ip22/32: Convert timers to use timer_setup()
...
Diffstat (limited to 'drivers/clocksource/sh_cmt.c')
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 76 |
1 files changed, 33 insertions, 43 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index e09e8bf0bb9b..70b3cf8e23d0 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -25,6 +25,7 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> @@ -39,16 +40,16 @@ struct sh_cmt_device; * SoC but also on the particular instance. The following table lists the main * characteristics of those flavours. * - * 16B 32B 32B-F 48B 48B-2 + * 16B 32B 32B-F 48B R-Car Gen2 * ----------------------------------------------------------------------------- * Channels 2 1/4 1 6 2/8 * Control Width 16 16 16 16 32 * Counter Width 16 32 32 32/48 32/48 * Shared Start/Stop Y Y Y Y N * - * The 48-bit gen2 version has a per-channel start/stop register located in the - * channel registers block. All other versions have a shared start/stop register - * located in the global space. + * The r8a73a4 / R-Car Gen2 version has a per-channel start/stop register + * located in the channel registers block. All other versions have a shared + * start/stop register located in the global space. * * Channels are indexed from 0 to N-1 in the documentation. The channel index * infers the start/stop bit position in the control register and the channel @@ -66,14 +67,16 @@ struct sh_cmt_device; enum sh_cmt_model { SH_CMT_16BIT, SH_CMT_32BIT, - SH_CMT_32BIT_FAST, SH_CMT_48BIT, - SH_CMT_48BIT_GEN2, + SH_CMT0_RCAR_GEN2, + SH_CMT1_RCAR_GEN2, }; struct sh_cmt_info { enum sh_cmt_model model; + unsigned int channels_mask; + unsigned long width; /* 16 or 32 bit version of hardware block */ unsigned long overflow_bit; unsigned long clear_bits; @@ -200,18 +203,20 @@ static const struct sh_cmt_info sh_cmt_info[] = { .read_count = sh_cmt_read32, .write_count = sh_cmt_write32, }, - [SH_CMT_32BIT_FAST] = { - .model = SH_CMT_32BIT_FAST, + [SH_CMT_48BIT] = { + .model = SH_CMT_48BIT, + .channels_mask = 0x3f, .width = 32, .overflow_bit = SH_CMT32_CMCSR_CMF, .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), - .read_control = sh_cmt_read16, - .write_control = sh_cmt_write16, + .read_control = sh_cmt_read32, + .write_control = sh_cmt_write32, .read_count = sh_cmt_read32, .write_count = sh_cmt_write32, }, - [SH_CMT_48BIT] = { - .model = SH_CMT_48BIT, + [SH_CMT0_RCAR_GEN2] = { + .model = SH_CMT0_RCAR_GEN2, + .channels_mask = 0x60, .width = 32, .overflow_bit = SH_CMT32_CMCSR_CMF, .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), @@ -220,8 +225,9 @@ static const struct sh_cmt_info sh_cmt_info[] = { .read_count = sh_cmt_read32, .write_count = sh_cmt_write32, }, - [SH_CMT_48BIT_GEN2] = { - .model = SH_CMT_48BIT_GEN2, + [SH_CMT1_RCAR_GEN2] = { + .model = SH_CMT1_RCAR_GEN2, + .channels_mask = 0xff, .width = 32, .overflow_bit = SH_CMT32_CMCSR_CMF, .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), @@ -859,6 +865,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, ch->cmt = cmt; ch->index = index; ch->hwidx = hwidx; + ch->timer_bit = hwidx; /* * Compute the address of the channel control register block. For the @@ -873,16 +880,11 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, case SH_CMT_48BIT: ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10; break; - case SH_CMT_32BIT_FAST: - /* - * The 32-bit "fast" timer has a single channel at hwidx 5 but - * is located at offset 0x40 instead of 0x60 for some reason. - */ - ch->ioctrl = cmt->mapbase + 0x40; - break; - case SH_CMT_48BIT_GEN2: + case SH_CMT0_RCAR_GEN2: + case SH_CMT1_RCAR_GEN2: ch->iostart = cmt->mapbase + ch->hwidx * 0x100; ch->ioctrl = ch->iostart + 0x10; + ch->timer_bit = 0; break; } @@ -894,8 +896,6 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, ch->match_value = ch->max_match_value; raw_spin_lock_init(&ch->lock); - ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx; - ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev), clockevent, clocksource); if (ret) { @@ -935,22 +935,18 @@ static const struct platform_device_id sh_cmt_id_table[] = { MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { - { .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] }, - { .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] }, { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] }, - { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] }, + { + /* deprecated, preserved for backward compatibility */ + .compatible = "renesas,cmt-48-gen2", + .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] + }, + { .compatible = "renesas,rcar-gen2-cmt0", .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] }, + { .compatible = "renesas,rcar-gen2-cmt1", .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] }, { } }; MODULE_DEVICE_TABLE(of, sh_cmt_of_table); -static int sh_cmt_parse_dt(struct sh_cmt_device *cmt) -{ - struct device_node *np = cmt->pdev->dev.of_node; - - return of_property_read_u32(np, "renesas,channels-mask", - &cmt->hw_channels); -} - static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) { unsigned int mask; @@ -961,14 +957,8 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) raw_spin_lock_init(&cmt->lock); if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { - const struct of_device_id *id; - - id = of_match_node(sh_cmt_of_table, pdev->dev.of_node); - cmt->info = id->data; - - ret = sh_cmt_parse_dt(cmt); - if (ret < 0) - return ret; + cmt->info = of_device_get_match_data(&pdev->dev); + cmt->hw_channels = cmt->info->channels_mask; } else if (pdev->dev.platform_data) { struct sh_timer_config *cfg = pdev->dev.platform_data; const struct platform_device_id *id = pdev->id_entry; |