1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
4  * All rights reserved.
5  *
6  * File: baseband.c
7  *
8  * Purpose: Implement functions to access baseband
9  *
10  * Author: Yiching Chen
11  *
12  * Date: May 20, 2004
13  *
14  * Functions:
15  *
16  * Revision History:
17  *
18  */
19 
20 #include <linux/compiler.h>
21 #include "firmware.h"
22 #include "usbpipe.h"
23 
24 #define FIRMWARE_VERSION	0x133		/* version 1.51 */
25 #define FIRMWARE_NAME		"vntwusb.fw"
26 
27 #define FIRMWARE_CHUNK_SIZE	0x400
28 
vnt_download_firmware(struct vnt_private * priv)29 int vnt_download_firmware(struct vnt_private *priv)
30 {
31 	struct device *dev = &priv->usb->dev;
32 	const struct firmware *fw;
33 	int status;
34 	void *buffer = NULL;
35 	bool result = false;
36 	u16 length;
37 	int ii, rc;
38 
39 	dev_dbg(dev, "---->Download firmware\n");
40 
41 	rc = request_firmware(&fw, FIRMWARE_NAME, dev);
42 	if (rc) {
43 		dev_err(dev, "firmware file %s request failed (%d)\n",
44 			FIRMWARE_NAME, rc);
45 			goto out;
46 	}
47 
48 	buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
49 	if (!buffer)
50 		goto free_fw;
51 
52 	for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
53 		length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
54 		memcpy(buffer, fw->data + ii, length);
55 
56 		status = vnt_control_out(priv,
57 					 0,
58 					 0x1200 + ii,
59 					 0x0000,
60 					 length,
61 					 buffer);
62 
63 		dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size);
64 
65 		if (status != STATUS_SUCCESS)
66 			goto free_fw;
67 	}
68 
69 	result = true;
70 free_fw:
71 	release_firmware(fw);
72 
73 out:
74 	kfree(buffer);
75 
76 	return result;
77 }
78 MODULE_FIRMWARE(FIRMWARE_NAME);
79 
vnt_firmware_branch_to_sram(struct vnt_private * priv)80 int vnt_firmware_branch_to_sram(struct vnt_private *priv)
81 {
82 	int status;
83 
84 	dev_dbg(&priv->usb->dev, "---->Branch to Sram\n");
85 
86 	status = vnt_control_out(priv,
87 				 1,
88 				 0x1200,
89 				 0x0000,
90 				 0,
91 				 NULL);
92 	return status == STATUS_SUCCESS;
93 }
94 
vnt_check_firmware_version(struct vnt_private * priv)95 int vnt_check_firmware_version(struct vnt_private *priv)
96 {
97 	int status;
98 
99 	status = vnt_control_in(priv,
100 				MESSAGE_TYPE_READ,
101 				0,
102 				MESSAGE_REQUEST_VERSION,
103 				2,
104 				(u8 *)&priv->firmware_version);
105 
106 	dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
107 		priv->firmware_version);
108 
109 	if (status != STATUS_SUCCESS) {
110 		dev_dbg(&priv->usb->dev, "Firmware Invalid.\n");
111 		return false;
112 	}
113 	if (priv->firmware_version == 0xFFFF) {
114 		dev_dbg(&priv->usb->dev, "In Loader.\n");
115 		return false;
116 	}
117 
118 	dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
119 		priv->firmware_version);
120 
121 	if (priv->firmware_version < FIRMWARE_VERSION) {
122 		/* branch to loader for download new firmware */
123 		vnt_firmware_branch_to_sram(priv);
124 		return false;
125 	}
126 	return true;
127 }
128