|  | // SPDX-License-Identifier: GPL-2.0+ | 
|  | /* | 
|  | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | 
|  | * All rights reserved. | 
|  | * | 
|  | * File: baseband.c | 
|  | * | 
|  | * Purpose: Implement functions to access baseband | 
|  | * | 
|  | * Author: Yiching Chen | 
|  | * | 
|  | * Date: May 20, 2004 | 
|  | * | 
|  | * Functions: | 
|  | * | 
|  | * Revision History: | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include <linux/compiler.h> | 
|  | #include "firmware.h" | 
|  | #include "usbpipe.h" | 
|  |  | 
|  | #define FIRMWARE_VERSION	0x133		/* version 1.51 */ | 
|  | #define FIRMWARE_NAME		"vntwusb.fw" | 
|  |  | 
|  | #define FIRMWARE_CHUNK_SIZE	0x400 | 
|  |  | 
|  | int vnt_download_firmware(struct vnt_private *priv) | 
|  | { | 
|  | struct device *dev = &priv->usb->dev; | 
|  | const struct firmware *fw; | 
|  | int status; | 
|  | void *buffer = NULL; | 
|  | bool result = false; | 
|  | u16 length; | 
|  | int ii, rc; | 
|  |  | 
|  | dev_dbg(dev, "---->Download firmware\n"); | 
|  |  | 
|  | rc = request_firmware(&fw, FIRMWARE_NAME, dev); | 
|  | if (rc) { | 
|  | dev_err(dev, "firmware file %s request failed (%d)\n", | 
|  | FIRMWARE_NAME, rc); | 
|  | goto out; | 
|  | } | 
|  |  | 
|  | buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); | 
|  | if (!buffer) | 
|  | goto free_fw; | 
|  |  | 
|  | for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) { | 
|  | length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE); | 
|  | memcpy(buffer, fw->data + ii, length); | 
|  |  | 
|  | status = vnt_control_out(priv, | 
|  | 0, | 
|  | 0x1200 + ii, | 
|  | 0x0000, | 
|  | length, | 
|  | buffer); | 
|  |  | 
|  | dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size); | 
|  |  | 
|  | if (status != STATUS_SUCCESS) | 
|  | goto free_fw; | 
|  | } | 
|  |  | 
|  | result = true; | 
|  | free_fw: | 
|  | release_firmware(fw); | 
|  |  | 
|  | out: | 
|  | kfree(buffer); | 
|  |  | 
|  | return result; | 
|  | } | 
|  | MODULE_FIRMWARE(FIRMWARE_NAME); | 
|  |  | 
|  | int vnt_firmware_branch_to_sram(struct vnt_private *priv) | 
|  | { | 
|  | int status; | 
|  |  | 
|  | dev_dbg(&priv->usb->dev, "---->Branch to Sram\n"); | 
|  |  | 
|  | status = vnt_control_out(priv, | 
|  | 1, | 
|  | 0x1200, | 
|  | 0x0000, | 
|  | 0, | 
|  | NULL); | 
|  | return status == STATUS_SUCCESS; | 
|  | } | 
|  |  | 
|  | int vnt_check_firmware_version(struct vnt_private *priv) | 
|  | { | 
|  | int status; | 
|  |  | 
|  | status = vnt_control_in(priv, | 
|  | MESSAGE_TYPE_READ, | 
|  | 0, | 
|  | MESSAGE_REQUEST_VERSION, | 
|  | 2, | 
|  | (u8 *)&priv->firmware_version); | 
|  |  | 
|  | dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n", | 
|  | priv->firmware_version); | 
|  |  | 
|  | if (status != STATUS_SUCCESS) { | 
|  | dev_dbg(&priv->usb->dev, "Firmware Invalid.\n"); | 
|  | return false; | 
|  | } | 
|  | if (priv->firmware_version == 0xFFFF) { | 
|  | dev_dbg(&priv->usb->dev, "In Loader.\n"); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n", | 
|  | priv->firmware_version); | 
|  |  | 
|  | if (priv->firmware_version < FIRMWARE_VERSION) { | 
|  | /* branch to loader for download new firmware */ | 
|  | vnt_firmware_branch_to_sram(priv); | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } |