sfsattrib.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. #include <linux/version.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h>
  4. #include <linux/module.h>
  5. #include <linux/kobject.h>
  6. #include <linux/errno.h>
  7. #include <linux/ctype.h>
  8. #include <linux/sysfs.h>
  9. #include <linux/syscalls.h>
  10. #include "defines.h"
  11. #include "sfsattrib.h"
  12. #include "kfirmware.h"
  13. #include "ksync.h"
  14. #include "kfile.h"
  15. #include "ktiva.h"
  16. /////////////////////////////////////////////////////////////////////////////
  17. int g_hw = -1, g_sw = -1;
  18. TIVA_ADC g_tadc;
  19. unsigned long long g_nUpTime = 0;
  20. TIVA_DCAP g_dcaps;
  21. TIVA_MEMORY_MAP g_tiMM[] =
  22. {
  23. { // Flash
  24. .baseAddr = KTIVA_FLASH_BASE_ADDRESS,
  25. .bIsRO = true
  26. },
  27. { // SRAM
  28. .baseAddr = KTIVA_SRAM_BASE_ADDRESS,
  29. .bIsRO = false
  30. },
  31. { // Bit banded SRAM
  32. .baseAddr = KTIVA_SRAM_BIT_BAND_BASE_ADDRESS,
  33. .bIsRO = false
  34. },
  35. { // Peripherals
  36. .baseAddr = KTIVA_PERIPHERALS_BASE_ADDRESS,
  37. .size = KTIVA_PERIPHERALS_SIZE,
  38. .bIsRO = false
  39. },
  40. { // Bit banded Peripherals
  41. .baseAddr = KTIVA_PERIPHERALS_BIT_BAND_BASE_ADDRESS,
  42. .size = KTIVA_PERIPHERALS_BIT_BAND_SIZE,
  43. .bIsRO = false
  44. }
  45. };
  46. static void *g_pFwBuffer = NULL;
  47. static size_t g_nCbFwData = 0;
  48. static atomic_t g_flgFwLocked;
  49. static atomic_t g_flgBacklightChanged;
  50. static atomic_t g_valBacklightDutyCyclePercent;
  51. static atomic_t g_valBacklightPeriod;
  52. /////////////////////////////////////////////////////////////////////////////
  53. void time64_to_tm(time64_t totalsecs, int offset, struct tm *result);
  54. /////////////////////////////////////////////////////////////////////////////
  55. /////////////////////////////////////////////////////////////////////////////
  56. bool SfAttInit(void)
  57. {
  58. g_nCbFwData = 0;
  59. atomic_set(&g_flgBacklightChanged, 0);
  60. SfAttSetBacklightPeriod(_BACKLIGHT_PERIOD_DEFAULT);
  61. SfAttSetBacklightDutyCyclePercent(_BACKLIGHT_DUTY_CYCLE_PERC_DEF);
  62. if(krtc_init() < 0)
  63. {
  64. KALERT("%s: krtc_init failed!\n", __FUNCTION__);
  65. }
  66. memset(&g_dcaps, 0xFF, sizeof(g_dcaps));
  67. g_pFwBuffer = (void*)__get_free_pages(GFP_KERNEL, _FIRMWARE_PAGES_COUNT);
  68. return !!g_pFwBuffer;
  69. }
  70. void SfAttExit(void)
  71. {
  72. g_nCbFwData = 0;
  73. if(g_pFwBuffer)
  74. {
  75. free_pages((unsigned long)g_pFwBuffer, _FIRMWARE_PAGES_COUNT);
  76. g_pFwBuffer = NULL;
  77. }
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. static bool _AddressReadable(unsigned int nAddr, unsigned int nLength)
  81. {
  82. size_t i;
  83. LPCTIVA_MEMORY_MAP pmm = g_tiMM;
  84. for(i = 0; i < _countof(g_tiMM); ++i, ++pmm)
  85. {
  86. if( (nAddr < pmm->baseAddr + pmm->size) &&
  87. (nAddr >= pmm->baseAddr))
  88. {
  89. return (nAddr + nLength) <= pmm->baseAddr + pmm->size;
  90. }
  91. }
  92. return false;
  93. }
  94. static bool _AddressWriteable(unsigned int nAddr, unsigned int nLength)
  95. {
  96. size_t i;
  97. LPCTIVA_MEMORY_MAP pmm = g_tiMM;
  98. for(i = 0; i < _countof(g_tiMM); ++i, ++pmm)
  99. {
  100. if( !pmm->bIsRO &&
  101. (nAddr < pmm->baseAddr + pmm->size) &&
  102. (nAddr >= pmm->baseAddr))
  103. {
  104. return (nAddr + nLength) <= pmm->baseAddr + pmm->size;
  105. }
  106. }
  107. return false;
  108. }
  109. /////////////////////////////////////////////////////////////////////////////
  110. static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  111. {
  112. int hw, sw;
  113. ksync_lock();
  114. hw = g_hw;
  115. sw = g_sw;
  116. ksync_unlock();
  117. return sprintf(buf, "%d %d", hw, sw);
  118. }
  119. /////////////////////////////////////////////////////////////////////////////
  120. static ssize_t did_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  121. {
  122. TIVA_DCAP dcaps;
  123. ksync_lock();
  124. dcaps = g_dcaps;
  125. ksync_unlock();
  126. return sprintf(buf, "DID0: %08X\n" \
  127. "DID1: %08X\n" \
  128. "##############\n" \
  129. "DID0Ver: %X\n" \
  130. "Class: %X\n" \
  131. "RevMaj: %X\n" \
  132. "RevMin: %X\n" \
  133. "##############\n" \
  134. "DID1Ver: %X\n" \
  135. "Family: %X\n" \
  136. "PartNo: %X\n" \
  137. "PinCnt: %X\n" \
  138. "TempRange: %X\n" \
  139. "PackageType: %X\n" \
  140. "RoHSComp: %X\n" \
  141. "QualStat: %X\n", \
  142. dcaps.did0, dcaps.did1,
  143. dcaps.ver0, dcaps.cls, dcaps.maj, dcaps.min,
  144. dcaps.ver1, dcaps.fam, dcaps.partno, dcaps.pincnt, dcaps.temp, dcaps.pkg, dcaps.rohs, dcaps.qual);
  145. }
  146. static ssize_t uptime_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  147. {
  148. unsigned long long nVal;
  149. ksync_lock();
  150. nVal = g_nUpTime;
  151. ksync_unlock();
  152. return sprintf(buf, "%llu", nVal);
  153. }
  154. /////////////////////////////////////////////////////////////////////////////
  155. static ssize_t UVers_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  156. {
  157. int nVal;
  158. ksync_lock();
  159. nVal = g_tadc.UVers + 40;
  160. ksync_unlock();
  161. return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
  162. }
  163. /////////////////////////////////////////////////////////////////////////////
  164. static ssize_t UBatV3_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  165. {
  166. int nVal;
  167. ksync_lock();
  168. nVal = g_tadc.UBatV3;
  169. ksync_unlock();
  170. return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
  171. }
  172. /////////////////////////////////////////////////////////////////////////////
  173. static ssize_t TempBoard_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  174. {
  175. int nVal;
  176. ksync_lock();
  177. nVal = g_tadc.Temp;
  178. ksync_unlock();
  179. return sprintf(buf, "%d.%d0", nVal / 10, nVal % 10);
  180. }
  181. /////////////////////////////////////////////////////////////////////////////
  182. static ssize_t UV5Vsys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  183. {
  184. int nVal;
  185. ksync_lock();
  186. nVal = g_tadc.UV5Vsys;
  187. ksync_unlock();
  188. return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
  189. }
  190. /////////////////////////////////////////////////////////////////////////////
  191. static ssize_t UV3V6Bat_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  192. {
  193. int nVal;
  194. ksync_lock();
  195. nVal = g_tadc.UV3V6Bat;
  196. ksync_unlock();
  197. return sprintf(buf, "%d.%02d", nVal / 100, nVal % 100);
  198. }
  199. /////////////////////////////////////////////////////////////////////////////
  200. static ssize_t TempTIVA_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  201. {
  202. long nVal;
  203. ksync_lock();
  204. nVal = 14750 - 18750 * g_tadc.TempTIVA / 4096;
  205. ksync_unlock();
  206. return sprintf(buf, "%ld.%02ld", nVal / 100, nVal % 100);
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. static ssize_t AdcBin_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  210. {
  211. if(off >= sizeof(g_tadc))
  212. return 0;
  213. if((len + off) > sizeof(g_tadc))
  214. len = sizeof(g_tadc) - off;
  215. ksync_lock();
  216. memcpy(buf, ((const unsigned char*)&g_tadc) + off, len);
  217. ksync_unlock();
  218. return (ssize_t)len;
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. static ssize_t dutycycle_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  222. {
  223. ssize_t ret = -EINVAL;
  224. if(buf && count)
  225. {
  226. char szBuf[32];
  227. long long val;
  228. if(count >= sizeof(szBuf))
  229. return -ENOMEM;
  230. memcpy(szBuf, buf, count);
  231. szBuf[count] = '\0';
  232. if(!(ret = kstrtoll(szBuf, 10, &val)))
  233. {
  234. SfAttSetBacklightDutyCyclePercent(val);
  235. atomic_set(&g_flgBacklightChanged, 1);
  236. ret = count;
  237. }
  238. }
  239. return ret;
  240. }
  241. /////////////////////////////////////////////////////////////////////////////
  242. static ssize_t period_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  243. {
  244. ssize_t ret = -EINVAL;
  245. if(buf && count)
  246. {
  247. char szBuf[32];
  248. long long val;
  249. if(count >= sizeof(szBuf))
  250. return -ENOMEM;
  251. memcpy(szBuf, buf, count);
  252. szBuf[count] = '\0';
  253. if(!(ret = kstrtoll(szBuf, 10, &val)))
  254. {
  255. SfAttSetBacklightPeriod(val);
  256. atomic_set(&g_flgBacklightChanged, 1);
  257. ret = count;
  258. }
  259. }
  260. return ret;
  261. }
  262. /////////////////////////////////////////////////////////////////////////////
  263. static ssize_t image_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  264. {
  265. return -EACCES;
  266. /* if(off >= g_nCbFwData)
  267. return 0;
  268. if((off + len) > g_nCbFwData)
  269. len = g_nCbFwData - off;
  270. ksync_lock();
  271. memcpy(buf, ((char*)g_pFwBuffer) + off, len);
  272. ksync_unlock();
  273. KALERT("%s buf: %p, off: %lld, len: %zu\n", __FUNCTION__, buf, off, len);
  274. return len;*/
  275. }
  276. static ssize_t image_write(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  277. {
  278. int nRet;
  279. size_t nCbUbound;
  280. static KFW_DROP_CTX dctx;
  281. if(SfAttIsFirmwareLocked())
  282. return -EBUSY;
  283. else if(len == 0)
  284. return 0;
  285. else if(off < 0)
  286. return -EFAULT;
  287. else if(off >= _FIRMWARE_BUFFER_SIZE)
  288. return -ENOMEM;
  289. else if((off + len) > _FIRMWARE_BUFFER_SIZE)
  290. len = _FIRMWARE_BUFFER_SIZE - off;
  291. if(off == 0) // first block of data
  292. {
  293. memset(&dctx, 0, sizeof(dctx));
  294. ksync_lock();
  295. g_nCbFwData = 0;
  296. memset(g_pFwBuffer, 0xFF, _FIRMWARE_BUFFER_SIZE);
  297. ksync_unlock();
  298. }
  299. nCbUbound = off + len;
  300. ksync_lock();
  301. memcpy(((char*)g_pFwBuffer) + off, buf, len);
  302. if(g_nCbFwData < nCbUbound)
  303. g_nCbFwData = nCbUbound;
  304. ksync_unlock();
  305. if((nRet = KfwOnDataDropped(g_pFwBuffer, g_nCbFwData, &dctx)) < 0)
  306. {
  307. ksync_lock();
  308. g_nCbFwData = 0;
  309. ksync_unlock();
  310. memset(&dctx, 0, sizeof(dctx));
  311. SfAttLockFirmware(false);
  312. return nRet;
  313. }
  314. else if(nRet > 0)
  315. {
  316. ksync_lock();
  317. g_nCbFwData = 0;
  318. ksync_unlock();
  319. memset(&dctx, 0, sizeof(dctx));
  320. }
  321. // KALERT("%s buf: %p, off: %lld, len: %zu\n", __FUNCTION__, buf, off, len);
  322. return len;
  323. }
  324. /////////////////////////////////////////////////////////////////////////////
  325. static ssize_t mem_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  326. {
  327. int ret;
  328. unsigned int val;
  329. struct file *pfSpiDev = NULL;
  330. if(SfAttIsFirmwareLocked())
  331. return -EBUSY;
  332. if(off & 0x00000003)
  333. {
  334. KALERT("%s: Invalid address: %lld\n", __FUNCTION__, off);
  335. return -EFAULT;
  336. }
  337. if(len > sizeof(val))
  338. len = sizeof(val);
  339. else if(len < sizeof(val))
  340. {
  341. KALERT("%s: Buffer too small: %zu\n", __FUNCTION__, len);
  342. return -EINVAL;
  343. }
  344. if(!_AddressReadable(off, len))
  345. {
  346. KALERT("%s: Invalid address (0x%llX) or length (%zu)\n", __FUNCTION__, off, len);
  347. return -EACCES;
  348. }
  349. // KALERT("%s: Try to read from 0x%08llX, length %zu Bytes.\n", __FUNCTION__, off, len);
  350. if((pfSpiDev = kf_open_locked(_SPI_DEVICE, O_RDWR, 0)))
  351. {
  352. if(KSpiInit(pfSpiDev))
  353. {
  354. if(!(ret = TivaCmdGetAddress(pfSpiDev, (unsigned int)off, &val)))
  355. {
  356. memcpy(buf, &val, len);
  357. ret = (ssize_t)len;
  358. }
  359. else
  360. {
  361. KALERT("%s: TivaCmdGetAddress failed (%d)\n", __FUNCTION__, ret);
  362. ret = -EIO;
  363. }
  364. }
  365. else
  366. {
  367. KALERT("%s: KSpiInit failed\n", __FUNCTION__);
  368. ret = -EIO;
  369. }
  370. kf_close(pfSpiDev);
  371. }
  372. else
  373. {
  374. KALERT("%s: kf_open_locked failed\n", __FUNCTION__);
  375. ret = -EIO;
  376. }
  377. return ret;
  378. }
  379. static ssize_t mem_write(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  380. {
  381. int ret;
  382. struct file *pfSpiDev = NULL;
  383. if(SfAttIsFirmwareLocked())
  384. return -EBUSY;
  385. if(off & 0x00000003)
  386. {
  387. KALERT("%s: Invalid address: %lld\n", __FUNCTION__, off);
  388. return -EFAULT;
  389. }
  390. if(len != sizeof(unsigned int))
  391. {
  392. KALERT("%s: Invalid buffer size: %zu (must be %zu)\n", __FUNCTION__, len, sizeof(unsigned int));
  393. return -EINVAL;
  394. }
  395. if(!_AddressWriteable(off, len))
  396. {
  397. KALERT("%s: Invalid address (0x%llX) or length (%zu) or range is read-only!\n", __FUNCTION__, off, len);
  398. return -EACCES;
  399. }
  400. if((pfSpiDev = kf_open_locked(_SPI_DEVICE, O_RDWR, 0)))
  401. {
  402. if(KSpiInit(pfSpiDev))
  403. {
  404. unsigned int val;
  405. memcpy(&val, buf, sizeof(val));
  406. if(!(ret = TivaCmdSetAddress(pfSpiDev, (unsigned int)off, val)))
  407. {
  408. ret = (ssize_t)len;
  409. }
  410. else
  411. {
  412. KALERT("%s: TivaCmdSetAddress failed (%d)\n", __FUNCTION__, ret);
  413. ret = -EIO;
  414. }
  415. }
  416. else
  417. {
  418. KALERT("%s: KSpiInit failed\n", __FUNCTION__);
  419. ret = -EIO;
  420. }
  421. kf_close(pfSpiDev);
  422. }
  423. else
  424. {
  425. KALERT("%s: kf_open_locked failed\n", __FUNCTION__);
  426. ret = -EIO;
  427. }
  428. return ret;
  429. }
  430. static ssize_t map_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  431. {
  432. return sprintf(buf, "On-chip FLASH: %08X-%08X %7X %s\n" \
  433. "On-chip SRAM: %08X-%08X %7X %s\n" \
  434. "BBA SRAM: %08X-%08X %7X %s\n" \
  435. "Peripheral: %08X-%08X %7X %s\n" \
  436. "BBA Peripheral: %08X-%08X %7X %s\n",
  437. g_tiMM[0].baseAddr, g_tiMM[0].baseAddr + g_tiMM[0].size - 1, g_tiMM[0].size, g_tiMM[0].bIsRO ? "RO" : "RW",
  438. g_tiMM[1].baseAddr, g_tiMM[1].baseAddr + g_tiMM[1].size - 1, g_tiMM[1].size, g_tiMM[1].bIsRO ? "RO" : "RW",
  439. g_tiMM[2].baseAddr, g_tiMM[2].baseAddr + g_tiMM[2].size - 1, g_tiMM[2].size, g_tiMM[2].bIsRO ? "RO" : "RW",
  440. g_tiMM[3].baseAddr, g_tiMM[3].baseAddr + g_tiMM[3].size - 1, g_tiMM[3].size, g_tiMM[3].bIsRO ? "RO" : "RW",
  441. g_tiMM[4].baseAddr, g_tiMM[4].baseAddr + g_tiMM[4].size - 1, g_tiMM[4].size, g_tiMM[4].bIsRO ? "RO" : "RW");
  442. }
  443. /////////////////////////////////////////////////////////////////////////////
  444. static ssize_t iso8601_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  445. {
  446. int ret;
  447. struct tm tm;
  448. if(SfAttIsFirmwareLocked())
  449. {
  450. KALERT("%s: Firmware update in progress!\n", __FUNCTION__);
  451. return -EBUSY;
  452. }
  453. SfAttLockFirmware(true);
  454. if((ret = krtc_get_date_time(&tm)) < 0)
  455. {
  456. SfAttLockFirmware(false);
  457. KALERT("%s: krtc_get_date_time failed!\n", __FUNCTION__);
  458. return ret;
  459. }
  460. SfAttLockFirmware(false);
  461. return sprintf(buf, "%04ld-%02d-%02dT%02d:%02d:%02d+00:00\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  462. }
  463. static ssize_t uxts64bin_read(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  464. {
  465. int ret;
  466. time64_t ts;
  467. struct tm tm;
  468. if(off != 0)
  469. {
  470. KALERT("%s: Offset must be 0!\n", __FUNCTION__);
  471. return -EINVAL;
  472. }
  473. if(len < sizeof(ts))
  474. {
  475. KALERT("%s: Insufficient buffer size: %zu! At least %zu bytes are required!\n", __FUNCTION__, len, sizeof(time64_t));
  476. return -ENOMEM;
  477. }
  478. if(SfAttIsFirmwareLocked())
  479. {
  480. KALERT("%s: Firmware update in progress!\n", __FUNCTION__);
  481. return -EBUSY;
  482. }
  483. SfAttLockFirmware(true);
  484. if((ret = krtc_get_date_time(&tm)) < 0)
  485. {
  486. SfAttLockFirmware(false);
  487. KALERT("%s: krtc_get_date_time failed!\n", __FUNCTION__);
  488. return ret;
  489. }
  490. SfAttLockFirmware(false);
  491. ts = mktime64(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  492. memcpy(buf, &ts, sizeof(ts));
  493. return sizeof(ts);
  494. }
  495. static ssize_t uxts64bin_write(struct file *pf, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t len)
  496. {
  497. int ret;
  498. time64_t ts;
  499. struct tm tm;
  500. if(off != 0 || len != sizeof(time64_t))
  501. {
  502. KALERT("%s: Offset must be 0 and length must be %zu byte!\n", __FUNCTION__, sizeof(time64_t));
  503. return -EINVAL;
  504. }
  505. memcpy(&ts, buf, sizeof(ts));
  506. if((ts < KRTC_TIMESTAMP_2000_01_01) || (ts >= KRTC_TIMESTAMP_2100_01_01))
  507. {
  508. KALERT("%s: Date/Time must be >= 2000-01-01 00:00:00 and < 2100-01-01 00:00:00!\n", __FUNCTION__);
  509. return -EINVAL;
  510. }
  511. time64_to_tm(ts, 0, &tm);
  512. if(SfAttIsFirmwareLocked())
  513. {
  514. KALERT("%s: Firmware update in progress!\n", __FUNCTION__);
  515. return -EBUSY;
  516. }
  517. SfAttLockFirmware(true);
  518. if((ret = krtc_set_date_time(&tm)) < 0)
  519. {
  520. SfAttLockFirmware(false);
  521. KALERT("%s: krtc_get_date_time failed!\n", __FUNCTION__);
  522. return ret;
  523. }
  524. SfAttLockFirmware(false);
  525. return len;
  526. }
  527. /////////////////////////////////////////////////////////////////////////////
  528. static ssize_t ctrl_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  529. {
  530. return sprintf(buf, "SysToRtc > 1\n" \
  531. "RtcToSys > 2\n" \
  532. "TestI2C > 3\n");
  533. }
  534. static ssize_t ctrl_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
  535. {
  536. int ret;
  537. time64_t ts;
  538. struct tm tm;
  539. struct timespec64 tp;
  540. if(SfAttIsFirmwareLocked())
  541. {
  542. KALERT("%s: Firmware update in progress!\n", __FUNCTION__);
  543. return -EBUSY;
  544. }
  545. if(count == 2)
  546. {
  547. if(!isspace(buf[1]) && (buf[1] != 0))
  548. {
  549. KALERT("%s: Invalid input: \"%s\"!\n", __FUNCTION__, buf);
  550. return -EINVAL;
  551. }
  552. }
  553. else if(count != 1)
  554. {
  555. KALERT("%s: Invalid input: \"%s\"!\n", __FUNCTION__, buf);
  556. return -EINVAL;
  557. }
  558. switch(*buf)
  559. {
  560. case 1:
  561. case '1':
  562. // KALERT("%s: Set System time to RTC\n", __FUNCTION__);
  563. SfAttLockFirmware(true);
  564. ts = ktime_get_real_seconds();
  565. if((ts < KRTC_TIMESTAMP_2000_01_01) || (ts >= KRTC_TIMESTAMP_2100_01_01))
  566. {
  567. SfAttLockFirmware(false);
  568. KALERT("%s: Date/Time must be >= 2000-01-01 00:00:00 and < 2100-01-01 00:00:00!\n", __FUNCTION__);
  569. return -EINVAL;
  570. }
  571. time64_to_tm(ts, 0, &tm);
  572. if((ret = krtc_set_date_time(&tm)) < 0)
  573. {
  574. SfAttLockFirmware(false);
  575. KALERT("%s: krtc_get_date_time failed!\n", __FUNCTION__);
  576. return ret;
  577. }
  578. SfAttLockFirmware(false);
  579. break;
  580. case 2:
  581. case '2':
  582. // KALERT("%s: Set RTC to System time\n", __FUNCTION__);
  583. SfAttLockFirmware(true);
  584. if((ret = krtc_get_date_time(&tm)) < 0)
  585. {
  586. SfAttLockFirmware(false);
  587. KALERT("%s: krtc_get_date_time failed!\n", __FUNCTION__);
  588. return ret;
  589. }
  590. ts = mktime64(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  591. tp.tv_sec = ts;
  592. tp.tv_nsec = 0;
  593. do_settimeofday64(&tp);
  594. SfAttLockFirmware(false);
  595. break;
  596. case 3:
  597. case '3':
  598. SfAttLockFirmware(true);
  599. if((ret = krtc_test_i2c()))
  600. {
  601. SfAttLockFirmware(false);
  602. KALERT("%s: I2C-Test error: %d!\n", __FUNCTION__, ret);
  603. return ret;
  604. }
  605. else
  606. KALERT("%s: I2C-Test success!\n", __FUNCTION__);
  607. SfAttLockFirmware(false);
  608. break;
  609. default:
  610. KALERT("%s: Invalid input: \"%c\"!\n", __FUNCTION__, *buf);
  611. return -EINVAL;
  612. }
  613. return count;
  614. }
  615. /////////////////////////////////////////////////////////////////////////////
  616. static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  617. {
  618. const char *pszType;
  619. RTCTypes type = krtc_get_type();
  620. switch(type)
  621. {
  622. case RTCT_MCP7940:
  623. pszType = "MCP7940";
  624. break;
  625. case RTCT_DS3231:
  626. pszType = "DS3231";
  627. break;
  628. default:
  629. pszType = "Unknown";
  630. break;
  631. }
  632. return sprintf(buf, "%s\n", pszType);
  633. }
  634. /////////////////////////////////////////////////////////////////////////////
  635. bool SfAttIsFirmwareLocked(void)
  636. {
  637. return !!atomic_read(&g_flgFwLocked);
  638. }
  639. /////////////////////////////////////////////////////////////////////////////
  640. void SfAttLockFirmware(bool bLock)
  641. {
  642. atomic_set(&g_flgFwLocked, bLock ? 1 : 0);
  643. }
  644. /////////////////////////////////////////////////////////////////////////////
  645. unsigned int SfAttGetBacklightDutyCyclePercent(void)
  646. {
  647. return (unsigned int)atomic_read(&g_valBacklightDutyCyclePercent);
  648. }
  649. /////////////////////////////////////////////////////////////////////////////
  650. void SfAttSetBacklightDutyCyclePercent(int val)
  651. {
  652. if(val < _BACKLIGHT_DUTY_CYCLE_PERC_MIN)
  653. val = _BACKLIGHT_DUTY_CYCLE_PERC_MIN;
  654. else if(val > _BACKLIGHT_DUTY_CYCLE_PERC_MAX)
  655. val = _BACKLIGHT_DUTY_CYCLE_PERC_MAX;
  656. atomic_set(&g_valBacklightDutyCyclePercent, val);
  657. }
  658. /////////////////////////////////////////////////////////////////////////////
  659. unsigned int SfAttGetBacklightPeriod(void)
  660. {
  661. return (unsigned int)atomic_read(&g_valBacklightPeriod);
  662. }
  663. /////////////////////////////////////////////////////////////////////////////
  664. void SfAttSetBacklightPeriod(int val)
  665. {
  666. if(val < _BACKLIGHT_PERIOD_MIN)
  667. val = _BACKLIGHT_PERIOD_MIN;
  668. else if(val > _BACKLIGHT_PERIOD_MAX)
  669. val = _BACKLIGHT_PERIOD_MAX;
  670. atomic_set(&g_valBacklightPeriod, val);
  671. }
  672. /////////////////////////////////////////////////////////////////////////////
  673. bool SfAttBacklightChanged(void)
  674. {
  675. bool ret = !!atomic_read(&g_flgBacklightChanged);
  676. if(ret)
  677. atomic_set(&g_flgBacklightChanged, 0);
  678. return ret;
  679. }
  680. /////////////////////////////////////////////////////////////////////////////
  681. /////////////////////////////////////////////////////////////////////////////
  682. /////////////////////////////////////////////////////////////////////////////
  683. // tiva generic
  684. struct kobj_attribute g_tivaDevIdAtt = __ATTR_RO(did);
  685. struct kobj_attribute g_tivaUptimeAtt = __ATTR_RO(uptime);
  686. /////////////////////////////////////////////////////////////////////////////
  687. // backlight
  688. struct kobj_attribute g_tivaDutyCycleAtt = __ATTR_WO(dutycycle);
  689. struct kobj_attribute g_tivaPeriodAtt = __ATTR_WO(period);
  690. /////////////////////////////////////////////////////////////////////////////
  691. // ADC
  692. struct kobj_attribute g_tivaUVersAtt = __ATTR_RO(UVers);
  693. struct kobj_attribute g_tivaUBatV3Att = __ATTR_RO(UBatV3);
  694. struct kobj_attribute g_tivaTempAtt = __ATTR_RO(TempBoard);
  695. struct kobj_attribute g_tivaUV5VsysAtt = __ATTR_RO(UV5Vsys);
  696. struct kobj_attribute g_tivaUV3V6BatAtt = __ATTR_RO(UV3V6Bat);
  697. struct kobj_attribute g_tivaTempTIVAAtt = __ATTR_RO(TempTIVA);
  698. struct bin_attribute g_tivaAdcBinAtt = __BIN_ATTR_RO(AdcBin, sizeof(TIVA_ADC));
  699. /////////////////////////////////////////////////////////////////////////////
  700. // tiva firmware
  701. struct kobj_attribute g_tivaVersionAtt = __ATTR_RO(version);
  702. struct bin_attribute g_tivaFwImageAtt = __BIN_ATTR_RW(image, 0);
  703. /////////////////////////////////////////////////////////////////////////////
  704. // tiva memory
  705. struct bin_attribute g_tivaMemory = __BIN_ATTR_RW(mem, 0);
  706. struct kobj_attribute g_tivaMemMap = __ATTR_RO(map);
  707. /////////////////////////////////////////////////////////////////////////////
  708. // tiva RTC
  709. struct kobj_attribute g_tivaRtcIso8601 = __ATTR_RO(iso8601);
  710. struct bin_attribute g_tivaRtcUnTsBin64 = __BIN_ATTR_RW(uxts64bin, sizeof(time64_t));
  711. struct kobj_attribute g_tivaRtcCtrl = __ATTR_RW(ctrl);
  712. struct kobj_attribute g_tivaRtcType = __ATTR_RO(type);