summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h
blob: 6fbc61488f321566de5fa21ff10eafd2a145f3dd (plain)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
/* -*- linux-c -*-
 * arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h
 *
 * Copyright (C) 2008 by Digi International Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 *  !Revision:   $Revision: 1.25 $
 *  !Author:     Silvano Najera, Luis Galdos
 *  !Descr:      
 *  !References:
 */


#ifndef _NS921X_FIM_CORE_H
#define _NS921X_FIM_CORE_H


#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
#include <linux/kfifo.h>
#include <linux/list.h>
#include <linux/interrupt.h>

#include <mach/dma-ns921x.h>


#define FIM_MAX_FIRMWARE_NAME			32


/* For DMA handling... */
#define	FIM_DMA_NCIP				(0x1)
#define FIM_DMA_NRIP				(0x2)
#define FIM_DMA_ECIP				(0x4)
#define FIM_DMA_CAIP				(0x8)
#define FIM_DMA_CANCELLED			FIM_DMA_CAIP
#define FIM_DMA_FLUSHED				(0x10)
#define FIM_DMA_SUCCESS		         	(FIM_DMA_NCIP | FIM_DMA_NRIP)


#define FIM_MAX_PIC_INDEX			(1)
#define FIM_MIN_PIC_INDEX			(0)
#define FIM_NR_PICS				(FIM_MAX_PIC_INDEX-FIM_MIN_PIC_INDEX+1)


/* @XXX: Place this macros in another place? */
#define NS92XX_FIM_GEN_CTRL_STOP_PIC		~NS92XX_FIM_GEN_CTRL_PROGMEM
#define NS92XX_FIM_GEN_CTRL_START_PIC		NS92XX_FIM_GEN_CTRL_PROGMEM



/* Please note that the maximal DMA-buffer size is 64kB */
/* @FIXME: Check that the maximal size of the descriptors is littler than one page */
#define PIC_DMA_RX_BUFFERS			(10)
#define PIC_DMA_TX_BUFFERS			(10)
#define PIC_DMA_BUFFER_SIZE			(1 * PAGE_SIZE)

/*
 * Internal structure for handling with the DMA-buffer descriptors
 * p_desc : Physical descriptors address
 * v_desc : Virtual access address for the descriptors
 * v_buf  : Virtual address of the memory buffers
 * length : Configured length of this buffer
 * tasked : Used for locking the descriptor
 */
struct pic_dma_desc_t {
	dma_addr_t src;
	size_t length;
	atomic_t tasked;
	void *private;
	int total_length;
};


/*
 * Structure used by the FIM-API to configure the DMA-buffer and buffer-descriptors.
 * rxnr : Number of RX-DMA-buffers
 * rxsz : Size of each DMA-buffer (in Bytes)
 * txnr : Number of TX-DMA-buffers
 * txsz : Size for each TX-buffer (in Bytes)
 */
struct fim_dma_cfg_t {
	int rxnr;
	int rxsz;
	int txnr;
	int txsz;
};


/*
 * This structure should be used for transferring data with the API
 * length  : Date length to transfer
 * data    : Data buffer
 * private : The API will not touch this pointer
 * sent    : The external driver can use it for waking up sleeping processes
 */
struct fim_buffer_t {
	int length;
	unsigned char *data;
	void *private;
	int sent;
};


/* @TODO: We need perhaps another PIC-structure for the U-Boot */
struct pic_t {
	int irq;
	struct device *dev;
	struct fim_driver *driver;
	void __iomem *reg_addr;
	void __iomem *instr_addr;
	void __iomem *hwa_addr;
	void __iomem *iohub_addr;
	spinlock_t lock;
	int index;
	atomic_t irq_enabled;
	atomic_t requested;
	
	/* RX-DMA structures */
	struct iohub_dma_fifo_t rx_fifo;
	spinlock_t rx_lock;
	struct fim_dma_cfg_t dma_cfg;
	
	/* Variables for the DMA-memory buffers */
	dma_addr_t dma_phys;
	void __iomem *dma_virt;
	size_t dma_size;
	
	/* Data for the handling of the TX-DMA buffers */
	spinlock_t tx_lock;
	struct pic_dma_desc_t *tx_desc;
	struct iohub_dma_fifo_t tx_fifo;
	atomic_t tx_tasked;
	atomic_t tx_aborted;
	struct tasklet_struct rx_tasklet;
	
	/* Info data for the sysfs */
	char fw_name[FIM_MAX_FIRMWARE_NAME];
	int fw_length;

	/* Functions for a low level access to the PICs */
	int (* is_running)(struct pic_t *);
	int (* start_at_zero)(struct pic_t *);
	int (* stop_and_reset)(struct pic_t *);
	int (* download_firmware)(struct pic_t *, const unsigned char *);
	int (* get_ctrl_reg)(struct pic_t *, int , unsigned int *);
	void (* set_ctrl_reg)(struct pic_t *, int , unsigned int );
	int (* send_interrupt)(struct pic_t *, u32 );
	void (* ack_interrupt)(struct pic_t * , int );
};


/*
 * Structure with the GPIOs to use for the driver to be initialized
 * nr     : GPIO number
 * name   : Name to use for the GPIO
 * picval : Value to pass to the PIC-firmware
 * func   : Function to be configured for the GPIO
 */
struct fim_gpio_t {
	int nr;
	char *name;
	unsigned char picval;  /* Value to pass to firmware */
	unsigned int func;
};

#define FIM_LAST_GPIO			-2
#define FIM_GPIO_DONT_USE		-1

/*
 * Internal structure for allocating a FIM driver
 * picnr       : Number of the PIC to use for this driver
 * fw_code     : Firmware code that should be used as firmware
 * fw_name     : Name of the firmware to get over the firmware layer
 * driver      : Driver structure
 * dev         : Device that should be set by the FIM-API
 * driver_data : The API will not touch this member
 * fim_isr     : Called when the PIC generates an interrupt
 * dma_tx_isr  : TX-callback function. Called in interrupt context
 * dma_rx_isr  : RX-callback. Called inside the interrupt context
 * dma_cfg     : If NULL then the API will use the default config
 * verbose     : Used by the FIM-core for printing sys messages (debug, infos, etc.)
 */
struct fim_driver {
	int picnr;
	const unsigned char *fw_code;
	const char *fw_name;
	struct device_driver driver;
	struct device *dev;
	void (*fim_isr)(struct fim_driver *, int, unsigned char, unsigned int);
	void (*dma_tx_isr)(struct fim_driver *, int, struct fim_buffer_t *);
	void (*dma_rx_isr)(struct fim_driver *, int, struct fim_buffer_t *);
	void (*dma_error_isr)(struct fim_driver *, ulong rx_err, ulong tx_err);
	void *driver_data;
	struct fim_dma_cfg_t *dma_cfg;
	int verbose;
};



/*
 * Structure for the FIM-devices with UART-support
 * If a GPIO should not be used, then it's required to disable it by using the
 * above macro 'FIM_GPIO_DONT_USE'
 *
 * fim_nr  : Number of the FIM to use for the device
 * gpio_nr : GPIO to use for the interface line
 * fim_cfg : Currently not used 
 */
struct fim_serial_platform_data {
	int fim_nr;
	
	int rx_gpio_nr;
	unsigned int rx_gpio_func;
	unsigned int rx_fim_cfg;

	int tx_gpio_nr;
	unsigned int tx_gpio_func;
	unsigned int tx_fim_cfg;

	int cts_gpio_nr;
	unsigned int cts_gpio_func;
	unsigned int cts_fim_cfg;

	int rts_gpio_nr;
	unsigned int rts_gpio_func;
	unsigned int rts_fim_cfg;
};


/* Macro for the configuration of the GPIOs for the FIM-serial driver */
#define NS921X_FIM_SERIAL_GPIOS(rx, tx, rts, cts, func)	\
		.rx_gpio_nr = rx, \
		.rx_gpio_func = func, \
		.tx_gpio_nr = tx, \
		.tx_gpio_func = func, \
		.rts_gpio_nr = rts, \
		.rts_gpio_func = func, \
		.cts_gpio_nr = cts, \
		.cts_gpio_func = func


/*
 * Structure for the FIM-devices with SDIO-support
 * If a GPIO should not be used, then it's required to disable it by using the
 * macro 'FIM_GPIO_DONT_USE'
 *
 * fim_nr    : Number of the FIM to use for the device
 * host_caps : Specific host capabilities (see: linux/mmc/host.h)
 */
