13fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* 23fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * SuperH Timer Support - CMT 33fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * 43fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * Copyright (C) 2008 Magnus Damm 53fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * 63fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * This program is free software; you can redistribute it and/or modify 73fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * it under the terms of the GNU General Public License as published by 83fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * the Free Software Foundation; either version 2 of the License 93fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * 103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * This program is distributed in the hope that it will be useful, 113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * but WITHOUT ANY WARRANTY; without even the implied warranty of 123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * GNU General Public License for more details. 143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 16e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/clk.h> 17e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/clockchips.h> 18e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/clocksource.h> 19e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/delay.h> 20e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/err.h> 213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/init.h> 223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/interrupt.h> 233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/io.h> 24e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/ioport.h> 253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/irq.h> 267deeab5dc414240a341e80f41b5f00620aa9ef98Paul Gortmaker#include <linux/module.h> 271768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart#include <linux/of.h> 28e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/platform_device.h> 29615a445f7f8a077c145e737864ae59a4d8717882Rafael J. Wysocki#include <linux/pm_domain.h> 30bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki#include <linux/pm_runtime.h> 31e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/sh_timer.h> 32e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/slab.h> 33e7a9bcc2372b0e62443569c63a369cfd528db4f4Laurent Pinchart#include <linux/spinlock.h> 343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 352653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchartstruct sh_cmt_device; 367269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart 372cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart/* 382cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * The CMT comes in 5 different identified flavours, depending not only on the 392cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * SoC but also on the particular instance. The following table lists the main 402cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * characteristics of those flavours. 412cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * 422cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * 16B 32B 32B-F 48B 48B-2 432cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * ----------------------------------------------------------------------------- 442cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * Channels 2 1/4 1 6 2/8 452cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * Control Width 16 16 16 16 32 462cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * Counter Width 16 32 32 32/48 32/48 472cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * Shared Start/Stop Y Y Y Y N 482cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * 492cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * The 48-bit gen2 version has a per-channel start/stop register located in the 502cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * channel registers block. All other versions have a shared start/stop register 512cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * located in the global space. 522cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * 5381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * Channels are indexed from 0 to N-1 in the documentation. The channel index 5481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * infers the start/stop bit position in the control register and the channel 5581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * registers block address. Some CMT instances have a subset of channels 5681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * available, in which case the index in the documentation doesn't match the 5781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * "real" index as implemented in hardware. This is for instance the case with 5881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * CMT0 on r8a7740, which is a 32-bit variant with a single channel numbered 0 5981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * in the documentation but using start/stop bit 5 and having its registers 6081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * block at 0x60. 6181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * 6281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit 632cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart * channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable. 642cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart */ 652cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 662cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchartenum sh_cmt_model { 672cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart SH_CMT_16BIT, 682cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart SH_CMT_32BIT, 692cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart SH_CMT_32BIT_FAST, 702cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart SH_CMT_48BIT, 712cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart SH_CMT_48BIT_GEN2, 722cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart}; 732cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 742cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchartstruct sh_cmt_info { 752cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart enum sh_cmt_model model; 762cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 772cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long width; /* 16 or 32 bit version of hardware block */ 782cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long overflow_bit; 792cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long clear_bits; 802cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 812cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart /* callbacks for CMSTR and CMCSR access */ 822cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long (*read_control)(void __iomem *base, unsigned long offs); 832cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart void (*write_control)(void __iomem *base, unsigned long offs, 842cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long value); 852cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 862cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart /* callbacks for CMCNT and CMCOR access */ 872cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long (*read_count)(void __iomem *base, unsigned long offs); 882cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart void (*write_count)(void __iomem *base, unsigned long offs, 892cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart unsigned long value); 902cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart}; 912cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 927269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstruct sh_cmt_channel { 932653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart struct sh_cmt_device *cmt; 943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 9581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart unsigned int index; /* Index in the documentation */ 9681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart unsigned int hwidx; /* Real hardware index */ 9781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 9881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart void __iomem *iostart; 9981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart void __iomem *ioctrl; 100c924d2d2a964715b55b6601be338b3bd05a1ced5Laurent Pinchart 10181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart unsigned int timer_bit; 1023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long flags; 1033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long match_value; 1043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long next_match_value; 1053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long max_match_value; 1063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long rate; 1077d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt raw_spinlock_t lock; 1083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm struct clock_event_device ced; 10919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm struct clocksource cs; 1103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long total_cycles; 111bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki bool cs_enabled; 1127269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart}; 1137269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart 1142653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchartstruct sh_cmt_device { 1157269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct platform_device *pdev; 1167269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart 1172cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart const struct sh_cmt_info *info; 1182cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 1197269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart void __iomem *mapbase; 1207269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct clk *clk; 1217269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart 122de599c8843ebbdfc29a119c94af481b1de76700eLaurent Pinchart raw_spinlock_t lock; /* Protect the shared start/stop register */ 123de599c8843ebbdfc29a119c94af481b1de76700eLaurent Pinchart 124f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart struct sh_cmt_channel *channels; 125f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart unsigned int num_channels; 1261768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart unsigned int hw_channels; 12781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 12881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart bool has_clockevent; 12981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart bool has_clocksource; 1303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}; 1313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 132d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CMF (1 << 7) 133d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CMIE (1 << 6) 134d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CKS8 (0 << 0) 135d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CKS32 (1 << 0) 136d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CKS128 (2 << 0) 137d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CKS512 (3 << 0) 138d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT16_CMCSR_CKS_MASK (3 << 0) 139d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart 140d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMF (1 << 15) 141d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_OVF (1 << 14) 142d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_WRFLG (1 << 13) 143d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_STTF (1 << 12) 144d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_STPF (1 << 11) 145d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_SSIE (1 << 10) 146d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMS (1 << 9) 147d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMM (1 << 8) 148d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMTOUT_IE (1 << 7) 149d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMR_NONE (0 << 4) 150d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMR_DMA (1 << 4) 151d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMR_IRQ (2 << 4) 152d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CMR_MASK (3 << 4) 153d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_DBGIVD (1 << 3) 154d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CKS_RCLK8 (4 << 0) 155d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CKS_RCLK32 (5 << 0) 156d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CKS_RCLK128 (6 << 0) 157d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CKS_RCLK1 (7 << 0) 158d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart#define SH_CMT32_CMCSR_CKS_MASK (7 << 0) 159d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart 160a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Dammstatic unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs) 161587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm{ 162587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm return ioread16(base + (offs << 1)); 163587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm} 164587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm 165a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Dammstatic unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs) 166a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm{ 167a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm return ioread32(base + (offs << 2)); 168a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm} 169a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm 170a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Dammstatic void sh_cmt_write16(void __iomem *base, unsigned long offs, 171a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm unsigned long value) 172587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm{ 173587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm iowrite16(value, base + (offs << 1)); 174587acb3dd5cf387de1325309e831fd0f560d1bf6Magnus Damm} 1753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 176a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Dammstatic void sh_cmt_write32(void __iomem *base, unsigned long offs, 177a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm unsigned long value) 178a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm{ 179a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm iowrite32(value, base + (offs << 2)); 180a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm} 181a6a912ca43843d43590ce5f1cbc85cbc7ac14bbaMagnus Damm 1822cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchartstatic const struct sh_cmt_info sh_cmt_info[] = { 1832cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart [SH_CMT_16BIT] = { 1842cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .model = SH_CMT_16BIT, 1852cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .width = 16, 186d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .overflow_bit = SH_CMT16_CMCSR_CMF, 187d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .clear_bits = ~SH_CMT16_CMCSR_CMF, 1882cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_control = sh_cmt_read16, 1892cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_control = sh_cmt_write16, 1902cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_count = sh_cmt_read16, 1912cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_count = sh_cmt_write16, 1922cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart }, 1932cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart [SH_CMT_32BIT] = { 1942cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .model = SH_CMT_32BIT, 1952cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .width = 32, 196d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .overflow_bit = SH_CMT32_CMCSR_CMF, 197d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), 1982cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_control = sh_cmt_read16, 1992cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_control = sh_cmt_write16, 2002cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_count = sh_cmt_read32, 2012cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_count = sh_cmt_write32, 2022cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart }, 2032cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart [SH_CMT_32BIT_FAST] = { 2042cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .model = SH_CMT_32BIT_FAST, 2052cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .width = 32, 206d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .overflow_bit = SH_CMT32_CMCSR_CMF, 207d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), 2082cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_control = sh_cmt_read16, 2092cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_control = sh_cmt_write16, 2102cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_count = sh_cmt_read32, 2112cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_count = sh_cmt_write32, 2122cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart }, 2132cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart [SH_CMT_48BIT] = { 2142cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .model = SH_CMT_48BIT, 2152cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .width = 32, 216d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .overflow_bit = SH_CMT32_CMCSR_CMF, 217d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), 2182cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_control = sh_cmt_read32, 2192cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_control = sh_cmt_write32, 2202cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_count = sh_cmt_read32, 2212cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_count = sh_cmt_write32, 2222cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart }, 2232cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart [SH_CMT_48BIT_GEN2] = { 2242cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .model = SH_CMT_48BIT_GEN2, 2252cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .width = 32, 226d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .overflow_bit = SH_CMT32_CMCSR_CMF, 227d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart .clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF), 2282cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_control = sh_cmt_read32, 2292cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_control = sh_cmt_write32, 2302cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .read_count = sh_cmt_read32, 2312cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart .write_count = sh_cmt_write32, 2322cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart }, 2332cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart}; 2342cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart 2353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCSR 0 /* channel register */ 2363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCNT 1 /* channel register */ 2373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCOR 2 /* channel register */ 2383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 2397269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch) 2401b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 24181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (ch->iostart) 24281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return ch->cmt->info->read_control(ch->iostart, 0); 24381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart else 24481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return ch->cmt->info->read_control(ch->cmt->mapbase, 0); 2451b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2461b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 24781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, 24881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart unsigned long value) 2491b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 25081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (ch->iostart) 25181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->info->write_control(ch->iostart, 0, value); 25281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart else 25381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); 2541b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2551b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 25681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) 2571b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 25881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return ch->cmt->info->read_control(ch->ioctrl, CMCSR); 2593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 2603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 26181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, 2621b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm unsigned long value) 2631b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 26481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); 2651b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2661b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 26781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) 2681b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 26981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return ch->cmt->info->read_count(ch->ioctrl, CMCNT); 2701b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2711b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 2727269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, 2731b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm unsigned long value) 2741b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 27581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->info->write_count(ch->ioctrl, CMCNT, value); 2761b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2771b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 2787269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, 2791b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm unsigned long value) 2801b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm{ 28181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); 2821b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm} 2831b56b96b663d135305c3c47755fbdde3dc0ef720Magnus Damm 2847269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch, 2853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm int *has_wrapped) 2863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 2873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long v1, v2, v3; 2885b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm int o1, o2; 2895b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm 2902cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit; 2913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 2923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* Make sure the timer value is stable. Stolen from acpi_pm.c */ 2933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm do { 2945b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm o2 = o1; 2957269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart v1 = sh_cmt_read_cmcnt(ch); 2967269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart v2 = sh_cmt_read_cmcnt(ch); 2977269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart v3 = sh_cmt_read_cmcnt(ch); 2982cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit; 2995b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) 3005b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); 3013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3025b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm *has_wrapped = o1; 3033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return v2; 3043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 3053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3067269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) 3073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 3083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long flags, value; 3093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* start stop register shared by multiple timer channels */ 311de599c8843ebbdfc29a119c94af481b1de76700eLaurent Pinchart raw_spin_lock_irqsave(&ch->cmt->lock, flags); 3127269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart value = sh_cmt_read_cmstr(ch); 3133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (start) 31581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart value |= 1 << ch->timer_bit; 3163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm else 31781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart value &= ~(1 << ch->timer_bit); 3183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3197269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_write_cmstr(ch, value); 320de599c8843ebbdfc29a119c94af481b1de76700eLaurent Pinchart raw_spin_unlock_irqrestore(&ch->cmt->lock, flags); 3213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 3223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3237269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate) 3243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 3253f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm int k, ret; 3263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3277269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_runtime_get_sync(&ch->cmt->pdev->dev); 3287269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart dev_pm_syscore_device(&ch->cmt->pdev->dev, true); 329bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 3309436b4abec28a22edd961ae375535d940625f1f2Paul Mundt /* enable clock */ 3317269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ret = clk_enable(ch->cmt->clk); 3323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (ret) { 333740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_err(&ch->cmt->pdev->dev, "ch%u: cannot enable clock\n", 334740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 3353f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm goto err0; 3363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 3373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* make sure channel is disabled */ 3397269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_start_stop_ch(ch, 0); 3403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* configure channel, periodic mode and maximum timeout */ 3422cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart if (ch->cmt->info->width == 16) { 3437269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart *rate = clk_get_rate(ch->cmt->clk) / 512; 344d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart sh_cmt_write_cmcsr(ch, SH_CMT16_CMCSR_CMIE | 345d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart SH_CMT16_CMCSR_CKS512); 3463014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm } else { 3477269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart *rate = clk_get_rate(ch->cmt->clk) / 8; 348d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart sh_cmt_write_cmcsr(ch, SH_CMT32_CMCSR_CMM | 349d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart SH_CMT32_CMCSR_CMTOUT_IE | 350d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart SH_CMT32_CMCSR_CMR_IRQ | 351d14be99b7e3fe52bc9921caa30953d49f499f121Laurent Pinchart SH_CMT32_CMCSR_CKS_RCLK8); 3523014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm } 3533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3547269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_write_cmcor(ch, 0xffffffff); 3557269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_write_cmcnt(ch, 0); 3563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3573f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm /* 3583f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * According to the sh73a0 user's manual, as CMCNT can be operated 3593f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * only by the RCLK (Pseudo 32 KHz), there's one restriction on 3603f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * modifying CMCNT register; two RCLK cycles are necessary before 3613f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * this register is either read or any modification of the value 3623f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * it holds is reflected in the LSI's actual operation. 3633f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * 3643f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * While at it, we're supposed to clear out the CMCNT as of this 3653f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * moment, so make sure it's processed properly here. This will 3663f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm * take RCLKx2 at maximum. 3673f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm */ 3683f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm for (k = 0; k < 100; k++) { 3697269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (!sh_cmt_read_cmcnt(ch)) 3703f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm break; 3713f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm udelay(1); 3723f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm } 3733f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm 3747269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (sh_cmt_read_cmcnt(ch)) { 375740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n", 376740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 3773f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm ret = -ETIMEDOUT; 3783f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm goto err1; 3793f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm } 3803f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm 3813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* enable channel */ 3827269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_start_stop_ch(ch, 1); 3833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return 0; 3843f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm err1: 3853f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm /* stop clock */ 3867269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart clk_disable(ch->cmt->clk); 3873f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm 3883f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm err0: 3893f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm return ret; 3903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 3913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 3927269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_disable(struct sh_cmt_channel *ch) 3933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 3943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* disable channel */ 3957269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_start_stop_ch(ch, 0); 3963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 397be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm /* disable interrupts in CMT block */ 3987269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_write_cmcsr(ch, 0); 399be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm 4009436b4abec28a22edd961ae375535d940625f1f2Paul Mundt /* stop clock */ 4017269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart clk_disable(ch->cmt->clk); 402bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 4037269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart dev_pm_syscore_device(&ch->cmt->pdev->dev, false); 4047269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_runtime_put(&ch->cmt->pdev->dev); 4053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 4063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* private flags */ 4083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKEVENT (1 << 0) 4093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKSOURCE (1 << 1) 4103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_REPROGRAM (1 << 2) 4113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_SKIPEVENT (1 << 3) 4123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_IRQCONTEXT (1 << 4) 4133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4147269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch, 4153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm int absolute) 4163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 4173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long new_match; 4187269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart unsigned long value = ch->next_match_value; 4193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long delay = 0; 4203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long now = 0; 4213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm int has_wrapped; 4223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4237269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart now = sh_cmt_get_counter(ch, &has_wrapped); 4247269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= FLAG_REPROGRAM; /* force reprogram */ 4253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (has_wrapped) { 4273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* we're competing with the interrupt handler. 4283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> let the interrupt handler reprogram the timer. 4293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> interrupt number two handles the event. 4303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4317269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= FLAG_SKIPEVENT; 4323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return; 4333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 4343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (absolute) 4363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm now = 0; 4373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm do { 4393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* reprogram the timer hardware, 4403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * but don't save the new match value yet. 4413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm new_match = now + value + delay; 4437269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (new_match > ch->max_match_value) 4447269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart new_match = ch->max_match_value; 4453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4467269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_write_cmcor(ch, new_match); 4473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4487269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart now = sh_cmt_get_counter(ch, &has_wrapped); 4497269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (has_wrapped && (new_match > ch->match_value)) { 4503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* we are changing to a greater match value, 4513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * so this wrap must be caused by the counter 4523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * matching the old value. 4533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> first interrupt reprograms the timer. 4543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> interrupt number two handles the event. 4553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4567269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= FLAG_SKIPEVENT; 4573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 4583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 4593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (has_wrapped) { 4613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* we are changing to a smaller match value, 4623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * so the wrap must be caused by the counter 4633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * matching the new value. 4643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> save programmed match value. 4653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> let isr handle the event. 4663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4677269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->match_value = new_match; 4683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 4693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 4703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* be safe: verify hardware settings */ 4723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (now < new_match) { 4733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* timer value is below match value, all good. 4743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * this makes sure we won't miss any match events. 4753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> save programmed match value. 4763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> let isr handle the event. 4773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4787269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->match_value = new_match; 4793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 4803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 4813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* the counter has reached a value greater 4833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * than our new match value. and since the 4843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * has_wrapped flag isn't set we must have 4853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * programmed a too close event. 4863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * -> increase delay and retry. 4873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 4883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (delay) 4893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm delay <<= 1; 4903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm else 4913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm delay = 1; 4923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (!delay) 494740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_warn(&ch->cmt->pdev->dev, "ch%u: too long delay\n", 495740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 4963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 4973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } while (delay); 4983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 4993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5007269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void __sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta) 5013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 5027269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (delta > ch->max_match_value) 503740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_warn(&ch->cmt->pdev->dev, "ch%u: delta out of range\n", 504740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 5053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5067269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->next_match_value = delta; 5077269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_clock_event_program_verify(ch, 0); 50865ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII} 50965ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII 5107269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta) 51165ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII{ 51265ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII unsigned long flags; 51365ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII 5147269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_lock_irqsave(&ch->lock, flags); 5157269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart __sh_cmt_set_next(ch, delta); 5167269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_unlock_irqrestore(&ch->lock, flags); 5173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 5183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) 5203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 5217269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = dev_id; 5223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* clear flags */ 5242cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & 5252cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart ch->cmt->info->clear_bits); 5263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* update clock source counter to begin with if enabled 5283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * the wrap flag should be cleared by the timer specific 5293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * isr before we end up here. 5303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */ 5317269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (ch->flags & FLAG_CLOCKSOURCE) 5327269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->total_cycles += ch->match_value + 1; 5333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5347269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (!(ch->flags & FLAG_REPROGRAM)) 5357269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->next_match_value = ch->max_match_value; 5363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5377269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= FLAG_IRQCONTEXT; 5383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5397269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (ch->flags & FLAG_CLOCKEVENT) { 5407269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (!(ch->flags & FLAG_SKIPEVENT)) { 5417269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT) { 5427269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->next_match_value = ch->max_match_value; 5437269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= FLAG_REPROGRAM; 5443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 5453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5467269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->ced.event_handler(&ch->ced); 5473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 5483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 5493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5507269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags &= ~FLAG_SKIPEVENT; 5513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5527269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (ch->flags & FLAG_REPROGRAM) { 5537269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags &= ~FLAG_REPROGRAM; 5547269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_clock_event_program_verify(ch, 1); 5553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5567269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (ch->flags & FLAG_CLOCKEVENT) 5577269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if ((ch->ced.mode == CLOCK_EVT_MODE_SHUTDOWN) 5587269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart || (ch->match_value == ch->next_match_value)) 5597269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags &= ~FLAG_REPROGRAM; 5603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 5613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5627269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags &= ~FLAG_IRQCONTEXT; 5633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return IRQ_HANDLED; 5653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 5663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5677269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag) 5683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 5693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm int ret = 0; 5703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long flags; 5713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5727269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_lock_irqsave(&ch->lock, flags); 5733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5747269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) 5757269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ret = sh_cmt_enable(ch, &ch->rate); 5763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (ret) 5783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm goto out; 5797269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags |= flag; 5803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* setup timeout if no clockevent */ 5827269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT))) 5837269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart __sh_cmt_set_next(ch, ch->max_match_value); 5843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm out: 5857269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_unlock_irqrestore(&ch->lock, flags); 5863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return ret; 5883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 5893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5907269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag) 5913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 5923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long flags; 5933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm unsigned long f; 5943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5957269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_lock_irqsave(&ch->lock, flags); 5963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 5977269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); 5987269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->flags &= ~flag; 5993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 6007269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) 6017269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_disable(ch); 6023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 6033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* adjust the timeout to maximum if only clocksource left */ 6047269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE)) 6057269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart __sh_cmt_set_next(ch, ch->max_match_value); 6063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 6077269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_unlock_irqrestore(&ch->lock, flags); 6083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 6093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 6107269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs) 61119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{ 6127269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart return container_of(cs, struct sh_cmt_channel, cs); 61319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm} 61419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 61519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic cycle_t sh_cmt_clocksource_read(struct clocksource *cs) 61619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{ 6177269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); 61819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm unsigned long flags, raw; 61919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm unsigned long value; 62019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm int has_wrapped; 62119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 6227269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_lock_irqsave(&ch->lock, flags); 6237269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart value = ch->total_cycles; 6247269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw = sh_cmt_get_counter(ch, &has_wrapped); 62519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 62619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm if (unlikely(has_wrapped)) 6277269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw += ch->match_value + 1; 6287269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart raw_spin_unlock_irqrestore(&ch->lock, flags); 62919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 63019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm return value + raw; 63119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm} 63219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 63319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_clocksource_enable(struct clocksource *cs) 63419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{ 6353593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm int ret; 6367269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); 63719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 6387269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart WARN_ON(ch->cs_enabled); 639bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 6407269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->total_cycles = 0; 64119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 6427269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE); 643bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki if (!ret) { 6447269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart __clocksource_updatefreq_hz(cs, ch->rate); 6457269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->cs_enabled = true; 646bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki } 6473593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm return ret; 64819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm} 64919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 65019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic void sh_cmt_clocksource_disable(struct clocksource *cs) 65119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{ 6527269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); 653bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 6547269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart WARN_ON(!ch->cs_enabled); 655bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 6567269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_stop(ch, FLAG_CLOCKSOURCE); 6577269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->cs_enabled = false; 65819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm} 65919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 6609bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clocksource_suspend(struct clocksource *cs) 6619bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{ 6627269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); 6639bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki 6647269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_stop(ch, FLAG_CLOCKSOURCE); 6657269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); 6669bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki} 6679bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki 668c81628848af8a01f103acc8166299c698898a8f4Magnus Dammstatic void sh_cmt_clocksource_resume(struct clocksource *cs) 669c81628848af8a01f103acc8166299c698898a8f4Magnus Damm{ 6707269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = cs_to_sh_cmt(cs); 6719bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki 6727269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); 6737269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_start(ch, FLAG_CLOCKSOURCE); 674c81628848af8a01f103acc8166299c698898a8f4Magnus Damm} 675c81628848af8a01f103acc8166299c698898a8f4Magnus Damm 6767269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic int sh_cmt_register_clocksource(struct sh_cmt_channel *ch, 677fb28a659813084365eced5c2876c6383da52e634Laurent Pinchart const char *name) 67819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{ 6797269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct clocksource *cs = &ch->cs; 68019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 68119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->name = name; 682fb28a659813084365eced5c2876c6383da52e634Laurent Pinchart cs->rating = 125; 68319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->read = sh_cmt_clocksource_read; 68419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->enable = sh_cmt_clocksource_enable; 68519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->disable = sh_cmt_clocksource_disable; 6869bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki cs->suspend = sh_cmt_clocksource_suspend; 687c81628848af8a01f103acc8166299c698898a8f4Magnus Damm cs->resume = sh_cmt_clocksource_resume; 68819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); 68919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 690f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt 691740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n", 692740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 693f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt 6943593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm /* Register with dummy 1 Hz value, gets updated in ->enable() */ 6953593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm clocksource_register_hz(cs, 1); 69619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm return 0; 69719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm} 69819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 6997269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced) 7003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 7017269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart return container_of(ced, struct sh_cmt_channel, ced); 7023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 7033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7047269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchartstatic void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic) 7053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 7067269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct clock_event_device *ced = &ch->ced; 7073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7087269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_start(ch, FLAG_CLOCKEVENT); 7093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* TODO: calculate good shift from rate and counter bit width */ 7113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->shift = 32; 7137269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ced->mult = div_sc(ch->rate, NSEC_PER_SEC, ced->shift); 7147269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced); 7153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); 7163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (periodic) 7187269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_set_next(ch, ((ch->rate + HZ/2) / HZ) - 1); 7193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm else 7207269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_set_next(ch, ch->max_match_value); 7213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 7223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_mode(enum clock_event_mode mode, 7243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm struct clock_event_device *ced) 7253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 7267269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 7273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm /* deal with old setting first */ 7293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm switch (ced->mode) { 7303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_PERIODIC: 7313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_ONESHOT: 7327269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_stop(ch, FLAG_CLOCKEVENT); 7333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm default: 7353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 7373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm switch (mode) { 7393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_PERIODIC: 7407269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart dev_info(&ch->cmt->pdev->dev, 741740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart "ch%u: used for periodic clock events\n", ch->index); 7427269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_clock_event_start(ch, 1); 7433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_ONESHOT: 7457269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart dev_info(&ch->cmt->pdev->dev, 746740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart "ch%u: used for oneshot clock events\n", ch->index); 7477269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_clock_event_start(ch, 0); 7483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_SHUTDOWN: 7503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm case CLOCK_EVT_MODE_UNUSED: 7517269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_stop(ch, FLAG_CLOCKEVENT); 7523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm default: 7543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm break; 7553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 7563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 7573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_clock_event_next(unsigned long delta, 7593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm struct clock_event_device *ced) 7603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 7617269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 7623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); 7647269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart if (likely(ch->flags & FLAG_IRQCONTEXT)) 7657269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart ch->next_match_value = delta - 1; 7663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm else 7677269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart sh_cmt_set_next(ch, delta - 1); 7683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return 0; 7703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 7713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 7729bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clock_event_suspend(struct clock_event_device *ced) 7739bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{ 7747269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 77557dee992df244ccce6a6a3a88a43160e285da5d8Laurent Pinchart 7767269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); 7777269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart clk_unprepare(ch->cmt->clk); 7789bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki} 7799bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki 7809bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clock_event_resume(struct clock_event_device *ced) 7819bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{ 7827269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 78357dee992df244ccce6a6a3a88a43160e285da5d8Laurent Pinchart 7847269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart clk_prepare(ch->cmt->clk); 7857269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); 7869bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki} 7879bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki 788bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchartstatic int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, 789bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart const char *name) 7903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 7917269f9333292586f2378c5321b40a8d3779c4653Laurent Pinchart struct clock_event_device *ced = &ch->ced; 792bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart int irq; 793bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart int ret; 794bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart 79531e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart irq = platform_get_irq(ch->cmt->pdev, ch->index); 796bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart if (irq < 0) { 797bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n", 798bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart ch->index); 799bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart return irq; 800bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart } 801bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart 802bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart ret = request_irq(irq, sh_cmt_interrupt, 803bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 804bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart dev_name(&ch->cmt->pdev->dev), ch); 805bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart if (ret) { 806bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart dev_err(&ch->cmt->pdev->dev, "ch%u: failed to request irq %d\n", 807bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart ch->index, irq); 808bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart return ret; 809bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart } 8103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 8113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->name = name; 8123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->features = CLOCK_EVT_FEAT_PERIODIC; 8133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->features |= CLOCK_EVT_FEAT_ONESHOT; 814b7fcbb0f830e6cccc9d358c24f8463e5d8018649Laurent Pinchart ced->rating = 125; 815f1ebe1e47e1979393a8492bfe751176908a830aeLaurent Pinchart ced->cpumask = cpu_possible_mask; 8163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->set_next_event = sh_cmt_clock_event_next; 8173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm ced->set_mode = sh_cmt_clock_event_mode; 8189bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki ced->suspend = sh_cmt_clock_event_suspend; 8199bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki ced->resume = sh_cmt_clock_event_resume; 8203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 821740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n", 822740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 8233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm clockevents_register_device(ced); 824bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart 825bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart return 0; 8263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 8273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 8281d053e1d8eb28f42b7ec57d1c11ce70b8fba45ffLaurent Pinchartstatic int sh_cmt_register(struct sh_cmt_channel *ch, const char *name, 829fb28a659813084365eced5c2876c6383da52e634Laurent Pinchart bool clockevent, bool clocksource) 8303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 831bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart int ret; 832bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart 83381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (clockevent) { 83481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->has_clockevent = true; 835bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart ret = sh_cmt_register_clockevent(ch, name); 836bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart if (ret < 0) 837bfa76bb12f23ecf0c6d07c302f4571a6fe9bc3e3Laurent Pinchart return ret; 83881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 8393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 84081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (clocksource) { 84181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->cmt->has_clocksource = true; 842fb28a659813084365eced5c2876c6383da52e634Laurent Pinchart sh_cmt_register_clocksource(ch, name); 84381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 84419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm 8453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return 0; 8463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 8473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 848740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchartstatic int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, 84981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart unsigned int hwidx, bool clockevent, 85081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart bool clocksource, struct sh_cmt_device *cmt) 851b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart{ 852b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart int ret; 853b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart 85481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart /* Skip unused channels. */ 85581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (!clockevent && !clocksource) 85681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return 0; 85781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 858b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart ch->cmt = cmt; 859740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index = index; 86081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart ch->hwidx = hwidx; 86181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 86281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart /* 86381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * Compute the address of the channel control register block. For the 86481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * timers with a per-channel start/stop register, compute its address 86581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart * as well. 86681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart */ 86731e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart switch (cmt->info->model) { 86831e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart case SH_CMT_16BIT: 86931e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6; 87031e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart break; 87131e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart case SH_CMT_32BIT: 87231e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart case SH_CMT_48BIT: 87331e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10; 87431e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart break; 87531e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart case SH_CMT_32BIT_FAST: 87631e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart /* 87731e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart * The 32-bit "fast" timer has a single channel at hwidx 5 but 87831e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart * is located at offset 0x40 instead of 0x60 for some reason. 87931e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart */ 88031e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->ioctrl = cmt->mapbase + 0x40; 88131e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart break; 88231e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart case SH_CMT_48BIT_GEN2: 88331e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->iostart = cmt->mapbase + ch->hwidx * 0x100; 88431e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->ioctrl = ch->iostart + 0x10; 88531e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart break; 88681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 88781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 8882cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart if (cmt->info->width == (sizeof(ch->max_match_value) * 8)) 889b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart ch->max_match_value = ~0; 890b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart else 8912cda3ac49d5744432e9ebffb8ba47bef6eca053dLaurent Pinchart ch->max_match_value = (1 << cmt->info->width) - 1; 892b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart 893b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart ch->match_value = ch->max_match_value; 894b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart raw_spin_lock_init(&ch->lock); 895b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart 89631e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx; 89781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 8981d053e1d8eb28f42b7ec57d1c11ce70b8fba45ffLaurent Pinchart ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev), 89981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart clockevent, clocksource); 900b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart if (ret) { 901740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart dev_err(&cmt->pdev->dev, "ch%u: registration failed\n", 902740a95184dd61eb0481f75ced05ea5e01b7ce6acLaurent Pinchart ch->index); 903b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart return ret; 904b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart } 905b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart ch->cs_enabled = false; 906b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart 907b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart return 0; 908b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart} 909b882e7b13bc12b3d6b00e4ea2fe374413ddcdd2dLaurent Pinchart 91081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic int sh_cmt_map_memory(struct sh_cmt_device *cmt) 9113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 91281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart struct resource *mem; 9133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 91481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart mem = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0); 91581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (!mem) { 91681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart dev_err(&cmt->pdev->dev, "failed to get I/O memory\n"); 91781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return -ENXIO; 91881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 9193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 92081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart cmt->mapbase = ioremap_nocache(mem->start, resource_size(mem)); 92181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (cmt->mapbase == NULL) { 92281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n"); 92381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return -ENXIO; 9243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 9253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 92681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return 0; 92781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart} 92881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 9291768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchartstatic const struct platform_device_id sh_cmt_id_table[] = { 9301768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] }, 9311768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] }, 9321768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] }, 9331768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] }, 9341768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] }, 9351768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { } 9361768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart}; 9371768aa2f4c1248051013282c6cf63b368016cb53Laurent PinchartMODULE_DEVICE_TABLE(platform, sh_cmt_id_table); 9381768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9391768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchartstatic const struct of_device_id sh_cmt_of_table[] __maybe_unused = { 9401768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] }, 9411768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] }, 9421768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] }, 9431768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] }, 9441768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart { } 9451768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart}; 9461768aa2f4c1248051013282c6cf63b368016cb53Laurent PinchartMODULE_DEVICE_TABLE(of, sh_cmt_of_table); 9471768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9481768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchartstatic int sh_cmt_parse_dt(struct sh_cmt_device *cmt) 9491768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart{ 9501768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart struct device_node *np = cmt->pdev->dev.of_node; 9511768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9521768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart return of_property_read_u32(np, "renesas,channels-mask", 9531768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart &cmt->hw_channels); 9541768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart} 9551768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 95681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchartstatic int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) 95781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart{ 95831e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart unsigned int mask; 95931e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart unsigned int i; 96081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart int ret; 96181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 96281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart memset(cmt, 0, sizeof(*cmt)); 96381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart cmt->pdev = pdev; 964de599c8843ebbdfc29a119c94af481b1de76700eLaurent Pinchart raw_spin_lock_init(&cmt->lock); 96581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 9661768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { 9671768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart const struct of_device_id *id; 9681768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9691768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart id = of_match_node(sh_cmt_of_table, pdev->dev.of_node); 9701768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart cmt->info = id->data; 9711768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9721768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart ret = sh_cmt_parse_dt(cmt); 9731768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart if (ret < 0) 9741768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart return ret; 9751768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart } else if (pdev->dev.platform_data) { 9761768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart struct sh_timer_config *cfg = pdev->dev.platform_data; 9771768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart const struct platform_device_id *id = pdev->id_entry; 9781768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart 9791768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart cmt->info = (const struct sh_cmt_info *)id->driver_data; 9801768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart cmt->hw_channels = cfg->channels_mask; 9811768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart } else { 98281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart dev_err(&cmt->pdev->dev, "missing platform data\n"); 98381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return -ENXIO; 98481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 98581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 98681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart /* Get hold of clock. */ 98731e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart cmt->clk = clk_get(&cmt->pdev->dev, "fck"); 9882653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart if (IS_ERR(cmt->clk)) { 9892653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart dev_err(&cmt->pdev->dev, "cannot get clock\n"); 99081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart return PTR_ERR(cmt->clk); 9913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 9923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 9932653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart ret = clk_prepare(cmt->clk); 99457dee992df244ccce6a6a3a88a43160e285da5d8Laurent Pinchart if (ret < 0) 99581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart goto err_clk_put; 99657dee992df244ccce6a6a3a88a43160e285da5d8Laurent Pinchart 99731e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart /* Map the memory resource(s). */ 99831e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ret = sh_cmt_map_memory(cmt); 99981b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (ret < 0) 100081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart goto err_clk_unprepare; 100181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 100281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart /* Allocate and setup the channels. */ 10031768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart cmt->num_channels = hweight8(cmt->hw_channels); 100481b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels), 100581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart GFP_KERNEL); 1006f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart if (cmt->channels == NULL) { 1007f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart ret = -ENOMEM; 100881b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart goto err_unmap; 1009f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart } 1010f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart 101131e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart /* 101231e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart * Use the first channel as a clock event device and the second channel 101331e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart * as a clock source. If only one channel is available use it for both. 101431e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart */ 10151768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) { 101631e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart unsigned int hwidx = ffs(mask) - 1; 101731e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart bool clocksource = i == 1 || cmt->num_channels == 1; 101831e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart bool clockevent = i == 0; 101931e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart 102031e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx, 102131e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart clockevent, clocksource, cmt); 102281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (ret < 0) 102381b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart goto err_unmap; 1024f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart 102531e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart mask &= ~(1 << hwidx); 102681b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart } 1027da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt 10282653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart platform_set_drvdata(pdev, cmt); 1029adccc69e7ad1815ce79b073830b244a803776bbdMagnus Damm 1030da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt return 0; 103181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart 103281b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pincharterr_unmap: 1033f5ec9b194a93c05e2ccdb3e90d9061cfedc806d9Laurent Pinchart kfree(cmt->channels); 103431e912f598371bcfdffc990289029e1110f8b3f9Laurent Pinchart iounmap(cmt->mapbase); 103581b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pincharterr_clk_unprepare: 10362653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart clk_unprepare(cmt->clk); 103781b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pincharterr_clk_put: 10382653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart clk_put(cmt->clk); 10393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return ret; 10403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 10413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10421850514b3ebde0f5eeedbe918a7d0d344b752653Greg Kroah-Hartmanstatic int sh_cmt_probe(struct platform_device *pdev) 10433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 10442653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart struct sh_cmt_device *cmt = platform_get_drvdata(pdev); 10453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm int ret; 10463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10479bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki if (!is_early_platform_device(pdev)) { 1048bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki pm_runtime_set_active(&pdev->dev); 1049bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki pm_runtime_enable(&pdev->dev); 10509bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki } 1051615a445f7f8a077c145e737864ae59a4d8717882Rafael J. Wysocki 10522653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart if (cmt) { 1053214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt dev_info(&pdev->dev, "kept as earlytimer\n"); 1054bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki goto out; 1055e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm } 1056e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm 1057b262bc74dcfd77355720342cbcf89cc8ec12e86bLaurent Pinchart cmt = kzalloc(sizeof(*cmt), GFP_KERNEL); 10580178f41d3d35b63ed25a066d90e7dda380018c06Jingoo Han if (cmt == NULL) 10593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return -ENOMEM; 10603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10612653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart ret = sh_cmt_setup(cmt, pdev); 10623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm if (ret) { 10632653caf4381f9adeec8c18dfec21ec3c855d801cLaurent Pinchart kfree(cmt); 1064bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki pm_runtime_idle(&pdev->dev); 1065bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki return ret; 10663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm } 1067bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki if (is_early_platform_device(pdev)) 1068bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki return 0; 1069bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 1070bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki out: 107181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart if (cmt->has_clockevent || cmt->has_clocksource) 1072bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki pm_runtime_irq_safe(&pdev->dev); 1073bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki else 1074bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki pm_runtime_idle(&pdev->dev); 1075bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki 1076bad813831e291cf34a007e6f03c37cf95037c868Rafael J. Wysocki return 0; 10773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 10783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10791850514b3ebde0f5eeedbe918a7d0d344b752653Greg Kroah-Hartmanstatic int sh_cmt_remove(struct platform_device *pdev) 10803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 10813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return -EBUSY; /* cannot unregister clockevent and clocksource */ 10823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 10833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct platform_driver sh_cmt_device_driver = { 10853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm .probe = sh_cmt_probe, 10861850514b3ebde0f5eeedbe918a7d0d344b752653Greg Kroah-Hartman .remove = sh_cmt_remove, 10873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm .driver = { 10883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm .name = "sh_cmt", 10891768aa2f4c1248051013282c6cf63b368016cb53Laurent Pinchart .of_match_table = of_match_ptr(sh_cmt_of_table), 109081b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart }, 109181b3b2711072b6047d5f332cd8751a1c5c9a3fb2Laurent Pinchart .id_table = sh_cmt_id_table, 10923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}; 10933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __init sh_cmt_init(void) 10953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 10963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm return platform_driver_register(&sh_cmt_device_driver); 10973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 10983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 10993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void __exit sh_cmt_exit(void) 11003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{ 11013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm platform_driver_unregister(&sh_cmt_device_driver); 11023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm} 11033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 1104e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Dammearly_platform_init("earlytimer", &sh_cmt_device_driver); 1105e903a031402c8dccc675b2f0cf8af40ac89163b0Simon Hormansubsys_initcall(sh_cmt_init); 11063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_exit(sh_cmt_exit); 11073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm 11083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_AUTHOR("Magnus Damm"); 11093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_DESCRIPTION("SuperH CMT Timer Driver"); 11103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_LICENSE("GPL v2"); 1111