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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. From 94800350cb8d2f29dda2206b5e9a3772024ee168 Mon Sep 17 00:00:00 2001
  2. From: John Crispin <blogic@openwrt.org>
  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 <blogic@openwrt.org>
  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,4 @@
  174. -obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o
  175. +obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
  176. obj-y += vmmc.o tffs.o
  177. --- /dev/null
  178. +++ b/arch/mips/lantiq/xway/timer.c
  179. @@ -0,0 +1,845 @@
  180. +#ifndef CONFIG_SOC_AMAZON_SE
  181. +
  182. +#include <linux/kernel.h>
  183. +#include <linux/module.h>
  184. +#include <linux/version.h>
  185. +#include <linux/types.h>
  186. +#include <linux/fs.h>
  187. +#include <linux/miscdevice.h>
  188. +#include <linux/init.h>
  189. +#include <linux/uaccess.h>
  190. +#include <linux/unistd.h>
  191. +#include <linux/errno.h>
  192. +#include <linux/interrupt.h>
  193. +#include <linux/sched.h>
  194. +
  195. +#include <asm/irq.h>
  196. +#include <asm/div64.h>
  197. +#include "../clk.h"
  198. +
  199. +#include <lantiq_soc.h>
  200. +#include <lantiq_irq.h>
  201. +#include <lantiq_timer.h>
  202. +
  203. +#define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6
  204. +
  205. +#ifdef TIMER1A
  206. +#define FIRST_TIMER TIMER1A
  207. +#else
  208. +#define FIRST_TIMER 2
  209. +#endif
  210. +
  211. +/*
  212. + * GPTC divider is set or not.
  213. + */
  214. +#define GPTU_CLC_RMC_IS_SET 0
  215. +
  216. +/*
  217. + * Timer Interrupt (IRQ)
  218. + */
  219. +/* Must be adjusted when ICU driver is available */
  220. +#define TIMER_INTERRUPT (INT_NUM_IM3_IRL0 + 22)
  221. +
  222. +/*
  223. + * Bits Operation
  224. + */
  225. +#define GET_BITS(x, msb, lsb) \
  226. + (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
  227. +#define SET_BITS(x, msb, lsb, value) \
  228. + (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | \
  229. + (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
  230. +
  231. +/*
  232. + * GPTU Register Mapping
  233. + */
  234. +#define LQ_GPTU (KSEG1 + 0x1E100A00)
  235. +#define LQ_GPTU_CLC ((volatile u32 *)(LQ_GPTU + 0x0000))
  236. +#define LQ_GPTU_ID ((volatile u32 *)(LQ_GPTU + 0x0008))
  237. +#define LQ_GPTU_CON(n, X) ((volatile u32 *)(LQ_GPTU + 0x0010 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  238. +#define LQ_GPTU_RUN(n, X) ((volatile u32 *)(LQ_GPTU + 0x0018 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  239. +#define LQ_GPTU_RELOAD(n, X) ((volatile u32 *)(LQ_GPTU + 0x0020 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  240. +#define LQ_GPTU_COUNT(n, X) ((volatile u32 *)(LQ_GPTU + 0x0028 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
  241. +#define LQ_GPTU_IRNEN ((volatile u32 *)(LQ_GPTU + 0x00F4))
  242. +#define LQ_GPTU_IRNICR ((volatile u32 *)(LQ_GPTU + 0x00F8))
  243. +#define LQ_GPTU_IRNCR ((volatile u32 *)(LQ_GPTU + 0x00FC))
  244. +
  245. +/*
  246. + * Clock Control Register
  247. + */
  248. +#define GPTU_CLC_SMC GET_BITS(*LQ_GPTU_CLC, 23, 16)
  249. +#define GPTU_CLC_RMC GET_BITS(*LQ_GPTU_CLC, 15, 8)
  250. +#define GPTU_CLC_FSOE (*LQ_GPTU_CLC & (1 << 5))
  251. +#define GPTU_CLC_EDIS (*LQ_GPTU_CLC & (1 << 3))
  252. +#define GPTU_CLC_SPEN (*LQ_GPTU_CLC & (1 << 2))
  253. +#define GPTU_CLC_DISS (*LQ_GPTU_CLC & (1 << 1))
  254. +#define GPTU_CLC_DISR (*LQ_GPTU_CLC & (1 << 0))
  255. +
  256. +#define GPTU_CLC_SMC_SET(value) SET_BITS(0, 23, 16, (value))
  257. +#define GPTU_CLC_RMC_SET(value) SET_BITS(0, 15, 8, (value))
  258. +#define GPTU_CLC_FSOE_SET(value) ((value) ? (1 << 5) : 0)
  259. +#define GPTU_CLC_SBWE_SET(value) ((value) ? (1 << 4) : 0)
  260. +#define GPTU_CLC_EDIS_SET(value) ((value) ? (1 << 3) : 0)
  261. +#define GPTU_CLC_SPEN_SET(value) ((value) ? (1 << 2) : 0)
  262. +#define GPTU_CLC_DISR_SET(value) ((value) ? (1 << 0) : 0)
  263. +
  264. +/*
  265. + * ID Register
  266. + */
  267. +#define GPTU_ID_ID GET_BITS(*LQ_GPTU_ID, 15, 8)
  268. +#define GPTU_ID_CFG GET_BITS(*LQ_GPTU_ID, 7, 5)
  269. +#define GPTU_ID_REV GET_BITS(*LQ_GPTU_ID, 4, 0)
  270. +
  271. +/*
  272. + * Control Register of Timer/Counter nX
  273. + * n is the index of block (1 based index)
  274. + * X is either A or B
  275. + */
  276. +#define GPTU_CON_SRC_EG(n, X) (*LQ_GPTU_CON(n, X) & (1 << 10))
  277. +#define GPTU_CON_SRC_EXT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 9))
  278. +#define GPTU_CON_SYNC(n, X) (*LQ_GPTU_CON(n, X) & (1 << 8))
  279. +#define GPTU_CON_EDGE(n, X) GET_BITS(*LQ_GPTU_CON(n, X), 7, 6)
  280. +#define GPTU_CON_INV(n, X) (*LQ_GPTU_CON(n, X) & (1 << 5))
  281. +#define GPTU_CON_EXT(n, X) (*LQ_GPTU_CON(n, A) & (1 << 4)) /* Timer/Counter B does not have this bit */
  282. +#define GPTU_CON_STP(n, X) (*LQ_GPTU_CON(n, X) & (1 << 3))
  283. +#define GPTU_CON_CNT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 2))
  284. +#define GPTU_CON_DIR(n, X) (*LQ_GPTU_CON(n, X) & (1 << 1))
  285. +#define GPTU_CON_EN(n, X) (*LQ_GPTU_CON(n, X) & (1 << 0))
  286. +
  287. +#define GPTU_CON_SRC_EG_SET(value) ((value) ? 0 : (1 << 10))
  288. +#define GPTU_CON_SRC_EXT_SET(value) ((value) ? (1 << 9) : 0)
  289. +#define GPTU_CON_SYNC_SET(value) ((value) ? (1 << 8) : 0)
  290. +#define GPTU_CON_EDGE_SET(value) SET_BITS(0, 7, 6, (value))
  291. +#define GPTU_CON_INV_SET(value) ((value) ? (1 << 5) : 0)
  292. +#define GPTU_CON_EXT_SET(value) ((value) ? (1 << 4) : 0)
  293. +#define GPTU_CON_STP_SET(value) ((value) ? (1 << 3) : 0)
  294. +#define GPTU_CON_CNT_SET(value) ((value) ? (1 << 2) : 0)
  295. +#define GPTU_CON_DIR_SET(value) ((value) ? (1 << 1) : 0)
  296. +
  297. +#define GPTU_RUN_RL_SET(value) ((value) ? (1 << 2) : 0)
  298. +#define GPTU_RUN_CEN_SET(value) ((value) ? (1 << 1) : 0)
  299. +#define GPTU_RUN_SEN_SET(value) ((value) ? (1 << 0) : 0)
  300. +
  301. +#define GPTU_IRNEN_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
  302. +#define GPTU_IRNCR_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
  303. +
  304. +#define TIMER_FLAG_MASK_SIZE(x) (x & 0x0001)
  305. +#define TIMER_FLAG_MASK_TYPE(x) (x & 0x0002)
  306. +#define TIMER_FLAG_MASK_STOP(x) (x & 0x0004)
  307. +#define TIMER_FLAG_MASK_DIR(x) (x & 0x0008)
  308. +#define TIMER_FLAG_NONE_EDGE 0x0000
  309. +#define TIMER_FLAG_MASK_EDGE(x) (x & 0x0030)
  310. +#define TIMER_FLAG_REAL 0x0000
  311. +#define TIMER_FLAG_INVERT 0x0040
  312. +#define TIMER_FLAG_MASK_INVERT(x) (x & 0x0040)
  313. +#define TIMER_FLAG_MASK_TRIGGER(x) (x & 0x0070)
  314. +#define TIMER_FLAG_MASK_SYNC(x) (x & 0x0080)
  315. +#define TIMER_FLAG_CALLBACK_IN_HB 0x0200
  316. +#define TIMER_FLAG_MASK_HANDLE(x) (x & 0x0300)
  317. +#define TIMER_FLAG_MASK_SRC(x) (x & 0x1000)
  318. +
  319. +struct timer_dev_timer {
  320. + unsigned int f_irq_on;
  321. + unsigned int irq;
  322. + unsigned int flag;
  323. + unsigned long arg1;
  324. + unsigned long arg2;
  325. +};
  326. +
  327. +struct timer_dev {
  328. + struct mutex gptu_mutex;
  329. + unsigned int number_of_timers;
  330. + unsigned int occupation;
  331. + unsigned int f_gptu_on;
  332. + struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2];
  333. +};
  334. +
  335. +
  336. +unsigned int ltq_get_fpi_bus_clock(int fpi) {
  337. + struct clk *clk = clk_get_fpi();
  338. + return clk_get_rate(clk);
  339. +}
  340. +
  341. +
  342. +static long gptu_ioctl(struct file *, unsigned int, unsigned long);
  343. +static int gptu_open(struct inode *, struct file *);
  344. +static int gptu_release(struct inode *, struct file *);
  345. +
  346. +static struct file_operations gptu_fops = {
  347. + .owner = THIS_MODULE,
  348. + .unlocked_ioctl = gptu_ioctl,
  349. + .open = gptu_open,
  350. + .release = gptu_release
  351. +};
  352. +
  353. +static struct miscdevice gptu_miscdev = {
  354. + .minor = MISC_DYNAMIC_MINOR,
  355. + .name = "gptu",
  356. + .fops = &gptu_fops,
  357. +};
  358. +
  359. +static struct timer_dev timer_dev;
  360. +
  361. +static irqreturn_t timer_irq_handler(int irq, void *p)
  362. +{
  363. + unsigned int timer;
  364. + unsigned int flag;
  365. + struct timer_dev_timer *dev_timer = (struct timer_dev_timer *)p;
  366. +
  367. + timer = irq - TIMER_INTERRUPT;
  368. + if (timer < timer_dev.number_of_timers
  369. + && dev_timer == &timer_dev.timer[timer]) {
  370. + /* Clear interrupt. */
  371. + ltq_w32(1 << timer, LQ_GPTU_IRNCR);
  372. +
  373. + /* Call user hanler or signal. */
  374. + flag = dev_timer->flag;
  375. + if (!(timer & 0x01)
  376. + || TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
  377. + /* 16-bit timer or timer A of 32-bit timer */
  378. + switch (TIMER_FLAG_MASK_HANDLE(flag)) {
  379. + case TIMER_FLAG_CALLBACK_IN_IRQ:
  380. + case TIMER_FLAG_CALLBACK_IN_HB:
  381. + if (dev_timer->arg1)
  382. + (*(timer_callback)dev_timer->arg1)(dev_timer->arg2);
  383. + break;
  384. + case TIMER_FLAG_SIGNAL:
  385. + send_sig((int)dev_timer->arg2, (struct task_struct *)dev_timer->arg1, 0);
  386. + break;
  387. + }
  388. + }
  389. + }
  390. + return IRQ_HANDLED;
  391. +}
  392. +
  393. +static inline void lq_enable_gptu(void)
  394. +{
  395. + struct clk *clk = clk_get_sys("1e100a00.gptu", NULL);
  396. + clk_enable(clk);
  397. +
  398. + //ltq_pmu_enable(PMU_GPT);
  399. +
  400. + /* Set divider as 1, disable write protection for SPEN, enable module. */
  401. + *LQ_GPTU_CLC =
  402. + GPTU_CLC_SMC_SET(0x00) |
  403. + GPTU_CLC_RMC_SET(0x01) |
  404. + GPTU_CLC_FSOE_SET(0) |
  405. + GPTU_CLC_SBWE_SET(1) |
  406. + GPTU_CLC_EDIS_SET(0) |
  407. + GPTU_CLC_SPEN_SET(0) |
  408. + GPTU_CLC_DISR_SET(0);
  409. +}
  410. +
  411. +static inline void lq_disable_gptu(void)
  412. +{
  413. + struct clk *clk = clk_get_sys("1e100a00.gptu", NULL);
  414. + ltq_w32(0x00, LQ_GPTU_IRNEN);
  415. + ltq_w32(0xfff, LQ_GPTU_IRNCR);
  416. +
  417. + /* Set divider as 0, enable write protection for SPEN, disable module. */
  418. + *LQ_GPTU_CLC =
  419. + GPTU_CLC_SMC_SET(0x00) |
  420. + GPTU_CLC_RMC_SET(0x00) |
  421. + GPTU_CLC_FSOE_SET(0) |
  422. + GPTU_CLC_SBWE_SET(0) |
  423. + GPTU_CLC_EDIS_SET(0) |
  424. + GPTU_CLC_SPEN_SET(0) |
  425. + GPTU_CLC_DISR_SET(1);
  426. +
  427. + clk_enable(clk);
  428. +}
  429. +
  430. +int lq_request_timer(unsigned int timer, unsigned int flag,
  431. + unsigned long value, unsigned long arg1, unsigned long arg2)
  432. +{
  433. + int ret = 0;
  434. + unsigned int con_reg, irnen_reg;
  435. + int n, X;
  436. +
  437. + if (timer >= FIRST_TIMER + timer_dev.number_of_timers)
  438. + return -EINVAL;
  439. +
  440. + printk(KERN_INFO "request_timer(%d, 0x%08X, %lu)...",
  441. + timer, flag, value);
  442. +
  443. + if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT)
  444. + value &= 0xFFFF;
  445. + else
  446. + timer &= ~0x01;
  447. +
  448. + mutex_lock(&timer_dev.gptu_mutex);
  449. +
  450. + /*
  451. + * Allocate timer.
  452. + */
  453. + if (timer < FIRST_TIMER) {
  454. + unsigned int mask;
  455. + unsigned int shift;
  456. + /* This takes care of TIMER1B which is the only choice for Voice TAPI system */
  457. + unsigned int offset = TIMER2A;
  458. +
  459. + /*
  460. + * Pick up a free timer.
  461. + */
  462. + if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
  463. + mask = 1 << offset;
  464. + shift = 1;
  465. + } else {
  466. + mask = 3 << offset;
  467. + shift = 2;
  468. + }
  469. + for (timer = offset;
  470. + timer < offset + timer_dev.number_of_timers;
  471. + timer += shift, mask <<= shift)
  472. + if (!(timer_dev.occupation & mask)) {
  473. + timer_dev.occupation |= mask;
  474. + break;
  475. + }
  476. + if (timer >= offset + timer_dev.number_of_timers) {
  477. + printk("failed![%d]\n", __LINE__);
  478. + mutex_unlock(&timer_dev.gptu_mutex);
  479. + return -EINVAL;
  480. + } else
  481. + ret = timer;
  482. + } else {
  483. + register unsigned int mask;
  484. +
  485. + /*
  486. + * Check if the requested timer is free.
  487. + */
  488. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  489. + if ((timer_dev.occupation & mask)) {
  490. + printk("failed![%d] mask %#x, timer_dev.occupation %#x\n",
  491. + __LINE__, mask, timer_dev.occupation);
  492. + mutex_unlock(&timer_dev.gptu_mutex);
  493. + return -EBUSY;
  494. + } else {
  495. + timer_dev.occupation |= mask;
  496. + ret = 0;
  497. + }
  498. + }
  499. +
  500. + /*
  501. + * Prepare control register value.
  502. + */
  503. + switch (TIMER_FLAG_MASK_EDGE(flag)) {
  504. + default:
  505. + case TIMER_FLAG_NONE_EDGE:
  506. + con_reg = GPTU_CON_EDGE_SET(0x00);
  507. + break;
  508. + case TIMER_FLAG_RISE_EDGE:
  509. + con_reg = GPTU_CON_EDGE_SET(0x01);
  510. + break;
  511. + case TIMER_FLAG_FALL_EDGE:
  512. + con_reg = GPTU_CON_EDGE_SET(0x02);
  513. + break;
  514. + case TIMER_FLAG_ANY_EDGE:
  515. + con_reg = GPTU_CON_EDGE_SET(0x03);
  516. + break;
  517. + }
  518. + if (TIMER_FLAG_MASK_TYPE(flag) == TIMER_FLAG_TIMER)
  519. + con_reg |=
  520. + TIMER_FLAG_MASK_SRC(flag) ==
  521. + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) :
  522. + GPTU_CON_SRC_EXT_SET(0);
  523. + else
  524. + con_reg |=
  525. + TIMER_FLAG_MASK_SRC(flag) ==
  526. + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) :
  527. + GPTU_CON_SRC_EG_SET(0);
  528. + con_reg |=
  529. + TIMER_FLAG_MASK_SYNC(flag) ==
  530. + TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) :
  531. + GPTU_CON_SYNC_SET(1);
  532. + con_reg |=
  533. + TIMER_FLAG_MASK_INVERT(flag) ==
  534. + TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
  535. + con_reg |=
  536. + TIMER_FLAG_MASK_SIZE(flag) ==
  537. + TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) :
  538. + GPTU_CON_EXT_SET(1);
  539. + con_reg |=
  540. + TIMER_FLAG_MASK_STOP(flag) ==
  541. + TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
  542. + con_reg |=
  543. + TIMER_FLAG_MASK_TYPE(flag) ==
  544. + TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) :
  545. + GPTU_CON_CNT_SET(1);
  546. + con_reg |=
  547. + TIMER_FLAG_MASK_DIR(flag) ==
  548. + TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
  549. +
  550. + /*
  551. + * Fill up running data.
  552. + */
  553. + timer_dev.timer[timer - FIRST_TIMER].flag = flag;
  554. + timer_dev.timer[timer - FIRST_TIMER].arg1 = arg1;
  555. + timer_dev.timer[timer - FIRST_TIMER].arg2 = arg2;
  556. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  557. + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flag;
  558. +
  559. + /*
  560. + * Enable GPTU module.
  561. + */
  562. + if (!timer_dev.f_gptu_on) {
  563. + lq_enable_gptu();
  564. + timer_dev.f_gptu_on = 1;
  565. + }
  566. +
  567. + /*
  568. + * Enable IRQ.
  569. + */
  570. + if (TIMER_FLAG_MASK_HANDLE(flag) != TIMER_FLAG_NO_HANDLE) {
  571. + if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL)
  572. + timer_dev.timer[timer - FIRST_TIMER].arg1 =
  573. + (unsigned long) find_task_by_vpid((int) arg1);
  574. +
  575. + irnen_reg = 1 << (timer - FIRST_TIMER);
  576. +
  577. + if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL
  578. + || (TIMER_FLAG_MASK_HANDLE(flag) ==
  579. + TIMER_FLAG_CALLBACK_IN_IRQ
  580. + && timer_dev.timer[timer - FIRST_TIMER].arg1)) {
  581. + enable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
  582. + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 1;
  583. + }
  584. + } else
  585. + irnen_reg = 0;
  586. +
  587. + /*
  588. + * Write config register, reload value and enable interrupt.
  589. + */
  590. + n = timer >> 1;
  591. + X = timer & 0x01;
  592. + *LQ_GPTU_CON(n, X) = con_reg;
  593. + *LQ_GPTU_RELOAD(n, X) = value;
  594. + /* printk("reload value = %d\n", (u32)value); */
  595. + *LQ_GPTU_IRNEN |= irnen_reg;
  596. +
  597. + mutex_unlock(&timer_dev.gptu_mutex);
  598. + printk("successful!\n");
  599. + return ret;
  600. +}
  601. +EXPORT_SYMBOL(lq_request_timer);
  602. +
  603. +int lq_free_timer(unsigned int timer)
  604. +{
  605. + unsigned int flag;
  606. + unsigned int mask;
  607. + int n, X;
  608. +
  609. + if (!timer_dev.f_gptu_on)
  610. + return -EINVAL;
  611. +
  612. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  613. + return -EINVAL;
  614. +
  615. + mutex_lock(&timer_dev.gptu_mutex);
  616. +
  617. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  618. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  619. + timer &= ~0x01;
  620. +
  621. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  622. + if (((timer_dev.occupation & mask) ^ mask)) {
  623. + mutex_unlock(&timer_dev.gptu_mutex);
  624. + return -EINVAL;
  625. + }
  626. +
  627. + n = timer >> 1;
  628. + X = timer & 0x01;
  629. +
  630. + if (GPTU_CON_EN(n, X))
  631. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
  632. +
  633. + *LQ_GPTU_IRNEN &= ~GPTU_IRNEN_TC_SET(n, X, 1);
  634. + *LQ_GPTU_IRNCR |= GPTU_IRNCR_TC_SET(n, X, 1);
  635. +
  636. + if (timer_dev.timer[timer - FIRST_TIMER].f_irq_on) {
  637. + disable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
  638. + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 0;
  639. + }
  640. +
  641. + timer_dev.occupation &= ~mask;
  642. + if (!timer_dev.occupation && timer_dev.f_gptu_on) {
  643. + lq_disable_gptu();
  644. + timer_dev.f_gptu_on = 0;
  645. + }
  646. +
  647. + mutex_unlock(&timer_dev.gptu_mutex);
  648. +
  649. + return 0;
  650. +}
  651. +EXPORT_SYMBOL(lq_free_timer);
  652. +
  653. +int lq_start_timer(unsigned int timer, int is_resume)
  654. +{
  655. + unsigned int flag;
  656. + unsigned int mask;
  657. + int n, X;
  658. +
  659. + if (!timer_dev.f_gptu_on)
  660. + return -EINVAL;
  661. +
  662. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  663. + return -EINVAL;
  664. +
  665. + mutex_lock(&timer_dev.gptu_mutex);
  666. +
  667. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  668. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  669. + timer &= ~0x01;
  670. +
  671. + mask = (TIMER_FLAG_MASK_SIZE(flag) ==
  672. + TIMER_FLAG_16BIT ? 1 : 3) << timer;
  673. + if (((timer_dev.occupation & mask) ^ mask)) {
  674. + mutex_unlock(&timer_dev.gptu_mutex);
  675. + return -EINVAL;
  676. + }
  677. +
  678. + n = timer >> 1;
  679. + X = timer & 0x01;
  680. +
  681. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_RL_SET(!is_resume) | GPTU_RUN_SEN_SET(1);
  682. +
  683. +
  684. + mutex_unlock(&timer_dev.gptu_mutex);
  685. +
  686. + return 0;
  687. +}
  688. +EXPORT_SYMBOL(lq_start_timer);
  689. +
  690. +int lq_stop_timer(unsigned int timer)
  691. +{
  692. + unsigned int flag;
  693. + unsigned int mask;
  694. + int n, X;
  695. +
  696. + if (!timer_dev.f_gptu_on)
  697. + return -EINVAL;
  698. +
  699. + if (timer < FIRST_TIMER
  700. + || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  701. + return -EINVAL;
  702. +
  703. + mutex_lock(&timer_dev.gptu_mutex);
  704. +
  705. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  706. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  707. + timer &= ~0x01;
  708. +
  709. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  710. + if (((timer_dev.occupation & mask) ^ mask)) {
  711. + mutex_unlock(&timer_dev.gptu_mutex);
  712. + return -EINVAL;
  713. + }
  714. +
  715. + n = timer >> 1;
  716. + X = timer & 0x01;
  717. +
  718. + *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
  719. +
  720. + mutex_unlock(&timer_dev.gptu_mutex);
  721. +
  722. + return 0;
  723. +}
  724. +EXPORT_SYMBOL(lq_stop_timer);
  725. +
  726. +int lq_reset_counter_flags(u32 timer, u32 flags)
  727. +{
  728. + unsigned int oflag;
  729. + unsigned int mask, con_reg;
  730. + int n, X;
  731. +
  732. + if (!timer_dev.f_gptu_on)
  733. + return -EINVAL;
  734. +
  735. + if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  736. + return -EINVAL;
  737. +
  738. + mutex_lock(&timer_dev.gptu_mutex);
  739. +
  740. + oflag = timer_dev.timer[timer - FIRST_TIMER].flag;
  741. + if (TIMER_FLAG_MASK_SIZE(oflag) != TIMER_FLAG_16BIT)
  742. + timer &= ~0x01;
  743. +
  744. + mask = (TIMER_FLAG_MASK_SIZE(oflag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  745. + if (((timer_dev.occupation & mask) ^ mask)) {
  746. + mutex_unlock(&timer_dev.gptu_mutex);
  747. + return -EINVAL;
  748. + }
  749. +
  750. + switch (TIMER_FLAG_MASK_EDGE(flags)) {
  751. + default:
  752. + case TIMER_FLAG_NONE_EDGE:
  753. + con_reg = GPTU_CON_EDGE_SET(0x00);
  754. + break;
  755. + case TIMER_FLAG_RISE_EDGE:
  756. + con_reg = GPTU_CON_EDGE_SET(0x01);
  757. + break;
  758. + case TIMER_FLAG_FALL_EDGE:
  759. + con_reg = GPTU_CON_EDGE_SET(0x02);
  760. + break;
  761. + case TIMER_FLAG_ANY_EDGE:
  762. + con_reg = GPTU_CON_EDGE_SET(0x03);
  763. + break;
  764. + }
  765. + if (TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER)
  766. + con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) : GPTU_CON_SRC_EXT_SET(0);
  767. + else
  768. + con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) : GPTU_CON_SRC_EG_SET(0);
  769. + con_reg |= TIMER_FLAG_MASK_SYNC(flags) == TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) : GPTU_CON_SYNC_SET(1);
  770. + con_reg |= TIMER_FLAG_MASK_INVERT(flags) == TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
  771. + con_reg |= TIMER_FLAG_MASK_SIZE(flags) == TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) : GPTU_CON_EXT_SET(1);
  772. + con_reg |= TIMER_FLAG_MASK_STOP(flags) == TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
  773. + con_reg |= TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) : GPTU_CON_CNT_SET(1);
  774. + con_reg |= TIMER_FLAG_MASK_DIR(flags) == TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
  775. +
  776. + timer_dev.timer[timer - FIRST_TIMER].flag = flags;
  777. + if (TIMER_FLAG_MASK_SIZE(flags) != TIMER_FLAG_16BIT)
  778. + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flags;
  779. +
  780. + n = timer >> 1;
  781. + X = timer & 0x01;
  782. +
  783. + *LQ_GPTU_CON(n, X) = con_reg;
  784. + smp_wmb();
  785. + mutex_unlock(&timer_dev.gptu_mutex);
  786. + return 0;
  787. +}
  788. +EXPORT_SYMBOL(lq_reset_counter_flags);
  789. +
  790. +int lq_get_count_value(unsigned int timer, unsigned long *value)
  791. +{
  792. + unsigned int flag;
  793. + unsigned int mask;
  794. + int n, X;
  795. +
  796. + if (!timer_dev.f_gptu_on)
  797. + return -EINVAL;
  798. +
  799. + if (timer < FIRST_TIMER
  800. + || timer >= FIRST_TIMER + timer_dev.number_of_timers)
  801. + return -EINVAL;
  802. +
  803. + mutex_lock(&timer_dev.gptu_mutex);
  804. +
  805. + flag = timer_dev.timer[timer - FIRST_TIMER].flag;
  806. + if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
  807. + timer &= ~0x01;
  808. +
  809. + mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
  810. + if (((timer_dev.occupation & mask) ^ mask)) {
  811. + mutex_unlock(&timer_dev.gptu_mutex);
  812. + return -EINVAL;
  813. + }
  814. +
  815. + n = timer >> 1;
  816. + X = timer & 0x01;
  817. +
  818. + *value = *LQ_GPTU_COUNT(n, X);
  819. +
  820. +
  821. + mutex_unlock(&timer_dev.gptu_mutex);
  822. +
  823. + return 0;
  824. +}
  825. +EXPORT_SYMBOL(lq_get_count_value);
  826. +
  827. +u32 lq_cal_divider(unsigned long freq)
  828. +{
  829. + u64 module_freq, fpi = ltq_get_fpi_bus_clock(2);
  830. + u32 clock_divider = 1;
  831. + module_freq = fpi * 1000;
  832. + do_div(module_freq, clock_divider * freq);
  833. + return module_freq;
  834. +}
  835. +EXPORT_SYMBOL(lq_cal_divider);
  836. +
  837. +int lq_set_timer(unsigned int timer, unsigned int freq, int is_cyclic,
  838. + int is_ext_src, unsigned int handle_flag, unsigned long arg1,
  839. + unsigned long arg2)
  840. +{
  841. + unsigned long divider;
  842. + unsigned int flag;
  843. +
  844. + divider = lq_cal_divider(freq);
  845. + if (divider == 0)
  846. + return -EINVAL;
  847. + flag = ((divider & ~0xFFFF) ? TIMER_FLAG_32BIT : TIMER_FLAG_16BIT)
  848. + | (is_cyclic ? TIMER_FLAG_CYCLIC : TIMER_FLAG_ONCE)
  849. + | (is_ext_src ? TIMER_FLAG_EXT_SRC : TIMER_FLAG_INT_SRC)
  850. + | TIMER_FLAG_TIMER | TIMER_FLAG_DOWN
  851. + | TIMER_FLAG_MASK_HANDLE(handle_flag);
  852. +
  853. + printk(KERN_INFO "lq_set_timer(%d, %d), divider = %lu\n",
  854. + timer, freq, divider);
  855. + return lq_request_timer(timer, flag, divider, arg1, arg2);
  856. +}
  857. +EXPORT_SYMBOL(lq_set_timer);
  858. +
  859. +int lq_set_counter(unsigned int timer, unsigned int flag, u32 reload,
  860. + unsigned long arg1, unsigned long arg2)
  861. +{
  862. + printk(KERN_INFO "lq_set_counter(%d, %#x, %d)\n", timer, flag, reload);
  863. + return lq_request_timer(timer, flag, reload, arg1, arg2);
  864. +}
  865. +EXPORT_SYMBOL(lq_set_counter);
  866. +
  867. +static long gptu_ioctl(struct file *file, unsigned int cmd,
  868. + unsigned long arg)
  869. +{
  870. + int ret;
  871. + struct gptu_ioctl_param param;
  872. +
  873. + if (!access_ok(VERIFY_READ, arg, sizeof(struct gptu_ioctl_param)))
  874. + return -EFAULT;
  875. + copy_from_user(&param, (void *) arg, sizeof(param));
  876. +
  877. + if ((((cmd == GPTU_REQUEST_TIMER || cmd == GPTU_SET_TIMER
  878. + || GPTU_SET_COUNTER) && param.timer < 2)
  879. + || cmd == GPTU_GET_COUNT_VALUE || cmd == GPTU_CALCULATE_DIVIDER)
  880. + && !access_ok(VERIFY_WRITE, arg,
  881. + sizeof(struct gptu_ioctl_param)))
  882. + return -EFAULT;
  883. +
  884. + switch (cmd) {
  885. + case GPTU_REQUEST_TIMER:
  886. + ret = lq_request_timer(param.timer, param.flag, param.value,
  887. + (unsigned long) param.pid,
  888. + (unsigned long) param.sig);
  889. + if (ret > 0) {
  890. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  891. + timer, &ret, sizeof(&ret));
  892. + ret = 0;
  893. + }
  894. + break;
  895. + case GPTU_FREE_TIMER:
  896. + ret = lq_free_timer(param.timer);
  897. + break;
  898. + case GPTU_START_TIMER:
  899. + ret = lq_start_timer(param.timer, param.flag);
  900. + break;
  901. + case GPTU_STOP_TIMER:
  902. + ret = lq_stop_timer(param.timer);
  903. + break;
  904. + case GPTU_GET_COUNT_VALUE:
  905. + ret = lq_get_count_value(param.timer, &param.value);
  906. + if (!ret)
  907. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  908. + value, &param.value,
  909. + sizeof(param.value));
  910. + break;
  911. + case GPTU_CALCULATE_DIVIDER:
  912. + param.value = lq_cal_divider(param.value);
  913. + if (param.value == 0)
  914. + ret = -EINVAL;
  915. + else {
  916. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  917. + value, &param.value,
  918. + sizeof(param.value));
  919. + ret = 0;
  920. + }
  921. + break;
  922. + case GPTU_SET_TIMER:
  923. + ret = lq_set_timer(param.timer, param.value,
  924. + TIMER_FLAG_MASK_STOP(param.flag) !=
  925. + TIMER_FLAG_ONCE ? 1 : 0,
  926. + TIMER_FLAG_MASK_SRC(param.flag) ==
  927. + TIMER_FLAG_EXT_SRC ? 1 : 0,
  928. + TIMER_FLAG_MASK_HANDLE(param.flag) ==
  929. + TIMER_FLAG_SIGNAL ? TIMER_FLAG_SIGNAL :
  930. + TIMER_FLAG_NO_HANDLE,
  931. + (unsigned long) param.pid,
  932. + (unsigned long) param.sig);
  933. + if (ret > 0) {
  934. + copy_to_user(&((struct gptu_ioctl_param *) arg)->
  935. + timer, &ret, sizeof(&ret));
  936. + ret = 0;
  937. + }
  938. + break;
  939. + case GPTU_SET_COUNTER:
  940. + lq_set_counter(param.timer, param.flag, param.value, 0, 0);
  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. + default:
  948. + ret = -ENOTTY;
  949. + }
  950. +
  951. + return ret;
  952. +}
  953. +
  954. +static int gptu_open(struct inode *inode, struct file *file)
  955. +{
  956. + return 0;
  957. +}
  958. +
  959. +static int gptu_release(struct inode *inode, struct file *file)
  960. +{
  961. + return 0;
  962. +}
  963. +
  964. +int __init lq_gptu_init(void)
  965. +{
  966. + int ret;
  967. + unsigned int i;
  968. +
  969. + ltq_w32(0, LQ_GPTU_IRNEN);
  970. + ltq_w32(0xfff, LQ_GPTU_IRNCR);
  971. +
  972. + memset(&timer_dev, 0, sizeof(timer_dev));
  973. + mutex_init(&timer_dev.gptu_mutex);
  974. +
  975. + lq_enable_gptu();
  976. + timer_dev.number_of_timers = GPTU_ID_CFG * 2;
  977. + lq_disable_gptu();
  978. + if (timer_dev.number_of_timers > MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2)
  979. + timer_dev.number_of_timers = MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2;
  980. + printk(KERN_INFO "gptu: totally %d 16-bit timers/counters\n", timer_dev.number_of_timers);
  981. +
  982. + ret = misc_register(&gptu_miscdev);
  983. + if (ret) {
  984. + printk(KERN_ERR "gptu: can't misc_register, get error %d\n", -ret);
  985. + return ret;
  986. + } else {
  987. + printk(KERN_INFO "gptu: misc_register on minor %d\n", gptu_miscdev.minor);
  988. + }
  989. +
  990. + for (i = 0; i < timer_dev.number_of_timers; i++) {
  991. + ret = request_irq(TIMER_INTERRUPT + i, timer_irq_handler, IRQF_TIMER, gptu_miscdev.name, &timer_dev.timer[i]);
  992. + if (ret) {
  993. + for (; i >= 0; i--)
  994. + free_irq(TIMER_INTERRUPT + i, &timer_dev.timer[i]);
  995. + misc_deregister(&gptu_miscdev);
  996. + printk(KERN_ERR "gptu: failed in requesting irq (%d), get error %d\n", i, -ret);
  997. + return ret;
  998. + } else {
  999. + timer_dev.timer[i].irq = TIMER_INTERRUPT + i;
  1000. + disable_irq(timer_dev.timer[i].irq);
  1001. + printk(KERN_INFO "gptu: succeeded to request irq %d\n", timer_dev.timer[i].irq);
  1002. + }
  1003. + }
  1004. +
  1005. + return 0;
  1006. +}
  1007. +
  1008. +void __exit lq_gptu_exit(void)
  1009. +{
  1010. + unsigned int i;
  1011. +
  1012. + for (i = 0; i < timer_dev.number_of_timers; i++) {
  1013. + if (timer_dev.timer[i].f_irq_on)
  1014. + disable_irq(timer_dev.timer[i].irq);
  1015. + free_irq(timer_dev.timer[i].irq, &timer_dev.timer[i]);
  1016. + }
  1017. + lq_disable_gptu();
  1018. + misc_deregister(&gptu_miscdev);
  1019. +}
  1020. +
  1021. +module_init(lq_gptu_init);
  1022. +module_exit(lq_gptu_exit);
  1023. +
  1024. +#endif