struct fim_sdio_platform_data {
	int fim_nr;
	unsigned int host_caps;         /* Host capabilities */
	
	int d0_gpio_nr;			/* data 0 */
	unsigned int d0_gpio_func;
	int d1_gpio_nr;			/* data 1 */
	unsigned int d1_gpio_func;
	int d2_gpio_nr;			/* data 2 */
	unsigned int d2_gpio_func;
	int d3_gpio_nr;			/* data 3 */
	unsigned int d3_gpio_func;
	int wp_gpio_nr;			/* write protect */
	unsigned int wp_gpio_func;
	int cd_gpio_nr;			/* card detect */
	unsigned int cd_gpio_func;
	int clk_gpio_nr;		/* clock */
	unsigned int clk_gpio_func;
	int cmd_gpio_nr;		/* command */
	unsigned int cmd_gpio_func;
};


/*
 * Use the below macro if all the GPIOs can be configured with the same function
 * number (this is the normal case)
 */
#define NS921X_FIM_SDIO_GPIOS(d0, d1, d2, d3, wp, cd, clk, cmd, func)	\
		.d0_gpio_nr = d0, \
		.d0_gpio_func = func, \
		.d1_gpio_nr = d1, \
		.d1_gpio_func = func, \
		.d2_gpio_nr = d2, \
		.d2_gpio_func = func, \
		.d3_gpio_nr = d3, \
		.d3_gpio_func = func, \
		.wp_gpio_nr = wp, \
		.wp_gpio_func = func, \
		.cd_gpio_nr = cd, \
		.cd_gpio_func = func, \
		.clk_gpio_nr = clk, \
		.clk_gpio_func = func, \
		.cmd_gpio_nr = cmd, \
		.cmd_gpio_func = func

/* 
 * The new FIM board doesn't connect all the lines to the FIM. The CMD
 * and CD are not connected to the FIM.
 */
#define NS921X_FIM_SDIO_GPIOS_FIM(d0, d1, d2, d3, clk, cmd, func)	\
		.d0_gpio_nr = d0, \
		.d0_gpio_func = func, \
		.d1_gpio_nr = d1, \
		.d1_gpio_func = func, \
		.d2_gpio_nr = d2, \
		.d2_gpio_func = func, \
		.d3_gpio_nr = d3, \
		.d3_gpio_func = func, \
		.clk_gpio_nr = clk, \
		.clk_gpio_func = func, \
		.cmd_gpio_nr = cmd, \
		.cmd_gpio_func = func

/*
 * Structure for the FIM-devices with CAN-support
 * If a GPIO should not be used, then it's required to disable it by using the
 * above macro 'FIM_GPIO_DONT_USE'
 *
 * fim_nr  : Number of the FIM to use for the device
 * gpio_nr : GPIO to use for the interface line
 */
struct fim_can_platform_data {

	int fim_nr;
	int fim_can_bitrate;

	int rx_gpio_nr;
	unsigned int rx_gpio_func;
	int tx_gpio_nr;
	unsigned int tx_gpio_func;
};

/* Macro for the configuration of the GPIOs for the FIM CAN driver */
#define NS921X_FIM_CAN_GPIOS(rx, tx, func)	\
		.rx_gpio_nr = rx, \
		.rx_gpio_func = func, \
		.tx_gpio_nr = tx, \
		.tx_gpio_func = func

/*
 * Structure for the FIM-devices with USB support
 * If a GPIO should not be used, then it's required to disable it by using the
 * above macro 'FIM_GPIO_DONT_USE'
 *
 * fim_nr  : Number of the FIM to use for the device
 * gpio_nr : GPIO to use for the interface line
 */
struct fim_usb_platform_data {

	int fim_nr;

	int (*init)(struct device *);
	int (*exit)(struct device *);

	int vp_gpio_nr;
	unsigned int vp_gpio_func;
	int vm_gpio_nr;
	unsigned int vm_gpio_func;
	int rcv_gpio_nr;
	unsigned int rcv_gpio_func;
	int oe_l_gpio_nr;
	unsigned int oe_l_gpio_func;
	int enum_gpio_nr;
	unsigned int enum_gpio_func;
	int spnd_gpio_nr;
	unsigned int spnd_gpio_func;
};

