0008-MIPS-lantiq-backport-old-timer-code.patch 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. From 94800350cb8d2f29dda2206b5e9a3772024ee168 Mon Sep 17 00:00:00 2001
  2. From: John Crispin <[email protected]>
  3. Date: Thu, 7 Aug 2014 18:30:56 +0200
  4. Subject: [PATCH 08/36] MIPS: lantiq: backport old timer code
  5. Signed-off-by: John Crispin <[email protected]>
  6. ---
  7. arch/mips/include/asm/mach-lantiq/lantiq_timer.h | 155 ++++
  8. arch/mips/lantiq/xway/Makefile | 2 +-
  9. arch/mips/lantiq/xway/timer.c | 845 ++++++++++++++++++++++
  10. 3 files changed, 1001 insertions(+), 1 deletion(-)
  11. create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_timer.h
  12. create mode 100644 arch/mips/lantiq/xway/timer.c
  13. --- /dev/null
  14. +++ b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
  15. @@ -0,0 +1,155 @@
  16. +#ifndef __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
  17. +#define __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
  18. +
  19. +
  20. +/******************************************************************************
  21. + Copyright (c) 2002, Infineon Technologies. All rights reserved.
  22. +
  23. + No Warranty
  24. + Because the program is licensed free of charge, there is no warranty for
  25. + the program, to the extent permitted by applicable law. Except when
  26. + otherwise stated in writing the copyright holders and/or other parties
  27. + provide the program "as is" without warranty of any kind, either
  28. + expressed or implied, including, but not limited to, the implied
  29. + warranties of merchantability and fitness for a particular purpose. The
  30. + entire risk as to the quality and performance of the program is with
  31. + you. should the program prove defective, you assume the cost of all
  32. + necessary servicing, repair or correction.
  33. +
  34. + In no event unless required by applicable law or agreed to in writing
  35. + will any copyright holder, or any other party who may modify and/or
  36. + redistribute the program as permitted above, be liable to you for
  37. + damages, including any general, special, incidental or consequential
  38. + damages arising out of the use or inability to use the program
  39. + (including but not limited to loss of data or data being rendered
  40. + inaccurate or losses sustained by you or third parties or a failure of
  41. + the program to operate with any other programs), even if such holder or
  42. + other party has been advised of the possibility of such damages.
  43. +******************************************************************************/
  44. +
  45. +
  46. +/*
  47. + * ####################################
  48. + * Definition
  49. + * ####################################
  50. + */
  51. +
  52. +/*
  53. + * Available Timer/Counter Index
  54. + */
  55. +#define TIMER(n, X) (n * 2 + (X ? 1 : 0))
  56. +#define TIMER_ANY 0x00
  57. +#define TIMER1A TIMER(1, 0)
  58. +#define TIMER1B TIMER(1, 1)
  59. +#define TIMER2A TIMER(2, 0)
  60. +#define TIMER2B TIMER(2, 1)
  61. +#define TIMER3A TIMER(3, 0)
  62. +#define TIMER3B TIMER(3, 1)
  63. +
  64. +/*
  65. + * Flag of Timer/Counter
  66. + * These flags specify the way in which timer is configured.
  67. + */
  68. +/* Bit size of timer/counter. */
  69. +#define TIMER_FLAG_16BIT 0x0000
  70. +#define TIMER_FLAG_32BIT 0x0001
  71. +/* Switch between timer and counter. */
  72. +#define TIMER_FLAG_TIMER 0x0000
  73. +#define TIMER_FLAG_COUNTER 0x0002
  74. +/* Stop or continue when overflowing/underflowing. */
  75. +#define TIMER_FLAG_ONCE 0x0000
  76. +#define TIMER_FLAG_CYCLIC 0x0004
  77. +/* Count up or counter down. */
  78. +#define TIMER_FLAG_UP 0x0000
  79. +#define TIMER_FLAG_DOWN 0x0008
  80. +/* Count on specific level or edge. */
  81. +#define TIMER_FLAG_HIGH_LEVEL_SENSITIVE 0x0000
  82. +#define TIMER_FLAG_LOW_LEVEL_SENSITIVE 0x0040
  83. +#define TIMER_FLAG_RISE_EDGE 0x0010
  84. +#define TIMER_FLAG_FALL_EDGE 0x0020
  85. +#define TIMER_FLAG_ANY_EDGE 0x0030
  86. +/* Signal is syncronous to module clock or not. */
  87. +#define TIMER_FLAG_UNSYNC 0x0000
  88. +#define TIMER_FLAG_SYNC 0x0080
  89. +/* Different interrupt handle type. */
  90. +#define TIMER_FLAG_NO_HANDLE 0x0000
  91. +#if defined(__KERNEL__)
  92. + #define TIMER_FLAG_CALLBACK_IN_IRQ 0x0100
  93. +#endif // defined(__KERNEL__)
  94. +#define TIMER_FLAG_SIGNAL 0x0300
  95. +/* Internal clock source or external clock source */
  96. +#define TIMER_FLAG_INT_SRC 0x0000
  97. +#define TIMER_FLAG_EXT_SRC 0x1000
  98. +
  99. +
  100. +/*
  101. + * ioctl Command
  102. + */
  103. +#define GPTU_REQUEST_TIMER 0x01 /* General method to setup timer/counter. */
  104. +#define GPTU_FREE_TIMER 0x02 /* Free timer/counter. */
  105. +#define GPTU_START_TIMER 0x03 /* Start or resume timer/counter. */
  106. +#define GPTU_STOP_TIMER 0x04 /* Suspend timer/counter. */
  107. +#define GPTU_GET_COUNT_VALUE 0x05 /* Get current count value. */
  108. +#define GPTU_CALCULATE_DIVIDER 0x06 /* Calculate timer divider from given freq.*/
  109. +#define GPTU_SET_TIMER 0x07 /* Simplified method to setup timer. */
  110. +#define GPTU_SET_COUNTER 0x08 /* Simplified method to setup counter. */
  111. +
  112. +/*
  113. + * Data Type Used to Call ioctl
  114. + */
  115. +struct gptu_ioctl_param {
  116. + unsigned int timer; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
  117. + * GPTU_SET_COUNTER, this field is ID of expected *
  118. + * timer/counter. If it's zero, a timer/counter would *
  119. + * be dynamically allocated and ID would be stored in *
  120. + * this field. *
  121. + * In command GPTU_GET_COUNT_VALUE, this field is *
  122. + * ignored. *
  123. + * In other command, this field is ID of timer/counter *
  124. + * allocated. */
  125. + unsigned int flag; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
  126. + * GPTU_SET_COUNTER, this field contains flags to *
  127. + * specify how to configure timer/counter. *
  128. + * In command GPTU_START_TIMER, zero indicate start *
  129. + * and non-zero indicate resume timer/counter. *
  130. + * In other command, this field is ignored. */
  131. + unsigned long value; /* In command GPTU_REQUEST_TIMER, this field contains *
  132. + * init/reload value. *
  133. + * In command GPTU_SET_TIMER, this field contains *
  134. + * frequency (0.001Hz) of timer. *
  135. + * In command GPTU_GET_COUNT_VALUE, current count *
  136. + * value would be stored in this field. *
  137. + * In command GPTU_CALCULATE_DIVIDER, this field *
  138. + * contains frequency wanted, and after calculation, *
  139. + * divider would be stored in this field to overwrite *
  140. + * the frequency. *
  141. + * In other command, this field is ignored. */
  142. + int pid; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
  143. + * if signal is required, this field contains process *
  144. + * ID to which signal would be sent. *
  145. + * In other command, this field is ignored. */
  146. + int sig; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
  147. + * if signal is required, this field contains signal *
  148. + * number which would be sent. *
  149. + * In other command, this field is ignored. */
  150. +};
  151. +
  152. +/*
  153. + * ####################################
  154. + * Data Type
  155. + * ####################################
  156. + */
  157. +typedef void (*timer_callback)(unsigned long arg);
  158. +
  159. +extern int lq_request_timer(unsigned int, unsigned int, unsigned long, unsigned long, unsigned long);
  160. +extern int lq_free_timer(unsigned int);
  161. +extern int lq_start_timer(unsigned int, int);
  162. +extern int lq_stop_timer(unsigned int);
  163. +extern int lq_reset_counter_flags(u32 timer, u32 flags);
  164. +extern int lq_get_count_value(unsigned int, unsigned long *);
  165. +extern u32 lq_cal_divider(unsigned long);
  166. +extern int lq_set_timer(unsigned int, unsigned int, int, int, unsigned int, unsigned long, unsigned long);
  167. +extern int lq_set_counter(unsigned int timer, unsigned int flag,
  168. + u32 reload, unsigned long arg1, unsigned long arg2);
  169. +
  170. +#endif /* __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ */
  171. --- a/arch/mips/lantiq/xway/Makefile
  172. +++ b/arch/mips/lantiq/xway/Makefile
  173. @@ -1,4 +1,10 @@
  174. # SPDX-License-Identifier: GPL-2.0-only
  175. -obj-y := prom.o sysctrl.o clk.o dma.o gptu.o dcdc.o
  176. +obj-y := prom.o sysctrl.o clk.o dma.o dcdc.o
  177. +
  178. +ifdef CONFIG_SOC_AMAZON_SE
  179. +obj-y += gptu.o
  180. +else
  181. +obj-y += timer.o
  182. +endif
  183. obj-y += vmmc.o
  184. --- /dev/null
  185. +++ b/arch/mips/lantiq/xway/timer.c
  186. @@ -0,0 +1,846 @@
  187. +#ifndef CONFIG_SOC_AMAZON_SE
  188. +
  189. +#include <linux/kernel.h>
  190. +#include <linux/module.h>
  191. +#include <linux/version.h>
  192. +#include <linux/types.h>
  193. +#include <linux/fs.h>
  194. +#include <linux/miscdevice.h>
  195. +#include <linux/init.h>
  196. +#include <linux/uaccess.h>
  197. +#include <linux/unistd.h>
  198. +#include <linux/errno.h>
  199. +#include <linux/interrupt.h>
  200. +#include <linux/sched.h>
  201. +#include <linux/sched/signal.h>
  202. +
  203. +#include <asm/irq.h>
  204. +#include <asm/div64.h>
  205. +#include "../clk.h"
  206. +
  207. +#include <lantiq_soc.h>
  208. +#include <lantiq_irq.h>
  209. +#include <lantiq_timer.h>
  210. +
  211. +#define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6
  212. +
  213. +#ifdef TIMER1A
  214. +#define FIRST_TIMER TIMER1A
  215. +#else
  216. +#define FIRST_TIMER 2
  217. +#endif
  218. +
  219. +/*
  220. + * GPTC divider is set or not.
  221. + */
  222. +#define GPTU_CLC_RMC_IS_SET 0
  223. +
  224. +/*
  225. + * Timer Interrupt (IRQ)
  226. + */
  227. +/* Must be adjusted when ICU driver is available */
  228. +#define TIMER_INTERRUPT (INT_NUM_IM3_IRL0 + 22)
  229. +
  230. +/*
  231. + * Bits Operation
  232. + */
  233. +#define GET_BITS(x, msb, lsb) \
  234. + (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
  235. +#define SET_BITS(x, msb, lsb, value) \
  236. + (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | \
  237. + (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
  238. +
  239. +/*
  240. + * GPTU Register Mapping
  241. + */
  242. +#define LQ_GPTU (KSEG1 + 0x1E100A00)
  243. +#define LQ_GPTU_CLC ((volatile u32 *)(LQ_GPTU + 0x0000))
  244. +#define LQ_GPTU_ID ((volatile u32 *)(LQ_GPTU + 0x0008))
  245. +#define LQ_GPTU_CON(n, X) ((volatile u32 *)(LQ_GPTU + 0x0010 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  246. +#define LQ_GPTU_RUN(n, X) ((volatile u32 *)(LQ_GPTU + 0x0018 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  247. +#define LQ_GPTU_RELOAD(n, X) ((volatile u32 *)(LQ_GPTU + 0x0020 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  248. +#define LQ_GPTU_COUNT(n, X) ((volatile u32 *)(LQ_GPTU + 0x0028 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  249. +#define LQ_GPTU_IRNEN ((volatile u32 *)(LQ_GPTU + 0x00F4))
  250. +#define LQ_GPTU_IRNICR ((volatile u32 *)(LQ_GPTU + 0x00F8))
  251. +#define LQ_GPTU_IRNCR ((volatile u32 *)(LQ_GPTU + 0x00FC))
  252. +
  253. +/*
  254. + * Clock Control Register
  255. + */
  256. +#define GPTU_CLC_SMC GET_BITS(*LQ_GPTU_CLC, 23, 16)
  257. +#define GPTU_CLC_RMC GET_BITS(*LQ_GPTU_CLC, 15, 8)
  258. +#define GPTU_CLC_FSOE (*LQ_GPTU_CLC & (1 << 5))
  259. +#define GPTU_CLC_EDIS (*LQ_GPTU_CLC & (1 << 3))
  260. +#define GPTU_CLC_SPEN (*LQ_GPTU_CLC & (1 << 2))
  261. +#define GPTU_CLC_DISS (*LQ_GPTU_CLC & (1 << 1))
  262. +#define GPTU_CLC_DISR (*LQ_GPTU_CLC & (1 << 0))
  263. +
  264. +#define GPTU_CLC_SMC_SET(value) SET_BITS(0, 23, 16, (value))
  265. +#define GPTU_CLC_RMC_SET(value) SET_BITS(0, 15, 8, (value))
  266. +#define GPTU_CLC_FSOE_SET(value) ((value) ? (1 << 5) : 0)
  267. +#define GPTU_CLC_SBWE_SET(value) ((value) ? (1 << 4) : 0)
  268. +#define GPTU_CLC_EDIS_SET(value) ((value) ? (1 << 3) : 0)
  269. +#define GPTU_CLC_SPEN_SET(value) ((value) ? (1 << 2) : 0)
  270. +#define GPTU_CLC_DISR_SET(value) ((value) ? (1 << 0) : 0)
  271. +
  272. +/*
  273. + * ID Register
  274. + */
  275. +#define GPTU_ID_ID GET_BITS(*LQ_GPTU_ID, 15, 8)
  276. +#define GPTU_ID_CFG GET_BITS(*LQ_GPTU_ID, 7, 5)
  277. +#define GPTU_ID_REV GET_BITS(*LQ_GPTU_ID, 4, 0)
  278. +
  279. +/*
  280. + * Control Register of Timer/Counter nX
  281. + * n is the index of block (1 based index)
  282. + * X is either A or B
  283. + */
  284. +#define GPTU_CON_SRC_EG(n, X) (*LQ_GPTU_CON(n, X) & (1 << 10))
  285. +#define GPTU_CON_SRC_EXT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 9))
  286. +#define GPTU_CON_SYNC(n, X) (*LQ_GPTU_CON(n, X) & (1 << 8))
  287. +#define GPTU_CON_EDGE(n, X) GET_BITS(*LQ_GPTU_CON(n, X), 7, 6)
  288. +#define GPTU_CON_INV(n, X) (*LQ_GPTU_CON(n, X) & (1 << 5))
  289. +#define GPTU_CON_EXT(n, X) (*LQ_GPTU_CON(n, A) & (1 << 4)) /* Timer/Counter B does not have this bit */
  290. +#define GPTU_CON_STP(n, X) (*LQ_GPTU_CON(n, X) & (1 << 3))
  291. +#define GPTU_CON_CNT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 2))
  292. +#define GPTU_CON_DIR(n, X) (*LQ_GPTU_CON(n, X) & (1 << 1))
  293. +#define GPTU_CON_EN(n, X) (*LQ_GPTU_CON(n, X) & (1 << 0))
  294. +
  295. +#define GPTU_CON_SRC_EG_SET(value) ((value) ? 0 : (1 << 10))
  296. +#define GPTU_CON_SRC_EXT_SET(value) ((value) ? (1 << 9) : 0)
  297. +#define GPTU_CON_SYNC_SET(value) ((value) ? (1 << 8) : 0)
  298. +#define GPTU_CON_EDGE_SET(value) SET_BITS(0, 7, 6, (value))
  299. +#define GPTU_CON_INV_SET(value) ((value) ? (1 << 5) : 0)
  300. +#define GPTU_CON_EXT_SET(value) ((value) ? (1 << 4) : 0)
  301. +#define GPTU_CON_STP_SET(value) ((value) ? (1 << 3) : 0)
  302. +#define GPTU_CON_CNT_SET(value) ((value) ? (1 << 2) : 0)
  303. +#define GPTU_CON_DIR_SET(value) ((value) ? (1 << 1) : 0)
  304. +
  305. +#define GPTU_RUN_RL_SET(value) ((value) ? (1 << 2) : 0)
  306. +#define GPTU_RUN_CEN_SET(value) ((value) ? (1 << 1) : 0)
  307. +#define GPTU_RUN_SEN_SET(value) ((value) ? (1 << 0) : 0)
  308. +
  309. +#define GPTU_IRNEN_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
  310. +#define GPTU_IRNCR_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
  311. +
  312. +#define TIMER_FLAG_MASK_SIZE(x) (x & 0x0001)
  313. +#define TIMER_FLAG_MASK_TYPE(x) (x & 0x0002)
  314. +#define TIMER_FLAG_MASK_STOP(x) (x & 0x0004)
  315. +#define TIMER_FLAG_MASK_DIR(x) (x & 0x0008)
  316. +#define TIMER_FLAG_NONE_EDGE 0x0000
  317. +#define TIMER_FLAG_MASK_EDGE(x) (x & 0x0030)
  318. +#define TIMER_FLAG_REAL 0x0000
  319. +#define TIMER_FLAG_INVERT 0x0040
  320. +#define TIMER_FLAG_MASK_INVERT(x) (x & 0x0040)
  321. +#define TIMER_FLAG_MASK_TRIGGER(x) (x & 0x0070)
  322. +#define TIMER_FLAG_MASK_SYNC(x) (x & 0x0080)
  323. +#define TIMER_FLAG_CALLBACK_IN_HB 0x0200
  324. +#define TIMER_FLAG_MASK_HANDLE(x) (x & 0x0300)
  325. +#define TIMER_FLAG_MASK_SRC(x) (x & 0x1000)
  326. +
  327. +struct timer_dev_timer {
  328. + unsigned int f_irq_on;
  329. + unsigned int irq;
  330. + unsigned int flag;
  331. + unsigned long arg1;
  332. + unsigned long arg2;
  333. +};
  334. +
  335. +struct timer_dev {
  336. + struct mutex gptu_mutex;
  337. + unsigned int number_of_timers;
  338. + unsigned int occupation;
  339. + unsigned int f_gptu_on;
  340. + struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2];
  341. +};
  342. +
  343. +
  344. +unsigned int ltq_get_fpi_bus_clock(int fpi) {
  345. + struct clk *clk = clk_get_fpi();
  346. + return clk_get_rate(clk);
  347. +}
  348. +
  349. +
  350. +static long gptu_ioctl(struct file *, unsigned int, unsigned long);
  351. +static int gptu_open(struct inode *, struct file *);
  352. +static int gptu_release(struct inode *, struct file *);
  353. +
  354. +static struct file_operations gptu_fops = {
  355. + .owner = THIS_MODULE,
  356. + .unlocked_ioctl = gptu_ioctl,
  357. + .open = gptu_open,
  358. + .release = gptu_release
  359. +};
  360. +
  361. +static struct miscdevice gptu_miscdev = {
  362. + .minor = MISC_DYNAMIC_MINOR,
  363. + .name = "gptu",
  364. + .fops = &gptu_fops,
  365. +};
  366. +
  367. +static struct timer_dev timer_dev;
  368. +
  369. +static irqreturn_t timer_irq_handler(int irq, void *p)
  370. +{
  371. + unsigned int timer;
  372. + unsigned int flag;
  373. + struct timer_dev_timer *dev_timer = (struct timer_dev_timer *)p;
  374. +
  375. + timer = irq - TIMER_INTERRUPT;
  376. + if (timer < timer_dev.number_of_timers
  377. + && dev_timer == &timer_dev.timer[timer]) {
  378. + /* Clear interrupt. */
  379. + ltq_w32(1 << timer, LQ_GPTU_IRNCR);
  380. +
  381. + /* Call user hanler or signal. */
  382. + flag = dev_timer->flag;
  383. + if (!(timer & 0x01)
  384. + || TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
  385. + /* 16-bit timer or timer A of 32-bit timer */
  386. + switch (TIMER_FLAG_MASK_HANDLE(flag)) {
  387. + case TIMER_FLAG_CALLBACK_IN_IRQ:
  388. + case TIMER_FLAG_CALLBACK_IN_HB:
  389. + if (dev_timer->arg1)
  390. + (*(timer_callback)dev_timer->arg1)(dev_timer->arg2);
  391. + break;
  392. + case TIMER_FLAG_SIGNAL:
  393. + send_sig((int)dev_timer->arg2, (struct task_struct *)dev_timer->arg1, 0);
  394. + break;
  395. + }
  396. + }
  397. + }
  398. + return IRQ_HANDLED;
  399. +}
  400. +
  401. +static inline void lq_enable_gptu(void)
  402. +{
  403. + struct clk *clk = clk_get_sys("1e100a00.gptu", NULL);
  404. + clk_enable(clk);
  405. +
  406. + //ltq_pmu_enable(PMU_GPT);
  407. +
  408. + /* Set divider as 1, disable write protection for SPEN, enable module. */
  409. + *LQ_GPTU_CLC =
  410. + GPTU_CLC_SMC_SET(0x00) |
  411. + GPTU_CLC_RMC_SET(0x01) |
  412. + GPTU_CLC_FSOE_SET(0) |
  413. + GPTU_CLC_SBWE_SET(1) |
  414. + GPTU_CLC_EDIS_SET(0) |
  415. + GPTU_CLC_SPEN_SET(0) |
  416. + GPTU_CLC_DISR_SET(0);
  417. +}
  418. +
  419. +static inline void lq_disable_gptu(void)
  420. +{
  421. + struct clk *clk = clk_get_sys("1e100a00.gptu", NULL);
  422. + ltq_w32(0x00, LQ_GPTU_IRNEN);
  423. + ltq_w32(0xfff, LQ_GPTU_IRNCR);
  424. +
  425. + /* Set divider as 0, enable write protection for SPEN, disable module. */
  426. + *LQ_GPTU_CLC =
  427. + GPTU_CLC_SMC_SET(0x00) |
  428. + GPTU_CLC_RMC_SET(0x00) |
  429. + GPTU_CLC_FSOE_SET(0) |
  430. + GPTU_CLC_SBWE_SET(0) |
  431. + GPTU_CLC_EDIS_SET(0) |
  432. + GPTU_CLC_SPEN_SET(0) |
  433. + GPTU_CLC_DISR_SET(1);
  434. +
  435. + clk_enable(clk);
  436. +}
  437. +
  438. +int lq_request_timer(unsigned int timer, unsigned int flag,
  439. + unsigned long value, unsigned long arg1, unsigned long arg2)
  440. +{
  441. + int ret = 0;
  442. + unsigned int con_reg, irnen_reg;
  443. + int n, X;
  444. +
  445. + if (timer >= FIRST_TIMER + timer_dev.number_of_timers)
  446. + return -EINVAL;
  447. +
  448. + printk(KERN_INFO "request_timer(%d, 0x%08X, %lu)...",
  449. + timer, flag, value);
  450. +
  451. + if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT)
  452. + value &= 0xFFFF;
  453. + else
  454. + timer &= ~0x01;
  455. +
  456. + mutex_lock(&timer_dev.gptu_mutex);
  457. +
  458. + /*
  459. + * Allocate timer.
  460. + */
  461. + if (timer < FIRST_TIMER) {
  462. + unsigned int mask;
  463. + unsigned int shift;
  464. + /* This takes care of TIMER1B which is the only choice for Voice TAPI system */
  465. + unsigned int offset = TIMER2A;
  466. +
  467. + /*
  468. + * Pick up a free timer.
  469. + */
  470. + if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
  471. + mask = 1 << offset;
  472. + shift = 1;
  473. + } else {
  474. + mask = 3 << offset;
  475. + shift = 2;
  476. + }
  477. + for (timer = offset;
  478. + timer < offset + timer_dev.number_of_timers;
  479. + timer += shift, mask <<= shift)
  480. + if (!(timer_dev.occupation & mask)) {
  481. + timer_dev.occupation |= mask;
  482. + break;
  483. + }
  484. + if (timer >= offset + timer_dev.number_of_timers) {
  485. + printk("failed![%d]\n", __LINE__);
  486. + mutex_unlock(&timer_dev.gptu_mutex);
  487. + return -EINVAL;
  488. + } else
  489. + ret = timer;
  490. + } else {
  491. + register unsigned int mask;
  492. +
  493. + /*
  494. + * Check if the requested timer is free.
  495. + */
  496. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  497. + if ((timer_dev.occupation & mask)) {
  498. + printk("failed![%d] mask %#x, timer_dev.occupation %#x\n",
  499. + __LINE__, mask, timer_dev.occupation);
  500. + mutex_unlock(&timer_dev.gptu_mutex);
  501. + return -EBUSY;
  502. + } else {
  503. + timer_dev.occupation |= mask;
  504. + ret = 0;
  505. + }
  506. + }
  507. +
  508. + /*
  509. + * Prepare control register value.
  510. + */
  511. + switch (TIMER_FLAG_MASK_EDGE(flag)) {
  512. + default:
  513. + case TIMER_FLAG_NONE_EDGE:
  514. + con_reg = GPTU_CON_EDGE_SET(0x00);
  515. + break;
  516. + case TIMER_FLAG_RISE_EDGE:
  517. + con_reg = GPTU_CON_EDGE_SET(0x01);
  518. + break;
  519. + case TIMER_FLAG_FALL_EDGE:
  520. + con_reg = GPTU_CON_EDGE_SET(0x02);
  521. + break;
  522. + case TIMER_FLAG_ANY_EDGE:
  523. + con_reg = GPTU_CON_EDGE_SET(0x03);
  524. + break;
  525. + }
  526. + if (TIMER_FLAG_MASK_TYPE(flag) == TIMER_FLAG_TIMER)
  527. + con_reg |=
  528. + TIMER_FLAG_MASK_SRC(flag) ==
  529. + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) :
  530. + GPTU_CON_SRC_EXT_SET(0);
  531. + else
  532. + con_reg |=
  533. + TIMER_FLAG_MASK_SRC(flag) ==
  534. + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) :
  535. + GPTU_CON_SRC_EG_SET(0);
  536. + con_reg |=
  537. + TIMER_FLAG_MASK_SYNC(flag) ==
  538. + TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) :
  539. + GPTU_CON_SYNC_SET(1);
  540. + con_reg |=
  541. + TIMER_FLAG_MASK_INVERT(flag) ==
  542. + TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
  543. + con_reg |=
  544. + TIMER_FLAG_MASK_SIZE(flag) ==
  545. + TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) :
  546. + GPTU_CON_EXT_SET(1);
  547. + con_reg |=
  548. + TIMER_FLAG_MASK_STOP(flag) ==
  549. + TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
  550. + con_reg |=
  551. + TIMER_FLAG_MASK_TYPE(flag) ==
  552. + TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) :
  553. + GPTU_CON_CNT_SET(1);
  554. + con_reg |=
  555. + TIMER_FLAG_MASK_DIR(flag) ==
  556. + TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
  557. +
  558. + /*
  559. + * Fill up running data.
  560. + */
  561. + timer_dev.timer[timer - FIRST_TIMER].flag = flag;
  562. + timer_dev.timer[timer - FIRST_TIMER].arg1 = arg1;
  563. + timer_dev.timer[timer - FIRST_TIMER].arg2 = arg2;
  564. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  565. + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flag;
  566. +
  567. + /*
  568. + * Enable GPTU module.
  569. + */
  570. + if (!timer_dev.f_gptu_on) {
  571. + lq_enable_gptu();
  572. + timer_dev.f_gptu_on = 1;
  573. + }
  574. +
  575. + /*
  576. + * Enable IRQ.
  577. + */
  578. + if (TIMER_FLAG_MASK_HANDLE(flag) != TIMER_FLAG_NO_HANDLE) {
  579. + if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL)
  580. + timer_dev.timer[timer - FIRST_TIMER].arg1 =
  581. + (unsigned long) find_task_by_vpid((int) arg1);
  582. +
  583. + irnen_reg = 1 << (timer - FIRST_TIMER);
  584. +
  585. + if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL
  586. + || (TIMER_FLAG_MASK_HANDLE(flag) ==
  587. + TIMER_FLAG_CALLBACK_IN_IRQ
  588. + && timer_dev.timer[timer - FIRST_TIMER].arg1)) {
  589. + enable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
  590. + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 1;
  591. + }
  592. + } else
  593. + irnen_reg = 0;
  594. +
  595. + /*
  596. + * Write config register, reload value and enable interrupt.
  597. + */
  598. + n = timer >> 1;
  599. + X = timer & 0x01;
  600. + *LQ_GPTU_CON(n, X) = con_reg;
  601. + *LQ_GPTU_RELOAD(n, X) = value;
  602. + /* printk("reload value = %d\n", (u32)value); */
  603. + *LQ_GPTU_IRNEN |= irnen_reg;
  604. +
  605. + mutex_unlock(&timer_dev.gptu_mutex);
  606. + printk("successful!\n");
  607. + return ret;
  608. +}
  609. +EXPORT_SYMBOL(lq_request_timer);
  610. +
  611. +int lq_free_timer(unsigned int timer)
  612. +{
  613. + unsigned int flag;
  614. + unsigned int mask;
  615. + int n, X;
  616. +
  617. + if (!timer_dev.f_gptu_on)
  618. + return -EINVAL;
  619. +
  620. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  621. + return -EINVAL;
  622. +
  623. + mutex_lock(&timer_dev.gptu_mutex);
  624. +
  625. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  626. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  627. + timer &= ~0x01;
  628. +
  629. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  630. + if (((timer_dev.occupation & mask) ^ mask)) {
  631. + mutex_unlock(&timer_dev.gptu_mutex);
  632. + return -EINVAL;
  633. + }
  634. +
  635. + n = timer >> 1;
  636. + X = timer & 0x01;
  637. +
  638. + if (GPTU_CON_EN(n, X))
  639. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
  640. +
  641. + *LQ_GPTU_IRNEN &= ~GPTU_IRNEN_TC_SET(n, X, 1);
  642. + *LQ_GPTU_IRNCR |= GPTU_IRNCR_TC_SET(n, X, 1);
  643. +
  644. + if (timer_dev.timer[timer - FIRST_TIMER].f_irq_on) {
  645. + disable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
  646. + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 0;
  647. + }
  648. +
  649. + timer_dev.occupation &= ~mask;
  650. + if (!timer_dev.occupation && timer_dev.f_gptu_on) {
  651. + lq_disable_gptu();
  652. + timer_dev.f_gptu_on = 0;
  653. + }
  654. +
  655. + mutex_unlock(&timer_dev.gptu_mutex);
  656. +
  657. + return 0;
  658. +}
  659. +EXPORT_SYMBOL(lq_free_timer);
  660. +
  661. +int lq_start_timer(unsigned int timer, int is_resume)
  662. +{
  663. + unsigned int flag;
  664. + unsigned int mask;
  665. + int n, X;
  666. +
  667. + if (!timer_dev.f_gptu_on)
  668. + return -EINVAL;
  669. +
  670. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  671. + return -EINVAL;
  672. +
  673. + mutex_lock(&timer_dev.gptu_mutex);
  674. +
  675. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  676. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  677. + timer &= ~0x01;
  678. +
  679. + mask = (TIMER_FLAG_MASK_SIZE(flag) ==
  680. + TIMER_FLAG_16BIT ? 1 : 3) << timer;
  681. + if (((timer_dev.occupation & mask) ^ mask)) {
  682. + mutex_unlock(&timer_dev.gptu_mutex);
  683. + return -EINVAL;
  684. + }
  685. +
  686. + n = timer >> 1;
  687. + X = timer & 0x01;
  688. +
  689. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_RL_SET(!is_resume) | GPTU_RUN_SEN_SET(1);
  690. +
  691. +
  692. + mutex_unlock(&timer_dev.gptu_mutex);
  693. +
  694. + return 0;
  695. +}
  696. +EXPORT_SYMBOL(lq_start_timer);
  697. +
  698. +int lq_stop_timer(unsigned int timer)
  699. +{
  700. + unsigned int flag;
  701. + unsigned int mask;
  702. + int n, X;
  703. +
  704. + if (!timer_dev.f_gptu_on)
  705. + return -EINVAL;
  706. +
  707. + if (timer < FIRST_TIMER
  708. + || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  709. + return -EINVAL;
  710. +
  711. + mutex_lock(&timer_dev.gptu_mutex);
  712. +
  713. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  714. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  715. + timer &= ~0x01;
  716. +
  717. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  718. + if (((timer_dev.occupation & mask) ^ mask)) {
  719. + mutex_unlock(&timer_dev.gptu_mutex);
  720. + return -EINVAL;
  721. + }
  722. +
  723. + n = timer >> 1;
  724. + X = timer & 0x01;
  725. +
  726. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
  727. +
  728. + mutex_unlock(&timer_dev.gptu_mutex);
  729. +
  730. + return 0;
  731. +}
  732. +EXPORT_SYMBOL(lq_stop_timer);
  733. +
  734. +int lq_reset_counter_flags(u32 timer, u32 flags)
  735. +{
  736. + unsigned int oflag;
  737. + unsigned int mask, con_reg;
  738. + int n, X;
  739. +
  740. + if (!timer_dev.f_gptu_on)
  741. + return -EINVAL;
  742. +
  743. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  744. + return -EINVAL;
  745. +
  746. + mutex_lock(&timer_dev.gptu_mutex);
  747. +
  748. + oflag = timer_dev.timer[timer - FIRST_TIMER].flag;
  749. + if (TIMER_FLAG_MASK_SIZE(oflag) != TIMER_FLAG_16BIT)
  750. + timer &= ~0x01;
  751. +
  752. + mask = (TIMER_FLAG_MASK_SIZE(oflag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  753. + if (((timer_dev.occupation & mask) ^ mask)) {
  754. + mutex_unlock(&timer_dev.gptu_mutex);
  755. + return -EINVAL;
  756. + }
  757. +
  758. + switch (TIMER_FLAG_MASK_EDGE(flags)) {
  759. + default:
  760. + case TIMER_FLAG_NONE_EDGE:
  761. + con_reg = GPTU_CON_EDGE_SET(0x00);
  762. + break;
  763. + case TIMER_FLAG_RISE_EDGE:
  764. + con_reg = GPTU_CON_EDGE_SET(0x01);
  765. + break;
  766. + case TIMER_FLAG_FALL_EDGE:
  767. + con_reg = GPTU_CON_EDGE_SET(0x02);
  768. + break;
  769. + case TIMER_FLAG_ANY_EDGE:
  770. + con_reg = GPTU_CON_EDGE_SET(0x03);
  771. + break;
  772. + }
  773. + if (TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER)
  774. + con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) : GPTU_CON_SRC_EXT_SET(0);
  775. + else
  776. + con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) : GPTU_CON_SRC_EG_SET(0);
  777. + con_reg |= TIMER_FLAG_MASK_SYNC(flags) == TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) : GPTU_CON_SYNC_SET(1);
  778. + con_reg |= TIMER_FLAG_MASK_INVERT(flags) == TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
  779. + con_reg |= TIMER_FLAG_MASK_SIZE(flags) == TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) : GPTU_CON_EXT_SET(1);
  780. + con_reg |= TIMER_FLAG_MASK_STOP(flags) == TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
  781. + con_reg |= TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) : GPTU_CON_CNT_SET(1);
  782. + con_reg |= TIMER_FLAG_MASK_DIR(flags) == TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
  783. +
  784. + timer_dev.timer[timer - FIRST_TIMER].flag = flags;
  785. + if (TIMER_FLAG_MASK_SIZE(flags) != TIMER_FLAG_16BIT)
  786. + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flags;
  787. +
  788. + n = timer >> 1;
  789. + X = timer & 0x01;
  790. +
  791. + *LQ_GPTU_CON(n, X) = con_reg;
  792. + smp_wmb();
  793. + mutex_unlock(&timer_dev.gptu_mutex);
  794. + return 0;
  795. +}
  796. +EXPORT_SYMBOL(lq_reset_counter_flags);
  797. +
  798. +int lq_get_count_value(unsigned int timer, unsigned long *value)
  799. +{
  800. + unsigned int flag;
  801. + unsigned int mask;
  802. + int n, X;
  803. +
  804. + if (!timer_dev.f_gptu_on)
  805. + return -EINVAL;
  806. +
  807. + if (timer < FIRST_TIMER
  808. + || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  809. + return -EINVAL;
  810. +
  811. + mutex_lock(&timer_dev.gptu_mutex);
  812. +
  813. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  814. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  815. + timer &= ~0x01;
  816. +
  817. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  818. + if (((timer_dev.occupation & mask) ^ mask)) {
  819. + mutex_unlock(&timer_dev.gptu_mutex);
  820. + return -EINVAL;
  821. + }
  822. +
  823. + n = timer >> 1;
  824. + X = timer & 0x01;
  825. +
  826. + *value = *LQ_GPTU_COUNT(n, X);
  827. +
  828. +
  829. + mutex_unlock(&timer_dev.gptu_mutex);
  830. +
  831. + return 0;
  832. +}
  833. +EXPORT_SYMBOL(lq_get_count_value);
  834. +
  835. +u32 lq_cal_divider(unsigned long freq)
  836. +{
  837. + u64 module_freq, fpi = ltq_get_fpi_bus_clock(2);
  838. + u32 clock_divider = 1;
  839. + module_freq = fpi * 1000;
  840. + do_div(module_freq, clock_divider * freq);
  841. + return module_freq;
  842. +}
  843. +EXPORT_SYMBOL(lq_cal_divider);
  844. +
  845. +int lq_set_timer(unsigned int timer, unsigned int freq, int is_cyclic,
  846. + int is_ext_src, unsigned int handle_flag, unsigned long arg1,
  847. + unsigned long arg2)
  848. +{
  849. + unsigned long divider;
  850. + unsigned int flag;
  851. +
  852. + divider = lq_cal_divider(freq);
  853. + if (divider == 0)
  854. + return -EINVAL;
  855. + flag = ((divider & ~0xFFFF) ? TIMER_FLAG_32BIT : TIMER_FLAG_16BIT)
  856. + | (is_cyclic ? TIMER_FLAG_CYCLIC : TIMER_FLAG_ONCE)
  857. + | (is_ext_src ? TIMER_FLAG_EXT_SRC : TIMER_FLAG_INT_SRC)
  858. + | TIMER_FLAG_TIMER | TIMER_FLAG_DOWN
  859. + | TIMER_FLAG_MASK_HANDLE(handle_flag);
  860. +
  861. + printk(KERN_INFO "lq_set_timer(%d, %d), divider = %lu\n",
  862. + timer, freq, divider);
  863. + return lq_request_timer(timer, flag, divider, arg1, arg2);
  864. +}
  865. +EXPORT_SYMBOL(lq_set_timer);
  866. +
  867. +int lq_set_counter(unsigned int timer, unsigned int flag, u32 reload,
  868. + unsigned long arg1, unsigned long arg2)
  869. +{
  870. + printk(KERN_INFO "lq_set_counter(%d, %#x, %d)\n", timer, flag, reload);
  871. + return lq_request_timer(timer, flag, reload, arg1, arg2);
  872. +}
  873. +EXPORT_SYMBOL(lq_set_counter);
  874. +
  875. +static long gptu_ioctl(struct file *file, unsigned int cmd,
  876. + unsigned long arg)
  877. +{
  878. + int ret;
  879. + struct gptu_ioctl_param param;
  880. +
  881. + if (!access_ok((void __user *)arg, sizeof(struct gptu_ioctl_param)))
  882. + return -EFAULT;
  883. + copy_from_user(&param, (void __user *)arg, sizeof(param));
  884. +
  885. + if ((((cmd == GPTU_REQUEST_TIMER || cmd == GPTU_SET_TIMER
  886. + || GPTU_SET_COUNTER) && param.timer < 2)
  887. + || cmd == GPTU_GET_COUNT_VALUE || cmd == GPTU_CALCULATE_DIVIDER)
  888. + && !access_ok((void __user *)arg,
  889. + sizeof(struct gptu_ioctl_param)))
  890. + return -EFAULT;
  891. +
  892. + switch (cmd) {
  893. + case GPTU_REQUEST_TIMER:
  894. + ret = lq_request_timer(param.timer, param.flag, param.value,
  895. + (unsigned long) param.pid,
  896. + (unsigned long) param.sig);
  897. + if (ret > 0) {
  898. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  899. + timer, &ret, sizeof(&ret));
  900. + ret = 0;
  901. + }
  902. + break;
  903. + case GPTU_FREE_TIMER:
  904. + ret = lq_free_timer(param.timer);
  905. + break;
  906. + case GPTU_START_TIMER:
  907. + ret = lq_start_timer(param.timer, param.flag);
  908. + break;
  909. + case GPTU_STOP_TIMER:
  910. + ret = lq_stop_timer(param.timer);
  911. + break;
  912. + case GPTU_GET_COUNT_VALUE:
  913. + ret = lq_get_count_value(param.timer, &param.value);
  914. + if (!ret)
  915. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  916. + value, &param.value,
  917. + sizeof(param.value));
  918. + break;
  919. + case GPTU_CALCULATE_DIVIDER:
  920. + param.value = lq_cal_divider(param.value);
  921. + if (param.value == 0)
  922. + ret = -EINVAL;
  923. + else {
  924. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  925. + value, &param.value,
  926. + sizeof(param.value));
  927. + ret = 0;
  928. + }
  929. + break;
  930. + case GPTU_SET_TIMER:
  931. + ret = lq_set_timer(param.timer, param.value,
  932. + TIMER_FLAG_MASK_STOP(param.flag) !=
  933. + TIMER_FLAG_ONCE ? 1 : 0,
  934. + TIMER_FLAG_MASK_SRC(param.flag) ==
  935. + TIMER_FLAG_EXT_SRC ? 1 : 0,
  936. + TIMER_FLAG_MASK_HANDLE(param.flag) ==
  937. + TIMER_FLAG_SIGNAL ? TIMER_FLAG_SIGNAL :
  938. + TIMER_FLAG_NO_HANDLE,
  939. + (unsigned long) param.pid,
  940. + (unsigned long) param.sig);
  941. + if (ret > 0) {
  942. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  943. + timer, &ret, sizeof(&ret));
  944. + ret = 0;
  945. + }
  946. + break;
  947. + case GPTU_SET_COUNTER:
  948. + lq_set_counter(param.timer, param.flag, param.value, 0, 0);
  949. + if (ret > 0) {
  950. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  951. + timer, &ret, sizeof(&ret));
  952. + ret = 0;
  953. + }
  954. + break;
  955. + default:
  956. + ret = -ENOTTY;
  957. + }
  958. +
  959. + return ret;
  960. +}
  961. +
  962. +static int gptu_open(struct inode *inode, struct file *file)
  963. +{
  964. + return 0;
  965. +}
  966. +
  967. +static int gptu_release(struct inode *inode, struct file *file)
  968. +{
  969. + return 0;
  970. +}
  971. +
  972. +int __init lq_gptu_init(void)
  973. +{
  974. + int ret;
  975. + unsigned int i;
  976. +
  977. + ltq_w32(0, LQ_GPTU_IRNEN);
  978. + ltq_w32(0xfff, LQ_GPTU_IRNCR);
  979. +
  980. + memset(&timer_dev, 0, sizeof(timer_dev));
  981. + mutex_init(&timer_dev.gptu_mutex);
  982. +
  983. + lq_enable_gptu();
  984. + timer_dev.number_of_timers = GPTU_ID_CFG * 2;
  985. + lq_disable_gptu();
  986. + if (timer_dev.number_of_timers > MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2)
  987. + timer_dev.number_of_timers = MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2;
  988. + printk(KERN_INFO "gptu: totally %d 16-bit timers/counters\n", timer_dev.number_of_timers);
  989. +
  990. + ret = misc_register(&gptu_miscdev);
  991. + if (ret) {
  992. + printk(KERN_ERR "gptu: can't misc_register, get error %d\n", -ret);
  993. + return ret;
  994. + } else {
  995. + printk(KERN_INFO "gptu: misc_register on minor %d\n", gptu_miscdev.minor);
  996. + }
  997. +
  998. + for (i = 0; i < timer_dev.number_of_timers; i++) {
  999. + ret = request_irq(TIMER_INTERRUPT + i, timer_irq_handler, IRQF_TIMER, gptu_miscdev.name, &timer_dev.timer[i]);
  1000. + if (ret) {
  1001. + for (; i >= 0; i--)
  1002. + free_irq(TIMER_INTERRUPT + i, &timer_dev.timer[i]);
  1003. + misc_deregister(&gptu_miscdev);
  1004. + printk(KERN_ERR "gptu: failed in requesting irq (%d), get error %d\n", i, -ret);
  1005. + return ret;
  1006. + } else {
  1007. + timer_dev.timer[i].irq = TIMER_INTERRUPT + i;
  1008. + disable_irq(timer_dev.timer[i].irq);
  1009. + printk(KERN_INFO "gptu: succeeded to request irq %d\n", timer_dev.timer[i].irq);
  1010. + }
  1011. + }
  1012. +
  1013. + return 0;
  1014. +}
  1015. +
  1016. +void __exit lq_gptu_exit(void)
  1017. +{
  1018. + unsigned int i;
  1019. +
  1020. + for (i = 0; i < timer_dev.number_of_timers; i++) {
  1021. + if (timer_dev.timer[i].f_irq_on)
  1022. + disable_irq(timer_dev.timer[i].irq);
  1023. + free_irq(timer_dev.timer[i].irq, &timer_dev.timer[i]);
  1024. + }
  1025. + lq_disable_gptu();
  1026. + misc_deregister(&gptu_miscdev);
  1027. +}
  1028. +
  1029. +module_init(lq_gptu_init);
  1030. +module_exit(lq_gptu_exit);
  1031. +
  1032. +#endif