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