sh_cmt.c revision 03ff858c09c81a659b2a90a08826bc0abdbb784c
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>
325a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstruct sh_cmt_priv {
353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *mapbase;
363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clk *clk;
373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long width; /* 16 or 32 bit version of hardware block */
383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long overflow_bit;
393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long clear_bits;
403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct irqaction irqaction;
413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct platform_device *pdev;
423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
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{
1533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
1543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable clock */
1563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = clk_enable(p->clk);
1573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
158214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "cannot enable clock\n");
1593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return ret;
1603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* make sure channel is disabled */
1633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
1643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* configure channel, periodic mode and maximum timeout */
1663014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	if (p->width == 16) {
1673014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 512;
1683014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		sh_cmt_write(p, CMCSR, 0x43);
1693014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	} else {
1703014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 8;
1713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCSR, 0x01a4);
1723014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	}
1733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCOR, 0xffffffff);
1753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCNT, 0);
1763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable channel */
1783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 1);
1793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
1803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_disable(struct sh_cmt_priv *p)
1833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* disable channel */
1853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
1863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
187be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	/* disable interrupts in CMT block */
188be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	sh_cmt_write(p, CMCSR, 0);
189be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm
1903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* stop clock */
1913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clk_disable(p->clk);
1923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* private flags */
1953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKEVENT (1 << 0)
1963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKSOURCE (1 << 1)
1973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_REPROGRAM (1 << 2)
1983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_SKIPEVENT (1 << 3)
1993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_IRQCONTEXT (1 << 4)
2003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
2023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					      int absolute)
2033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long new_match;
2053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long value = p->next_match_value;
2063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long delay = 0;
2073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long now = 0;
2083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int has_wrapped;
2093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	now = sh_cmt_get_counter(p, &has_wrapped);
2113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_REPROGRAM; /* force reprogram */
2123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (has_wrapped) {
2143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* we're competing with the interrupt handler.
2153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> let the interrupt handler reprogram the timer.
2163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> interrupt number two handles the event.
2173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags |= FLAG_SKIPEVENT;
2193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return;
2203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
2213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (absolute)
2233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = 0;
2243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
2263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* reprogram the timer hardware,
2273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * but don't save the new match value yet.
2283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		new_match = now + value + delay;
2303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (new_match > p->max_match_value)
2313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			new_match = p->max_match_value;
2323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCOR, new_match);
2343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = sh_cmt_get_counter(p, &has_wrapped);
2363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped && (new_match > p->match_value)) {
2373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a greater match value,
2383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so this wrap must be caused by the counter
2393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the old value.
2403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> first interrupt reprograms the timer.
2413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> interrupt number two handles the event.
2423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->flags |= FLAG_SKIPEVENT;
2443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped) {
2483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a smaller match value,
2493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so the wrap must be caused by the counter
2503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the new value.
2513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* be safe: verify hardware settings */
2593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (now < new_match) {
2603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* timer value is below match value, all good.
2613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * this makes sure we won't miss any match events.
2623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* the counter has reached a value greater
2703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * than our new match value. and since the
2713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * has_wrapped flag isn't set we must have
2723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * programmed a too close event.
2733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * -> increase delay and retry.
2743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (delay)
2763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay <<= 1;
2773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		else
2783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay = 1;
2793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!delay)
281214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt			dev_warn(&p->pdev->dev, "too long delay\n");
2823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} while (delay);
2843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
2873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
2893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (delta > p->max_match_value)
291214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_warn(&p->pdev->dev, "delta out of range\n");
2923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
2943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->next_match_value = delta;
2953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_clock_event_program_verify(p, 0);
2963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
2973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
3003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = dev_id;
3023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* clear flags */
3043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
3053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* update clock source counter to begin with if enabled
3073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * the wrap flag should be cleared by the timer specific
3083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * isr before we end up here.
3093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 */
3103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKSOURCE)
31143809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		p->total_cycles += p->match_value + 1;
3123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & FLAG_REPROGRAM))
3143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = p->max_match_value;
3153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_IRQCONTEXT;
3173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKEVENT) {
3193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!(p->flags & FLAG_SKIPEVENT)) {
3203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
3213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->next_match_value = p->max_match_value;
3223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags |= FLAG_REPROGRAM;
3233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			}
3243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->ced.event_handler(&p->ced);
3263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
3273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_SKIPEVENT;
3303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_REPROGRAM) {
3323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags &= ~FLAG_REPROGRAM;
3333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_program_verify(p, 1);
3343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (p->flags & FLAG_CLOCKEVENT)
3363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
3373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			    || (p->match_value == p->next_match_value))
3383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags &= ~FLAG_REPROGRAM;
3393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_IRQCONTEXT;
3423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return IRQ_HANDLED;
3443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
3473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret = 0;
3493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = sh_cmt_enable(p, &p->rate);
3553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret)
3573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto out;
3583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= flag;
3593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* setup timeout if no clockevent */
3613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
3623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm out:
3643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
3673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
3703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long f;
3733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
3773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~flag;
3783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_disable(p);
3813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* adjust the timeout to maximum if only clocksource left */
3833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
3843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
38919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
39019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
39119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return container_of(cs, struct sh_cmt_priv, cs);
39219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
39319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
39419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
39519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
39619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
39719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long flags, raw;
39819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long value;
39919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int has_wrapped;
40019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_lock_irqsave(&p->lock, flags);
40219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	value = p->total_cycles;
40319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	raw = sh_cmt_get_counter(p, &has_wrapped);
40419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (unlikely(has_wrapped))
40643809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		raw += p->match_value + 1;
40719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
40819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return value + raw;
41019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
41119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_clocksource_enable(struct clocksource *cs)
41319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
41419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
41519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	p->total_cycles = 0;
41719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
418f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	return sh_cmt_start(p, FLAG_CLOCKSOURCE);
41919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
42019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
42119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic void sh_cmt_clocksource_disable(struct clocksource *cs)
42219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
42319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
42419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
42519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
426c81628848af8a01f103acc8166299c698898a8f4Magnus Dammstatic void sh_cmt_clocksource_resume(struct clocksource *cs)
427c81628848af8a01f103acc8166299c698898a8f4Magnus Damm{
428c81628848af8a01f103acc8166299c698898a8f4Magnus Damm	sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
429c81628848af8a01f103acc8166299c698898a8f4Magnus Damm}
430c81628848af8a01f103acc8166299c698898a8f4Magnus Damm
43119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
43219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm				       char *name, unsigned long rating)
43319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
43419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource *cs = &p->cs;
43519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
43619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->name = name;
43719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->rating = rating;
43819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->read = sh_cmt_clocksource_read;
43919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->enable = sh_cmt_clocksource_enable;
44019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->disable = sh_cmt_clocksource_disable;
441c81628848af8a01f103acc8166299c698898a8f4Magnus Damm	cs->suspend = sh_cmt_clocksource_disable;
442c81628848af8a01f103acc8166299c698898a8f4Magnus Damm	cs->resume = sh_cmt_clocksource_resume;
44319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
44419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
445f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
446f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	/* clk_get_rate() needs an enabled clock */
447f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	clk_enable(p->clk);
44838409d726bc6413d39f082f60bc803f52d8b5849Magnus Damm	p->rate = clk_get_rate(p->clk) / ((p->width == 16) ? 512 : 8);
449f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	clk_disable(p->clk);
450f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
451f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	/* TODO: calculate good shift from rate and counter bit width */
4525967d33ce8a030f01a716fc0b25fcb03744a5fdaPaul Mundt	cs->shift = 0;
453f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
454f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
455214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	dev_info(&p->pdev->dev, "used as clock source\n");
456f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
45719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	clocksource_register(cs);
458f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
45919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
46019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
46119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
4633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return container_of(ced, struct sh_cmt_priv, ced);
4653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
4683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
4703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start(p, FLAG_CLOCKEVENT);
4723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
4743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->shift = 32;
4763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
4773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
4783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
4793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (periodic)
48143809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1);
4823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
4833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
4843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_mode(enum clock_event_mode mode,
4873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				    struct clock_event_device *ced)
4883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
4903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* deal with old setting first */
4923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (ced->mode) {
4933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
4943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
4953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
4963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
4983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (mode) {
5023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
503214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&p->pdev->dev, "used for periodic clock events\n");
5043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 1);
5053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
507214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&p->pdev->dev, "used for oneshot clock events\n");
5083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 0);
5093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_SHUTDOWN:
5113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_UNUSED:
5123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
5133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
5153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_clock_event_next(unsigned long delta,
5203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				   struct clock_event_device *ced)
5213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
5233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
5253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (likely(p->flags & FLAG_IRQCONTEXT))
52643809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		p->next_match_value = delta - 1;
5273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
52843809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		sh_cmt_set_next(p, delta - 1);
5293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
5343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				       char *name, unsigned long rating)
5353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
5373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(ced, 0, sizeof(*ced));
5393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->name = name;
5413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features = CLOCK_EVT_FEAT_PERIODIC;
5423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
5433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->rating = rating;
5443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->cpumask = cpumask_of(0);
5453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_next_event = sh_cmt_clock_event_next;
5463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_mode = sh_cmt_clock_event_mode;
5473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
548214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	dev_info(&p->pdev->dev, "used for clock events\n");
5493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clockevents_register_device(ced);
5503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
552d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundtstatic int sh_cmt_register(struct sh_cmt_priv *p, char *name,
553d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clockevent_rating,
554d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clocksource_rating)
5553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == (sizeof(p->max_match_value) * 8))
5573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = ~0;
5583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = (1 << p->width) - 1;
5603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->match_value = p->max_match_value;
5623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_init(&p->lock);
5633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (clockevent_rating)
5653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_register_clockevent(p, name, clockevent_rating);
5663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
56719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (clocksource_rating)
56819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		sh_cmt_register_clocksource(p, name, clocksource_rating);
56919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
5703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
5743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
57546a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = pdev->dev.platform_data;
5763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct resource *res;
5773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int irq, ret;
5783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = -ENXIO;
5793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(p, 0, sizeof(*p));
5813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->pdev = pdev;
5823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!cfg) {
5843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "missing platform data\n");
5853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_set_drvdata(pdev, p);
5893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
5913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!res) {
5923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
5933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	irq = platform_get_irq(p->pdev, 0);
5973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (irq < 0) {
5983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get irq\n");
5993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* map memory, let mapbase point to our channel */
6033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->mapbase = ioremap_nocache(res->start, resource_size(res));
6043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->mapbase == NULL) {
605214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "failed to remap I/O memory\n");
6063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* request irq using setup_irq() (too early for request_irq()) */
610214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	p->irqaction.name = dev_name(&p->pdev->dev);
6113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.handler = sh_cmt_interrupt;
6123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.dev_id = p;
613fecf066c2d2fbc7e6a7e7e3a5af772a165bdd7b0Paul Mundt	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \
614fecf066c2d2fbc7e6a7e7e3a5af772a165bdd7b0Paul Mundt			     IRQF_IRQPOLL  | IRQF_NOBALANCING;
6153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* get hold of clock */
617c2a25e819717ea34e8f682d67a3fa76f4893395bPaul Mundt	p->clk = clk_get(&p->pdev->dev, "cmt_fck");
6183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (IS_ERR(p->clk)) {
61903ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		dev_err(&p->pdev->dev, "cannot get clock\n");
62003ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		ret = PTR_ERR(p->clk);
62103ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		goto err1;
6223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (resource_size(res) == 6) {
6253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 16;
6263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x80;
6273014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		p->clear_bits = ~0x80;
6283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else {
6293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 32;
6303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x8000;
6313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->clear_bits = ~0xc000;
6323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
634214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
635da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clockevent_rating,
636da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clocksource_rating);
637da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
638214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "registration failed\n");
639da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
640da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
641da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
642da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	ret = setup_irq(irq, &p->irqaction);
643da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
644214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
645da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
646da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
647da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
648da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	return 0;
649da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
650da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr1:
6513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iounmap(p->mapbase);
652da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr0:
6533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devinit sh_cmt_probe(struct platform_device *pdev)
6573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
6593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
6603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
661e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	if (p) {
662214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&pdev->dev, "kept as earlytimer\n");
663e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		return 0;
664e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	}
665e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm
6668e0b842948156e3463879caed12b4ce51bed772eMagnus Damm	p = kmalloc(sizeof(*p), GFP_KERNEL);
6673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p == NULL) {
6683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&pdev->dev, "failed to allocate driver data\n");
6693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return -ENOMEM;
6703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = sh_cmt_setup(p, pdev);
6733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
6748e0b842948156e3463879caed12b4ce51bed772eMagnus Damm		kfree(p);
6753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		platform_set_drvdata(pdev, NULL);
6763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devexit sh_cmt_remove(struct platform_device *pdev)
6813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return -EBUSY; /* cannot unregister clockevent and clocksource */
6833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct platform_driver sh_cmt_device_driver = {
6863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.probe		= sh_cmt_probe,
6873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.remove		= __devexit_p(sh_cmt_remove),
6883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.driver		= {
6893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		.name	= "sh_cmt",
6903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
6923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __init sh_cmt_init(void)
6943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return platform_driver_register(&sh_cmt_device_driver);
6963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void __exit sh_cmt_exit(void)
6993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_driver_unregister(&sh_cmt_device_driver);
7013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
703e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Dammearly_platform_init("earlytimer", &sh_cmt_device_driver);
7043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_init(sh_cmt_init);
7053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_exit(sh_cmt_exit);
7063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_AUTHOR("Magnus Damm");
7083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_DESCRIPTION("SuperH CMT Timer Driver");
7093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_LICENSE("GPL v2");
710