dmtimer.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  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/clk.h>
  38. #include <linux/module.h>
  39. #include <linux/io.h>
  40. #include <linux/device.h>
  41. #include <linux/err.h>
  42. #include <linux/pm_runtime.h>
  43. #include <linux/of.h>
  44. #include <linux/of_device.h>
  45. #include <linux/platform_device.h>
  46. #include <linux/platform_data/dmtimer-omap.h>
  47. #include <plat/dmtimer.h>
  48. static u32 omap_reserved_systimers;
  49. static LIST_HEAD(omap_timer_list);
  50. static DEFINE_SPINLOCK(dm_timer_lock);
  51. /**
  52. * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
  53. * @timer: timer pointer over which read operation to perform
  54. * @reg: lowest byte holds the register offset
  55. *
  56. * The posted mode bit is encoded in reg. Note that in posted mode write
  57. * pending bit must be checked. Otherwise a read of a non completed write
  58. * will produce an error.
  59. */
  60. static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
  61. {
  62. WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  63. return __omap_dm_timer_read(timer, reg, timer->posted);
  64. }
  65. /**
  66. * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
  67. * @timer: timer pointer over which write operation is to perform
  68. * @reg: lowest byte holds the register offset
  69. * @value: data to write into the register
  70. *
  71. * The posted mode bit is encoded in reg. Note that in posted mode the write
  72. * pending bit must be checked. Otherwise a write on a register which has a
  73. * pending write will be lost.
  74. */
  75. static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  76. u32 value)
  77. {
  78. WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  79. __omap_dm_timer_write(timer, reg, value, timer->posted);
  80. }
  81. static void omap_timer_restore_context(struct omap_dm_timer *timer)
  82. {
  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 int omap_dm_timer_reset(struct omap_dm_timer *timer)
  98. {
  99. u32 l, timeout = 100000;
  100. if (timer->revision != 1)
  101. return -EINVAL;
  102. omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
  103. do {
  104. l = __omap_dm_timer_read(timer,
  105. OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
  106. } while (!l && timeout--);
  107. if (!timeout) {
  108. dev_err(&timer->pdev->dev, "Timer failed to reset\n");
  109. return -ETIMEDOUT;
  110. }
  111. /* Configure timer for smart-idle mode */
  112. l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
  113. l |= 0x2 << 0x3;
  114. __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
  115. timer->posted = 0;
  116. return 0;
  117. }
  118. static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
  119. {
  120. int rc;
  121. /*
  122. * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
  123. * do not call clk_get() for these devices.
  124. */
  125. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
  126. timer->fclk = clk_get(&timer->pdev->dev, "fck");
  127. if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
  128. timer->fclk = NULL;
  129. dev_err(&timer->pdev->dev, ": No fclk handle.\n");
  130. return -EINVAL;
  131. }
  132. }
  133. omap_dm_timer_enable(timer);
  134. if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
  135. rc = omap_dm_timer_reset(timer);
  136. if (rc) {
  137. omap_dm_timer_disable(timer);
  138. return rc;
  139. }
  140. }
  141. __omap_dm_timer_enable_posted(timer);
  142. omap_dm_timer_disable(timer);
  143. return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
  144. }
  145. static inline u32 omap_dm_timer_reserved_systimer(int id)
  146. {
  147. return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
  148. }
  149. int omap_dm_timer_reserve_systimer(int id)
  150. {
  151. if (omap_dm_timer_reserved_systimer(id))
  152. return -ENODEV;
  153. omap_reserved_systimers |= (1 << (id - 1));
  154. return 0;
  155. }
  156. struct omap_dm_timer *omap_dm_timer_request(void)
  157. {
  158. struct omap_dm_timer *timer = NULL, *t;
  159. unsigned long flags;
  160. int ret = 0;
  161. spin_lock_irqsave(&dm_timer_lock, flags);
  162. list_for_each_entry(t, &omap_timer_list, node) {
  163. if (t->reserved)
  164. continue;
  165. timer = t;
  166. timer->reserved = 1;
  167. break;
  168. }
  169. spin_unlock_irqrestore(&dm_timer_lock, flags);
  170. if (timer) {
  171. ret = omap_dm_timer_prepare(timer);
  172. if (ret) {
  173. timer->reserved = 0;
  174. timer = NULL;
  175. }
  176. }
  177. if (!timer)
  178. pr_debug("%s: timer request failed!\n", __func__);
  179. return timer;
  180. }
  181. EXPORT_SYMBOL_GPL(omap_dm_timer_request);
  182. struct omap_dm_timer *omap_dm_timer_request_specific(int id)
  183. {
  184. struct omap_dm_timer *timer = NULL, *t;
  185. unsigned long flags;
  186. int ret = 0;
  187. /* Requesting timer by ID is not supported when device tree is used */
  188. if (of_have_populated_dt()) {
  189. pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n",
  190. __func__);
  191. return NULL;
  192. }
  193. spin_lock_irqsave(&dm_timer_lock, flags);
  194. list_for_each_entry(t, &omap_timer_list, node) {
  195. if (t->pdev->id == id && !t->reserved) {
  196. timer = t;
  197. timer->reserved = 1;
  198. break;
  199. }
  200. }
  201. spin_unlock_irqrestore(&dm_timer_lock, flags);
  202. if (timer) {
  203. ret = omap_dm_timer_prepare(timer);
  204. if (ret) {
  205. timer->reserved = 0;
  206. timer = NULL;
  207. }
  208. }
  209. if (!timer)
  210. pr_debug("%s: timer%d request failed!\n", __func__, id);
  211. return timer;
  212. }
  213. EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
  214. /**
  215. * omap_dm_timer_request_by_cap - Request a timer by capability
  216. * @cap: Bit mask of capabilities to match
  217. *
  218. * Find a timer based upon capabilities bit mask. Callers of this function
  219. * should use the definitions found in the plat/dmtimer.h file under the
  220. * comment "timer capabilities used in hwmod database". Returns pointer to
  221. * timer handle on success and a NULL pointer on failure.
  222. */
  223. struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
  224. {
  225. struct omap_dm_timer *timer = NULL, *t;
  226. unsigned long flags;
  227. if (!cap)
  228. return NULL;
  229. spin_lock_irqsave(&dm_timer_lock, flags);
  230. list_for_each_entry(t, &omap_timer_list, node) {
  231. if ((!t->reserved) && ((t->capability & cap) == cap)) {
  232. /*
  233. * If timer is not NULL, we have already found one timer
  234. * but it was not an exact match because it had more
  235. * capabilites that what was required. Therefore,
  236. * unreserve the last timer found and see if this one
  237. * is a better match.
  238. */
  239. if (timer)
  240. timer->reserved = 0;
  241. timer = t;
  242. timer->reserved = 1;
  243. /* Exit loop early if we find an exact match */
  244. if (t->capability == cap)
  245. break;
  246. }
  247. }
  248. spin_unlock_irqrestore(&dm_timer_lock, flags);
  249. if (timer && omap_dm_timer_prepare(timer)) {
  250. timer->reserved = 0;
  251. timer = NULL;
  252. }
  253. if (!timer)
  254. pr_debug("%s: timer request failed!\n", __func__);
  255. return timer;
  256. }
  257. EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
  258. int omap_dm_timer_free(struct omap_dm_timer *timer)
  259. {
  260. if (unlikely(!timer))
  261. return -EINVAL;
  262. clk_put(timer->fclk);
  263. WARN_ON(!timer->reserved);
  264. timer->reserved = 0;
  265. return 0;
  266. }
  267. EXPORT_SYMBOL_GPL(omap_dm_timer_free);
  268. void omap_dm_timer_enable(struct omap_dm_timer *timer)
  269. {
  270. int c;
  271. pm_runtime_get_sync(&timer->pdev->dev);
  272. if (!(timer->capability & OMAP_TIMER_ALWON)) {
  273. if (timer->get_context_loss_count) {
  274. c = timer->get_context_loss_count(&timer->pdev->dev);
  275. if (c != timer->ctx_loss_count) {
  276. omap_timer_restore_context(timer);
  277. timer->ctx_loss_count = c;
  278. }
  279. }
  280. }
  281. }
  282. EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
  283. void omap_dm_timer_disable(struct omap_dm_timer *timer)
  284. {
  285. pm_runtime_put_sync(&timer->pdev->dev);
  286. }
  287. EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
  288. int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
  289. {
  290. if (timer)
  291. return timer->irq;
  292. return -EINVAL;
  293. }
  294. EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
  295. #if defined(CONFIG_ARCH_OMAP1)
  296. #include <mach/hardware.h>
  297. /**
  298. * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
  299. * @inputmask: current value of idlect mask
  300. */
  301. __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  302. {
  303. int i = 0;
  304. struct omap_dm_timer *timer = NULL;
  305. unsigned long flags;
  306. /* If ARMXOR cannot be idled this function call is unnecessary */
  307. if (!(inputmask & (1 << 1)))
  308. return inputmask;
  309. /* If any active timer is using ARMXOR return modified mask */
  310. spin_lock_irqsave(&dm_timer_lock, flags);
  311. list_for_each_entry(timer, &omap_timer_list, node) {
  312. u32 l;
  313. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  314. if (l & OMAP_TIMER_CTRL_ST) {
  315. if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
  316. inputmask &= ~(1 << 1);
  317. else
  318. inputmask &= ~(1 << 2);
  319. }
  320. i++;
  321. }
  322. spin_unlock_irqrestore(&dm_timer_lock, flags);
  323. return inputmask;
  324. }
  325. EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
  326. #else
  327. struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
  328. {
  329. if (timer)
  330. return timer->fclk;
  331. return NULL;
  332. }
  333. EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
  334. __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  335. {
  336. BUG();
  337. return 0;
  338. }
  339. EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
  340. #endif
  341. int omap_dm_timer_trigger(struct omap_dm_timer *timer)
  342. {
  343. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  344. pr_err("%s: timer not available or enabled.\n", __func__);
  345. return -EINVAL;
  346. }
  347. omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
  348. return 0;
  349. }
  350. EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
  351. int omap_dm_timer_start(struct omap_dm_timer *timer)
  352. {
  353. u32 l;
  354. if (unlikely(!timer))
  355. return -EINVAL;
  356. omap_dm_timer_enable(timer);
  357. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  358. if (!(l & OMAP_TIMER_CTRL_ST)) {
  359. l |= OMAP_TIMER_CTRL_ST;
  360. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  361. }
  362. /* Save the context */
  363. timer->context.tclr = l;
  364. return 0;
  365. }
  366. EXPORT_SYMBOL_GPL(omap_dm_timer_start);
  367. int omap_dm_timer_stop(struct omap_dm_timer *timer)
  368. {
  369. unsigned long rate = 0;
  370. if (unlikely(!timer))
  371. return -EINVAL;
  372. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
  373. rate = clk_get_rate(timer->fclk);
  374. __omap_dm_timer_stop(timer, timer->posted, rate);
  375. /*
  376. * Since the register values are computed and written within
  377. * __omap_dm_timer_stop, we need to use read to retrieve the
  378. * context.
  379. */
  380. timer->context.tclr =
  381. omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  382. omap_dm_timer_disable(timer);
  383. return 0;
  384. }
  385. EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
  386. int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
  387. {
  388. int ret;
  389. char *parent_name = NULL;
  390. struct clk *parent;
  391. struct dmtimer_platform_data *pdata;
  392. if (unlikely(!timer))
  393. return -EINVAL;
  394. pdata = timer->pdev->dev.platform_data;
  395. if (source < 0 || source >= 3)
  396. return -EINVAL;
  397. /*
  398. * FIXME: Used for OMAP1 devices only because they do not currently
  399. * use the clock framework to set the parent clock. To be removed
  400. * once OMAP1 migrated to using clock framework for dmtimers
  401. */
  402. if (pdata && pdata->set_timer_src)
  403. return pdata->set_timer_src(timer->pdev, source);
  404. if (!timer->fclk)
  405. return -EINVAL;
  406. switch (source) {
  407. case OMAP_TIMER_SRC_SYS_CLK:
  408. parent_name = "timer_sys_ck";
  409. break;
  410. case OMAP_TIMER_SRC_32_KHZ:
  411. parent_name = "timer_32k_ck";
  412. break;
  413. case OMAP_TIMER_SRC_EXT_CLK:
  414. parent_name = "timer_ext_ck";
  415. break;
  416. }
  417. parent = clk_get(&timer->pdev->dev, parent_name);
  418. if (IS_ERR_OR_NULL(parent)) {
  419. pr_err("%s: %s not found\n", __func__, parent_name);
  420. return -EINVAL;
  421. }
  422. ret = clk_set_parent(timer->fclk, parent);
  423. if (IS_ERR_VALUE(ret))
  424. pr_err("%s: failed to set %s as parent\n", __func__,
  425. parent_name);
  426. clk_put(parent);
  427. return ret;
  428. }
  429. EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
  430. int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
  431. unsigned int load)
  432. {
  433. u32 l;
  434. if (unlikely(!timer))
  435. return -EINVAL;
  436. omap_dm_timer_enable(timer);
  437. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  438. if (autoreload)
  439. l |= OMAP_TIMER_CTRL_AR;
  440. else
  441. l &= ~OMAP_TIMER_CTRL_AR;
  442. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  443. omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  444. omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
  445. /* Save the context */
  446. timer->context.tclr = l;
  447. timer->context.tldr = load;
  448. omap_dm_timer_disable(timer);
  449. return 0;
  450. }
  451. EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
  452. /* Optimized set_load which removes costly spin wait in timer_start */
  453. int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
  454. unsigned int load)
  455. {
  456. u32 l;
  457. if (unlikely(!timer))
  458. return -EINVAL;
  459. omap_dm_timer_enable(timer);
  460. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  461. if (autoreload) {
  462. l |= OMAP_TIMER_CTRL_AR;
  463. omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  464. } else {
  465. l &= ~OMAP_TIMER_CTRL_AR;
  466. }
  467. l |= OMAP_TIMER_CTRL_ST;
  468. __omap_dm_timer_load_start(timer, l, load, timer->posted);
  469. /* Save the context */
  470. timer->context.tclr = l;
  471. timer->context.tldr = load;
  472. timer->context.tcrr = load;
  473. return 0;
  474. }
  475. EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
  476. int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
  477. unsigned int match)
  478. {
  479. u32 l;
  480. if (unlikely(!timer))
  481. return -EINVAL;
  482. omap_dm_timer_enable(timer);
  483. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  484. if (enable)
  485. l |= OMAP_TIMER_CTRL_CE;
  486. else
  487. l &= ~OMAP_TIMER_CTRL_CE;
  488. omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
  489. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  490. /* Save the context */
  491. timer->context.tclr = l;
  492. timer->context.tmar = match;
  493. omap_dm_timer_disable(timer);
  494. return 0;
  495. }
  496. EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
  497. int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
  498. int toggle, int trigger)
  499. {
  500. u32 l;
  501. if (unlikely(!timer))
  502. return -EINVAL;
  503. omap_dm_timer_enable(timer);
  504. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  505. l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
  506. OMAP_TIMER_CTRL_PT | (0x03 << 10));
  507. if (def_on)
  508. l |= OMAP_TIMER_CTRL_SCPWM;
  509. if (toggle)
  510. l |= OMAP_TIMER_CTRL_PT;
  511. l |= trigger << 10;
  512. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  513. /* Save the context */
  514. timer->context.tclr = l;
  515. omap_dm_timer_disable(timer);
  516. return 0;
  517. }
  518. EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
  519. int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
  520. {
  521. u32 l;
  522. if (unlikely(!timer))
  523. return -EINVAL;
  524. omap_dm_timer_enable(timer);
  525. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  526. l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
  527. if (prescaler >= 0x00 && prescaler <= 0x07) {
  528. l |= OMAP_TIMER_CTRL_PRE;
  529. l |= prescaler << 2;
  530. }
  531. omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  532. /* Save the context */
  533. timer->context.tclr = l;
  534. omap_dm_timer_disable(timer);
  535. return 0;
  536. }
  537. EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
  538. int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
  539. unsigned int value)
  540. {
  541. if (unlikely(!timer))
  542. return -EINVAL;
  543. omap_dm_timer_enable(timer);
  544. __omap_dm_timer_int_enable(timer, value);
  545. /* Save the context */
  546. timer->context.tier = value;
  547. timer->context.twer = value;
  548. omap_dm_timer_disable(timer);
  549. return 0;
  550. }
  551. EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
  552. /**
  553. * omap_dm_timer_set_int_disable - disable timer interrupts
  554. * @timer: pointer to timer handle
  555. * @mask: bit mask of interrupts to be disabled
  556. *
  557. * Disables the specified timer interrupts for a timer.
  558. */
  559. int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
  560. {
  561. u32 l = mask;
  562. if (unlikely(!timer))
  563. return -EINVAL;
  564. omap_dm_timer_enable(timer);
  565. if (timer->revision == 1)
  566. l = __raw_readl(timer->irq_ena) & ~mask;
  567. __raw_writel(l, timer->irq_dis);
  568. l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
  569. omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
  570. /* Save the context */
  571. timer->context.tier &= ~mask;
  572. timer->context.twer &= ~mask;
  573. omap_dm_timer_disable(timer);
  574. return 0;
  575. }
  576. EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
  577. unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
  578. {
  579. unsigned int l;
  580. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  581. pr_err("%s: timer not available or enabled.\n", __func__);
  582. return 0;
  583. }
  584. l = __raw_readl(timer->irq_stat);
  585. return l;
  586. }
  587. EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
  588. int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
  589. {
  590. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
  591. return -EINVAL;
  592. __omap_dm_timer_write_status(timer, value);
  593. return 0;
  594. }
  595. EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
  596. unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
  597. {
  598. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  599. pr_err("%s: timer not iavailable or enabled.\n", __func__);
  600. return 0;
  601. }
  602. return __omap_dm_timer_read_counter(timer, timer->posted);
  603. }
  604. EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
  605. int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
  606. {
  607. if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  608. pr_err("%s: timer not available or enabled.\n", __func__);
  609. return -EINVAL;
  610. }
  611. omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
  612. /* Save the context */
  613. timer->context.tcrr = value;
  614. return 0;
  615. }
  616. EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
  617. int omap_dm_timers_active(void)
  618. {
  619. struct omap_dm_timer *timer;
  620. list_for_each_entry(timer, &omap_timer_list, node) {
  621. if (!timer->reserved)
  622. continue;
  623. if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
  624. OMAP_TIMER_CTRL_ST) {
  625. return 1;
  626. }
  627. }
  628. return 0;
  629. }
  630. EXPORT_SYMBOL_GPL(omap_dm_timers_active);
  631. /**
  632. * omap_dm_timer_probe - probe function called for every registered device
  633. * @pdev: pointer to current timer platform device
  634. *
  635. * Called by driver framework at the end of device registration for all
  636. * timer devices.
  637. */
  638. static int omap_dm_timer_probe(struct platform_device *pdev)
  639. {
  640. unsigned long flags;
  641. struct omap_dm_timer *timer;
  642. struct resource *mem, *irq;
  643. struct device *dev = &pdev->dev;
  644. struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
  645. if (!pdata && !dev->of_node) {
  646. dev_err(dev, "%s: no platform data.\n", __func__);
  647. return -ENODEV;
  648. }
  649. irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  650. if (unlikely(!irq)) {
  651. dev_err(dev, "%s: no IRQ resource.\n", __func__);
  652. return -ENODEV;
  653. }
  654. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  655. if (unlikely(!mem)) {
  656. dev_err(dev, "%s: no memory resource.\n", __func__);
  657. return -ENODEV;
  658. }
  659. timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
  660. if (!timer) {
  661. dev_err(dev, "%s: memory alloc failed!\n", __func__);
  662. return -ENOMEM;
  663. }
  664. timer->io_base = devm_ioremap_resource(dev, mem);
  665. if (IS_ERR(timer->io_base))
  666. return PTR_ERR(timer->io_base);
  667. if (dev->of_node) {
  668. if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
  669. timer->capability |= OMAP_TIMER_ALWON;
  670. if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
  671. timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
  672. if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
  673. timer->capability |= OMAP_TIMER_HAS_PWM;
  674. if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
  675. timer->capability |= OMAP_TIMER_SECURE;
  676. } else {
  677. timer->id = pdev->id;
  678. timer->errata = pdata->timer_errata;
  679. timer->capability = pdata->timer_capability;
  680. timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
  681. timer->get_context_loss_count = pdata->get_context_loss_count;
  682. }
  683. timer->irq = irq->start;
  684. timer->pdev = pdev;
  685. /* Skip pm_runtime_enable for OMAP1 */
  686. if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
  687. pm_runtime_enable(dev);
  688. pm_runtime_irq_safe(dev);
  689. }
  690. if (!timer->reserved) {
  691. pm_runtime_get_sync(dev);
  692. __omap_dm_timer_init_regs(timer);
  693. pm_runtime_put(dev);
  694. }
  695. /* add the timer element to the list */
  696. spin_lock_irqsave(&dm_timer_lock, flags);
  697. list_add_tail(&timer->node, &omap_timer_list);
  698. spin_unlock_irqrestore(&dm_timer_lock, flags);
  699. dev_dbg(dev, "Device Probed.\n");
  700. return 0;
  701. }
  702. /**
  703. * omap_dm_timer_remove - cleanup a registered timer device
  704. * @pdev: pointer to current timer platform device
  705. *
  706. * Called by driver framework whenever a timer device is unregistered.
  707. * In addition to freeing platform resources it also deletes the timer
  708. * entry from the local list.
  709. */
  710. static int omap_dm_timer_remove(struct platform_device *pdev)
  711. {
  712. struct omap_dm_timer *timer;
  713. unsigned long flags;
  714. int ret = -EINVAL;
  715. spin_lock_irqsave(&dm_timer_lock, flags);
  716. list_for_each_entry(timer, &omap_timer_list, node)
  717. if (!strcmp(dev_name(&timer->pdev->dev),
  718. dev_name(&pdev->dev))) {
  719. list_del(&timer->node);
  720. ret = 0;
  721. break;
  722. }
  723. spin_unlock_irqrestore(&dm_timer_lock, flags);
  724. return ret;
  725. }
  726. static const struct of_device_id omap_timer_match[] = {
  727. { .compatible = "ti,omap2-timer", },
  728. {},
  729. };
  730. MODULE_DEVICE_TABLE(of, omap_timer_match);
  731. static struct platform_driver omap_dm_timer_driver = {
  732. .probe = omap_dm_timer_probe,
  733. .remove = omap_dm_timer_remove,
  734. .driver = {
  735. .name = "omap_timer",
  736. .of_match_table = of_match_ptr(omap_timer_match),
  737. },
  738. };
  739. early_platform_init("earlytimer", &omap_dm_timer_driver);
  740. module_platform_driver(omap_dm_timer_driver);
  741. MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
  742. MODULE_LICENSE("GPL");
  743. MODULE_ALIAS("platform:" DRIVER_NAME);
  744. MODULE_AUTHOR("Texas Instruments Inc");