int ath6kl_set_reg_dmn(struct ath6kl *ar) { u8 buf[REG_DMN_BOARD_DATA_LEN]; __le16 old_sum, old_ver, old_rd, old_rd_next; __le32 brd_dat_addr = 0, new_sum, new_rd; int ret; if (reg_domain == 0xffff) return 0; printk("%s enter \n",__FUNCTION__); ret = ath6kl_bmi_read(ar, AR6003_BOARD_DATA_ADDR, (u8 *)&brd_dat_addr, 4); if (ret) return ret; memset(buf, 0, sizeof(buf)); ret = ath6kl_bmi_read(ar, brd_dat_addr, buf, sizeof(buf)); if (ret) return ret; memcpy((u8 *)&old_sum, buf + AR6003_BOARD_DATA_OFFSET, 2); memcpy((u8 *)&old_ver, buf + AR6003_BOARD_DATA_OFFSET + 2, 2); memcpy((u8 *)&old_rd, buf + AR6003_RD_OFFSET, 2); memcpy((u8 *)&old_rd_next, buf + AR6003_RD_OFFSET + 2, 2); /* * Overwrite the new regulatory domain and preserve the * MAC addr which is in the same word. */ new_rd = cpu_to_le32((le32_to_cpu(old_rd_next) << 16) + reg_domain); ret = ath6kl_bmi_write(ar, cpu_to_le32(le32_to_cpu(brd_dat_addr) + AR6003_RD_OFFSET), (u8 *)&new_rd, 4); if (ret) return ret; /* * Recompute the board data checksum with the new regulatory * domain, preserve the version information which is in the * same word. */ new_sum = cpu_to_le32((le32_to_cpu(old_ver) << 16) + (le32_to_cpu(old_sum) ^ le32_to_cpu(old_rd) ^ reg_domain)); ret = ath6kl_bmi_write(ar, cpu_to_le32(le32_to_cpu(brd_dat_addr) + AR6003_BOARD_DATA_OFFSET), (u8 *)&new_sum, 4); return ret; }
static int ath6kl_upload_board_file(struct ath6kl *ar) { u32 board_address, board_ext_address, param; int ret; if (ar->fw_board == NULL) { ret = ath6kl_fetch_board_file(ar); if (ret) return ret; } /* Determine where in Target RAM to write Board Data */ ath6kl_bmi_read(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_data)), (u8 *) &board_address, 4); ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n", board_address); /* determine where in target ram to write extended board data */ ath6kl_bmi_read(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_ext_data)), (u8 *) &board_ext_address, 4); ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n", board_ext_address); if (board_ext_address == 0) { ath6kl_err("Failed to get board file target address.\n"); return -EINVAL; } if (ar->fw_board_len == (AR6003_BOARD_DATA_SZ + AR6003_BOARD_EXT_DATA_SZ)) { /* write extended board data */ ret = ath6kl_bmi_write(ar, board_ext_address, ar->fw_board + AR6003_BOARD_DATA_SZ, AR6003_BOARD_EXT_DATA_SZ); if (ret) { ath6kl_err("Failed to write extended board data: %d\n", ret); return ret; } /* record that extended board data is initialized */ param = (AR6003_BOARD_EXT_DATA_SZ << 16) | 1; ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_ext_data_config)), (unsigned char *) ¶m, 4); } if (ar->fw_board_len < AR6003_BOARD_DATA_SZ) { ath6kl_err("Too small board file: %zu\n", ar->fw_board_len); ret = -EINVAL; return ret; } ret = ath6kl_bmi_write(ar, board_address, ar->fw_board, AR6003_BOARD_DATA_SZ); if (ret) { ath6kl_err("Board file bmi write failed: %d\n", ret); return ret; } /* record the fact that Board Data IS initialized */ param = 1; ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_data_initialized)), (u8 *)¶m, 4); return ret; }
int ath6kl_configure_target(struct ath6kl *ar) { u32 param, ram_reserved_size; u8 fw_iftype; fw_iftype = ath6kl_get_fw_iftype(ar); if (fw_iftype == 0xff) return -EINVAL; /* Tell target which HTC version it is used*/ param = HTC_PROTOCOL_VERSION; if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest)), (u8 *)¶m, 4) != 0) { ath6kl_err("bmi_write_memory for htc version failed\n"); return -EIO; } /* set the firmware mode to STA/IBSS/AP */ param = 0; if (ath6kl_bmi_read(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_option_flag)), (u8 *)¶m, 4) != 0) { ath6kl_err("bmi_read_memory for setting fwmode failed\n"); return -EIO; } param |= (1 << HI_OPTION_NUM_DEV_SHIFT); param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT); param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_option_flag)), (u8 *)¶m, 4) != 0) { ath6kl_err("bmi_write_memory for setting fwmode failed\n"); return -EIO; } ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n"); /* * Hardcode the address use for the extended board data * Ideally this should be pre-allocate by the OS at boot time * But since it is a new feature and board data is loaded * at init time, we have to workaround this from host. * It is difficult to patch the firmware boot code, * but possible in theory. */ if (ar->target_type == TARGET_TYPE_AR6003) { if (ar->version.target_ver == AR6003_REV2_VERSION) { param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; ram_reserved_size = AR6003_REV2_RAM_RESERVE_SIZE; } else { param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; ram_reserved_size = AR6003_REV3_RAM_RESERVE_SIZE; } if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_board_ext_data)), (u8 *)¶m, 4) != 0) { ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); return -EIO; } if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_end_ram_reserve_sz)), (u8 *)&ram_reserved_size, 4) != 0) { ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); return -EIO; } } /* set the block size for the target */ if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0)) /* use default number of control buffers */ return -EIO; return 0; }