Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Copyright (C) 2011 Andy Pugh
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //
- // The code in this file is based on UFLBP.PAS by Peter C. Wallace.
- #include <linux/firmware.h>
- #include "rtapi.h"
- #include "rtapi_app.h"
- #include "hal.h"
- #include "hostmot2.h"
- #include "sserial.h"
- static int comp_id;
- /* module information */
- MODULE_AUTHOR("Andy Pugh");
- MODULE_DESCRIPTION("A simple util for nvram setting on smart-serial cards");
- MODULE_LICENSE("GPL");
- static char *cmd;
- RTAPI_MP_STRING(cmd, "smart-serial setting commands");
- char **cmd_list;
- hostmot2_t *hm2;
- hm2_sserial_remote_t *remote;
- int waitfor(void){
- u32 buff;
- long long int starttime = rtapi_get_time();
- do {
- rtapi_delay(50000);
- HM2READ(remote->command_reg_addr, buff);
- if (rtapi_get_time() - starttime > 1000000000){
- rtapi_print_msg(RTAPI_MSG_ERR, "Timeout waiting for CMD to clear\n");
- return -1;
- }
- } while (buff);
- return 0;
- }
- int doit(void){
- u32 buff = 0x1000 | (1 << remote->index);
- HM2WRITE(remote->command_reg_addr, buff);
- if (waitfor() < 0) return -1;
- HM2READ(remote->data_reg_addr, buff);
- if (buff & (1 << remote->index)){
- rtapi_print_msg(RTAPI_MSG_ERR, "Error flag set after CMD Clear %08x\n",
- buff);
- return -1;
- }
- return 0;
- }
- int stop_all(void){
- int buff=0x8FF;
- HM2WRITE(remote->command_reg_addr, buff);
- return waitfor();
- }
- int setup_start(void){
- int buff=0xF00 | 1 << remote->index;
- HM2WRITE(remote->command_reg_addr, buff);
- if (waitfor() < 0) return -1;
- HM2READ(remote->data_reg_addr, buff);
- rtapi_print("setup start: data_reg readback = %x\n", buff);
- if (buff & (1 << remote->index)){
- rtapi_print("Remote failed to start\n");
- return -1;
- }
- return 0;
- }
- int nv_access(int type){
- int buff = LBPNONVOL_flag + LBPWRITE;
- rtapi_print("buff = %x\n", buff);
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, type);
- return doit();
- }
- int set_nvram_param(u32 addr, u32 value){
- int buff;
- if (stop_all() < 0) goto fail0;
- if (setup_start() < 0) goto fail0;
- if (nv_access(LBPNONVOLEEPROM) < 0) goto fail0;
- // value to set
- HM2WRITE(remote->reg_0_addr, value);
- buff = WRITE_REM_WORD_CMD | addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0) goto fail0;
- if (nv_access(LBPNONVOLCLEAR) < 0) goto fail0;
- return 0;
- fail0: // It's all gone wrong
- buff=0x800; //Stop
- HM2WRITE(remote->command_reg_addr, buff);
- rtapi_print_msg(RTAPI_MSG_ERR,
- "Problem with Smart Serial parameter setting, see dmesg\n");
- return -1;
- }
- static void setsserial_release(struct device *dev) {
- // nothing to do here
- }
- int getlocal(int addr, int bytes){
- u32 val = 0;
- u32 buff;
- for (;bytes--;){
- buff = READ_LOCAL_CMD | (addr + bytes);
- HM2WRITE(remote->command_reg_addr, buff);
- waitfor();
- HM2READ(remote->data_reg_addr, buff);
- val = (val << 8) | buff;
- } return val;
- }
- int setlocal(int addr, int val, int bytes){
- unsigned char b = 0;
- u32 buff;
- int i;
- for (i = 0; i < bytes; i++){
- b = val & 0xFF;
- val >>= 8;
- HM2WRITE(remote->data_reg_addr, b);
- buff = WRITE_LOCAL_CMD | (addr + i);
- HM2WRITE(remote->command_reg_addr, buff);
- if (waitfor() < 0) return -1;
- }
- return 0;
- }
- void sslbp_write_lbp(u32 cmd, u32 data){
- u32 buff = LBPWRITE + cmd;
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, data);
- doit();
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- }
- u8 sslbp_read_cookie(void){
- u32 buff = READ_COOKIE_CMD;
- u8 res;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_read_cookie, trying to abort\n");
- return -1;
- }
- HM2READ(remote->reg_0_addr, res);
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return res;
- }
- u8 sslbp_read_byte(u32 addr){
- u32 buff = READ_REM_BYTE_CMD + addr;
- u32 res;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_read_byte, trying to abort\n");
- return -1;
- }
- HM2READ(remote->reg_0_addr, res);
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return res;
- }
- u16 sslbp_read_word(u32 addr){
- u32 buff = READ_REM_WORD_CMD + addr;
- u32 res;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_read_word, trying to abort\n");
- return -1;
- }
- HM2READ(remote->reg_0_addr, res);
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return res;
- }
- u32 sslbp_read_long(u32 addr){
- u32 buff = READ_REM_LONG_CMD + addr;
- u32 res;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_read_long, trying to abort\n");
- return -1;
- }
- HM2READ(remote->reg_0_addr, buff);
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return res;
- }
- u64 sslbp_read_double(u32 addr){
- u64 res;
- u32 buff = READ_REM_DOUBLE_CMD + addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_read_double, trying to abort\n");
- return -1;
- }
- HM2READ(remote->reg_1_addr, buff);
- res = buff;
- res <<= 32;
- HM2READ(remote->reg_0_addr, buff);
- res += buff;
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return res;
- }
- int sslbp_write_byte(u32 addr, u32 data){
- u32 buff = WRITE_REM_BYTE_CMD + addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, data);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_write_byte, trying to abort\n");
- return -1;
- }
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return 0;
- }
- int sslbp_write_word(u32 addr, u32 data){
- u32 buff = WRITE_REM_WORD_CMD + addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, data);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_write_word, trying to abort\n");
- return -1;
- }
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return 0;
- }
- int sslbp_write_long(u32 addr, u32 data){
- u32 buff = WRITE_REM_LONG_CMD + addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, data);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_write_long, trying to abort\n");
- return -1;
- }
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return 0;
- }
- int sslbp_write_double(u32 addr, u32 data0, u32 data1){
- u32 buff = WRITE_REM_DOUBLE_CMD + addr;
- HM2WRITE(remote->reg_cs_addr, buff);
- HM2WRITE(remote->reg_0_addr, data0);
- HM2WRITE(remote->reg_1_addr, data1);
- if (doit() < 0){
- HM2_ERR("Error in sslbp_write_double, trying to abort\n");
- return -1;
- }
- buff = 0;
- HM2WRITE(remote->reg_cs_addr, buff);
- return 0;
- }
- void flash_start(void){
- sslbp_write_lbp(LBPNONVOL_flag, LBPNONVOLFLASH);
- }
- void flash_stop(void){
- sslbp_write_lbp(LBPNONVOL_flag, 0);
- }
- int sslbp_flash(char *fname){
- const struct firmware *fw;
- struct device dev;
- int r;
- int write_sz, erase_sz;
- if (strstr("8i20", remote->name)){
- if (hm2->sserial.version < 40){
- rtapi_print("SSLBP Version must be at least v37 to flash the 8i20"
- "This firmware has v%i. Sorry about that\n"
- ,hm2->sserial.version);
- return -1;
- }
- }
- else if (hm2->sserial.version < 34){
- rtapi_print("SSLBP Version must be at least v34. This firmware has v%i"
- "\n",hm2->sserial.version);
- return -1;
- }
- if (hm2->sserial.baudrate != 115200){
- rtapi_print("To flash firmware the baud rate of the board must be set "
- "to 115200 by jumper, and in Hostmot2 using the "
- "sserial_baudrate modparam\n");
- goto fail0;
- }
- //Copied direct from hostmot2.c. A bit of a faff, but seems to be necessary.
- memset(&dev, '\0', sizeof(dev));
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
- strncpy(dev.bus_id, hm2->llio->name, BUS_ID_SIZE);
- dev.bus_id[BUS_ID_SIZE - 1] = '\0';
- #else
- dev_set_name(&dev, hm2->llio->name);
- #endif
- dev.release = setsserial_release;
- r = device_register(&dev);
- if (r != 0) {
- HM2_ERR("error with device_register\n");
- goto fail0;
- }
- r = request_firmware(&fw, fname, &dev);
- device_unregister(&dev);
- if (r == -ENOENT) {
- HM2_ERR("firmware %s not found\n",fname);
- goto fail0;
- }
- if (r != 0) {
- HM2_ERR("request for firmware %s failed, aborting\n", fname);
- goto fail0;
- }
- rtapi_print("Firmware size 0x%x\n", fw->size);
- if (setup_start() < 0) goto fail0;
- flash_start();
- write_sz = 1 << sslbp_read_byte(LBPFLASHWRITESIZELOC);
- erase_sz = 1 << sslbp_read_byte(LBPFLASHERASESIZELOC);
- HM2_PRINT("Write Size = %x, Erase Size = %x\n", write_sz, erase_sz);
- flash_stop();
- //Programming Loop
- {
- int ReservedBlock = 0;
- int StartBlock = ReservedBlock + 1;
- int blocknum = StartBlock;
- int block_start;
- int i, j, t;
- while (blocknum * erase_sz < fw->size){
- block_start = blocknum * erase_sz;
- HM2_PRINT("block_start %i blocknum %i erase_sz %i\n", block_start, blocknum, erase_sz);
- for (t = 0; t < erase_sz && fw->data[block_start + t] == 0 ; t++){ }
- if (t < erase_sz){ // found a non-zero byte
- flash_start();
- sslbp_write_long(LBPFLASHOFFSETLOC, block_start);
- //sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHERASE_CMD);
- sslbp_write_byte(LBPFLASHCOMMITLOC, 0);
- if (sslbp_read_cookie() != LBPCOOKIE){
- HM2_ERR("Synch failed during block erase: aborting\n");
- goto fail0;
- }
- flash_stop();
- HM2_PRINT("Erased block %i\n", blocknum);
- flash_start();
- for (i = 0; i < erase_sz ; i += write_sz){
- //sslbp_write_long(LBPFLASHOFFSETLOC, block_start + i);
- for (j = 0 ; j < write_sz ; j += 8){
- u32 data0, data1;
- memcpy(&data0, &(fw->data[block_start + i + j]), 4);
- memcpy(&data1, &(fw->data[block_start + i + j + 4]), 4);
- //sslbp_write_double(j, data0, data1);
- }
- //sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHWRITE_CMD);
- //sslbp_write_byte(LBPFLASHCOMMITLOC, 0);
- //if (sslbp_read_cookie() != LBPCOOKIE){
- // HM2_ERR("Synch failed during block write: aborting\n");
- // goto fail0;
- //}
- }
- flash_stop();
- HM2_PRINT("Wrote block %i\n", blocknum);
- }
- else // Looks like an all-zeros block
- {
- HM2_PRINT("Skipped Block %i\n", blocknum);
- }
- blocknum++;
- }
- }
- release_firmware(fw);
- return 0;
- fail0:
- flash_stop();
- return -1;
- }
- int rtapi_app_main(void)
- {
- int cnt;
- comp_id = hal_init("setsserial");
- hal_ready(comp_id);
- cmd_list = argv_split(GFP_KERNEL, cmd, &cnt);
- remote = hm2_get_sserial(&hm2, cmd_list[1]);
- if (! remote) {
- rtapi_print_msg(RTAPI_MSG_ERR,
- "Unable to find sserial remote corresponding to %s\n",
- cmd_list[1]);
- return -1;
- }
- if (! strncmp("set", cmd_list[0], 3) && cnt == 3){
- u32 value;
- u32 addr;
- int i;
- rtapi_print("set command %s\n", cmd_list[1]);
- addr = 0;
- for (i = 0; i < remote->num_globals; i++){
- if (strstr(cmd_list[1], remote->globals[i].NameString)){
- addr = remote->globals[i].ParmAddr;
- break;
- }
- }
- if (! addr) {
- rtapi_print_msg(RTAPI_MSG_ERR,
- "Unable to find parameter corresponding to %s\n",
- cmd_list[1]);
- return -1;
- }
- value = simple_strtol(cmd_list[2], NULL, 0);
- rtapi_print("remote name = %s ParamAddr = %x Value = %i\n",
- remote->name,
- addr,
- value);
- if (set_nvram_param(addr, value) < 0) {
- rtapi_print_msg(RTAPI_MSG_ERR, "Parameter setting failed\n");
- return -1;
- }
- else
- { rtapi_print_msg(RTAPI_MSG_ERR, "Parameter setting success\n");
- return 0;
- }
- }
- else if (! strncmp("flash", cmd_list[0], 5) && cnt == 3){
- rtapi_print("flash command\n");
- if ( ! strstr(cmd_list[2], ".BIN")){
- rtapi_print("Smart-Serial remote firmwares are .BIN format\n "
- "flashing with the wrong one would be bad. Aborting\n");
- return -EINVAL;
- }
- if (sslbp_flash(cmd_list[2]) < 0){
- rtapi_print_msg(RTAPI_MSG_ERR, "Firmware Flash Failed\n");
- return -1;
- }
- else
- { rtapi_print_msg(RTAPI_MSG_ERR, "Firmware Flash Success\n");
- return 0;
- }
- }
- else {
- rtapi_print_msg(RTAPI_MSG_ERR,
- "Unknown commmand or wrong number of parameters to "
- "setsserial command");
- return -1;
- }
- return 0;
- }
- void rtapi_app_exit(void)
- {
- hal_exit(comp_id);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement