• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Abilis Systems Single DVB-T Receiver
3  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/ctype.h>
23 #include <linux/delay.h>
24 #include <linux/firmware.h>
25 
26 #include "as102_drv.h"
27 #include "as102_fw.h"
28 
29 char as102_st_fw1[] = "as102_data1_st.hex";
30 char as102_st_fw2[] = "as102_data2_st.hex";
31 char as102_dt_fw1[] = "as102_data1_dt.hex";
32 char as102_dt_fw2[] = "as102_data2_dt.hex";
33 
atohx(unsigned char * dst,char * src)34 static unsigned char atohx(unsigned char *dst, char *src)
35 {
36 	unsigned char value = 0;
37 
38 	char msb = tolower(*src) - '0';
39 	char lsb = tolower(*(src + 1)) - '0';
40 
41 	if (msb > 9)
42 		msb -= 7;
43 	if (lsb > 9)
44 		lsb -= 7;
45 
46 	*dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
47 	return value;
48 }
49 
50 /*
51  * Parse INTEL HEX firmware file to extract address and data.
52  */
parse_hex_line(unsigned char * fw_data,unsigned char * addr,unsigned char * data,int * dataLength,unsigned char * addr_has_changed)53 static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
54 			  unsigned char *data, int *dataLength,
55 			  unsigned char *addr_has_changed) {
56 
57 	int count = 0;
58 	unsigned char *src, dst;
59 
60 	if (*fw_data++ != ':') {
61 		pr_err("invalid firmware file\n");
62 		return -EFAULT;
63 	}
64 
65 	/* locate end of line */
66 	for (src = fw_data; *src != '\n'; src += 2) {
67 		atohx(&dst, src);
68 		/* parse line to split addr / data */
69 		switch (count) {
70 		case 0:
71 			*dataLength = dst;
72 			break;
73 		case 1:
74 			addr[2] = dst;
75 			break;
76 		case 2:
77 			addr[3] = dst;
78 			break;
79 		case 3:
80 			/* check if data is an address */
81 			if (dst == 0x04)
82 				*addr_has_changed = 1;
83 			else
84 				*addr_has_changed = 0;
85 			break;
86 		case  4:
87 		case  5:
88 			if (*addr_has_changed)
89 				addr[(count - 4)] = dst;
90 			else
91 				data[(count - 4)] = dst;
92 			break;
93 		default:
94 			data[(count - 4)] = dst;
95 			break;
96 		}
97 		count++;
98 	}
99 
100 	/* return read value + ':' + '\n' */
101 	return (count * 2) + 2;
102 }
103 
as102_firmware_upload(struct as10x_bus_adapter_t * bus_adap,unsigned char * cmd,const struct firmware * firmware)104 static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
105 				 unsigned char *cmd,
106 				 const struct firmware *firmware) {
107 
108 	struct as10x_fw_pkt_t fw_pkt;
109 	int total_read_bytes = 0, errno = 0;
110 	unsigned char addr_has_changed = 0;
111 
112 	ENTER();
113 
114 	for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
115 		int read_bytes = 0, data_len = 0;
116 
117 		/* parse intel hex line */
118 		read_bytes = parse_hex_line(
119 				(u8 *) (firmware->data + total_read_bytes),
120 				fw_pkt.raw.address,
121 				fw_pkt.raw.data,
122 				&data_len,
123 				&addr_has_changed);
124 
125 		if (read_bytes <= 0)
126 			goto error;
127 
128 		/* detect the end of file */
129 		total_read_bytes += read_bytes;
130 		if (total_read_bytes == firmware->size) {
131 			fw_pkt.u.request[0] = 0x00;
132 			fw_pkt.u.request[1] = 0x03;
133 
134 			/* send EOF command */
135 			errno = bus_adap->ops->upload_fw_pkt(bus_adap,
136 							     (uint8_t *)
137 							     &fw_pkt, 2, 0);
138 			if (errno < 0)
139 				goto error;
140 		} else {
141 			if (!addr_has_changed) {
142 				/* prepare command to send */
143 				fw_pkt.u.request[0] = 0x00;
144 				fw_pkt.u.request[1] = 0x01;
145 
146 				data_len += sizeof(fw_pkt.u.request);
147 				data_len += sizeof(fw_pkt.raw.address);
148 
149 				/* send cmd to device */
150 				errno = bus_adap->ops->upload_fw_pkt(bus_adap,
151 								     (uint8_t *)
152 								     &fw_pkt,
153 								     data_len,
154 								     0);
155 				if (errno < 0)
156 					goto error;
157 			}
158 		}
159 	}
160 error:
161 	LEAVE();
162 	return (errno == 0) ? total_read_bytes : errno;
163 }
164 
as102_fw_upload(struct as10x_bus_adapter_t * bus_adap)165 int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
166 {
167 	int errno = -EFAULT;
168 	const struct firmware *firmware = NULL;
169 	unsigned char *cmd_buf = NULL;
170 	char *fw1, *fw2;
171 	struct usb_device *dev = bus_adap->usb_dev;
172 
173 	ENTER();
174 
175 	/* select fw file to upload */
176 	if (dual_tuner) {
177 		fw1 = as102_dt_fw1;
178 		fw2 = as102_dt_fw2;
179 	} else {
180 		fw1 = as102_st_fw1;
181 		fw2 = as102_st_fw2;
182 	}
183 
184 	/* allocate buffer to store firmware upload command and data */
185 	cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
186 	if (cmd_buf == NULL) {
187 		errno = -ENOMEM;
188 		goto error;
189 	}
190 
191 	/* request kernel to locate firmware file: part1 */
192 	errno = request_firmware(&firmware, fw1, &dev->dev);
193 	if (errno < 0) {
194 		pr_err("%s: unable to locate firmware file: %s\n",
195 		       DRIVER_NAME, fw1);
196 		goto error;
197 	}
198 
199 	/* initiate firmware upload */
200 	errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
201 	if (errno < 0) {
202 		pr_err("%s: error during firmware upload part1\n",
203 		       DRIVER_NAME);
204 		goto error;
205 	}
206 
207 	pr_info("%s: firmware: %s loaded with success\n",
208 		DRIVER_NAME, fw1);
209 	release_firmware(firmware);
210 
211 	/* wait for boot to complete */
212 	mdelay(100);
213 
214 	/* request kernel to locate firmware file: part2 */
215 	errno = request_firmware(&firmware, fw2, &dev->dev);
216 	if (errno < 0) {
217 		pr_err("%s: unable to locate firmware file: %s\n",
218 		       DRIVER_NAME, fw2);
219 		goto error;
220 	}
221 
222 	/* initiate firmware upload */
223 	errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
224 	if (errno < 0) {
225 		pr_err("%s: error during firmware upload part2\n",
226 		       DRIVER_NAME);
227 		goto error;
228 	}
229 
230 	pr_info("%s: firmware: %s loaded with success\n",
231 		DRIVER_NAME, fw2);
232 error:
233 	kfree(cmd_buf);
234 	release_firmware(firmware);
235 
236 	LEAVE();
237 	return errno;
238 }
239