dmtimer.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. /*
  2. * linux/arch/arm/plat-omap/dmtimer.c
  3. *
  4. * OMAP Dual-Mode Timers
  5. *
  6. * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
  7. * Tarun Kanti DebBarma <tarun.kanti@ti.com>
  8. * Thara Gopinath <thara@ti.com>
  9. *
  10. * dmtimer adaptation to platform_driver.
  11. *
  12. * Copyright (C) 2005 Nokia Corporation
  13. * OMAP2 support by Juha Yrjola
  14. * API improvements and OMAP2 clock framework support by Timo Teras
  15. *
  16. * Copyright (C) 2009 Texas Instruments
  17. * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  18. *
  19. * This program is free software; you can redistribute it and/or modify it
  20. * under the terms of the GNU General Public License as published by the
  21. * Free Software Foundation; either version 2 of the License, or (at your
  22. * option) any later version.
  23. *
  24. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  25. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  27. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  29. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. * You should have received a copy of the GNU General Public License along
  34. * with this program; if not, write to the Free Software Foundation, Inc.,
  35. * 675 Mass Ave, Cambridge, MA 02139, USA.
  36. */
  37. #include <linux/module.h>
  38. #include <linux/io.h>
  39. #include <linux/device.h>
  40. #include <linux/err.h>
  41. #include <linux/pm_runtime.h>
  42. #include <plat/dmtimer.h>
  43. #include <plat/omap-pm.h>
  44. #include <mach/hardware.h>
  45. static u32 omap_reserved_systimers;
  46. static LIST_HEAD(omap_timer_list);
  47. static DEFINE_SPINLOCK(dm_timer_lock);
  48. /**
  49. * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
  50. * @timer: timer pointer over which read operation to perform
  51. * @reg: lowest byte holds the register offset
  52. *
  53. * The posted mode bit is encoded in reg. Note that in posted mode write
  54. * pending bit must be checked. Otherwise a read of a non completed write
  55. * will produce an error.
  56. */
  57. static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
  58. {
  59. WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  60. return __omap_dm_timer_read(timer, reg, timer->posted);
  61. }
  62. /**
  63. * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
  64. * @timer: timer pointer over which write operation is to perform
  65. * @reg: lowest byte holds the register offset
  66. * @value: data to write into the register
  67. *
  68. * The posted mode bit is encoded in reg. Note that in posted mode the write
  69. * pending bit must be checked. Otherwise a write on a register which has a
  70. * pending write will be lost.
  71. */
  72. static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  73. u32 value)
  74. {
  75. WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  76. __omap_dm_timer_write(timer, reg, value, timer->posted);
  77. }
  78. static void omap_timer_restore_context(struct omap_dm_timer *timer)
  79. {
  80. if (timer->revision == 1)
  81. __raw_writel(timer->context.tistat, timer->sys_stat);
  82. __raw_writel(timer->context.tisr, timer->irq_stat);
  83. omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
  84. timer->context.twer);
  85. omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
  86. timer->context.tcrr);
  87. omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
  88. timer->context.tldr);
  89. omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
  90. timer->context.tmar);
  91. omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
  92. timer->context.tsicr);
  93. __raw_writel(timer->context.tier, timer->irq_ena);
  94. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
  95. timer->context.tclr);
  96. }
  97. static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
  98. {
  99. int c;
  100. if (!timer->sys_stat)
  101. return;
  102. c = 0;
  103. while (!(__raw_readl(timer->sys_stat) & 1)) {
  104. c++;
  105. if (c > 100000) {
  106. printk(KERN_ERR "Timer failed to reset\n");
  107. return;
  108. }
  109. }
  110. }
  111. static void omap_dm_timer_reset(struct omap_dm_timer *timer)
  112. {
  113. omap_dm_timer_enable(timer);
  114. if (timer->pdev->id != 1) {
  115. omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
  116. omap_dm_timer_wait_for_reset(timer);
  117. }
  118. __omap_dm_timer_reset(timer, 0, 0);
  119. omap_dm_timer_disable(timer);
  120. timer->posted = 1;
  121. }
  122. int omap_dm_timer_prepare(struct omap_dm_timer *timer)
  123. {
  124. int ret;
  125. /*
  126. * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
  127. * do not call clk_get() for these devices.
  128. */
  129. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
  130. timer->fclk = clk_get(&timer->pdev->dev, "fck");
  131. if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
  132. timer->fclk = NULL;
  133. dev_err(&timer->pdev->dev, ": No fclk handle.\n");
  134. return -EINVAL;
  135. }
  136. }
  137. if (timer->capability & OMAP_TIMER_NEEDS_RESET)
  138. omap_dm_timer_reset(timer);
  139. ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
  140. timer->posted = 1;
  141. return ret;
  142. }
  143. static inline u32 omap_dm_timer_reserved_systimer(int id)
  144. {
  145. return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
  146. }
  147. int omap_dm_timer_reserve_systimer(int id)
  148. {
  149. if (omap_dm_timer_reserved_systimer(id))
  150. return -ENODEV;
  151. omap_reserved_systimers |= (1 << (id - 1));
  152. return 0;
  153. }
  154. struct omap_dm_timer *omap_dm_timer_request(void)
  155. {
  156. struct omap_dm_timer *timer = NULL, *t;
  157. unsigned long flags;
  158. int ret = 0;
  159. spin_lock_irqsave(&dm_timer_lock, flags);
  160. list_for_each_entry(t, &omap_timer_list, node) {
  161. if (t->reserved)
  162. continue;
  163. timer = t;
  164. timer->reserved = 1;
  165. break;
  166. }
  167. if (timer) {
  168. ret = omap_dm_timer_prepare(timer);
  169. if (ret) {
  170. timer->reserved = 0;
  171. timer = NULL;
  172. }
  173. }
  174. spin_unlock_irqrestore(&dm_timer_lock, flags);
  175. if (!timer)
  176. pr_debug("%s: timer request failed!\n", __func__);
  177. return timer;
  178. }
  179. EXPORT_SYMBOL_GPL(omap_dm_timer_request);
  180. struct omap_dm_timer *omap_dm_timer_request_specific(int id)
  181. {
  182. struct omap_dm_timer *timer = NULL, *t;
  183. unsigned long flags;
  184. int ret = 0;
  185. spin_lock_irqsave(&dm_timer_lock, flags);
  186. list_for_each_entry(t, &omap_timer_list, node) {
  187. if (t->pdev->id == id && !t->reserved) {
  188. timer = t;
  189. timer->reserved = 1;
  190. break;
  191. }
  192. }
  193. if (timer) {
  194. ret = omap_dm_timer_prepare(timer);
  195. if (ret) {
  196. timer->reserved = 0;
  197. timer = NULL;
  198. }
  199. }
  200. spin_unlock_irqrestore(&dm_timer_lock, flags);
  201. if (!timer)
  202. pr_debug("%s: timer%d request failed!\n", __func__, id);
  203. return timer;
  204. }
  205. EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
  206. int omap_dm_timer_free(struct omap_dm_timer *timer)
  207. {
  208. if (unlikely(!timer))
  209. return -EINVAL;
  210. clk_put(timer->fclk);
  211. WARN_ON(!timer->reserved);
  212. timer->reserved = 0;
  213. return 0;
  214. }
  215. EXPORT_SYMBOL_GPL(omap_dm_timer_free);
  216. void omap_dm_timer_enable(struct omap_dm_timer *timer)
  217. {
  218. pm_runtime_get_sync(&timer->pdev->dev);
  219. }
  220. EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
  221. void omap_dm_timer_disable(struct omap_dm_timer *timer)
  222. {
  223. pm_runtime_put(&timer->pdev->dev);
  224. }
  225. EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
  226. int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
  227. {
  228. if (timer)
  229. return timer->irq;
  230. return -EINVAL;
  231. }
  232. EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
  233. #if defined(CONFIG_ARCH_OMAP1)
  234. /**
  235. * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
  236. * @inputmask: current value of idlect mask
  237. */
  238. __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  239. {
  240. int i = 0;
  241. struct omap_dm_timer *timer = NULL;
  242. unsigned long flags;
  243. /* If ARMXOR cannot be idled this function call is unnecessary */
  244. if (!(inputmask & (1 << 1)))
  245. return inputmask;
  246. /* If any active timer is using ARMXOR return modified mask */
  247. spin_lock_irqsave(&dm_timer_lock, flags);
  248. list_for_each_entry(timer, &omap_timer_list, node) {
  249. u32 l;
  250. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  251. if (l & OMAP_TIMER_CTRL_ST) {
  252. if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
  253. inputmask &= ~(1 << 1);
  254. else
  255. inputmask &= ~(1 << 2);
  256. }
  257. i++;
  258. }
  259. spin_unlock_irqrestore(&dm_timer_lock, flags);
  260. return inputmask;
  261. }
  262. EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
  263. #else
  264. struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
  265. {
  266. if (timer)
  267. return timer->fclk;
  268. return NULL;
  269. }
  270. EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
  271. __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  272. {
  273. BUG();
  274. return 0;
  275. }
  276. EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
  277. #endif
  278. int omap_dm_timer_trigger(struct omap_dm_timer *timer)
  279. {
  280. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  281. pr_err("%s: timer not available or enabled.\n", __func__);
  282. return -EINVAL;
  283. }
  284. omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
  285. return 0;
  286. }
  287. EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
  288. int omap_dm_timer_start(struct omap_dm_timer *timer)
  289. {
  290. u32 l;
  291. if (unlikely(!timer))
  292. return -EINVAL;
  293. omap_dm_timer_enable(timer);
  294. if (!(timer->capability & OMAP_TIMER_ALWON)) {
  295. if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
  296. timer->ctx_loss_count)
  297. omap_timer_restore_context(timer);
  298. }
  299. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  300. if (!(l & OMAP_TIMER_CTRL_ST)) {
  301. l |= OMAP_TIMER_CTRL_ST;
  302. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  303. }
  304. /* Save the context */
  305. timer->context.tclr = l;
  306. return 0;
  307. }
  308. EXPORT_SYMBOL_GPL(omap_dm_timer_start);
  309. int omap_dm_timer_stop(struct omap_dm_timer *timer)
  310. {
  311. unsigned long rate = 0;
  312. if (unlikely(!timer))
  313. return -EINVAL;
  314. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
  315. rate = clk_get_rate(timer->fclk);
  316. __omap_dm_timer_stop(timer, timer->posted, rate);
  317. if (!(timer->capability & OMAP_TIMER_ALWON))
  318. timer->ctx_loss_count =
  319. omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
  320. /*
  321. * Since the register values are computed and written within
  322. * __omap_dm_timer_stop, we need to use read to retrieve the
  323. * context.
  324. */
  325. timer->context.tclr =
  326. omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  327. timer->context.tisr = __raw_readl(timer->irq_stat);
  328. omap_dm_timer_disable(timer);
  329. return 0;
  330. }
  331. EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
  332. int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
  333. {
  334. int ret;
  335. char *parent_name = NULL;
  336. struct clk *fclk, *parent;
  337. struct dmtimer_platform_data *pdata;
  338. if (unlikely(!timer))
  339. return -EINVAL;
  340. pdata = timer->pdev->dev.platform_data;
  341. if (source < 0 || source >= 3)
  342. return -EINVAL;
  343. /*
  344. * FIXME: Used for OMAP1 devices only because they do not currently
  345. * use the clock framework to set the parent clock. To be removed
  346. * once OMAP1 migrated to using clock framework for dmtimers
  347. */
  348. if (pdata->set_timer_src)
  349. return pdata->set_timer_src(timer->pdev, source);
  350. fclk = clk_get(&timer->pdev->dev, "fck");
  351. if (IS_ERR_OR_NULL(fclk)) {
  352. pr_err("%s: fck not found\n", __func__);
  353. return -EINVAL;
  354. }
  355. switch (source) {
  356. case OMAP_TIMER_SRC_SYS_CLK:
  357. parent_name = "timer_sys_ck";
  358. break;
  359. case OMAP_TIMER_SRC_32_KHZ:
  360. parent_name = "timer_32k_ck";
  361. break;
  362. case OMAP_TIMER_SRC_EXT_CLK:
  363. parent_name = "timer_ext_ck";
  364. break;
  365. }
  366. parent = clk_get(&timer->pdev->dev, parent_name);
  367. if (IS_ERR_OR_NULL(parent)) {
  368. pr_err("%s: %s not found\n", __func__, parent_name);
  369. ret = -EINVAL;
  370. goto out;
  371. }
  372. ret = clk_set_parent(fclk, parent);
  373. if (IS_ERR_VALUE(ret))
  374. pr_err("%s: failed to set %s as parent\n", __func__,
  375. parent_name);
  376. clk_put(parent);
  377. out:
  378. clk_put(fclk);
  379. return ret;
  380. }
  381. EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
  382. int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
  383. unsigned int load)
  384. {
  385. u32 l;
  386. if (unlikely(!timer))
  387. return -EINVAL;
  388. omap_dm_timer_enable(timer);
  389. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  390. if (autoreload)
  391. l |= OMAP_TIMER_CTRL_AR;
  392. else
  393. l &= ~OMAP_TIMER_CTRL_AR;
  394. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  395. omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  396. omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
  397. /* Save the context */
  398. timer->context.tclr = l;
  399. timer->context.tldr = load;
  400. omap_dm_timer_disable(timer);
  401. return 0;
  402. }
  403. EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
  404. /* Optimized set_load which removes costly spin wait in timer_start */
  405. int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
  406. unsigned int load)
  407. {
  408. u32 l;
  409. if (unlikely(!timer))
  410. return -EINVAL;
  411. omap_dm_timer_enable(timer);
  412. if (!(timer->capability & OMAP_TIMER_ALWON)) {
  413. if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
  414. timer->ctx_loss_count)
  415. omap_timer_restore_context(timer);
  416. }
  417. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  418. if (autoreload) {
  419. l |= OMAP_TIMER_CTRL_AR;
  420. omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  421. } else {
  422. l &= ~OMAP_TIMER_CTRL_AR;
  423. }
  424. l |= OMAP_TIMER_CTRL_ST;
  425. __omap_dm_timer_load_start(timer, l, load, timer->posted);
  426. /* Save the context */
  427. timer->context.tclr = l;
  428. timer->context.tldr = load;
  429. timer->context.tcrr = load;
  430. return 0;
  431. }
  432. EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
  433. int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
  434. unsigned int match)
  435. {
  436. u32 l;
  437. if (unlikely(!timer))
  438. return -EINVAL;
  439. omap_dm_timer_enable(timer);
  440. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  441. if (enable)
  442. l |= OMAP_TIMER_CTRL_CE;
  443. else
  444. l &= ~OMAP_TIMER_CTRL_CE;
  445. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  446. omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
  447. /* Save the context */
  448. timer->context.tclr = l;
  449. timer->context.tmar = match;
  450. omap_dm_timer_disable(timer);
  451. return 0;
  452. }
  453. EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
  454. int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
  455. int toggle, int trigger)
  456. {
  457. u32 l;
  458. if (unlikely(!timer))
  459. return -EINVAL;
  460. omap_dm_timer_enable(timer);
  461. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  462. l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
  463. OMAP_TIMER_CTRL_PT | (0x03 << 10));
  464. if (def_on)
  465. l |= OMAP_TIMER_CTRL_SCPWM;
  466. if (toggle)
  467. l |= OMAP_TIMER_CTRL_PT;
  468. l |= trigger << 10;
  469. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  470. /* Save the context */
  471. timer->context.tclr = l;
  472. omap_dm_timer_disable(timer);
  473. return 0;
  474. }
  475. EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
  476. int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
  477. {
  478. u32 l;
  479. if (unlikely(!timer))
  480. return -EINVAL;
  481. omap_dm_timer_enable(timer);
  482. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  483. l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
  484. if (prescaler >= 0x00 && prescaler <= 0x07) {
  485. l |= OMAP_TIMER_CTRL_PRE;
  486. l |= prescaler << 2;
  487. }
  488. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  489. /* Save the context */
  490. timer->context.tclr = l;
  491. omap_dm_timer_disable(timer);
  492. return 0;
  493. }
  494. EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
  495. int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
  496. unsigned int value)
  497. {
  498. if (unlikely(!timer))
  499. return -EINVAL;
  500. omap_dm_timer_enable(timer);
  501. __omap_dm_timer_int_enable(timer, value);
  502. /* Save the context */
  503. timer->context.tier = value;
  504. timer->context.twer = value;
  505. omap_dm_timer_disable(timer);
  506. return 0;
  507. }
  508. EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
  509. unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
  510. {
  511. unsigned int l;
  512. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  513. pr_err("%s: timer not available or enabled.\n", __func__);
  514. return 0;
  515. }
  516. l = __raw_readl(timer->irq_stat);
  517. return l;
  518. }
  519. EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
  520. int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
  521. {
  522. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
  523. return -EINVAL;
  524. __omap_dm_timer_write_status(timer, value);
  525. /* Save the context */
  526. timer->context.tisr = value;
  527. return 0;
  528. }
  529. EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
  530. unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
  531. {
  532. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  533. pr_err("%s: timer not iavailable or enabled.\n", __func__);
  534. return 0;
  535. }
  536. return __omap_dm_timer_read_counter(timer, timer->posted);
  537. }
  538. EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
  539. int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
  540. {
  541. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  542. pr_err("%s: timer not available or enabled.\n", __func__);
  543. return -EINVAL;
  544. }
  545. omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
  546. /* Save the context */
  547. timer->context.tcrr = value;
  548. return 0;
  549. }
  550. EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
  551. int omap_dm_timers_active(void)
  552. {
  553. struct omap_dm_timer *timer;
  554. list_for_each_entry(timer, &omap_timer_list, node) {
  555. if (!timer->reserved)
  556. continue;
  557. if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
  558. OMAP_TIMER_CTRL_ST) {
  559. return 1;
  560. }
  561. }
  562. return 0;
  563. }
  564. EXPORT_SYMBOL_GPL(omap_dm_timers_active);
  565. /**
  566. * omap_dm_timer_probe - probe function called for every registered device
  567. * @pdev: pointer to current timer platform device
  568. *
  569. * Called by driver framework at the end of device registration for all
  570. * timer devices.
  571. */
  572. static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
  573. {
  574. unsigned long flags;
  575. struct omap_dm_timer *timer;
  576. struct resource *mem, *irq;
  577. struct device *dev = &pdev->dev;
  578. struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
  579. if (!pdata) {
  580. dev_err(dev, "%s: no platform data.\n", __func__);
  581. return -ENODEV;
  582. }
  583. irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  584. if (unlikely(!irq)) {
  585. dev_err(dev, "%s: no IRQ resource.\n", __func__);
  586. return -ENODEV;
  587. }
  588. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  589. if (unlikely(!mem)) {
  590. dev_err(dev, "%s: no memory resource.\n", __func__);
  591. return -ENODEV;
  592. }
  593. timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
  594. if (!timer) {
  595. dev_err(dev, "%s: memory alloc failed!\n", __func__);
  596. return -ENOMEM;
  597. }
  598. timer->io_base = devm_request_and_ioremap(dev, mem);
  599. if (!timer->io_base) {
  600. dev_err(dev, "%s: region already claimed.\n", __func__);
  601. return -ENOMEM;
  602. }
  603. timer->id = pdev->id;
  604. timer->irq = irq->start;
  605. timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
  606. timer->pdev = pdev;
  607. timer->capability = pdata->timer_capability;
  608. /* Skip pm_runtime_enable for OMAP1 */
  609. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
  610. pm_runtime_enable(dev);
  611. pm_runtime_irq_safe(dev);
  612. }
  613. if (!timer->reserved) {
  614. pm_runtime_get_sync(dev);
  615. __omap_dm_timer_init_regs(timer);
  616. pm_runtime_put(dev);
  617. }
  618. /* add the timer element to the list */
  619. spin_lock_irqsave(&dm_timer_lock, flags);
  620. list_add_tail(&timer->node, &omap_timer_list);
  621. spin_unlock_irqrestore(&dm_timer_lock, flags);
  622. dev_dbg(dev, "Device Probed.\n");
  623. return 0;
  624. }
  625. /**
  626. * omap_dm_timer_remove - cleanup a registered timer device
  627. * @pdev: pointer to current timer platform device
  628. *
  629. * Called by driver framework whenever a timer device is unregistered.
  630. * In addition to freeing platform resources it also deletes the timer
  631. * entry from the local list.
  632. */
  633. static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
  634. {
  635. struct omap_dm_timer *timer;
  636. unsigned long flags;
  637. int ret = -EINVAL;
  638. spin_lock_irqsave(&dm_timer_lock, flags);
  639. list_for_each_entry(timer, &omap_timer_list, node)
  640. if (timer->pdev->id == pdev->id) {
  641. list_del(&timer->node);
  642. ret = 0;
  643. break;
  644. }
  645. spin_unlock_irqrestore(&dm_timer_lock, flags);
  646. return ret;
  647. }
  648. static struct platform_driver omap_dm_timer_driver = {
  649. .probe = omap_dm_timer_probe,
  650. .remove = __devexit_p(omap_dm_timer_remove),
  651. .driver = {
  652. .name = "omap_timer",
  653. },
  654. };
  655. static int __init omap_dm_timer_driver_init(void)
  656. {
  657. return platform_driver_register(&omap_dm_timer_driver);
  658. }
  659. static void __exit omap_dm_timer_driver_exit(void)
  660. {
  661. platform_driver_unregister(&omap_dm_timer_driver);
  662. }
  663. early_platform_init("earlytimer", &omap_dm_timer_driver);
  664. module_init(omap_dm_timer_driver_init);
  665. module_exit(omap_dm_timer_driver_exit);
  666. MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
  667. MODULE_LICENSE("GPL");
  668. MODULE_ALIAS("platform:" DRIVER_NAME);
  669. MODULE_AUTHOR("Texas Instruments Inc");