tlclk.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /*
  2. * Telecom Clock driver for Intel NetStructure(tm) MPCBL0010
  3. *
  4. * Copyright (C) 2005 Kontron Canada
  5. *
  6. * All rights reserved.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or (at
  11. * your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  16. * NON INFRINGEMENT. See the GNU General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. *
  23. * Send feedback to <sebastien.bouchard@ca.kontron.com> and the current
  24. * Maintainer <mark.gross@intel.com>
  25. *
  26. * Description : This is the TELECOM CLOCK module driver for the ATCA
  27. * MPCBL0010 ATCA computer.
  28. */
  29. #include <linux/module.h>
  30. #include <linux/init.h>
  31. #include <linux/kernel.h> /* printk() */
  32. #include <linux/fs.h> /* everything... */
  33. #include <linux/errno.h> /* error codes */
  34. #include <linux/slab.h>
  35. #include <linux/ioport.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/spinlock.h>
  38. #include <linux/timer.h>
  39. #include <linux/sysfs.h>
  40. #include <linux/device.h>
  41. #include <linux/miscdevice.h>
  42. #include <linux/platform_device.h>
  43. #include <asm/io.h> /* inb/outb */
  44. #include <asm/uaccess.h>
  45. MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
  46. MODULE_LICENSE("GPL");
  47. /*Hardware Reset of the PLL */
  48. #define RESET_ON 0x00
  49. #define RESET_OFF 0x01
  50. /* MODE SELECT */
  51. #define NORMAL_MODE 0x00
  52. #define HOLDOVER_MODE 0x10
  53. #define FREERUN_MODE 0x20
  54. /* FILTER SELECT */
  55. #define FILTER_6HZ 0x04
  56. #define FILTER_12HZ 0x00
  57. /* SELECT REFERENCE FREQUENCY */
  58. #define REF_CLK1_8kHz 0x00
  59. #define REF_CLK2_19_44MHz 0x02
  60. /* Select primary or secondary redundant clock */
  61. #define PRIMARY_CLOCK 0x00
  62. #define SECONDARY_CLOCK 0x01
  63. /* CLOCK TRANSMISSION DEFINE */
  64. #define CLK_8kHz 0xff
  65. #define CLK_16_384MHz 0xfb
  66. #define CLK_1_544MHz 0x00
  67. #define CLK_2_048MHz 0x01
  68. #define CLK_4_096MHz 0x02
  69. #define CLK_6_312MHz 0x03
  70. #define CLK_8_192MHz 0x04
  71. #define CLK_19_440MHz 0x06
  72. #define CLK_8_592MHz 0x08
  73. #define CLK_11_184MHz 0x09
  74. #define CLK_34_368MHz 0x0b
  75. #define CLK_44_736MHz 0x0a
  76. /* RECEIVED REFERENCE */
  77. #define AMC_B1 0
  78. #define AMC_B2 1
  79. /* HARDWARE SWITCHING DEFINE */
  80. #define HW_ENABLE 0x80
  81. #define HW_DISABLE 0x00
  82. /* HARDWARE SWITCHING MODE DEFINE */
  83. #define PLL_HOLDOVER 0x40
  84. #define LOST_CLOCK 0x00
  85. /* ALARMS DEFINE */
  86. #define UNLOCK_MASK 0x10
  87. #define HOLDOVER_MASK 0x20
  88. #define SEC_LOST_MASK 0x40
  89. #define PRI_LOST_MASK 0x80
  90. /* INTERRUPT CAUSE DEFINE */
  91. #define PRI_LOS_01_MASK 0x01
  92. #define PRI_LOS_10_MASK 0x02
  93. #define SEC_LOS_01_MASK 0x04
  94. #define SEC_LOS_10_MASK 0x08
  95. #define HOLDOVER_01_MASK 0x10
  96. #define HOLDOVER_10_MASK 0x20
  97. #define UNLOCK_01_MASK 0x40
  98. #define UNLOCK_10_MASK 0x80
  99. struct tlclk_alarms {
  100. __u32 lost_clocks;
  101. __u32 lost_primary_clock;
  102. __u32 lost_secondary_clock;
  103. __u32 primary_clock_back;
  104. __u32 secondary_clock_back;
  105. __u32 switchover_primary;
  106. __u32 switchover_secondary;
  107. __u32 pll_holdover;
  108. __u32 pll_end_holdover;
  109. __u32 pll_lost_sync;
  110. __u32 pll_sync;
  111. };
  112. /* Telecom clock I/O register definition */
  113. #define TLCLK_BASE 0xa08
  114. #define TLCLK_REG0 TLCLK_BASE
  115. #define TLCLK_REG1 (TLCLK_BASE+1)
  116. #define TLCLK_REG2 (TLCLK_BASE+2)
  117. #define TLCLK_REG3 (TLCLK_BASE+3)
  118. #define TLCLK_REG4 (TLCLK_BASE+4)
  119. #define TLCLK_REG5 (TLCLK_BASE+5)
  120. #define TLCLK_REG6 (TLCLK_BASE+6)
  121. #define TLCLK_REG7 (TLCLK_BASE+7)
  122. #define SET_PORT_BITS(port, mask, val) outb(((inb(port) & mask) | val), port)
  123. /* 0 = Dynamic allocation of the major device number */
  124. #define TLCLK_MAJOR 0
  125. /* sysfs interface definition:
  126. Upon loading the driver will create a sysfs directory under
  127. /sys/devices/platform/telco_clock.
  128. This directory exports the following interfaces. There operation is
  129. documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
  130. alarms :
  131. current_ref :
  132. received_ref_clk3a :
  133. received_ref_clk3b :
  134. enable_clk3a_output :
  135. enable_clk3b_output :
  136. enable_clka0_output :
  137. enable_clka1_output :
  138. enable_clkb0_output :
  139. enable_clkb1_output :
  140. filter_select :
  141. hardware_switching :
  142. hardware_switching_mode :
  143. telclock_version :
  144. mode_select :
  145. refalign :
  146. reset :
  147. select_amcb1_transmit_clock :
  148. select_amcb2_transmit_clock :
  149. select_redundant_clock :
  150. select_ref_frequency :
  151. All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
  152. has the same effect as echo 0x99 > refalign.
  153. */
  154. static unsigned int telclk_interrupt;
  155. static int int_events; /* Event that generate a interrupt */
  156. static int got_event; /* if events processing have been done */
  157. static void switchover_timeout(unsigned long data);
  158. static struct timer_list switchover_timer =
  159. TIMER_INITIALIZER(switchover_timeout , 0, 0);
  160. static unsigned long tlclk_timer_data;
  161. static struct tlclk_alarms *alarm_events;
  162. static DEFINE_SPINLOCK(event_lock);
  163. static int tlclk_major = TLCLK_MAJOR;
  164. static irqreturn_t tlclk_interrupt(int irq, void *dev_id);
  165. static DECLARE_WAIT_QUEUE_HEAD(wq);
  166. static unsigned long useflags;
  167. static DEFINE_MUTEX(tlclk_mutex);
  168. static int tlclk_open(struct inode *inode, struct file *filp)
  169. {
  170. int result;
  171. if (test_and_set_bit(0, &useflags))
  172. return -EBUSY;
  173. /* this legacy device is always one per system and it doesn't
  174. * know how to handle multiple concurrent clients.
  175. */
  176. /* Make sure there is no interrupt pending while
  177. * initialising interrupt handler */
  178. inb(TLCLK_REG6);
  179. /* This device is wired through the FPGA IO space of the ATCA blade
  180. * we can't share this IRQ */
  181. result = request_irq(telclk_interrupt, &tlclk_interrupt,
  182. IRQF_DISABLED, "telco_clock", tlclk_interrupt);
  183. if (result == -EBUSY) {
  184. printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
  185. return -EBUSY;
  186. }
  187. inb(TLCLK_REG6); /* Clear interrupt events */
  188. return 0;
  189. }
  190. static int tlclk_release(struct inode *inode, struct file *filp)
  191. {
  192. free_irq(telclk_interrupt, tlclk_interrupt);
  193. clear_bit(0, &useflags);
  194. return 0;
  195. }
  196. static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
  197. loff_t *f_pos)
  198. {
  199. if (count < sizeof(struct tlclk_alarms))
  200. return -EIO;
  201. if (mutex_lock_interruptible(&tlclk_mutex))
  202. return -EINTR;
  203. wait_event_interruptible(wq, got_event);
  204. if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) {
  205. mutex_unlock(&tlclk_mutex);
  206. return -EFAULT;
  207. }
  208. memset(alarm_events, 0, sizeof(struct tlclk_alarms));
  209. got_event = 0;
  210. mutex_unlock(&tlclk_mutex);
  211. return sizeof(struct tlclk_alarms);
  212. }
  213. static const struct file_operations tlclk_fops = {
  214. .read = tlclk_read,
  215. .open = tlclk_open,
  216. .release = tlclk_release,
  217. };
  218. static struct miscdevice tlclk_miscdev = {
  219. .minor = MISC_DYNAMIC_MINOR,
  220. .name = "telco_clock",
  221. .fops = &tlclk_fops,
  222. };
  223. static ssize_t show_current_ref(struct device *d,
  224. struct device_attribute *attr, char *buf)
  225. {
  226. unsigned long ret_val;
  227. unsigned long flags;
  228. spin_lock_irqsave(&event_lock, flags);
  229. ret_val = ((inb(TLCLK_REG1) & 0x08) >> 3);
  230. spin_unlock_irqrestore(&event_lock, flags);
  231. return sprintf(buf, "0x%lX\n", ret_val);
  232. }
  233. static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
  234. static ssize_t show_telclock_version(struct device *d,
  235. struct device_attribute *attr, char *buf)
  236. {
  237. unsigned long ret_val;
  238. unsigned long flags;
  239. spin_lock_irqsave(&event_lock, flags);
  240. ret_val = inb(TLCLK_REG5);
  241. spin_unlock_irqrestore(&event_lock, flags);
  242. return sprintf(buf, "0x%lX\n", ret_val);
  243. }
  244. static DEVICE_ATTR(telclock_version, S_IRUGO,
  245. show_telclock_version, NULL);
  246. static ssize_t show_alarms(struct device *d,
  247. struct device_attribute *attr, char *buf)
  248. {
  249. unsigned long ret_val;
  250. unsigned long flags;
  251. spin_lock_irqsave(&event_lock, flags);
  252. ret_val = (inb(TLCLK_REG2) & 0xf0);
  253. spin_unlock_irqrestore(&event_lock, flags);
  254. return sprintf(buf, "0x%lX\n", ret_val);
  255. }
  256. static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
  257. static ssize_t store_received_ref_clk3a(struct device *d,
  258. struct device_attribute *attr, const char *buf, size_t count)
  259. {
  260. unsigned long tmp;
  261. unsigned char val;
  262. unsigned long flags;
  263. sscanf(buf, "%lX", &tmp);
  264. dev_dbg(d, ": tmp = 0x%lX\n", tmp);
  265. val = (unsigned char)tmp;
  266. spin_lock_irqsave(&event_lock, flags);
  267. SET_PORT_BITS(TLCLK_REG1, 0xef, val);
  268. spin_unlock_irqrestore(&event_lock, flags);
  269. return strnlen(buf, count);
  270. }
  271. static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
  272. store_received_ref_clk3a);
  273. static ssize_t store_received_ref_clk3b(struct device *d,
  274. struct device_attribute *attr, const char *buf, size_t count)
  275. {
  276. unsigned long tmp;
  277. unsigned char val;
  278. unsigned long flags;
  279. sscanf(buf, "%lX", &tmp);
  280. dev_dbg(d, ": tmp = 0x%lX\n", tmp);
  281. val = (unsigned char)tmp;
  282. spin_lock_irqsave(&event_lock, flags);
  283. SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1);
  284. spin_unlock_irqrestore(&event_lock, flags);
  285. return strnlen(buf, count);
  286. }
  287. static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
  288. store_received_ref_clk3b);
  289. static ssize_t store_enable_clk3b_output(struct device *d,
  290. struct device_attribute *attr, const char *buf, size_t count)
  291. {
  292. unsigned long tmp;
  293. unsigned char val;
  294. unsigned long flags;
  295. sscanf(buf, "%lX", &tmp);
  296. dev_dbg(d, ": tmp = 0x%lX\n", tmp);
  297. val = (unsigned char)tmp;
  298. spin_lock_irqsave(&event_lock, flags);
  299. SET_PORT_BITS(TLCLK_REG3, 0x7f, val << 7);
  300. spin_unlock_irqrestore(&event_lock, flags);
  301. return strnlen(buf, count);
  302. }
  303. static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
  304. store_enable_clk3b_output);
  305. static ssize_t store_enable_clk3a_output(struct device *d,
  306. struct device_attribute *attr, const char *buf, size_t count)
  307. {
  308. unsigned long flags;
  309. unsigned long tmp;
  310. unsigned char val;
  311. sscanf(buf, "%lX", &tmp);
  312. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  313. val = (unsigned char)tmp;
  314. spin_lock_irqsave(&event_lock, flags);
  315. SET_PORT_BITS(TLCLK_REG3, 0xbf, val << 6);
  316. spin_unlock_irqrestore(&event_lock, flags);
  317. return strnlen(buf, count);
  318. }
  319. static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
  320. store_enable_clk3a_output);
  321. static ssize_t store_enable_clkb1_output(struct device *d,
  322. struct device_attribute *attr, const char *buf, size_t count)
  323. {
  324. unsigned long flags;
  325. unsigned long tmp;
  326. unsigned char val;
  327. sscanf(buf, "%lX", &tmp);
  328. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  329. val = (unsigned char)tmp;
  330. spin_lock_irqsave(&event_lock, flags);
  331. SET_PORT_BITS(TLCLK_REG2, 0xf7, val << 3);
  332. spin_unlock_irqrestore(&event_lock, flags);
  333. return strnlen(buf, count);
  334. }
  335. static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
  336. store_enable_clkb1_output);
  337. static ssize_t store_enable_clka1_output(struct device *d,
  338. struct device_attribute *attr, const char *buf, size_t count)
  339. {
  340. unsigned long flags;
  341. unsigned long tmp;
  342. unsigned char val;
  343. sscanf(buf, "%lX", &tmp);
  344. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  345. val = (unsigned char)tmp;
  346. spin_lock_irqsave(&event_lock, flags);
  347. SET_PORT_BITS(TLCLK_REG2, 0xfb, val << 2);
  348. spin_unlock_irqrestore(&event_lock, flags);
  349. return strnlen(buf, count);
  350. }
  351. static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
  352. store_enable_clka1_output);
  353. static ssize_t store_enable_clkb0_output(struct device *d,
  354. struct device_attribute *attr, const char *buf, size_t count)
  355. {
  356. unsigned long flags;
  357. unsigned long tmp;
  358. unsigned char val;
  359. sscanf(buf, "%lX", &tmp);
  360. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  361. val = (unsigned char)tmp;
  362. spin_lock_irqsave(&event_lock, flags);
  363. SET_PORT_BITS(TLCLK_REG2, 0xfd, val << 1);
  364. spin_unlock_irqrestore(&event_lock, flags);
  365. return strnlen(buf, count);
  366. }
  367. static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
  368. store_enable_clkb0_output);
  369. static ssize_t store_enable_clka0_output(struct device *d,
  370. struct device_attribute *attr, const char *buf, size_t count)
  371. {
  372. unsigned long flags;
  373. unsigned long tmp;
  374. unsigned char val;
  375. sscanf(buf, "%lX", &tmp);
  376. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  377. val = (unsigned char)tmp;
  378. spin_lock_irqsave(&event_lock, flags);
  379. SET_PORT_BITS(TLCLK_REG2, 0xfe, val);
  380. spin_unlock_irqrestore(&event_lock, flags);
  381. return strnlen(buf, count);
  382. }
  383. static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
  384. store_enable_clka0_output);
  385. static ssize_t store_select_amcb2_transmit_clock(struct device *d,
  386. struct device_attribute *attr, const char *buf, size_t count)
  387. {
  388. unsigned long flags;
  389. unsigned long tmp;
  390. unsigned char val;
  391. sscanf(buf, "%lX", &tmp);
  392. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  393. val = (unsigned char)tmp;
  394. spin_lock_irqsave(&event_lock, flags);
  395. if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
  396. SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x28);
  397. SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
  398. } else if (val >= CLK_8_592MHz) {
  399. SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
  400. switch (val) {
  401. case CLK_8_592MHz:
  402. SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
  403. break;
  404. case CLK_11_184MHz:
  405. SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
  406. break;
  407. case CLK_34_368MHz:
  408. SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
  409. break;
  410. case CLK_44_736MHz:
  411. SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
  412. break;
  413. }
  414. } else
  415. SET_PORT_BITS(TLCLK_REG3, 0xc7, val << 3);
  416. spin_unlock_irqrestore(&event_lock, flags);
  417. return strnlen(buf, count);
  418. }
  419. static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
  420. store_select_amcb2_transmit_clock);
  421. static ssize_t store_select_amcb1_transmit_clock(struct device *d,
  422. struct device_attribute *attr, const char *buf, size_t count)
  423. {
  424. unsigned long tmp;
  425. unsigned char val;
  426. unsigned long flags;
  427. sscanf(buf, "%lX", &tmp);
  428. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  429. val = (unsigned char)tmp;
  430. spin_lock_irqsave(&event_lock, flags);
  431. if ((val == CLK_8kHz) || (val == CLK_16_384MHz)) {
  432. SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x5);
  433. SET_PORT_BITS(TLCLK_REG1, 0xfb, ~val);
  434. } else if (val >= CLK_8_592MHz) {
  435. SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7);
  436. switch (val) {
  437. case CLK_8_592MHz:
  438. SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
  439. break;
  440. case CLK_11_184MHz:
  441. SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
  442. break;
  443. case CLK_34_368MHz:
  444. SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
  445. break;
  446. case CLK_44_736MHz:
  447. SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
  448. break;
  449. }
  450. } else
  451. SET_PORT_BITS(TLCLK_REG3, 0xf8, val);
  452. spin_unlock_irqrestore(&event_lock, flags);
  453. return strnlen(buf, count);
  454. }
  455. static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
  456. store_select_amcb1_transmit_clock);
  457. static ssize_t store_select_redundant_clock(struct device *d,
  458. struct device_attribute *attr, const char *buf, size_t count)
  459. {
  460. unsigned long tmp;
  461. unsigned char val;
  462. unsigned long flags;
  463. sscanf(buf, "%lX", &tmp);
  464. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  465. val = (unsigned char)tmp;
  466. spin_lock_irqsave(&event_lock, flags);
  467. SET_PORT_BITS(TLCLK_REG1, 0xfe, val);
  468. spin_unlock_irqrestore(&event_lock, flags);
  469. return strnlen(buf, count);
  470. }
  471. static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
  472. store_select_redundant_clock);
  473. static ssize_t store_select_ref_frequency(struct device *d,
  474. struct device_attribute *attr, const char *buf, size_t count)
  475. {
  476. unsigned long tmp;
  477. unsigned char val;
  478. unsigned long flags;
  479. sscanf(buf, "%lX", &tmp);
  480. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  481. val = (unsigned char)tmp;
  482. spin_lock_irqsave(&event_lock, flags);
  483. SET_PORT_BITS(TLCLK_REG1, 0xfd, val);
  484. spin_unlock_irqrestore(&event_lock, flags);
  485. return strnlen(buf, count);
  486. }
  487. static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
  488. store_select_ref_frequency);
  489. static ssize_t store_filter_select(struct device *d,
  490. struct device_attribute *attr, const char *buf, size_t count)
  491. {
  492. unsigned long tmp;
  493. unsigned char val;
  494. unsigned long flags;
  495. sscanf(buf, "%lX", &tmp);
  496. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  497. val = (unsigned char)tmp;
  498. spin_lock_irqsave(&event_lock, flags);
  499. SET_PORT_BITS(TLCLK_REG0, 0xfb, val);
  500. spin_unlock_irqrestore(&event_lock, flags);
  501. return strnlen(buf, count);
  502. }
  503. static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
  504. static ssize_t store_hardware_switching_mode(struct device *d,
  505. struct device_attribute *attr, const char *buf, size_t count)
  506. {
  507. unsigned long tmp;
  508. unsigned char val;
  509. unsigned long flags;
  510. sscanf(buf, "%lX", &tmp);
  511. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  512. val = (unsigned char)tmp;
  513. spin_lock_irqsave(&event_lock, flags);
  514. SET_PORT_BITS(TLCLK_REG0, 0xbf, val);
  515. spin_unlock_irqrestore(&event_lock, flags);
  516. return strnlen(buf, count);
  517. }
  518. static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
  519. store_hardware_switching_mode);
  520. static ssize_t store_hardware_switching(struct device *d,
  521. struct device_attribute *attr, const char *buf, size_t count)
  522. {
  523. unsigned long tmp;
  524. unsigned char val;
  525. unsigned long flags;
  526. sscanf(buf, "%lX", &tmp);
  527. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  528. val = (unsigned char)tmp;
  529. spin_lock_irqsave(&event_lock, flags);
  530. SET_PORT_BITS(TLCLK_REG0, 0x7f, val);
  531. spin_unlock_irqrestore(&event_lock, flags);
  532. return strnlen(buf, count);
  533. }
  534. static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
  535. store_hardware_switching);
  536. static ssize_t store_refalign (struct device *d,
  537. struct device_attribute *attr, const char *buf, size_t count)
  538. {
  539. unsigned long tmp;
  540. unsigned long flags;
  541. sscanf(buf, "%lX", &tmp);
  542. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  543. spin_lock_irqsave(&event_lock, flags);
  544. SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
  545. SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
  546. SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
  547. spin_unlock_irqrestore(&event_lock, flags);
  548. return strnlen(buf, count);
  549. }
  550. static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
  551. static ssize_t store_mode_select (struct device *d,
  552. struct device_attribute *attr, const char *buf, size_t count)
  553. {
  554. unsigned long tmp;
  555. unsigned char val;
  556. unsigned long flags;
  557. sscanf(buf, "%lX", &tmp);
  558. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  559. val = (unsigned char)tmp;
  560. spin_lock_irqsave(&event_lock, flags);
  561. SET_PORT_BITS(TLCLK_REG0, 0xcf, val);
  562. spin_unlock_irqrestore(&event_lock, flags);
  563. return strnlen(buf, count);
  564. }
  565. static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
  566. static ssize_t store_reset (struct device *d,
  567. struct device_attribute *attr, const char *buf, size_t count)
  568. {
  569. unsigned long tmp;
  570. unsigned char val;
  571. unsigned long flags;
  572. sscanf(buf, "%lX", &tmp);
  573. dev_dbg(d, "tmp = 0x%lX\n", tmp);
  574. val = (unsigned char)tmp;
  575. spin_lock_irqsave(&event_lock, flags);
  576. SET_PORT_BITS(TLCLK_REG4, 0xfd, val);
  577. spin_unlock_irqrestore(&event_lock, flags);
  578. return strnlen(buf, count);
  579. }
  580. static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
  581. static struct attribute *tlclk_sysfs_entries[] = {
  582. &dev_attr_current_ref.attr,
  583. &dev_attr_telclock_version.attr,
  584. &dev_attr_alarms.attr,
  585. &dev_attr_received_ref_clk3a.attr,
  586. &dev_attr_received_ref_clk3b.attr,
  587. &dev_attr_enable_clk3a_output.attr,
  588. &dev_attr_enable_clk3b_output.attr,
  589. &dev_attr_enable_clkb1_output.attr,
  590. &dev_attr_enable_clka1_output.attr,
  591. &dev_attr_enable_clkb0_output.attr,
  592. &dev_attr_enable_clka0_output.attr,
  593. &dev_attr_select_amcb1_transmit_clock.attr,
  594. &dev_attr_select_amcb2_transmit_clock.attr,
  595. &dev_attr_select_redundant_clock.attr,
  596. &dev_attr_select_ref_frequency.attr,
  597. &dev_attr_filter_select.attr,
  598. &dev_attr_hardware_switching_mode.attr,
  599. &dev_attr_hardware_switching.attr,
  600. &dev_attr_refalign.attr,
  601. &dev_attr_mode_select.attr,
  602. &dev_attr_reset.attr,
  603. NULL
  604. };
  605. static struct attribute_group tlclk_attribute_group = {
  606. .name = NULL, /* put in device directory */
  607. .attrs = tlclk_sysfs_entries,
  608. };
  609. static struct platform_device *tlclk_device;
  610. static int __init tlclk_init(void)
  611. {
  612. int ret;
  613. ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
  614. if (ret < 0) {
  615. printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
  616. return ret;
  617. }
  618. tlclk_major = ret;
  619. alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
  620. if (!alarm_events)
  621. goto out1;
  622. /* Read telecom clock IRQ number (Set by BIOS) */
  623. if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
  624. printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
  625. TLCLK_BASE);
  626. ret = -EBUSY;
  627. goto out2;
  628. }
  629. telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
  630. if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
  631. printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n",
  632. telclk_interrupt);
  633. ret = -ENXIO;
  634. goto out3;
  635. }
  636. init_timer(&switchover_timer);
  637. ret = misc_register(&tlclk_miscdev);
  638. if (ret < 0) {
  639. printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
  640. goto out3;
  641. }
  642. tlclk_device = platform_device_register_simple("telco_clock",
  643. -1, NULL, 0);
  644. if (IS_ERR(tlclk_device)) {
  645. printk(KERN_ERR "tlclk: platform_device_register failed.\n");
  646. ret = PTR_ERR(tlclk_device);
  647. goto out4;
  648. }
  649. ret = sysfs_create_group(&tlclk_device->dev.kobj,
  650. &tlclk_attribute_group);
  651. if (ret) {
  652. printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
  653. goto out5;
  654. }
  655. return 0;
  656. out5:
  657. platform_device_unregister(tlclk_device);
  658. out4:
  659. misc_deregister(&tlclk_miscdev);
  660. out3:
  661. release_region(TLCLK_BASE, 8);
  662. out2:
  663. kfree(alarm_events);
  664. out1:
  665. unregister_chrdev(tlclk_major, "telco_clock");
  666. return ret;
  667. }
  668. static void __exit tlclk_cleanup(void)
  669. {
  670. sysfs_remove_group(&tlclk_device->dev.kobj, &tlclk_attribute_group);
  671. platform_device_unregister(tlclk_device);
  672. misc_deregister(&tlclk_miscdev);
  673. unregister_chrdev(tlclk_major, "telco_clock");
  674. release_region(TLCLK_BASE, 8);
  675. del_timer_sync(&switchover_timer);
  676. kfree(alarm_events);
  677. }
  678. static void switchover_timeout(unsigned long data)
  679. {
  680. unsigned long flags = *(unsigned long *) data;
  681. if ((flags & 1)) {
  682. if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
  683. alarm_events->switchover_primary++;
  684. } else {
  685. if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08))
  686. alarm_events->switchover_secondary++;
  687. }
  688. /* Alarm processing is done, wake up read task */
  689. del_timer(&switchover_timer);
  690. got_event = 1;
  691. wake_up(&wq);
  692. }
  693. static irqreturn_t tlclk_interrupt(int irq, void *dev_id)
  694. {
  695. unsigned long flags;
  696. spin_lock_irqsave(&event_lock, flags);
  697. /* Read and clear interrupt events */
  698. int_events = inb(TLCLK_REG6);
  699. /* Primary_Los changed from 0 to 1 ? */
  700. if (int_events & PRI_LOS_01_MASK) {
  701. if (inb(TLCLK_REG2) & SEC_LOST_MASK)
  702. alarm_events->lost_clocks++;
  703. else
  704. alarm_events->lost_primary_clock++;
  705. }
  706. /* Primary_Los changed from 1 to 0 ? */
  707. if (int_events & PRI_LOS_10_MASK) {
  708. alarm_events->primary_clock_back++;
  709. SET_PORT_BITS(TLCLK_REG1, 0xFE, 1);
  710. }
  711. /* Secondary_Los changed from 0 to 1 ? */
  712. if (int_events & SEC_LOS_01_MASK) {
  713. if (inb(TLCLK_REG2) & PRI_LOST_MASK)
  714. alarm_events->lost_clocks++;
  715. else
  716. alarm_events->lost_secondary_clock++;
  717. }
  718. /* Secondary_Los changed from 1 to 0 ? */
  719. if (int_events & SEC_LOS_10_MASK) {
  720. alarm_events->secondary_clock_back++;
  721. SET_PORT_BITS(TLCLK_REG1, 0xFE, 0);
  722. }
  723. if (int_events & HOLDOVER_10_MASK)
  724. alarm_events->pll_end_holdover++;
  725. if (int_events & UNLOCK_01_MASK)
  726. alarm_events->pll_lost_sync++;
  727. if (int_events & UNLOCK_10_MASK)
  728. alarm_events->pll_sync++;
  729. /* Holdover changed from 0 to 1 ? */
  730. if (int_events & HOLDOVER_01_MASK) {
  731. alarm_events->pll_holdover++;
  732. /* TIMEOUT in ~10ms */
  733. switchover_timer.expires = jiffies + msecs_to_jiffies(10);
  734. tlclk_timer_data = inb(TLCLK_REG1);
  735. switchover_timer.data = (unsigned long) &tlclk_timer_data;
  736. mod_timer(&switchover_timer, switchover_timer.expires);
  737. } else {
  738. got_event = 1;
  739. wake_up(&wq);
  740. }
  741. spin_unlock_irqrestore(&event_lock, flags);
  742. return IRQ_HANDLED;
  743. }
  744. module_init(tlclk_init);
  745. module_exit(tlclk_cleanup);