Blame view

drivers/tty/serial/mpsc.c 55 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
   * Generic driver for the MPSC (UART mode) on Marvell parts (e.g., GT64240,
   * GT64260, MV64340, MV64360, GT96100, ... ).
   *
   * Author: Mark A. Greer <mgreer@mvista.com>
   *
   * Based on an old MPSC driver that was in the linuxppc tree.  It appears to
   * have been created by Chris Zankel (formerly of MontaVista) but there
   * is no proper Copyright so I'm not sure.  Apparently, parts were also
   * taken from PPCBoot (now U-Boot).  Also based on drivers/serial/8250.c
   * by Russell King.
   *
   * 2004 (c) MontaVista, Software, Inc.  This file is licensed under
   * the terms of the GNU General Public License version 2.  This program
   * is licensed "as is" without any warranty of any kind, whether express
   * or implied.
   */
  /*
   * The MPSC interface is much like a typical network controller's interface.
   * That is, you set up separate rings of descriptors for transmitting and
   * receiving data.  There is also a pool of buffers with (one buffer per
   * descriptor) that incoming data are dma'd into or outgoing data are dma'd
   * out of.
   *
   * The MPSC requires two other controllers to be able to work.  The Baud Rate
   * Generator (BRG) provides a clock at programmable frequencies which determines
   * the baud rate.  The Serial DMA Controller (SDMA) takes incoming data from the
   * MPSC and DMA's it into memory or DMA's outgoing data and passes it to the
   * MPSC.  It is actually the SDMA interrupt that the driver uses to keep the
   * transmit and receive "engines" going (i.e., indicate data has been
   * transmitted or received).
   *
   * NOTES:
   *
   * 1) Some chips have an erratum where several regs cannot be
   * read.  To work around that, we keep a local copy of those regs in
   * 'mpsc_port_info'.
   *
   * 2) Some chips have an erratum where the ctlr will hang when the SDMA ctlr
   * accesses system mem with coherency enabled.  For that reason, the driver
   * assumes that coherency for that ctlr has been disabled.  This means
   * that when in a cache coherent system, the driver has to manually manage
   * the data cache on the areas that it touches because the dma_* macro are
   * basically no-ops.
   *
   * 3) There is an erratum (on PPC) where you can't use the instruction to do
   * a DMA_TO_DEVICE/cache clean so DMA_BIDIRECTIONAL/flushes are used in places
   * where a DMA_TO_DEVICE/clean would have [otherwise] sufficed.
   *
   * 4) AFAICT, hardware flow control isn't supported by the controller --MAG.
   */
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
52
53
54
55
  
  #if defined(CONFIG_SERIAL_MPSC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
  #define SUPPORT_SYSRQ
  #endif
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
56
57
58
59
60
61
62
63
64
65
66
67
  #include <linux/tty.h>
  #include <linux/tty_flip.h>
  #include <linux/ioport.h>
  #include <linux/init.h>
  #include <linux/console.h>
  #include <linux/sysrq.h>
  #include <linux/serial.h>
  #include <linux/serial_core.h>
  #include <linux/delay.h>
  #include <linux/device.h>
  #include <linux/dma-mapping.h>
  #include <linux/mv643xx.h>
d052d1bef   Russell King   Create platform_d...
68
  #include <linux/platform_device.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
69
  #include <linux/gfp.h>
d052d1bef   Russell King   Create platform_d...
70

e4294b3ec   Mark A. Greer   [PATCH] serial: m...
71
72
  #include <asm/io.h>
  #include <asm/irq.h>
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  #define	MPSC_NUM_CTLRS		2
  
  /*
   * Descriptors and buffers must be cache line aligned.
   * Buffers lengths must be multiple of cache line size.
   * Number of Tx & Rx descriptors must be powers of 2.
   */
  #define	MPSC_RXR_ENTRIES	32
  #define	MPSC_RXRE_SIZE		dma_get_cache_alignment()
  #define	MPSC_RXR_SIZE		(MPSC_RXR_ENTRIES * MPSC_RXRE_SIZE)
  #define	MPSC_RXBE_SIZE		dma_get_cache_alignment()
  #define	MPSC_RXB_SIZE		(MPSC_RXR_ENTRIES * MPSC_RXBE_SIZE)
  
  #define	MPSC_TXR_ENTRIES	32
  #define	MPSC_TXRE_SIZE		dma_get_cache_alignment()
  #define	MPSC_TXR_SIZE		(MPSC_TXR_ENTRIES * MPSC_TXRE_SIZE)
  #define	MPSC_TXBE_SIZE		dma_get_cache_alignment()
  #define	MPSC_TXB_SIZE		(MPSC_TXR_ENTRIES * MPSC_TXBE_SIZE)
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
91
92
  #define	MPSC_DMA_ALLOC_SIZE	(MPSC_RXR_SIZE + MPSC_RXB_SIZE + MPSC_TXR_SIZE \
  		+ MPSC_TXB_SIZE + dma_get_cache_alignment() /* for alignment */)
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
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
  
  /* Rx and Tx Ring entry descriptors -- assume entry size is <= cacheline size */
  struct mpsc_rx_desc {
  	u16 bufsize;
  	u16 bytecnt;
  	u32 cmdstat;
  	u32 link;
  	u32 buf_ptr;
  } __attribute((packed));
  
  struct mpsc_tx_desc {
  	u16 bytecnt;
  	u16 shadow;
  	u32 cmdstat;
  	u32 link;
  	u32 buf_ptr;
  } __attribute((packed));
  
  /*
   * Some regs that have the erratum that you can't read them are are shared
   * between the two MPSC controllers.  This struct contains those shared regs.
   */
  struct mpsc_shared_regs {
  	phys_addr_t mpsc_routing_base_p;
  	phys_addr_t sdma_intr_base_p;
  
  	void __iomem *mpsc_routing_base;
  	void __iomem *sdma_intr_base;
  
  	u32 MPSC_MRR_m;
  	u32 MPSC_RCRR_m;
  	u32 MPSC_TCRR_m;
  	u32 SDMA_INTR_CAUSE_m;
  	u32 SDMA_INTR_MASK_m;
  };
  
  /* The main driver data structure */
  struct mpsc_port_info {
  	struct uart_port port;	/* Overlay uart_port structure */
  
  	/* Internal driver state for this ctlr */
  	u8 ready;
  	u8 rcv_data;
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
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
  
  	/* Info passed in from platform */
  	u8 mirror_regs;		/* Need to mirror regs? */
  	u8 cache_mgmt;		/* Need manual cache mgmt? */
  	u8 brg_can_tune;	/* BRG has baud tuning? */
  	u32 brg_clk_src;
  	u16 mpsc_max_idle;
  	int default_baud;
  	int default_bits;
  	int default_parity;
  	int default_flow;
  
  	/* Physical addresses of various blocks of registers (from platform) */
  	phys_addr_t mpsc_base_p;
  	phys_addr_t sdma_base_p;
  	phys_addr_t brg_base_p;
  
  	/* Virtual addresses of various blocks of registers (from platform) */
  	void __iomem *mpsc_base;
  	void __iomem *sdma_base;
  	void __iomem *brg_base;
  
  	/* Descriptor ring and buffer allocations */
  	void *dma_region;
  	dma_addr_t dma_region_p;
  
  	dma_addr_t rxr;		/* Rx descriptor ring */
  	dma_addr_t rxr_p;	/* Phys addr of rxr */
  	u8 *rxb;		/* Rx Ring I/O buf */
  	u8 *rxb_p;		/* Phys addr of rxb */
  	u32 rxr_posn;		/* First desc w/ Rx data */
  
  	dma_addr_t txr;		/* Tx descriptor ring */
  	dma_addr_t txr_p;	/* Phys addr of txr */
  	u8 *txb;		/* Tx Ring I/O buf */
  	u8 *txb_p;		/* Phys addr of txb */
  	int txr_head;		/* Where new data goes */
  	int txr_tail;		/* Where sent data comes off */
1733310bb   Dave Jiang   MPSC serial drive...
174
  	spinlock_t tx_lock;	/* transmit lock */
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
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
  
  	/* Mirrored values of regs we can't read (if 'mirror_regs' set) */
  	u32 MPSC_MPCR_m;
  	u32 MPSC_CHR_1_m;
  	u32 MPSC_CHR_2_m;
  	u32 MPSC_CHR_10_m;
  	u32 BRG_BCR_m;
  	struct mpsc_shared_regs *shared_regs;
  };
  
  /* Hooks to platform-specific code */
  int mpsc_platform_register_driver(void);
  void mpsc_platform_unregister_driver(void);
  
  /* Hooks back in to mpsc common to be called by platform-specific code */
  struct mpsc_port_info *mpsc_device_probe(int index);
  struct mpsc_port_info *mpsc_device_remove(int index);
  
  /* Main MPSC Configuration Register Offsets */
  #define	MPSC_MMCRL			0x0000
  #define	MPSC_MMCRH			0x0004
  #define	MPSC_MPCR			0x0008
  #define	MPSC_CHR_1			0x000c
  #define	MPSC_CHR_2			0x0010
  #define	MPSC_CHR_3			0x0014
  #define	MPSC_CHR_4			0x0018
  #define	MPSC_CHR_5			0x001c
  #define	MPSC_CHR_6			0x0020
  #define	MPSC_CHR_7			0x0024
  #define	MPSC_CHR_8			0x0028
  #define	MPSC_CHR_9			0x002c
  #define	MPSC_CHR_10			0x0030
  #define	MPSC_CHR_11			0x0034
  
  #define	MPSC_MPCR_FRZ			(1 << 9)
  #define	MPSC_MPCR_CL_5			0
  #define	MPSC_MPCR_CL_6			1
  #define	MPSC_MPCR_CL_7			2
  #define	MPSC_MPCR_CL_8			3
  #define	MPSC_MPCR_SBL_1			0
  #define	MPSC_MPCR_SBL_2			1
  
  #define	MPSC_CHR_2_TEV			(1<<1)
  #define	MPSC_CHR_2_TA			(1<<7)
  #define	MPSC_CHR_2_TTCS			(1<<9)
  #define	MPSC_CHR_2_REV			(1<<17)
  #define	MPSC_CHR_2_RA			(1<<23)
  #define	MPSC_CHR_2_CRD			(1<<25)
  #define	MPSC_CHR_2_EH			(1<<31)
  #define	MPSC_CHR_2_PAR_ODD		0
  #define	MPSC_CHR_2_PAR_SPACE		1
  #define	MPSC_CHR_2_PAR_EVEN		2
  #define	MPSC_CHR_2_PAR_MARK		3
  
  /* MPSC Signal Routing */
  #define	MPSC_MRR			0x0000
  #define	MPSC_RCRR			0x0004
  #define	MPSC_TCRR			0x0008
  
  /* Serial DMA Controller Interface Registers */
  #define	SDMA_SDC			0x0000
  #define	SDMA_SDCM			0x0008
  #define	SDMA_RX_DESC			0x0800
  #define	SDMA_RX_BUF_PTR			0x0808
  #define	SDMA_SCRDP			0x0810
  #define	SDMA_TX_DESC			0x0c00
  #define	SDMA_SCTDP			0x0c10
  #define	SDMA_SFTDP			0x0c14
  
  #define	SDMA_DESC_CMDSTAT_PE		(1<<0)
  #define	SDMA_DESC_CMDSTAT_CDL		(1<<1)
  #define	SDMA_DESC_CMDSTAT_FR		(1<<3)
  #define	SDMA_DESC_CMDSTAT_OR		(1<<6)
  #define	SDMA_DESC_CMDSTAT_BR		(1<<9)
  #define	SDMA_DESC_CMDSTAT_MI		(1<<10)
  #define	SDMA_DESC_CMDSTAT_A		(1<<11)
  #define	SDMA_DESC_CMDSTAT_AM		(1<<12)
  #define	SDMA_DESC_CMDSTAT_CT		(1<<13)
  #define	SDMA_DESC_CMDSTAT_C		(1<<14)
  #define	SDMA_DESC_CMDSTAT_ES		(1<<15)
  #define	SDMA_DESC_CMDSTAT_L		(1<<16)
  #define	SDMA_DESC_CMDSTAT_F		(1<<17)
  #define	SDMA_DESC_CMDSTAT_P		(1<<18)
  #define	SDMA_DESC_CMDSTAT_EI		(1<<23)
  #define	SDMA_DESC_CMDSTAT_O		(1<<31)
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
260
261
  #define SDMA_DESC_DFLT			(SDMA_DESC_CMDSTAT_O \
  		| SDMA_DESC_CMDSTAT_EI)
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  
  #define	SDMA_SDC_RFT			(1<<0)
  #define	SDMA_SDC_SFM			(1<<1)
  #define	SDMA_SDC_BLMR			(1<<6)
  #define	SDMA_SDC_BLMT			(1<<7)
  #define	SDMA_SDC_POVR			(1<<8)
  #define	SDMA_SDC_RIFB			(1<<9)
  
  #define	SDMA_SDCM_ERD			(1<<7)
  #define	SDMA_SDCM_AR			(1<<15)
  #define	SDMA_SDCM_STD			(1<<16)
  #define	SDMA_SDCM_TXD			(1<<23)
  #define	SDMA_SDCM_AT			(1<<31)
  
  #define	SDMA_0_CAUSE_RXBUF		(1<<0)
  #define	SDMA_0_CAUSE_RXERR		(1<<1)
  #define	SDMA_0_CAUSE_TXBUF		(1<<2)
  #define	SDMA_0_CAUSE_TXEND		(1<<3)
  #define	SDMA_1_CAUSE_RXBUF		(1<<8)
  #define	SDMA_1_CAUSE_RXERR		(1<<9)
  #define	SDMA_1_CAUSE_TXBUF		(1<<10)
  #define	SDMA_1_CAUSE_TXEND		(1<<11)
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
284
285
286
287
  #define	SDMA_CAUSE_RX_MASK	(SDMA_0_CAUSE_RXBUF | SDMA_0_CAUSE_RXERR \
  		| SDMA_1_CAUSE_RXBUF | SDMA_1_CAUSE_RXERR)
  #define	SDMA_CAUSE_TX_MASK	(SDMA_0_CAUSE_TXBUF | SDMA_0_CAUSE_TXEND \
  		| SDMA_1_CAUSE_TXBUF | SDMA_1_CAUSE_TXEND)
