sh_cmt.c revision 9bb5ec8872312751f992cdac9968805fe03e81aa
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>
293f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm#include <linux/delay.h>
303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/clocksource.h>
313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#include <linux/clockchips.h>
3246a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt#include <linux/sh_timer.h>
335a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
347deeab5dc414240a341e80f41b5f00620aa9ef98Paul Gortmaker#include <linux/module.h>
35615a445f7f8a077c145e737864ae59a4d8717882Rafael J. Wysocki#include <linux/pm_domain.h>
363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstruct sh_cmt_priv {
383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *mapbase;
393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clk *clk;
403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long width; /* 16 or 32 bit version of hardware block */
413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long overflow_bit;
423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long clear_bits;
433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct irqaction irqaction;
443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct platform_device *pdev;
453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long match_value;
483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long next_match_value;
493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long max_match_value;
503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long rate;
517d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spinlock_t lock;
523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device ced;
5319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource cs;
543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long total_cycles;
553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
577d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundtstatic DEFINE_RAW_SPINLOCK(sh_cmt_lock);
583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMSTR -1 /* shared register */
603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCSR 0 /* channel register */
613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCNT 1 /* channel register */
623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define CMCOR 2 /* channel register */
633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6646a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return ioread32(base + offs);
823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ioread16(base + offs);
853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				unsigned long value)
893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
9046a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	void __iomem *base = p->mapbase;
923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long offs;
933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (reg_nr == CMSTR) {
953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = 0;
963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		base -= cfg->channel_offset;
973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else
983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs = reg_nr;
993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == 16)
1013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 1;
1023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else {
1033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		offs <<= 2;
1043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
1053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			iowrite32(value, base + offs);
1063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			return;
1073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
1083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iowrite16(value, base + offs);
1113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
1143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					int *has_wrapped)
1153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long v1, v2, v3;
1175b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	int o1, o2;
1185b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm
1195b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
1223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
1235b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o2 = o1;
1243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v1 = sh_cmt_read(p, CMCNT);
1253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v2 = sh_cmt_read(p, CMCNT);
1263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		v3 = sh_cmt_read(p, CMCNT);
1275b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
1285b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
1295b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
1303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1315b644c7a218702668d7b610994e7dcbc3d4705d3Magnus Damm	*has_wrapped = o1;
1323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return v2;
1333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
1373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
13846a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
1393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags, value;
1403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* start stop register shared by multiple timer channels */
1427d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
1433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	value = sh_cmt_read(p, CMSTR);
1443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (start)
1463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value |= 1 << cfg->timer_bit;
1473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
1483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		value &= ~(1 << cfg->timer_bit);
1493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMSTR, value);
1517d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
1523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
1533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
1553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
1563f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	int k, ret;
1573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1589436b4abec28a22edd961ae375535d940625f1f2Paul Mundt	/* enable clock */
1593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = clk_enable(p->clk);
1603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
161214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "cannot enable clock\n");
1623f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		goto err0;
1633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
1643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* make sure channel is disabled */
1663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
1673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* configure channel, periodic mode and maximum timeout */
1693014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	if (p->width == 16) {
1703014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 512;
1713014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		sh_cmt_write(p, CMCSR, 0x43);
1723014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	} else {
1733014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		*rate = clk_get_rate(p->clk) / 8;
1743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCSR, 0x01a4);
1753014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm	}
1763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCOR, 0xffffffff);
1783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCNT, 0);
1793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
1803f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	/*
1813f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * According to the sh73a0 user's manual, as CMCNT can be operated
1823f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * only by the RCLK (Pseudo 32 KHz), there's one restriction on
1833f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * modifying CMCNT register; two RCLK cycles are necessary before
1843f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * this register is either read or any modification of the value
1853f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * it holds is reflected in the LSI's actual operation.
1863f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 *
1873f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * While at it, we're supposed to clear out the CMCNT as of this
1883f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * moment, so make sure it's processed properly here.  This will
1893f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 * take RCLKx2 at maximum.
1903f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	 */
1913f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	for (k = 0; k < 100; k++) {
1923f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		if (!sh_cmt_read(p, CMCNT))
1933f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm			break;
1943f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		udelay(1);
1953f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	}
1963f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm
1973f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	if (sh_cmt_read(p, CMCNT)) {
1983f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
1993f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		ret = -ETIMEDOUT;
2003f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm		goto err1;
2013f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	}
2023f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm
2033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* enable channel */
2043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 1);
2053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
2063f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm err1:
2073f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	/* stop clock */
2083f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	clk_disable(p->clk);
2093f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm
2103f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm err0:
2113f7e5e2423f6233f7665d54061ba7761ca90cf52Magnus Damm	return ret;
2123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_disable(struct sh_cmt_priv *p)
2153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* disable channel */
2173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start_stop_ch(p, 0);
2183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
219be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	/* disable interrupts in CMT block */
220be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm	sh_cmt_write(p, CMCSR, 0);
221be890a1a95fb439594e796f1968f86ee9f36e718Magnus Damm
2229436b4abec28a22edd961ae375535d940625f1f2Paul Mundt	/* stop clock */
2233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clk_disable(p->clk);
2243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
2253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm/* private flags */
2273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKEVENT (1 << 0)
2283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_CLOCKSOURCE (1 << 1)
2293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_REPROGRAM (1 << 2)
2303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_SKIPEVENT (1 << 3)
2313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm#define FLAG_IRQCONTEXT (1 << 4)
2323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
2343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm					      int absolute)
2353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
2363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long new_match;
2373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long value = p->next_match_value;
2383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long delay = 0;
2393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long now = 0;
2403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int has_wrapped;
2413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	now = sh_cmt_get_counter(p, &has_wrapped);
2433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_REPROGRAM; /* force reprogram */
2443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (has_wrapped) {
2463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* we're competing with the interrupt handler.
2473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> let the interrupt handler reprogram the timer.
2483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 *  -> interrupt number two handles the event.
2493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags |= FLAG_SKIPEVENT;
2513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return;
2523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
2533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (absolute)
2553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = 0;
2563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	do {
2583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* reprogram the timer hardware,
2593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * but don't save the new match value yet.
2603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
2613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		new_match = now + value + delay;
2623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (new_match > p->max_match_value)
2633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			new_match = p->max_match_value;
2643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_write(p, CMCOR, new_match);
2663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		now = sh_cmt_get_counter(p, &has_wrapped);
2683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped && (new_match > p->match_value)) {
2693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a greater match value,
2703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so this wrap must be caused by the counter
2713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the old value.
2723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> first interrupt reprograms the timer.
2733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> interrupt number two handles the event.
2743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->flags |= FLAG_SKIPEVENT;
2763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (has_wrapped) {
2803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* we are changing to a smaller match value,
2813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * so the wrap must be caused by the counter
2823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * matching the new value.
2833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
2893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
2903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* be safe: verify hardware settings */
2913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (now < new_match) {
2923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			/* timer value is below match value, all good.
2933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * this makes sure we won't miss any match events.
2943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> save programmed match value.
2953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 * -> let isr handle the event.
2963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			 */
2973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->match_value = new_match;
2983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			break;
2993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
3003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3013fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		/* the counter has reached a value greater
3023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * than our new match value. and since the
3033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * has_wrapped flag isn't set we must have
3043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * programmed a too close event.
3053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 * -> increase delay and retry.
3063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		 */
3073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (delay)
3083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay <<= 1;
3093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		else
3103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			delay = 1;
3113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!delay)
313214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt			dev_warn(&p->pdev->dev, "too long delay\n");
3143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} while (delay);
3163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
31865ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHIIstatic void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
3193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (delta > p->max_match_value)
321214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_warn(&p->pdev->dev, "delta out of range\n");
3223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->next_match_value = delta;
3243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_clock_event_program_verify(p, 0);
32565ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII}
32665ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII
32765ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHIIstatic void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
32865ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII{
32965ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII	unsigned long flags;
33065ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII
3317d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_irqsave(&p->lock, flags);
33265ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII	__sh_cmt_set_next(p, delta);
3337d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_unlock_irqrestore(&p->lock, flags);
3343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
3373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = dev_id;
3393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* clear flags */
3413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
3423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* update clock source counter to begin with if enabled
3443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * the wrap flag should be cleared by the timer specific
3453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 * isr before we end up here.
3463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	 */
3473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKSOURCE)
34843809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		p->total_cycles += p->match_value + 1;
3493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & FLAG_REPROGRAM))
3513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->next_match_value = p->max_match_value;
3523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= FLAG_IRQCONTEXT;
3543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_CLOCKEVENT) {
3563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (!(p->flags & FLAG_SKIPEVENT)) {
3573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
3583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->next_match_value = p->max_match_value;
3593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags |= FLAG_REPROGRAM;
3603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			}
3613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			p->ced.event_handler(&p->ced);
3633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		}
3643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_SKIPEVENT;
3673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->flags & FLAG_REPROGRAM) {
3693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->flags &= ~FLAG_REPROGRAM;
3703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_program_verify(p, 1);
3713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		if (p->flags & FLAG_CLOCKEVENT)
3733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
3743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm			    || (p->match_value == p->next_match_value))
3753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				p->flags &= ~FLAG_REPROGRAM;
3763fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
3773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~FLAG_IRQCONTEXT;
3793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return IRQ_HANDLED;
3813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
3823fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
3843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
3853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret = 0;
3863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
3873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3887d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_irqsave(&p->lock, flags);
3893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
3913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		ret = sh_cmt_enable(p, &p->rate);
3923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret)
3943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto out;
3953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags |= flag;
3963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
3973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* setup timeout if no clockevent */
3983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
39965ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII		__sh_cmt_set_next(p, p->max_match_value);
4003fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm out:
4017d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_unlock_irqrestore(&p->lock, flags);
4023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4033fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
4043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
4073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
4083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long flags;
4093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	unsigned long f;
4103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4117d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_irqsave(&p->lock, flags);
4123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
4143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->flags &= ~flag;
4153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
4173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_disable(p);
4183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* adjust the timeout to maximum if only clocksource left */
4203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
42165ada547d68dc075aa06df92fe325bff07cbc606Takashi YOSHII		__sh_cmt_set_next(p, p->max_match_value);
4223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
4237d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_unlock_irqrestore(&p->lock, flags);
4243fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
4253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
42619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
42719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
42819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return container_of(cs, struct sh_cmt_priv, cs);
42919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
43019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
43119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
43219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
43319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
43419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long flags, raw;
43519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	unsigned long value;
43619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	int has_wrapped;
43719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4387d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_irqsave(&p->lock, flags);
43919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	value = p->total_cycles;
44019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	raw = sh_cmt_get_counter(p, &has_wrapped);
44119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
44219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (unlikely(has_wrapped))
44343809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		raw += p->match_value + 1;
4447d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_unlock_irqrestore(&p->lock, flags);
44519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
44619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return value + raw;
44719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
44819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
44919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_clocksource_enable(struct clocksource *cs)
45019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
4513593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	int ret;
45219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
45319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
45419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	p->total_cycles = 0;
45519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4563593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
4573593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	if (!ret)
4583593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm		__clocksource_updatefreq_hz(cs, p->rate);
4593593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	return ret;
46019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
46119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
46219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic void sh_cmt_clocksource_disable(struct clocksource *cs)
46319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
46419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
46519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
46619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
4679bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clocksource_suspend(struct clocksource *cs)
4689bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{
4699bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
4709bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
4719bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	sh_cmt_stop(p, FLAG_CLOCKSOURCE);
4729bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	pm_genpd_syscore_poweroff(&p->pdev->dev);
4739bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki}
4749bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
475c81628848af8a01f103acc8166299c698898a8f4Magnus Dammstatic void sh_cmt_clocksource_resume(struct clocksource *cs)
476c81628848af8a01f103acc8166299c698898a8f4Magnus Damm{
4779bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
4789bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
4799bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	pm_genpd_syscore_poweron(&p->pdev->dev);
4809bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	sh_cmt_start(p, FLAG_CLOCKSOURCE);
481c81628848af8a01f103acc8166299c698898a8f4Magnus Damm}
482c81628848af8a01f103acc8166299c698898a8f4Magnus Damm
48319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Dammstatic int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
48419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm				       char *name, unsigned long rating)
48519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm{
48619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	struct clocksource *cs = &p->cs;
48719bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
48819bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->name = name;
48919bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->rating = rating;
49019bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->read = sh_cmt_clocksource_read;
49119bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->enable = sh_cmt_clocksource_enable;
49219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->disable = sh_cmt_clocksource_disable;
4939bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	cs->suspend = sh_cmt_clocksource_suspend;
494c81628848af8a01f103acc8166299c698898a8f4Magnus Damm	cs->resume = sh_cmt_clocksource_resume;
49519bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
49619bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
497f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
498214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	dev_info(&p->pdev->dev, "used as clock source\n");
499f4d7c3565c1692c54d9152b52090fe73f0029e37Paul Mundt
5003593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	/* Register with dummy 1 Hz value, gets updated in ->enable() */
5013593f5fe40a13badf6921ccbc3378b02fbf6a532Magnus Damm	clocksource_register_hz(cs, 1);
50219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	return 0;
50319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm}
50419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
5053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
5063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5073fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return container_of(ced, struct sh_cmt_priv, ced);
5083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
5113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
5133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	sh_cmt_start(p, FLAG_CLOCKEVENT);
5153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* TODO: calculate good shift from rate and counter bit width */
5173fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->shift = 32;
5193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
5203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
5213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
5223fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5233fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (periodic)
52443809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1);
5253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
5263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_set_next(p, p->max_match_value);
5273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_clock_event_mode(enum clock_event_mode mode,
5303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				    struct clock_event_device *ced)
5313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
5333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* deal with old setting first */
5353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (ced->mode) {
5363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
5373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
5383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
5393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
5413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	switch (mode) {
5453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_PERIODIC:
546214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&p->pdev->dev, "used for periodic clock events\n");
5473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 1);
5483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_ONESHOT:
550214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&p->pdev->dev, "used for oneshot clock events\n");
5513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_clock_event_start(p, 0);
5523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_SHUTDOWN:
5543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	case CLOCK_EVT_MODE_UNUSED:
5553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_stop(p, FLAG_CLOCKEVENT);
5563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	default:
5583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		break;
5593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
5603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_clock_event_next(unsigned long delta,
5633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				   struct clock_event_device *ced)
5643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5653fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
5663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
5683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (likely(p->flags & FLAG_IRQCONTEXT))
56943809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		p->next_match_value = delta - 1;
5703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
57143809473b9d5fa9f82bf64ddeb3c21fe1140ef0eMagnus Damm		sh_cmt_set_next(p, delta - 1);
5723fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
5743fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
5753fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5769bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
5779bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{
5789bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev);
5799bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki}
5809bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
5819bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysockistatic void sh_cmt_clock_event_resume(struct clock_event_device *ced)
5829bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki{
5839bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev);
5849bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki}
5859bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
5863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
5873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm				       char *name, unsigned long rating)
5883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
5893fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct clock_event_device *ced = &p->ced;
5903fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5913fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(ced, 0, sizeof(*ced));
5923fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
5933fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->name = name;
5943fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features = CLOCK_EVT_FEAT_PERIODIC;
5953fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
5963fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->rating = rating;
5973fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->cpumask = cpumask_of(0);
5983fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_next_event = sh_cmt_clock_event_next;
5993fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ced->set_mode = sh_cmt_clock_event_mode;
6009bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	ced->suspend = sh_cmt_clock_event_suspend;
6019bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	ced->resume = sh_cmt_clock_event_resume;
6023fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
603214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	dev_info(&p->pdev->dev, "used for clock events\n");
6043fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	clockevents_register_device(ced);
6053fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
607d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundtstatic int sh_cmt_register(struct sh_cmt_priv *p, char *name,
608d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clockevent_rating,
609d1fcc0a8db5e47c1abaa783a3e83dbf5f2184969Paul Mundt			   unsigned long clocksource_rating)
6103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
6113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->width == (sizeof(p->max_match_value) * 8))
6123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = ~0;
6133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	else
6143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->max_match_value = (1 << p->width) - 1;
6153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6163fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->match_value = p->max_match_value;
6177d0c399fe94d4fe572eadc7405654a282e5df63dPaul Mundt	raw_spin_lock_init(&p->lock);
6183fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6193fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (clockevent_rating)
6203fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		sh_cmt_register_clockevent(p, name, clockevent_rating);
6213fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
62219bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm	if (clocksource_rating)
62319bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm		sh_cmt_register_clocksource(p, name, clocksource_rating);
62419bdc9d061bcb71efd2b53083d96b59bbe1a1751Magnus Damm
6253fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return 0;
6263fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
6273fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6283fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
6293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
63046a12f7426d71cabc08972cf8d3ffdd441d26a3aPaul Mundt	struct sh_timer_config *cfg = pdev->dev.platform_data;
6313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct resource *res;
6323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int irq, ret;
6333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = -ENXIO;
6343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	memset(p, 0, sizeof(*p));
6363fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->pdev = pdev;
6373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!cfg) {
6393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "missing platform data\n");
6403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_set_drvdata(pdev, p);
6443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
6463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (!res) {
6473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
6483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	irq = platform_get_irq(p->pdev, 0);
6523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (irq < 0) {
6533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&p->pdev->dev, "failed to get irq\n");
6543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* map memory, let mapbase point to our channel */
6583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->mapbase = ioremap_nocache(res->start, resource_size(res));
6593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p->mapbase == NULL) {
660214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "failed to remap I/O memory\n");
6613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		goto err0;
6623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* request irq using setup_irq() (too early for request_irq()) */
665214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	p->irqaction.name = dev_name(&p->pdev->dev);
6663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.handler = sh_cmt_interrupt;
6673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	p->irqaction.dev_id = p;
668fecf066c2d2fbc7e6a7e7e3a5af772a165bdd7b0Paul Mundt	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \
669fecf066c2d2fbc7e6a7e7e3a5af772a165bdd7b0Paul Mundt			     IRQF_IRQPOLL  | IRQF_NOBALANCING;
6703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	/* get hold of clock */
672c2a25e819717ea34e8f682d67a3fa76f4893395bPaul Mundt	p->clk = clk_get(&p->pdev->dev, "cmt_fck");
6733fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (IS_ERR(p->clk)) {
67403ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		dev_err(&p->pdev->dev, "cannot get clock\n");
67503ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		ret = PTR_ERR(p->clk);
67603ff858c09c81a659b2a90a08826bc0abdbb784cMagnus Damm		goto err1;
6773fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6783fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
6793fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (resource_size(res) == 6) {
6803fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 16;
6813fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x80;
6823014f47460ecfb13d4169daae51f26a20bacfa17Magnus Damm		p->clear_bits = ~0x80;
6833fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	} else {
6843fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->width = 32;
6853fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->overflow_bit = 0x8000;
6863fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		p->clear_bits = ~0xc000;
6873fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
6883fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
689214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt	ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
690da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clockevent_rating,
691da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt			      cfg->clocksource_rating);
692da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
693214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "registration failed\n");
694da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
695da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
696da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
697da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	ret = setup_irq(irq, &p->irqaction);
698da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	if (ret) {
699214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
700da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt		goto err1;
701da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	}
702da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
703da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt	return 0;
704da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundt
705da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr1:
7063fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	iounmap(p->mapbase);
707da64c2a8dee66ca03f4f3e15d84be7bedf73db3dPaul Mundterr0:
7083fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
7093fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7103fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7113fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devinit sh_cmt_probe(struct platform_device *pdev)
7123fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7133fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
7143fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	int ret;
7153fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7169bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	if (!is_early_platform_device(pdev)) {
7179bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki		struct sh_timer_config *cfg = pdev->dev.platform_data;
7189bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki
7199bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki		if (cfg->clocksource_rating || cfg->clockevent_rating)
7209bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki			pm_genpd_dev_always_on(&pdev->dev, true);
7219bb5ec8872312751f992cdac9968805fe03e81aaRafael J. Wysocki	}
722615a445f7f8a077c145e737864ae59a4d8717882Rafael J. Wysocki
723e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	if (p) {
724214a607a4f5bf5a14dab0304ba350cdaf3916795Paul Mundt		dev_info(&pdev->dev, "kept as earlytimer\n");
725e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm		return 0;
726e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm	}
727e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Damm
7288e0b842948156e3463879caed12b4ce51bed772eMagnus Damm	p = kmalloc(sizeof(*p), GFP_KERNEL);
7293fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (p == NULL) {
7303fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		dev_err(&pdev->dev, "failed to allocate driver data\n");
7313fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		return -ENOMEM;
7323fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
7333fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7343fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	ret = sh_cmt_setup(p, pdev);
7353fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	if (ret) {
7368e0b842948156e3463879caed12b4ce51bed772eMagnus Damm		kfree(p);
7373fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		platform_set_drvdata(pdev, NULL);
7383fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
7393fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return ret;
7403fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7413fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7423fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __devexit sh_cmt_remove(struct platform_device *pdev)
7433fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7443fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return -EBUSY; /* cannot unregister clockevent and clocksource */
7453fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7463fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7473fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic struct platform_driver sh_cmt_device_driver = {
7483fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.probe		= sh_cmt_probe,
7493fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.remove		= __devexit_p(sh_cmt_remove),
7503fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	.driver		= {
7513fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm		.name	= "sh_cmt",
7523fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	}
7533fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm};
7543fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7553fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic int __init sh_cmt_init(void)
7563fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7573fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	return platform_driver_register(&sh_cmt_device_driver);
7583fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7593fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7603fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammstatic void __exit sh_cmt_exit(void)
7613fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm{
7623fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm	platform_driver_unregister(&sh_cmt_device_driver);
7633fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm}
7643fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
765e475eedb09ee9a0fd855f3e923aa9af31c17d141Magnus Dammearly_platform_init("earlytimer", &sh_cmt_device_driver);
7663fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_init(sh_cmt_init);
7673fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Dammmodule_exit(sh_cmt_exit);
7683fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus Damm
7693fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_AUTHOR("Magnus Damm");
7703fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_DESCRIPTION("SuperH CMT Timer Driver");
7713fb1b6ad0679ad671bd496712b2a088550ee86b2Magnus DammMODULE_LICENSE("GPL v2");
772