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