e4294b3ec   Mark A. Greer   [PATCH] serial: m...
288
289
290
291
292
293
294
295
  
  /* SDMA Interrupt registers */
  #define	SDMA_INTR_CAUSE			0x0000
  #define	SDMA_INTR_MASK			0x0080
  
  /* Baud Rate Generator Interface Registers */
  #define	BRG_BCR				0x0000
  #define	BRG_BTR				0x0004
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  
  /*
   * Define how this driver is known to the outside (we've been assigned a
   * range on the "Low-density serial ports" major).
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
301
302
303
304
305
  #define MPSC_MAJOR			204
  #define MPSC_MINOR_START		44
  #define	MPSC_DRIVER_NAME		"MPSC"
  #define	MPSC_DEV_NAME			"ttyMM"
  #define	MPSC_VERSION			"1.00"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
  
  static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS];
  static struct mpsc_shared_regs mpsc_shared_regs;
4d0145a7d   Lee Nicks   [PATCH] compilati...
309
  static struct uart_driver mpsc_reg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

4d0145a7d   Lee Nicks   [PATCH] compilati...
311
312
313
  static void mpsc_start_rx(struct mpsc_port_info *pi);
  static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
  static void mpsc_release_port(struct uart_port *port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
320
  /*
   ******************************************************************************
   *
   * Baud Rate Generator Routines (BRG)
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
321
  static void mpsc_brg_init(struct mpsc_port_info *pi, u32 clk_src)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  {
  	u32	v;
  
  	v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
  	v = (v & ~(0xf << 18)) | ((clk_src & 0xf) << 18);
  
  	if (pi->brg_can_tune)
  		v &= ~(1 << 25);
  
  	if (pi->mirror_regs)
  		pi->BRG_BCR_m = v;
  	writel(v, pi->brg_base + BRG_BCR);
  
  	writel(readl(pi->brg_base + BRG_BTR) & 0xffff0000,
  		pi->brg_base + BRG_BTR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
338
  static void mpsc_brg_enable(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
345
346
347
  {
  	u32	v;
  
  	v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
  	v |= (1 << 16);
  
  	if (pi->mirror_regs)
  		pi->BRG_BCR_m = v;
  	writel(v, pi->brg_base + BRG_BCR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
349
  static void mpsc_brg_disable(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
355
356
357
358
  {
  	u32	v;
  
  	v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
  	v &= ~(1 << 16);
  
  	if (pi->mirror_regs)
  		pi->BRG_BCR_m = v;
  	writel(v, pi->brg_base + BRG_BCR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
360
361
362
363
364
365
366
367
368
369
  /*
   * To set the baud, we adjust the CDV field in the BRG_BCR reg.
   * From manual: Baud = clk / ((CDV+1)*2) ==> CDV = (clk / (baud*2)) - 1.
   * However, the input clock is divided by 16 in the MPSC b/c of how
   * 'MPSC_MMCRH' was set up so we have to divide the 'clk' used in our
   * calculation by 16 to account for that.  So the real calculation
   * that accounts for the way the mpsc is set up is:
   * CDV = (clk / (baud*2*16)) - 1 ==> CDV = (clk / (baud << 5)) - 1.
   */
  static void mpsc_set_baudrate(struct mpsc_port_info *pi, u32 baud)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
