Advertisement
Guest User

Untitled

a guest
Jan 25th, 2013
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.71 KB | None | 0 0
  1. //
  2. // Copyright (C) 2011 Andy Pugh
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //
  19. // The code in this file is based on UFLBP.PAS by Peter C. Wallace.
  20.  
  21. #include <linux/firmware.h>
  22. #include "rtapi.h"
  23. #include "rtapi_app.h"
  24. #include "hal.h"
  25. #include "hostmot2.h"
  26. #include "sserial.h"
  27.  
  28. static int comp_id;
  29.  
  30. /* module information */
  31. MODULE_AUTHOR("Andy Pugh");
  32. MODULE_DESCRIPTION("A simple util for nvram setting on smart-serial cards");
  33. MODULE_LICENSE("GPL");
  34.  
  35. static char *cmd;
  36. RTAPI_MP_STRING(cmd, "smart-serial setting commands");
  37.  
  38. char **cmd_list;
  39.  
  40. hostmot2_t *hm2;
  41. hm2_sserial_remote_t *remote;
  42.  
  43. int waitfor(void){
  44. u32 buff;
  45. long long int starttime = rtapi_get_time();
  46. do {
  47. rtapi_delay(50000);
  48. HM2READ(remote->command_reg_addr, buff);
  49. if (rtapi_get_time() - starttime > 1000000000){
  50. rtapi_print_msg(RTAPI_MSG_ERR, "Timeout waiting for CMD to clear\n");
  51. return -1;
  52. }
  53. } while (buff);
  54.  
  55. return 0;
  56. }
  57.  
  58. int doit(void){
  59. u32 buff = 0x1000 | (1 << remote->index);
  60. HM2WRITE(remote->command_reg_addr, buff);
  61. if (waitfor() < 0) return -1;
  62. HM2READ(remote->data_reg_addr, buff);
  63. if (buff & (1 << remote->index)){
  64. rtapi_print_msg(RTAPI_MSG_ERR, "Error flag set after CMD Clear %08x\n",
  65. buff);
  66. return -1;
  67. }
  68. return 0;
  69. }
  70.  
  71. int stop_all(void){
  72. int buff=0x8FF;
  73. HM2WRITE(remote->command_reg_addr, buff);
  74. return waitfor();
  75. }
  76.  
  77. int setup_start(void){
  78. int buff=0xF00 | 1 << remote->index;
  79. HM2WRITE(remote->command_reg_addr, buff);
  80. if (waitfor() < 0) return -1;
  81. HM2READ(remote->data_reg_addr, buff);
  82. rtapi_print("setup start: data_reg readback = %x\n", buff);
  83. if (buff & (1 << remote->index)){
  84. rtapi_print("Remote failed to start\n");
  85. return -1;
  86. }
  87. return 0;
  88. }
  89.  
  90. int nv_access(int type){
  91. int buff = LBPNONVOL_flag + LBPWRITE;
  92. rtapi_print("buff = %x\n", buff);
  93. HM2WRITE(remote->reg_cs_addr, buff);
  94. HM2WRITE(remote->reg_0_addr, type);
  95. return doit();
  96. }
  97.  
  98. int set_nvram_param(u32 addr, u32 value){
  99. int buff;
  100.  
  101. if (stop_all() < 0) goto fail0;
  102. if (setup_start() < 0) goto fail0;
  103. if (nv_access(LBPNONVOLEEPROM) < 0) goto fail0;
  104.  
  105. // value to set
  106. HM2WRITE(remote->reg_0_addr, value);
  107. buff = WRITE_REM_WORD_CMD | addr;
  108. HM2WRITE(remote->reg_cs_addr, buff);
  109. if (doit() < 0) goto fail0;
  110.  
  111. if (nv_access(LBPNONVOLCLEAR) < 0) goto fail0;
  112.  
  113. return 0;
  114. fail0: // It's all gone wrong
  115. buff=0x800; //Stop
  116. HM2WRITE(remote->command_reg_addr, buff);
  117. rtapi_print_msg(RTAPI_MSG_ERR,
  118. "Problem with Smart Serial parameter setting, see dmesg\n");
  119. return -1;
  120. }
  121.  
  122. static void setsserial_release(struct device *dev) {
  123. // nothing to do here
  124. }
  125.  
  126. int getlocal(int addr, int bytes){
  127. u32 val = 0;
  128. u32 buff;
  129. for (;bytes--;){
  130. buff = READ_LOCAL_CMD | (addr + bytes);
  131. HM2WRITE(remote->command_reg_addr, buff);
  132. waitfor();
  133. HM2READ(remote->data_reg_addr, buff);
  134. val = (val << 8) | buff;
  135. } return val;
  136. }
  137.  
  138. int setlocal(int addr, int val, int bytes){
  139. unsigned char b = 0;
  140. u32 buff;
  141. int i;
  142. for (i = 0; i < bytes; i++){
  143. b = val & 0xFF;
  144. val >>= 8;
  145. HM2WRITE(remote->data_reg_addr, b);
  146. buff = WRITE_LOCAL_CMD | (addr + i);
  147. HM2WRITE(remote->command_reg_addr, buff);
  148. if (waitfor() < 0) return -1;
  149. }
  150. return 0;
  151. }
  152.  
  153. void sslbp_write_lbp(u32 cmd, u32 data){
  154. u32 buff = LBPWRITE + cmd;
  155. HM2WRITE(remote->reg_cs_addr, buff);
  156. HM2WRITE(remote->reg_0_addr, data);
  157. doit();
  158. buff = 0;
  159. HM2WRITE(remote->reg_cs_addr, buff);
  160. }
  161.  
  162. u8 sslbp_read_cookie(void){
  163. u32 buff = READ_COOKIE_CMD;
  164. u8 res;
  165. HM2WRITE(remote->reg_cs_addr, buff);
  166. if (doit() < 0){
  167. HM2_ERR("Error in sslbp_read_cookie, trying to abort\n");
  168. return -1;
  169. }
  170. HM2READ(remote->reg_0_addr, res);
  171. buff = 0;
  172. HM2WRITE(remote->reg_cs_addr, buff);
  173. return res;
  174. }
  175.  
  176. u8 sslbp_read_byte(u32 addr){
  177. u32 buff = READ_REM_BYTE_CMD + addr;
  178. u32 res;
  179. HM2WRITE(remote->reg_cs_addr, buff);
  180. if (doit() < 0){
  181. HM2_ERR("Error in sslbp_read_byte, trying to abort\n");
  182. return -1;
  183. }
  184. HM2READ(remote->reg_0_addr, res);
  185. buff = 0;
  186. HM2WRITE(remote->reg_cs_addr, buff);
  187. return res;
  188. }
  189.  
  190. u16 sslbp_read_word(u32 addr){
  191. u32 buff = READ_REM_WORD_CMD + addr;
  192. u32 res;
  193. HM2WRITE(remote->reg_cs_addr, buff);
  194. if (doit() < 0){
  195. HM2_ERR("Error in sslbp_read_word, trying to abort\n");
  196. return -1;
  197. }
  198. HM2READ(remote->reg_0_addr, res);
  199. buff = 0;
  200. HM2WRITE(remote->reg_cs_addr, buff);
  201. return res;
  202. }
  203.  
  204. u32 sslbp_read_long(u32 addr){
  205. u32 buff = READ_REM_LONG_CMD + addr;
  206. u32 res;
  207. HM2WRITE(remote->reg_cs_addr, buff);
  208. if (doit() < 0){
  209. HM2_ERR("Error in sslbp_read_long, trying to abort\n");
  210. return -1;
  211. }
  212. HM2READ(remote->reg_0_addr, buff);
  213. buff = 0;
  214. HM2WRITE(remote->reg_cs_addr, buff);
  215. return res;
  216. }
  217.  
  218. u64 sslbp_read_double(u32 addr){
  219. u64 res;
  220. u32 buff = READ_REM_DOUBLE_CMD + addr;
  221. HM2WRITE(remote->reg_cs_addr, buff);
  222. if (doit() < 0){
  223. HM2_ERR("Error in sslbp_read_double, trying to abort\n");
  224. return -1;
  225. }
  226. HM2READ(remote->reg_1_addr, buff);
  227. res = buff;
  228. res <<= 32;
  229. HM2READ(remote->reg_0_addr, buff);
  230. res += buff;
  231. buff = 0;
  232. HM2WRITE(remote->reg_cs_addr, buff);
  233. return res;
  234. }
  235.  
  236. int sslbp_write_byte(u32 addr, u32 data){
  237. u32 buff = WRITE_REM_BYTE_CMD + addr;
  238. HM2WRITE(remote->reg_cs_addr, buff);
  239. HM2WRITE(remote->reg_0_addr, data);
  240. if (doit() < 0){
  241. HM2_ERR("Error in sslbp_write_byte, trying to abort\n");
  242. return -1;
  243. }
  244. buff = 0;
  245. HM2WRITE(remote->reg_cs_addr, buff);
  246. return 0;
  247. }
  248.  
  249. int sslbp_write_word(u32 addr, u32 data){
  250. u32 buff = WRITE_REM_WORD_CMD + addr;
  251. HM2WRITE(remote->reg_cs_addr, buff);
  252. HM2WRITE(remote->reg_0_addr, data);
  253. if (doit() < 0){
  254. HM2_ERR("Error in sslbp_write_word, trying to abort\n");
  255. return -1;
  256. }
  257. buff = 0;
  258. HM2WRITE(remote->reg_cs_addr, buff);
  259. return 0;
  260. }
  261.  
  262. int sslbp_write_long(u32 addr, u32 data){
  263. u32 buff = WRITE_REM_LONG_CMD + addr;
  264. HM2WRITE(remote->reg_cs_addr, buff);
  265. HM2WRITE(remote->reg_0_addr, data);
  266. if (doit() < 0){
  267. HM2_ERR("Error in sslbp_write_long, trying to abort\n");
  268. return -1;
  269. }
  270. buff = 0;
  271. HM2WRITE(remote->reg_cs_addr, buff);
  272. return 0;
  273. }
  274.  
  275. int sslbp_write_double(u32 addr, u32 data0, u32 data1){
  276. u32 buff = WRITE_REM_DOUBLE_CMD + addr;
  277. HM2WRITE(remote->reg_cs_addr, buff);
  278. HM2WRITE(remote->reg_0_addr, data0);
  279. HM2WRITE(remote->reg_1_addr, data1);
  280. if (doit() < 0){
  281. HM2_ERR("Error in sslbp_write_double, trying to abort\n");
  282. return -1;
  283. }
  284. buff = 0;
  285. HM2WRITE(remote->reg_cs_addr, buff);
  286. return 0;
  287. }
  288.  
  289.  
  290. void flash_start(void){
  291. sslbp_write_lbp(LBPNONVOL_flag, LBPNONVOLFLASH);
  292. }
  293.  
  294. void flash_stop(void){
  295. sslbp_write_lbp(LBPNONVOL_flag, 0);
  296. }
  297.  
  298. int sslbp_flash(char *fname){
  299. const struct firmware *fw;
  300. struct device dev;
  301. int r;
  302. int write_sz, erase_sz;
  303.  
  304. if (strstr("8i20", remote->name)){
  305. if (hm2->sserial.version < 40){
  306. rtapi_print("SSLBP Version must be at least v37 to flash the 8i20"
  307. "This firmware has v%i. Sorry about that\n"
  308. ,hm2->sserial.version);
  309. return -1;
  310. }
  311. }
  312. else if (hm2->sserial.version < 34){
  313. rtapi_print("SSLBP Version must be at least v34. This firmware has v%i"
  314. "\n",hm2->sserial.version);
  315. return -1;
  316. }
  317.  
  318. if (hm2->sserial.baudrate != 115200){
  319. rtapi_print("To flash firmware the baud rate of the board must be set "
  320. "to 115200 by jumper, and in Hostmot2 using the "
  321. "sserial_baudrate modparam\n");
  322. goto fail0;
  323. }
  324.  
  325. //Copied direct from hostmot2.c. A bit of a faff, but seems to be necessary.
  326. memset(&dev, '\0', sizeof(dev));
  327. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
  328. strncpy(dev.bus_id, hm2->llio->name, BUS_ID_SIZE);
  329. dev.bus_id[BUS_ID_SIZE - 1] = '\0';
  330. #else
  331. dev_set_name(&dev, hm2->llio->name);
  332. #endif
  333. dev.release = setsserial_release;
  334. r = device_register(&dev);
  335. if (r != 0) {
  336. HM2_ERR("error with device_register\n");
  337. goto fail0;
  338. }
  339. r = request_firmware(&fw, fname, &dev);
  340. device_unregister(&dev);
  341. if (r == -ENOENT) {
  342. HM2_ERR("firmware %s not found\n",fname);
  343. goto fail0;
  344. }
  345. if (r != 0) {
  346. HM2_ERR("request for firmware %s failed, aborting\n", fname);
  347. goto fail0;
  348. }
  349. rtapi_print("Firmware size 0x%x\n", fw->size);
  350.  
  351. if (setup_start() < 0) goto fail0;
  352. flash_start();
  353. write_sz = 1 << sslbp_read_byte(LBPFLASHWRITESIZELOC);
  354. erase_sz = 1 << sslbp_read_byte(LBPFLASHERASESIZELOC);
  355. HM2_PRINT("Write Size = %x, Erase Size = %x\n", write_sz, erase_sz);
  356. flash_stop();
  357.  
  358. //Programming Loop
  359. {
  360. int ReservedBlock = 0;
  361. int StartBlock = ReservedBlock + 1;
  362.  
  363. int blocknum = StartBlock;
  364. int block_start;
  365. int i, j, t;
  366. while (blocknum * erase_sz < fw->size){
  367. block_start = blocknum * erase_sz;
  368. HM2_PRINT("block_start %i blocknum %i erase_sz %i\n", block_start, blocknum, erase_sz);
  369. for (t = 0; t < erase_sz && fw->data[block_start + t] == 0 ; t++){ }
  370. if (t < erase_sz){ // found a non-zero byte
  371. flash_start();
  372. sslbp_write_long(LBPFLASHOFFSETLOC, block_start);
  373. //sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHERASE_CMD);
  374. sslbp_write_byte(LBPFLASHCOMMITLOC, 0);
  375. if (sslbp_read_cookie() != LBPCOOKIE){
  376. HM2_ERR("Synch failed during block erase: aborting\n");
  377. goto fail0;
  378. }
  379. flash_stop();
  380. HM2_PRINT("Erased block %i\n", blocknum);
  381. flash_start();
  382. for (i = 0; i < erase_sz ; i += write_sz){
  383. //sslbp_write_long(LBPFLASHOFFSETLOC, block_start + i);
  384. for (j = 0 ; j < write_sz ; j += 8){
  385. u32 data0, data1;
  386. memcpy(&data0, &(fw->data[block_start + i + j]), 4);
  387. memcpy(&data1, &(fw->data[block_start + i + j + 4]), 4);
  388. //sslbp_write_double(j, data0, data1);
  389. }
  390. //sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHWRITE_CMD);
  391. //sslbp_write_byte(LBPFLASHCOMMITLOC, 0);
  392. //if (sslbp_read_cookie() != LBPCOOKIE){
  393. // HM2_ERR("Synch failed during block write: aborting\n");
  394. // goto fail0;
  395. //}
  396. }
  397. flash_stop();
  398. HM2_PRINT("Wrote block %i\n", blocknum);
  399. }
  400. else // Looks like an all-zeros block
  401. {
  402. HM2_PRINT("Skipped Block %i\n", blocknum);
  403. }
  404. blocknum++;
  405. }
  406. }
  407.  
  408. release_firmware(fw);
  409.  
  410. return 0;
  411.  
  412. fail0:
  413. flash_stop();
  414. return -1;
  415. }
  416.  
  417. int rtapi_app_main(void)
  418. {
  419. int cnt;
  420.  
  421. comp_id = hal_init("setsserial");
  422. hal_ready(comp_id);
  423.  
  424. cmd_list = argv_split(GFP_KERNEL, cmd, &cnt);
  425.  
  426. remote = hm2_get_sserial(&hm2, cmd_list[1]);
  427. if (! remote) {
  428. rtapi_print_msg(RTAPI_MSG_ERR,
  429. "Unable to find sserial remote corresponding to %s\n",
  430. cmd_list[1]);
  431. return -1;
  432. }
  433.  
  434. if (! strncmp("set", cmd_list[0], 3) && cnt == 3){
  435. u32 value;
  436. u32 addr;
  437. int i;
  438. rtapi_print("set command %s\n", cmd_list[1]);
  439. addr = 0;
  440. for (i = 0; i < remote->num_globals; i++){
  441. if (strstr(cmd_list[1], remote->globals[i].NameString)){
  442. addr = remote->globals[i].ParmAddr;
  443. break;
  444. }
  445. }
  446. if (! addr) {
  447. rtapi_print_msg(RTAPI_MSG_ERR,
  448. "Unable to find parameter corresponding to %s\n",
  449. cmd_list[1]);
  450. return -1;
  451. }
  452. value = simple_strtol(cmd_list[2], NULL, 0);
  453. rtapi_print("remote name = %s ParamAddr = %x Value = %i\n",
  454. remote->name,
  455. addr,
  456. value);
  457. if (set_nvram_param(addr, value) < 0) {
  458. rtapi_print_msg(RTAPI_MSG_ERR, "Parameter setting failed\n");
  459. return -1;
  460. }
  461. else
  462. { rtapi_print_msg(RTAPI_MSG_ERR, "Parameter setting success\n");
  463. return 0;
  464. }
  465. }
  466. else if (! strncmp("flash", cmd_list[0], 5) && cnt == 3){
  467. rtapi_print("flash command\n");
  468. if ( ! strstr(cmd_list[2], ".BIN")){
  469. rtapi_print("Smart-Serial remote firmwares are .BIN format\n "
  470. "flashing with the wrong one would be bad. Aborting\n");
  471. return -EINVAL;
  472. }
  473. if (sslbp_flash(cmd_list[2]) < 0){
  474. rtapi_print_msg(RTAPI_MSG_ERR, "Firmware Flash Failed\n");
  475. return -1;
  476. }
  477. else
  478. { rtapi_print_msg(RTAPI_MSG_ERR, "Firmware Flash Success\n");
  479. return 0;
  480. }
  481. }
  482. else {
  483. rtapi_print_msg(RTAPI_MSG_ERR,
  484. "Unknown commmand or wrong number of parameters to "
  485. "setsserial command");
  486. return -1;
  487. }
  488.  
  489. return 0;
  490. }
  491.  
  492. void rtapi_app_exit(void)
  493. {
  494. hal_exit(comp_id);
  495. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement