104-quad-8.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Counter driver for the ACCES 104-QUAD-8
  4. * Copyright (C) 2016 William Breathitt Gray
  5. *
  6. * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
  7. */
  8. #include <linux/bitops.h>
  9. #include <linux/counter.h>
  10. #include <linux/device.h>
  11. #include <linux/errno.h>
  12. #include <linux/io.h>
  13. #include <linux/ioport.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/isa.h>
  16. #include <linux/kernel.h>
  17. #include <linux/list.h>
  18. #include <linux/module.h>
  19. #include <linux/moduleparam.h>
  20. #include <linux/types.h>
  21. #include <linux/spinlock.h>
  22. #define QUAD8_EXTENT 32
  23. static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
  24. static unsigned int num_quad8;
  25. module_param_hw_array(base, uint, ioport, &num_quad8, 0);
  26. MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
  27. static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)];
  28. static unsigned int num_irq;
  29. module_param_hw_array(irq, uint, irq, &num_irq, 0);
  30. MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
  31. #define QUAD8_NUM_COUNTERS 8
  32. /**
  33. * struct channel_reg - channel register structure
  34. * @data: Count data
  35. * @control: Channel flags and control
  36. */
  37. struct channel_reg {
  38. u8 data;
  39. u8 control;
  40. };
  41. /**
  42. * struct quad8_reg - device register structure
  43. * @channel: quadrature counter data and control
  44. * @interrupt_status: channel interrupt status
  45. * @channel_oper: enable/reset counters and interrupt functions
  46. * @index_interrupt: enable channel interrupts
  47. * @reserved: reserved for Factory Use
  48. * @index_input_levels: index signal logical input level
  49. * @cable_status: differential encoder cable status
  50. */
  51. struct quad8_reg {
  52. struct channel_reg channel[QUAD8_NUM_COUNTERS];
  53. u8 interrupt_status;
  54. u8 channel_oper;
  55. u8 index_interrupt;
  56. u8 reserved[3];
  57. u8 index_input_levels;
  58. u8 cable_status;
  59. };
  60. /**
  61. * struct quad8 - device private data structure
  62. * @lock: lock to prevent clobbering device states during R/W ops
  63. * @counter: instance of the counter_device
  64. * @fck_prescaler: array of filter clock prescaler configurations
  65. * @preset: array of preset values
  66. * @count_mode: array of count mode configurations
  67. * @quadrature_mode: array of quadrature mode configurations
  68. * @quadrature_scale: array of quadrature mode scale configurations
  69. * @ab_enable: array of A and B inputs enable configurations
  70. * @preset_enable: array of set_to_preset_on_index attribute configurations
  71. * @irq_trigger: array of current IRQ trigger function configurations
  72. * @synchronous_mode: array of index function synchronous mode configurations
  73. * @index_polarity: array of index function polarity configurations
  74. * @cable_fault_enable: differential encoder cable status enable configurations
  75. * @reg: I/O address offset for the device registers
  76. */
  77. struct quad8 {
  78. spinlock_t lock;
  79. unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
  80. unsigned int preset[QUAD8_NUM_COUNTERS];
  81. unsigned int count_mode[QUAD8_NUM_COUNTERS];
  82. unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
  83. unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
  84. unsigned int ab_enable[QUAD8_NUM_COUNTERS];
  85. unsigned int preset_enable[QUAD8_NUM_COUNTERS];
  86. unsigned int irq_trigger[QUAD8_NUM_COUNTERS];
  87. unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
  88. unsigned int index_polarity[QUAD8_NUM_COUNTERS];
  89. unsigned int cable_fault_enable;
  90. struct quad8_reg __iomem *reg;
  91. };
  92. /* Error flag */
  93. #define QUAD8_FLAG_E BIT(4)
  94. /* Up/Down flag */
  95. #define QUAD8_FLAG_UD BIT(5)
  96. /* Reset and Load Signal Decoders */
  97. #define QUAD8_CTR_RLD 0x00
  98. /* Counter Mode Register */
  99. #define QUAD8_CTR_CMR 0x20
  100. /* Input / Output Control Register */
  101. #define QUAD8_CTR_IOR 0x40
  102. /* Index Control Register */
  103. #define QUAD8_CTR_IDR 0x60
  104. /* Reset Byte Pointer (three byte data pointer) */
  105. #define QUAD8_RLD_RESET_BP 0x01
  106. /* Reset Counter */
  107. #define QUAD8_RLD_RESET_CNTR 0x02
  108. /* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
  109. #define QUAD8_RLD_RESET_FLAGS 0x04
  110. /* Reset Error flag */
  111. #define QUAD8_RLD_RESET_E 0x06
  112. /* Preset Register to Counter */
  113. #define QUAD8_RLD_PRESET_CNTR 0x08
  114. /* Transfer Counter to Output Latch */
  115. #define QUAD8_RLD_CNTR_OUT 0x10
  116. /* Transfer Preset Register LSB to FCK Prescaler */
  117. #define QUAD8_RLD_PRESET_PSC 0x18
  118. #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
  119. #define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04
  120. #define QUAD8_CMR_QUADRATURE_X1 0x08
  121. #define QUAD8_CMR_QUADRATURE_X2 0x10
  122. #define QUAD8_CMR_QUADRATURE_X4 0x18
  123. /* Each Counter is 24 bits wide */
  124. #define LS7267_CNTR_MAX GENMASK(23, 0)
  125. static int quad8_signal_read(struct counter_device *counter,
  126. struct counter_signal *signal,
  127. enum counter_signal_level *level)
  128. {
  129. const struct quad8 *const priv = counter_priv(counter);
  130. unsigned int state;
  131. /* Only Index signal levels can be read */
  132. if (signal->id < 16)
  133. return -EINVAL;
  134. state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
  135. *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
  136. return 0;
  137. }
  138. static int quad8_count_read(struct counter_device *counter,
  139. struct counter_count *count, u64 *val)
  140. {
  141. struct quad8 *const priv = counter_priv(counter);
  142. struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
  143. unsigned long irqflags;
  144. int i;
  145. *val = 0;
  146. spin_lock_irqsave(&priv->lock, irqflags);
  147. /* Reset Byte Pointer; transfer Counter to Output Latch */
  148. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
  149. &chan->control);
  150. for (i = 0; i < 3; i++)
  151. *val |= (unsigned long)ioread8(&chan->data) << (8 * i);
  152. spin_unlock_irqrestore(&priv->lock, irqflags);
  153. return 0;
  154. }
  155. static int quad8_count_write(struct counter_device *counter,
  156. struct counter_count *count, u64 val)
  157. {
  158. struct quad8 *const priv = counter_priv(counter);
  159. struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
  160. unsigned long irqflags;
  161. int i;
  162. if (val > LS7267_CNTR_MAX)
  163. return -ERANGE;
  164. spin_lock_irqsave(&priv->lock, irqflags);
  165. /* Reset Byte Pointer */
  166. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  167. /* Counter can only be set via Preset Register */
  168. for (i = 0; i < 3; i++)
  169. iowrite8(val >> (8 * i), &chan->data);
  170. /* Transfer Preset Register to Counter */
  171. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
  172. /* Reset Byte Pointer */
  173. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  174. /* Set Preset Register back to original value */
  175. val = priv->preset[count->id];
  176. for (i = 0; i < 3; i++)
  177. iowrite8(val >> (8 * i), &chan->data);
  178. /* Reset Borrow, Carry, Compare, and Sign flags */
  179. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
  180. /* Reset Error flag */
  181. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
  182. spin_unlock_irqrestore(&priv->lock, irqflags);
  183. return 0;
  184. }
  185. static const enum counter_function quad8_count_functions_list[] = {
  186. COUNTER_FUNCTION_PULSE_DIRECTION,
  187. COUNTER_FUNCTION_QUADRATURE_X1_A,
  188. COUNTER_FUNCTION_QUADRATURE_X2_A,
  189. COUNTER_FUNCTION_QUADRATURE_X4,
  190. };
  191. static int quad8_function_get(const struct quad8 *const priv, const size_t id,
  192. enum counter_function *const function)
  193. {
  194. if (!priv->quadrature_mode[id]) {
  195. *function = COUNTER_FUNCTION_PULSE_DIRECTION;
  196. return 0;
  197. }
  198. switch (priv->quadrature_scale[id]) {
  199. case 0:
  200. *function = COUNTER_FUNCTION_QUADRATURE_X1_A;
  201. return 0;
  202. case 1:
  203. *function = COUNTER_FUNCTION_QUADRATURE_X2_A;
  204. return 0;
  205. case 2:
  206. *function = COUNTER_FUNCTION_QUADRATURE_X4;
  207. return 0;
  208. default:
  209. /* should never reach this path */
  210. return -EINVAL;
  211. }
  212. }
  213. static int quad8_function_read(struct counter_device *counter,
  214. struct counter_count *count,
  215. enum counter_function *function)
  216. {
  217. struct quad8 *const priv = counter_priv(counter);
  218. unsigned long irqflags;
  219. int retval;
  220. spin_lock_irqsave(&priv->lock, irqflags);
  221. retval = quad8_function_get(priv, count->id, function);
  222. spin_unlock_irqrestore(&priv->lock, irqflags);
  223. return retval;
  224. }
  225. static int quad8_function_write(struct counter_device *counter,
  226. struct counter_count *count,
  227. enum counter_function function)
  228. {
  229. struct quad8 *const priv = counter_priv(counter);
  230. const int id = count->id;
  231. unsigned int *const quadrature_mode = priv->quadrature_mode + id;
  232. unsigned int *const scale = priv->quadrature_scale + id;
  233. unsigned int *const synchronous_mode = priv->synchronous_mode + id;
  234. u8 __iomem *const control = &priv->reg->channel[id].control;
  235. unsigned long irqflags;
  236. unsigned int mode_cfg;
  237. unsigned int idr_cfg;
  238. spin_lock_irqsave(&priv->lock, irqflags);
  239. mode_cfg = priv->count_mode[id] << 1;
  240. idr_cfg = priv->index_polarity[id] << 1;
  241. if (function == COUNTER_FUNCTION_PULSE_DIRECTION) {
  242. *quadrature_mode = 0;
  243. /* Quadrature scaling only available in quadrature mode */
  244. *scale = 0;
  245. /* Synchronous function not supported in non-quadrature mode */
  246. if (*synchronous_mode) {
  247. *synchronous_mode = 0;
  248. /* Disable synchronous function mode */
  249. iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
  250. }
  251. } else {
  252. *quadrature_mode = 1;
  253. switch (function) {
  254. case COUNTER_FUNCTION_QUADRATURE_X1_A:
  255. *scale = 0;
  256. mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
  257. break;
  258. case COUNTER_FUNCTION_QUADRATURE_X2_A:
  259. *scale = 1;
  260. mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
  261. break;
  262. case COUNTER_FUNCTION_QUADRATURE_X4:
  263. *scale = 2;
  264. mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
  265. break;
  266. default:
  267. /* should never reach this path */
  268. spin_unlock_irqrestore(&priv->lock, irqflags);
  269. return -EINVAL;
  270. }
  271. }
  272. /* Load mode configuration to Counter Mode Register */
  273. iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
  274. spin_unlock_irqrestore(&priv->lock, irqflags);
  275. return 0;
  276. }
  277. static int quad8_direction_read(struct counter_device *counter,
  278. struct counter_count *count,
  279. enum counter_count_direction *direction)
  280. {
  281. const struct quad8 *const priv = counter_priv(counter);
  282. unsigned int ud_flag;
  283. u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
  284. /* U/D flag: nonzero = up, zero = down */
  285. ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
  286. *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
  287. COUNTER_COUNT_DIRECTION_BACKWARD;
  288. return 0;
  289. }
  290. static const enum counter_synapse_action quad8_index_actions_list[] = {
  291. COUNTER_SYNAPSE_ACTION_NONE,
  292. COUNTER_SYNAPSE_ACTION_RISING_EDGE,
  293. };
  294. static const enum counter_synapse_action quad8_synapse_actions_list[] = {
  295. COUNTER_SYNAPSE_ACTION_NONE,
  296. COUNTER_SYNAPSE_ACTION_RISING_EDGE,
  297. COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
  298. COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
  299. };
  300. static int quad8_action_read(struct counter_device *counter,
  301. struct counter_count *count,
  302. struct counter_synapse *synapse,
  303. enum counter_synapse_action *action)
  304. {
  305. struct quad8 *const priv = counter_priv(counter);
  306. unsigned long irqflags;
  307. int err;
  308. enum counter_function function;
  309. const size_t signal_a_id = count->synapses[0].signal->id;
  310. enum counter_count_direction direction;
  311. /* Handle Index signals */
  312. if (synapse->signal->id >= 16) {
  313. if (!priv->preset_enable[count->id])
  314. *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
  315. else
  316. *action = COUNTER_SYNAPSE_ACTION_NONE;
  317. return 0;
  318. }
  319. spin_lock_irqsave(&priv->lock, irqflags);
  320. /* Get Count function and direction atomically */
  321. err = quad8_function_get(priv, count->id, &function);
  322. if (err) {
  323. spin_unlock_irqrestore(&priv->lock, irqflags);
  324. return err;
  325. }
  326. err = quad8_direction_read(counter, count, &direction);
  327. if (err) {
  328. spin_unlock_irqrestore(&priv->lock, irqflags);
  329. return err;
  330. }
  331. spin_unlock_irqrestore(&priv->lock, irqflags);
  332. /* Default action mode */
  333. *action = COUNTER_SYNAPSE_ACTION_NONE;
  334. /* Determine action mode based on current count function mode */
  335. switch (function) {
  336. case COUNTER_FUNCTION_PULSE_DIRECTION:
  337. if (synapse->signal->id == signal_a_id)
  338. *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
  339. return 0;
  340. case COUNTER_FUNCTION_QUADRATURE_X1_A:
  341. if (synapse->signal->id == signal_a_id) {
  342. if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
  343. *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
  344. else
  345. *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
  346. }
  347. return 0;
  348. case COUNTER_FUNCTION_QUADRATURE_X2_A:
  349. if (synapse->signal->id == signal_a_id)
  350. *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
  351. return 0;
  352. case COUNTER_FUNCTION_QUADRATURE_X4:
  353. *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
  354. return 0;
  355. default:
  356. /* should never reach this path */
  357. return -EINVAL;
  358. }
  359. }
  360. enum {
  361. QUAD8_EVENT_CARRY = 0,
  362. QUAD8_EVENT_COMPARE = 1,
  363. QUAD8_EVENT_CARRY_BORROW = 2,
  364. QUAD8_EVENT_INDEX = 3,
  365. };
  366. static int quad8_events_configure(struct counter_device *counter)
  367. {
  368. struct quad8 *const priv = counter_priv(counter);
  369. unsigned long irq_enabled = 0;
  370. unsigned long irqflags;
  371. struct counter_event_node *event_node;
  372. unsigned int next_irq_trigger;
  373. unsigned long ior_cfg;
  374. spin_lock_irqsave(&priv->lock, irqflags);
  375. list_for_each_entry(event_node, &counter->events_list, l) {
  376. switch (event_node->event) {
  377. case COUNTER_EVENT_OVERFLOW:
  378. next_irq_trigger = QUAD8_EVENT_CARRY;
  379. break;
  380. case COUNTER_EVENT_THRESHOLD:
  381. next_irq_trigger = QUAD8_EVENT_COMPARE;
  382. break;
  383. case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
  384. next_irq_trigger = QUAD8_EVENT_CARRY_BORROW;
  385. break;
  386. case COUNTER_EVENT_INDEX:
  387. next_irq_trigger = QUAD8_EVENT_INDEX;
  388. break;
  389. default:
  390. /* should never reach this path */
  391. spin_unlock_irqrestore(&priv->lock, irqflags);
  392. return -EINVAL;
  393. }
  394. /* Enable IRQ line */
  395. irq_enabled |= BIT(event_node->channel);
  396. /* Skip configuration if it is the same as previously set */
  397. if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
  398. continue;
  399. /* Save new IRQ function configuration */
  400. priv->irq_trigger[event_node->channel] = next_irq_trigger;
  401. /* Load configuration to I/O Control Register */
  402. ior_cfg = priv->ab_enable[event_node->channel] |
  403. priv->preset_enable[event_node->channel] << 1 |
  404. priv->irq_trigger[event_node->channel] << 3;
  405. iowrite8(QUAD8_CTR_IOR | ior_cfg,
  406. &priv->reg->channel[event_node->channel].control);
  407. }
  408. iowrite8(irq_enabled, &priv->reg->index_interrupt);
  409. spin_unlock_irqrestore(&priv->lock, irqflags);
  410. return 0;
  411. }
  412. static int quad8_watch_validate(struct counter_device *counter,
  413. const struct counter_watch *watch)
  414. {
  415. struct counter_event_node *event_node;
  416. if (watch->channel > QUAD8_NUM_COUNTERS - 1)
  417. return -EINVAL;
  418. switch (watch->event) {
  419. case COUNTER_EVENT_OVERFLOW:
  420. case COUNTER_EVENT_THRESHOLD:
  421. case COUNTER_EVENT_OVERFLOW_UNDERFLOW:
  422. case COUNTER_EVENT_INDEX:
  423. list_for_each_entry(event_node, &counter->next_events_list, l)
  424. if (watch->channel == event_node->channel &&
  425. watch->event != event_node->event)
  426. return -EINVAL;
  427. return 0;
  428. default:
  429. return -EINVAL;
  430. }
  431. }
  432. static const struct counter_ops quad8_ops = {
  433. .signal_read = quad8_signal_read,
  434. .count_read = quad8_count_read,
  435. .count_write = quad8_count_write,
  436. .function_read = quad8_function_read,
  437. .function_write = quad8_function_write,
  438. .action_read = quad8_action_read,
  439. .events_configure = quad8_events_configure,
  440. .watch_validate = quad8_watch_validate,
  441. };
  442. static const char *const quad8_index_polarity_modes[] = {
  443. "negative",
  444. "positive"
  445. };
  446. static int quad8_index_polarity_get(struct counter_device *counter,
  447. struct counter_signal *signal,
  448. u32 *index_polarity)
  449. {
  450. const struct quad8 *const priv = counter_priv(counter);
  451. const size_t channel_id = signal->id - 16;
  452. *index_polarity = priv->index_polarity[channel_id];
  453. return 0;
  454. }
  455. static int quad8_index_polarity_set(struct counter_device *counter,
  456. struct counter_signal *signal,
  457. u32 index_polarity)
  458. {
  459. struct quad8 *const priv = counter_priv(counter);
  460. const size_t channel_id = signal->id - 16;
  461. u8 __iomem *const control = &priv->reg->channel[channel_id].control;
  462. unsigned long irqflags;
  463. unsigned int idr_cfg = index_polarity << 1;
  464. spin_lock_irqsave(&priv->lock, irqflags);
  465. idr_cfg |= priv->synchronous_mode[channel_id];
  466. priv->index_polarity[channel_id] = index_polarity;
  467. /* Load Index Control configuration to Index Control Register */
  468. iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
  469. spin_unlock_irqrestore(&priv->lock, irqflags);
  470. return 0;
  471. }
  472. static int quad8_polarity_read(struct counter_device *counter,
  473. struct counter_signal *signal,
  474. enum counter_signal_polarity *polarity)
  475. {
  476. int err;
  477. u32 index_polarity;
  478. err = quad8_index_polarity_get(counter, signal, &index_polarity);
  479. if (err)
  480. return err;
  481. *polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE :
  482. COUNTER_SIGNAL_POLARITY_NEGATIVE;
  483. return 0;
  484. }
  485. static int quad8_polarity_write(struct counter_device *counter,
  486. struct counter_signal *signal,
  487. enum counter_signal_polarity polarity)
  488. {
  489. const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0;
  490. return quad8_index_polarity_set(counter, signal, pol);
  491. }
  492. static const char *const quad8_synchronous_modes[] = {
  493. "non-synchronous",
  494. "synchronous"
  495. };
  496. static int quad8_synchronous_mode_get(struct counter_device *counter,
  497. struct counter_signal *signal,
  498. u32 *synchronous_mode)
  499. {
  500. const struct quad8 *const priv = counter_priv(counter);
  501. const size_t channel_id = signal->id - 16;
  502. *synchronous_mode = priv->synchronous_mode[channel_id];
  503. return 0;
  504. }
  505. static int quad8_synchronous_mode_set(struct counter_device *counter,
  506. struct counter_signal *signal,
  507. u32 synchronous_mode)
  508. {
  509. struct quad8 *const priv = counter_priv(counter);
  510. const size_t channel_id = signal->id - 16;
  511. u8 __iomem *const control = &priv->reg->channel[channel_id].control;
  512. unsigned long irqflags;
  513. unsigned int idr_cfg = synchronous_mode;
  514. spin_lock_irqsave(&priv->lock, irqflags);
  515. idr_cfg |= priv->index_polarity[channel_id] << 1;
  516. /* Index function must be non-synchronous in non-quadrature mode */
  517. if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
  518. spin_unlock_irqrestore(&priv->lock, irqflags);
  519. return -EINVAL;
  520. }
  521. priv->synchronous_mode[channel_id] = synchronous_mode;
  522. /* Load Index Control configuration to Index Control Register */
  523. iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
  524. spin_unlock_irqrestore(&priv->lock, irqflags);
  525. return 0;
  526. }
  527. static int quad8_count_floor_read(struct counter_device *counter,
  528. struct counter_count *count, u64 *floor)
  529. {
  530. /* Only a floor of 0 is supported */
  531. *floor = 0;
  532. return 0;
  533. }
  534. static int quad8_count_mode_read(struct counter_device *counter,
  535. struct counter_count *count,
  536. enum counter_count_mode *cnt_mode)
  537. {
  538. const struct quad8 *const priv = counter_priv(counter);
  539. /* Map 104-QUAD-8 count mode to Generic Counter count mode */
  540. switch (priv->count_mode[count->id]) {
  541. case 0:
  542. *cnt_mode = COUNTER_COUNT_MODE_NORMAL;
  543. break;
  544. case 1:
  545. *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
  546. break;
  547. case 2:
  548. *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
  549. break;
  550. case 3:
  551. *cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
  552. break;
  553. }
  554. return 0;
  555. }
  556. static int quad8_count_mode_write(struct counter_device *counter,
  557. struct counter_count *count,
  558. enum counter_count_mode cnt_mode)
  559. {
  560. struct quad8 *const priv = counter_priv(counter);
  561. unsigned int count_mode;
  562. unsigned int mode_cfg;
  563. u8 __iomem *const control = &priv->reg->channel[count->id].control;
  564. unsigned long irqflags;
  565. /* Map Generic Counter count mode to 104-QUAD-8 count mode */
  566. switch (cnt_mode) {
  567. case COUNTER_COUNT_MODE_NORMAL:
  568. count_mode = 0;
  569. break;
  570. case COUNTER_COUNT_MODE_RANGE_LIMIT:
  571. count_mode = 1;
  572. break;
  573. case COUNTER_COUNT_MODE_NON_RECYCLE:
  574. count_mode = 2;
  575. break;
  576. case COUNTER_COUNT_MODE_MODULO_N:
  577. count_mode = 3;
  578. break;
  579. default:
  580. /* should never reach this path */
  581. return -EINVAL;
  582. }
  583. spin_lock_irqsave(&priv->lock, irqflags);
  584. priv->count_mode[count->id] = count_mode;
  585. /* Set count mode configuration value */
  586. mode_cfg = count_mode << 1;
  587. /* Add quadrature mode configuration */
  588. if (priv->quadrature_mode[count->id])
  589. mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
  590. /* Load mode configuration to Counter Mode Register */
  591. iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
  592. spin_unlock_irqrestore(&priv->lock, irqflags);
  593. return 0;
  594. }
  595. static int quad8_count_enable_read(struct counter_device *counter,
  596. struct counter_count *count, u8 *enable)
  597. {
  598. const struct quad8 *const priv = counter_priv(counter);
  599. *enable = priv->ab_enable[count->id];
  600. return 0;
  601. }
  602. static int quad8_count_enable_write(struct counter_device *counter,
  603. struct counter_count *count, u8 enable)
  604. {
  605. struct quad8 *const priv = counter_priv(counter);
  606. u8 __iomem *const control = &priv->reg->channel[count->id].control;
  607. unsigned long irqflags;
  608. unsigned int ior_cfg;
  609. spin_lock_irqsave(&priv->lock, irqflags);
  610. priv->ab_enable[count->id] = enable;
  611. ior_cfg = enable | priv->preset_enable[count->id] << 1 |
  612. priv->irq_trigger[count->id] << 3;
  613. /* Load I/O control configuration */
  614. iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
  615. spin_unlock_irqrestore(&priv->lock, irqflags);
  616. return 0;
  617. }
  618. static const char *const quad8_noise_error_states[] = {
  619. "No excessive noise is present at the count inputs",
  620. "Excessive noise is present at the count inputs"
  621. };
  622. static int quad8_error_noise_get(struct counter_device *counter,
  623. struct counter_count *count, u32 *noise_error)
  624. {
  625. const struct quad8 *const priv = counter_priv(counter);
  626. u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
  627. *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
  628. return 0;
  629. }
  630. static int quad8_count_preset_read(struct counter_device *counter,
  631. struct counter_count *count, u64 *preset)
  632. {
  633. const struct quad8 *const priv = counter_priv(counter);
  634. *preset = priv->preset[count->id];
  635. return 0;
  636. }
  637. static void quad8_preset_register_set(struct quad8 *const priv, const int id,
  638. const unsigned int preset)
  639. {
  640. struct channel_reg __iomem *const chan = priv->reg->channel + id;
  641. int i;
  642. priv->preset[id] = preset;
  643. /* Reset Byte Pointer */
  644. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  645. /* Set Preset Register */
  646. for (i = 0; i < 3; i++)
  647. iowrite8(preset >> (8 * i), &chan->data);
  648. }
  649. static int quad8_count_preset_write(struct counter_device *counter,
  650. struct counter_count *count, u64 preset)
  651. {
  652. struct quad8 *const priv = counter_priv(counter);
  653. unsigned long irqflags;
  654. if (preset > LS7267_CNTR_MAX)
  655. return -ERANGE;
  656. spin_lock_irqsave(&priv->lock, irqflags);
  657. quad8_preset_register_set(priv, count->id, preset);
  658. spin_unlock_irqrestore(&priv->lock, irqflags);
  659. return 0;
  660. }
  661. static int quad8_count_ceiling_read(struct counter_device *counter,
  662. struct counter_count *count, u64 *ceiling)
  663. {
  664. struct quad8 *const priv = counter_priv(counter);
  665. unsigned long irqflags;
  666. spin_lock_irqsave(&priv->lock, irqflags);
  667. /* Range Limit and Modulo-N count modes use preset value as ceiling */
  668. switch (priv->count_mode[count->id]) {
  669. case 1:
  670. case 3:
  671. *ceiling = priv->preset[count->id];
  672. break;
  673. default:
  674. *ceiling = LS7267_CNTR_MAX;
  675. break;
  676. }
  677. spin_unlock_irqrestore(&priv->lock, irqflags);
  678. return 0;
  679. }
  680. static int quad8_count_ceiling_write(struct counter_device *counter,
  681. struct counter_count *count, u64 ceiling)
  682. {
  683. struct quad8 *const priv = counter_priv(counter);
  684. unsigned long irqflags;
  685. if (ceiling > LS7267_CNTR_MAX)
  686. return -ERANGE;
  687. spin_lock_irqsave(&priv->lock, irqflags);
  688. /* Range Limit and Modulo-N count modes use preset value as ceiling */
  689. switch (priv->count_mode[count->id]) {
  690. case 1:
  691. case 3:
  692. quad8_preset_register_set(priv, count->id, ceiling);
  693. spin_unlock_irqrestore(&priv->lock, irqflags);
  694. return 0;
  695. }
  696. spin_unlock_irqrestore(&priv->lock, irqflags);
  697. return -EINVAL;
  698. }
  699. static int quad8_count_preset_enable_read(struct counter_device *counter,
  700. struct counter_count *count,
  701. u8 *preset_enable)
  702. {
  703. const struct quad8 *const priv = counter_priv(counter);
  704. *preset_enable = !priv->preset_enable[count->id];
  705. return 0;
  706. }
  707. static int quad8_count_preset_enable_write(struct counter_device *counter,
  708. struct counter_count *count,
  709. u8 preset_enable)
  710. {
  711. struct quad8 *const priv = counter_priv(counter);
  712. u8 __iomem *const control = &priv->reg->channel[count->id].control;
  713. unsigned long irqflags;
  714. unsigned int ior_cfg;
  715. /* Preset enable is active low in Input/Output Control register */
  716. preset_enable = !preset_enable;
  717. spin_lock_irqsave(&priv->lock, irqflags);
  718. priv->preset_enable[count->id] = preset_enable;
  719. ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 |
  720. priv->irq_trigger[count->id] << 3;
  721. /* Load I/O control configuration to Input / Output Control Register */
  722. iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
  723. spin_unlock_irqrestore(&priv->lock, irqflags);
  724. return 0;
  725. }
  726. static int quad8_signal_cable_fault_read(struct counter_device *counter,
  727. struct counter_signal *signal,
  728. u8 *cable_fault)
  729. {
  730. struct quad8 *const priv = counter_priv(counter);
  731. const size_t channel_id = signal->id / 2;
  732. unsigned long irqflags;
  733. bool disabled;
  734. unsigned int status;
  735. spin_lock_irqsave(&priv->lock, irqflags);
  736. disabled = !(priv->cable_fault_enable & BIT(channel_id));
  737. if (disabled) {
  738. spin_unlock_irqrestore(&priv->lock, irqflags);
  739. return -EINVAL;
  740. }
  741. /* Logic 0 = cable fault */
  742. status = ioread8(&priv->reg->cable_status);
  743. spin_unlock_irqrestore(&priv->lock, irqflags);
  744. /* Mask respective channel and invert logic */
  745. *cable_fault = !(status & BIT(channel_id));
  746. return 0;
  747. }
  748. static int quad8_signal_cable_fault_enable_read(struct counter_device *counter,
  749. struct counter_signal *signal,
  750. u8 *enable)
  751. {
  752. const struct quad8 *const priv = counter_priv(counter);
  753. const size_t channel_id = signal->id / 2;
  754. *enable = !!(priv->cable_fault_enable & BIT(channel_id));
  755. return 0;
  756. }
  757. static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
  758. struct counter_signal *signal,
  759. u8 enable)
  760. {
  761. struct quad8 *const priv = counter_priv(counter);
  762. const size_t channel_id = signal->id / 2;
  763. unsigned long irqflags;
  764. unsigned int cable_fault_enable;
  765. spin_lock_irqsave(&priv->lock, irqflags);
  766. if (enable)
  767. priv->cable_fault_enable |= BIT(channel_id);
  768. else
  769. priv->cable_fault_enable &= ~BIT(channel_id);
  770. /* Enable is active low in Differential Encoder Cable Status register */
  771. cable_fault_enable = ~priv->cable_fault_enable;
  772. iowrite8(cable_fault_enable, &priv->reg->cable_status);
  773. spin_unlock_irqrestore(&priv->lock, irqflags);
  774. return 0;
  775. }
  776. static int quad8_signal_fck_prescaler_read(struct counter_device *counter,
  777. struct counter_signal *signal,
  778. u8 *prescaler)
  779. {
  780. const struct quad8 *const priv = counter_priv(counter);
  781. *prescaler = priv->fck_prescaler[signal->id / 2];
  782. return 0;
  783. }
  784. static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
  785. struct counter_signal *signal,
  786. u8 prescaler)
  787. {
  788. struct quad8 *const priv = counter_priv(counter);
  789. const size_t channel_id = signal->id / 2;
  790. struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
  791. unsigned long irqflags;
  792. spin_lock_irqsave(&priv->lock, irqflags);
  793. priv->fck_prescaler[channel_id] = prescaler;
  794. /* Reset Byte Pointer */
  795. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  796. /* Set filter clock factor */
  797. iowrite8(prescaler, &chan->data);
  798. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
  799. &chan->control);
  800. spin_unlock_irqrestore(&priv->lock, irqflags);
  801. return 0;
  802. }
  803. static struct counter_comp quad8_signal_ext[] = {
  804. COUNTER_COMP_SIGNAL_BOOL("cable_fault", quad8_signal_cable_fault_read,
  805. NULL),
  806. COUNTER_COMP_SIGNAL_BOOL("cable_fault_enable",
  807. quad8_signal_cable_fault_enable_read,
  808. quad8_signal_cable_fault_enable_write),
  809. COUNTER_COMP_SIGNAL_U8("filter_clock_prescaler",
  810. quad8_signal_fck_prescaler_read,
  811. quad8_signal_fck_prescaler_write)
  812. };
  813. static const enum counter_signal_polarity quad8_polarities[] = {
  814. COUNTER_SIGNAL_POLARITY_POSITIVE,
  815. COUNTER_SIGNAL_POLARITY_NEGATIVE,
  816. };
  817. static DEFINE_COUNTER_AVAILABLE(quad8_polarity_available, quad8_polarities);
  818. static DEFINE_COUNTER_ENUM(quad8_index_pol_enum, quad8_index_polarity_modes);
  819. static DEFINE_COUNTER_ENUM(quad8_synch_mode_enum, quad8_synchronous_modes);
  820. static struct counter_comp quad8_index_ext[] = {
  821. COUNTER_COMP_SIGNAL_ENUM("index_polarity", quad8_index_polarity_get,
  822. quad8_index_polarity_set,
  823. quad8_index_pol_enum),
  824. COUNTER_COMP_POLARITY(quad8_polarity_read, quad8_polarity_write,
  825. quad8_polarity_available),
  826. COUNTER_COMP_SIGNAL_ENUM("synchronous_mode", quad8_synchronous_mode_get,
  827. quad8_synchronous_mode_set,
  828. quad8_synch_mode_enum),
  829. };
  830. #define QUAD8_QUAD_SIGNAL(_id, _name) { \
  831. .id = (_id), \
  832. .name = (_name), \
  833. .ext = quad8_signal_ext, \
  834. .num_ext = ARRAY_SIZE(quad8_signal_ext) \
  835. }
  836. #define QUAD8_INDEX_SIGNAL(_id, _name) { \
  837. .id = (_id), \
  838. .name = (_name), \
  839. .ext = quad8_index_ext, \
  840. .num_ext = ARRAY_SIZE(quad8_index_ext) \
  841. }
  842. static struct counter_signal quad8_signals[] = {
  843. QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
  844. QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
  845. QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
  846. QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
  847. QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
  848. QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
  849. QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
  850. QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
  851. QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
  852. QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
  853. QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
  854. QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
  855. QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
  856. QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
  857. QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
  858. QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
  859. QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
  860. QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
  861. QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
  862. QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
  863. QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
  864. QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
  865. QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
  866. QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
  867. };
  868. #define QUAD8_COUNT_SYNAPSES(_id) { \
  869. { \
  870. .actions_list = quad8_synapse_actions_list, \
  871. .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
  872. .signal = quad8_signals + 2 * (_id) \
  873. }, \
  874. { \
  875. .actions_list = quad8_synapse_actions_list, \
  876. .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
  877. .signal = quad8_signals + 2 * (_id) + 1 \
  878. }, \
  879. { \
  880. .actions_list = quad8_index_actions_list, \
  881. .num_actions = ARRAY_SIZE(quad8_index_actions_list), \
  882. .signal = quad8_signals + 2 * (_id) + 16 \
  883. } \
  884. }
  885. static struct counter_synapse quad8_count_synapses[][3] = {
  886. QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
  887. QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
  888. QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
  889. QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
  890. };
  891. static const enum counter_count_mode quad8_cnt_modes[] = {
  892. COUNTER_COUNT_MODE_NORMAL,
  893. COUNTER_COUNT_MODE_RANGE_LIMIT,
  894. COUNTER_COUNT_MODE_NON_RECYCLE,
  895. COUNTER_COUNT_MODE_MODULO_N,
  896. };
  897. static DEFINE_COUNTER_AVAILABLE(quad8_count_mode_available, quad8_cnt_modes);
  898. static DEFINE_COUNTER_ENUM(quad8_error_noise_enum, quad8_noise_error_states);
  899. static struct counter_comp quad8_count_ext[] = {
  900. COUNTER_COMP_CEILING(quad8_count_ceiling_read,
  901. quad8_count_ceiling_write),
  902. COUNTER_COMP_FLOOR(quad8_count_floor_read, NULL),
  903. COUNTER_COMP_COUNT_MODE(quad8_count_mode_read, quad8_count_mode_write,
  904. quad8_count_mode_available),
  905. COUNTER_COMP_DIRECTION(quad8_direction_read),
  906. COUNTER_COMP_ENABLE(quad8_count_enable_read, quad8_count_enable_write),
  907. COUNTER_COMP_COUNT_ENUM("error_noise", quad8_error_noise_get, NULL,
  908. quad8_error_noise_enum),
  909. COUNTER_COMP_PRESET(quad8_count_preset_read, quad8_count_preset_write),
  910. COUNTER_COMP_PRESET_ENABLE(quad8_count_preset_enable_read,
  911. quad8_count_preset_enable_write),
  912. };
  913. #define QUAD8_COUNT(_id, _cntname) { \
  914. .id = (_id), \
  915. .name = (_cntname), \
  916. .functions_list = quad8_count_functions_list, \
  917. .num_functions = ARRAY_SIZE(quad8_count_functions_list), \
  918. .synapses = quad8_count_synapses[(_id)], \
  919. .num_synapses = 2, \
  920. .ext = quad8_count_ext, \
  921. .num_ext = ARRAY_SIZE(quad8_count_ext) \
  922. }
  923. static struct counter_count quad8_counts[] = {
  924. QUAD8_COUNT(0, "Channel 1 Count"),
  925. QUAD8_COUNT(1, "Channel 2 Count"),
  926. QUAD8_COUNT(2, "Channel 3 Count"),
  927. QUAD8_COUNT(3, "Channel 4 Count"),
  928. QUAD8_COUNT(4, "Channel 5 Count"),
  929. QUAD8_COUNT(5, "Channel 6 Count"),
  930. QUAD8_COUNT(6, "Channel 7 Count"),
  931. QUAD8_COUNT(7, "Channel 8 Count")
  932. };
  933. static irqreturn_t quad8_irq_handler(int irq, void *private)
  934. {
  935. struct counter_device *counter = private;
  936. struct quad8 *const priv = counter_priv(counter);
  937. unsigned long irq_status;
  938. unsigned long channel;
  939. u8 event;
  940. irq_status = ioread8(&priv->reg->interrupt_status);
  941. if (!irq_status)
  942. return IRQ_NONE;
  943. for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) {
  944. switch (priv->irq_trigger[channel]) {
  945. case QUAD8_EVENT_CARRY:
  946. event = COUNTER_EVENT_OVERFLOW;
  947. break;
  948. case QUAD8_EVENT_COMPARE:
  949. event = COUNTER_EVENT_THRESHOLD;
  950. break;
  951. case QUAD8_EVENT_CARRY_BORROW:
  952. event = COUNTER_EVENT_OVERFLOW_UNDERFLOW;
  953. break;
  954. case QUAD8_EVENT_INDEX:
  955. event = COUNTER_EVENT_INDEX;
  956. break;
  957. default:
  958. /* should never reach this path */
  959. WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n",
  960. priv->irq_trigger[channel], channel);
  961. continue;
  962. }
  963. counter_push_event(counter, event, channel);
  964. }
  965. /* Clear pending interrupts on device */
  966. iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
  967. return IRQ_HANDLED;
  968. }
  969. static void quad8_init_counter(struct channel_reg __iomem *const chan)
  970. {
  971. unsigned long i;
  972. /* Reset Byte Pointer */
  973. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  974. /* Reset filter clock factor */
  975. iowrite8(0, &chan->data);
  976. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
  977. &chan->control);
  978. /* Reset Byte Pointer */
  979. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
  980. /* Reset Preset Register */
  981. for (i = 0; i < 3; i++)
  982. iowrite8(0x00, &chan->data);
  983. /* Reset Borrow, Carry, Compare, and Sign flags */
  984. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
  985. /* Reset Error flag */
  986. iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
  987. /* Binary encoding; Normal count; non-quadrature mode */
  988. iowrite8(QUAD8_CTR_CMR, &chan->control);
  989. /* Disable A and B inputs; preset on index; FLG1 as Carry */
  990. iowrite8(QUAD8_CTR_IOR, &chan->control);
  991. /* Disable index function; negative index polarity */
  992. iowrite8(QUAD8_CTR_IDR, &chan->control);
  993. }
  994. static int quad8_probe(struct device *dev, unsigned int id)
  995. {
  996. struct counter_device *counter;
  997. struct quad8 *priv;
  998. unsigned long i;
  999. int err;
  1000. if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
  1001. dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
  1002. base[id], base[id] + QUAD8_EXTENT);
  1003. return -EBUSY;
  1004. }
  1005. counter = devm_counter_alloc(dev, sizeof(*priv));
  1006. if (!counter)
  1007. return -ENOMEM;
  1008. priv = counter_priv(counter);
  1009. priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
  1010. if (!priv->reg)
  1011. return -ENOMEM;
  1012. /* Initialize Counter device and driver data */
  1013. counter->name = dev_name(dev);
  1014. counter->parent = dev;
  1015. counter->ops = &quad8_ops;
  1016. counter->counts = quad8_counts;
  1017. counter->num_counts = ARRAY_SIZE(quad8_counts);
  1018. counter->signals = quad8_signals;
  1019. counter->num_signals = ARRAY_SIZE(quad8_signals);
  1020. spin_lock_init(&priv->lock);
  1021. /* Reset Index/Interrupt Register */
  1022. iowrite8(0x00, &priv->reg->index_interrupt);
  1023. /* Reset all counters and disable interrupt function */
  1024. iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
  1025. /* Set initial configuration for all counters */
  1026. for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
  1027. quad8_init_counter(priv->reg->channel + i);
  1028. /* Disable Differential Encoder Cable Status for all channels */
  1029. iowrite8(0xFF, &priv->reg->cable_status);
  1030. /* Enable all counters and enable interrupt function */
  1031. iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
  1032. err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
  1033. IRQF_SHARED, counter->name, counter);
  1034. if (err)
  1035. return err;
  1036. err = devm_counter_add(dev, counter);
  1037. if (err < 0)
  1038. return dev_err_probe(dev, err, "Failed to add counter\n");
  1039. return 0;
  1040. }
  1041. static struct isa_driver quad8_driver = {
  1042. .probe = quad8_probe,
  1043. .driver = {
  1044. .name = "104-quad-8"
  1045. }
  1046. };
  1047. module_isa_driver_with_irq(quad8_driver, num_quad8, num_irq);
  1048. MODULE_AUTHOR("William Breathitt Gray <[email protected]>");
  1049. MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");
  1050. MODULE_LICENSE("GPL v2");
  1051. MODULE_IMPORT_NS(COUNTER);