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