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