1/**
2 * Copyright (c) 2014 Redpine Signals Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 */
17
18#include <linux/firmware.h>
19#include "rsi_usb.h"
20
21/**
22 * rsi_copy_to_card() - This function includes the actual funtionality of
23 *			copying the TA firmware to the card.Basically this
24 *			function includes opening the TA file,reading the TA
25 *			file and writing their values in blocks of data.
26 * @common: Pointer to the driver private structure.
27 * @fw: Pointer to the firmware value to be written.
28 * @len: length of firmware file.
29 * @num_blocks: Number of blocks to be written to the card.
30 *
31 * Return: 0 on success and -1 on failure.
32 */
33static int rsi_copy_to_card(struct rsi_common *common,
34			    const u8 *fw,
35			    u32 len,
36			    u32 num_blocks)
37{
38	struct rsi_hw *adapter = common->priv;
39	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
40	u32 indx, ii;
41	u32 block_size = dev->tx_blk_size;
42	u32 lsb_address;
43	u32 base_address;
44
45	base_address = TA_LOAD_ADDRESS;
46
47	for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
48		lsb_address = base_address;
49		if (rsi_usb_write_register_multiple(adapter,
50						    lsb_address,
51						    (u8 *)(fw + indx),
52						    block_size)) {
53			rsi_dbg(ERR_ZONE,
54				"%s: Unable to load %s blk\n", __func__,
55				FIRMWARE_RSI9113);
56			return -EIO;
57		}
58		rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
59		base_address += block_size;
60	}
61
62	if (len % block_size) {
63		lsb_address = base_address;
64		if (rsi_usb_write_register_multiple(adapter,
65						    lsb_address,
66						    (u8 *)(fw + indx),
67						    len % block_size)) {
68			rsi_dbg(ERR_ZONE,
69				"%s: Unable to load %s blk\n", __func__,
70				FIRMWARE_RSI9113);
71			return -EIO;
72		}
73	}
74	rsi_dbg(INIT_ZONE,
75		"%s: Succesfully loaded %s instructions\n", __func__,
76		FIRMWARE_RSI9113);
77
78	rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
79	return 0;
80}
81
82/**
83 * rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
84 *			 the USB device.
85 * @common: Pointer to the driver private structure.
86 *
87 * Return: None.
88 */
89void rsi_usb_rx_thread(struct rsi_common *common)
90{
91	struct rsi_hw *adapter = common->priv;
92	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
93	int status;
94
95	do {
96		rsi_wait_event(&dev->rx_thread.event, EVENT_WAIT_FOREVER);
97
98		if (atomic_read(&dev->rx_thread.thread_done))
99			goto out;
100
101		mutex_lock(&common->tx_rxlock);
102		status = rsi_read_pkt(common, 0);
103		if (status) {
104			rsi_dbg(ERR_ZONE, "%s: Failed To read data", __func__);
105			mutex_unlock(&common->tx_rxlock);
106			return;
107		}
108		mutex_unlock(&common->tx_rxlock);
109		rsi_reset_event(&dev->rx_thread.event);
110		if (adapter->rx_urb_submit(adapter)) {
111			rsi_dbg(ERR_ZONE,
112				"%s: Failed in urb submission", __func__);
113			return;
114		}
115	} while (1);
116
117out:
118	rsi_dbg(INFO_ZONE, "%s: Terminated thread\n", __func__);
119	complete_and_exit(&dev->rx_thread.completion, 0);
120}
121
122
123/**
124 * rsi_load_ta_instructions() - This function includes the actual funtionality
125 *				of loading the TA firmware.This function also
126 *				includes opening the TA file,reading the TA
127 *				file and writing their value in blocks of data.
128 * @common: Pointer to the driver private structure.
129 *
130 * Return: status: 0 on success, -1 on failure.
131 */
132static int rsi_load_ta_instructions(struct rsi_common *common)
133{
134	struct rsi_hw *adapter = common->priv;
135	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
136	const struct firmware *fw_entry = NULL;
137	u32 block_size = dev->tx_blk_size;
138	const u8 *fw;
139	u32 num_blocks, len;
140	int status = 0;
141
142	status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
143	if (status < 0) {
144		rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
145			__func__, FIRMWARE_RSI9113);
146		return status;
147	}
148
149	/* Copy firmware into DMA-accessible memory */
150	fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
151	if (!fw) {
152		status = -ENOMEM;
153		goto out;
154	}
155	len = fw_entry->size;
156
157	if (len % 4)
158		len += (4 - (len % 4));
159
160	num_blocks = (len / block_size);
161
162	rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
163	rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
164
165	status = rsi_copy_to_card(common, fw, len, num_blocks);
166	kfree(fw);
167
168out:
169	release_firmware(fw_entry);
170	return status;
171}
172
173/**
174 * rsi_device_init() - This Function Initializes The HAL.
175 * @common: Pointer to the driver private structure.
176 *
177 * Return: 0 on success, -1 on failure.
178 */
179int rsi_usb_device_init(struct rsi_common *common)
180{
181	if (rsi_load_ta_instructions(common))
182		return -EIO;
183
184	return 0;
185		}
186