sh_cmt.c revision da64c2a8dee66ca03f4f3e15d84be7bedf73db3d
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 * You should have received a copy of the GNU General Public License
163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * along with this program; if not, write to the Free Software
173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm */
193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/init.h>
213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/platform_device.h>
223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/spinlock.h>
233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/interrupt.h>
243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/ioport.h>
253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/io.h>
263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/clk.h>
273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/irq.h>
283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/err.h>
293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/clocksource.h>
303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/clockchips.h>
3146a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt#include <linux/sh_timer.h>
323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstruct sh_cmt_priv {
343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *mapbase;
353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clk *clk;
363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long width; /* 16 or 32 bit version of hardware block */
373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long overflow_bit;
383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long clear_bits;
393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct irqaction irqaction;
403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct platform_device *pdev;
413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
43f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	unsigned long flags_suspend;
443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long match_value;
453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long next_match_value;
463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long max_match_value;
473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long rate;
483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spinlock_t lock;
493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device ced;
5019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource cs;
513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long total_cycles;
523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic DEFINE_SPINLOCK(sh_cmt_lock);
553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMSTR -1 /* shared register */
573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCSR 0 /* channel register */
583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCNT 1 /* channel register */
593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCOR 2 /* channel register */
603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6346a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return ioread32(base + offs);
793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ioread16(base + offs);
823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				unsigned long value)
863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
8746a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
1003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
1013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
1023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			iowrite32(value, base + offs);
1033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return;
1043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
1053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iowrite16(value, base + offs);
1083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
1113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					int *has_wrapped)
1123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long v1, v2, v3;
1145b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	int o1, o2;
1155b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm
1165b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
1193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
1205b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o2 = o1;
1213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v1 = sh_cmt_read(p, CMCNT);
1223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v2 = sh_cmt_read(p, CMCNT);
1233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v3 = sh_cmt_read(p, CMCNT);
1245b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1255b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
1265b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
1273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1285b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	*has_wrapped = o1;
1293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return v2;
1303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
1343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
13546a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
1363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags, value;
1373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* start stop register shared by multiple timer channels */
1393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&sh_cmt_lock, flags);
1403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	value = sh_cmt_read(p, CMSTR);
1413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (start)
1433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value |= 1 << cfg->timer_bit;
1443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
1453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value &= ~(1 << cfg->timer_bit);
1463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMSTR, value);
1483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&sh_cmt_lock, flags);
1493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
1523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
15346a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
1543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
1553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable clock */
1573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = clk_enable(p->clk);
1583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
1593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk);
1603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return ret;
1613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* make sure channel is disabled */
1643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
1653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* configure channel, periodic mode and maximum timeout */
1673014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	if (p->width == 16) {
1683014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 512;
1693014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		sh_cmt_write(p, CMCSR, 0x43);
1703014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	} else {
1713014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 8;
1723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCSR, 0x01a4);
1733014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	}
1743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCOR, 0xffffffff);
1763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCNT, 0);
1773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable channel */
1793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 1);
1803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
1813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_disable(struct sh_cmt_priv *p)
1843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* disable channel */
1863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
1873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
188be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	/* disable interrupts in CMT block */
189be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	sh_cmt_write(p, CMCSR, 0);
190be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm
1913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* stop clock */
1923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clk_disable(p->clk);
1933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* private flags */
1963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKEVENT (1 << 0)
1973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKSOURCE (1 << 1)
1983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_REPROGRAM (1 << 2)
1993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_SKIPEVENT (1 << 3)
2003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_IRQCONTEXT (1 << 4)
2013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
2033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					      int absolute)
2043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long new_match;
2063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long value = p->next_match_value;
2073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long delay = 0;
2083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long now = 0;
2093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int has_wrapped;
2103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	now = sh_cmt_get_counter(p, &has_wrapped);
2123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_REPROGRAM; /* force reprogram */
2133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (has_wrapped) {
2153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* we're competing with the interrupt handler.
2163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> let the interrupt handler reprogram the timer.
2173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> interrupt number two handles the event.
2183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags |= FLAG_SKIPEVENT;
2203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return;
2213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
2223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (absolute)
2243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = 0;
2253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
2273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* reprogram the timer hardware,
2283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * but don't save the new match value yet.
2293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		new_match = now + value + delay;
2313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (new_match > p->max_match_value)
2323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			new_match = p->max_match_value;
2333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCOR, new_match);
2353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = sh_cmt_get_counter(p, &has_wrapped);
2373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped && (new_match > p->match_value)) {
2383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a greater match value,
2393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so this wrap must be caused by the counter
2403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the old value.
2413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> first interrupt reprograms the timer.
2423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> interrupt number two handles the event.
2433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->flags |= FLAG_SKIPEVENT;
2453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped) {
2493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a smaller match value,
2503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so the wrap must be caused by the counter
2513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the new value.
2523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* be safe: verify hardware settings */
2603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (now < new_match) {
2613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* timer value is below match value, all good.
2623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * this makes sure we won't miss any match events.
2633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* the counter has reached a value greater
2713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * than our new match value. and since the
2723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * has_wrapped flag isn't set we must have
2733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * programmed a too close event.
2743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * -> increase delay and retry.
2753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (delay)
2773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay <<= 1;
2783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		else
2793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay = 1;
2803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!delay)
2823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			pr_warning("sh_cmt: too long delay\n");
2833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} while (delay);
2853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
2883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
2903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (delta > p->max_match_value)
2923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_warning("sh_cmt: delta out of range\n");
2933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
2953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->next_match_value = delta;
2963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_clock_event_program_verify(p, 0);
2973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
2983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
3013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = dev_id;
3033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* clear flags */
3053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
3063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* update clock source counter to begin with if enabled
3083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * the wrap flag should be cleared by the timer specific
3093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * isr before we end up here.
3103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 */
3113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKSOURCE)
3123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->total_cycles += p->match_value;
3133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & FLAG_REPROGRAM))
3153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = p->max_match_value;
3163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_IRQCONTEXT;
3183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKEVENT) {
3203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!(p->flags & FLAG_SKIPEVENT)) {
3213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
3223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->next_match_value = p->max_match_value;
3233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags |= FLAG_REPROGRAM;
3243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			}
3253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->ced.event_handler(&p->ced);
3273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
3283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_SKIPEVENT;
3313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_REPROGRAM) {
3333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags &= ~FLAG_REPROGRAM;
3343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_program_verify(p, 1);
3353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (p->flags & FLAG_CLOCKEVENT)
3373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
3383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			    || (p->match_value == p->next_match_value))
3393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags &= ~FLAG_REPROGRAM;
3403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_IRQCONTEXT;
3433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return IRQ_HANDLED;
3453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
3483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret = 0;
3503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = sh_cmt_enable(p, &p->rate);
3563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret)
3583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto out;
3593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= flag;
3603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* setup timeout if no clockevent */
3623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
3633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm out:
3653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
3683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
3713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long f;
3743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
3783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~flag;
3793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_disable(p);
3823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* adjust the timeout to maximum if only clocksource left */
3843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
3853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
39019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
39119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
39219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return container_of(cs, struct sh_cmt_priv, cs);
39319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
39419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
39519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
39619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
39719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
39819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long flags, raw;
39919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long value;
40019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int has_wrapped;
40119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_lock_irqsave(&p->lock, flags);
40319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	value = p->total_cycles;
40419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	raw = sh_cmt_get_counter(p, &has_wrapped);
40519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (unlikely(has_wrapped))
4075b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		raw += p->match_value;
40819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
40919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return value + raw;
41119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
41219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_clocksource_enable(struct clocksource *cs)
41419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
41519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
41619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int ret;
41719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	p->total_cycles = 0;
41919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
42019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
42119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (ret)
42219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		return ret;
42319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
42419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
42519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->shift = 0;
42619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
42719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
42819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
42919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
43019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic void sh_cmt_clocksource_disable(struct clocksource *cs)
43119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
43219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
43319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
43419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
43519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
43619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm				       char *name, unsigned long rating)
43719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
43819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource *cs = &p->cs;
43919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
44019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->name = name;
44119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->rating = rating;
44219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->read = sh_cmt_clocksource_read;
44319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->enable = sh_cmt_clocksource_enable;
44419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->disable = sh_cmt_clocksource_disable;
44519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
44619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
44719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	pr_info("sh_cmt: %s used as clock source\n", cs->name);
44819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	clocksource_register(cs);
44919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
45019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
45119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
4533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return container_of(ced, struct sh_cmt_priv, ced);
4553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
4583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
4603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start(p, FLAG_CLOCKEVENT);
4623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
4643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->shift = 32;
4663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
4673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
4683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
4693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (periodic)
4713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, (p->rate + HZ/2) / HZ);
4723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
4733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
4743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_mode(enum clock_event_mode mode,
4773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				    struct clock_event_device *ced)
4783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
4803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* deal with old setting first */
4823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (ced->mode) {
4833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
4843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
4853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
4863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
4883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
4903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (mode) {
4923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
4933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_info("sh_cmt: %s used for periodic clock events\n",
4943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			ced->name);
4953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 1);
4963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
4983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_info("sh_cmt: %s used for oneshot clock events\n",
4993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			ced->name);
5003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 0);
5013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_SHUTDOWN:
5033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_UNUSED:
5043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
5053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
5073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_clock_event_next(unsigned long delta,
5123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				   struct clock_event_device *ced)
5133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
5153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
5173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (likely(p->flags & FLAG_IRQCONTEXT))
5183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = delta;
5193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, delta);
5213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
5263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				       char *name, unsigned long rating)
5273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
5293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(ced, 0, sizeof(*ced));
5313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->name = name;
5333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features = CLOCK_EVT_FEAT_PERIODIC;
5343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
5353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->rating = rating;
5363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->cpumask = cpumask_of(0);
5373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_next_event = sh_cmt_clock_event_next;
5383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_mode = sh_cmt_clock_event_mode;
5393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	pr_info("sh_cmt: %s used for clock events\n", ced->name);
5413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clockevents_register_device(ced);
5423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
544d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundtstatic int sh_cmt_register(struct sh_cmt_priv *p, char *name,
545d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clockevent_rating,
546d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clocksource_rating)
5473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == (sizeof(p->max_match_value) * 8))
5493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = ~0;
5503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = (1 << p->width) - 1;
5523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->match_value = p->max_match_value;
5543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_init(&p->lock);
5553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (clockevent_rating)
5573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_register_clockevent(p, name, clockevent_rating);
5583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
55919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (clocksource_rating)
56019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		sh_cmt_register_clocksource(p, name, clocksource_rating);
56119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
5623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
5663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
56746a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = pdev->dev.platform_data;
5683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct resource *res;
5693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int irq, ret;
5703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = -ENXIO;
5713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(p, 0, sizeof(*p));
5733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->pdev = pdev;
5743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!cfg) {
5763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "missing platform data\n");
5773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_set_drvdata(pdev, p);
5813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
5833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!res) {
5843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
5853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	irq = platform_get_irq(p->pdev, 0);
5893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (irq < 0) {
5903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get irq\n");
5913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* map memory, let mapbase point to our channel */
5953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->mapbase = ioremap_nocache(res->start, resource_size(res));
5963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->mapbase == NULL) {
5973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: failed to remap I/O memory\n");
5983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* request irq using setup_irq() (too early for request_irq()) */
6023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.name = cfg->name;
6033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.handler = sh_cmt_interrupt;
6043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.dev_id = p;
6053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
6063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* get hold of clock */
6083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->clk = clk_get(&p->pdev->dev, cfg->clk);
6093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (IS_ERR(p->clk)) {
6103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
6113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = PTR_ERR(p->clk);
612da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
6133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (resource_size(res) == 6) {
6163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 16;
6173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x80;
6183014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		p->clear_bits = ~0x80;
6193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else {
6203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 32;
6213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x8000;
6223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->clear_bits = ~0xc000;
6233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
625da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	ret = sh_cmt_register(p, cfg->name,
626da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clockevent_rating,
627da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clocksource_rating);
628da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
629da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		pr_err("sh_cmt: registration failed\n");
630da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
631da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
632da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
633da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	ret = setup_irq(irq, &p->irqaction);
634da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
635da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		pr_err("sh_cmt: failed to request irq %d\n", irq);
636da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
637da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
638da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
639da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	return 0;
640da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
641da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr1:
6423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iounmap(p->mapbase);
643da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr0:
6443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devinit sh_cmt_probe(struct platform_device *pdev)
6483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
65046a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = pdev->dev.platform_data;
6513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
6523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
653e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	if (p) {
654e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name);
655e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		return 0;
656e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	}
657e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm
6588e0b842948156e3463879caed12b4ce51bed772eMagnus Damm	p = kmalloc(sizeof(*p), GFP_KERNEL);
6593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p == NULL) {
6603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&pdev->dev, "failed to allocate driver data\n");
6613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return -ENOMEM;
6623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = sh_cmt_setup(p, pdev);
6653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
6668e0b842948156e3463879caed12b4ce51bed772eMagnus Damm		kfree(p);
6673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		platform_set_drvdata(pdev, NULL);
6683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devexit sh_cmt_remove(struct platform_device *pdev)
6733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return -EBUSY; /* cannot unregister clockevent and clocksource */
6753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
677f6431732f128a241b149c0aa85dfec852455ebf9Magnus Dammstatic int sh_cmt_suspend(struct device *dev)
678f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm{
679f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	struct platform_device *pdev = to_platform_device(dev);
680f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
681f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm
682f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	/* save flag state and stop CMT channel */
683f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	p->flags_suspend = p->flags;
684f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	sh_cmt_stop(p, p->flags);
685f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	return 0;
686f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm}
687f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm
688f6431732f128a241b149c0aa85dfec852455ebf9Magnus Dammstatic int sh_cmt_resume(struct device *dev)
689f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm{
690f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	struct platform_device *pdev = to_platform_device(dev);
691f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
692f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm
693f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	/* start CMT channel from saved state */
694f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	sh_cmt_start(p, p->flags_suspend);
695f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	return 0;
696f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm}
697f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm
698f6431732f128a241b149c0aa85dfec852455ebf9Magnus Dammstatic struct dev_pm_ops sh_cmt_dev_pm_ops = {
699f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	.suspend = sh_cmt_suspend,
700f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm	.resume = sh_cmt_resume,
701f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm};
702f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm
7033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct platform_driver sh_cmt_device_driver = {
7043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.probe		= sh_cmt_probe,
7053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.remove		= __devexit_p(sh_cmt_remove),
7063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.driver		= {
7073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		.name	= "sh_cmt",
708f6431732f128a241b149c0aa85dfec852455ebf9Magnus Damm		.pm	= &sh_cmt_dev_pm_ops,
7093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
7103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
7113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __init sh_cmt_init(void)
7133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return platform_driver_register(&sh_cmt_device_driver);
7153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void __exit sh_cmt_exit(void)
7183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_driver_unregister(&sh_cmt_device_driver);
7203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
722e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Dammearly_platform_init("earlytimer", &sh_cmt_device_driver);
7233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_init(sh_cmt_init);
7243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_exit(sh_cmt_exit);
7253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_AUTHOR("Magnus Damm");
7273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_DESCRIPTION("SuperH CMT Timer Driver");
7283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_LICENSE("GPL v2");
729