104-quad-8.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  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/iio/iio.h>
  13. #include <linux/iio/types.h>
  14. #include <linux/io.h>
  15. #include <linux/ioport.h>
  16. #include <linux/isa.h>
  17. #include <linux/kernel.h>
  18. #include <linux/module.h>
  19. #include <linux/moduleparam.h>
  20. #include <linux/types.h>
  21. #define QUAD8_EXTENT 32
  22. static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
  23. static unsigned int num_quad8;
  24. module_param_array(base, uint, &num_quad8, 0);
  25. MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
  26. #define QUAD8_NUM_COUNTERS 8
  27. /**
  28. * struct quad8_iio - IIO device private data structure
  29. * @counter: instance of the counter_device
  30. * @preset: array of preset values
  31. * @count_mode: array of count mode configurations
  32. * @quadrature_mode: array of quadrature mode configurations
  33. * @quadrature_scale: array of quadrature mode scale configurations
  34. * @ab_enable: array of A and B inputs enable configurations
  35. * @preset_enable: array of set_to_preset_on_index attribute configurations
  36. * @synchronous_mode: array of index function synchronous mode configurations
  37. * @index_polarity: array of index function polarity configurations
  38. * @base: base port address of the IIO device
  39. */
  40. struct quad8_iio {
  41. struct mutex lock;
  42. struct counter_device counter;
  43. unsigned int preset[QUAD8_NUM_COUNTERS];
  44. unsigned int count_mode[QUAD8_NUM_COUNTERS];
  45. unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
  46. unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
  47. unsigned int ab_enable[QUAD8_NUM_COUNTERS];
  48. unsigned int preset_enable[QUAD8_NUM_COUNTERS];
  49. unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
  50. unsigned int index_polarity[QUAD8_NUM_COUNTERS];
  51. unsigned int base;
  52. };
  53. #define QUAD8_REG_CHAN_OP 0x11
  54. #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
  55. /* Borrow Toggle flip-flop */
  56. #define QUAD8_FLAG_BT BIT(0)
  57. /* Carry Toggle flip-flop */
  58. #define QUAD8_FLAG_CT BIT(1)
  59. /* Error flag */
  60. #define QUAD8_FLAG_E BIT(4)
  61. /* Up/Down flag */
  62. #define QUAD8_FLAG_UD BIT(5)
  63. /* Reset and Load Signal Decoders */
  64. #define QUAD8_CTR_RLD 0x00
  65. /* Counter Mode Register */
  66. #define QUAD8_CTR_CMR 0x20
  67. /* Input / Output Control Register */
  68. #define QUAD8_CTR_IOR 0x40
  69. /* Index Control Register */
  70. #define QUAD8_CTR_IDR 0x60
  71. /* Reset Byte Pointer (three byte data pointer) */
  72. #define QUAD8_RLD_RESET_BP 0x01
  73. /* Reset Counter */
  74. #define QUAD8_RLD_RESET_CNTR 0x02
  75. /* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */
  76. #define QUAD8_RLD_RESET_FLAGS 0x04
  77. /* Reset Error flag */
  78. #define QUAD8_RLD_RESET_E 0x06
  79. /* Preset Register to Counter */
  80. #define QUAD8_RLD_PRESET_CNTR 0x08
  81. /* Transfer Counter to Output Latch */
  82. #define QUAD8_RLD_CNTR_OUT 0x10
  83. #define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00
  84. #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
  85. #define QUAD8_CMR_QUADRATURE_X1 0x08
  86. #define QUAD8_CMR_QUADRATURE_X2 0x10
  87. #define QUAD8_CMR_QUADRATURE_X4 0x18
  88. static int quad8_read_raw(struct iio_dev *indio_dev,
  89. struct iio_chan_spec const *chan, int *val, int *val2, long mask)
  90. {
  91. struct quad8_iio *const priv = iio_priv(indio_dev);
  92. const int base_offset = priv->base + 2 * chan->channel;
  93. unsigned int flags;
  94. unsigned int borrow;
  95. unsigned int carry;
  96. int i;
  97. switch (mask) {
  98. case IIO_CHAN_INFO_RAW:
  99. if (chan->type == IIO_INDEX) {
  100. *val = !!(inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
  101. & BIT(chan->channel));
  102. return IIO_VAL_INT;
  103. }
  104. flags = inb(base_offset + 1);
  105. borrow = flags & QUAD8_FLAG_BT;
  106. carry = !!(flags & QUAD8_FLAG_CT);
  107. /* Borrow XOR Carry effectively doubles count range */
  108. *val = (borrow ^ carry) << 24;
  109. mutex_lock(&priv->lock);
  110. /* Reset Byte Pointer; transfer Counter to Output Latch */
  111. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
  112. base_offset + 1);
  113. for (i = 0; i < 3; i++)
  114. *val |= (unsigned int)inb(base_offset) << (8 * i);
  115. mutex_unlock(&priv->lock);
  116. return IIO_VAL_INT;
  117. case IIO_CHAN_INFO_ENABLE:
  118. *val = priv->ab_enable[chan->channel];
  119. return IIO_VAL_INT;
  120. case IIO_CHAN_INFO_SCALE:
  121. *val = 1;
  122. *val2 = priv->quadrature_scale[chan->channel];
  123. return IIO_VAL_FRACTIONAL_LOG2;
  124. }
  125. return -EINVAL;
  126. }
  127. static int quad8_write_raw(struct iio_dev *indio_dev,
  128. struct iio_chan_spec const *chan, int val, int val2, long mask)
  129. {
  130. struct quad8_iio *const priv = iio_priv(indio_dev);
  131. const int base_offset = priv->base + 2 * chan->channel;
  132. int i;
  133. unsigned int ior_cfg;
  134. switch (mask) {
  135. case IIO_CHAN_INFO_RAW:
  136. if (chan->type == IIO_INDEX)
  137. return -EINVAL;
  138. /* Only 24-bit values are supported */
  139. if ((unsigned int)val > 0xFFFFFF)
  140. return -EINVAL;
  141. mutex_lock(&priv->lock);
  142. /* Reset Byte Pointer */
  143. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  144. /* Counter can only be set via Preset Register */
  145. for (i = 0; i < 3; i++)
  146. outb(val >> (8 * i), base_offset);
  147. /* Transfer Preset Register to Counter */
  148. outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
  149. /* Reset Byte Pointer */
  150. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  151. /* Set Preset Register back to original value */
  152. val = priv->preset[chan->channel];
  153. for (i = 0; i < 3; i++)
  154. outb(val >> (8 * i), base_offset);
  155. /* Reset Borrow, Carry, Compare, and Sign flags */
  156. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
  157. /* Reset Error flag */
  158. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
  159. mutex_unlock(&priv->lock);
  160. return 0;
  161. case IIO_CHAN_INFO_ENABLE:
  162. /* only boolean values accepted */
  163. if (val < 0 || val > 1)
  164. return -EINVAL;
  165. mutex_lock(&priv->lock);
  166. priv->ab_enable[chan->channel] = val;
  167. ior_cfg = val | priv->preset_enable[chan->channel] << 1;
  168. /* Load I/O control configuration */
  169. outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
  170. mutex_unlock(&priv->lock);
  171. return 0;
  172. case IIO_CHAN_INFO_SCALE:
  173. mutex_lock(&priv->lock);
  174. /* Quadrature scaling only available in quadrature mode */
  175. if (!priv->quadrature_mode[chan->channel] &&
  176. (val2 || val != 1)) {
  177. mutex_unlock(&priv->lock);
  178. return -EINVAL;
  179. }
  180. /* Only three gain states (1, 0.5, 0.25) */
  181. if (val == 1 && !val2)
  182. priv->quadrature_scale[chan->channel] = 0;
  183. else if (!val)
  184. switch (val2) {
  185. case 500000:
  186. priv->quadrature_scale[chan->channel] = 1;
  187. break;
  188. case 250000:
  189. priv->quadrature_scale[chan->channel] = 2;
  190. break;
  191. default:
  192. mutex_unlock(&priv->lock);
  193. return -EINVAL;
  194. }
  195. else {
  196. mutex_unlock(&priv->lock);
  197. return -EINVAL;
  198. }
  199. mutex_unlock(&priv->lock);
  200. return 0;
  201. }
  202. return -EINVAL;
  203. }
  204. static const struct iio_info quad8_info = {
  205. .read_raw = quad8_read_raw,
  206. .write_raw = quad8_write_raw
  207. };
  208. static ssize_t quad8_read_preset(struct iio_dev *indio_dev, uintptr_t private,
  209. const struct iio_chan_spec *chan, char *buf)
  210. {
  211. const struct quad8_iio *const priv = iio_priv(indio_dev);
  212. return snprintf(buf, PAGE_SIZE, "%u\n", priv->preset[chan->channel]);
  213. }
  214. static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
  215. const struct iio_chan_spec *chan, const char *buf, size_t len)
  216. {
  217. struct quad8_iio *const priv = iio_priv(indio_dev);
  218. const int base_offset = priv->base + 2 * chan->channel;
  219. unsigned int preset;
  220. int ret;
  221. int i;
  222. ret = kstrtouint(buf, 0, &preset);
  223. if (ret)
  224. return ret;
  225. /* Only 24-bit values are supported */
  226. if (preset > 0xFFFFFF)
  227. return -EINVAL;
  228. mutex_lock(&priv->lock);
  229. priv->preset[chan->channel] = preset;
  230. /* Reset Byte Pointer */
  231. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  232. /* Set Preset Register */
  233. for (i = 0; i < 3; i++)
  234. outb(preset >> (8 * i), base_offset);
  235. mutex_unlock(&priv->lock);
  236. return len;
  237. }
  238. static ssize_t quad8_read_set_to_preset_on_index(struct iio_dev *indio_dev,
  239. uintptr_t private, const struct iio_chan_spec *chan, char *buf)
  240. {
  241. const struct quad8_iio *const priv = iio_priv(indio_dev);
  242. return snprintf(buf, PAGE_SIZE, "%u\n",
  243. !priv->preset_enable[chan->channel]);
  244. }
  245. static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
  246. uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
  247. size_t len)
  248. {
  249. struct quad8_iio *const priv = iio_priv(indio_dev);
  250. const int base_offset = priv->base + 2 * chan->channel + 1;
  251. bool preset_enable;
  252. int ret;
  253. unsigned int ior_cfg;
  254. ret = kstrtobool(buf, &preset_enable);
  255. if (ret)
  256. return ret;
  257. /* Preset enable is active low in Input/Output Control register */
  258. preset_enable = !preset_enable;
  259. mutex_lock(&priv->lock);
  260. priv->preset_enable[chan->channel] = preset_enable;
  261. ior_cfg = priv->ab_enable[chan->channel] |
  262. (unsigned int)preset_enable << 1;
  263. /* Load I/O control configuration to Input / Output Control Register */
  264. outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
  265. mutex_unlock(&priv->lock);
  266. return len;
  267. }
  268. static const char *const quad8_noise_error_states[] = {
  269. "No excessive noise is present at the count inputs",
  270. "Excessive noise is present at the count inputs"
  271. };
  272. static int quad8_get_noise_error(struct iio_dev *indio_dev,
  273. const struct iio_chan_spec *chan)
  274. {
  275. struct quad8_iio *const priv = iio_priv(indio_dev);
  276. const int base_offset = priv->base + 2 * chan->channel + 1;
  277. return !!(inb(base_offset) & QUAD8_FLAG_E);
  278. }
  279. static const struct iio_enum quad8_noise_error_enum = {
  280. .items = quad8_noise_error_states,
  281. .num_items = ARRAY_SIZE(quad8_noise_error_states),
  282. .get = quad8_get_noise_error
  283. };
  284. static const char *const quad8_count_direction_states[] = {
  285. "down",
  286. "up"
  287. };
  288. static int quad8_get_count_direction(struct iio_dev *indio_dev,
  289. const struct iio_chan_spec *chan)
  290. {
  291. struct quad8_iio *const priv = iio_priv(indio_dev);
  292. const int base_offset = priv->base + 2 * chan->channel + 1;
  293. return !!(inb(base_offset) & QUAD8_FLAG_UD);
  294. }
  295. static const struct iio_enum quad8_count_direction_enum = {
  296. .items = quad8_count_direction_states,
  297. .num_items = ARRAY_SIZE(quad8_count_direction_states),
  298. .get = quad8_get_count_direction
  299. };
  300. static const char *const quad8_count_modes[] = {
  301. "normal",
  302. "range limit",
  303. "non-recycle",
  304. "modulo-n"
  305. };
  306. static int quad8_set_count_mode(struct iio_dev *indio_dev,
  307. const struct iio_chan_spec *chan, unsigned int cnt_mode)
  308. {
  309. struct quad8_iio *const priv = iio_priv(indio_dev);
  310. unsigned int mode_cfg = cnt_mode << 1;
  311. const int base_offset = priv->base + 2 * chan->channel + 1;
  312. mutex_lock(&priv->lock);
  313. priv->count_mode[chan->channel] = cnt_mode;
  314. /* Add quadrature mode configuration */
  315. if (priv->quadrature_mode[chan->channel])
  316. mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
  317. /* Load mode configuration to Counter Mode Register */
  318. outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
  319. mutex_unlock(&priv->lock);
  320. return 0;
  321. }
  322. static int quad8_get_count_mode(struct iio_dev *indio_dev,
  323. const struct iio_chan_spec *chan)
  324. {
  325. const struct quad8_iio *const priv = iio_priv(indio_dev);
  326. return priv->count_mode[chan->channel];
  327. }
  328. static const struct iio_enum quad8_count_mode_enum = {
  329. .items = quad8_count_modes,
  330. .num_items = ARRAY_SIZE(quad8_count_modes),
  331. .set = quad8_set_count_mode,
  332. .get = quad8_get_count_mode
  333. };
  334. static const char *const quad8_synchronous_modes[] = {
  335. "non-synchronous",
  336. "synchronous"
  337. };
  338. static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
  339. const struct iio_chan_spec *chan, unsigned int synchronous_mode)
  340. {
  341. struct quad8_iio *const priv = iio_priv(indio_dev);
  342. const int base_offset = priv->base + 2 * chan->channel + 1;
  343. unsigned int idr_cfg = synchronous_mode;
  344. mutex_lock(&priv->lock);
  345. idr_cfg |= priv->index_polarity[chan->channel] << 1;
  346. /* Index function must be non-synchronous in non-quadrature mode */
  347. if (synchronous_mode && !priv->quadrature_mode[chan->channel]) {
  348. mutex_unlock(&priv->lock);
  349. return -EINVAL;
  350. }
  351. priv->synchronous_mode[chan->channel] = synchronous_mode;
  352. /* Load Index Control configuration to Index Control Register */
  353. outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
  354. mutex_unlock(&priv->lock);
  355. return 0;
  356. }
  357. static int quad8_get_synchronous_mode(struct iio_dev *indio_dev,
  358. const struct iio_chan_spec *chan)
  359. {
  360. const struct quad8_iio *const priv = iio_priv(indio_dev);
  361. return priv->synchronous_mode[chan->channel];
  362. }
  363. static const struct iio_enum quad8_synchronous_mode_enum = {
  364. .items = quad8_synchronous_modes,
  365. .num_items = ARRAY_SIZE(quad8_synchronous_modes),
  366. .set = quad8_set_synchronous_mode,
  367. .get = quad8_get_synchronous_mode
  368. };
  369. static const char *const quad8_quadrature_modes[] = {
  370. "non-quadrature",
  371. "quadrature"
  372. };
  373. static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
  374. const struct iio_chan_spec *chan, unsigned int quadrature_mode)
  375. {
  376. struct quad8_iio *const priv = iio_priv(indio_dev);
  377. const int base_offset = priv->base + 2 * chan->channel + 1;
  378. unsigned int mode_cfg;
  379. mutex_lock(&priv->lock);
  380. mode_cfg = priv->count_mode[chan->channel] << 1;
  381. if (quadrature_mode)
  382. mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
  383. else {
  384. /* Quadrature scaling only available in quadrature mode */
  385. priv->quadrature_scale[chan->channel] = 0;
  386. /* Synchronous function not supported in non-quadrature mode */
  387. if (priv->synchronous_mode[chan->channel])
  388. quad8_set_synchronous_mode(indio_dev, chan, 0);
  389. }
  390. priv->quadrature_mode[chan->channel] = quadrature_mode;
  391. /* Load mode configuration to Counter Mode Register */
  392. outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
  393. mutex_unlock(&priv->lock);
  394. return 0;
  395. }
  396. static int quad8_get_quadrature_mode(struct iio_dev *indio_dev,
  397. const struct iio_chan_spec *chan)
  398. {
  399. const struct quad8_iio *const priv = iio_priv(indio_dev);
  400. return priv->quadrature_mode[chan->channel];
  401. }
  402. static const struct iio_enum quad8_quadrature_mode_enum = {
  403. .items = quad8_quadrature_modes,
  404. .num_items = ARRAY_SIZE(quad8_quadrature_modes),
  405. .set = quad8_set_quadrature_mode,
  406. .get = quad8_get_quadrature_mode
  407. };
  408. static const char *const quad8_index_polarity_modes[] = {
  409. "negative",
  410. "positive"
  411. };
  412. static int quad8_set_index_polarity(struct iio_dev *indio_dev,
  413. const struct iio_chan_spec *chan, unsigned int index_polarity)
  414. {
  415. struct quad8_iio *const priv = iio_priv(indio_dev);
  416. const int base_offset = priv->base + 2 * chan->channel + 1;
  417. unsigned int idr_cfg = index_polarity << 1;
  418. mutex_lock(&priv->lock);
  419. idr_cfg |= priv->synchronous_mode[chan->channel];
  420. priv->index_polarity[chan->channel] = index_polarity;
  421. /* Load Index Control configuration to Index Control Register */
  422. outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
  423. mutex_unlock(&priv->lock);
  424. return 0;
  425. }
  426. static int quad8_get_index_polarity(struct iio_dev *indio_dev,
  427. const struct iio_chan_spec *chan)
  428. {
  429. const struct quad8_iio *const priv = iio_priv(indio_dev);
  430. return priv->index_polarity[chan->channel];
  431. }
  432. static const struct iio_enum quad8_index_polarity_enum = {
  433. .items = quad8_index_polarity_modes,
  434. .num_items = ARRAY_SIZE(quad8_index_polarity_modes),
  435. .set = quad8_set_index_polarity,
  436. .get = quad8_get_index_polarity
  437. };
  438. static const struct iio_chan_spec_ext_info quad8_count_ext_info[] = {
  439. {
  440. .name = "preset",
  441. .shared = IIO_SEPARATE,
  442. .read = quad8_read_preset,
  443. .write = quad8_write_preset
  444. },
  445. {
  446. .name = "set_to_preset_on_index",
  447. .shared = IIO_SEPARATE,
  448. .read = quad8_read_set_to_preset_on_index,
  449. .write = quad8_write_set_to_preset_on_index
  450. },
  451. IIO_ENUM("noise_error", IIO_SEPARATE, &quad8_noise_error_enum),
  452. IIO_ENUM_AVAILABLE("noise_error", &quad8_noise_error_enum),
  453. IIO_ENUM("count_direction", IIO_SEPARATE, &quad8_count_direction_enum),
  454. IIO_ENUM_AVAILABLE("count_direction", &quad8_count_direction_enum),
  455. IIO_ENUM("count_mode", IIO_SEPARATE, &quad8_count_mode_enum),
  456. IIO_ENUM_AVAILABLE("count_mode", &quad8_count_mode_enum),
  457. IIO_ENUM("quadrature_mode", IIO_SEPARATE, &quad8_quadrature_mode_enum),
  458. IIO_ENUM_AVAILABLE("quadrature_mode", &quad8_quadrature_mode_enum),
  459. {}
  460. };
  461. static const struct iio_chan_spec_ext_info quad8_index_ext_info[] = {
  462. IIO_ENUM("synchronous_mode", IIO_SEPARATE,
  463. &quad8_synchronous_mode_enum),
  464. IIO_ENUM_AVAILABLE("synchronous_mode", &quad8_synchronous_mode_enum),
  465. IIO_ENUM("index_polarity", IIO_SEPARATE, &quad8_index_polarity_enum),
  466. IIO_ENUM_AVAILABLE("index_polarity", &quad8_index_polarity_enum),
  467. {}
  468. };
  469. #define QUAD8_COUNT_CHAN(_chan) { \
  470. .type = IIO_COUNT, \
  471. .channel = (_chan), \
  472. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
  473. BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_SCALE), \
  474. .ext_info = quad8_count_ext_info, \
  475. .indexed = 1 \
  476. }
  477. #define QUAD8_INDEX_CHAN(_chan) { \
  478. .type = IIO_INDEX, \
  479. .channel = (_chan), \
  480. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  481. .ext_info = quad8_index_ext_info, \
  482. .indexed = 1 \
  483. }
  484. static const struct iio_chan_spec quad8_channels[] = {
  485. QUAD8_COUNT_CHAN(0), QUAD8_INDEX_CHAN(0),
  486. QUAD8_COUNT_CHAN(1), QUAD8_INDEX_CHAN(1),
  487. QUAD8_COUNT_CHAN(2), QUAD8_INDEX_CHAN(2),
  488. QUAD8_COUNT_CHAN(3), QUAD8_INDEX_CHAN(3),
  489. QUAD8_COUNT_CHAN(4), QUAD8_INDEX_CHAN(4),
  490. QUAD8_COUNT_CHAN(5), QUAD8_INDEX_CHAN(5),
  491. QUAD8_COUNT_CHAN(6), QUAD8_INDEX_CHAN(6),
  492. QUAD8_COUNT_CHAN(7), QUAD8_INDEX_CHAN(7)
  493. };
  494. static int quad8_signal_read(struct counter_device *counter,
  495. struct counter_signal *signal, struct counter_signal_read_value *val)
  496. {
  497. const struct quad8_iio *const priv = counter->priv;
  498. unsigned int state;
  499. enum counter_signal_level level;
  500. /* Only Index signal levels can be read */
  501. if (signal->id < 16)
  502. return -EINVAL;
  503. state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
  504. & BIT(signal->id - 16);
  505. level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
  506. counter_signal_read_value_set(val, COUNTER_SIGNAL_LEVEL, &level);
  507. return 0;
  508. }
  509. static int quad8_count_read(struct counter_device *counter,
  510. struct counter_count *count, struct counter_count_read_value *val)
  511. {
  512. struct quad8_iio *const priv = counter->priv;
  513. const int base_offset = priv->base + 2 * count->id;
  514. unsigned int flags;
  515. unsigned int borrow;
  516. unsigned int carry;
  517. unsigned long position;
  518. int i;
  519. flags = inb(base_offset + 1);
  520. borrow = flags & QUAD8_FLAG_BT;
  521. carry = !!(flags & QUAD8_FLAG_CT);
  522. /* Borrow XOR Carry effectively doubles count range */
  523. position = (unsigned long)(borrow ^ carry) << 24;
  524. mutex_lock(&priv->lock);
  525. /* Reset Byte Pointer; transfer Counter to Output Latch */
  526. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
  527. base_offset + 1);
  528. for (i = 0; i < 3; i++)
  529. position |= (unsigned long)inb(base_offset) << (8 * i);
  530. counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &position);
  531. mutex_unlock(&priv->lock);
  532. return 0;
  533. }
  534. static int quad8_count_write(struct counter_device *counter,
  535. struct counter_count *count, struct counter_count_write_value *val)
  536. {
  537. struct quad8_iio *const priv = counter->priv;
  538. const int base_offset = priv->base + 2 * count->id;
  539. int err;
  540. unsigned long position;
  541. int i;
  542. err = counter_count_write_value_get(&position, COUNTER_COUNT_POSITION,
  543. val);
  544. if (err)
  545. return err;
  546. /* Only 24-bit values are supported */
  547. if (position > 0xFFFFFF)
  548. return -EINVAL;
  549. mutex_lock(&priv->lock);
  550. /* Reset Byte Pointer */
  551. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  552. /* Counter can only be set via Preset Register */
  553. for (i = 0; i < 3; i++)
  554. outb(position >> (8 * i), base_offset);
  555. /* Transfer Preset Register to Counter */
  556. outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
  557. /* Reset Byte Pointer */
  558. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  559. /* Set Preset Register back to original value */
  560. position = priv->preset[count->id];
  561. for (i = 0; i < 3; i++)
  562. outb(position >> (8 * i), base_offset);
  563. /* Reset Borrow, Carry, Compare, and Sign flags */
  564. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
  565. /* Reset Error flag */
  566. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
  567. mutex_unlock(&priv->lock);
  568. return 0;
  569. }
  570. enum quad8_count_function {
  571. QUAD8_COUNT_FUNCTION_PULSE_DIRECTION = 0,
  572. QUAD8_COUNT_FUNCTION_QUADRATURE_X1,
  573. QUAD8_COUNT_FUNCTION_QUADRATURE_X2,
  574. QUAD8_COUNT_FUNCTION_QUADRATURE_X4
  575. };
  576. static enum counter_count_function quad8_count_functions_list[] = {
  577. [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
  578. [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A,
  579. [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
  580. [QUAD8_COUNT_FUNCTION_QUADRATURE_X4] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4
  581. };
  582. static int quad8_function_get(struct counter_device *counter,
  583. struct counter_count *count, size_t *function)
  584. {
  585. struct quad8_iio *const priv = counter->priv;
  586. const int id = count->id;
  587. mutex_lock(&priv->lock);
  588. if (priv->quadrature_mode[id])
  589. switch (priv->quadrature_scale[id]) {
  590. case 0:
  591. *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1;
  592. break;
  593. case 1:
  594. *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X2;
  595. break;
  596. case 2:
  597. *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X4;
  598. break;
  599. }
  600. else
  601. *function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION;
  602. mutex_unlock(&priv->lock);
  603. return 0;
  604. }
  605. static int quad8_function_set(struct counter_device *counter,
  606. struct counter_count *count, size_t function)
  607. {
  608. struct quad8_iio *const priv = counter->priv;
  609. const int id = count->id;
  610. unsigned int *const quadrature_mode = priv->quadrature_mode + id;
  611. unsigned int *const scale = priv->quadrature_scale + id;
  612. unsigned int *const synchronous_mode = priv->synchronous_mode + id;
  613. const int base_offset = priv->base + 2 * id + 1;
  614. unsigned int mode_cfg;
  615. unsigned int idr_cfg;
  616. mutex_lock(&priv->lock);
  617. mode_cfg = priv->count_mode[id] << 1;
  618. idr_cfg = priv->index_polarity[id] << 1;
  619. if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) {
  620. *quadrature_mode = 0;
  621. /* Quadrature scaling only available in quadrature mode */
  622. *scale = 0;
  623. /* Synchronous function not supported in non-quadrature mode */
  624. if (*synchronous_mode) {
  625. *synchronous_mode = 0;
  626. /* Disable synchronous function mode */
  627. outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
  628. }
  629. } else {
  630. *quadrature_mode = 1;
  631. switch (function) {
  632. case QUAD8_COUNT_FUNCTION_QUADRATURE_X1:
  633. *scale = 0;
  634. mode_cfg |= QUAD8_CMR_QUADRATURE_X1;
  635. break;
  636. case QUAD8_COUNT_FUNCTION_QUADRATURE_X2:
  637. *scale = 1;
  638. mode_cfg |= QUAD8_CMR_QUADRATURE_X2;
  639. break;
  640. case QUAD8_COUNT_FUNCTION_QUADRATURE_X4:
  641. *scale = 2;
  642. mode_cfg |= QUAD8_CMR_QUADRATURE_X4;
  643. break;
  644. }
  645. }
  646. /* Load mode configuration to Counter Mode Register */
  647. outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
  648. mutex_unlock(&priv->lock);
  649. return 0;
  650. }
  651. static void quad8_direction_get(struct counter_device *counter,
  652. struct counter_count *count, enum counter_count_direction *direction)
  653. {
  654. const struct quad8_iio *const priv = counter->priv;
  655. unsigned int ud_flag;
  656. const unsigned int flag_addr = priv->base + 2 * count->id + 1;
  657. /* U/D flag: nonzero = up, zero = down */
  658. ud_flag = inb(flag_addr) & QUAD8_FLAG_UD;
  659. *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
  660. COUNTER_COUNT_DIRECTION_BACKWARD;
  661. }
  662. enum quad8_synapse_action {
  663. QUAD8_SYNAPSE_ACTION_NONE = 0,
  664. QUAD8_SYNAPSE_ACTION_RISING_EDGE,
  665. QUAD8_SYNAPSE_ACTION_FALLING_EDGE,
  666. QUAD8_SYNAPSE_ACTION_BOTH_EDGES
  667. };
  668. static enum counter_synapse_action quad8_index_actions_list[] = {
  669. [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
  670. [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE
  671. };
  672. static enum counter_synapse_action quad8_synapse_actions_list[] = {
  673. [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
  674. [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE,
  675. [QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
  676. [QUAD8_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES
  677. };
  678. static int quad8_action_get(struct counter_device *counter,
  679. struct counter_count *count, struct counter_synapse *synapse,
  680. size_t *action)
  681. {
  682. struct quad8_iio *const priv = counter->priv;
  683. int err;
  684. size_t function = 0;
  685. const size_t signal_a_id = count->synapses[0].signal->id;
  686. enum counter_count_direction direction;
  687. /* Handle Index signals */
  688. if (synapse->signal->id >= 16) {
  689. if (priv->preset_enable[count->id])
  690. *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
  691. else
  692. *action = QUAD8_SYNAPSE_ACTION_NONE;
  693. return 0;
  694. }
  695. err = quad8_function_get(counter, count, &function);
  696. if (err)
  697. return err;
  698. /* Default action mode */
  699. *action = QUAD8_SYNAPSE_ACTION_NONE;
  700. /* Determine action mode based on current count function mode */
  701. switch (function) {
  702. case QUAD8_COUNT_FUNCTION_PULSE_DIRECTION:
  703. if (synapse->signal->id == signal_a_id)
  704. *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
  705. break;
  706. case QUAD8_COUNT_FUNCTION_QUADRATURE_X1:
  707. if (synapse->signal->id == signal_a_id) {
  708. quad8_direction_get(counter, count, &direction);
  709. if (direction == COUNTER_COUNT_DIRECTION_FORWARD)
  710. *action = QUAD8_SYNAPSE_ACTION_RISING_EDGE;
  711. else
  712. *action = QUAD8_SYNAPSE_ACTION_FALLING_EDGE;
  713. }
  714. break;
  715. case QUAD8_COUNT_FUNCTION_QUADRATURE_X2:
  716. if (synapse->signal->id == signal_a_id)
  717. *action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
  718. break;
  719. case QUAD8_COUNT_FUNCTION_QUADRATURE_X4:
  720. *action = QUAD8_SYNAPSE_ACTION_BOTH_EDGES;
  721. break;
  722. }
  723. return 0;
  724. }
  725. static const struct counter_ops quad8_ops = {
  726. .signal_read = quad8_signal_read,
  727. .count_read = quad8_count_read,
  728. .count_write = quad8_count_write,
  729. .function_get = quad8_function_get,
  730. .function_set = quad8_function_set,
  731. .action_get = quad8_action_get
  732. };
  733. static int quad8_index_polarity_get(struct counter_device *counter,
  734. struct counter_signal *signal, size_t *index_polarity)
  735. {
  736. const struct quad8_iio *const priv = counter->priv;
  737. const size_t channel_id = signal->id - 16;
  738. *index_polarity = priv->index_polarity[channel_id];
  739. return 0;
  740. }
  741. static int quad8_index_polarity_set(struct counter_device *counter,
  742. struct counter_signal *signal, size_t index_polarity)
  743. {
  744. struct quad8_iio *const priv = counter->priv;
  745. const size_t channel_id = signal->id - 16;
  746. const int base_offset = priv->base + 2 * channel_id + 1;
  747. unsigned int idr_cfg = index_polarity << 1;
  748. mutex_lock(&priv->lock);
  749. idr_cfg |= priv->synchronous_mode[channel_id];
  750. priv->index_polarity[channel_id] = index_polarity;
  751. /* Load Index Control configuration to Index Control Register */
  752. outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
  753. mutex_unlock(&priv->lock);
  754. return 0;
  755. }
  756. static struct counter_signal_enum_ext quad8_index_pol_enum = {
  757. .items = quad8_index_polarity_modes,
  758. .num_items = ARRAY_SIZE(quad8_index_polarity_modes),
  759. .get = quad8_index_polarity_get,
  760. .set = quad8_index_polarity_set
  761. };
  762. static int quad8_synchronous_mode_get(struct counter_device *counter,
  763. struct counter_signal *signal, size_t *synchronous_mode)
  764. {
  765. const struct quad8_iio *const priv = counter->priv;
  766. const size_t channel_id = signal->id - 16;
  767. *synchronous_mode = priv->synchronous_mode[channel_id];
  768. return 0;
  769. }
  770. static int quad8_synchronous_mode_set(struct counter_device *counter,
  771. struct counter_signal *signal, size_t synchronous_mode)
  772. {
  773. struct quad8_iio *const priv = counter->priv;
  774. const size_t channel_id = signal->id - 16;
  775. const int base_offset = priv->base + 2 * channel_id + 1;
  776. unsigned int idr_cfg = synchronous_mode;
  777. mutex_lock(&priv->lock);
  778. idr_cfg |= priv->index_polarity[channel_id] << 1;
  779. /* Index function must be non-synchronous in non-quadrature mode */
  780. if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
  781. mutex_unlock(&priv->lock);
  782. return -EINVAL;
  783. }
  784. priv->synchronous_mode[channel_id] = synchronous_mode;
  785. /* Load Index Control configuration to Index Control Register */
  786. outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
  787. mutex_unlock(&priv->lock);
  788. return 0;
  789. }
  790. static struct counter_signal_enum_ext quad8_syn_mode_enum = {
  791. .items = quad8_synchronous_modes,
  792. .num_items = ARRAY_SIZE(quad8_synchronous_modes),
  793. .get = quad8_synchronous_mode_get,
  794. .set = quad8_synchronous_mode_set
  795. };
  796. static ssize_t quad8_count_floor_read(struct counter_device *counter,
  797. struct counter_count *count, void *private, char *buf)
  798. {
  799. /* Only a floor of 0 is supported */
  800. return sprintf(buf, "0\n");
  801. }
  802. static int quad8_count_mode_get(struct counter_device *counter,
  803. struct counter_count *count, size_t *cnt_mode)
  804. {
  805. const struct quad8_iio *const priv = counter->priv;
  806. /* Map 104-QUAD-8 count mode to Generic Counter count mode */
  807. switch (priv->count_mode[count->id]) {
  808. case 0:
  809. *cnt_mode = COUNTER_COUNT_MODE_NORMAL;
  810. break;
  811. case 1:
  812. *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT;
  813. break;
  814. case 2:
  815. *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE;
  816. break;
  817. case 3:
  818. *cnt_mode = COUNTER_COUNT_MODE_MODULO_N;
  819. break;
  820. }
  821. return 0;
  822. }
  823. static int quad8_count_mode_set(struct counter_device *counter,
  824. struct counter_count *count, size_t cnt_mode)
  825. {
  826. struct quad8_iio *const priv = counter->priv;
  827. unsigned int mode_cfg;
  828. const int base_offset = priv->base + 2 * count->id + 1;
  829. /* Map Generic Counter count mode to 104-QUAD-8 count mode */
  830. switch (cnt_mode) {
  831. case COUNTER_COUNT_MODE_NORMAL:
  832. cnt_mode = 0;
  833. break;
  834. case COUNTER_COUNT_MODE_RANGE_LIMIT:
  835. cnt_mode = 1;
  836. break;
  837. case COUNTER_COUNT_MODE_NON_RECYCLE:
  838. cnt_mode = 2;
  839. break;
  840. case COUNTER_COUNT_MODE_MODULO_N:
  841. cnt_mode = 3;
  842. break;
  843. }
  844. mutex_lock(&priv->lock);
  845. priv->count_mode[count->id] = cnt_mode;
  846. /* Set count mode configuration value */
  847. mode_cfg = cnt_mode << 1;
  848. /* Add quadrature mode configuration */
  849. if (priv->quadrature_mode[count->id])
  850. mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
  851. /* Load mode configuration to Counter Mode Register */
  852. outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
  853. mutex_unlock(&priv->lock);
  854. return 0;
  855. }
  856. static struct counter_count_enum_ext quad8_cnt_mode_enum = {
  857. .items = counter_count_mode_str,
  858. .num_items = ARRAY_SIZE(counter_count_mode_str),
  859. .get = quad8_count_mode_get,
  860. .set = quad8_count_mode_set
  861. };
  862. static ssize_t quad8_count_direction_read(struct counter_device *counter,
  863. struct counter_count *count, void *priv, char *buf)
  864. {
  865. enum counter_count_direction dir;
  866. quad8_direction_get(counter, count, &dir);
  867. return sprintf(buf, "%s\n", counter_count_direction_str[dir]);
  868. }
  869. static ssize_t quad8_count_enable_read(struct counter_device *counter,
  870. struct counter_count *count, void *private, char *buf)
  871. {
  872. const struct quad8_iio *const priv = counter->priv;
  873. return sprintf(buf, "%u\n", priv->ab_enable[count->id]);
  874. }
  875. static ssize_t quad8_count_enable_write(struct counter_device *counter,
  876. struct counter_count *count, void *private, const char *buf, size_t len)
  877. {
  878. struct quad8_iio *const priv = counter->priv;
  879. const int base_offset = priv->base + 2 * count->id;
  880. int err;
  881. bool ab_enable;
  882. unsigned int ior_cfg;
  883. err = kstrtobool(buf, &ab_enable);
  884. if (err)
  885. return err;
  886. mutex_lock(&priv->lock);
  887. priv->ab_enable[count->id] = ab_enable;
  888. ior_cfg = ab_enable | priv->preset_enable[count->id] << 1;
  889. /* Load I/O control configuration */
  890. outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
  891. mutex_unlock(&priv->lock);
  892. return len;
  893. }
  894. static int quad8_error_noise_get(struct counter_device *counter,
  895. struct counter_count *count, size_t *noise_error)
  896. {
  897. const struct quad8_iio *const priv = counter->priv;
  898. const int base_offset = priv->base + 2 * count->id + 1;
  899. *noise_error = !!(inb(base_offset) & QUAD8_FLAG_E);
  900. return 0;
  901. }
  902. static struct counter_count_enum_ext quad8_error_noise_enum = {
  903. .items = quad8_noise_error_states,
  904. .num_items = ARRAY_SIZE(quad8_noise_error_states),
  905. .get = quad8_error_noise_get
  906. };
  907. static ssize_t quad8_count_preset_read(struct counter_device *counter,
  908. struct counter_count *count, void *private, char *buf)
  909. {
  910. const struct quad8_iio *const priv = counter->priv;
  911. return sprintf(buf, "%u\n", priv->preset[count->id]);
  912. }
  913. static void quad8_preset_register_set(struct quad8_iio *quad8iio, int id,
  914. unsigned int preset)
  915. {
  916. const unsigned int base_offset = quad8iio->base + 2 * id;
  917. int i;
  918. quad8iio->preset[id] = preset;
  919. /* Reset Byte Pointer */
  920. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  921. /* Set Preset Register */
  922. for (i = 0; i < 3; i++)
  923. outb(preset >> (8 * i), base_offset);
  924. }
  925. static ssize_t quad8_count_preset_write(struct counter_device *counter,
  926. struct counter_count *count, void *private, const char *buf, size_t len)
  927. {
  928. struct quad8_iio *const priv = counter->priv;
  929. unsigned int preset;
  930. int ret;
  931. ret = kstrtouint(buf, 0, &preset);
  932. if (ret)
  933. return ret;
  934. /* Only 24-bit values are supported */
  935. if (preset > 0xFFFFFF)
  936. return -EINVAL;
  937. mutex_lock(&priv->lock);
  938. quad8_preset_register_set(priv, count->id, preset);
  939. mutex_unlock(&priv->lock);
  940. return len;
  941. }
  942. static ssize_t quad8_count_ceiling_read(struct counter_device *counter,
  943. struct counter_count *count, void *private, char *buf)
  944. {
  945. struct quad8_iio *const priv = counter->priv;
  946. mutex_lock(&priv->lock);
  947. /* Range Limit and Modulo-N count modes use preset value as ceiling */
  948. switch (priv->count_mode[count->id]) {
  949. case 1:
  950. case 3:
  951. mutex_unlock(&priv->lock);
  952. return sprintf(buf, "%u\n", priv->preset[count->id]);
  953. }
  954. mutex_unlock(&priv->lock);
  955. /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
  956. return sprintf(buf, "33554431\n");
  957. }
  958. static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
  959. struct counter_count *count, void *private, const char *buf, size_t len)
  960. {
  961. struct quad8_iio *const priv = counter->priv;
  962. unsigned int ceiling;
  963. int ret;
  964. ret = kstrtouint(buf, 0, &ceiling);
  965. if (ret)
  966. return ret;
  967. /* Only 24-bit values are supported */
  968. if (ceiling > 0xFFFFFF)
  969. return -EINVAL;
  970. mutex_lock(&priv->lock);
  971. /* Range Limit and Modulo-N count modes use preset value as ceiling */
  972. switch (priv->count_mode[count->id]) {
  973. case 1:
  974. case 3:
  975. quad8_preset_register_set(priv, count->id, ceiling);
  976. mutex_unlock(&priv->lock);
  977. return len;
  978. }
  979. mutex_unlock(&priv->lock);
  980. return -EINVAL;
  981. }
  982. static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
  983. struct counter_count *count, void *private, char *buf)
  984. {
  985. const struct quad8_iio *const priv = counter->priv;
  986. return sprintf(buf, "%u\n", !priv->preset_enable[count->id]);
  987. }
  988. static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
  989. struct counter_count *count, void *private, const char *buf, size_t len)
  990. {
  991. struct quad8_iio *const priv = counter->priv;
  992. const int base_offset = priv->base + 2 * count->id + 1;
  993. bool preset_enable;
  994. int ret;
  995. unsigned int ior_cfg;
  996. ret = kstrtobool(buf, &preset_enable);
  997. if (ret)
  998. return ret;
  999. /* Preset enable is active low in Input/Output Control register */
  1000. preset_enable = !preset_enable;
  1001. mutex_lock(&priv->lock);
  1002. priv->preset_enable[count->id] = preset_enable;
  1003. ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1;
  1004. /* Load I/O control configuration to Input / Output Control Register */
  1005. outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
  1006. mutex_unlock(&priv->lock);
  1007. return len;
  1008. }
  1009. static const struct counter_signal_ext quad8_index_ext[] = {
  1010. COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum),
  1011. COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum),
  1012. COUNTER_SIGNAL_ENUM("synchronous_mode", &quad8_syn_mode_enum),
  1013. COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum)
  1014. };
  1015. #define QUAD8_QUAD_SIGNAL(_id, _name) { \
  1016. .id = (_id), \
  1017. .name = (_name) \
  1018. }
  1019. #define QUAD8_INDEX_SIGNAL(_id, _name) { \
  1020. .id = (_id), \
  1021. .name = (_name), \
  1022. .ext = quad8_index_ext, \
  1023. .num_ext = ARRAY_SIZE(quad8_index_ext) \
  1024. }
  1025. static struct counter_signal quad8_signals[] = {
  1026. QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
  1027. QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
  1028. QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
  1029. QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
  1030. QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
  1031. QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
  1032. QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
  1033. QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
  1034. QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
  1035. QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
  1036. QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
  1037. QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
  1038. QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
  1039. QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
  1040. QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
  1041. QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
  1042. QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
  1043. QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
  1044. QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
  1045. QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
  1046. QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
  1047. QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
  1048. QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
  1049. QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
  1050. };
  1051. #define QUAD8_COUNT_SYNAPSES(_id) { \
  1052. { \
  1053. .actions_list = quad8_synapse_actions_list, \
  1054. .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
  1055. .signal = quad8_signals + 2 * (_id) \
  1056. }, \
  1057. { \
  1058. .actions_list = quad8_synapse_actions_list, \
  1059. .num_actions = ARRAY_SIZE(quad8_synapse_actions_list), \
  1060. .signal = quad8_signals + 2 * (_id) + 1 \
  1061. }, \
  1062. { \
  1063. .actions_list = quad8_index_actions_list, \
  1064. .num_actions = ARRAY_SIZE(quad8_index_actions_list), \
  1065. .signal = quad8_signals + 2 * (_id) + 16 \
  1066. } \
  1067. }
  1068. static struct counter_synapse quad8_count_synapses[][3] = {
  1069. QUAD8_COUNT_SYNAPSES(0), QUAD8_COUNT_SYNAPSES(1),
  1070. QUAD8_COUNT_SYNAPSES(2), QUAD8_COUNT_SYNAPSES(3),
  1071. QUAD8_COUNT_SYNAPSES(4), QUAD8_COUNT_SYNAPSES(5),
  1072. QUAD8_COUNT_SYNAPSES(6), QUAD8_COUNT_SYNAPSES(7)
  1073. };
  1074. static const struct counter_count_ext quad8_count_ext[] = {
  1075. {
  1076. .name = "ceiling",
  1077. .read = quad8_count_ceiling_read,
  1078. .write = quad8_count_ceiling_write
  1079. },
  1080. {
  1081. .name = "floor",
  1082. .read = quad8_count_floor_read
  1083. },
  1084. COUNTER_COUNT_ENUM("count_mode", &quad8_cnt_mode_enum),
  1085. COUNTER_COUNT_ENUM_AVAILABLE("count_mode", &quad8_cnt_mode_enum),
  1086. {
  1087. .name = "direction",
  1088. .read = quad8_count_direction_read
  1089. },
  1090. {
  1091. .name = "enable",
  1092. .read = quad8_count_enable_read,
  1093. .write = quad8_count_enable_write
  1094. },
  1095. COUNTER_COUNT_ENUM("error_noise", &quad8_error_noise_enum),
  1096. COUNTER_COUNT_ENUM_AVAILABLE("error_noise", &quad8_error_noise_enum),
  1097. {
  1098. .name = "preset",
  1099. .read = quad8_count_preset_read,
  1100. .write = quad8_count_preset_write
  1101. },
  1102. {
  1103. .name = "preset_enable",
  1104. .read = quad8_count_preset_enable_read,
  1105. .write = quad8_count_preset_enable_write
  1106. }
  1107. };
  1108. #define QUAD8_COUNT(_id, _cntname) { \
  1109. .id = (_id), \
  1110. .name = (_cntname), \
  1111. .functions_list = quad8_count_functions_list, \
  1112. .num_functions = ARRAY_SIZE(quad8_count_functions_list), \
  1113. .synapses = quad8_count_synapses[(_id)], \
  1114. .num_synapses = 2, \
  1115. .ext = quad8_count_ext, \
  1116. .num_ext = ARRAY_SIZE(quad8_count_ext) \
  1117. }
  1118. static struct counter_count quad8_counts[] = {
  1119. QUAD8_COUNT(0, "Channel 1 Count"),
  1120. QUAD8_COUNT(1, "Channel 2 Count"),
  1121. QUAD8_COUNT(2, "Channel 3 Count"),
  1122. QUAD8_COUNT(3, "Channel 4 Count"),
  1123. QUAD8_COUNT(4, "Channel 5 Count"),
  1124. QUAD8_COUNT(5, "Channel 6 Count"),
  1125. QUAD8_COUNT(6, "Channel 7 Count"),
  1126. QUAD8_COUNT(7, "Channel 8 Count")
  1127. };
  1128. static int quad8_probe(struct device *dev, unsigned int id)
  1129. {
  1130. struct iio_dev *indio_dev;
  1131. struct quad8_iio *quad8iio;
  1132. int i, j;
  1133. unsigned int base_offset;
  1134. int err;
  1135. if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
  1136. dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
  1137. base[id], base[id] + QUAD8_EXTENT);
  1138. return -EBUSY;
  1139. }
  1140. /* Allocate IIO device; this also allocates driver data structure */
  1141. indio_dev = devm_iio_device_alloc(dev, sizeof(*quad8iio));
  1142. if (!indio_dev)
  1143. return -ENOMEM;
  1144. /* Initialize IIO device */
  1145. indio_dev->info = &quad8_info;
  1146. indio_dev->modes = INDIO_DIRECT_MODE;
  1147. indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
  1148. indio_dev->channels = quad8_channels;
  1149. indio_dev->name = dev_name(dev);
  1150. indio_dev->dev.parent = dev;
  1151. /* Initialize Counter device and driver data */
  1152. quad8iio = iio_priv(indio_dev);
  1153. quad8iio->counter.name = dev_name(dev);
  1154. quad8iio->counter.parent = dev;
  1155. quad8iio->counter.ops = &quad8_ops;
  1156. quad8iio->counter.counts = quad8_counts;
  1157. quad8iio->counter.num_counts = ARRAY_SIZE(quad8_counts);
  1158. quad8iio->counter.signals = quad8_signals;
  1159. quad8iio->counter.num_signals = ARRAY_SIZE(quad8_signals);
  1160. quad8iio->counter.priv = quad8iio;
  1161. quad8iio->base = base[id];
  1162. /* Initialize mutex */
  1163. mutex_init(&quad8iio->lock);
  1164. /* Reset all counters and disable interrupt function */
  1165. outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
  1166. /* Set initial configuration for all counters */
  1167. for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
  1168. base_offset = base[id] + 2 * i;
  1169. /* Reset Byte Pointer */
  1170. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
  1171. /* Reset Preset Register */
  1172. for (j = 0; j < 3; j++)
  1173. outb(0x00, base_offset);
  1174. /* Reset Borrow, Carry, Compare, and Sign flags */
  1175. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
  1176. /* Reset Error flag */
  1177. outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
  1178. /* Binary encoding; Normal count; non-quadrature mode */
  1179. outb(QUAD8_CTR_CMR, base_offset + 1);
  1180. /* Disable A and B inputs; preset on index; FLG1 as Carry */
  1181. outb(QUAD8_CTR_IOR, base_offset + 1);
  1182. /* Disable index function; negative index polarity */
  1183. outb(QUAD8_CTR_IDR, base_offset + 1);
  1184. }
  1185. /* Enable all counters */
  1186. outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
  1187. /* Register IIO device */
  1188. err = devm_iio_device_register(dev, indio_dev);
  1189. if (err)
  1190. return err;
  1191. /* Register Counter device */
  1192. return devm_counter_register(dev, &quad8iio->counter);
  1193. }
  1194. static struct isa_driver quad8_driver = {
  1195. .probe = quad8_probe,
  1196. .driver = {
  1197. .name = "104-quad-8"
  1198. }
  1199. };
  1200. module_isa_driver(quad8_driver, num_quad8);
  1201. MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
  1202. MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver");
  1203. MODULE_LICENSE("GPL v2");