io_ti.c 72.5 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Edgeport USB Serial Converter driver
 *
 * Copyright (C) 2000-2002 Inside Out Networks, All rights reserved.
 * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 * Supports the following devices:
 *	EP/1 EP/2 EP/4 EP/21 EP/22 EP/221 EP/42 EP/421 WATCHPORT
 *
 * For questions or problems with this driver, contact Inside Out
 * Networks technical support, or Peter Berger <pberger@brimson.com>,
 * or Al Borchers <alborchers@steinerpoint.com>.
 */

#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
30
#include <linux/mutex.h>
Linus Torvalds's avatar
Linus Torvalds committed
31
#include <linux/serial.h>
32
#include <linux/kfifo.h>
Linus Torvalds's avatar
Linus Torvalds committed
33
#include <linux/ioctl.h>
34
#include <linux/firmware.h>
35
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
36
#include <linux/usb.h>
37
#include <linux/usb/serial.h>
Linus Torvalds's avatar
Linus Torvalds committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#include "io_16654.h"
#include "io_usbvend.h"
#include "io_ti.h"

#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"

#define EPROM_PAGE_SIZE		64


/* different hardware types */
#define HARDWARE_TYPE_930	0
#define HARDWARE_TYPE_TIUMP	1

53
54
55
56
57
58
/* IOCTL_PRIVATE_TI_GET_MODE Definitions */
#define	TI_MODE_CONFIGURING	0   /* Device has not entered start device */
#define	TI_MODE_BOOT		1   /* Staying in boot mode		   */
#define TI_MODE_DOWNLOAD	2   /* Made it to download mode		   */
#define TI_MODE_TRANSITIONING	3   /* Currently in boot mode but
				       transitioning to download mode	   */
Linus Torvalds's avatar
Linus Torvalds committed
59
60
61
62
63
64
65
66
67
68
69
70

/* read urb state */
#define EDGE_READ_URB_RUNNING	0
#define EDGE_READ_URB_STOPPING	1
#define EDGE_READ_URB_STOPPED	2

#define EDGE_CLOSING_WAIT	4000	/* in .01 sec */

#define EDGE_OUT_BUF_SIZE	1024


/* Product information read from the Edgeport */
71
72
73
struct product_info {
	int	TiMode;			/* Current TI Mode  */
	__u8	hardware_type;		/* Type of hardware */
Linus Torvalds's avatar
Linus Torvalds committed
74
75
76
77
78
79
80
81
82
} __attribute__((packed));

struct edgeport_port {
	__u16 uart_base;
	__u16 dma_address;
	__u8 shadow_msr;
	__u8 shadow_mcr;
	__u8 shadow_lsr;
	__u8 lsr_mask;
83
	__u32 ump_read_timeout;		/* Number of milliseconds the UMP will
Linus Torvalds's avatar
Linus Torvalds committed
84
85
86
87
88
					   wait without data before completing
					   a read short */
	int baud_rate;
	int close_pending;
	int lsr_event;
89

Linus Torvalds's avatar
Linus Torvalds committed
90
91
	struct edgeport_serial	*edge_serial;
	struct usb_serial_port	*port;
92
	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
Linus Torvalds's avatar
Linus Torvalds committed
93
94
95
	spinlock_t ep_lock;
	int ep_read_urb_state;
	int ep_write_urb_in_use;
96
	struct kfifo write_fifo;
Linus Torvalds's avatar
Linus Torvalds committed
97
98
99
100
};

struct edgeport_serial {
	struct product_info product_info;
101
102
103
	u8 TI_I2C_Type;			/* Type of I2C in UMP */
	u8 TiReadI2C;			/* Set to TRUE if we have read the
					   I2c in Boot Mode */
104
	struct mutex es_lock;
Linus Torvalds's avatar
Linus Torvalds committed
105
106
107
108
109
110
	int num_ports_open;
	struct usb_serial *serial;
};


/* Devices that this driver supports */
111
static const struct usb_device_id edgeport_1port_id_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) },
	{ }
};

131
static const struct usb_device_id edgeport_2port_id_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
132
133
134
135
136
137
138
139
140
141
142
143
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
144
	/* The 4, 8 and 16 port devices show up as multiple 2 port devices */
Linus Torvalds's avatar
Linus Torvalds committed
145
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
146
147
148
149
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
Linus Torvalds's avatar
Linus Torvalds committed
150
151
152
153
	{ }
};

/* Devices that this driver supports */
154
static const struct usb_device_id id_table_combined[] = {
Linus Torvalds's avatar
Linus Torvalds committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
184
185
186
187
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
Linus Torvalds's avatar
Linus Torvalds committed
188
189
190
	{ }
};

191
MODULE_DEVICE_TABLE(usb, id_table_combined);
Linus Torvalds's avatar
Linus Torvalds committed
192

193
194
195
static unsigned char OperationalMajorVersion;
static unsigned char OperationalMinorVersion;
static unsigned short OperationalBuildNumber;
Linus Torvalds's avatar
Linus Torvalds committed
196
197

static int closing_wait = EDGE_CLOSING_WAIT;
198
static bool ignore_cpu_rev;
199
static int default_uart_mode;		/* RS232 */
Linus Torvalds's avatar
Linus Torvalds committed
200

Jiri Slaby's avatar
Jiri Slaby committed
201
202
static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data,
		int length);
Linus Torvalds's avatar
Linus Torvalds committed
203
204
205
206

static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);

Alan Cox's avatar
Alan Cox committed
207
208
static void edge_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios);
209
static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
Linus Torvalds's avatar
Linus Torvalds committed
210

211
212
213
214
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
static int edge_remove_sysfs_attrs(struct usb_serial_port *port);

Linus Torvalds's avatar
Linus Torvalds committed
215

216
217
static int ti_vread_sync(struct usb_device *dev, __u8 request,
				__u16 value, __u16 index, u8 *data, int size)
Linus Torvalds's avatar
Linus Torvalds committed
218
219
220
{
	int status;

221
222
223
	status = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
			(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
			value, index, data, size, 1000);
Linus Torvalds's avatar
Linus Torvalds committed
224
225
226
	if (status < 0)
		return status;
	if (status != size) {
227
228
		dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n",
			__func__, size, status);
Linus Torvalds's avatar
Linus Torvalds committed
229
230
231
232
233
		return -ECOMM;
	}
	return 0;
}

234
235
static int ti_vsend_sync(struct usb_device *dev, __u8 request,
				__u16 value, __u16 index, u8 *data, int size)
Linus Torvalds's avatar
Linus Torvalds committed
236
237
238
{
	int status;

239
240
241
	status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
			(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
			value, index, data, size, 1000);
Linus Torvalds's avatar
Linus Torvalds committed
242
243
244
	if (status < 0)
		return status;
	if (status != size) {
245
246
		dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n",
			__func__, size, status);
Linus Torvalds's avatar
Linus Torvalds committed
247
248
249
250
251
		return -ECOMM;
	}
	return 0;
}

252
static int send_cmd(struct usb_device *dev, __u8 command,
Linus Torvalds's avatar
Linus Torvalds committed
253
254
255
				__u8 moduleid, __u16 value, u8 *data,
				int size)
{
256
	return ti_vsend_sync(dev, command, value, moduleid, data, size);
Linus Torvalds's avatar
Linus Torvalds committed
257
258
259
}

/* clear tx/rx buffers and fifo in TI UMP */
260
static int purge_port(struct usb_serial_port *port, __u16 mask)
Linus Torvalds's avatar
Linus Torvalds committed
261
262
263
{
	int port_number = port->number - port->serial->minor;

264
	dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask);
Linus Torvalds's avatar
Linus Torvalds committed
265

266
	return send_cmd(port->serial->dev,
Linus Torvalds's avatar
Linus Torvalds committed
267
268
269
270
271
272
273
274
					UMPC_PURGE_PORT,
					(__u8)(UMPM_UART1_PORT + port_number),
					mask,
					NULL,
					0);
}

/**
275
 * read_download_mem - Read edgeport memory from TI chip
Linus Torvalds's avatar
Linus Torvalds committed
276
277
278
279
280
281
 * @dev: usb device pointer
 * @start_address: Device CPU address at which to read
 * @length: Length of above data
 * @address_type: Can read both XDATA and I2C
 * @buffer: pointer to input data buffer
 */
282
static int read_download_mem(struct usb_device *dev, int start_address,
Linus Torvalds's avatar
Linus Torvalds committed
283
284
285
286
287
				int length, __u8 address_type, __u8 *buffer)
{
	int status = 0;
	__u8 read_length;
	__be16 be_start_address;
288

289
	dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
Linus Torvalds's avatar
Linus Torvalds committed
290
291
292
293
294
295

	/* Read in blocks of 64 bytes
	 * (TI firmware can't handle more than 64 byte reads)
	 */
	while (length) {
		if (length > 64)
296
			read_length = 64;
Linus Torvalds's avatar
Linus Torvalds committed
297
298
299
300
		else
			read_length = (__u8)length;

		if (read_length > 1) {
301
			dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length);
Linus Torvalds's avatar
Linus Torvalds committed
302
		}
303
304
305
306
307
		be_start_address = cpu_to_be16(start_address);
		status = ti_vread_sync(dev, UMPC_MEMORY_READ,
					(__u16)address_type,
					(__force __u16)be_start_address,
					buffer, read_length);
Linus Torvalds's avatar
Linus Torvalds committed
308
309

		if (status) {
310
			dev_dbg(&dev->dev, "%s - ERROR %x\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
311
312
313
			return status;
		}

314
		if (read_length > 1)
315
			usb_serial_debug_data(&dev->dev, __func__, read_length, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
316
317
318
319
320
321

		/* Update pointers/length */
		start_address += read_length;
		buffer += read_length;
		length -= read_length;
	}
322

Linus Torvalds's avatar
Linus Torvalds committed
323
324
325
	return status;
}

326
327
static int read_ram(struct usb_device *dev, int start_address,
						int length, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
328
{
329
330
	return read_download_mem(dev, start_address, length,
					DTK_ADDR_SPACE_XDATA, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
331
332
333
}

/* Read edgeport memory to a given block */
334
335
static int read_boot_mem(struct edgeport_serial *serial,
				int start_address, int length, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
336
337
338
339
{
	int status = 0;
	int i;

340
341
342
343
	for (i = 0; i < length; i++) {
		status = ti_vread_sync(serial->serial->dev,
				UMPC_MEMORY_READ, serial->TI_I2C_Type,
				(__u16)(start_address+i), &buffer[i], 0x01);
Linus Torvalds's avatar
Linus Torvalds committed
344
		if (status) {
345
			dev_dbg(&serial->serial->dev->dev, "%s - ERROR %x\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
346
347
348
349
			return status;
		}
	}

350
351
	dev_dbg(&serial->serial->dev->dev, "%s - start_address = %x, length = %d\n",
		__func__, start_address, length);
352
	usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
353
354
355
356
357
358
359

	serial->TiReadI2C = 1;

	return status;
}

/* Write given block to TI EPROM memory */
360
361
static int write_boot_mem(struct edgeport_serial *serial,
				int start_address, int length, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
362
363
364
{
	int status = 0;
	int i;
365
	u8 *temp;
Linus Torvalds's avatar
Linus Torvalds committed
366
367
368

	/* Must do a read before write */
	if (!serial->TiReadI2C) {
369
370
371
372
373
374
375
376
		temp = kmalloc(1, GFP_KERNEL);
		if (!temp) {
			dev_err(&serial->serial->dev->dev,
					"%s - out of memory\n", __func__);
			return -ENOMEM;
		}
		status = read_boot_mem(serial, 0, 1, temp);
		kfree(temp);
Linus Torvalds's avatar
Linus Torvalds committed
377
378
379
380
		if (status)
			return status;
	}

381
382
383
384
	for (i = 0; i < length; ++i) {
		status = ti_vsend_sync(serial->serial->dev,
				UMPC_MEMORY_WRITE, buffer[i],
				(__u16)(i + start_address), NULL, 0);
Linus Torvalds's avatar
Linus Torvalds committed
385
386
387
388
		if (status)
			return status;
	}

389
	dev_dbg(&serial->serial->dev->dev, "%s - start_sddr = %x, length = %d\n", __func__, start_address, length);
390
	usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
391
392
393
394
395
396

	return status;
}


/* Write edgeport I2C memory to TI chip	*/
397
398
static int write_i2c_mem(struct edgeport_serial *serial,
		int start_address, int length, __u8 address_type, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
399
{
400
	struct device *dev = &serial->serial->dev->dev;
Linus Torvalds's avatar
Linus Torvalds committed
401
402
403
404
405
	int status = 0;
	int write_length;
	__be16 be_start_address;

	/* We can only send a maximum of 1 aligned byte page at a time */
406

Lucas De Marchi's avatar
Lucas De Marchi committed
407
	/* calculate the number of bytes left in the first page */
408
409
	write_length = EPROM_PAGE_SIZE -
				(start_address & (EPROM_PAGE_SIZE - 1));
Linus Torvalds's avatar
Linus Torvalds committed
410
411
412
413

	if (write_length > length)
		write_length = length;

414
415
	dev_dbg(dev, "%s - BytesInFirstPage Addr = %x, length = %d\n",
		__func__, start_address, write_length);
416
	usb_serial_debug_data(dev, __func__, write_length, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
417
418

	/* Write first page */
419
420
421
422
423
	be_start_address = cpu_to_be16(start_address);
	status = ti_vsend_sync(serial->serial->dev,
				UMPC_MEMORY_WRITE, (__u16)address_type,
				(__force __u16)be_start_address,
				buffer,	write_length);
Linus Torvalds's avatar
Linus Torvalds committed
424
	if (status) {
425
		dev_dbg(dev, "%s - ERROR %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
426
427
428
429
430
431
432
		return status;
	}

	length		-= write_length;
	start_address	+= write_length;
	buffer		+= write_length;

433
434
	/* We should be aligned now -- can write
	   max page size bytes at a time */
Linus Torvalds's avatar
Linus Torvalds committed
435
436
437
438
439
440
	while (length) {
		if (length > EPROM_PAGE_SIZE)
			write_length = EPROM_PAGE_SIZE;
		else
			write_length = length;

441
442
		dev_dbg(dev, "%s - Page Write Addr = %x, length = %d\n",
			__func__, start_address, write_length);
443
		usb_serial_debug_data(dev, __func__, write_length, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
444
445

		/* Write next page */
446
447
448
449
450
		be_start_address = cpu_to_be16(start_address);
		status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
				(__u16)address_type,
				(__force __u16)be_start_address,
				buffer, write_length);
Linus Torvalds's avatar
Linus Torvalds committed
451
		if (status) {
452
			dev_err(dev, "%s - ERROR %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
453
454
			return status;
		}
455

Linus Torvalds's avatar
Linus Torvalds committed
456
457
458
459
460
461
462
463
		length		-= write_length;
		start_address	+= write_length;
		buffer		+= write_length;
	}
	return status;
}

/* Examine the UMP DMA registers and LSR
464
 *
Linus Torvalds's avatar
Linus Torvalds committed
465
466
467
468
 * Check the MSBit of the X and Y DMA byte count registers.
 * A zero in this bit indicates that the TX DMA buffers are empty
 * then check the TX Empty bit in the UART.
 */
469
static int tx_active(struct edgeport_port *port)
Linus Torvalds's avatar
Linus Torvalds committed
470
471
472
473
474
475
{
	int status;
	struct out_endpoint_desc_block *oedb;
	__u8 *lsr;
	int bytes_left = 0;

476
	oedb = kmalloc(sizeof(*oedb), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
477
	if (!oedb) {
478
		dev_err(&port->port->dev, "%s - out of memory\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
479
480
481
		return -ENOMEM;
	}

482
	lsr = kmalloc(1, GFP_KERNEL);	/* Sigh, that's right, just one byte,
Linus Torvalds's avatar
Linus Torvalds committed
483
484
485
486
487
488
489
					   as not all platforms can do DMA
					   from stack */
	if (!lsr) {
		kfree(oedb);
		return -ENOMEM;
	}
	/* Read the DMA Count Registers */
490
491
	status = read_ram(port->port->serial->dev, port->dma_address,
						sizeof(*oedb), (void *)oedb);
Linus Torvalds's avatar
Linus Torvalds committed
492
493
494
	if (status)
		goto exit_is_tx_active;

495
	dev_dbg(&port->port->dev, "%s - XByteCount    0x%X\n", __func__, oedb->XByteCount);
Linus Torvalds's avatar
Linus Torvalds committed
496
497

	/* and the LSR */
498
499
	status = read_ram(port->port->serial->dev,
			port->uart_base + UMPMEM_OFFS_UART_LSR, 1, lsr);
Linus Torvalds's avatar
Linus Torvalds committed
500
501
502

	if (status)
		goto exit_is_tx_active;
503
	dev_dbg(&port->port->dev, "%s - LSR = 0x%X\n", __func__, *lsr);
504

Linus Torvalds's avatar
Linus Torvalds committed
505
	/* If either buffer has data or we are transmitting then return TRUE */
506
	if ((oedb->XByteCount & 0x80) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
507
508
		bytes_left += 64;

509
	if ((*lsr & UMP_UART_LSR_TX_MASK) == 0)
Linus Torvalds's avatar
Linus Torvalds committed
510
511
512
513
		bytes_left += 1;

	/* We return Not Active if we get any kind of error */
exit_is_tx_active:
514
	dev_dbg(&port->port->dev, "%s - return %d\n", __func__, bytes_left);
Linus Torvalds's avatar
Linus Torvalds committed
515
516
517
518
519
520

	kfree(lsr);
	kfree(oedb);
	return bytes_left;
}

521
static int choose_config(struct usb_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
522
{
523
524
525
526
527
528
	/*
	 * There may be multiple configurations on this device, in which case
	 * we would need to read and parse all of them to find out which one
	 * we want. However, we just support one config at this point,
	 * configuration # 1, which is Config Descriptor 0.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
529

530
531
532
533
	dev_dbg(&dev->dev, "%s - Number of Interfaces = %d\n",
		__func__, dev->config->desc.bNumInterfaces);
	dev_dbg(&dev->dev, "%s - MAX Power            = %d\n",
		__func__, dev->config->desc.bMaxPower * 2);
Linus Torvalds's avatar
Linus Torvalds committed
534
535

	if (dev->config->desc.bNumInterfaces != 1) {
536
		dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
537
538
539
540
541
542
		return -ENODEV;
	}

	return 0;
}

543
544
static int read_rom(struct edgeport_serial *serial,
				int start_address, int length, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
545
546
547
548
{
	int status;

	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
549
		status = read_download_mem(serial->serial->dev,
Linus Torvalds's avatar
Linus Torvalds committed
550
551
552
553
554
					       start_address,
					       length,
					       serial->TI_I2C_Type,
					       buffer);
	} else {
555
556
		status = read_boot_mem(serial, start_address, length,
								buffer);
Linus Torvalds's avatar
Linus Torvalds committed
557
558
559
560
	}
	return status;
}

561
562
static int write_rom(struct edgeport_serial *serial, int start_address,
						int length, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
563
564
{
	if (serial->product_info.TiMode == TI_MODE_BOOT)
565
566
		return write_boot_mem(serial, start_address, length,
								buffer);
Linus Torvalds's avatar
Linus Torvalds committed
567
568

	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD)
569
570
		return write_i2c_mem(serial, start_address, length,
						serial->TI_I2C_Type, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
571
572
573
574
575
576
	return -EINVAL;
}



/* Read a descriptor header from I2C based on type */
577
578
static int get_descriptor_addr(struct edgeport_serial *serial,
				int desc_type, struct ti_i2c_desc *rom_desc)
Linus Torvalds's avatar
Linus Torvalds committed
579
580
581
582
583
584
585
{
	int start_address;
	int status;

	/* Search for requested descriptor in I2C */
	start_address = 2;
	do {
586
		status = read_rom(serial,
Linus Torvalds's avatar
Linus Torvalds committed
587
588
				   start_address,
				   sizeof(struct ti_i2c_desc),
589
				   (__u8 *)rom_desc);
Linus Torvalds's avatar
Linus Torvalds committed
590
591
592
593
594
595
		if (status)
			return 0;

		if (rom_desc->Type == desc_type)
			return start_address;

596
597
		start_address = start_address + sizeof(struct ti_i2c_desc)
							+ rom_desc->Size;
Linus Torvalds's avatar
Linus Torvalds committed
598
599

	} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
600

Linus Torvalds's avatar
Linus Torvalds committed
601
602
603
604
	return 0;
}

/* Validate descriptor checksum */
605
static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
606
607
608
609
{
	__u16 i;
	__u8 cs = 0;

610
	for (i = 0; i < rom_desc->Size; i++)
Linus Torvalds's avatar
Linus Torvalds committed
611
		cs = (__u8)(cs + buffer[i]);
612

Linus Torvalds's avatar
Linus Torvalds committed
613
	if (cs != rom_desc->CheckSum) {
614
		pr_debug("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
Linus Torvalds's avatar
Linus Torvalds committed
615
616
617
618
619
620
		return -EINVAL;
	}
	return 0;
}

/* Make sure that the I2C image is good */
621
static int check_i2c_image(struct edgeport_serial *serial)
Linus Torvalds's avatar
Linus Torvalds committed
622
623
624
625
626
627
628
629
{
	struct device *dev = &serial->serial->dev->dev;
	int status = 0;
	struct ti_i2c_desc *rom_desc;
	int start_address = 2;
	__u8 *buffer;
	__u16 ttype;

630
	rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
631
	if (!rom_desc) {
632
		dev_err(dev, "%s - out of memory\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
633
634
		return -ENOMEM;
	}
635
	buffer = kmalloc(TI_MAX_I2C_SIZE, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
636
	if (!buffer) {
637
638
639
		dev_err(dev, "%s - out of memory when allocating buffer\n",
								__func__);
		kfree(rom_desc);
Linus Torvalds's avatar
Linus Torvalds committed
640
641
642
		return -ENOMEM;
	}

643
644
	/* Read the first byte (Signature0) must be 0x52 or 0x10 */
	status = read_rom(serial, 0, 1, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
645
	if (status)
646
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
647
648

	if (*buffer != UMP5152 && *buffer != UMP3410) {
649
		dev_err(dev, "%s - invalid buffer signature\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
650
		status = -ENODEV;
651
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
652
653
654
	}

	do {
655
656
		/* Validate the I2C */
		status = read_rom(serial,
Linus Torvalds's avatar
Linus Torvalds committed
657
658
659
660
661
662
				start_address,
				sizeof(struct ti_i2c_desc),
				(__u8 *)rom_desc);
		if (status)
			break;

663
664
		if ((start_address + sizeof(struct ti_i2c_desc) +
					rom_desc->Size) > TI_MAX_I2C_SIZE) {
Linus Torvalds's avatar
Linus Torvalds committed
665
			status = -ENODEV;
666
			dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
667
668
669
			break;
		}

670
		dev_dbg(dev, "%s Type = 0x%x\n", __func__, rom_desc->Type);
Linus Torvalds's avatar
Linus Torvalds committed
671

672
		/* Skip type 2 record */
Linus Torvalds's avatar
Linus Torvalds committed
673
		ttype = rom_desc->Type & 0x0f;
674
675
676
677
678
679
		if (ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
			&& ttype != I2C_DESC_TYPE_FIRMWARE_AUTO) {
			/* Read the descriptor data */
			status = read_rom(serial, start_address +
						sizeof(struct ti_i2c_desc),
						rom_desc->Size, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
680
681
682
			if (status)
				break;

683
			status = valid_csum(rom_desc, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
684
685
686
			if (status)
				break;
		}
687
688
		start_address = start_address + sizeof(struct ti_i2c_desc) +
								rom_desc->Size;
Linus Torvalds's avatar
Linus Torvalds committed
689

690
691
	} while ((rom_desc->Type != I2C_DESC_TYPE_ION) &&
				(start_address < TI_MAX_I2C_SIZE));
Linus Torvalds's avatar
Linus Torvalds committed
692

693
694
	if ((rom_desc->Type != I2C_DESC_TYPE_ION) ||
				(start_address > TI_MAX_I2C_SIZE))
Linus Torvalds's avatar
Linus Torvalds committed
695
696
		status = -ENODEV;

697
698
699
out:
	kfree(buffer);
	kfree(rom_desc);
Linus Torvalds's avatar
Linus Torvalds committed
700
701
702
	return status;
}

703
static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
Linus Torvalds's avatar
Linus Torvalds committed
704
705
706
707
708
{
	int status;
	int start_address;
	struct ti_i2c_desc *rom_desc;
	struct edge_ti_manuf_descriptor *desc;
709
	struct device *dev = &serial->serial->dev->dev;
Linus Torvalds's avatar
Linus Torvalds committed
710

711
	rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
712
	if (!rom_desc) {
713
		dev_err(dev, "%s - out of memory\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
714
715
		return -ENOMEM;
	}
716
717
	start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
								rom_desc);
Linus Torvalds's avatar
Linus Torvalds committed
718
719

	if (!start_address) {
720
		dev_dbg(dev, "%s - Edge Descriptor not found in I2C\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
721
722
723
724
		status = -ENODEV;
		goto exit;
	}

725
726
727
	/* Read the descriptor data */
	status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
						rom_desc->Size, buffer);
Linus Torvalds's avatar
Linus Torvalds committed
728
729
	if (status)
		goto exit;
730
731
732

	status = valid_csum(rom_desc, buffer);

Linus Torvalds's avatar
Linus Torvalds committed
733
	desc = (struct edge_ti_manuf_descriptor *)buffer;
734
735
736
737
738
739
	dev_dbg(dev, "%s - IonConfig      0x%x\n", __func__, desc->IonConfig);
	dev_dbg(dev, "%s - Version          %d\n", __func__, desc->Version);
	dev_dbg(dev, "%s - Cpu/Board      0x%x\n", __func__, desc->CpuRev_BoardRev);
	dev_dbg(dev, "%s - NumPorts         %d\n", __func__, desc->NumPorts);
	dev_dbg(dev, "%s - NumVirtualPorts  %d\n", __func__, desc->NumVirtualPorts);
	dev_dbg(dev, "%s - TotalPorts       %d\n", __func__, desc->TotalPorts);
Linus Torvalds's avatar
Linus Torvalds committed
740
741

exit:
742
	kfree(rom_desc);
Linus Torvalds's avatar
Linus Torvalds committed
743
744
745
746
	return status;
}

/* Build firmware header used for firmware update */
747
static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
748
749
750
751
{
	__u8 *buffer;
	int buffer_size;
	int i;
752
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
753
754
755
756
	__u8 cs = 0;
	struct ti_i2c_desc *i2c_header;
	struct ti_i2c_image_header *img_header;
	struct ti_i2c_firmware_rec *firmware_rec;
757
758
	const struct firmware *fw;
	const char *fw_name = "edgeport/down3.bin";
Linus Torvalds's avatar
Linus Torvalds committed
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
	/* In order to update the I2C firmware we must change the type 2 record
	 * to type 0xF2.  This will force the UMP to come up in Boot Mode.
	 * Then while in boot mode, the driver will download the latest
	 * firmware (padded to 15.5k) into the UMP ram.  And finally when the
	 * device comes back up in download mode the driver will cause the new
	 * firmware to be copied from the UMP Ram to I2C and the firmware will
	 * update the record type from 0xf2 to 0x02.
	 */

	/* Allocate a 15.5k buffer + 2 bytes for version number
	 * (Firmware Record) */
	buffer_size = (((1024 * 16) - 512 ) +
			sizeof(struct ti_i2c_firmware_rec));

	buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
775
	if (!buffer) {
776
		dev_err(dev, "%s - out of memory\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
777
778
		return -ENOMEM;
	}
779

Linus Torvalds's avatar
Linus Torvalds committed
780
	// Set entire image of 0xffs
781
	memset(buffer, 0xff, buffer_size);
Linus Torvalds's avatar
Linus Torvalds committed
782

783
784
	err = request_firmware(&fw, fw_name, dev);
	if (err) {
785
786
		dev_err(dev, "Failed to load image \"%s\" err %d\n",
			fw_name, err);
787
788
789
790
791
792
793
794
795
		kfree(buffer);
		return err;
	}

	/* Save Download Version Number */
	OperationalMajorVersion = fw->data[0];
	OperationalMinorVersion = fw->data[1];
	OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8);

796
	/* Copy version number into firmware record */
Linus Torvalds's avatar
Linus Torvalds committed
797
798
	firmware_rec = (struct ti_i2c_firmware_rec *)buffer;

799
800
	firmware_rec->Ver_Major	= OperationalMajorVersion;
	firmware_rec->Ver_Minor	= OperationalMinorVersion;
Linus Torvalds's avatar
Linus Torvalds committed
801

802
	/* Pointer to fw_down memory image */
803
	img_header = (struct ti_i2c_image_header *)&fw->data[4];
Linus Torvalds's avatar
Linus Torvalds committed
804

805
	memcpy(buffer + sizeof(struct ti_i2c_firmware_rec),
806
		&fw->data[4 + sizeof(struct ti_i2c_image_header)],
Linus Torvalds's avatar
Linus Torvalds committed
807
808
		le16_to_cpu(img_header->Length));

809
810
	release_firmware(fw);

Linus Torvalds's avatar
Linus Torvalds committed
811
812
813
814
	for (i=0; i < buffer_size; i++) {
		cs = (__u8)(cs + buffer[i]);
	}

815
	kfree(buffer);
Linus Torvalds's avatar
Linus Torvalds committed
816

817
	/* Build new header */
Linus Torvalds's avatar
Linus Torvalds committed
818
819
	i2c_header =  (struct ti_i2c_desc *)header;
	firmware_rec =  (struct ti_i2c_firmware_rec*)i2c_header->Data;
820

Linus Torvalds's avatar
Linus Torvalds committed
821
822
823
	i2c_header->Type	= I2C_DESC_TYPE_FIRMWARE_BLANK;
	i2c_header->Size	= (__u16)buffer_size;
	i2c_header->CheckSum	= cs;
824
825
	firmware_rec->Ver_Major	= OperationalMajorVersion;
	firmware_rec->Ver_Minor	= OperationalMinorVersion;
Linus Torvalds's avatar
Linus Torvalds committed
826
827
828
829
830

	return 0;
}

/* Try to figure out what type of I2c we have */
831
static int i2c_type_bootmode(struct edgeport_serial *serial)
Linus Torvalds's avatar
Linus Torvalds committed
832
{
833
	struct device *dev = &serial->serial->dev->dev;
Linus Torvalds's avatar
Linus Torvalds committed
834
	int status;
835
836
837
838
	u8 *data;

	data = kmalloc(1, GFP_KERNEL);
	if (!data) {
839
		dev_err(dev, "%s - out of memory\n", __func__);
840
841
		return -ENOMEM;
	}
842
843
844

	/* Try to read type 2 */
	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
845
				DTK_ADDR_SPACE_I2C_TYPE_II, 0, data, 0x01);
Linus Torvalds's avatar
Linus Torvalds committed
846
	if (status)
847
		dev_dbg(dev, "%s - read 2 status error = %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
848
	else
849
		dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data);
850
	if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
851
		dev_dbg(dev, "%s - ROM_TYPE_II\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
852
		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
853
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
854
855
	}

856
857
	/* Try to read type 3 */
	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
858
				DTK_ADDR_SPACE_I2C_TYPE_III, 0,	data, 0x01);
Linus Torvalds's avatar
Linus Torvalds committed
859
	if (status)
860
		dev_dbg(dev, "%s - read 3 status error = %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
861
	else
862
		dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data);
863
	if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
864
		dev_dbg(dev, "%s - ROM_TYPE_III\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
865
		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
866
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
867
868
	}

869
	dev_dbg(dev, "%s - Unknown\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
870
	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
871
872
873
874
	status = -ENODEV;
out:
	kfree(data);
	return status;
Linus Torvalds's avatar
Linus Torvalds committed
875
876
}

877
878
static int bulk_xfer(struct usb_serial *serial, void *buffer,
						int length, int *num_sent)
Linus Torvalds's avatar
Linus Torvalds committed
879
880
881
{
	int status;

882
883
884
885
	status = usb_bulk_msg(serial->dev,
			usb_sndbulkpipe(serial->dev,
				serial->port[0]->bulk_out_endpointAddress),
			buffer, length, num_sent, 1000);
Linus Torvalds's avatar
Linus Torvalds committed
886
887
888
889
	return status;
}

/* Download given firmware image to the device (IN BOOT MODE) */
890
891
static int download_code(struct edgeport_serial *serial, __u8 *image,
							int image_length)
Linus Torvalds's avatar
Linus Torvalds committed
892
893
894
895
896
897
{
	int status = 0;
	int pos;
	int transfer;
	int done;

898
	/* Transfer firmware image */
Linus Torvalds's avatar
Linus Torvalds committed
899
	for (pos = 0; pos < image_length; ) {
900
		/* Read the next buffer from file */
Linus Torvalds's avatar
Linus Torvalds committed
901
902
903
904
		transfer = image_length - pos;
		if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE)
			transfer = EDGE_FW_BULK_MAX_PACKET_SIZE;

905
906
907
		/* Transfer data */
		status = bulk_xfer(serial->serial, &image[pos],
							transfer, &done);
Linus Torvalds's avatar
Linus Torvalds committed
908
909
		if (status)
			break;
910
		/* Advance buffer pointer */
Linus Torvalds's avatar
Linus Torvalds committed
911
912
913
914
915
916
		pos += done;
	}

	return status;
}

917
918
/* FIXME!!! */
static int config_boot_dev(struct usb_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
919
920
921
922
{
	return 0;
}

923
924
925
926
927
static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc)
{
	return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
}

Linus Torvalds's avatar
Linus Torvalds committed
928
929
/**
 * DownloadTIFirmware - Download run-time operating firmware to the TI5052
930
 *
Linus Torvalds's avatar
Linus Torvalds committed
931
932
933
 * This routine downloads the main operating code into the TI5052, using the
 * boot code already burned into E2PROM or ROM.
 */
934
static int download_fw(struct edgeport_serial *serial)
Linus Torvalds's avatar
Linus Torvalds committed
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
{
	struct device *dev = &serial->serial->dev->dev;
	int status = 0;
	int start_address;
	struct edge_ti_manuf_descriptor *ti_manuf_desc;
	struct usb_interface_descriptor *interface;
	int download_cur_ver;
	int download_new_ver;

	/* This routine is entered by both the BOOT mode and the Download mode
	 * We can determine which code is running by the reading the config
	 * descriptor and if we have only one bulk pipe it is in boot mode
	 */
	serial->product_info.hardware_type = HARDWARE_TYPE_TIUMP;

	/* Default to type 2 i2c */
	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;

953
	status = choose_config(serial->serial->dev);
Linus Torvalds's avatar
Linus Torvalds committed
954
955
956
957
958
	if (status)
		return status;

	interface = &serial->serial->interface->cur_altsetting->desc;
	if (!interface) {
959
		dev_err(dev, "%s - no interface set, error!\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
960
961
962
		return -ENODEV;
	}

963
964
965
966
967
	/*
	 * Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
	 * if we have more than one endpoint we are definitely in download
	 * mode
	 */
Linus Torvalds's avatar
Linus Torvalds committed
968
969
970
	if (interface->bNumEndpoints > 1)
		serial->product_info.TiMode = TI_MODE_DOWNLOAD;
	else
971
		/* Otherwise we will remain in configuring mode */
Linus Torvalds's avatar
Linus Torvalds committed
972
973
974
975
976
977
978
979
		serial->product_info.TiMode = TI_MODE_CONFIGURING;

	/********************************************************************/
	/* Download Mode */
	/********************************************************************/
	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
		struct ti_i2c_desc *rom_desc;

980
		dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
981

982
		status = check_i2c_image(serial);
Linus Torvalds's avatar
Linus Torvalds committed
983
		if (status) {
984
			dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
985
986
			return status;
		}
987

Linus Torvalds's avatar
Linus Torvalds committed
988
989
990
		/* Validate Hardware version number
		 * Read Manufacturing Descriptor from TI Based Edgeport
		 */
991
		ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
992
		if (!ti_manuf_desc) {
993
			dev_err(dev, "%s - out of memory.\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
994
995
			return -ENOMEM;
		}
996
		status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
997
		if (status) {
998
			kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
999
1000
1001
			return status;
		}

1002
1003
		/* Check version number of ION descriptor */
		if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
1004
			dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
1005
1006
1007
1008
				__func__, ti_cpu_rev(ti_manuf_desc));
			kfree(ti_manuf_desc);
			return -EINVAL;
  		}
Linus Torvalds's avatar
Linus Torvalds committed
1009

1010
		rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1011
		if (!rom_desc) {
1012
1013
			dev_err(dev, "%s - out of memory.\n", __func__);
			kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1014
1015
1016
			return -ENOMEM;
		}

1017
1018
1019
1020
		/* Search for type 2 record (firmware record) */
		start_address = get_descriptor_addr(serial,
				I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
		if (start_address != 0) {
Linus Torvalds's avatar
Linus Torvalds committed
1021
			struct ti_i2c_firmware_rec *firmware_version;
1022
			u8 *record;
Linus Torvalds's avatar
Linus Torvalds committed
1023

1024
			dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
1025

1026
1027
			firmware_version = kmalloc(sizeof(*firmware_version),
								GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1028
			if (!firmware_version) {
1029
1030
1031
				dev_err(dev, "%s - out of memory.\n", __func__);
				kfree(rom_desc);
				kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1032
1033
1034
				return -ENOMEM;
			}

1035
1036
1037
1038
1039
			/* Validate version number
			 * Read the descriptor data
			 */
			status = read_rom(serial, start_address +
					sizeof(struct ti_i2c_desc),
Linus Torvalds's avatar
Linus Torvalds committed
1040
1041
1042
					sizeof(struct ti_i2c_firmware_rec),
					(__u8 *)firmware_version);
			if (status) {
1043
1044
1045
				kfree(firmware_version);
				kfree(rom_desc);
				kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1046
1047
1048
				return status;
			}

1049
1050
1051
			/* Check version number of download with current
			   version in I2c */
			download_cur_ver = (firmware_version->Ver_Major << 8) +
Linus Torvalds's avatar
Linus Torvalds committed
1052
					   (firmware_version->Ver_Minor);
1053
1054
			download_new_ver = (OperationalMajorVersion << 8) +
					   (OperationalMinorVersion);
Linus Torvalds's avatar
Linus Torvalds committed
1055

1056
1057
1058
1059
1060
			dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
				__func__, firmware_version->Ver_Major,
				firmware_version->Ver_Minor,
				OperationalMajorVersion,
				OperationalMinorVersion);
Linus Torvalds's avatar
Linus Torvalds committed
1061

1062
1063
			/* Check if we have an old version in the I2C and
			   update if necessary */
1064
			if (download_cur_ver < download_new_ver) {
1065
1066
1067
1068
1069
1070
				dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
					__func__,
					firmware_version->Ver_Major,
					firmware_version->Ver_Minor,
					OperationalMajorVersion,
					OperationalMinorVersion);
1071

1072
1073
1074
1075
1076
1077
1078
1079
1080
				record = kmalloc(1, GFP_KERNEL);
				if (!record) {
					dev_err(dev, "%s - out of memory.\n",
							__func__);
					kfree(firmware_version);
					kfree(rom_desc);
					kfree(ti_manuf_desc);
					return -ENOMEM;
				}
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
				/* In order to update the I2C firmware we must
				 * change the type 2 record to type 0xF2. This
				 * will force the UMP to come up in Boot Mode.
				 * Then while in boot mode, the driver will
				 * download the latest firmware (padded to
				 * 15.5k) into the UMP ram. Finally when the
				 * device comes back up in download mode the
				 * driver will cause the new firmware to be
				 * copied from the UMP Ram to I2C and the
				 * firmware will update the record type from
				 * 0xf2 to 0x02.
				 */
1093
				*record = I2C_DESC_TYPE_FIRMWARE_BLANK;
Linus Torvalds's avatar
Linus Torvalds committed
1094

1095
1096
1097
				/* Change the I2C Firmware record type to
				   0xf2 to trigger an update */
				status = write_rom(serial, start_address,
1098
						sizeof(*record), record);
Linus Torvalds's avatar
Linus Torvalds committed
1099
				if (status) {
1100
					kfree(record);
1101
1102
1103
					kfree(firmware_version);
					kfree(rom_desc);
					kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1104
1105
1106
					return status;
				}

1107
1108
1109
1110
1111
				/* verify the write -- must do this in order
				 * for write to complete before we do the
				 * hardware reset
				 */
				status = read_rom(serial,
Linus Torvalds's avatar
Linus Torvalds committed
1112
							start_address,
1113
1114
							sizeof(*record),
							record);
Linus Torvalds's avatar
Linus Torvalds committed
1115
				if (status) {
1116
					kfree(record);
1117
1118
1119
					kfree(firmware_version);
					kfree(rom_desc);
					kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1120
1121
1122
					return status;
				}

1123
				if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
1124
					dev_err(dev, "%s - error resetting device\n", __func__);
1125
					kfree(record);
1126
1127
1128
					kfree(firmware_version);
					kfree(rom_desc);
					kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1129
1130
1131
					return -ENODEV;
				}

1132
				dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
Linus Torvalds's avatar
Linus Torvalds committed
1133

1134
1135
1136
1137
				/* Reset UMP -- Back to BOOT MODE */
				status = ti_vsend_sync(serial->serial->dev,
						UMPC_HARDWARE_RESET,
						0, 0, NULL, 0);
Linus Torvalds's avatar
Linus Torvalds committed
1138

1139
				dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
1140
1141

				/* return an error on purpose. */
1142
				kfree(record);
1143
1144
1145
				kfree(firmware_version);
				kfree(rom_desc);
				kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1146
1147
				return -ENODEV;
			}
1148
			kfree(firmware_version);
Linus Torvalds's avatar
Linus Torvalds committed
1149
		}
1150
1151
1152
1153
		/* Search for type 0xF2 record (firmware blank record) */
		else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
#define HEADER_SIZE	(sizeof(struct ti_i2c_desc) + \
					sizeof(struct ti_i2c_firmware_rec))
Linus Torvalds's avatar
Linus Torvalds committed
1154
1155
1156
			__u8 *header;
			__u8 *vheader;

1157
			header = kmalloc(HEADER_SIZE, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1158
			if (!header) {
1159
1160
1161
				dev_err(dev, "%s - out of memory.\n", __func__);
				kfree(rom_desc);
				kfree(ti_manuf_desc);
Linus Torvalds's avatar
Linus Torvalds committed
1162
1163
				return -ENOMEM;
			}
1164
1165

			vheader = kmalloc(HEADER_SIZE, GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed