sfsattrib.c 21 KB

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