vpmoct.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. /*
  2. * VPMOCT Driver.
  3. *
  4. * Written by Russ Meyerriecks <rmeyerriecks@digium.com>
  5. *
  6. * Copyright (C) 2010-2011 Digium, Inc.
  7. *
  8. * All rights reserved.
  9. *
  10. */
  11. /*
  12. * See http://www.asterisk.org for more information about
  13. * the Asterisk project. Please do not directly contact
  14. * any of the maintainers of this project for assistance;
  15. * the project provides a web site, mailing lists and IRC
  16. * channels for your use.
  17. *
  18. * This program is free software, distributed under the terms of
  19. * the GNU General Public License Version 2 as published by the
  20. * Free Software Foundation. See the LICENSE file included with
  21. * this program for more details.
  22. */
  23. #include <linux/jiffies.h>
  24. #include <linux/delay.h>
  25. #include <linux/sched.h>
  26. #include <linux/crc32.h>
  27. #include <linux/slab.h>
  28. #include "voicebus/vpmoct.h"
  29. #include "linux/firmware.h"
  30. struct vpmoct_header {
  31. u8 header[6];
  32. __le32 chksum;
  33. u8 pad[20];
  34. u8 major;
  35. u8 minor;
  36. } __packed;
  37. static int _vpmoct_read(struct vpmoct *vpm, u8 address,
  38. void *data, size_t size,
  39. u8 *new_command, u8 *new_address)
  40. {
  41. struct vpmoct_cmd *cmd;
  42. unsigned long flags;
  43. if (unlikely(size >= ARRAY_SIZE(cmd->data))) {
  44. memset(data, -1, size);
  45. return -1;
  46. }
  47. cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  48. if (!cmd) {
  49. dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n");
  50. return 0;
  51. }
  52. init_completion(&cmd->complete);
  53. cmd->command = 0x60 + size;
  54. cmd->address = address;
  55. cmd->chunksize = size;
  56. spin_lock_irqsave(&vpm->list_lock, flags);
  57. list_add_tail(&cmd->node, &vpm->pending_list);
  58. spin_unlock_irqrestore(&vpm->list_lock, flags);
  59. /* Wait for receiveprep to process our result */
  60. if (!wait_for_completion_timeout(&cmd->complete, HZ/5)) {
  61. spin_lock_irqsave(&vpm->list_lock, flags);
  62. list_del(&cmd->node);
  63. spin_unlock_irqrestore(&vpm->list_lock, flags);
  64. kfree(cmd);
  65. dev_err(vpm->dev, "vpmoct_read_byte cmd timed out\n");
  66. return 0;
  67. }
  68. memcpy(data, &cmd->data[0], size);
  69. if (new_command)
  70. *new_command = cmd->command;
  71. if (new_address)
  72. *new_address = cmd->address;
  73. kfree(cmd);
  74. return 0;
  75. }
  76. static u8 vpmoct_read_byte(struct vpmoct *vpm, u8 address)
  77. {
  78. u8 val;
  79. _vpmoct_read(vpm, address, &val, sizeof(val), NULL, NULL);
  80. return val;
  81. }
  82. static u32 vpmoct_read_dword(struct vpmoct *vpm, u8 address)
  83. {
  84. __le32 val;
  85. _vpmoct_read(vpm, address, &val, sizeof(val), NULL, NULL);
  86. return le32_to_cpu(val);
  87. }
  88. static void vpmoct_write_byte(struct vpmoct *vpm, u8 address, u8 data)
  89. {
  90. struct vpmoct_cmd *cmd;
  91. unsigned long flags;
  92. cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  93. if (!cmd) {
  94. dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n");
  95. return;
  96. }
  97. cmd->command = 0x21;
  98. cmd->address = address;
  99. cmd->data[0] = data;
  100. cmd->chunksize = 1;
  101. spin_lock_irqsave(&vpm->list_lock, flags);
  102. list_add_tail(&cmd->node, &vpm->pending_list);
  103. spin_unlock_irqrestore(&vpm->list_lock, flags);
  104. }
  105. static void vpmoct_write_dword(struct vpmoct *vpm, u8 address, u32 data)
  106. {
  107. struct vpmoct_cmd *cmd;
  108. unsigned long flags;
  109. cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
  110. if (!cmd) {
  111. dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n");
  112. return;
  113. }
  114. cmd->command = 0x20 + sizeof(data);
  115. cmd->address = address;
  116. *(__le32 *)(&cmd->data[0]) = cpu_to_le32(data);
  117. cmd->chunksize = sizeof(data);
  118. spin_lock_irqsave(&vpm->list_lock, flags);
  119. list_add_tail(&cmd->node, &vpm->pending_list);
  120. spin_unlock_irqrestore(&vpm->list_lock, flags);
  121. }
  122. static void vpmoct_write_chunk(struct vpmoct *vpm, u8 address,
  123. const u8 *data, u8 chunksize)
  124. {
  125. struct vpmoct_cmd *cmd;
  126. unsigned long flags;
  127. if (unlikely(chunksize > ARRAY_SIZE(cmd->data)))
  128. return;
  129. cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
  130. if (unlikely(!cmd)) {
  131. dev_info(vpm->dev, "Unable to allocate memory for vpmoct_cmd\n");
  132. return;
  133. }
  134. cmd->command = 0x20 + chunksize;
  135. cmd->address = address;
  136. cmd->chunksize = chunksize;
  137. memcpy(cmd->data, data, chunksize);
  138. spin_lock_irqsave(&vpm->list_lock, flags);
  139. list_add_tail(&cmd->node, &vpm->pending_list);
  140. spin_unlock_irqrestore(&vpm->list_lock, flags);
  141. }
  142. static u8 vpmoct_resync(struct vpmoct *vpm)
  143. {
  144. unsigned long time;
  145. u8 status = 0xff;
  146. u8 address;
  147. u8 command;
  148. /* Poll the status register until it returns valid values
  149. * This is because we have to wait on the bootloader to do
  150. * its thing.
  151. * Timeout after 3 seconds
  152. */
  153. time = jiffies + 3*HZ;
  154. while (time_after(time, jiffies) && (0xff == status)) {
  155. status = _vpmoct_read(vpm, VPMOCT_BOOT_STATUS, &status,
  156. sizeof(status), &command, &address);
  157. /* Throw out invalid statuses */
  158. if ((0x55 != command) || (0xaa != address))
  159. status = 0xff;
  160. }
  161. if ((status != 0xff) && status)
  162. dev_info(vpm->dev, "Resync with status %x\n", status);
  163. return status;
  164. }
  165. static inline short vpmoct_erase_flash(struct vpmoct *vpm)
  166. {
  167. short res;
  168. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_FLASH_ERASE);
  169. res = vpmoct_resync(vpm);
  170. if (res)
  171. dev_info(vpm->dev, "Unable to erase flash\n");
  172. return res;
  173. }
  174. static inline short
  175. vpmoct_send_firmware_header(struct vpmoct *vpm, const struct firmware *fw)
  176. {
  177. unsigned short i;
  178. short res;
  179. /* Send the encrypted firmware header */
  180. for (i = 0; i < VPMOCT_FIRM_HEADER_LEN; i++) {
  181. vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+i,
  182. fw->data[i + sizeof(struct vpmoct_header)]);
  183. }
  184. /* Decrypt header */
  185. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_DECRYPT);
  186. res = vpmoct_resync(vpm);
  187. if (res)
  188. dev_info(vpm->dev, "Unable to send firmware header\n");
  189. return res;
  190. }
  191. static inline short
  192. vpmoct_send_firmware_body(struct vpmoct *vpm, const struct firmware *fw)
  193. {
  194. unsigned int i, ram_index, flash_index, flash_address;
  195. const u8 *buf;
  196. u8 chunksize;
  197. /* Load the body of the firmware */
  198. ram_index = 0;
  199. flash_index = 0;
  200. flash_address = 0;
  201. for (i = VPMOCT_FIRM_HEADER_LEN*2; i < fw->size;) {
  202. if (ram_index >= VPMOCT_BOOT_RAM_LEN) {
  203. /* Tell bootloader to load ram buffer into buffer */
  204. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD,
  205. 0x10 + flash_index);
  206. /* Assuming the memory load doesn't take longer than 1
  207. * eframe just insert a blank eframe before continuing
  208. * the firmware load */
  209. vpmoct_read_byte(vpm, VPMOCT_BOOT_STATUS);
  210. ram_index = 0;
  211. flash_index++;
  212. }
  213. if (flash_index >= VPMOCT_FLASH_BUF_SECTIONS) {
  214. /* Tell the bootloader the memory address for load */
  215. vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS1,
  216. flash_address);
  217. /* Tell the bootloader to load from flash buffer */
  218. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD,
  219. VPMOCT_BOOT_FLASH_COPY);
  220. if (vpmoct_resync(vpm))
  221. goto error;
  222. flash_index = 0;
  223. flash_address = i-VPMOCT_FIRM_HEADER_LEN*2;
  224. }
  225. /* Try to buffer for batch writes if possible */
  226. chunksize = VPMOCT_BOOT_RAM_LEN - ram_index;
  227. if (chunksize > VPMOCT_MAX_CHUNK)
  228. chunksize = VPMOCT_MAX_CHUNK;
  229. buf = &fw->data[i];
  230. vpmoct_write_chunk(vpm, VPMOCT_BOOT_RAM+ram_index,
  231. buf, chunksize);
  232. ram_index += chunksize;
  233. i += chunksize;
  234. }
  235. /* Flush remaining ram buffer to flash buffer */
  236. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD,
  237. VPMOCT_BOOT_FLASHLOAD + flash_index);
  238. if (vpmoct_resync(vpm))
  239. goto error;
  240. /* Tell boot loader the memory address to flash load */
  241. vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS1, flash_address);
  242. /* Tell the bootloader to load flash from flash buffer */
  243. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_FLASH_COPY);
  244. if (vpmoct_resync(vpm))
  245. goto error;
  246. return 0;
  247. error:
  248. dev_info(vpm->dev, "Unable to load firmware body\n");
  249. return -1;
  250. }
  251. /**
  252. * vpmoct_get_mode - Return the current operating mode of the VPMOCT032.
  253. * @vpm: The vpm to query.
  254. *
  255. * Will be either BOOTLOADER, APPLICATION, or UNKNOWN.
  256. *
  257. */
  258. static enum vpmoct_mode vpmoct_get_mode(struct vpmoct *vpm)
  259. {
  260. int i;
  261. enum vpmoct_mode ret = UNKNOWN;
  262. char identifier[11] = {0};
  263. for (i = 0; i < ARRAY_SIZE(identifier) - 1; i++)
  264. identifier[i] = vpmoct_read_byte(vpm, VPMOCT_IDENT+i);
  265. if (!memcmp(identifier, "bootloader", sizeof(identifier) - 1))
  266. ret = BOOTLOADER;
  267. else if (!memcmp(identifier, "VPMOCT032\0", sizeof(identifier) - 1))
  268. ret = APPLICATION;
  269. dev_dbg(vpm->dev, "vpmoct identifier: %s\n", identifier);
  270. return ret;
  271. }
  272. static inline short
  273. vpmoct_check_firmware_crc(struct vpmoct *vpm, size_t size, u8 major, u8 minor)
  274. {
  275. short ret = 0;
  276. u8 status;
  277. /* Load firmware size */
  278. vpmoct_write_dword(vpm, VPMOCT_BOOT_RAM, size);
  279. /* Load firmware version */
  280. vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+8, major);
  281. vpmoct_write_byte(vpm, VPMOCT_BOOT_RAM+9, minor);
  282. /* Validate the firmware load */
  283. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_IMAGE_VALIDATE);
  284. status = vpmoct_resync(vpm);
  285. if (status) {
  286. dev_info(vpm->dev,
  287. "vpmoct firmware CRC check failed: %x\n", status);
  288. /* TODO: Try the load again */
  289. ret = -1;
  290. } else {
  291. /* Switch to application code */
  292. vpmoct_write_dword(vpm, VPMOCT_BOOT_ADDRESS2, 0xDEADBEEF);
  293. vpmoct_write_byte(vpm, VPMOCT_BOOT_CMD, VPMOCT_BOOT_REBOOT);
  294. msleep(250);
  295. status = vpmoct_resync(vpm);
  296. if (APPLICATION != vpmoct_get_mode(vpm)) {
  297. dev_info(vpm->dev,
  298. "vpmoct firmware failed to switch to "
  299. "application. (%x)\n", status);
  300. ret = -1;
  301. } else {
  302. vpm->mode = APPLICATION;
  303. dev_info(vpm->dev,
  304. "vpmoct firmware uploaded successfully\n");
  305. }
  306. }
  307. return ret;
  308. }
  309. static inline short vpmoct_switch_to_boot(struct vpmoct *vpm)
  310. {
  311. vpmoct_write_dword(vpm, 0x74, 0x00009876);
  312. vpmoct_write_byte(vpm, 0x71, 0x02);
  313. if (vpmoct_resync(vpm)) {
  314. dev_info(vpm->dev, "Failed to switch to bootloader\n");
  315. return -1;
  316. }
  317. vpm->mode = BOOTLOADER;
  318. return 0;
  319. }
  320. struct vpmoct_load_work {
  321. struct vpmoct *vpm;
  322. struct work_struct work;
  323. struct workqueue_struct *wq;
  324. load_complete_func_t load_complete;
  325. bool operational;
  326. };
  327. /**
  328. * vpmoct_load_complete_fn -
  329. *
  330. * This function should run in the context of one of the system workqueues so
  331. * that it can destroy any workqueues that may have been created to setup a
  332. * long running firmware load.
  333. *
  334. */
  335. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
  336. static void vpmoct_load_complete_fn(void *data)
  337. {
  338. struct vpmoct_load_work *work = data;
  339. #else
  340. static void vpmoct_load_complete_fn(struct work_struct *data)
  341. {
  342. struct vpmoct_load_work *work =
  343. container_of(data, struct vpmoct_load_work, work);
  344. #endif
  345. /* Do not touch work->vpm after calling load complete. It may have
  346. * been freed in the function by the board driver. */
  347. work->load_complete(work->vpm->dev, work->operational);
  348. destroy_workqueue(work->wq);
  349. kfree(work);
  350. }
  351. /**
  352. * vpmoct_load_complete - Call the load_complete function in a system workqueue.
  353. * @work:
  354. * @operational: Whether the VPM is functioning or not.
  355. *
  356. */
  357. static void
  358. vpmoct_load_complete(struct vpmoct_load_work *work, bool operational)
  359. {
  360. work->operational = operational;
  361. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
  362. INIT_WORK(&work->work, vpmoct_load_complete_fn, work);
  363. #else
  364. INIT_WORK(&work->work, vpmoct_load_complete_fn);
  365. #endif
  366. schedule_work(&work->work);
  367. }
  368. static bool is_valid_vpmoct_firmware(const struct firmware *fw)
  369. {
  370. const struct vpmoct_header *header =
  371. (const struct vpmoct_header *)fw->data;
  372. u32 crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0;
  373. return (!memcmp("DIGIUM", header->header, sizeof(header->header)) &&
  374. (le32_to_cpu(header->chksum) == crc));
  375. }
  376. static void vpmoct_set_defaults(struct vpmoct *vpm)
  377. {
  378. vpmoct_write_dword(vpm, 0x40, 0);
  379. vpmoct_write_dword(vpm, 0x30, 0);
  380. }
  381. static const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin";
  382. #if defined(HOTPLUG_FIRMWARE)
  383. static int
  384. vpmoct_request_firmware(const struct firmware **fw, struct device *dev)
  385. {
  386. return request_firmware(fw, FIRMWARE_NAME, dev);
  387. }
  388. static void vpmoct_release_firmware(const struct firmware *fw)
  389. {
  390. release_firmware(fw);
  391. }
  392. #else
  393. static int
  394. vpmoct_request_firmware(const struct firmware **fw_p, struct device *dev)
  395. {
  396. struct firmware *fw;
  397. extern void _binary_dahdi_fw_vpmoct032_bin_size;
  398. extern u8 _binary_dahdi_fw_vpmoct032_bin_start[];
  399. *fw_p = fw = kzalloc(sizeof(*fw), GFP_KERNEL);
  400. if (!fw)
  401. return -ENOMEM;
  402. fw->data = _binary_dahdi_fw_vpmoct032_bin_start;
  403. /* Yes... this is weird. objcopy gives us a symbol containing
  404. the size of the firmware, not a pointer a variable containing the
  405. size. The only way we can get the value of the symbol is to take
  406. its address, so we define it as a pointer and then cast that value
  407. to the proper type. */
  408. fw->size = (size_t) &_binary_dahdi_fw_vpmoct032_bin_size;
  409. return 0;
  410. }
  411. static void vpmoct_release_firmware(const struct firmware *fw)
  412. {
  413. kfree(fw);
  414. }
  415. #endif
  416. /**
  417. * vpmoct_load_flash - Check the current flash version and possibly load.
  418. * @vpm: The VPMOCT032 module to check / load.
  419. *
  420. */
  421. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
  422. static void vpmoct_load_flash(void *data)
  423. {
  424. struct vpmoct_load_work *work = data;
  425. #else
  426. static void vpmoct_load_flash(struct work_struct *data)
  427. {
  428. struct vpmoct_load_work *work =
  429. container_of(data, struct vpmoct_load_work, work);
  430. #endif
  431. int res;
  432. struct vpmoct *const vpm = work->vpm;
  433. const struct firmware *fw;
  434. const struct vpmoct_header *header;
  435. char serial[VPMOCT_SERIAL_SIZE+1];
  436. int i;
  437. res = vpmoct_request_firmware(&fw, vpm->dev);
  438. if (res) {
  439. dev_warn(vpm->dev,
  440. "vpmoct: Failed to load firmware from userspace! %d\n",
  441. res);
  442. header = NULL;
  443. fw = NULL;
  444. } else {
  445. header = (const struct vpmoct_header *)fw->data;
  446. }
  447. if (vpm->mode == APPLICATION) {
  448. /* Check the running application firmware
  449. * for the proper version */
  450. vpm->major = vpmoct_read_byte(vpm, VPMOCT_MAJOR);
  451. vpm->minor = vpmoct_read_byte(vpm, VPMOCT_MINOR);
  452. for (i = 0; i < VPMOCT_SERIAL_SIZE; i++)
  453. serial[i] = vpmoct_read_byte(vpm, VPMOCT_SERIAL+i);
  454. serial[VPMOCT_SERIAL_SIZE] = '\0';
  455. dev_info(vpm->dev,
  456. "vpmoct: Detected firmware v%d.%d Serial: %s\n",
  457. vpm->major, vpm->minor,
  458. (serial[0] != -1) ? serial : "(None)");
  459. if (!fw) {
  460. /* Again, we'll use the existing loaded firmware. */
  461. vpmoct_set_defaults(vpm);
  462. vpmoct_load_complete(work, true);
  463. return;
  464. }
  465. if (!is_valid_vpmoct_firmware(fw)) {
  466. dev_warn(vpm->dev,
  467. "%s is invalid. Please reinstall.\n",
  468. FIRMWARE_NAME);
  469. /* Just use the old version of the fimware. */
  470. vpmoct_release_firmware(fw);
  471. vpmoct_set_defaults(vpm);
  472. vpmoct_load_complete(work, true);
  473. return;
  474. }
  475. if (vpm->minor == header->minor &&
  476. vpm->major == header->major) {
  477. /* Proper version is running */
  478. vpmoct_release_firmware(fw);
  479. vpmoct_set_defaults(vpm);
  480. vpmoct_load_complete(work, true);
  481. return;
  482. } else {
  483. /* Incorrect version of application code is
  484. * loaded. Reset to bootloader mode */
  485. if (vpmoct_switch_to_boot(vpm))
  486. goto error;
  487. }
  488. }
  489. if (!fw) {
  490. vpmoct_load_complete(work, false);
  491. return;
  492. } else if (!is_valid_vpmoct_firmware(fw)) {
  493. dev_warn(vpm->dev,
  494. "%s is invalid. Please reinstall.\n", FIRMWARE_NAME);
  495. goto error;
  496. }
  497. dev_info(vpm->dev, "vpmoct: Uploading firmware, v%d.%d. This can "\
  498. "take up to 1 minute\n",
  499. header->major, header->minor);
  500. if (vpmoct_erase_flash(vpm))
  501. goto error;
  502. if (vpmoct_send_firmware_header(vpm, fw))
  503. goto error;
  504. if (vpmoct_send_firmware_body(vpm, fw))
  505. goto error;
  506. if (vpmoct_check_firmware_crc(vpm, fw->size-VPMOCT_FIRM_HEADER_LEN*2,
  507. header->major, header->minor))
  508. goto error;
  509. vpmoct_release_firmware(fw);
  510. vpmoct_set_defaults(vpm);
  511. vpmoct_load_complete(work, true);
  512. return;
  513. error:
  514. dev_info(vpm->dev, "Unable to load firmware\n");
  515. vpmoct_release_firmware(fw);
  516. /* TODO: Should we disable module if the firmware doesn't load? */
  517. vpmoct_load_complete(work, false);
  518. return;
  519. }
  520. struct vpmoct *vpmoct_alloc(void)
  521. {
  522. struct vpmoct *vpm;
  523. vpm = kzalloc(sizeof(*vpm), GFP_KERNEL);
  524. if (!vpm)
  525. return NULL;
  526. spin_lock_init(&vpm->list_lock);
  527. INIT_LIST_HEAD(&vpm->pending_list);
  528. INIT_LIST_HEAD(&vpm->active_list);
  529. mutex_init(&vpm->mutex);
  530. return vpm;
  531. }
  532. EXPORT_SYMBOL(vpmoct_alloc);
  533. void vpmoct_free(struct vpmoct *vpm)
  534. {
  535. unsigned long flags;
  536. struct vpmoct_cmd *cmd;
  537. LIST_HEAD(list);
  538. if (!vpm)
  539. return;
  540. spin_lock_irqsave(&vpm->list_lock, flags);
  541. list_splice(&vpm->active_list, &list);
  542. list_splice(&vpm->pending_list, &list);
  543. spin_unlock_irqrestore(&vpm->list_lock, flags);
  544. while (!list_empty(&list)) {
  545. cmd = list_entry(list.next, struct vpmoct_cmd, node);
  546. list_del(&cmd->node);
  547. kfree(cmd);
  548. }
  549. kfree(vpm);
  550. }
  551. EXPORT_SYMBOL(vpmoct_free);
  552. /**
  553. * vpmoct_init - Check for / initialize VPMOCT032 module.
  554. * @vpm: struct vpmoct allocated with vpmoct_alloc
  555. * @load_complete_fn: Function to call when the load is complete.
  556. *
  557. * Check to see if there is a VPMOCT module installed. If there appears to be
  558. * one return 0 and perform any necessary setup in the background. The
  559. * load_complete function will be called in a system global workqueue when the
  560. * initialization is complete.
  561. *
  562. * Must be called in process context.
  563. */
  564. int vpmoct_init(struct vpmoct *vpm, load_complete_func_t load_complete)
  565. {
  566. struct vpmoct_load_work *work;
  567. if (!vpm || !vpm->dev || !load_complete)
  568. return -EINVAL;
  569. if (vpmoct_resync(vpm)) {
  570. load_complete(vpm->dev, false);
  571. return -ENODEV;
  572. }
  573. vpm->mode = vpmoct_get_mode(vpm);
  574. if (UNKNOWN == vpm->mode) {
  575. load_complete(vpm->dev, false);
  576. return -ENODEV;
  577. }
  578. work = kzalloc(sizeof(*work), GFP_KERNEL);
  579. if (!work) {
  580. load_complete(vpm->dev, false);
  581. return -ENOMEM;
  582. }
  583. work->wq = create_singlethread_workqueue("vpmoct");
  584. if (!work->wq) {
  585. kfree(work);
  586. load_complete(vpm->dev, false);
  587. return -ENOMEM;
  588. }
  589. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
  590. INIT_WORK(&work->work, vpmoct_load_flash, work);
  591. #else
  592. INIT_WORK(&work->work, vpmoct_load_flash);
  593. #endif
  594. work->vpm = vpm;
  595. work->load_complete = load_complete;
  596. queue_work(work->wq, &work->work);
  597. return 0;
  598. }
  599. EXPORT_SYMBOL(vpmoct_init);
  600. static void
  601. vpmoct_set_companding(struct vpmoct *vpm, int channo, int companding)
  602. {
  603. u32 new_companding;
  604. bool do_update = false;
  605. mutex_lock(&vpm->mutex);
  606. new_companding = (DAHDI_LAW_MULAW == companding) ?
  607. (vpm->companding & ~(1 << channo)) :
  608. (vpm->companding | (1 << channo));
  609. if (vpm->companding != new_companding) {
  610. vpm->companding = new_companding;
  611. if (!vpm->companding_update_active) {
  612. do_update = true;
  613. vpm->companding_update_active = 1;
  614. }
  615. }
  616. mutex_unlock(&vpm->mutex);
  617. while (do_update) {
  618. u32 update;
  619. vpmoct_write_dword(vpm, 0x40, new_companding);
  620. update = vpmoct_read_dword(vpm, 0x40);
  621. WARN_ON(new_companding != update);
  622. mutex_lock(&vpm->mutex);
  623. if (vpm->companding != new_companding) {
  624. new_companding = vpm->companding;
  625. } else {
  626. vpm->companding_update_active = 0;
  627. do_update = false;
  628. }
  629. mutex_unlock(&vpm->mutex);
  630. }
  631. }
  632. /**
  633. * vpmoct_echo_update - Enable / Disable the VPMOCT032 echocan state
  634. * @vpm: The echocan to operate on.
  635. * @channo: Which echocan timeslot to enable / disable.
  636. * @echo_on: Whether we're turning the echocan on or off.
  637. *
  638. * When this function returns, the echocan is scheduled to be enabled or
  639. * disabled at some point in the near future.
  640. *
  641. * Must be called in process context.
  642. *
  643. */
  644. static void vpmoct_echo_update(struct vpmoct *vpm, int channo, bool echo_on)
  645. {
  646. u32 echo;
  647. unsigned long timeout;
  648. bool do_update = false;
  649. mutex_lock(&vpm->mutex);
  650. echo = (echo_on) ? (vpm->echo | (1 << channo)) :
  651. (vpm->echo & ~(1 << channo));
  652. if (vpm->echo != echo) {
  653. vpm->echo = echo;
  654. if (!vpm->echo_update_active) {
  655. do_update = true;
  656. vpm->echo_update_active = 1;
  657. }
  658. }
  659. mutex_unlock(&vpm->mutex);
  660. timeout = jiffies + 2*HZ;
  661. while (do_update) {
  662. u32 new;
  663. vpmoct_write_dword(vpm, 0x30, echo);
  664. new = vpmoct_read_dword(vpm, 0x10);
  665. mutex_lock(&vpm->mutex);
  666. if (((vpm->echo != echo) || (new != echo)) &&
  667. time_before(jiffies, timeout)) {
  668. echo = vpm->echo;
  669. } else {
  670. vpm->echo_update_active = 0;
  671. do_update = false;
  672. }
  673. mutex_unlock(&vpm->mutex);
  674. }
  675. if (!time_before(jiffies, timeout))
  676. dev_warn(vpm->dev, "vpmoct: Updating echo state timed out.\n");
  677. }
  678. int vpmoct_echocan_create(struct vpmoct *vpm, int channo, int companding)
  679. {
  680. vpmoct_set_companding(vpm, channo, companding);
  681. vpmoct_echo_update(vpm, channo, true);
  682. return 0;
  683. }
  684. EXPORT_SYMBOL(vpmoct_echocan_create);
  685. void vpmoct_echocan_free(struct vpmoct *vpm, int channo)
  686. {
  687. vpmoct_echo_update(vpm, channo, false);
  688. }
  689. EXPORT_SYMBOL(vpmoct_echocan_free);
  690. /* Enable a vpm debugging mode where the pre-echo-canceled audio
  691. * stream is physically output on timeslot 24.
  692. */
  693. int vpmoct_preecho_enable(struct vpmoct *vpm, const int channo)
  694. {
  695. int ret;
  696. mutex_lock(&vpm->mutex);
  697. if (!vpm->preecho_enabled) {
  698. vpm->preecho_enabled = 1;
  699. vpm->preecho_timeslot = channo;
  700. vpmoct_write_dword(vpm, 0x74, channo);
  701. /* Begin pre-echo stream on timeslot 24 */
  702. vpmoct_write_byte(vpm, 0x71, 0x0a);
  703. ret = 0;
  704. } else {
  705. ret = -EBUSY;
  706. }
  707. mutex_unlock(&vpm->mutex);
  708. return ret;
  709. }
  710. EXPORT_SYMBOL(vpmoct_preecho_enable);
  711. int vpmoct_preecho_disable(struct vpmoct *vpm, const int channo)
  712. {
  713. int ret;
  714. mutex_lock(&vpm->mutex);
  715. if (!vpm->preecho_enabled) {
  716. ret = 0;
  717. } else if (channo == vpm->preecho_timeslot) {
  718. vpm->preecho_enabled = 0;
  719. /* Disable pre-echo stream by loading in a non-existing
  720. * channel number */
  721. vpmoct_write_byte(vpm, 0x74, 0xff);
  722. /* Stop pre-echo stream on timeslot 24 */
  723. vpmoct_write_byte(vpm, 0x71, 0x0a);
  724. ret = 0;
  725. } else {
  726. ret = -EINVAL;
  727. }
  728. mutex_unlock(&vpm->mutex);
  729. return ret;
  730. }
  731. EXPORT_SYMBOL(vpmoct_preecho_disable);