/*
 * Macro for the configuration of the GPIOs for the FIM USB driver
 * IMPORTANT: The FIM-firmware is able to control the DP, DM, OE and RCV pins, but NOT
 * the lines for the enumeration (ENUM) and suspend (SPND). The 'func_out' defines the
 * function for the output GPIOs
 */
#define NS921X_FIM_USB_GPIOS(vp, vm, rcv, oe_l, enume, spnd, func, func_out)      \
		.vp_gpio_nr = vp, \
		.vp_gpio_func = func, \
		.vm_gpio_nr = vm, \
		.vm_gpio_func = func, \
		.rcv_gpio_nr = rcv, \
		.rcv_gpio_func = func, \
		.oe_l_gpio_nr = oe_l, \
		.oe_l_gpio_func = func, \
		.enum_gpio_nr = enume, \
		.enum_gpio_func = func_out, \
		.spnd_gpio_nr = spnd, \
		.spnd_gpio_func = func_out

/* Macros for building the FIM-drivers as loadable modules */
#if defined(MODULE)
# define NS921X_FIM_NUMBERS_PARAM(number)		\
	static int number = -1;				\
	module_param_named(fims, number, int, 0644);
#else
# define NS921X_FIM_NUMBERS_PARAM(number)		\
	static int number = FIM_NR_PICS;
#endif

/* Call the function for checking the FIM module parameter */
#if defined(MODULE)
inline int fim_check_numbers_param(int number)	    \
{						    \
	if (number < 0 || number > FIM_NR_PICS)	    \
		return -1;			    \
	else					    \
		return 0;			    \
}
inline int fim_check_device_id(int number, uint id) {    \
	int ret;					  \
	if (id < 0)				       \
		ret = 1;			       \
	else if (number == FIM_NR_PICS && id < number) \
		ret = 0;			       \
	else if (number < FIM_NR_PICS && id == number) \
		ret = 0;			       \
	else					       \
		ret = 1;			       \
	return ret;				       \
}
#else
# define fim_check_numbers_param(number)        (0)
# define fim_check_device_id(number, id)        (id < 0 || id >= number)
#endif

/* These are the functions of the FIM-API */
int fim_register_driver(struct fim_driver *driver);
int fim_unregister_driver(struct fim_driver *driver);
int fim_send_interrupt2(struct fim_driver *driver, unsigned int code);
int fim_get_exp_reg(struct fim_driver *driver, int nr, unsigned int *value);
int fim_enable_irq(struct fim_driver *driver);
int fim_disable_irq(struct fim_driver *driver);
int fim_send_buffer(struct fim_driver *driver, const struct fim_buffer_t *bufdesc);
int fim_tx_buffers_room(struct fim_driver *driver);
int fim_tx_buffers_level(struct fim_driver *driver);
int fim_send_reset(struct fim_driver *driver);
int fim_send_start(struct fim_driver *driver);
int fim_send_stop(struct fim_driver *driver);
void fim_flush_rx(struct fim_driver *driver);
void fim_flush_tx(struct fim_driver *driver);
struct fim_buffer_t *fim_alloc_buffer(struct fim_driver *driver, int length,
				      unsigned int gfp_flags);
void fim_free_buffer(struct fim_driver *driver, struct fim_buffer_t *buffer);
void fim_set_ctrl_reg(struct fim_driver *driver, int reg, unsigned int val);
void fim_set_exp_reg(struct fim_driver *driver, int reg, unsigned int val);
int fim_get_ctrl_reg(struct fim_driver *driver, int reg, unsigned int *val);
int fim_get_stat_reg(struct fim_driver *driver, int reg, unsigned int *val);
struct pic_t *fim_request_pic(int picnr);
void fim_free_pic(struct pic_t *pic);
void fim_print_fifo_status(struct fim_driver *driver);
int fim_number_pics(void);
int fim_download_firmware(struct fim_driver *driver);
int fim_is_running(struct fim_driver *driver);

int fim_dma_stop(struct fim_driver *fim);
int fim_dma_start(struct fim_driver *fim, struct fim_dma_cfg_t *cfg);

#endif /* ifndef _NS921X_FIM_CORE_H */