diff --git a/meta-facebook/meta-fby3/recipes-fby3/fw-util/files/bic_cpld_ext.cpp b/meta-facebook/meta-fby3/recipes-fby3/fw-util/files/bic_cpld_ext.cpp index 4f97e07939eb..d77b1fe2ad48 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/fw-util/files/bic_cpld_ext.cpp +++ b/meta-facebook/meta-fby3/recipes-fby3/fw-util/files/bic_cpld_ext.cpp @@ -11,10 +11,21 @@ using namespace std; int CpldExtComponent::update(string image) { int ret = 0; + int intf = FEXP_BIC_INTF; + string comp = component(); try { server.ready(); expansion.ready(); + if (comp == "1ou_cpld") { + intf = FEXP_BIC_INTF; + } else { + intf = REXP_BIC_INTF; + } + remote_bic_set_gpio(slot_id, EXP_GPIO_RST_USB_HUB, VALUE_HIGH, intf); + bic_set_gpio(slot_id, GPIO_RST_USB_HUB, VALUE_HIGH); ret = bic_update_fw(slot_id, fw_comp, (char *)image.c_str(), FORCE_UPDATE_UNSET); + bic_set_gpio(slot_id, GPIO_RST_USB_HUB, VALUE_LOW); + remote_bic_set_gpio(slot_id, EXP_GPIO_RST_USB_HUB, VALUE_LOW, intf); } catch (string err) { return FW_STATUS_NOT_SUPPORTED; } @@ -23,10 +34,21 @@ int CpldExtComponent::update(string image) { int CpldExtComponent::fupdate(string image) { int ret = 0; + int intf = FEXP_BIC_INTF; + string comp = component(); try { server.ready(); expansion.ready(); + if (comp == "1ou_cpld") { + intf = FEXP_BIC_INTF; + } else { + intf = REXP_BIC_INTF; + } + remote_bic_set_gpio(slot_id, EXP_GPIO_RST_USB_HUB, VALUE_HIGH, intf); + bic_set_gpio(slot_id, GPIO_RST_USB_HUB, VALUE_HIGH); ret = bic_update_fw(slot_id, fw_comp, (char *)image.c_str(), FORCE_UPDATE_SET); + bic_set_gpio(slot_id, GPIO_RST_USB_HUB, VALUE_HIGH); + remote_bic_set_gpio(slot_id, EXP_GPIO_RST_USB_HUB, VALUE_LOW, intf); } catch (string err) { return FW_STATUS_NOT_SUPPORTED; } diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic.h b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic.h index 2e961fff6c52..75ae8643e7e8 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic.h +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic.h @@ -43,6 +43,11 @@ extern "C" { #define IPMB_RETRY_DELAY_TIME 500 #define MAX_CHECK_DEVICE_TIME 8 +#define GPIO_RST_USB_HUB 0x10 +#define EXP_GPIO_RST_USB_HUB 0x9 +#define VALUE_LOW 0 +#define VALUE_HIGH 1 + /*IFX VR pages*/ #define VR_PAGE 0x00 #define VR_PAGE32 0x32 diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_bios_fwupdate.h b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_bios_fwupdate.h index 9468e24b65d6..4554aaedf167 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_bios_fwupdate.h +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_bios_fwupdate.h @@ -27,10 +27,13 @@ extern "C" { #include "bic_xfer.h" #include "bic.h" +#include #define BIOS_CAPSULE_OFFSET 0x7F0000 #define CPLD_CAPSULE_OFFSET 0x17F0000 +int print_configuration(struct libusb_device_handle *hDevice,struct libusb_config_descriptor *config); +int active_config(struct libusb_device *dev,struct libusb_device_handle *handle); int bic_get_fw_cksum(uint8_t slot_id, uint8_t target, uint32_t offset, uint32_t len, uint8_t *ver); int update_bic_bios(uint8_t slot_id, uint8_t comp, char *image, uint8_t force); int update_bic_usb_bios(uint8_t slot_id, uint8_t comp, char *image); diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.c b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.c index 418e42002c07..7259fe789ede 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.c +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.c @@ -11,11 +11,26 @@ #include #include #include +#include +#include #include "bic_cpld_lattice_fwupdate.h" +#include "bic_bios_fwupdate.h" + +#define EXP1_TI_VENDOR_ID 0x1CBF +#define EXP1_TI_PRODUCT_ID 0x0007 + +#define EXP2_TI_VENDOR_ID 0x1CC0 +#define EXP2_TI_PRODUCT_ID 0x0007 #define MAX_RETRY 500 #define LATTICE_COL_SIZE 128 +#define USB_PKT_SIZE 0x20 +#define USB_DAT_SIZE (USB_PKT_SIZE-7) +#define BIOS_PKT_SIZE 32 + +int alt_interface,interface_number; + //#define CPLD_DEBUG typedef struct { @@ -36,7 +51,6 @@ enum { }; -#if 1 static int _update_fw(uint8_t slot_id, uint8_t target, uint32_t offset, uint16_t len, uint8_t *buf, uint8_t intf) { uint8_t tbuf[256] = {0x00}; @@ -74,6 +88,26 @@ _update_fw(uint8_t slot_id, uint8_t target, uint32_t offset, uint16_t len, uint8 return ret; } + +#if 0 +static int +_set_fw_update_ongoing(uint8_t slot_id, uint16_t tmout) { + char key[64]; + char value[64] = {0}; + struct timespec ts; + + sprintf(key, "fru%u_fwupd", slot_id); + + clock_gettime(CLOCK_MONOTONIC, &ts); + ts.tv_sec += tmout; + sprintf(value, "%ld", ts.tv_sec); + + if (kv_set(key, value, 0, 0) < 0) { + return -1; + } + + return 0; +} #endif static int @@ -912,13 +946,11 @@ int update_bic_cpld_lattice(uint8_t slot_id, char *image, uint8_t intf, uint8_t printf("send cf data but ret < 0. exit.\n"); goto error_exit; } - if ( (record_offset + fsize) <= i ) { printf("updated cpld: %d %%\n", (i/fsize)*5); record_offset += fsize; } } - #endif //step 6 - program user code @@ -975,3 +1007,398 @@ int update_bic_cpld_lattice(uint8_t slot_id, char *image, uint8_t intf, uint8_t return ret; } + +int +bic_init_exp_usb_dev(uint8_t slot_id, uint8_t intf, usb_dev* udev) +{ + int ret; + int index = 0; + char found = 0; + ssize_t cnt; + uint8_t bmc_location = 0; + int recheck = MAX_CHECK_DEVICE_TIME; + uint16_t vid = EXP1_TI_VENDOR_ID; + uint16_t pid = EXP1_TI_PRODUCT_ID; + + ret = libusb_init(NULL); + if (ret < 0) { + printf("Failed to initialise libusb\n"); + goto error_exit; + } else { + printf("Init libusb Successful!\n"); + } + + if ( intf == FEXP_BIC_INTF) { + vid = EXP1_TI_VENDOR_ID; + pid = EXP1_TI_PRODUCT_ID; + } else if ( intf == REXP_BIC_INTF) { + vid = EXP2_TI_VENDOR_ID; + pid = EXP2_TI_PRODUCT_ID; + } else { + printf("Unknow update interface\n"); + goto error_exit; + } + + do { + cnt = libusb_get_device_list(NULL, &udev->devs); + if (cnt < 0) { + printf("There are no USB devices on bus\n"); + goto error_exit; + } + index = 0; + while ((udev->dev = udev->devs[index++]) != NULL) { + ret = libusb_get_device_descriptor(udev->dev, &udev->desc); + if ( ret < 0 ) { + printf("Failed to get device descriptor -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + ret = libusb_open(udev->dev, &udev->handle); + if ( ret < 0 ) { + printf("Error opening device -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + if( (vid == udev->desc.idVendor) && (pid == udev->desc.idProduct) ) { + ret = libusb_get_string_descriptor_ascii(udev->handle, udev->desc.iManufacturer, (unsigned char*) udev->manufacturer, sizeof(udev->manufacturer)); + if ( ret < 0 ) { + printf("Error get Manufacturer string descriptor -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + ret = fby3_common_get_bmc_location(&bmc_location); + if (ret < 0) { + syslog(LOG_ERR, "%s() Cannot get the location of BMC", __func__); + goto error_exit; + } + + ret = libusb_get_port_numbers(udev->dev, udev->path, sizeof(udev->path)); + if (ret < 0) { + printf("Error get port number\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + if ( (bmc_location == BB_BMC) || (bmc_location == DVT_BB_BMC) ) { + if ( udev->path[1] != slot_id) { + continue; + } + } + printf("%04x:%04x (bus %d, device %d)",udev->desc.idVendor, udev->desc.idProduct, libusb_get_bus_number(udev->dev), libusb_get_device_address(udev->dev)); + printf(" path: %d", udev->path[0]); + for (index = 1; index < ret; index++) { + printf(".%d", udev->path[index]); + } + printf("\n"); + + ret = libusb_get_string_descriptor_ascii(udev->handle, udev->desc.iProduct, (unsigned char*) udev->product, sizeof(udev->product)); + if ( ret < 0 ) { + printf("Error get Product string descriptor -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + printf("Manufactured : %s\n",udev->manufacturer); + printf("Product : %s\n",udev->product); + printf("----------------------------------------\n"); + printf("Device Descriptors:\n"); + printf("Vendor ID : %x\n",udev->desc.idVendor); + printf("Product ID : %x\n",udev->desc.idProduct); + printf("Serial Number : %x\n",udev->desc.iSerialNumber); + printf("Size of Device Descriptor : %d\n",udev->desc.bLength); + printf("Type of Descriptor : %d\n",udev->desc.bDescriptorType); + printf("USB Specification Release Number : %d\n",udev->desc.bcdUSB); + printf("Device Release Number : %d\n",udev->desc.bcdDevice); + printf("Device Class : %d\n",udev->desc.bDeviceClass); + printf("Device Sub-Class : %d\n",udev->desc.bDeviceSubClass); + printf("Device Protocol : %d\n",udev->desc.bDeviceProtocol); + printf("Max. Packet Size : %d\n",udev->desc.bMaxPacketSize0); + printf("No. of Configuraions : %d\n",udev->desc.bNumConfigurations); + + found = 1; + break; + } + } + + if ( found != 1) { + sleep(3); + } else { + break; + } + } while ((--recheck) > 0); + + + if ( found == 0 ) { + printf("Device NOT found -- exit\n"); + libusb_free_device_list(udev->devs,1); + ret = -1; + goto error_exit; + } + + ret = libusb_get_configuration(udev->handle, &udev->config); + if ( ret != 0 ) { + printf("Error in libusb_get_configuration -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + + printf("Configured value : %d\n", udev->config); + if ( udev->config != 1 ) { + libusb_set_configuration(udev->handle, 1); + if ( ret != 0 ) { + printf("Error in libusb_set_configuration -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + printf("Device is in configured state!\n"); + } + + libusb_free_device_list(udev->devs, 1); + + if(libusb_kernel_driver_active(udev->handle, udev->ci) == 1) { + printf("Kernel Driver Active\n"); + if(libusb_detach_kernel_driver(udev->handle, udev->ci) == 0) { + printf("Kernel Driver Detached!"); + } else { + printf("Couldn't detach kernel driver -- exit\n"); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + } + + ret = libusb_claim_interface(udev->handle, udev->ci); + if ( ret < 0 ) { + printf("Couldn't claim interface -- exit. err:%s\n", libusb_error_name(ret)); + libusb_free_device_list(udev->devs,1); + goto error_exit; + } + printf("Claimed Interface: %d, EP addr: 0x%02X\n", udev->ci, udev->epaddr); + + active_config(udev->dev, udev->handle); + return 0; +error_exit: + return -1; +} + +int +bic_update_cpld_lattice_usb(uint8_t slot_id, uint8_t intf, const char *image, usb_dev* udev) { + int ret = 0; + uint32_t fsize = 0; + uint32_t record_offset = 0; + CPLDInfo dev_info = {0}; + FILE *fp = NULL; + uint8_t addr = 0xff; + uint8_t buf[16] = {0}; + uint8_t transfer_buf[32] = {0}; + uint32_t offset = 0; + const uint16_t read_count = 16; + int retry = 0; + int retries = 3; + uint8_t data[USB_PKT_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + char fpath[128]; + + strcpy(fpath, image); + fp = fopen(image, "r"); + if ( fp == NULL ) { + ret = -1; + goto exit; + } + + memset(&dev_info, 0, sizeof(dev_info)); + ret = LCMXO2Family_JED_File_Parser(fp, &dev_info); + if ( ret < 0 ) { + goto exit; + } + + fsize = dev_info.CF_Line / 20; + + do { + // step 1 - detect CPLD + ret = detect_cpld_dev(slot_id, intf); + if ( ret < 0 ) { + printf("Device is not found!\n"); + goto exit; + } + + //step 1.5 - provide the addr + addr = CPLD; + + //step 2 - enter transparent mode and check the status + ret = enter_transparent_mode(slot_id, intf, addr); + if ( ret < 0 ) { + printf("Couldn't enter transparent mode!\n"); + goto exit; + } + + //step 3 - erase the CF and check the status + ret = erase_flash(slot_id, intf, addr); + if ( ret < 0 ) { + printf("Couldn't erase the flash!\n"); + goto exit; + } + + //step 4 - Transmit Reset Configuration Address + ret = reset_config_addr(slot_id, intf, addr); + if ( ret < 0 ) { + printf("Couldn't reset the flash!\n"); + goto exit; + } + + int transferlen = 0; + int transferred = 0; + int data_idx, idx, i; + printf("[Update CPLD via USB]\n"); + while (1) { + memset(data, 0xFF, sizeof(data)); + + for (i = 0, data_idx = 0; i < dev_info.CF_Line; i++, data_idx+=4) { + memcpy(buf, (uint8_t *)&dev_info.CF[data_idx], read_count); + for (idx = 0; idx <= 12; idx+=4) { + transfer_buf[idx + 0] = buf[idx + 3]; + transfer_buf[idx + 1] = buf[idx + 2]; + transfer_buf[idx + 2] = buf[idx + 1]; + transfer_buf[idx + 3] = buf[idx + 0]; + } + + memcpy(&data[7], (uint8_t *)&transfer_buf, read_count); + transferlen = read_count + 7; + + data[1] = offset & 0xFF; + data[2] = (offset >> 8) & 0xFF; + data[3] = (offset >> 16) & 0xFF; + data[4] = (offset >> 24) & 0xFF; + data[5] = read_count & 0xFF; + data[6] = (read_count >> 8) & 0xFF; + +resend: + ret = libusb_bulk_transfer(udev->handle, udev->epaddr, data, transferlen, &transferred, 3000); + msleep(1); + if(((ret != 0) || (transferlen != transferred))) { + printf("Error in transferring data! err = %d and transferred = %d(expected data length 64)\n",ret ,transferred); + printf("Retry since %s\n", libusb_error_name(ret)); + retries--; + if (!retries) { + ret = -1; + break; + } + msleep(100); + goto resend; + } + + offset += read_count; + if ( (record_offset + fsize) <= i ) { + _set_fw_update_ongoing(slot_id, 60); + printf("updated cpld: %d %%\n", (i/fsize)*5); + record_offset += fsize; + } + } + + if (i == dev_info.CF_Line) { + break; + } + } + + //step 6 - program user code + ret = program_user_code(slot_id, intf, addr, (uint8_t *)&dev_info.Version); + if ( ret < 0 ) { + printf("Couldn't program the usercode!\n"); + goto exit; + } + + //step 7 - verify the CF data + //step 7.1 Transmit Reset Configuration Address again + ret = reset_config_addr(slot_id, intf, addr); + if ( ret < 0 ) { + printf("Couldn't reset the flash again!\n"); + goto exit; + } + + record_offset = 0; + //step 7.2 Transmit Read Command with Number of Pages + for (i = 0, data_idx = 0; i < dev_info.CF_Line; i++, data_idx+=4) { + ret = verify_cf(slot_id, intf, addr, (uint8_t *)&dev_info.CF[data_idx]); + if ( ret < 0 ) { + printf("Read cf data but ret < 0. exit\n"); + goto exit;//break; + } + + if ( (record_offset + fsize) <= i ) { + printf("verify cpld: %d %%\n", (i/fsize)*5); + record_offset += fsize; + } + } + + if (i == dev_info.CF_Line) { + break; + } + } while ((++retry) < RETRY_TIME); + + if (retry == RETRY_TIME) { + goto exit; + } + + //step 8 - program done + ret = program_done(slot_id, intf, addr); + if ( ret < 0 ) { + printf("Couldn't finish the program!\n"); + goto exit; + } + +exit: + if ( fp != NULL ) fclose(fp); + if ( dev_info.CF != NULL ) free(dev_info.CF); + + return ret; +} + +int +bic_close_exp_usb_dev(usb_dev* udev) { + if (libusb_release_interface(udev->handle, udev->ci) < 0) { + printf("Couldn't release the interface 0x%X\n", udev->ci); + } + + if (udev->handle != NULL ) + libusb_close(udev->handle); + libusb_exit(NULL); + + return 0; +} + +int +update_bic_cpld_lattice_usb(uint8_t slot_id, char *image, uint8_t intf, uint8_t force) { + struct timeval start, end; + int ret = 0; + usb_dev bic_udev; + usb_dev* udev = &bic_udev; + + udev->ci = 1; + udev->epaddr = 0x1; + + // init usb device + ret = bic_init_exp_usb_dev(slot_id, intf, udev); + if (ret < 0) { + goto error_exit; + } + + printf("Input: %s, USB timeout: 3000ms\n", image); + gettimeofday(&start, NULL); + + // sending file + ret = bic_update_cpld_lattice_usb(slot_id, intf, image, udev); + if (ret < 0) { + goto error_exit; + } + + gettimeofday(&end, NULL); + printf("Elapsed time: %d sec.\n", (int)(end.tv_sec - start.tv_sec)); + ret = 0; + +error_exit: + // close usb device + bic_close_exp_usb_dev(udev); + + return ret; +} diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.h b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.h index c06932231aac..4227ffe7a3b2 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.h +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_cpld_lattice_fwupdate.h @@ -29,6 +29,7 @@ extern "C" { #include "bic.h" int update_bic_cpld_lattice(uint8_t slot_id, char *image, uint8_t intf, uint8_t force); +int update_bic_cpld_lattice_usb(uint8_t slot_id, char *image, uint8_t intf, uint8_t force); #ifdef __cplusplus } // extern "C" diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_fwupdate.c b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_fwupdate.c index b6cdab828370..8be13266d9a7 100755 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_fwupdate.c +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_fwupdate.c @@ -1078,7 +1078,11 @@ bic_update_fw(uint8_t slot_id, uint8_t comp, char *path, uint8_t force) { break; case FW_1OU_CPLD: case FW_2OU_CPLD: - ret = update_bic_cpld_lattice(slot_id, path, intf, force); + if (loc != NULL) { + ret = update_bic_cpld_lattice(slot_id, path, intf, force); + } else { + ret = update_bic_cpld_lattice_usb(slot_id, path, intf, force); + } break; case FW_BB_CPLD: case FW_CPLD: diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.c b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.c index 7f87b5c94b31..d0e0ee75cc68 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.c +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.c @@ -1129,6 +1129,27 @@ bic_set_gpio(uint8_t slot_id, uint8_t gpio_num, uint8_t value) { return 0; } +int +remote_bic_set_gpio(uint8_t slot_id, uint8_t gpio_num, uint8_t value, uint8_t intf) { + uint8_t tbuf[6] = {0x9c, 0x9c, 0x00}; + uint8_t rbuf[1] = {0}; + uint8_t tlen = 6; + uint8_t rlen = 0; + int ret = 0; + + tbuf[3] = 0x01; + tbuf[4] = gpio_num; + tbuf[5] = value; + + ret = bic_ipmb_send(slot_id, NETFN_OEM_1S_REQ, BIC_CMD_OEM_GET_SET_GPIO, tbuf, tlen, rbuf, &rlen, intf); + + if ( ret < 0 ) { + return -1; + } + + return 0; +} + // Get all GPIO pin status int bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio, uint8_t intf) { diff --git a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.h b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.h index 9bd7f9c3d90d..b79ad7167aac 100644 --- a/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.h +++ b/meta-facebook/meta-fby3/recipes-fby3/plat-libs/files/bic/bic_ipmi.h @@ -49,6 +49,7 @@ int bic_is_m2_exp_prsnt_cache(uint8_t slot_id); int me_recovery(uint8_t slot_id, uint8_t command); int bic_switch_mux_for_bios_spi(uint8_t slot_id, uint8_t mux); int bic_set_gpio(uint8_t slot_id, uint8_t gpio_num,uint8_t value); +int remote_bic_set_gpio(uint8_t slot_id, uint8_t gpio_num,uint8_t value, uint8_t intf); int bic_get_one_gpio_status(uint8_t slot_id, uint8_t gpio_num, uint8_t *value); int bic_asd_init(uint8_t slot_id, uint8_t cmd); int bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, uint8_t *data);