timer-imx-gpt.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /*
  2. * linux/arch/arm/plat-mxc/time.c
  3. *
  4. * Copyright (C) 2000-2001 Deep Blue Solutions
  5. * Copyright (C) 2002 Shane Nay (shane@minirl.com)
  6. * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
  7. * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21. * MA 02110-1301, USA.
  22. */
  23. #include <linux/interrupt.h>
  24. #include <linux/irq.h>
  25. #include <linux/clockchips.h>
  26. #include <linux/clk.h>
  27. #include <linux/delay.h>
  28. #include <linux/err.h>
  29. #include <linux/sched_clock.h>
  30. #include <linux/slab.h>
  31. #include <linux/of.h>
  32. #include <linux/of_address.h>
  33. #include <linux/of_irq.h>
  34. #include <soc/imx/timer.h>
  35. /*
  36. * There are 4 versions of the timer hardware on Freescale MXC hardware.
  37. * - MX1/MXL
  38. * - MX21, MX27.
  39. * - MX25, MX31, MX35, MX37, MX51, MX6Q(rev1.0)
  40. * - MX6DL, MX6SX, MX6Q(rev1.1+)
  41. */
  42. /* defines common for all i.MX */
  43. #define MXC_TCTL 0x00
  44. #define MXC_TCTL_TEN (1 << 0) /* Enable module */
  45. #define MXC_TPRER 0x04
  46. /* MX1, MX21, MX27 */
  47. #define MX1_2_TCTL_CLK_PCLK1 (1 << 1)
  48. #define MX1_2_TCTL_IRQEN (1 << 4)
  49. #define MX1_2_TCTL_FRR (1 << 8)
  50. #define MX1_2_TCMP 0x08
  51. #define MX1_2_TCN 0x10
  52. #define MX1_2_TSTAT 0x14
  53. /* MX21, MX27 */
  54. #define MX2_TSTAT_CAPT (1 << 1)
  55. #define MX2_TSTAT_COMP (1 << 0)
  56. /* MX31, MX35, MX25, MX5, MX6 */
  57. #define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */
  58. #define V2_TCTL_CLK_IPG (1 << 6)
  59. #define V2_TCTL_CLK_PER (2 << 6)
  60. #define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
  61. #define V2_TCTL_FRR (1 << 9)
  62. #define V2_TCTL_24MEN (1 << 10)
  63. #define V2_TPRER_PRE24M 12
  64. #define V2_IR 0x0c
  65. #define V2_TSTAT 0x08
  66. #define V2_TSTAT_OF1 (1 << 0)
  67. #define V2_TCN 0x24
  68. #define V2_TCMP 0x10
  69. #define V2_TIMER_RATE_OSC_DIV8 3000000
  70. struct imx_timer {
  71. enum imx_gpt_type type;
  72. void __iomem *base;
  73. int irq;
  74. struct clk *clk_per;
  75. struct clk *clk_ipg;
  76. const struct imx_gpt_data *gpt;
  77. struct clock_event_device ced;
  78. enum clock_event_mode cem;
  79. struct irqaction act;
  80. };
  81. struct imx_gpt_data {
  82. int reg_tstat;
  83. int reg_tcn;
  84. int reg_tcmp;
  85. void (*gpt_setup_tctl)(struct imx_timer *imxtm);
  86. void (*gpt_irq_enable)(struct imx_timer *imxtm);
  87. void (*gpt_irq_disable)(struct imx_timer *imxtm);
  88. void (*gpt_irq_acknowledge)(struct imx_timer *imxtm);
  89. int (*set_next_event)(unsigned long evt,
  90. struct clock_event_device *ced);
  91. };
  92. static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced)
  93. {
  94. return container_of(ced, struct imx_timer, ced);
  95. }
  96. static void imx1_gpt_irq_disable(struct imx_timer *imxtm)
  97. {
  98. unsigned int tmp;
  99. tmp = readl_relaxed(imxtm->base + MXC_TCTL);
  100. writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
  101. }
  102. #define imx21_gpt_irq_disable imx1_gpt_irq_disable
  103. static void imx31_gpt_irq_disable(struct imx_timer *imxtm)
  104. {
  105. writel_relaxed(0, imxtm->base + V2_IR);
  106. }
  107. #define imx6dl_gpt_irq_disable imx31_gpt_irq_disable
  108. static void imx1_gpt_irq_enable(struct imx_timer *imxtm)
  109. {
  110. unsigned int tmp;
  111. tmp = readl_relaxed(imxtm->base + MXC_TCTL);
  112. writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
  113. }
  114. #define imx21_gpt_irq_enable imx1_gpt_irq_enable
  115. static void imx31_gpt_irq_enable(struct imx_timer *imxtm)
  116. {
  117. writel_relaxed(1<<0, imxtm->base + V2_IR);
  118. }
  119. #define imx6dl_gpt_irq_enable imx31_gpt_irq_enable
  120. static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm)
  121. {
  122. writel_relaxed(0, imxtm->base + MX1_2_TSTAT);
  123. }
  124. static void imx21_gpt_irq_acknowledge(struct imx_timer *imxtm)
  125. {
  126. writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
  127. imxtm->base + MX1_2_TSTAT);
  128. }
  129. static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm)
  130. {
  131. writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT);
  132. }
  133. #define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge
  134. static void __iomem *sched_clock_reg;
  135. static u64 notrace mxc_read_sched_clock(void)
  136. {
  137. return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0;
  138. }
  139. static struct delay_timer imx_delay_timer;
  140. static unsigned long imx_read_current_timer(void)
  141. {
  142. return readl_relaxed(sched_clock_reg);
  143. }
  144. static int __init mxc_clocksource_init(struct imx_timer *imxtm)
  145. {
  146. unsigned int c = clk_get_rate(imxtm->clk_per);
  147. void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn;
  148. imx_delay_timer.read_current_timer = &imx_read_current_timer;
  149. imx_delay_timer.freq = c;
  150. register_current_timer_delay(&imx_delay_timer);
  151. sched_clock_reg = reg;
  152. sched_clock_register(mxc_read_sched_clock, 32, c);
  153. return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
  154. clocksource_mmio_readl_up);
  155. }
  156. /* clock event */
  157. static int mx1_2_set_next_event(unsigned long evt,
  158. struct clock_event_device *ced)
  159. {
  160. struct imx_timer *imxtm = to_imx_timer(ced);
  161. unsigned long tcmp;
  162. tcmp = readl_relaxed(imxtm->base + MX1_2_TCN) + evt;
  163. writel_relaxed(tcmp, imxtm->base + MX1_2_TCMP);
  164. return (int)(tcmp - readl_relaxed(imxtm->base + MX1_2_TCN)) < 0 ?
  165. -ETIME : 0;
  166. }
  167. static int v2_set_next_event(unsigned long evt,
  168. struct clock_event_device *ced)
  169. {
  170. struct imx_timer *imxtm = to_imx_timer(ced);
  171. unsigned long tcmp;
  172. tcmp = readl_relaxed(imxtm->base + V2_TCN) + evt;
  173. writel_relaxed(tcmp, imxtm->base + V2_TCMP);
  174. return evt < 0x7fffffff &&
  175. (int)(tcmp - readl_relaxed(imxtm->base + V2_TCN)) < 0 ?
  176. -ETIME : 0;
  177. }
  178. #ifdef DEBUG
  179. static const char *clock_event_mode_label[] = {
  180. [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
  181. [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
  182. [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
  183. [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED",
  184. [CLOCK_EVT_MODE_RESUME] = "CLOCK_EVT_MODE_RESUME",
  185. };
  186. #endif /* DEBUG */
  187. static void mxc_set_mode(enum clock_event_mode mode,
  188. struct clock_event_device *ced)
  189. {
  190. struct imx_timer *imxtm = to_imx_timer(ced);
  191. unsigned long flags;
  192. /*
  193. * The timer interrupt generation is disabled at least
  194. * for enough time to call mxc_set_next_event()
  195. */
  196. local_irq_save(flags);
  197. /* Disable interrupt in GPT module */
  198. imxtm->gpt->gpt_irq_disable(imxtm);
  199. if (mode != imxtm->cem) {
  200. u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
  201. /* Set event time into far-far future */
  202. writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
  203. /* Clear pending interrupt */
  204. imxtm->gpt->gpt_irq_acknowledge(imxtm);
  205. }
  206. #ifdef DEBUG
  207. printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
  208. clock_event_mode_label[imxtm->cem],
  209. clock_event_mode_label[mode]);
  210. #endif /* DEBUG */
  211. /* Remember timer mode */
  212. imxtm->cem = mode;
  213. local_irq_restore(flags);
  214. switch (mode) {
  215. case CLOCK_EVT_MODE_PERIODIC:
  216. printk(KERN_ERR"mxc_set_mode: Periodic mode is not "
  217. "supported for i.MX\n");
  218. break;
  219. case CLOCK_EVT_MODE_ONESHOT:
  220. /*
  221. * Do not put overhead of interrupt enable/disable into
  222. * mxc_set_next_event(), the core has about 4 minutes
  223. * to call mxc_set_next_event() or shutdown clock after
  224. * mode switching
  225. */
  226. local_irq_save(flags);
  227. imxtm->gpt->gpt_irq_enable(imxtm);
  228. local_irq_restore(flags);
  229. break;
  230. case CLOCK_EVT_MODE_SHUTDOWN:
  231. case CLOCK_EVT_MODE_UNUSED:
  232. case CLOCK_EVT_MODE_RESUME:
  233. /* Left event sources disabled, no more interrupts appear */
  234. break;
  235. }
  236. }
  237. /*
  238. * IRQ handler for the timer
  239. */
  240. static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
  241. {
  242. struct clock_event_device *ced = dev_id;
  243. struct imx_timer *imxtm = to_imx_timer(ced);
  244. uint32_t tstat;
  245. tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
  246. imxtm->gpt->gpt_irq_acknowledge(imxtm);
  247. ced->event_handler(ced);
  248. return IRQ_HANDLED;
  249. }
  250. static int __init mxc_clockevent_init(struct imx_timer *imxtm)
  251. {
  252. struct clock_event_device *ced = &imxtm->ced;
  253. struct irqaction *act = &imxtm->act;
  254. imxtm->cem = CLOCK_EVT_MODE_UNUSED;
  255. ced->name = "mxc_timer1";
  256. ced->features = CLOCK_EVT_FEAT_ONESHOT;
  257. ced->set_mode = mxc_set_mode;
  258. ced->set_next_event = imxtm->gpt->set_next_event;
  259. ced->rating = 200;
  260. ced->cpumask = cpumask_of(0);
  261. clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),
  262. 0xff, 0xfffffffe);
  263. act->name = "i.MX Timer Tick";
  264. act->flags = IRQF_TIMER | IRQF_IRQPOLL;
  265. act->handler = mxc_timer_interrupt;
  266. act->dev_id = ced;
  267. return setup_irq(imxtm->irq, act);
  268. }
  269. static void imx1_gpt_setup_tctl(struct imx_timer *imxtm)
  270. {
  271. u32 tctl_val;
  272. tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
  273. writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
  274. }
  275. #define imx21_gpt_setup_tctl imx1_gpt_setup_tctl
  276. static void imx31_gpt_setup_tctl(struct imx_timer *imxtm)
  277. {
  278. u32 tctl_val;
  279. tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
  280. if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8)
  281. tctl_val |= V2_TCTL_CLK_OSC_DIV8;
  282. else
  283. tctl_val |= V2_TCTL_CLK_PER;
  284. writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
  285. }
  286. static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm)
  287. {
  288. u32 tctl_val;
  289. tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
  290. if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) {
  291. tctl_val |= V2_TCTL_CLK_OSC_DIV8;
  292. /* 24 / 8 = 3 MHz */
  293. writel_relaxed(7 << V2_TPRER_PRE24M, imxtm->base + MXC_TPRER);
  294. tctl_val |= V2_TCTL_24MEN;
  295. } else {
  296. tctl_val |= V2_TCTL_CLK_PER;
  297. }
  298. writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
  299. }
  300. static const struct imx_gpt_data imx1_gpt_data = {
  301. .reg_tstat = MX1_2_TSTAT,
  302. .reg_tcn = MX1_2_TCN,
  303. .reg_tcmp = MX1_2_TCMP,
  304. .gpt_irq_enable = imx1_gpt_irq_enable,
  305. .gpt_irq_disable = imx1_gpt_irq_disable,
  306. .gpt_irq_acknowledge = imx1_gpt_irq_acknowledge,
  307. .gpt_setup_tctl = imx1_gpt_setup_tctl,
  308. .set_next_event = mx1_2_set_next_event,
  309. };
  310. static const struct imx_gpt_data imx21_gpt_data = {
  311. .reg_tstat = MX1_2_TSTAT,
  312. .reg_tcn = MX1_2_TCN,
  313. .reg_tcmp = MX1_2_TCMP,
  314. .gpt_irq_enable = imx21_gpt_irq_enable,
  315. .gpt_irq_disable = imx21_gpt_irq_disable,
  316. .gpt_irq_acknowledge = imx21_gpt_irq_acknowledge,
  317. .gpt_setup_tctl = imx21_gpt_setup_tctl,
  318. .set_next_event = mx1_2_set_next_event,
  319. };
  320. static const struct imx_gpt_data imx31_gpt_data = {
  321. .reg_tstat = V2_TSTAT,
  322. .reg_tcn = V2_TCN,
  323. .reg_tcmp = V2_TCMP,
  324. .gpt_irq_enable = imx31_gpt_irq_enable,
  325. .gpt_irq_disable = imx31_gpt_irq_disable,
  326. .gpt_irq_acknowledge = imx31_gpt_irq_acknowledge,
  327. .gpt_setup_tctl = imx31_gpt_setup_tctl,
  328. .set_next_event = v2_set_next_event,
  329. };
  330. static const struct imx_gpt_data imx6dl_gpt_data = {
  331. .reg_tstat = V2_TSTAT,
  332. .reg_tcn = V2_TCN,
  333. .reg_tcmp = V2_TCMP,
  334. .gpt_irq_enable = imx6dl_gpt_irq_enable,
  335. .gpt_irq_disable = imx6dl_gpt_irq_disable,
  336. .gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge,
  337. .gpt_setup_tctl = imx6dl_gpt_setup_tctl,
  338. .set_next_event = v2_set_next_event,
  339. };
  340. static void __init _mxc_timer_init(struct imx_timer *imxtm)
  341. {
  342. switch (imxtm->type) {
  343. case GPT_TYPE_IMX1:
  344. imxtm->gpt = &imx1_gpt_data;
  345. break;
  346. case GPT_TYPE_IMX21:
  347. imxtm->gpt = &imx21_gpt_data;
  348. break;
  349. case GPT_TYPE_IMX31:
  350. imxtm->gpt = &imx31_gpt_data;
  351. break;
  352. case GPT_TYPE_IMX6DL:
  353. imxtm->gpt = &imx6dl_gpt_data;
  354. break;
  355. default:
  356. BUG();
  357. }
  358. if (IS_ERR(imxtm->clk_per)) {
  359. pr_err("i.MX timer: unable to get clk\n");
  360. return;
  361. }
  362. if (!IS_ERR(imxtm->clk_ipg))
  363. clk_prepare_enable(imxtm->clk_ipg);
  364. clk_prepare_enable(imxtm->clk_per);
  365. /*
  366. * Initialise to a known state (all timers off, and timing reset)
  367. */
  368. writel_relaxed(0, imxtm->base + MXC_TCTL);
  369. writel_relaxed(0, imxtm->base + MXC_TPRER); /* see datasheet note */
  370. imxtm->gpt->gpt_setup_tctl(imxtm);
  371. /* init and register the timer to the framework */
  372. mxc_clocksource_init(imxtm);
  373. mxc_clockevent_init(imxtm);
  374. }
  375. void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
  376. {
  377. struct imx_timer *imxtm;
  378. imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
  379. BUG_ON(!imxtm);
  380. imxtm->clk_per = clk_get_sys("imx-gpt.0", "per");
  381. imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
  382. imxtm->base = ioremap(pbase, SZ_4K);
  383. BUG_ON(!imxtm->base);
  384. imxtm->type = type;
  385. _mxc_timer_init(imxtm);
  386. }
  387. static void __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type type)
  388. {
  389. struct imx_timer *imxtm;
  390. static int initialized;
  391. /* Support one instance only */
  392. if (initialized)
  393. return;
  394. imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
  395. BUG_ON(!imxtm);
  396. imxtm->base = of_iomap(np, 0);
  397. WARN_ON(!imxtm->base);
  398. imxtm->irq = irq_of_parse_and_map(np, 0);
  399. imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
  400. /* Try osc_per first, and fall back to per otherwise */
  401. imxtm->clk_per = of_clk_get_by_name(np, "osc_per");
  402. if (IS_ERR(imxtm->clk_per))
  403. imxtm->clk_per = of_clk_get_by_name(np, "per");
  404. imxtm->type = type;
  405. _mxc_timer_init(imxtm);
  406. initialized = 1;
  407. }
  408. static void __init imx1_timer_init_dt(struct device_node *np)
  409. {
  410. mxc_timer_init_dt(np, GPT_TYPE_IMX1);
  411. }
  412. static void __init imx21_timer_init_dt(struct device_node *np)
  413. {
  414. mxc_timer_init_dt(np, GPT_TYPE_IMX21);
  415. }
  416. static void __init imx31_timer_init_dt(struct device_node *np)
  417. {
  418. enum imx_gpt_type type = GPT_TYPE_IMX31;
  419. /*
  420. * We were using the same compatible string for i.MX6Q/D and i.MX6DL/S
  421. * GPT device, while they actually have different programming model.
  422. * This is a workaround to keep the existing i.MX6DL/S DTBs continue
  423. * working with the new kernel.
  424. */
  425. if (of_machine_is_compatible("fsl,imx6dl"))
  426. type = GPT_TYPE_IMX6DL;
  427. mxc_timer_init_dt(np, type);
  428. }
  429. static void __init imx6dl_timer_init_dt(struct device_node *np)
  430. {
  431. mxc_timer_init_dt(np, GPT_TYPE_IMX6DL);
  432. }
  433. CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
  434. CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
  435. CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
  436. CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
  437. CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
  438. CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
  439. CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
  440. CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
  441. CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
  442. CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
  443. CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);