drvmain.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. #include <linux/version.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h> // printk()
  4. #include <linux/module.h> // THIS_MODULE
  5. #include <linux/kobject.h> // struct kobject
  6. #include <linux/timer.h>
  7. #include <linux/errno.h> // error codes
  8. #include <linux/sysfs.h>
  9. #include <linux/syscalls.h>
  10. #include <linux/workqueue.h>
  11. #include <asm/ioctls.h>
  12. #include <linux/spi/spidev.h>
  13. #include "defines.h"
  14. #include "kfile.h"
  15. #include "kspi.h"
  16. #include "ktiva.h"
  17. #include "sfsattrib.h"
  18. #include "kfirmware.h"
  19. /////////////////////////////////////////////////////////////////////////////
  20. MODULE_LICENSE("Dual BSD/GPL");
  21. MODULE_AUTHOR("GfA");
  22. #define _THREAD_DELAY_JIFFIES 5
  23. #define _IS_REVIVE_STATE(ret) ((ret) != -ECOMM)
  24. /////////////////////////////////////////////////////////////////////////////
  25. // sys fs
  26. static struct kobject *g_pKoGfa = NULL, *g_pKoTiva = NULL;
  27. static bool g_bHasFwVersion = false;
  28. /////////////////////////////////////////////////////////////////////////////
  29. // worker threads
  30. static void _SysFsWorkProc(struct work_struct *work);
  31. static void _FwUploadWorkProc(struct work_struct *work);
  32. static struct workqueue_struct *g_pwq = NULL;
  33. static DECLARE_WORK(g_sysFsWorkObj, _SysFsWorkProc);
  34. static DECLARE_WORK(g_fwUploadWorkObj, _FwUploadWorkProc);
  35. /////////////////////////////////////////////////////////////////////////////
  36. // timer
  37. static volatile bool g_bTimerRunning = false;
  38. static struct timer_list g_jiq_timer;
  39. /////////////////////////////////////////////////////////////////////////////
  40. typedef enum _WorkerState
  41. {
  42. WS_SysFs,
  43. WS_FwUpload
  44. }WorkerState;
  45. static TIVA_UPLOAD_INFO g_tui;
  46. /////////////////////////////////////////////////////////////////////////////
  47. static void OnJigTimer(unsigned long ptr)
  48. {
  49. static unsigned int nPass = 0;
  50. static WorkerState ws = WS_SysFs;
  51. // KALERT("%s: %d, %p\n", __FUNCTION__, g_bTimerRunning ? 1 : 0, g_pwq);
  52. if(g_bTimerRunning && g_pwq)
  53. {
  54. if(KfwQueryUploadInfo(&g_tui))
  55. ws = WS_FwUpload;
  56. switch(ws)
  57. {
  58. case WS_SysFs:
  59. if(++nPass == 3)
  60. {
  61. if(!queue_work(g_pwq, &g_sysFsWorkObj))
  62. {
  63. KALERT("%s: queue_work failed\n", __FUNCTION__);
  64. }
  65. nPass = 0;
  66. }
  67. else
  68. {
  69. mutex_lock(&g_mutex);
  70. mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
  71. mutex_unlock(&g_mutex);
  72. }
  73. break;
  74. case WS_FwUpload:
  75. if(!queue_work(g_pwq, &g_fwUploadWorkObj))
  76. {
  77. KALERT("%s: queue_work failed\n", __FUNCTION__);
  78. }
  79. ws = WS_SysFs;
  80. // nPass = 2;
  81. nPass = 1;
  82. break;
  83. }
  84. }
  85. }
  86. /////////////////////////////////////////////////////////////////////////////
  87. // work queue
  88. // sysfs_notify
  89. // https://stackoverflow.com/questions/16367623/using-the-linux-sysfs-notify-call
  90. //
  91. static void _FwUploadWorkProc(struct work_struct *work)
  92. {
  93. struct file *pfSpiDev = NULL;
  94. uint8_t mode = 0;
  95. uint8_t bits = 0;
  96. uint32_t speed = 0;
  97. if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
  98. {
  99. do
  100. {
  101. unsigned char stat = 0xFF;
  102. if(kspi_write_mode(pfSpiDev, SPI_MODE_3) < 0)
  103. {
  104. KALERT("%s: kspi_write_mode failed!\n", __FUNCTION__);
  105. break;
  106. }
  107. if(kspi_read_mode(pfSpiDev, &mode) < 0)
  108. {
  109. KALERT("%s: kspi_read_mode failed!\n", __FUNCTION__);
  110. break;
  111. }
  112. if(mode != SPI_MODE_3)
  113. {
  114. KALERT("%s: Invalid mode!\n", __FUNCTION__);
  115. break;
  116. }
  117. /////////////////////////////////////////////////////////////////
  118. if(kspi_write_bits_per_word(pfSpiDev, _SPI_BITS_PER_WORD) < 0)
  119. {
  120. KALERT("%s: kspi_write_bits_per_word failed!\n", __FUNCTION__);
  121. break;
  122. }
  123. if(kspi_read_bits_per_word(pfSpiDev, &bits) < 0)
  124. {
  125. KALERT("%s: kspi_read_bits_per_word failed!\n", __FUNCTION__);
  126. break;
  127. }
  128. if(bits != _SPI_BITS_PER_WORD)
  129. {
  130. KALERT("%s: Invalid bits per word!\n", __FUNCTION__);
  131. break;
  132. }
  133. /////////////////////////////////////////////////////////////////
  134. if(kspi_write_max_speed_hz(pfSpiDev, _SPI_SPEED_HZ) < 0)
  135. {
  136. KALERT("%s: kspi_write_max_speed_hz failed!\n", __FUNCTION__);
  137. break;
  138. }
  139. if(kspi_read_max_speed_hz(pfSpiDev, &speed) < 0)
  140. {
  141. KALERT("%s: kspi_read_max_speed_hz failed!\n", __FUNCTION__);
  142. break;
  143. }
  144. if(speed != _SPI_SPEED_HZ)
  145. {
  146. KALERT("%s: Invalid max. speed!\n", __FUNCTION__);
  147. break;
  148. }
  149. /////////////////////////////////////////////////////////////////
  150. if(g_sw >= KFW_MIN_HAS_MATERIAL_NR_VERSION)
  151. {
  152. }
  153. if(TivaCmdStartBootloader(pfSpiDev) < 0)
  154. {
  155. KALERT("%s: TivaCmdStartBootloader failed!\n", __FUNCTION__);
  156. break;
  157. }
  158. g_hw = -1;
  159. g_sw = -1;
  160. g_bHasFwVersion = false;
  161. sysfs_notify(g_pKoTiva, NULL, "version");
  162. KALERT("%s: Started bootloader!\n", __FUNCTION__);
  163. set_current_state(TASK_INTERRUPTIBLE);
  164. schedule_timeout(_THREAD_DELAY_JIFFIES);
  165. if(TivaCmdGetBootloaderStatus(pfSpiDev, &stat) < 0)
  166. {
  167. KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
  168. break;
  169. }
  170. KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
  171. set_current_state(TASK_INTERRUPTIBLE);
  172. schedule_timeout(_THREAD_DELAY_JIFFIES);
  173. if(TivaCmdPing(pfSpiDev) < 0)
  174. {
  175. KALERT("%s: TivaCmdPing failed!\n", __FUNCTION__);
  176. break;
  177. }
  178. KALERT("%s: Ping success!\n", __FUNCTION__);
  179. set_current_state(TASK_INTERRUPTIBLE);
  180. schedule_timeout(_THREAD_DELAY_JIFFIES);
  181. if(TivaCmdGetBootloaderStatus(pfSpiDev, &stat) < 0)
  182. {
  183. KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
  184. break;
  185. }
  186. KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
  187. set_current_state(TASK_INTERRUPTIBLE);
  188. schedule_timeout(_THREAD_DELAY_JIFFIES);
  189. if(TivaCmdReset(pfSpiDev) < 0)
  190. {
  191. KALERT("%s: TivaCmdReset failed!\n", __FUNCTION__);
  192. break;
  193. }
  194. KALERT("%s: Started firmware!\n", __FUNCTION__);
  195. set_current_state(TASK_INTERRUPTIBLE);
  196. schedule_timeout(_THREAD_DELAY_JIFFIES);
  197. if(TivaCmdGetStatus(pfSpiDev, &stat) < 0)
  198. {
  199. KALERT("%s: TivaCmdGetStatus failed!\n", __FUNCTION__);
  200. break;
  201. }
  202. KALERT("%s: Status: 0x%02hhX\n", __FUNCTION__, stat);
  203. // KALERT("%s: data: 0x%p, cb: %zu, mat: %s, bld: %s\n", __FUNCTION__, g_tui.pData, g_tui.nCbData, g_tui.pszMat, g_tui.pszBld);
  204. }
  205. while(0);
  206. SfAttLockFirmware(false);
  207. kf_close(pfSpiDev);
  208. }
  209. else
  210. {
  211. KALERT("%s: kf_open failed\n", __FUNCTION__);
  212. }
  213. if(g_bTimerRunning)
  214. {
  215. mutex_lock(&g_mutex);
  216. mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
  217. mutex_unlock(&g_mutex);
  218. }
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. static void _SysFsWorkProc(struct work_struct *work)
  222. {
  223. TIVA_ADC tadc;
  224. unsigned char stat;
  225. int hw, sw, ret;
  226. unsigned long long nUpTime;
  227. struct file *pfSpiDev = NULL;
  228. uint8_t mode = 0;
  229. uint8_t bits = 0;
  230. uint32_t speed = 0;
  231. // unsigned long start = jiffies;
  232. // KALERT("%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  233. if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
  234. {
  235. do
  236. {
  237. if(kspi_write_mode(pfSpiDev, SPI_MODE_3) < 0)
  238. {
  239. KALERT("%s: kspi_write_mode failed!\n", __FUNCTION__);
  240. break;
  241. }
  242. if(kspi_read_mode(pfSpiDev, &mode) < 0)
  243. {
  244. KALERT("%s: kspi_read_mode failed!\n", __FUNCTION__);
  245. break;
  246. }
  247. if(mode != SPI_MODE_3)
  248. {
  249. KALERT("%s: Invalid mode!\n", __FUNCTION__);
  250. break;
  251. }
  252. /////////////////////////////////////////////////////////////////
  253. if(kspi_write_bits_per_word(pfSpiDev, _SPI_BITS_PER_WORD) < 0)
  254. {
  255. KALERT("%s: kspi_write_bits_per_word failed!\n", __FUNCTION__);
  256. break;
  257. }
  258. if(kspi_read_bits_per_word(pfSpiDev, &bits) < 0)
  259. {
  260. KALERT("%s: kspi_read_bits_per_word failed!\n", __FUNCTION__);
  261. break;
  262. }
  263. if(bits != _SPI_BITS_PER_WORD)
  264. {
  265. KALERT("%s: Invalid bits per word!\n", __FUNCTION__);
  266. break;
  267. }
  268. /////////////////////////////////////////////////////////////////
  269. if(kspi_write_max_speed_hz(pfSpiDev, _SPI_SPEED_HZ) < 0)
  270. {
  271. KALERT("%s: kspi_write_max_speed_hz failed!\n", __FUNCTION__);
  272. break;
  273. }
  274. if(kspi_read_max_speed_hz(pfSpiDev, &speed) < 0)
  275. {
  276. KALERT("%s: kspi_read_max_speed_hz failed!\n", __FUNCTION__);
  277. break;
  278. }
  279. if(speed != _SPI_SPEED_HZ)
  280. {
  281. KALERT("%s: Invalid max. speed!\n", __FUNCTION__);
  282. break;
  283. }
  284. /////////////////////////////////////////////////////////////////
  285. if( (ret = TivaCmdPing(pfSpiDev)) < 0 &&
  286. _IS_REVIVE_STATE(ret))
  287. {
  288. KALERT("%s: TivaCmdPing failed: %d - call TivaRevive\n", __FUNCTION__, ret);
  289. TivaRevive(pfSpiDev);
  290. }
  291. set_current_state(TASK_INTERRUPTIBLE);
  292. schedule_timeout(_THREAD_DELAY_JIFFIES);
  293. /////////////////////////////////////////////////////////////////
  294. if(!g_bHasFwVersion)
  295. {
  296. if((ret = TivaCmdGetFirmwareVersion(pfSpiDev, &hw, &sw)) == 0)
  297. {
  298. if((g_hw != hw) || (g_sw != sw))
  299. {
  300. g_hw = hw;
  301. g_sw = sw;
  302. sysfs_notify(g_pKoTiva, NULL, "version");
  303. }
  304. g_bHasFwVersion = true;
  305. }
  306. else if(_IS_REVIVE_STATE(ret))
  307. {
  308. KALERT("%s: TivaCmdGetFirmwareVersion failed: %d - call TivaRevive\n", __FUNCTION__, ret);
  309. TivaRevive(pfSpiDev);
  310. break;
  311. }
  312. set_current_state(TASK_INTERRUPTIBLE);
  313. schedule_timeout(_THREAD_DELAY_JIFFIES);
  314. }
  315. /////////////////////////////////////////////////////////////////
  316. if((ret = TivaCmdGetADC(pfSpiDev, &tadc)) == 0)
  317. {
  318. bool bModified = false;
  319. if(g_tadc.UVers != tadc.UVers)
  320. {
  321. g_tadc.UVers = tadc.UVers;
  322. bModified = true;
  323. sysfs_notify(g_pKoTiva, NULL, "UVers");
  324. }
  325. if(g_tadc.UBatV3 != tadc.UBatV3)
  326. {
  327. g_tadc.UBatV3 = tadc.UBatV3;
  328. bModified = true;
  329. sysfs_notify(g_pKoTiva, NULL, "UBatV3");
  330. }
  331. if(g_tadc.Temp != tadc.Temp)
  332. {
  333. g_tadc.Temp = tadc.Temp;
  334. bModified = true;
  335. sysfs_notify(g_pKoTiva, NULL, "TempBoard");
  336. }
  337. if(g_tadc.UV5Vsys != tadc.UV5Vsys)
  338. {
  339. g_tadc.UV5Vsys = tadc.UV5Vsys;
  340. bModified = true;
  341. sysfs_notify(g_pKoTiva, NULL, "UV5Vsys");
  342. }
  343. if(g_tadc.UV3V6Bat != tadc.UV3V6Bat)
  344. {
  345. g_tadc.UV3V6Bat = tadc.UV3V6Bat;
  346. bModified = true;
  347. sysfs_notify(g_pKoTiva, NULL, "UV3V6Bat");
  348. }
  349. if(g_tadc.TempTIVA != tadc.TempTIVA)
  350. {
  351. g_tadc.TempTIVA = tadc.TempTIVA;
  352. bModified = true;
  353. sysfs_notify(g_pKoTiva, NULL, "TempTIVA");
  354. }
  355. if(bModified) // if any of the ADC values have changed, signal the binary file
  356. {
  357. sysfs_notify(g_pKoTiva, NULL, "AdcBin");
  358. }
  359. }
  360. else if(_IS_REVIVE_STATE(ret))
  361. {
  362. KALERT("%s: TivaCmdGetADC failed: %d - call TivaRevive\n", __FUNCTION__, ret);
  363. TivaRevive(pfSpiDev);
  364. }
  365. set_current_state(TASK_INTERRUPTIBLE);
  366. schedule_timeout(_THREAD_DELAY_JIFFIES);
  367. /////////////////////////////////////////////////////////////////
  368. if((ret = TivaCmdGetUptime(pfSpiDev, &nUpTime)) == 0)
  369. {
  370. if(g_nUpTime != nUpTime)
  371. {
  372. g_nUpTime = nUpTime;
  373. sysfs_notify(g_pKoTiva, NULL, "Uptime");
  374. }
  375. }
  376. else if(_IS_REVIVE_STATE(ret))
  377. {
  378. KALERT("%s: TivaCmdGetUptime failed: %d - call TivaRevive\n", __FUNCTION__, ret);
  379. TivaRevive(pfSpiDev);
  380. }
  381. set_current_state(TASK_INTERRUPTIBLE);
  382. schedule_timeout(_THREAD_DELAY_JIFFIES);
  383. /////////////////////////////////////////////////////////////////
  384. if((ret = TivaCmdGetStatus(pfSpiDev, &stat)) == 0)
  385. {
  386. }
  387. else if(_IS_REVIVE_STATE(ret))
  388. {
  389. KALERT("%s: TivaCmdGetStatus failed: %d - call TivaRevive\n", __FUNCTION__, ret);
  390. TivaRevive(pfSpiDev);
  391. }
  392. /////////////////////////////////////////////////////////////////
  393. // KALERT("Worker pass - jiffies: %ld - status: 0x%02hhX\n", _JIFFY_DIFF(jiffies, start), stat);
  394. }
  395. while(0);
  396. kf_close(pfSpiDev);
  397. }
  398. else
  399. {
  400. KALERT("%s: kf_open failed\n", __FUNCTION__);
  401. }
  402. if(g_bTimerRunning)
  403. {
  404. mutex_lock(&g_mutex);
  405. mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
  406. mutex_unlock(&g_mutex);
  407. }
  408. }
  409. /////////////////////////////////////////////////////////////////////////////
  410. static int drv_init(void)
  411. {
  412. /////////////////////////////////////////////////////////////////////////
  413. do
  414. {
  415. if(!(g_pKoGfa = kobject_create_and_add("gfa", NULL)))
  416. {
  417. KALERT("kobject_create_and_add failed\n");
  418. break;
  419. }
  420. if(!(g_pKoTiva = kobject_create_and_add("tiva", g_pKoGfa)))
  421. {
  422. KALERT("kobject_create_and_add failed\n");
  423. break;
  424. }
  425. /////////////////////////////////////////////////////////////////////
  426. if(sysfs_create_file(g_pKoTiva, &g_tivaVersionAtt.attr))
  427. {
  428. KALERT("sysfs_create_file failed\n");
  429. break;
  430. }
  431. if(sysfs_create_file(g_pKoTiva, &g_tivaUptimeAtt.attr))
  432. {
  433. KALERT("sysfs_create_file failed\n");
  434. break;
  435. }
  436. if(sysfs_create_file(g_pKoTiva, &g_tivaUVersAtt.attr))
  437. {
  438. KALERT("sysfs_create_file failed\n");
  439. break;
  440. }
  441. if(sysfs_create_file(g_pKoTiva, &g_tivaUBatV3Att.attr))
  442. {
  443. KALERT("sysfs_create_file failed\n");
  444. break;
  445. }
  446. if(sysfs_create_file(g_pKoTiva, &g_tivaTempAtt.attr))
  447. {
  448. KALERT("sysfs_create_file failed\n");
  449. break;
  450. }
  451. if(sysfs_create_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr))
  452. {
  453. KALERT("sysfs_create_file failed\n");
  454. break;
  455. }
  456. if(sysfs_create_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr))
  457. {
  458. KALERT("sysfs_create_file failed\n");
  459. break;
  460. }
  461. if(sysfs_create_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr))
  462. {
  463. KALERT("sysfs_create_file failed\n");
  464. break;
  465. }
  466. if(sysfs_create_bin_file(g_pKoTiva, &g_tivaAdcBinAtt))
  467. {
  468. KALERT("sysfs_create_file failed\n");
  469. break;
  470. }
  471. g_nCbFwData = 0;
  472. if((g_pFwBuffer = (void*)__get_free_pages(GFP_KERNEL, _FIRMWARE_PAGES_COUNT)))
  473. {
  474. if(sysfs_create_bin_file(g_pKoTiva, &g_tivaFirmwareAtt))
  475. {
  476. KALERT("sysfs_create_file failed\n");
  477. break;
  478. }
  479. }
  480. /////////////////////////////////////////////////////////////////////
  481. if(!(g_pwq = create_workqueue("GfaWrk")))
  482. {
  483. KALERT("create_workqueue failed!\n");
  484. break;
  485. }
  486. /////////////////////////////////////////////////////////////////////
  487. init_timer(&g_jiq_timer);
  488. g_jiq_timer.function = OnJigTimer;
  489. g_jiq_timer.data = 0;
  490. g_jiq_timer.expires = _TIMER_INTERVAL;
  491. add_timer(&g_jiq_timer);
  492. g_bTimerRunning = true;
  493. /////////////////////////////////////////////////////////////////////
  494. if(!queue_work(g_pwq, &g_sysFsWorkObj))
  495. {
  496. KALERT("%s: queue_work failed\n", __FUNCTION__);
  497. break;
  498. }
  499. /////////////////////////////////////////////////////////////////////
  500. KALERT("%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  501. return 0;
  502. }
  503. while(0);
  504. /////////////////////////////////////////////////////////////////////////
  505. if(g_bTimerRunning)
  506. {
  507. g_bTimerRunning = false;
  508. del_timer_sync(&g_jiq_timer);
  509. }
  510. if(g_pwq)
  511. {
  512. destroy_workqueue(g_pwq);
  513. g_pwq = NULL;
  514. }
  515. if(g_pFwBuffer)
  516. {
  517. free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
  518. g_pFwBuffer = NULL;
  519. g_nCbFwData = 0;
  520. }
  521. if(g_pKoTiva)
  522. {
  523. sysfs_remove_file(g_pKoTiva, &g_tivaVersionAtt.attr);
  524. sysfs_remove_file(g_pKoTiva, &g_tivaUptimeAtt.attr);
  525. sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
  526. sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
  527. sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
  528. sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
  529. sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
  530. sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
  531. sysfs_remove_bin_file(g_pKoTiva, &g_tivaAdcBinAtt);
  532. sysfs_remove_bin_file(g_pKoTiva, &g_tivaFirmwareAtt);
  533. kobject_put(g_pKoTiva);
  534. g_pKoTiva = NULL;
  535. }
  536. if(g_pKoGfa)
  537. {
  538. kobject_put(g_pKoGfa);
  539. g_pKoGfa = NULL;
  540. }
  541. return -ENOMEM;
  542. }
  543. /////////////////////////////////////////////////////////////////////////////
  544. static void drv_exit(void)
  545. {
  546. g_bTimerRunning = false;
  547. del_timer_sync(&g_jiq_timer);
  548. if(g_pwq)
  549. {
  550. destroy_workqueue(g_pwq);
  551. g_pwq = NULL;
  552. }
  553. if(g_pFwBuffer)
  554. {
  555. free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
  556. g_pFwBuffer = NULL;
  557. g_nCbFwData = 0;
  558. }
  559. if(g_pKoTiva)
  560. {
  561. sysfs_remove_file(g_pKoTiva, &g_tivaVersionAtt.attr);
  562. sysfs_remove_file(g_pKoTiva, &g_tivaUptimeAtt.attr);
  563. sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
  564. sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
  565. sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
  566. sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
  567. sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
  568. sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
  569. sysfs_remove_bin_file(g_pKoTiva, &g_tivaFirmwareAtt);
  570. kobject_put(g_pKoTiva);
  571. }
  572. if(g_pKoGfa)
  573. kobject_put(g_pKoGfa);
  574. KALERT("%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  575. }
  576. /////////////////////////////////////////////////////////////////////////////
  577. module_init(drv_init);
  578. module_exit(drv_exit);