1/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 *
20 * File: baseband.c
21 *
22 * Purpose: Implement functions to access baseband
23 *
24 * Author: Yiching Chen
25 *
26 * Date: May 20, 2004
27 *
28 * Functions:
29 *
30 * Revision History:
31 *
32 */
33
34#include <linux/compiler.h>
35#include "firmware.h"
36#include "usbpipe.h"
37
38#define FIRMWARE_VERSION	0x133		/* version 1.51 */
39#define FIRMWARE_NAME		"vntwusb.fw"
40
41#define FIRMWARE_CHUNK_SIZE	0x400
42
43int vnt_download_firmware(struct vnt_private *priv)
44{
45	struct device *dev = &priv->usb->dev;
46	const struct firmware *fw;
47	int status;
48	void *buffer = NULL;
49	bool result = false;
50	u16 length;
51	int ii, rc;
52
53	dev_dbg(dev, "---->Download firmware\n");
54
55	rc = request_firmware(&fw, FIRMWARE_NAME, dev);
56	if (rc) {
57		dev_err(dev, "firmware file %s request failed (%d)\n",
58			FIRMWARE_NAME, rc);
59			goto out;
60	}
61
62	buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
63	if (!buffer)
64		goto free_fw;
65
66	for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
67		length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
68		memcpy(buffer, fw->data + ii, length);
69
70		status = vnt_control_out(priv,
71						0,
72						0x1200+ii,
73						0x0000,
74						length,
75						buffer);
76
77		dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size);
78
79		if (status != STATUS_SUCCESS)
80			goto free_fw;
81	}
82
83	result = true;
84free_fw:
85	release_firmware(fw);
86
87out:
88	kfree(buffer);
89
90	return result;
91}
92MODULE_FIRMWARE(FIRMWARE_NAME);
93
94int vnt_firmware_branch_to_sram(struct vnt_private *priv)
95{
96	int status;
97
98	dev_dbg(&priv->usb->dev, "---->Branch to Sram\n");
99
100	status = vnt_control_out(priv,
101					1,
102					0x1200,
103					0x0000,
104					0,
105					NULL);
106	return status == STATUS_SUCCESS;
107}
108
109int vnt_check_firmware_version(struct vnt_private *priv)
110{
111	int status;
112
113	status = vnt_control_in(priv,
114					MESSAGE_TYPE_READ,
115					0,
116					MESSAGE_REQUEST_VERSION,
117					2,
118					(u8 *)&priv->firmware_version);
119
120	dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
121						priv->firmware_version);
122
123	if (status != STATUS_SUCCESS) {
124		dev_dbg(&priv->usb->dev, "Firmware Invalid.\n");
125		return false;
126	}
127	if (priv->firmware_version == 0xFFFF) {
128		dev_dbg(&priv->usb->dev, "In Loader.\n");
129		return false;
130	}
131
132	dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
133						priv->firmware_version);
134
135	if (priv->firmware_version < FIRMWARE_VERSION) {
136		/* branch to loader for download new firmware */
137		vnt_firmware_branch_to_sram(priv);
138		return false;
139	}
140	return true;
141}
142