379
380
381
  	u32	cdv = (pi->port.uartclk / (baud << 5)) - 1;
  	u32	v;
  
  	mpsc_brg_disable(pi);
  	v = (pi->mirror_regs) ? pi->BRG_BCR_m : readl(pi->brg_base + BRG_BCR);
  	v = (v & 0xffff0000) | (cdv & 0xffff);
  
  	if (pi->mirror_regs)
  		pi->BRG_BCR_m = v;
  	writel(v, pi->brg_base + BRG_BCR);
  	mpsc_brg_enable(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
386
387
388
389
390
  }
  
  /*
   ******************************************************************************
   *
   * Serial DMA Routines (SDMA)
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
391
  static void mpsc_sdma_burstsize(struct mpsc_port_info *pi, u32 burst_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
396
  {
  	u32	v;
  
  	pr_debug("mpsc_sdma_burstsize[%d]: burst_size: %d
  ",
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
397
  			pi->port.line, burst_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  
  	burst_size >>= 3; /* Divide by 8 b/c reg values are 8-byte chunks */
  
  	if (burst_size < 2)
  		v = 0x0;	/* 1 64-bit word */
  	else if (burst_size < 4)
  		v = 0x1;	/* 2 64-bit words */
  	else if (burst_size < 8)
  		v = 0x2;	/* 4 64-bit words */
  	else
  		v = 0x3;	/* 8 64-bit words */
  
  	writel((readl(pi->sdma_base + SDMA_SDC) & (0x3 << 12)) | (v << 12),
  		pi->sdma_base + SDMA_SDC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
413
  static void mpsc_sdma_init(struct mpsc_port_info *pi, u32 burst_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
416
417
418
419
420
421
  {
  	pr_debug("mpsc_sdma_init[%d]: burst_size: %d
  ", pi->port.line,
  		burst_size);
  
  	writel((readl(pi->sdma_base + SDMA_SDC) & 0x3ff) | 0x03f,
  		pi->sdma_base + SDMA_SDC);
  	mpsc_sdma_burstsize(pi, burst_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
423
  static u32 mpsc_sdma_intr_mask(struct mpsc_port_info *pi, u32 mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  {
  	u32	old, v;
  
  	pr_debug("mpsc_sdma_intr_mask[%d]: mask: 0x%x
  ", pi->port.line, mask);
  
  	old = v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m :
  		readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
  
  	mask &= 0xf;
  	if (pi->port.line)
  		mask <<= 8;
  	v &= ~mask;
  
  	if (pi->mirror_regs)
  		pi->shared_regs->SDMA_INTR_MASK_m = v;
  	writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
  
  	if (pi->port.line)
  		old >>= 8;
  	return old & 0xf;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
446
  static void mpsc_sdma_intr_unmask(struct mpsc_port_info *pi, u32 mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
  {
  	u32	v;
  
  	pr_debug("mpsc_sdma_intr_unmask[%d]: mask: 0x%x
  ", pi->port.line,mask);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
452
453
  	v = (pi->mirror_regs) ? pi->shared_regs->SDMA_INTR_MASK_m
  		: readl(pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
459
460
461
462
  
  	mask &= 0xf;
  	if (pi->port.line)
  		mask <<= 8;
  	v |= mask;
  
  	if (pi->mirror_regs)
  		pi->shared_regs->SDMA_INTR_MASK_m = v;
  	writel(v, pi->shared_regs->sdma_intr_base + SDMA_INTR_MASK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
464
  static void mpsc_sdma_intr_ack(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
  {
  	pr_debug("mpsc_sdma_intr_ack[%d]: Acknowledging IRQ
  ", pi->port.line);
  
  	if (pi->mirror_regs)
  		pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
471
472
  	writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE
  			+ pi->port.line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
474
475
  static void mpsc_sdma_set_rx_ring(struct mpsc_port_info *pi,
  		struct mpsc_rx_desc *rxre_p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
  {
  	pr_debug("mpsc_sdma_set_rx_ring[%d]: rxre_p: 0x%x
  ",
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
479
  		pi->port.line, (u32)rxre_p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  
  	writel((u32)rxre_p, pi->sdma_base + SDMA_SCRDP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
483
484
  static void mpsc_sdma_set_tx_ring(struct mpsc_port_info *pi,
  		struct mpsc_tx_desc *txre_p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
  {
  	writel((u32)txre_p, pi->sdma_base + SDMA_SFTDP);
  	writel((u32)txre_p, pi->sdma_base + SDMA_SCTDP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
489
  static void mpsc_sdma_cmd(struct mpsc_port_info *pi, u32 val)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
492
493
494
495
496
497
498
499
500
  {
  	u32	v;
  
  	v = readl(pi->sdma_base + SDMA_SDCM);
  	if (val)
  		v |= val;
  	else
  		v = 0;
  	wmb();
  	writel(v, pi->sdma_base + SDMA_SDCM);
  	wmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
502
  static uint mpsc_sdma_tx_active(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
  {
  	return readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_TXD;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
506
  static void mpsc_sdma_start_tx(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
509
510
511
  {
  	struct mpsc_tx_desc *txre, *txre_p;
  
  	/* If tx isn't running & there's a desc ready to go, start it */
  	if (!mpsc_sdma_tx_active(pi)) {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
512
513
514
515
  		txre = (struct mpsc_tx_desc *)(pi->txr
  				+ (pi->txr_tail * MPSC_TXRE_SIZE));
  		dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
  				DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			invalidate_dcache_range((ulong)txre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
519
  					(ulong)txre + MPSC_TXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
  #endif
  
  		if (be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O) {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
523
524
  			txre_p = (struct mpsc_tx_desc *)
  				(pi->txr_p + (pi->txr_tail * MPSC_TXRE_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
  
  			mpsc_sdma_set_tx_ring(pi, txre_p);
  			mpsc_sdma_cmd(pi, SDMA_SDCM_STD | SDMA_SDCM_TXD);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
531
  static void mpsc_sdma_stop(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
536
537
538
539
540
  {
  	pr_debug("mpsc_sdma_stop[%d]: Stopping SDMA
  ", pi->port.line);
  
  	/* Abort any SDMA transfers */
  	mpsc_sdma_cmd(pi, 0);
  	mpsc_sdma_cmd(pi, SDMA_SDCM_AR | SDMA_SDCM_AT);
  
  	/* Clear the SDMA current and first TX and RX pointers */
2c6e75999   Al Viro   [PATCH] ppc annot...
541
542
  	mpsc_sdma_set_tx_ring(pi, NULL);
  	mpsc_sdma_set_rx_ring(pi, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
545
546
  
  	/* Disable interrupts */
  	mpsc_sdma_intr_mask(pi, 0xf);
  	mpsc_sdma_intr_ack(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
553
554
555
  }
  
  /*
   ******************************************************************************
   *
   * Multi-Protocol Serial Controller Routines (MPSC)
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
556
  static void mpsc_hw_init(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  {
  	u32	v;
  
  	pr_debug("mpsc_hw_init[%d]: Initializing hardware
  ", pi->port.line);
  
  	/* Set up clock routing */
  	if (pi->mirror_regs) {
  		v = pi->shared_regs->MPSC_MRR_m;
  		v &= ~0x1c7;
  		pi->shared_regs->MPSC_MRR_m = v;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR);
  
  		v = pi->shared_regs->MPSC_RCRR_m;
  		v = (v & ~0xf0f) | 0x100;
  		pi->shared_regs->MPSC_RCRR_m = v;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
  
  		v = pi->shared_regs->MPSC_TCRR_m;
  		v = (v & ~0xf0f) | 0x100;
  		pi->shared_regs->MPSC_TCRR_m = v;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
579
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  		v = readl(pi->shared_regs->mpsc_routing_base + MPSC_MRR);
  		v &= ~0x1c7;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_MRR);
  
  		v = readl(pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
  		v = (v & ~0xf0f) | 0x100;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_RCRR);
  
  		v = readl(pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
  		v = (v & ~0xf0f) | 0x100;
  		writel(v, pi->shared_regs->mpsc_routing_base + MPSC_TCRR);
  	}
  
  	/* Put MPSC in UART mode & enabel Tx/Rx egines */
  	writel(0x000004c4, pi->mpsc_base + MPSC_MMCRL);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
595
  	/* No preamble, 16x divider, low-latency, */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
  	writel(0x04400400, pi->mpsc_base + MPSC_MMCRH);
7bbdc3d51   Mark A. Greer   serial: MPSC: set...
597
  	mpsc_set_baudrate(pi, pi->default_baud);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
  
  	if (pi->mirror_regs) {
  		pi->MPSC_CHR_1_m = 0;
  		pi->MPSC_CHR_2_m = 0;
  	}
  	writel(0, pi->mpsc_base + MPSC_CHR_1);
  	writel(0, pi->mpsc_base + MPSC_CHR_2);
  	writel(pi->mpsc_max_idle, pi->mpsc_base + MPSC_CHR_3);
  	writel(0, pi->mpsc_base + MPSC_CHR_4);
  	writel(0, pi->mpsc_base + MPSC_CHR_5);
  	writel(0, pi->mpsc_base + MPSC_CHR_6);
  	writel(0, pi->mpsc_base + MPSC_CHR_7);
  	writel(0, pi->mpsc_base + MPSC_CHR_8);
  	writel(0, pi->mpsc_base + MPSC_CHR_9);
  	writel(0, pi->mpsc_base + MPSC_CHR_10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
614
  static void mpsc_enter_hunt(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
618
619
620
621
622
623
  {
  	pr_debug("mpsc_enter_hunt[%d]: Hunting...
  ", pi->port.line);
  
  	if (pi->mirror_regs) {
  		writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_EH,
  			pi->mpsc_base + MPSC_CHR_2);
  		/* Erratum prevents reading CHR_2 so just delay for a while */
  		udelay(100);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
624
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  		writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_EH,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
626
  				pi->mpsc_base + MPSC_CHR_2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
  
  		while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_EH)
  			udelay(10);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
632
  static void mpsc_freeze(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
637
638
639
640
641
642
643
644
645
  {
  	u32	v;
  
  	pr_debug("mpsc_freeze[%d]: Freezing
  ", pi->port.line);
  
  	v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
  		readl(pi->mpsc_base + MPSC_MPCR);
  	v |= MPSC_MPCR_FRZ;
  
  	if (pi->mirror_regs)
  		pi->MPSC_MPCR_m = v;
  	writel(v, pi->mpsc_base + MPSC_MPCR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
647
  static void mpsc_unfreeze(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
651
652
653
654
655
656
657
658
659
660
  {
  	u32	v;
  
  	v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
  		readl(pi->mpsc_base + MPSC_MPCR);
  	v &= ~MPSC_MPCR_FRZ;
  
  	if (pi->mirror_regs)
  		pi->MPSC_MPCR_m = v;
  	writel(v, pi->mpsc_base + MPSC_MPCR);
  
  	pr_debug("mpsc_unfreeze[%d]: Unfrozen
  ", pi->port.line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
662
  static void mpsc_set_char_length(struct mpsc_port_info *pi, u32 len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
665
666
667
668
669
670
671
672
673
674
675
  {
  	u32	v;
  
  	pr_debug("mpsc_set_char_length[%d]: char len: %d
  ", pi->port.line,len);
  
  	v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
  		readl(pi->mpsc_base + MPSC_MPCR);
  	v = (v & ~(0x3 << 12)) | ((len & 0x3) << 12);
  
  	if (pi->mirror_regs)
  		pi->MPSC_MPCR_m = v;
  	writel(v, pi->mpsc_base + MPSC_MPCR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
677
  static void mpsc_set_stop_bit_length(struct mpsc_port_info *pi, u32 len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  {
  	u32	v;
  
  	pr_debug("mpsc_set_stop_bit_length[%d]: stop bits: %d
  ",
  		pi->port.line, len);
  
  	v = (pi->mirror_regs) ? pi->MPSC_MPCR_m :
  		readl(pi->mpsc_base + MPSC_MPCR);
  
  	v = (v & ~(1 << 14)) | ((len & 0x1) << 14);
  
  	if (pi->mirror_regs)
  		pi->MPSC_MPCR_m = v;
  	writel(v, pi->mpsc_base + MPSC_MPCR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
694
  static void mpsc_set_parity(struct mpsc_port_info *pi, u32 p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
  {
  	u32	v;
  
  	pr_debug("mpsc_set_parity[%d]: parity bits: 0x%x
  ", pi->port.line, p);
  
  	v = (pi->mirror_regs) ? pi->MPSC_CHR_2_m :
  		readl(pi->mpsc_base + MPSC_CHR_2);
  
  	p &= 0x3;
  	v = (v & ~0xc000c) | (p << 18) | (p << 2);
  
  	if (pi->mirror_regs)
  		pi->MPSC_CHR_2_m = v;
  	writel(v, pi->mpsc_base + MPSC_CHR_2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
714
715
716
717
718
  }
  
  /*
   ******************************************************************************
   *
   * Driver Init Routines
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
719
  static void mpsc_init_hw(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
723
724
725
726
727
728
  {
  	pr_debug("mpsc_init_hw[%d]: Initializing
  ", pi->port.line);
  
  	mpsc_brg_init(pi, pi->brg_clk_src);
  	mpsc_brg_enable(pi);
  	mpsc_sdma_init(pi, dma_get_cache_alignment());	/* burst a cacheline */
  	mpsc_sdma_stop(pi);
  	mpsc_hw_init(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
730
  static int mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
  {
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
737
738
  
  	pr_debug("mpsc_alloc_ring_mem[%d]: Allocating ring mem
  ",
  		pi->port.line);
  
  	if (!pi->dma_region) {
fc12c116b   Christoph Hellwig   mpsc: use dma_set...
739
  		if (!dma_set_mask(pi->port.dev, 0xffffffff)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
741
742
  			printk(KERN_ERR "MPSC: Inadequate DMA support
  ");
  			rc = -ENXIO;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
743
744
745
746
  		} else if ((pi->dma_region = dma_alloc_noncoherent(pi->port.dev,
  						MPSC_DMA_ALLOC_SIZE,
  						&pi->dma_region_p, GFP_KERNEL))
  				== NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
748
749
750
751
752
753
754
  			printk(KERN_ERR "MPSC: Can't alloc Desc region
  ");
  			rc = -ENOMEM;
  		}
  	}
  
  	return rc;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
755
  static void mpsc_free_ring_mem(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
759
760
761
  {
  	pr_debug("mpsc_free_ring_mem[%d]: Freeing ring mem
  ", pi->port.line);
  
  	if (pi->dma_region) {
  		dma_free_noncoherent(pi->port.dev, MPSC_DMA_ALLOC_SIZE,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
762
  				pi->dma_region, pi->dma_region_p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  		pi->dma_region = NULL;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
764
  		pi->dma_region_p = (dma_addr_t)NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
767
  static void mpsc_init_rings(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  {
  	struct mpsc_rx_desc *rxre;
  	struct mpsc_tx_desc *txre;
  	dma_addr_t dp, dp_p;
  	u8 *bp, *bp_p;
  	int i;
  
  	pr_debug("mpsc_init_rings[%d]: Initializing rings
  ", pi->port.line);
  
  	BUG_ON(pi->dma_region == NULL);
  
  	memset(pi->dma_region, 0, MPSC_DMA_ALLOC_SIZE);
  
  	/*
  	 * Descriptors & buffers are multiples of cacheline size and must be
  	 * cacheline aligned.
  	 */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
786
787
  	dp = ALIGN((u32)pi->dma_region, dma_get_cache_alignment());
  	dp_p = ALIGN((u32)pi->dma_region_p, dma_get_cache_alignment());
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
792
793
794
795
796
  
  	/*
  	 * Partition dma region into rx ring descriptor, rx buffers,
  	 * tx ring descriptors, and tx buffers.
  	 */
  	pi->rxr = dp;
  	pi->rxr_p = dp_p;
  	dp += MPSC_RXR_SIZE;
  	dp_p += MPSC_RXR_SIZE;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
797
798
  	pi->rxb = (u8 *)dp;
  	pi->rxb_p = (u8 *)dp_p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
800
801
802
803
804
805
806
807
  	dp += MPSC_RXB_SIZE;
  	dp_p += MPSC_RXB_SIZE;
  
  	pi->rxr_posn = 0;
  
  	pi->txr = dp;
  	pi->txr_p = dp_p;
  	dp += MPSC_TXR_SIZE;
  	dp_p += MPSC_TXR_SIZE;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
808
809
  	pi->txb = (u8 *)dp;
  	pi->txb_p = (u8 *)dp_p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
  
  	pi->txr_head = 0;
  	pi->txr_tail = 0;
  
  	/* Init rx ring descriptors */
  	dp = pi->rxr;
  	dp_p = pi->rxr_p;
  	bp = pi->rxb;
  	bp_p = pi->rxb_p;
  
  	for (i = 0; i < MPSC_RXR_ENTRIES; i++) {
  		rxre = (struct mpsc_rx_desc *)dp;
  
  		rxre->bufsize = cpu_to_be16(MPSC_RXBE_SIZE);
  		rxre->bytecnt = cpu_to_be16(0);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
825
826
827
  		rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O
  				| SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F
  				| SDMA_DESC_CMDSTAT_L);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  		rxre->link = cpu_to_be32(dp_p + MPSC_RXRE_SIZE);
  		rxre->buf_ptr = cpu_to_be32(bp_p);
  
  		dp += MPSC_RXRE_SIZE;
  		dp_p += MPSC_RXRE_SIZE;
  		bp += MPSC_RXBE_SIZE;
  		bp_p += MPSC_RXBE_SIZE;
  	}
  	rxre->link = cpu_to_be32(pi->rxr_p);	/* Wrap last back to first */
  
  	/* Init tx ring descriptors */
  	dp = pi->txr;
  	dp_p = pi->txr_p;
  	bp = pi->txb;
  	bp_p = pi->txb_p;
  
  	for (i = 0; i < MPSC_TXR_ENTRIES; i++) {
  		txre = (struct mpsc_tx_desc *)dp;
  
  		txre->link = cpu_to_be32(dp_p + MPSC_TXRE_SIZE);
  		txre->buf_ptr = cpu_to_be32(bp_p);
  
  		dp += MPSC_TXRE_SIZE;
  		dp_p += MPSC_TXRE_SIZE;
  		bp += MPSC_TXBE_SIZE;
  		bp_p += MPSC_TXBE_SIZE;
  	}
  	txre->link = cpu_to_be32(pi->txr_p);	/* Wrap last back to first */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
856
857
  	dma_cache_sync(pi->port.dev, (void *)pi->dma_region,
  			MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
860
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			flush_dcache_range((ulong)pi->dma_region,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
861
862
  					(ulong)pi->dma_region
  					+ MPSC_DMA_ALLOC_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
865
866
  #endif
  
  	return;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
867
  static void mpsc_uninit_rings(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
  {
  	pr_debug("mpsc_uninit_rings[%d]: Uninitializing rings
  ",pi->port.line);
  
  	BUG_ON(pi->dma_region == NULL);
  
  	pi->rxr = 0;
  	pi->rxr_p = 0;
  	pi->rxb = NULL;
  	pi->rxb_p = NULL;
  	pi->rxr_posn = 0;
  
  	pi->txr = 0;
  	pi->txr_p = 0;
  	pi->txb = NULL;
  	pi->txb_p = NULL;
  	pi->txr_head = 0;
  	pi->txr_tail = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
887
  static int mpsc_make_ready(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
891
892
893
894
895
  {
  	int rc;
  
  	pr_debug("mpsc_make_ready[%d]: Making cltr ready
  ", pi->port.line);
  
  	if (!pi->ready) {
  		mpsc_init_hw(pi);
f2908f70c   Greg Kroah-Hartman   tty: mpsc.c: move...
896
897
  		rc = mpsc_alloc_ring_mem(pi);
  		if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
900
901
902
903
904
  			return rc;
  		mpsc_init_rings(pi);
  		pi->ready = 1;
  	}
  
  	return 0;
  }
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
905
906
907
  #ifdef CONFIG_CONSOLE_POLL
  static int serial_polled;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
911
912
913
914
  /*
   ******************************************************************************
   *
   * Interrupt Handling Routines
   *
   ******************************************************************************
   */
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
915
  static int mpsc_rx_intr(struct mpsc_port_info *pi, unsigned long *flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
  {
  	struct mpsc_rx_desc *rxre;
227434f89   Jiri Slaby   TTY: switch tty_b...
918
  	struct tty_port *port = &pi->port.state->port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
  	u32	cmdstat, bytes_in, i;
  	int	rc = 0;
  	u8	*bp;
  	char	flag = TTY_NORMAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
925
926
927
  
  	pr_debug("mpsc_rx_intr[%d]: Handling Rx intr
  ", pi->port.line);
  
  	rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE));
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
928
929
  	dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
  			DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  	if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  		invalidate_dcache_range((ulong)rxre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
933
  				(ulong)rxre + MPSC_RXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
  #endif
  
  	/*
  	 * Loop through Rx descriptors handling ones that have been completed.
  	 */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
939
940
  	while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
  				& SDMA_DESC_CMDSTAT_O)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
  		bytes_in = be16_to_cpu(rxre->bytecnt);
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
942
943
944
945
946
947
  #ifdef CONFIG_CONSOLE_POLL
  		if (unlikely(serial_polled)) {
  			serial_polled = 0;
  			return 0;
  		}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
  		/* Following use of tty struct directly is deprecated */
227434f89   Jiri Slaby   TTY: switch tty_b...
949
  		if (tty_buffer_request_room(port, bytes_in) < bytes_in) {
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
950
951
  			if (port->low_latency) {
  				spin_unlock_irqrestore(&pi->port.lock, *flags);
2e124b4a3   Jiri Slaby   TTY: switch tty_f...
952
  				tty_flip_buffer_push(port);
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
953
954
  				spin_lock_irqsave(&pi->port.lock, *flags);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  			/*
33f0f88f1   Alan Cox   [PATCH] TTY layer...
956
957
  			 * If this failed then we will throw away the bytes
  			 * but must do so to clear interrupts.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
961
  			 */
  		}
  
  		bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
962
963
  		dma_cache_sync(pi->port.dev, (void *)bp, MPSC_RXBE_SIZE,
  				DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
966
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			invalidate_dcache_range((ulong)bp,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
967
  					(ulong)bp + MPSC_RXBE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
969
970
971
972
973
974
975
976
977
  #endif
  
  		/*
  		 * Other than for parity error, the manual provides little
  		 * info on what data will be in a frame flagged by any of
  		 * these errors.  For parity error, it is the last byte in
  		 * the buffer that had the error.  As for the rest, I guess
  		 * we'll assume there is no data in the buffer.
  		 * If there is...it gets lost.
  		 */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
978
979
980
  		if (unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR
  						| SDMA_DESC_CMDSTAT_FR
  						| SDMA_DESC_CMDSTAT_OR))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
983
984
985
986
987
988
  
  			pi->port.icount.rx++;
  
  			if (cmdstat & SDMA_DESC_CMDSTAT_BR) {	/* Break */
  				pi->port.icount.brk++;
  
  				if (uart_handle_break(&pi->port))
  					goto next_frame;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
989
  			} else if (cmdstat & SDMA_DESC_CMDSTAT_FR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  				pi->port.icount.frame++;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
991
  			} else if (cmdstat & SDMA_DESC_CMDSTAT_OR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
  				pi->port.icount.overrun++;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
993
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
  
  			cmdstat &= pi->port.read_status_mask;
  
  			if (cmdstat & SDMA_DESC_CMDSTAT_BR)
  				flag = TTY_BREAK;
  			else if (cmdstat & SDMA_DESC_CMDSTAT_FR)
  				flag = TTY_FRAME;
  			else if (cmdstat & SDMA_DESC_CMDSTAT_OR)
  				flag = TTY_OVERRUN;
  			else if (cmdstat & SDMA_DESC_CMDSTAT_PE)
  				flag = TTY_PARITY;
  		}
7d12e780e   David Howells   IRQ: Maintain reg...
1006
  		if (uart_handle_sysrq_char(&pi->port, *bp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
  			bp++;
  			bytes_in--;
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
1009
1010
1011
1012
1013
1014
  #ifdef CONFIG_CONSOLE_POLL
  			if (unlikely(serial_polled)) {
  				serial_polled = 0;
  				return 0;
  			}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
  			goto next_frame;
  		}
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1017
1018
1019
1020
  		if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR
  						| SDMA_DESC_CMDSTAT_FR
  						| SDMA_DESC_CMDSTAT_OR)))
  				&& !(cmdstat & pi->port.ignore_status_mask)) {
92a19f9ce   Jiri Slaby   TTY: switch tty_i...
1021
  			tty_insert_flip_char(port, *bp, flag);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1022
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  			for (i=0; i<bytes_in; i++)
92a19f9ce   Jiri Slaby   TTY: switch tty_i...
1024
  				tty_insert_flip_char(port, *bp++, TTY_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
1027
1028
1029
1030
1031
  
  			pi->port.icount.rx += bytes_in;
  		}
  
  next_frame:
  		rxre->bytecnt = cpu_to_be16(0);
  		wmb();
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1032
1033
1034
  		rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O
  				| SDMA_DESC_CMDSTAT_EI | SDMA_DESC_CMDSTAT_F
  				| SDMA_DESC_CMDSTAT_L);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035
  		wmb();
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1036
1037
  		dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
  				DMA_BIDIRECTIONAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
1039
1040
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			flush_dcache_range((ulong)rxre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1041
  					(ulong)rxre + MPSC_RXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
1043
1044
1045
  #endif
  
  		/* Advance to next descriptor */
  		pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1046
1047
1048
1049
  		rxre = (struct mpsc_rx_desc *)
  			(pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE));
  		dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE,
  				DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			invalidate_dcache_range((ulong)rxre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1053
  					(ulong)rxre + MPSC_RXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1054
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
1056
1057
1058
1059
1060
  		rc = 1;
  	}
  
  	/* Restart rx engine, if its stopped */
  	if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
  		mpsc_start_rx(pi);
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
1061
  	spin_unlock_irqrestore(&pi->port.lock, *flags);
2e124b4a3   Jiri Slaby   TTY: switch tty_f...
1062
  	tty_flip_buffer_push(port);
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
1063
  	spin_lock_irqsave(&pi->port.lock, *flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
  	return rc;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1066
  static void mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
  {
  	struct mpsc_tx_desc *txre;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1069
1070
  	txre = (struct mpsc_tx_desc *)(pi->txr
  			+ (pi->txr_head * MPSC_TXRE_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
1072
1073
1074
  
  	txre->bytecnt = cpu_to_be16(count);
  	txre->shadow = txre->bytecnt;
  	wmb();			/* ensure cmdstat is last field updated */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1075
1076
1077
  	txre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O | SDMA_DESC_CMDSTAT_F
  			| SDMA_DESC_CMDSTAT_L
  			| ((intr) ? SDMA_DESC_CMDSTAT_EI : 0));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
  	wmb();
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1079
1080
  	dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
  			DMA_BIDIRECTIONAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081
1082
1083
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  	if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  		flush_dcache_range((ulong)txre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1084
  				(ulong)txre + MPSC_TXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1087
  static void mpsc_copy_tx_data(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
  {
ebd2c8f6d   Alan Cox   serial: kill off ...
1089
  	struct circ_buf *xmit = &pi->port.state->xmit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
1091
1092
1093
  	u8 *bp;
  	u32 i;
  
  	/* Make sure the desc ring isn't full */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1094
1095
  	while (CIRC_CNT(pi->txr_head, pi->txr_tail, MPSC_TXR_ENTRIES)
  			< (MPSC_TXR_ENTRIES - 1)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
  		if (pi->port.x_char) {
  			/*
  			 * Ideally, we should use the TCS field in
  			 * CHR_1 to put the x_char out immediately but
  			 * errata prevents us from being able to read
  			 * CHR_2 to know that its safe to write to
  			 * CHR_1.  Instead, just put it in-band with
  			 * all the other Tx data.
  			 */
  			bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
  			*bp = pi->port.x_char;
  			pi->port.x_char = 0;
  			i = 1;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1109
1110
1111
1112
1113
  		} else if (!uart_circ_empty(xmit)
  				&& !uart_tx_stopped(&pi->port)) {
  			i = min((u32)MPSC_TXBE_SIZE,
  				(u32)uart_circ_chars_pending(xmit));
  			i = min(i, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
1117
1118
1119
1120
  				UART_XMIT_SIZE));
  			bp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
  			memcpy(bp, &xmit->buf[xmit->tail], i);
  			xmit->tail = (xmit->tail + i) & (UART_XMIT_SIZE - 1);
  
  			if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  				uart_write_wakeup(&pi->port);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1121
  		} else { /* All tx data copied into ring bufs */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
  			return;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1123
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124

2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1125
1126
  		dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE,
  				DMA_BIDIRECTIONAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			flush_dcache_range((ulong)bp,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1130
  					(ulong)bp + MPSC_TXBE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
1132
1133
1134
1135
1136
  #endif
  		mpsc_setup_tx_desc(pi, i, 1);
  
  		/* Advance to next descriptor */
  		pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1138
  static int mpsc_tx_intr(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
1140
1141
  {
  	struct mpsc_tx_desc *txre;
  	int rc = 0;
1733310bb   Dave Jiang   MPSC serial drive...
1142
1143
1144
  	unsigned long iflags;
  
  	spin_lock_irqsave(&pi->tx_lock, iflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145
1146
  
  	if (!mpsc_sdma_tx_active(pi)) {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1147
1148
  		txre = (struct mpsc_tx_desc *)(pi->txr
  				+ (pi->txr_tail * MPSC_TXRE_SIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149

2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1150
1151
  		dma_cache_sync(pi->port.dev, (void *)txre, MPSC_TXRE_SIZE,
  				DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
1154
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			invalidate_dcache_range((ulong)txre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1155
  					(ulong)txre + MPSC_TXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  #endif
  
  		while (!(be32_to_cpu(txre->cmdstat) & SDMA_DESC_CMDSTAT_O)) {
  			rc = 1;
  			pi->port.icount.tx += be16_to_cpu(txre->bytecnt);
  			pi->txr_tail = (pi->txr_tail+1) & (MPSC_TXR_ENTRIES-1);
  
  			/* If no more data to tx, fall out of loop */
  			if (pi->txr_head == pi->txr_tail)
  				break;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1166
1167
1168
1169
  			txre = (struct mpsc_tx_desc *)(pi->txr
  					+ (pi->txr_tail * MPSC_TXRE_SIZE));
  			dma_cache_sync(pi->port.dev, (void *)txre,
  					MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
1171
1172
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  				invalidate_dcache_range((ulong)txre,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1173
  						(ulong)txre + MPSC_TXRE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
1175
1176
1177
1178
1179
  #endif
  		}
  
  		mpsc_copy_tx_data(pi);
  		mpsc_sdma_start_tx(pi);	/* start next desc if ready */
  	}
1733310bb   Dave Jiang   MPSC serial drive...
1180
  	spin_unlock_irqrestore(&pi->tx_lock, iflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
1182
1183
1184
1185
1186
1187
1188
  	return rc;
  }
  
  /*
   * This is the driver's interrupt handler.  To avoid a race, we first clear
   * the interrupt, then handle any completed Rx/Tx descriptors.  When done
   * handling those descriptors, we restart the Rx/Tx engines if they're stopped.
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1189
  static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
  {
  	struct mpsc_port_info *pi = dev_id;
  	ulong iflags;
  	int rc = IRQ_NONE;
  
  	pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Received
  ",pi->port.line);
  
  	spin_lock_irqsave(&pi->port.lock, iflags);
  	mpsc_sdma_intr_ack(pi);
bf7f5ee36   Viresh Kumar   tty: serial: mpsc...
1200
  	if (mpsc_rx_intr(pi, &iflags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
  		rc = IRQ_HANDLED;
  	if (mpsc_tx_intr(pi))
  		rc = IRQ_HANDLED;
  	spin_unlock_irqrestore(&pi->port.lock, iflags);
  
  	pr_debug("mpsc_sdma_intr[%d]: SDMA Interrupt Handled
  ", pi->port.line);
  	return rc;
  }
  
  /*
   ******************************************************************************
   *
   * serial_core.c Interface routines
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1218
  static uint mpsc_tx_empty(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1220
1221
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
1224
1225
1226
1227
1228
1229
1230
  	ulong iflags;
  	uint rc;
  
  	spin_lock_irqsave(&pi->port.lock, iflags);
  	rc = mpsc_sdma_tx_active(pi) ? 0 : TIOCSER_TEMT;
  	spin_unlock_irqrestore(&pi->port.lock, iflags);
  
  	return rc;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1231
  static void mpsc_set_mctrl(struct uart_port *port, uint mctrl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
  {
  	/* Have no way to set modem control lines AFAICT */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1235
  static uint mpsc_get_mctrl(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1237
1238
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
  	u32 mflags, status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240

2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1241
1242
  	status = (pi->mirror_regs) ? pi->MPSC_CHR_10_m
  		: readl(pi->mpsc_base + MPSC_CHR_10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
1246
1247
1248
1249
1250
1251
  
  	mflags = 0;
  	if (status & 0x1)
  		mflags |= TIOCM_CTS;
  	if (status & 0x2)
  		mflags |= TIOCM_CAR;
  
  	return mflags | TIOCM_DSR;	/* No way to tell if DSR asserted */
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1252
  static void mpsc_stop_tx(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1254
1255
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256

b129a8ccd   Russell King   [SERIAL] Clean up...
1257
1258
  	pr_debug("mpsc_stop_tx[%d]
  ", port->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
  
  	mpsc_freeze(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1262
  static void mpsc_start_tx(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1264
1265
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1733310bb   Dave Jiang   MPSC serial drive...
1266
1267
1268
  	unsigned long iflags;
  
  	spin_lock_irqsave(&pi->tx_lock, iflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
1270
1271
1272
  
  	mpsc_unfreeze(pi);
  	mpsc_copy_tx_data(pi);
  	mpsc_sdma_start_tx(pi);
1733310bb   Dave Jiang   MPSC serial drive...
1273
  	spin_unlock_irqrestore(&pi->tx_lock, iflags);
b129a8ccd   Russell King   [SERIAL] Clean up...
1274
1275
  	pr_debug("mpsc_start_tx[%d]
  ", port->line);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1277
  static void mpsc_start_rx(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
1283
1284
1285
  {
  	pr_debug("mpsc_start_rx[%d]: Starting...
  ", pi->port.line);
  
  	if (pi->rcv_data) {
  		mpsc_enter_hunt(pi);
  		mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1287
  static void mpsc_stop_rx(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1289
1290
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
1292
1293
  
  	pr_debug("mpsc_stop_rx[%d]: Stopping...
  ", port->line);
6c1ead5e7   Carlos Sanchez   serial: MPSC: Rem...
1294
1295
1296
1297
1298
  	if (pi->mirror_regs) {
  		writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA,
  				pi->mpsc_base + MPSC_CHR_2);
  		/* Erratum prevents reading CHR_2 so just delay for a while */
  		udelay(100);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1299
  	} else {
6c1ead5e7   Carlos Sanchez   serial: MPSC: Rem...
1300
  		writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1301
  				pi->mpsc_base + MPSC_CHR_2);
6c1ead5e7   Carlos Sanchez   serial: MPSC: Rem...
1302
1303
1304
1305
  
  		while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA)
  			udelay(10);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
  	mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1307
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1308
  static void mpsc_break_ctl(struct uart_port *port, int ctl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1310
1311
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
  	ulong	flags;
  	u32	v;
  
  	v = ctl ? 0x00ff0000 : 0;
  
  	spin_lock_irqsave(&pi->port.lock, flags);
  	if (pi->mirror_regs)
  		pi->MPSC_CHR_1_m = v;
  	writel(v, pi->mpsc_base + MPSC_CHR_1);
  	spin_unlock_irqrestore(&pi->port.lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1323
  static int mpsc_startup(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1325
1326
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
  	u32 flag = 0;
  	int rc;
  
  	pr_debug("mpsc_startup[%d]: Starting up MPSC, irq: %d
  ",
  		port->line, pi->port.irq);
  
  	if ((rc = mpsc_make_ready(pi)) == 0) {
  		/* Setup IRQ handler */
  		mpsc_sdma_intr_ack(pi);
  
  		/* If irq's are shared, need to set flag */
  		if (mpsc_ports[0].port.irq == mpsc_ports[1].port.irq)
40663cc7f   Thomas Gleixner   [PATCH] irq-flags...
1340
  			flag = IRQF_SHARED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
  
  		if (request_irq(pi->port.irq, mpsc_sdma_intr, flag,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1343
  					"mpsc-sdma", pi))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
  			printk(KERN_ERR "MPSC: Can't get SDMA IRQ %d
  ",
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1346
  					pi->port.irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
1348
  
  		mpsc_sdma_intr_unmask(pi, 0xf);
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1349
1350
  		mpsc_sdma_set_rx_ring(pi, (struct mpsc_rx_desc *)(pi->rxr_p
  					+ (pi->rxr_posn * MPSC_RXRE_SIZE)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
1352
1353
1354
  	}
  
  	return rc;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1355
  static void mpsc_shutdown(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1357
1358
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
1362
1363
1364
  
  	pr_debug("mpsc_shutdown[%d]: Shutting down MPSC
  ", port->line);
  
  	mpsc_sdma_stop(pi);
  	free_irq(pi->port.irq, pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1366
  static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios,
606d099cd   Alan Cox   [PATCH] tty: swit...
1367
  		 struct ktermios *old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1369
1370
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
1373
  	u32 baud;
  	ulong flags;
  	u32 chr_bits, stop_bits, par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
  	switch (termios->c_cflag & CSIZE) {
  	case CS5:
  		chr_bits = MPSC_MPCR_CL_5;
  		break;
  	case CS6:
  		chr_bits = MPSC_MPCR_CL_6;
  		break;
  	case CS7:
  		chr_bits = MPSC_MPCR_CL_7;
  		break;
  	case CS8:
  	default:
  		chr_bits = MPSC_MPCR_CL_8;
  		break;
  	}
  
  	if (termios->c_cflag & CSTOPB)
  		stop_bits = MPSC_MPCR_SBL_2;
  	else
  		stop_bits = MPSC_MPCR_SBL_1;
  
  	par = MPSC_CHR_2_PAR_EVEN;
  	if (termios->c_cflag & PARENB)
  		if (termios->c_cflag & PARODD)
  			par = MPSC_CHR_2_PAR_ODD;
  #ifdef	CMSPAR
  		if (termios->c_cflag & CMSPAR) {
  			if (termios->c_cflag & PARODD)
  				par = MPSC_CHR_2_PAR_MARK;
  			else
  				par = MPSC_CHR_2_PAR_SPACE;
  		}
  #endif
  
  	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk);
  
  	spin_lock_irqsave(&pi->port.lock, flags);
  
  	uart_update_timeout(port, termios->c_cflag, baud);
  
  	mpsc_set_char_length(pi, chr_bits);
  	mpsc_set_stop_bit_length(pi, stop_bits);
  	mpsc_set_parity(pi, par);
  	mpsc_set_baudrate(pi, baud);
  
  	/* Characters/events to read */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
1421
1422
  	pi->port.read_status_mask = SDMA_DESC_CMDSTAT_OR;
  
  	if (termios->c_iflag & INPCK)
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1423
1424
  		pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_PE
  			| SDMA_DESC_CMDSTAT_FR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425

ef8b9ddcb   Peter Hurley   serial: Fix IGNBR...
1426
  	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
1428
1429
1430
1431
1432
  		pi->port.read_status_mask |= SDMA_DESC_CMDSTAT_BR;
  
  	/* Characters/events to ignore */
  	pi->port.ignore_status_mask = 0;
  
  	if (termios->c_iflag & IGNPAR)
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1433
1434
  		pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_PE
  			| SDMA_DESC_CMDSTAT_FR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
1436
1437
1438
1439
1440
1441
  
  	if (termios->c_iflag & IGNBRK) {
  		pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_BR;
  
  		if (termios->c_iflag & IGNPAR)
  			pi->port.ignore_status_mask |= SDMA_DESC_CMDSTAT_OR;
  	}
5797ae364   Stephane Chazelas   serial: MPSC: Sto...
1442
1443
1444
1445
1446
1447
1448
  	if ((termios->c_cflag & CREAD)) {
  		if (!pi->rcv_data) {
  			pi->rcv_data = 1;
  			mpsc_start_rx(pi);
  		}
  	} else if (pi->rcv_data) {
  		mpsc_stop_rx(port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449
  		pi->rcv_data = 0;
5797ae364   Stephane Chazelas   serial: MPSC: Sto...
1450
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
1452
  
  	spin_unlock_irqrestore(&pi->port.lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1454
  static const char *mpsc_type(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
1456
1457
1458
1459
  {
  	pr_debug("mpsc_type[%d]: port type: %s
  ", port->line,MPSC_DRIVER_NAME);
  	return MPSC_DRIVER_NAME;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1460
  static int mpsc_request_port(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
1463
1464
  {
  	/* Should make chip/platform specific call */
  	return 0;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1465
  static void mpsc_release_port(struct uart_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1467
1468
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
1470
1471
1472
1473
1474
  
  	if (pi->ready) {
  		mpsc_uninit_rings(pi);
  		mpsc_free_ring_mem(pi);
  		pi->ready = 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1476
  static void mpsc_config_port(struct uart_port *port, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1477
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1479
  static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1481
1482
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
  	int rc = 0;
  
  	pr_debug("mpsc_verify_port[%d]: Verifying port data
  ", pi->port.line);
  
  	if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPSC)
  		rc = -EINVAL;
  	else if (pi->port.irq != ser->irq)
  		rc = -EINVAL;
  	else if (ser->io_type != SERIAL_IO_MEM)
  		rc = -EINVAL;
  	else if (pi->port.uartclk / 16 != ser->baud_base) /* Not sure */
  		rc = -EINVAL;
  	else if ((void *)pi->port.mapbase != ser->iomem_base)
  		rc = -EINVAL;
  	else if (pi->port.iobase != ser->port)
  		rc = -EINVAL;
  	else if (ser->hub6 != 0)
  		rc = -EINVAL;
  
  	return rc;
  }
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
  #ifdef CONFIG_CONSOLE_POLL
  /* Serial polling routines for writing and reading from the uart while
   * in an interrupt or debug context.
   */
  
  static char poll_buf[2048];
  static int poll_ptr;
  static int poll_cnt;
  static void mpsc_put_poll_char(struct uart_port *port,
  							   unsigned char c);
  
  static int mpsc_get_poll_char(struct uart_port *port)
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1518
1519
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
  	struct mpsc_rx_desc *rxre;
  	u32	cmdstat, bytes_in, i;
  	u8	*bp;
  
  	if (!serial_polled)
  		serial_polled = 1;
  
  	pr_debug("mpsc_rx_intr[%d]: Handling Rx intr
  ", pi->port.line);
  
  	if (poll_cnt) {
  		poll_cnt--;
  		return poll_buf[poll_ptr++];
  	}
  	poll_ptr = 0;
  	poll_cnt = 0;
  
  	while (poll_cnt == 0) {
  		rxre = (struct mpsc_rx_desc *)(pi->rxr +
  		       (pi->rxr_posn*MPSC_RXRE_SIZE));
  		dma_cache_sync(pi->port.dev, (void *)rxre,
  			       MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			invalidate_dcache_range((ulong)rxre,
  			(ulong)rxre + MPSC_RXRE_SIZE);
  #endif
  		/*
  		 * Loop through Rx descriptors handling ones that have
  		 * been completed.
  		 */
  		while (poll_cnt == 0 &&
  		       !((cmdstat = be32_to_cpu(rxre->cmdstat)) &
  			 SDMA_DESC_CMDSTAT_O)){
  			bytes_in = be16_to_cpu(rxre->bytecnt);
  			bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
  			dma_cache_sync(pi->port.dev, (void *) bp,
  				       MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  				invalidate_dcache_range((ulong)bp,
  					(ulong)bp + MPSC_RXBE_SIZE);
  #endif
  			if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
  			 SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
  				!(cmdstat & pi->port.ignore_status_mask)) {
  				poll_buf[poll_cnt] = *bp;
  				poll_cnt++;
  			} else {
  				for (i = 0; i < bytes_in; i++) {
  					poll_buf[poll_cnt] = *bp++;
  					poll_cnt++;
  				}
  				pi->port.icount.rx += bytes_in;
  			}
  			rxre->bytecnt = cpu_to_be16(0);
  			wmb();
  			rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
  						    SDMA_DESC_CMDSTAT_EI |
  						    SDMA_DESC_CMDSTAT_F |
  						    SDMA_DESC_CMDSTAT_L);
  			wmb();
  			dma_cache_sync(pi->port.dev, (void *)rxre,
  				       MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  				flush_dcache_range((ulong)rxre,
  					   (ulong)rxre + MPSC_RXRE_SIZE);
  #endif
  
  			/* Advance to next descriptor */
  			pi->rxr_posn = (pi->rxr_posn + 1) &
  				(MPSC_RXR_ENTRIES - 1);
  			rxre = (struct mpsc_rx_desc *)(pi->rxr +
  				       (pi->rxr_posn * MPSC_RXRE_SIZE));
  			dma_cache_sync(pi->port.dev, (void *)rxre,
  				       MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  				invalidate_dcache_range((ulong)rxre,
  						(ulong)rxre + MPSC_RXRE_SIZE);
  #endif
  		}
  
  		/* Restart rx engine, if its stopped */
  		if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
  			mpsc_start_rx(pi);
  	}
  	if (poll_cnt) {
  		poll_cnt--;
  		return poll_buf[poll_ptr++];
  	}
  
  	return 0;
  }
  
  
  static void mpsc_put_poll_char(struct uart_port *port,
  			 unsigned char c)
  {
22d4d44c4   Fabian Frederick   serial: mpsc: use...
1620
1621
  	struct mpsc_port_info *pi =
  		container_of(port, struct mpsc_port_info, port);
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
  	u32 data;
  
  	data = readl(pi->mpsc_base + MPSC_MPCR);
  	writeb(c, pi->mpsc_base + MPSC_CHR_1);
  	mb();
  	data = readl(pi->mpsc_base + MPSC_CHR_2);
  	data |= MPSC_CHR_2_TTCS;
  	writel(data, pi->mpsc_base + MPSC_CHR_2);
  	mb();
  
  	while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
  
  static struct uart_ops mpsc_pops = {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1637
1638
1639
1640
1641
1642
  	.tx_empty	= mpsc_tx_empty,
  	.set_mctrl	= mpsc_set_mctrl,
  	.get_mctrl	= mpsc_get_mctrl,
  	.stop_tx	= mpsc_stop_tx,
  	.start_tx	= mpsc_start_tx,
  	.stop_rx	= mpsc_stop_rx,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1643
1644
1645
1646
1647
1648
1649
1650
1651
  	.break_ctl	= mpsc_break_ctl,
  	.startup	= mpsc_startup,
  	.shutdown	= mpsc_shutdown,
  	.set_termios	= mpsc_set_termios,
  	.type		= mpsc_type,
  	.release_port	= mpsc_release_port,
  	.request_port	= mpsc_request_port,
  	.config_port	= mpsc_config_port,
  	.verify_port	= mpsc_verify_port,
3b216c9ed   Jason Wessel   kgdb: kgdboc cons...
1652
1653
1654
1655
  #ifdef CONFIG_CONSOLE_POLL
  	.poll_get_char = mpsc_get_poll_char,
  	.poll_put_char = mpsc_put_poll_char,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
  };
  
  /*
   ******************************************************************************
   *
   * Console Interface Routines
   *
   ******************************************************************************
   */
  
  #ifdef CONFIG_SERIAL_MPSC_CONSOLE
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1667
  static void mpsc_console_write(struct console *co, const char *s, uint count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
1669
1670
1671
  {
  	struct mpsc_port_info *pi = &mpsc_ports[co->index];
  	u8 *bp, *dp, add_cr = 0;
  	int i;
1733310bb   Dave Jiang   MPSC serial drive...
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
  	unsigned long iflags;
  
  	spin_lock_irqsave(&pi->tx_lock, iflags);
  
  	while (pi->txr_head != pi->txr_tail) {
  		while (mpsc_sdma_tx_active(pi))
  			udelay(100);
  		mpsc_sdma_intr_ack(pi);
  		mpsc_tx_intr(pi);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
  
  	while (mpsc_sdma_tx_active(pi))
  		udelay(100);
  
  	while (count > 0) {
  		bp = dp = pi->txb + (pi->txr_head * MPSC_TXBE_SIZE);
  
  		for (i = 0; i < MPSC_TXBE_SIZE; i++) {
  			if (count == 0)
  				break;
  
  			if (add_cr) {
  				*(dp++) = '\r';
  				add_cr = 0;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1696
  			} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
  				*(dp++) = *s;
  
  				if (*(s++) == '
  ') { /* add '\r' after '
  ' */
  					add_cr = 1;
  					count++;
  				}
  			}
  
  			count--;
  		}
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1709
1710
  		dma_cache_sync(pi->port.dev, (void *)bp, MPSC_TXBE_SIZE,
  				DMA_BIDIRECTIONAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1711
1712
1713
  #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
  		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
  			flush_dcache_range((ulong)bp,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1714
  					(ulong)bp + MPSC_TXBE_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
  #endif
  		mpsc_setup_tx_desc(pi, i, 0);
  		pi->txr_head = (pi->txr_head + 1) & (MPSC_TXR_ENTRIES - 1);
  		mpsc_sdma_start_tx(pi);
  
  		while (mpsc_sdma_tx_active(pi))
  			udelay(100);
  
  		pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1);
  	}
1733310bb   Dave Jiang   MPSC serial drive...
1725
  	spin_unlock_irqrestore(&pi->tx_lock, iflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1727
  static int __init mpsc_console_setup(struct console *co, char *options)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
  {
  	struct mpsc_port_info *pi;
  	int baud, bits, parity, flow;
  
  	pr_debug("mpsc_console_setup[%d]: options: %s
  ", co->index, options);
  
  	if (co->index >= MPSC_NUM_CTLRS)
  		co->index = 0;
  
  	pi = &mpsc_ports[co->index];
  
  	baud = pi->default_baud;
  	bits = pi->default_bits;
  	parity = pi->default_parity;
  	flow = pi->default_flow;
  
  	if (!pi->port.ops)
  		return -ENODEV;
  
  	spin_lock_init(&pi->port.lock);	/* Temporary fix--copied from 8250.c */
  
  	if (options)
  		uart_parse_options(options, &baud, &parity, &bits, &flow);
  
  	return uart_set_options(&pi->port, co, baud, parity, bits, flow);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
  static struct console mpsc_console = {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1756
1757
1758
1759
1760
1761
1762
  	.name	= MPSC_DEV_NAME,
  	.write	= mpsc_console_write,
  	.device	= uart_console_device,
  	.setup	= mpsc_console_setup,
  	.flags	= CON_PRINTBUFFER,
  	.index	= -1,
  	.data	= &mpsc_reg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
  };
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1764
  static int __init mpsc_late_console_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
  {
  	pr_debug("mpsc_late_console_init: Enter
  ");
  
  	if (!(mpsc_console.flags & CON_ENABLED))
  		register_console(&mpsc_console);
  	return 0;
  }
  
  late_initcall(mpsc_late_console_init);
  
  #define MPSC_CONSOLE	&mpsc_console
  #else
  #define MPSC_CONSOLE	NULL
  #endif
  /*
   ******************************************************************************
   *
   * Dummy Platform Driver to extract & map shared register regions
   *
   ******************************************************************************
   */
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1787
  static void mpsc_resource_err(char *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
1789
1790
  {
  	printk(KERN_WARNING "MPSC: Platform device resource error in %s
  ", s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1792
  static int mpsc_shared_map_regs(struct platform_device *pd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
1794
1795
1796
  {
  	struct resource	*r;
  
  	if ((r = platform_get_resource(pd, IORESOURCE_MEM,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1797
1798
1799
1800
  					MPSC_ROUTING_BASE_ORDER))
  			&& request_mem_region(r->start,
  				MPSC_ROUTING_REG_BLOCK_SIZE,
  				"mpsc_routing_regs")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  		mpsc_shared_regs.mpsc_routing_base = ioremap(r->start,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1802
  				MPSC_ROUTING_REG_BLOCK_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
  		mpsc_shared_regs.mpsc_routing_base_p = r->start;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1804
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
1806
1807
1808
1809
  		mpsc_resource_err("MPSC routing base");
  		return -ENOMEM;
  	}
  
  	if ((r = platform_get_resource(pd, IORESOURCE_MEM,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1810
1811
1812
1813
  					MPSC_SDMA_INTR_BASE_ORDER))
  			&& request_mem_region(r->start,
  				MPSC_SDMA_INTR_REG_BLOCK_SIZE,
  				"sdma_intr_regs")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
1815
1816
  		mpsc_shared_regs.sdma_intr_base = ioremap(r->start,
  			MPSC_SDMA_INTR_REG_BLOCK_SIZE);
  		mpsc_shared_regs.sdma_intr_base_p = r->start;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1817
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
  		iounmap(mpsc_shared_regs.mpsc_routing_base);
  		release_mem_region(mpsc_shared_regs.mpsc_routing_base_p,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1820
  				MPSC_ROUTING_REG_BLOCK_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
1822
1823
1824
1825
1826
  		mpsc_resource_err("SDMA intr base");
  		return -ENOMEM;
  	}
  
  	return 0;
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1827
  static void mpsc_shared_unmap_regs(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1828
  {
1fba6a594   Jiri Slaby   TTY: serial/mpsc,...
1829
  	if (mpsc_shared_regs.mpsc_routing_base) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
  		iounmap(mpsc_shared_regs.mpsc_routing_base);
  		release_mem_region(mpsc_shared_regs.mpsc_routing_base_p,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1832
  				MPSC_ROUTING_REG_BLOCK_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
  	}
1fba6a594   Jiri Slaby   TTY: serial/mpsc,...
1834
  	if (mpsc_shared_regs.sdma_intr_base) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1835
1836
  		iounmap(mpsc_shared_regs.sdma_intr_base);
  		release_mem_region(mpsc_shared_regs.sdma_intr_base_p,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1837
  				MPSC_SDMA_INTR_REG_BLOCK_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
  	}
2c6e75999   Al Viro   [PATCH] ppc annot...
1839
1840
  	mpsc_shared_regs.mpsc_routing_base = NULL;
  	mpsc_shared_regs.sdma_intr_base = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
1842
1843
  
  	mpsc_shared_regs.mpsc_routing_base_p = 0;
  	mpsc_shared_regs.sdma_intr_base_p = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1845
  static int mpsc_shared_drv_probe(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
  	struct mpsc_shared_pdata	*pdata;
bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1848
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849

bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
  	if (dev->id != 0)
  		return -ENODEV;
  
  	rc = mpsc_shared_map_regs(dev);
  	if (rc)
  		return rc;
  
  	pdata = dev_get_platdata(&dev->dev);
  
  	mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val;
  	mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val;
  	mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val;
  	mpsc_shared_regs.SDMA_INTR_CAUSE_m = pdata->intr_cause_val;
  	mpsc_shared_regs.SDMA_INTR_MASK_m = pdata->intr_mask_val;
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1867
  static int mpsc_shared_drv_remove(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
  {
bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1869
1870
  	if (dev->id != 0)
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871

bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1872
1873
1874
1875
1876
1877
  	mpsc_shared_unmap_regs();
  	mpsc_shared_regs.MPSC_MRR_m = 0;
  	mpsc_shared_regs.MPSC_RCRR_m = 0;
  	mpsc_shared_regs.MPSC_TCRR_m = 0;
  	mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0;
  	mpsc_shared_regs.SDMA_INTR_MASK_m = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878

bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1879
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
  }
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
1881
  static struct platform_driver mpsc_shared_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
1883
  	.probe	= mpsc_shared_drv_probe,
  	.remove	= mpsc_shared_drv_remove,
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
1884
  	.driver	= {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1885
  		.name	= MPSC_SHARED_NAME,
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
1886
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
  };
  
  /*
   ******************************************************************************
   *
   * Driver Interface Routines
   *
   ******************************************************************************
   */
  static struct uart_driver mpsc_reg = {
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1897
1898
1899
1900
1901
1902
1903
  	.owner		= THIS_MODULE,
  	.driver_name	= MPSC_DRIVER_NAME,
  	.dev_name	= MPSC_DEV_NAME,
  	.major		= MPSC_MAJOR,
  	.minor		= MPSC_MINOR_START,
  	.nr		= MPSC_NUM_CTLRS,
  	.cons		= MPSC_CONSOLE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
  };
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1905
1906
  static int mpsc_drv_map_regs(struct mpsc_port_info *pi,
  		struct platform_device *pd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
  {
  	struct resource	*r;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1909
1910
1911
  	if ((r = platform_get_resource(pd, IORESOURCE_MEM, MPSC_BASE_ORDER))
  			&& request_mem_region(r->start, MPSC_REG_BLOCK_SIZE,
  			"mpsc_regs")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
  		pi->mpsc_base = ioremap(r->start, MPSC_REG_BLOCK_SIZE);
  		pi->mpsc_base_p = r->start;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1914
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1915
  		mpsc_resource_err("MPSC base");
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1916
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
1918
1919
  	}
  
  	if ((r = platform_get_resource(pd, IORESOURCE_MEM,
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1920
1921
1922
  					MPSC_SDMA_BASE_ORDER))
  			&& request_mem_region(r->start,
  				MPSC_SDMA_REG_BLOCK_SIZE, "sdma_regs")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
1924
  		pi->sdma_base = ioremap(r->start,MPSC_SDMA_REG_BLOCK_SIZE);
  		pi->sdma_base_p = r->start;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1925
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  		mpsc_resource_err("SDMA base");
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1927
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
1929
1930
  	}
  
  	if ((r = platform_get_resource(pd,IORESOURCE_MEM,MPSC_BRG_BASE_ORDER))
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1931
1932
  			&& request_mem_region(r->start,
  				MPSC_BRG_REG_BLOCK_SIZE, "brg_regs")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1933
1934
  		pi->brg_base = ioremap(r->start, MPSC_BRG_REG_BLOCK_SIZE);
  		pi->brg_base_p = r->start;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1935
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
  		mpsc_resource_err("BRG base");
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1937
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
  	return 0;
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1940
1941
  
  err:
bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
1942
1943
1944
1945
1946
1947
1948
1949
  	if (pi->sdma_base) {
  		iounmap(pi->sdma_base);
  		pi->sdma_base = NULL;
  	}
  	if (pi->mpsc_base) {
  		iounmap(pi->mpsc_base);
  		pi->mpsc_base = NULL;
  	}
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1950
  	return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1952
  static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1953
  {
1fba6a594   Jiri Slaby   TTY: serial/mpsc,...
1954
  	if (pi->mpsc_base) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1955
1956
1957
  		iounmap(pi->mpsc_base);
  		release_mem_region(pi->mpsc_base_p, MPSC_REG_BLOCK_SIZE);
  	}
1fba6a594   Jiri Slaby   TTY: serial/mpsc,...
1958
  	if (pi->sdma_base) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1959
1960
1961
  		iounmap(pi->sdma_base);
  		release_mem_region(pi->sdma_base_p, MPSC_SDMA_REG_BLOCK_SIZE);
  	}
1fba6a594   Jiri Slaby   TTY: serial/mpsc,...
1962
  	if (pi->brg_base) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
1964
1965
  		iounmap(pi->brg_base);
  		release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE);
  	}
2c6e75999   Al Viro   [PATCH] ppc annot...
1966
1967
1968
  	pi->mpsc_base = NULL;
  	pi->sdma_base = NULL;
  	pi->brg_base = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
1970
1971
1972
  
  	pi->mpsc_base_p = 0;
  	pi->sdma_base_p = 0;
  	pi->brg_base_p = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1973
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
1974
1975
  static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
  		struct platform_device *pd, int num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1976
1977
  {
  	struct mpsc_pdata	*pdata;
5c02fab62   Jingoo Han   serial: mpsc: Rem...
1978
  	pdata = dev_get_platdata(&pd->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
  
  	pi->port.uartclk = pdata->brg_clk_freq;
  	pi->port.iotype = UPIO_MEM;
  	pi->port.line = num;
  	pi->port.type = PORT_MPSC;
  	pi->port.fifosize = MPSC_TXBE_SIZE;
  	pi->port.membase = pi->mpsc_base;
  	pi->port.mapbase = (ulong)pi->mpsc_base;
  	pi->port.ops = &mpsc_pops;
  
  	pi->mirror_regs = pdata->mirror_regs;
  	pi->cache_mgmt = pdata->cache_mgmt;
  	pi->brg_can_tune = pdata->brg_can_tune;
  	pi->brg_clk_src = pdata->brg_clk_src;
  	pi->mpsc_max_idle = pdata->max_idle;
  	pi->default_baud = pdata->default_baud;
  	pi->default_bits = pdata->default_bits;
  	pi->default_parity = pdata->default_parity;
  	pi->default_flow = pdata->default_flow;
  
  	/* Initial values of mirrored regs */
  	pi->MPSC_CHR_1_m = pdata->chr_1_val;
  	pi->MPSC_CHR_2_m = pdata->chr_2_val;
  	pi->MPSC_CHR_10_m = pdata->chr_10_val;
  	pi->MPSC_MPCR_m = pdata->mpcr_val;
  	pi->BRG_BCR_m = pdata->bcr_val;
  
  	pi->shared_regs = &mpsc_shared_regs;
  
  	pi->port.irq = platform_get_irq(pd, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2009
  }
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
2010
  static int mpsc_drv_probe(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
  {
bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
  	struct mpsc_port_info *pi;
  	int rc;
  
  	dev_dbg(&dev->dev, "mpsc_drv_probe: Adding MPSC %d
  ", dev->id);
  
  	if (dev->id >= MPSC_NUM_CTLRS)
  		return -ENODEV;
  
  	pi = &mpsc_ports[dev->id];
  
  	rc = mpsc_drv_map_regs(pi, dev);
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026

bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
  	mpsc_drv_get_platform_data(pi, dev, dev->id);
  	pi->port.dev = &dev->dev;
  
  	rc = mpsc_make_ready(pi);
  	if (rc)
  		goto err_unmap;
  
  	spin_lock_init(&pi->tx_lock);
  	rc = uart_add_one_port(&mpsc_reg, &pi->port);
  	if (rc)
  		goto err_relport;
  
  	return 0;
  err_relport:
  	mpsc_release_port(&pi->port);
  err_unmap:
  	mpsc_drv_unmap_regs(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
2045
  	return rc;
  }
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
2046
  static struct platform_driver mpsc_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047
  	.probe	= mpsc_drv_probe,
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
2048
  	.driver	= {
6200cbaf6   Paul Gortmaker   tty: disable unbi...
2049
2050
  		.name			= MPSC_CTLR_NAME,
  		.suppress_bind_attrs	= true,
3ae5eaec1   Russell King   [DRIVER MODEL] Co...
2051
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
  };
2e89db75a   Mark A. Greer   serial: MPSC: Fix...
2053
  static int __init mpsc_drv_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
2055
  {
  	int	rc;
d87a6d951   Adrian Bunk   drivers/serial/: ...
2056
2057
  	printk(KERN_INFO "Serial: MPSC driver
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
2059
2060
  
  	memset(mpsc_ports, 0, sizeof(mpsc_ports));
  	memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs));
f2908f70c   Greg Kroah-Hartman   tty: mpsc.c: move...
2061
  	rc = uart_register_driver(&mpsc_reg);
bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
2062
2063
2064
2065
2066
2067
  	if (rc)
  		return rc;
  
  	rc = platform_driver_register(&mpsc_shared_driver);
  	if (rc)
  		goto err_unreg_uart;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068

bca1481ec   Jiri Slaby   TTY: serial/mpsc,...
2069
2070
2071
2072
2073
2074
2075
2076
2077
  	rc = platform_driver_register(&mpsc_driver);
  	if (rc)
  		goto err_unreg_plat;
  
  	return 0;
  err_unreg_plat:
  	platform_driver_unregister(&mpsc_shared_driver);
  err_unreg_uart:
  	uart_unregister_driver(&mpsc_reg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2079
  }
128a3d060   Paul Gortmaker   drivers/tty: make...
2080
  device_initcall(mpsc_drv_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2081

128a3d060   Paul Gortmaker   drivers/tty: make...
2082
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2083
  MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
d87a6d951   Adrian Bunk   drivers/serial/: ...
2084
  MODULE_DESCRIPTION("Generic Marvell MPSC serial/UART driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
  MODULE_LICENSE("GPL");
128a3d060   Paul Gortmaker   drivers/tty: make...
2086
  */