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;
}
Ejemplo n.º 2
0
static int ath6kl_upload_patch(struct ath6kl *ar)
{
	const char *filename;
	u32 address, param;
	int ret;

	switch (ar->version.target_ver) {
	case AR6003_REV2_VERSION:
		filename = AR6003_REV2_PATCH_FILE;
		break;
	default:
		filename = AR6003_REV3_PATCH_FILE;
		break;
	}

	if (ar->fw_patch == NULL) {
		ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
				    &ar->fw_patch_len);
		if (ret) {
			ath6kl_err("Failed to get patch file %s: %d\n",
				   filename, ret);
			return ret;
		}
	}

	address = ath6kl_get_load_address(ar->version.target_ver,
					  DATASET_PATCH_ADDR);

	ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
	if (ret) {
		ath6kl_err("Failed to write patch file: %d\n", ret);
		return ret;
	}

	param = address;
	ath6kl_bmi_write(ar,
			 ath6kl_get_hi_item_addr(ar,
			 HI_ITEM(hi_dset_list_head)),
			 (unsigned char *) &param, 4);

	return 0;
}
Ejemplo n.º 3
0
/*
 * Set HTC/Mbox operational parameters, this can only be called when the
 * target is in the BMI phase.
 */
static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
				 u8 htc_ctrl_buf)
{
	int status;
	u32 blk_size;

	blk_size = ar->mbox_info.block_size;

	if (htc_ctrl_buf)
		blk_size |=  ((u32)htc_ctrl_buf) << 16;

	/* set the host interest area for the block size */
	status = ath6kl_bmi_write(ar,
			ath6kl_get_hi_item_addr(ar,
			HI_ITEM(hi_mbox_io_block_sz)),
			(u8 *)&blk_size,
			4);
	if (status) {
		ath6kl_err("bmi_write_memory for IO block size failed\n");
		goto out;
	}

	ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
		   blk_size,
		   ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));

	if (mbox_isr_yield_val) {
		/* set the host interest area for the mbox ISR yield limit */
		status = ath6kl_bmi_write(ar,
				ath6kl_get_hi_item_addr(ar,
				HI_ITEM(hi_mbox_isr_yield_limit)),
				(u8 *)&mbox_isr_yield_val,
				4);
		if (status) {
			ath6kl_err("bmi_write_memory for yield limit failed\n");
			goto out;
		}
	}

out:
	return status;
}
Ejemplo n.º 4
0
static int ath6kl_init_upload(struct ath6kl *ar)
{
	u32 param, options, sleep, address;
	int status = 0;

	if (ar->target_type != TARGET_TYPE_AR6003)
		return -EINVAL;

	/* temporarily disable system sleep */
	address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
	status = ath6kl_bmi_reg_read(ar, address, &param);
	if (status)
		return status;

	options = param;

	param |= ATH6KL_OPTION_SLEEP_DISABLE;
	status = ath6kl_bmi_reg_write(ar, address, param);
	if (status)
		return status;

	address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
	status = ath6kl_bmi_reg_read(ar, address, &param);
	if (status)
		return status;

	sleep = param;

	param |= SM(SYSTEM_SLEEP_DISABLE, 1);
	status = ath6kl_bmi_reg_write(ar, address, param);
	if (status)
		return status;

	ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
		   options, sleep);

	/* program analog PLL register */
	status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
				      0xF9104001);
	if (status)
		return status;

	/* Run at 80/88MHz by default */
	param = SM(CPU_CLOCK_STANDARD, 1);

	address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
	status = ath6kl_bmi_reg_write(ar, address, param);
	if (status)
		return status;

	param = 0;
	address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
	param = SM(LPO_CAL_ENABLE, 1);
	status = ath6kl_bmi_reg_write(ar, address, param);
	if (status)
		return status;

	/* WAR to avoid SDIO CRC err */
	if (ar->version.target_ver == AR6003_REV2_VERSION) {
		ath6kl_err("temporary war to avoid sdio crc error\n");

		param = 0x20;

		address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
		status = ath6kl_bmi_reg_write(ar, address, param);
		if (status)
			return status;

		address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
		status = ath6kl_bmi_reg_write(ar, address, param);
		if (status)
			return status;

		address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
		status = ath6kl_bmi_reg_write(ar, address, param);
		if (status)
			return status;

		address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
		status = ath6kl_bmi_reg_write(ar, address, param);
		if (status)
			return status;
	}

	/* write EEPROM data to Target RAM */
	status = ath6kl_upload_board_file(ar);
	if (status)
		return status;

	/* transfer One time Programmable data */
	status = ath6kl_upload_otp(ar);
	if (status)
		return status;

	/* Download Target firmware */
	status = ath6kl_upload_firmware(ar);
	if (status)
		return status;

	status = ath6kl_upload_patch(ar);
	if (status)
		return status;

	/* Restore system sleep */
	address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
	status = ath6kl_bmi_reg_write(ar, address, sleep);
	if (status)
		return status;

	address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
	param = options | 0x20;
	status = ath6kl_bmi_reg_write(ar, address, param);
	if (status)
		return status;

	/* Configure GPIO AR6003 UART */
	param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
	status = ath6kl_bmi_write(ar,
				  ath6kl_get_hi_item_addr(ar,
				  HI_ITEM(hi_dbg_uart_txpin)),
				  (u8 *)&param, 4);

	return status;
}
Ejemplo n.º 5
0
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 *) &param, 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 *)&param, 4);

	return ret;
}
Ejemplo n.º 6
0
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 *)&param, 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 *)&param, 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 *)&param,
			     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 *)&param, 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;
}