sh_cmt.c revision 3014f47460ecfb13d4169daae51f26a20bacfa17
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>
313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/sh_cmt.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;
433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long match_value;
443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long next_match_value;
453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long max_match_value;
463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long rate;
473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spinlock_t lock;
483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device ced;
4919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource cs;
503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long total_cycles;
513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic DEFINE_SPINLOCK(sh_cmt_lock);
543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMSTR -1 /* shared register */
563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCSR 0 /* channel register */
573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCNT 1 /* channel register */
583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCOR 2 /* channel register */
593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return ioread32(base + offs);
783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ioread16(base + offs);
813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				unsigned long value)
853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
1003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
1013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			iowrite32(value, base + offs);
1023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return;
1033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
1043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iowrite16(value, base + offs);
1073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
1103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					int *has_wrapped)
1113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long v1, v2, v3;
1135b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	int o1, o2;
1145b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm
1155b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
1183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
1195b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o2 = o1;
1203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v1 = sh_cmt_read(p, CMCNT);
1213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v2 = sh_cmt_read(p, CMCNT);
1223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v3 = sh_cmt_read(p, CMCNT);
1235b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1245b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
1255b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
1263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1275b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	*has_wrapped = o1;
1283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return v2;
1293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
1333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
1353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags, value;
1363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* start stop register shared by multiple timer channels */
1383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&sh_cmt_lock, flags);
1393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	value = sh_cmt_read(p, CMSTR);
1403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (start)
1423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value |= 1 << cfg->timer_bit;
1433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
1443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value &= ~(1 << cfg->timer_bit);
1453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMSTR, value);
1473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&sh_cmt_lock, flags);
1483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
1513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_config *cfg = p->pdev->dev.platform_data;
1533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
1543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable clock */
1563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = clk_enable(p->clk);
1573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
1583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk);
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
1873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* stop clock */
1883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clk_disable(p->clk);
1893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* private flags */
1923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKEVENT (1 << 0)
1933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKSOURCE (1 << 1)
1943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_REPROGRAM (1 << 2)
1953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_SKIPEVENT (1 << 3)
1963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_IRQCONTEXT (1 << 4)
1973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
1993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					      int absolute)
2003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long new_match;
2023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long value = p->next_match_value;
2033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long delay = 0;
2043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long now = 0;
2053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int has_wrapped;
2063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	now = sh_cmt_get_counter(p, &has_wrapped);
2083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_REPROGRAM; /* force reprogram */
2093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (has_wrapped) {
2113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* we're competing with the interrupt handler.
2123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> let the interrupt handler reprogram the timer.
2133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> interrupt number two handles the event.
2143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags |= FLAG_SKIPEVENT;
2163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return;
2173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
2183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (absolute)
2203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = 0;
2213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
2233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* reprogram the timer hardware,
2243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * but don't save the new match value yet.
2253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		new_match = now + value + delay;
2273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (new_match > p->max_match_value)
2283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			new_match = p->max_match_value;
2293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCOR, new_match);
2313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = sh_cmt_get_counter(p, &has_wrapped);
2333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped && (new_match > p->match_value)) {
2343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a greater match value,
2353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so this wrap must be caused by the counter
2363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the old value.
2373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> first interrupt reprograms the timer.
2383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> interrupt number two handles the event.
2393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->flags |= FLAG_SKIPEVENT;
2413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped) {
2453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a smaller match value,
2463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so the wrap must be caused by the counter
2473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the new value.
2483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* be safe: verify hardware settings */
2563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (now < new_match) {
2573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* timer value is below match value, all good.
2583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * this makes sure we won't miss any match events.
2593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* the counter has reached a value greater
2673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * than our new match value. and since the
2683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * has_wrapped flag isn't set we must have
2693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * programmed a too close event.
2703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * -> increase delay and retry.
2713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (delay)
2733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay <<= 1;
2743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		else
2753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay = 1;
2763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!delay)
2783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			pr_warning("sh_cmt: too long delay\n");
2793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} while (delay);
2813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
2843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
2863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (delta > p->max_match_value)
2883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_warning("sh_cmt: delta out of range\n");
2893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
2913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->next_match_value = delta;
2923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_clock_event_program_verify(p, 0);
2933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
2943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
2973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = dev_id;
2993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* clear flags */
3013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
3023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* update clock source counter to begin with if enabled
3043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * the wrap flag should be cleared by the timer specific
3053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * isr before we end up here.
3063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 */
3073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKSOURCE)
3083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->total_cycles += p->match_value;
3093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & FLAG_REPROGRAM))
3113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = p->max_match_value;
3123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_IRQCONTEXT;
3143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKEVENT) {
3163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!(p->flags & FLAG_SKIPEVENT)) {
3173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
3183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->next_match_value = p->max_match_value;
3193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags |= FLAG_REPROGRAM;
3203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			}
3213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->ced.event_handler(&p->ced);
3233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
3243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_SKIPEVENT;
3273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_REPROGRAM) {
3293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags &= ~FLAG_REPROGRAM;
3303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_program_verify(p, 1);
3313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (p->flags & FLAG_CLOCKEVENT)
3333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
3343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			    || (p->match_value == p->next_match_value))
3353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags &= ~FLAG_REPROGRAM;
3363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_IRQCONTEXT;
3393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return IRQ_HANDLED;
3413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
3443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret = 0;
3463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = sh_cmt_enable(p, &p->rate);
3523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret)
3543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto out;
3553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= flag;
3563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* setup timeout if no clockevent */
3583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
3593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm out:
3613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
3643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
3673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long f;
3703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_irqsave(&p->lock, flags);
3723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
3743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~flag;
3753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_disable(p);
3783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* adjust the timeout to maximum if only clocksource left */
3803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
3813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
3823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
3843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
38619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
38719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
38819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return container_of(cs, struct sh_cmt_priv, cs);
38919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
39019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
39119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
39219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
39319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
39419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long flags, raw;
39519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long value;
39619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int has_wrapped;
39719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
39819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_lock_irqsave(&p->lock, flags);
39919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	value = p->total_cycles;
40019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	raw = sh_cmt_get_counter(p, &has_wrapped);
40119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (unlikely(has_wrapped))
4035b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		raw += p->match_value;
40419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	spin_unlock_irqrestore(&p->lock, flags);
40519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return value + raw;
40719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
40819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
40919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_clocksource_enable(struct clocksource *cs)
41019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
41119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
41219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int ret;
41319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	p->total_cycles = 0;
41519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
41619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
41719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (ret)
41819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		return ret;
41919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
42019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
42119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->shift = 0;
42219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
42319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
42419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
42519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
42619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic void sh_cmt_clocksource_disable(struct clocksource *cs)
42719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
42819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
42919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
43019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus 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;
44119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
44219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
44319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	pr_info("sh_cmt: %s used as clock source\n", cs->name);
44419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	clocksource_register(cs);
44519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
44619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
44719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
4493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return container_of(ced, struct sh_cmt_priv, ced);
4513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
4543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
4563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start(p, FLAG_CLOCKEVENT);
4583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
4603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->shift = 32;
4623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
4633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
4643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
4653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (periodic)
4673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, (p->rate + HZ/2) / HZ);
4683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
4693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
4703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_mode(enum clock_event_mode mode,
4733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				    struct clock_event_device *ced)
4743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
4763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* deal with old setting first */
4783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (ced->mode) {
4793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
4803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
4813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
4823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
4843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
4863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (mode) {
4883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
4893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_info("sh_cmt: %s used for periodic clock events\n",
4903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			ced->name);
4913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 1);
4923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
4943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_info("sh_cmt: %s used for oneshot clock events\n",
4953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			ced->name);
4963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 0);
4973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
4983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_SHUTDOWN:
4993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_UNUSED:
5003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
5013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
5033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_clock_event_next(unsigned long delta,
5083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				   struct clock_event_device *ced)
5093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
5113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
5133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (likely(p->flags & FLAG_IRQCONTEXT))
5143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = delta;
5153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, delta);
5173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
5223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				       char *name, unsigned long rating)
5233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
5253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(ced, 0, sizeof(*ced));
5273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->name = name;
5293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features = CLOCK_EVT_FEAT_PERIODIC;
5303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
5313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->rating = rating;
5323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->cpumask = cpumask_of(0);
5333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_next_event = sh_cmt_clock_event_next;
5343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_mode = sh_cmt_clock_event_mode;
5353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	pr_info("sh_cmt: %s used for clock events\n", ced->name);
5373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clockevents_register_device(ced);
5383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammint sh_cmt_register(struct sh_cmt_priv *p, char *name,
5413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		    unsigned long clockevent_rating,
5423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		    unsigned long clocksource_rating)
5433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == (sizeof(p->max_match_value) * 8))
5453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = ~0;
5463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = (1 << p->width) - 1;
5483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->match_value = p->max_match_value;
5503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	spin_lock_init(&p->lock);
5513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (clockevent_rating)
5533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_register_clockevent(p, name, clockevent_rating);
5543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
55519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (clocksource_rating)
55619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		sh_cmt_register_clocksource(p, name, clocksource_rating);
55719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
5583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
5623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_config *cfg = pdev->dev.platform_data;
5643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct resource *res;
5653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int irq, ret;
5663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = -ENXIO;
5673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(p, 0, sizeof(*p));
5693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->pdev = pdev;
5703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!cfg) {
5723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "missing platform data\n");
5733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_set_drvdata(pdev, p);
5773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
5793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!res) {
5803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
5813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	irq = platform_get_irq(p->pdev, 0);
5853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (irq < 0) {
5863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get irq\n");
5873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* map memory, let mapbase point to our channel */
5913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->mapbase = ioremap_nocache(res->start, resource_size(res));
5923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->mapbase == NULL) {
5933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: failed to remap I/O memory\n");
5943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
5953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* request irq using setup_irq() (too early for request_irq()) */
5983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.name = cfg->name;
5993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.handler = sh_cmt_interrupt;
6003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.dev_id = p;
6013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
6023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.mask = CPU_MASK_NONE;
6033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = setup_irq(irq, &p->irqaction);
6043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
6053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: failed to request irq %d\n", irq);
6063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err1;
6073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* get hold of clock */
6103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->clk = clk_get(&p->pdev->dev, cfg->clk);
6113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (IS_ERR(p->clk)) {
6123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
6133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = PTR_ERR(p->clk);
6143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err2;
6153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (resource_size(res) == 6) {
6183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 16;
6193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x80;
6203014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		p->clear_bits = ~0x80;
6213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else {
6223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 32;
6233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x8000;
6243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->clear_bits = ~0xc000;
6253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return sh_cmt_register(p, cfg->name,
6283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			       cfg->clockevent_rating,
6293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			       cfg->clocksource_rating);
6303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm err2:
6313093e78ebab100ada1c724c9f751d9da39602a97Magnus Damm	remove_irq(irq, &p->irqaction);
6323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm err1:
6333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iounmap(p->mapbase);
6343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm err0:
6353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devinit sh_cmt_probe(struct platform_device *pdev)
6393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
641e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	struct sh_cmt_config *cfg = pdev->dev.platform_data;
6423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
6433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
644e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	if (p) {
645e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name);
646e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		return 0;
647e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	}
648e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm
6498e0b842948156e3463879caed12b4ce51bed772eMagnus Damm	p = kmalloc(sizeof(*p), GFP_KERNEL);
6503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p == NULL) {
6513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&pdev->dev, "failed to allocate driver data\n");
6523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return -ENOMEM;
6533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = sh_cmt_setup(p, pdev);
6563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
6578e0b842948156e3463879caed12b4ce51bed772eMagnus Damm		kfree(p);
6583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		platform_set_drvdata(pdev, NULL);
6593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
6613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devexit sh_cmt_remove(struct platform_device *pdev)
6643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return -EBUSY; /* cannot unregister clockevent and clocksource */
6663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct platform_driver sh_cmt_device_driver = {
6693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.probe		= sh_cmt_probe,
6703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.remove		= __devexit_p(sh_cmt_remove),
6713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.driver		= {
6723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		.name	= "sh_cmt",
6733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
6753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __init sh_cmt_init(void)
6773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return platform_driver_register(&sh_cmt_device_driver);
6793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void __exit sh_cmt_exit(void)
6823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_driver_unregister(&sh_cmt_device_driver);
6843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
686e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Dammearly_platform_init("earlytimer", &sh_cmt_device_driver);
6873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_init(sh_cmt_init);
6883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_exit(sh_cmt_exit);
6893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_AUTHOR("Magnus Damm");
6913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_DESCRIPTION("SuperH CMT Timer Driver");
6923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_LICENSE("GPL v2");
693