| /** |
| **************************************************************************************** |
| * |
| * @file rwnx_configparse.c |
| * |
| * Copyright (C) RivieraWaves 2012-2019 |
| * |
| **************************************************************************************** |
| */ |
| #include <linux/firmware.h> |
| #include <linux/if_ether.h> |
| |
| #include "rwnx_defs.h" |
| #include "rwnx_cfgfile.h" |
| |
| /** |
| * |
| */ |
| static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, |
| const char *tag_name, unsigned int tag_len) |
| { |
| unsigned int curr, line_start = 0, line_size; |
| |
| RWNX_DBG(RWNX_FN_ENTRY_STR); |
| |
| /* Walk through all the lines of the configuration file */ |
| while (line_start < file_size) { |
| /* Search the end of the current line (or the end of the file) */ |
| for (curr = line_start; curr < file_size; curr++) |
| if (file_data[curr] == '\n') |
| break; |
| |
| /* Compute the line size */ |
| line_size = curr - line_start; |
| |
| /* Check if this line contains the expected tag */ |
| if ((line_size == (strlen(tag_name) + tag_len)) && |
| (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) |
| return &file_data[line_start + strlen(tag_name)]; |
| |
| /* Move to next line */ |
| line_start = curr + 1; |
| } |
| |
| /* Tag not found */ |
| return NULL; |
| } |
| |
| /** |
| * Parse the Config file used at init time |
| */ |
| int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, |
| struct rwnx_conf_file *config) |
| { |
| const struct firmware *config_fw; |
| u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; |
| int ret; |
| const u8 *tag_ptr; |
| |
| RWNX_DBG(RWNX_FN_ENTRY_STR); |
| |
| ret = request_firmware(&config_fw, filename, rwnx_hw->dev); |
| if (ret) { |
| printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); |
| return ret; |
| } |
| |
| /* Get MAC Address */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "MAC_ADDR=", strlen("00:00:00:00:00:00")); |
| if (tag_ptr != NULL) { |
| u8 *addr = config->mac_addr; |
| if (sscanf(tag_ptr, |
| "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", |
| addr + 0, addr + 1, addr + 2, |
| addr + 3, addr + 4, addr + 5) != ETH_ALEN) |
| memcpy(config->mac_addr, dflt_mac, ETH_ALEN); |
| } else |
| memcpy(config->mac_addr, dflt_mac, ETH_ALEN); |
| |
| RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); |
| |
| /* Release the configuration file */ |
| release_firmware(config_fw); |
| |
| return 0; |
| } |
| |
| /** |
| * Parse the Config file used at init time |
| */ |
| int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, |
| struct rwnx_phy_conf_file *config, int path) |
| { |
| const struct firmware *config_fw; |
| int ret; |
| const u8 *tag_ptr; |
| |
| RWNX_DBG(RWNX_FN_ENTRY_STR); |
| |
| ret = request_firmware(&config_fw, filename, rwnx_hw->dev); |
| if (ret) { |
| printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); |
| return ret; |
| } |
| |
| /* Get Trident path mapping */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "TRD_PATH_MAPPING=", strlen("00")); |
| if (tag_ptr != NULL) { |
| u8 val; |
| if (sscanf(tag_ptr, "%hhx", &val) == 1) |
| config->trd.path_mapping = val; |
| else |
| config->trd.path_mapping = path; |
| } else |
| config->trd.path_mapping = path; |
| |
| RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); |
| |
| /* Get DC offset compensation */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "TX_DC_OFF_COMP=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) |
| config->trd.tx_dc_off_comp = 0; |
| } else |
| config->trd.tx_dc_off_comp = 0; |
| |
| RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); |
| |
| /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) |
| config->karst.tx_iq_comp_2_4G[0] = 0x01000000; |
| } else |
| config->karst.tx_iq_comp_2_4G[0] = 0x01000000; |
| |
| RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); |
| |
| /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) |
| config->karst.tx_iq_comp_2_4G[1] = 0x01000000; |
| } else |
| config->karst.tx_iq_comp_2_4G[1] = 0x01000000; |
| |
| RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); |
| |
| /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) |
| config->karst.rx_iq_comp_2_4G[0] = 0x01000000; |
| } else |
| config->karst.rx_iq_comp_2_4G[0] = 0x01000000; |
| |
| RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); |
| |
| /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) |
| config->karst.rx_iq_comp_2_4G[1] = 0x01000000; |
| } else |
| config->karst.rx_iq_comp_2_4G[1] = 0x01000000; |
| |
| RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); |
| |
| /* Get Karst TX IQ compensation value for path0 on 5GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) |
| config->karst.tx_iq_comp_5G[0] = 0x01000000; |
| } else |
| config->karst.tx_iq_comp_5G[0] = 0x01000000; |
| |
| RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); |
| |
| /* Get Karst TX IQ compensation value for path1 on 5GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) |
| config->karst.tx_iq_comp_5G[1] = 0x01000000; |
| } else |
| config->karst.tx_iq_comp_5G[1] = 0x01000000; |
| |
| RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); |
| |
| /* Get Karst RX IQ compensation value for path0 on 5GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) |
| config->karst.rx_iq_comp_5G[0] = 0x01000000; |
| } else |
| config->karst.rx_iq_comp_5G[0] = 0x01000000; |
| |
| RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); |
| |
| /* Get Karst RX IQ compensation value for path1 on 5GHz */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); |
| if (tag_ptr != NULL) { |
| if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) |
| config->karst.rx_iq_comp_5G[1] = 0x01000000; |
| } else |
| config->karst.rx_iq_comp_5G[1] = 0x01000000; |
| |
| RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); |
| |
| /* Get Karst default path */ |
| tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, |
| "KARST_DEFAULT_PATH=", strlen("00")); |
| if (tag_ptr != NULL) { |
| u8 val; |
| if (sscanf(tag_ptr, "%hhx", &val) == 1) |
| config->karst.path_used = val; |
| else |
| config->karst.path_used = path; |
| } else |
| config->karst.path_used = path; |
| |
| RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); |
| |
| /* Release the configuration file */ |
| release_firmware(config_fw); |
| |
| return 0; |
| } |
| |