// this is the function exported to HAL // it keeps the watchdog from biting us for a while static int hm2_pet_watchdog(void *void_hm2, const hal_funct_args_t *fa) { hostmot2_t *hm2 = void_hm2; static int print_warning = 1; if (print_warning) { HM2_PRINT("The hm2 pet_watchdog function is no longer needed.\n"); HM2_PRINT("The hm2 write function now pets the watchdog.\n"); print_warning = 0; } return 0; }
// this is the function exported to HAL // it keeps the watchdog from biting us for a while static void hm2_pet_watchdog(void *void_hm2, long period_ns) { hostmot2_t *hm2 = void_hm2; // if there is no watchdog, then there's nothing to do if (hm2->watchdog.num_instances == 0) return; // if there are comm problems, wait for the user to fix it if ((*hm2->llio->io_error) != 0) return; // if the requested timeout is dangerously short compared to the petting-period, warn the user once if (hm2->watchdog.instance[0].hal.param.timeout_ns < (1.5 * period_ns)) { if (0 == hm2->watchdog.instance[0].warned_about_short_timeout) { hm2->watchdog.instance[0].warned_about_short_timeout = 1; HM2_PRINT( "Watchdog timeout (%u ns) is dangerously short compared to pet_watchdog() period (%ld ns)\n", hm2->watchdog.instance[0].hal.param.timeout_ns, period_ns ); } } // if the watchdog has bit, wait for the user to reset it if (*hm2->watchdog.instance[0].hal.pin.has_bit) return; // petting the watchdog wakes it up, and now we can't stop or it will bite! hm2->watchdog.instance[0].enable = 1; if (hm2->llio->needs_reset) { // user has cleared the bit HM2_PRINT("trying to recover from IO error or Watchdog bite\n"); // reset the watchdog status hm2->watchdog.status_reg[0] = 0; // write all settings out to the FPGA hm2_force_write(hm2); if ((*hm2->llio->io_error) != 0) { HM2_PRINT("error recovery failed\n"); return; } HM2_PRINT("error recover successful!\n"); hm2->llio->needs_reset = 0; } // reset the watchdog timer // FIXME: write just 1 byte hm2->llio->write(hm2->llio, hm2->watchdog.reset_addr, hm2->watchdog.reset_reg, (hm2->watchdog.num_instances * sizeof(u32))); }
// if the user has changed the timeout, sync it out to the watchdog void hm2_watchdog_write(hostmot2_t *hm2, long period_ns) { if (hm2->watchdog.num_instances != 1) return; // if there are comm problems, wait for the user to fix it if ((*hm2->llio->io_error) != 0) return; // if the watchdog has bit, wait for the user to reset it if (*hm2->watchdog.instance[0].hal.pin.has_bit) return; // writing to the watchdog wakes it up, and now we can't stop or it will bite! hm2->watchdog.instance[0].enable = 1; if (hm2->llio->needs_reset) { // user has cleared the bit HM2_PRINT("trying to recover from IO error or Watchdog bite\n"); // reset the watchdog status hm2->watchdog.status_reg[0] = 0; // write all settings out to the FPGA hm2_force_write(hm2); if ((*hm2->llio->io_error) != 0) { HM2_PRINT("error recovery failed\n"); return; } HM2_PRINT("error recover successful!\n"); hm2->llio->needs_reset = 0; } if ( (hm2->watchdog.instance[0].hal.param.timeout_ns == hm2->watchdog.instance[0].written_timeout_ns) && (hm2->watchdog.instance[0].enable == hm2->watchdog.instance[0].written_enable) ) { return; } // if the requested timeout is dangerously short compared to the petting-period, warn the user once if (hm2->watchdog.instance[0].hal.param.timeout_ns < (1.5 * period_ns)) { HM2_PRINT( "Watchdog timeout (%u ns) is dangerously short compared to hm2_write() period (%ld ns)\n", hm2->watchdog.instance[0].hal.param.timeout_ns, period_ns ); } hm2_watchdog_force_write(hm2); }
void hm2_watchdog_print_module(hostmot2_t *hm2) { int i; HM2_PRINT("Watchdog: %d\n", hm2->watchdog.num_instances); if (hm2->watchdog.num_instances <= 0) return; HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->watchdog.clock_frequency, hm2_hz_to_mhz(hm2->watchdog.clock_frequency)); HM2_PRINT(" version: %d\n", hm2->watchdog.version); HM2_PRINT(" timer_addr: 0x%04X\n", hm2->watchdog.timer_addr); HM2_PRINT(" status_addr: 0x%04X\n", hm2->watchdog.status_addr); HM2_PRINT(" reset_addr: 0x%04X\n", hm2->watchdog.reset_addr); for (i = 0; i < hm2->watchdog.num_instances; i ++) { HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" param timeout_ns = %u\n", hm2->watchdog.instance[i].hal.param.timeout_ns); HM2_PRINT(" pin has_bit = %d\n", (*hm2->watchdog.instance[i].hal.pin.has_bit)); HM2_PRINT(" reg timer = 0x%08X\n", hm2->watchdog.timer_reg[i]); } }
void hm2_print_pin_usage(hostmot2_t *hm2) { int i; HM2_PRINT("%d I/O Pins used:\n", hm2->num_pins); for (i = 0; i < hm2->num_pins; i ++) { hm2_pin_t *pin = &(hm2->pin[i]); if (pin->gtag == pin->sec_tag) { if(pin->sec_unit & 0x80) HM2_PRINT( " IO Pin %03d (%s-%02d): %s (all), pin %s (%s)\n", i, hm2->llio->ioport_connector_name[pin->port_num], pin->port_pin, hm2_get_general_function_name(pin->gtag), hm2_get_pin_secondary_name(&hm2->pin[i]), ((pin->sec_pin & 0x80) ? "Output" : "Input") ); else HM2_PRINT( " IO Pin %03d (%s-%02d): %s #%d, pin %s (%s)\n", i, hm2->llio->ioport_connector_name[pin->port_num], pin->port_pin, hm2_get_general_function_name(pin->gtag), pin->sec_unit, hm2_get_pin_secondary_name(pin), ((pin->sec_pin & 0x80) ? "Output" : "Input") ); } else { HM2_PRINT( " IO Pin %03d (%s-%02d): %s\n", i, hm2->llio->ioport_connector_name[pin->port_num], pin->port_pin, hm2_get_general_function_name(pin->gtag) ); } } }
static void hm2_print_pin_descriptors(hostmot2_t *hm2) { int i; HM2_PRINT("%d HM2 Pin Descriptors:\n", hm2->num_pins); for (i = 0; i < hm2->num_pins; i ++) { HM2_PRINT(" pin %d:\n", i); HM2_PRINT( " Primary Tag: 0x%02X (%s)\n", hm2->pin[i].primary_tag, hm2_get_general_function_name(hm2->pin[i].primary_tag) ); if (hm2->pin[i].sec_tag != 0) { HM2_PRINT( " Secondary Tag: 0x%02X (%s)\n", hm2->pin[i].sec_tag, hm2_get_general_function_name(hm2->pin[i].sec_tag) ); HM2_PRINT(" Secondary Unit: 0x%02X\n", hm2->pin[i].sec_unit); HM2_PRINT( " Secondary Pin: 0x%02X (%s, %s)\n", hm2->pin[i].sec_pin, hm2_get_pin_secondary_name(&hm2->pin[i]), ((hm2->pin[i].sec_pin & 0x80) ? "Output" : "Input") ); } } }
void hm2_resolver_print_module(hostmot2_t *hm2) { int i; HM2_PRINT("resolvers: %d\n", hm2->resolver.num_instances); if (hm2->resolver.num_instances <= 0) return; HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->resolver.clock_frequency, hm2_hz_to_mhz(hm2->resolver.clock_frequency)); HM2_PRINT(" version: %d\n", hm2->resolver.version); HM2_PRINT(" position_addr: 0x%04X\n", hm2->resolver.position_addr); HM2_PRINT(" velocity_addr: 0x%04X\n", hm2->resolver.velocity_addr); for (i = 0; i < hm2->resolver.num_instances; i ++) { HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" hw:\n"); HM2_PRINT(" position = %08x\n", (hm2->resolver.position_reg[i])); HM2_PRINT(" velocity = %08x\n", (hm2->resolver.velocity_reg[i])); } }
void hm2_bspi_print_module(hostmot2_t *hm2){ int i,j; HM2_PRINT("Buffered SPI: %d\n", hm2->bspi.num_instances); if (hm2->bspi.num_instances <= 0) return; HM2_PRINT(" version: %d\n", hm2->bspi.version); HM2_PRINT(" channel configurations\n"); for (i = 0; i < hm2->bspi.num_instances; i ++) { HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->bspi.instance[i].clock_freq, hm2_hz_to_mhz(hm2->bspi.instance[i].clock_freq)); HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" HAL name = %s\n", hm2->bspi.instance[i].name); for (j = 0; j < 16 ; j++){ HM2_PRINT(" frame %i config = %08x\n", j, hm2->bspi.instance[i].cd[j]); HM2_PRINT(" address = %08x\n", hm2->bspi.instance[i].addr[j]); } } }
void hm2_uart_print_module(hostmot2_t *hm2){ int i; HM2_PRINT("UART: %d\n", hm2->uart.num_instances); if (hm2->uart.num_instances <= 0) return; HM2_PRINT(" version: %d\n", hm2->uart.version); HM2_PRINT(" channel configurations\n"); for (i = 0; i < hm2->uart.num_instances; i ++) { HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->uart.instance[i].clock_freq, hm2_hz_to_mhz(hm2->uart.instance[i].clock_freq)); HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" HAL name = %s\n", hm2->uart.instance[i].name); } }
void hm2_watchdog_process_tram_read(hostmot2_t *hm2) { // if there is no watchdog, then there's nothing to do if (hm2->watchdog.num_instances == 0) return; // if there are comm problems, wait for the user to fix it if ((*hm2->llio->io_error) != 0) return; // if we've already noticed the board needs to be reset, don't re-read // the watchdog has-bit bit // Note: we check needs_reset instead of the has-bit pin here, because // has-bit might be cleared by the user at any time, so using it here // would cause a race condition between this function and pet_watchdog if (hm2->llio->needs_reset != 0) return; // last time we were here, everything was fine // see if the watchdog has bit since then if (hm2->watchdog.status_reg[0] & 0x1) { HM2_PRINT("Watchdog has bit! (set the .has-bit pin to False to resume)\n"); *hm2->watchdog.instance[0].hal.pin.has_bit = 1; hm2->llio->needs_reset = 1; } }
int sslbp_flash(char *fname){ const struct rtapi_firmware *fw; struct rtapi_device dev; int r; int write_sz, erase_sz; if (strstr("8i20", remote->name)){ if (hm2->sserial.version < 37){ 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"); return -1; } //Copied direct from hostmot2.c. A bit of a faff, but seems to be necessary. memset(&dev, '\0', sizeof(dev)); rtapi_dev_set_name(&dev, hm2->llio->name); dev.release = setsserial_release; r = rtapi_device_register(&dev); if (r != 0) { HM2_ERR("error with device_register\n"); return -1; } r = rtapi_request_firmware(&fw, fname, &dev); rtapi_device_unregister(&dev); if (r == -ENOENT) { HM2_ERR("firmware %s not found\n",fname); return -1; } if (r != 0) { HM2_ERR("request for firmware %s failed, aborting\n", fname); return -1; } rtapi_print("Firmware size 0x%zx\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; 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); 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){ rtapi_u32 data0, data1, m; m = block_start + i + j; data0 = (fw->data[m] + (fw->data[m + 1] << 8) + (fw->data[m + 2] << 16) + (fw->data[m + 3] << 24)); data1 = (fw->data[m + 4] + (fw->data[m + 5] << 8) + (fw->data[m + 6] << 16) + (fw->data[m + 7] << 24)); sslbp_write_double(j, data0, data1); } sslbp_write_byte(LBPFLASHCOMMITLOC, FLASHWRITE_CMD); 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++; } } rtapi_release_firmware(fw); return 0; fail0: flash_stop(); return -1; }
int hm2_bspi_parse_md(hostmot2_t *hm2, int md_index) { // All this function actually does is allocate memory // and give the bspi modules names. // // some standard sanity checks // int i, j, r = -EINVAL; hm2_module_descriptor_t *md = &hm2->md[md_index]; if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 0x40, 0x0007)) { HM2_ERR("inconsistent Module Descriptor!\n"); return -EINVAL; } if (hm2->bspi.num_instances != 0) { HM2_ERR( "found duplicate Module Descriptor for %s (inconsistent " "firmware), not loading driver\n", hm2_get_general_function_name(md->gtag) ); return -EINVAL; } if (hm2->config.num_bspis > md->instances) { HM2_ERR( "config defines %d bspis, but only %d are available, " "not loading driver\n", hm2->config.num_bspis, md->instances ); return -EINVAL; } if (hm2->config.num_bspis == 0) { return 0; } // // looks good, start initializing // if (hm2->config.num_bspis == -1) { hm2->bspi.num_instances = md->instances; } else { hm2->bspi.num_instances = hm2->config.num_bspis; } hm2->bspi.instance = (hm2_bspi_instance_t *)hal_malloc(hm2->bspi.num_instances * sizeof(hm2_bspi_instance_t)); if (hm2->bspi.instance == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } for (i = 0 ; i < hm2->bspi.num_instances ; i++){ hm2_bspi_instance_t *chan = &hm2->bspi.instance[i]; chan->clock_freq = md->clock_freq; r = sprintf(chan->name, "%s.bspi.%01d", hm2->llio->name, i); HM2_PRINT("created Buffered SPI function %s.\n", chan->name); chan->base_address = md->base_address + i * md->instance_stride; chan->register_stride = md->register_stride; chan->instance_stride = md->instance_stride; chan->cd_addr = md->base_address + md->register_stride + i * sizeof(rtapi_u32); chan->count_addr = md->base_address + 2 * md->register_stride + i * sizeof(rtapi_u32); for (j = 0 ; j < 16 ; j++ ){ chan->addr[j] = chan->base_address + j * sizeof(rtapi_u32); } } return hm2->bspi.num_instances; fail0: return r; }
int hm2_watchdog_parse_md(hostmot2_t *hm2, int md_index) { hm2_module_descriptor_t *md = &hm2->md[md_index]; int r; // // some standard sanity checks // if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 4, 0)) { HM2_ERR("inconsistent Module Descriptor!\n"); return -EINVAL; } if (hm2->watchdog.num_instances != 0) { HM2_ERR( "found duplicate Module Descriptor for %s (inconsistent firmware), not loading driver\n", hm2_get_general_function_name(md->gtag) ); return -EINVAL; } // // special sanity checks for watchdog // if (md->instances != 1) { HM2_PRINT("MD declares %d watchdogs! only using the first one...\n", md->instances); } // // looks good, start initializing // hm2->watchdog.num_instances = 1; hm2->watchdog.instance = (hm2_watchdog_instance_t *)hal_malloc(hm2->watchdog.num_instances * sizeof(hm2_watchdog_instance_t)); if (hm2->watchdog.instance == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } hm2->watchdog.clock_frequency = md->clock_freq; hm2->watchdog.version = md->version; hm2->watchdog.timer_addr = md->base_address + (0 * md->register_stride); hm2->watchdog.status_addr = md->base_address + (1 * md->register_stride); hm2->watchdog.reset_addr = md->base_address + (2 * md->register_stride); r = hm2_register_tram_read_region(hm2, hm2->watchdog.status_addr, (hm2->watchdog.num_instances * sizeof(u32)), &hm2->watchdog.status_reg); if (r < 0) { HM2_ERR("error registering tram read region for watchdog (%d)\n", r); goto fail0; } r = hm2_register_tram_write_region(hm2, hm2->watchdog.reset_addr, sizeof(u32), &hm2->watchdog.reset_reg); if (r < 0) { HM2_ERR("error registering tram write region for watchdog (%d)!\n", r); goto fail0; } // // allocate memory for register buffers // hm2->watchdog.timer_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL); if (hm2->watchdog.timer_reg == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } // // export to HAL // // pins r = hal_pin_bit_newf( HAL_IO, &(hm2->watchdog.instance[0].hal.pin.has_bit), hm2->llio->comp_id, "%s.watchdog.has_bit", hm2->llio->name ); if (r < 0) { HM2_ERR("error adding pin, aborting\n"); r = -EINVAL; goto fail1; } // params r = hal_param_u32_newf( HAL_RW, &(hm2->watchdog.instance[0].hal.param.timeout_ns), hm2->llio->comp_id, "%s.watchdog.timeout_ns", hm2->llio->name ); if (r < 0) { HM2_ERR("error adding param, aborting\n"); r = -EINVAL; goto fail1; } // the function { hal_export_xfunct_args_t xfunct_args = { .type = FS_XTHREADFUNC, .funct.x = hm2_pet_watchdog, .arg = hm2, .uses_fp = 0, .reentrant = 0, .owner_id = hm2->llio->comp_id }; if ((r = hal_export_xfunctf(&xfunct_args, "%s.pet_watchdog", hm2->llio->name)) != 0) { HM2_ERR("hal_export pet_watchdog failed - %d\n", r); r = -EINVAL; goto fail1; } } // // initialize the watchdog // *hm2->watchdog.instance[0].hal.pin.has_bit = 0; hm2->watchdog.instance[0].hal.param.timeout_ns = 5 * 1000 * 1000; // default timeout is 5 milliseconds hm2->watchdog.instance[0].enable = 0; // the first pet_watchdog will turn it on return hm2->watchdog.num_instances; fail1: kfree(hm2->watchdog.timer_reg); fail0: hm2->watchdog.num_instances = 0; return r; } void hm2_watchdog_print_module(hostmot2_t *hm2) { int i; HM2_PRINT("Watchdog: %d\n", hm2->watchdog.num_instances); if (hm2->watchdog.num_instances <= 0) return; HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->watchdog.clock_frequency, hm2_hz_to_mhz(hm2->watchdog.clock_frequency)); HM2_PRINT(" version: %d\n", hm2->watchdog.version); HM2_PRINT(" timer_addr: 0x%04X\n", hm2->watchdog.timer_addr); HM2_PRINT(" status_addr: 0x%04X\n", hm2->watchdog.status_addr); HM2_PRINT(" reset_addr: 0x%04X\n", hm2->watchdog.reset_addr); for (i = 0; i < hm2->watchdog.num_instances; i ++) { HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" param timeout_ns = %u\n", hm2->watchdog.instance[i].hal.param.timeout_ns); HM2_PRINT(" pin has_bit = %d\n", (*hm2->watchdog.instance[i].hal.pin.has_bit)); HM2_PRINT(" reg timer = 0x%08X\n", hm2->watchdog.timer_reg[i]); } }
void hm2_pwmgen_print_module(hostmot2_t *hm2) { int i; HM2_PRINT("PWMGen: %d\n", hm2->pwmgen.num_instances); if (hm2->pwmgen.num_instances <= 0) return; HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n", hm2->pwmgen.clock_frequency, hm2_hz_to_mhz(hm2->pwmgen.clock_frequency)); HM2_PRINT(" version: %d\n", hm2->pwmgen.version); HM2_PRINT(" pwmgen_master_rate_dds: 0x%08X (%d)\n", hm2->pwmgen.pwmgen_master_rate_dds_reg, hm2->pwmgen.pwmgen_master_rate_dds_reg); HM2_PRINT(" pdmgen_master_rate_dds: 0x%08X (%d)\n", hm2->pwmgen.pdmgen_master_rate_dds_reg, hm2->pwmgen.pdmgen_master_rate_dds_reg); HM2_PRINT(" enable: 0x%08X\n", hm2->pwmgen.enable_reg); HM2_PRINT(" pwm_value_addr: 0x%04X\n", hm2->pwmgen.pwm_value_addr); HM2_PRINT(" pwm_mode_addr: 0x%04X\n", hm2->pwmgen.pwm_mode_addr); HM2_PRINT(" pwmgen_master_rate_dds_addr: 0x%04X\n", hm2->pwmgen.pwmgen_master_rate_dds_addr); HM2_PRINT(" pdmgen_master_rate_dds_addr: 0x%04X\n", hm2->pwmgen.pdmgen_master_rate_dds_addr); HM2_PRINT(" enable_addr: 0x%04X\n", hm2->pwmgen.enable_addr); for (i = 0; i < hm2->pwmgen.num_instances; i ++) { HM2_PRINT(" instance %d:\n", i); HM2_PRINT(" hw:\n"); HM2_PRINT( " pwm_val = 0x%08X (%s%d)\n", hm2->pwmgen.pwm_value_reg[i], ((hm2->pwmgen.pwm_value_reg[i] & 0x80000000) ? "-" : ""), ((hm2->pwmgen.pwm_value_reg[i]>>16) & 0x7fff) ); HM2_PRINT(" pwm_mode = 0x%08X\n", hm2->pwmgen.pwm_mode_reg[i]); } }
int hm2_uart_parse_md(hostmot2_t *hm2, int md_index) { // All this function actually does is allocate memory // and give the uart modules names. // // some standard sanity checks // int i, r = -EINVAL; hm2_module_descriptor_t *md = &hm2->md[md_index]; static int last_gtag = -1; //The UART declares a TX and RX module separately if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 4, 0x10, 0x000F)) { HM2_ERR("inconsistent Module Descriptor!\n"); return -EINVAL; } if (hm2->uart.num_instances > 1 && last_gtag == md->gtag) { HM2_ERR( "found duplicate Module Descriptor for %s (inconsistent " "firmware), not loading driver %i %i\n", hm2_get_general_function_name(md->gtag), md->gtag, last_gtag ); return -EINVAL; } last_gtag = md->gtag; if (hm2->config.num_uarts > md->instances) { HM2_ERR( "config defines %d uarts, but only %d are available, " "not loading driver\n", hm2->config.num_uarts, md->instances ); return -EINVAL; } if (hm2->config.num_uarts == 0) { return 0; } // // looks good, start, or continue, initializing // if (hm2->uart.num_instances == 0){ if (hm2->config.num_uarts == -1) { hm2->uart.num_instances = md->instances; } else { hm2->uart.num_instances = hm2->config.num_uarts; } hm2->uart.instance = (hm2_uart_instance_t *)hal_malloc(hm2->uart.num_instances * sizeof(hm2_uart_instance_t)); if (hm2->uart.instance == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } } for (i = 0 ; i < hm2->uart.num_instances ; i++){ hm2_uart_instance_t *inst = &hm2->uart.instance[i]; // For the time being we assume that all UARTS come on pairs if (inst->clock_freq == 0){ inst->clock_freq = md->clock_freq; r = sprintf(inst->name, "%s.uart.%01d", hm2->llio->name, i); HM2_PRINT("created UART Interface function %s.\n", inst->name); } if (md->gtag == HM2_GTAG_UART_TX){ inst->tx1_addr = md->base_address + i * md->instance_stride; inst->tx2_addr = md->base_address + i * md->instance_stride + 0x4; inst->tx3_addr = md->base_address + i * md->instance_stride + 0x8; inst->tx4_addr = md->base_address + i * md->instance_stride + 0xC; inst->tx_fifo_count_addr = (md->base_address + md->register_stride + i * md->instance_stride); inst->tx_bitrate_addr = (md->base_address + 2 * md->register_stride + i * md->instance_stride); inst->tx_mode_addr = (md->base_address + 3 * md->register_stride +i * md->instance_stride); } else if (md->gtag == HM2_GTAG_UART_RX){ inst->rx1_addr = md->base_address + i * md->instance_stride; inst->rx2_addr = md->base_address + i * md->instance_stride + 0x4; inst->rx3_addr = md->base_address + i * md->instance_stride + 0x8; inst->rx4_addr = md->base_address + i * md->instance_stride + 0xC; inst->rx_fifo_count_addr = (md->base_address + md->register_stride + i * md->instance_stride); inst->rx_bitrate_addr = (md->base_address + 2 * md->register_stride + i * md->instance_stride); inst->rx_mode_addr = (md->base_address + 3 * md->register_stride +i * md->instance_stride); } else{ HM2_ERR("Something very wierd happened"); goto fail0; } } return hm2->uart.num_instances; fail0: return r; }
int hm2_watchdog_parse_md(hostmot2_t *hm2, int md_index) { hm2_module_descriptor_t *md = &hm2->md[md_index]; int r; // // some standard sanity checks // if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 3, 4, 0)) { HM2_ERR("inconsistent Module Descriptor!\n"); return -EINVAL; } if (hm2->watchdog.num_instances != 0) { HM2_ERR( "found duplicate Module Descriptor for %s (inconsistent firmware), not loading driver\n", hm2_get_general_function_name(md->gtag) ); return -EINVAL; } // // special sanity checks for watchdog // if (md->instances != 1) { HM2_PRINT("MD declares %d watchdogs! only using the first one...\n", md->instances); } // // looks good, start initializing // hm2->watchdog.num_instances = 1; hm2->watchdog.instance = (hm2_watchdog_instance_t *)hal_malloc(hm2->watchdog.num_instances * sizeof(hm2_watchdog_instance_t)); if (hm2->watchdog.instance == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } hm2->watchdog.clock_frequency = md->clock_freq; hm2->watchdog.version = md->version; hm2->watchdog.timer_addr = md->base_address + (0 * md->register_stride); hm2->watchdog.status_addr = md->base_address + (1 * md->register_stride); hm2->watchdog.reset_addr = md->base_address + (2 * md->register_stride); // // allocate memory for register buffers // hm2->watchdog.status_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL); if (hm2->watchdog.status_reg == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail0; } hm2->watchdog.reset_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL); if (hm2->watchdog.reset_reg == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail1; } hm2->watchdog.timer_reg = (u32 *)kmalloc(hm2->watchdog.num_instances * sizeof(u32), GFP_KERNEL); if (hm2->watchdog.timer_reg == NULL) { HM2_ERR("out of memory!\n"); r = -ENOMEM; goto fail2; } // // export to HAL // // pins r = hal_pin_bit_newf( HAL_IO, &(hm2->watchdog.instance[0].hal.pin.has_bit), hm2->llio->comp_id, "%s.watchdog.has_bit", hm2->llio->name ); if (r < 0) { HM2_ERR("error adding pin, aborting\n"); r = -EINVAL; goto fail3; } // params r = hal_param_u32_newf( HAL_RW, &(hm2->watchdog.instance[0].hal.param.timeout_ns), hm2->llio->comp_id, "%s.watchdog.timeout_ns", hm2->llio->name ); if (r < 0) { HM2_ERR("error adding param, aborting\n"); r = -EINVAL; goto fail3; } // the function { char name[HAL_NAME_LEN + 1]; rtapi_snprintf(name, sizeof(name), "%s.pet_watchdog", hm2->llio->name); r = hal_export_funct(name, hm2_pet_watchdog, hm2, 0, 0, hm2->llio->comp_id); if (r != 0) { HM2_ERR("error %d exporting pet_watchdog function %s\n", r, name); r = -EINVAL; goto fail3; } } // // initialize the watchdog // *hm2->watchdog.instance[0].hal.pin.has_bit = 0; hm2->watchdog.instance[0].hal.param.timeout_ns = 5 * 1000 * 1000; // default timeout is 5 milliseconds hm2->watchdog.instance[0].enable = 0; // the first pet_watchdog will turn it on hm2->watchdog.instance[0].warned_about_short_timeout = 0; hm2->watchdog.reset_reg[0] = 0x5a000000; hm2->watchdog.status_reg[0] = 0; return hm2->watchdog.num_instances; fail3: kfree(hm2->watchdog.timer_reg); fail2: kfree(hm2->watchdog.reset_reg); fail1: kfree(hm2->watchdog.status_reg); fail0: hm2->watchdog.num_instances = 0; return r; }