OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ps3/] [ps3-vuart.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  PS3 virtual uart
3
 *
4
 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
5
 *  Copyright 2006 Sony Corp.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; version 2 of the License.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
#include <linux/kernel.h>
22
#include <linux/module.h>
23
#include <linux/interrupt.h>
24
#include <linux/workqueue.h>
25
#include <linux/bitops.h>
26
#include <asm/ps3.h>
27
 
28
#include <asm/firmware.h>
29
#include <asm/lv1call.h>
30
 
31
#include "vuart.h"
32
 
33
MODULE_AUTHOR("Sony Corporation");
34
MODULE_LICENSE("GPL v2");
35
MODULE_DESCRIPTION("PS3 vuart");
36
 
37
/**
38
 * vuart - An inter-partition data link service.
39
 *  port 0: PS3 AV Settings.
40
 *  port 2: PS3 System Manager.
41
 *
42
 * The vuart provides a bi-directional byte stream data link between logical
43
 * partitions.  Its primary role is as a communications link between the guest
44
 * OS and the system policy module.  The current HV does not support any
45
 * connections other than those listed.
46
 */
47
 
48
enum {PORT_COUNT = 3,};
49
 
50
enum vuart_param {
51
        PARAM_TX_TRIGGER = 0,
52
        PARAM_RX_TRIGGER = 1,
53
        PARAM_INTERRUPT_MASK = 2,
54
        PARAM_RX_BUF_SIZE = 3, /* read only */
55
        PARAM_RX_BYTES = 4, /* read only */
56
        PARAM_TX_BUF_SIZE = 5, /* read only */
57
        PARAM_TX_BYTES = 6, /* read only */
58
        PARAM_INTERRUPT_STATUS = 7, /* read only */
59
};
60
 
61
enum vuart_interrupt_bit {
62
        INTERRUPT_BIT_TX = 0,
63
        INTERRUPT_BIT_RX = 1,
64
        INTERRUPT_BIT_DISCONNECT = 2,
65
};
66
 
67
enum vuart_interrupt_mask {
68
        INTERRUPT_MASK_TX = 1,
69
        INTERRUPT_MASK_RX = 2,
70
        INTERRUPT_MASK_DISCONNECT = 4,
71
};
72
 
73
/**
74
 * struct ps3_vuart_port_priv - private vuart device data.
75
 */
76
 
77
struct ps3_vuart_port_priv {
78
        u64 interrupt_mask;
79
 
80
        struct {
81
                spinlock_t lock;
82
                struct list_head head;
83
        } tx_list;
84
        struct {
85
                struct ps3_vuart_work work;
86
                unsigned long bytes_held;
87
                spinlock_t lock;
88
                struct list_head head;
89
        } rx_list;
90
        struct ps3_vuart_stats stats;
91
};
92
 
93
static struct ps3_vuart_port_priv *to_port_priv(
94
        struct ps3_system_bus_device *dev)
95
{
96
        BUG_ON(!dev);
97
        BUG_ON(!dev->driver_priv);
98
        return (struct ps3_vuart_port_priv *)dev->driver_priv;
99
}
100
 
101
/**
102
 * struct ports_bmp - bitmap indicating ports needing service.
103
 *
104
 * A 256 bit read only bitmap indicating ports needing service.  Do not write
105
 * to these bits.  Must not cross a page boundary.
106
 */
107
 
108
struct ports_bmp {
109
        u64 status;
110
        u64 unused[3];
111
} __attribute__ ((aligned (32)));
112
 
113
#define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
114
static void __maybe_unused _dump_ports_bmp(
115
        const struct ports_bmp* bmp, const char* func, int line)
116
{
117
        pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
118
}
119
 
120
#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
121
static void __maybe_unused _dump_port_params(unsigned int port_number,
122
        const char* func, int line)
123
{
124
#if defined(DEBUG)
125
        static const char *strings[] = {
126
                "tx_trigger      ",
127
                "rx_trigger      ",
128
                "interrupt_mask  ",
129
                "rx_buf_size     ",
130
                "rx_bytes        ",
131
                "tx_buf_size     ",
132
                "tx_bytes        ",
133
                "interrupt_status",
134
        };
135
        int result;
136
        unsigned int i;
137
        u64 value;
138
 
139
        for (i = 0; i < ARRAY_SIZE(strings); i++) {
140
                result = lv1_get_virtual_uart_param(port_number, i, &value);
141
 
142
                if (result) {
143
                        pr_debug("%s:%d: port_%u: %s failed: %s\n", func, line,
144
                                port_number, strings[i], ps3_result(result));
145
                        continue;
146
                }
147
                pr_debug("%s:%d: port_%u: %s = %lxh\n",
148
                        func, line, port_number, strings[i], value);
149
        }
150
#endif
151
}
152
 
153
struct vuart_triggers {
154
        unsigned long rx;
155
        unsigned long tx;
156
};
157
 
158
int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
159
        struct vuart_triggers *trig)
160
{
161
        int result;
162
        unsigned long size;
163
        unsigned long val;
164
 
165
        result = lv1_get_virtual_uart_param(dev->port_number,
166
                PARAM_TX_TRIGGER, &trig->tx);
167
 
168
        if (result) {
169
                dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
170
                        __func__, __LINE__, ps3_result(result));
171
                return result;
172
        }
173
 
174
        result = lv1_get_virtual_uart_param(dev->port_number,
175
                PARAM_RX_BUF_SIZE, &size);
176
 
177
        if (result) {
178
                dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
179
                        __func__, __LINE__, ps3_result(result));
180
                return result;
181
        }
182
 
183
        result = lv1_get_virtual_uart_param(dev->port_number,
184
                PARAM_RX_TRIGGER, &val);
185
 
186
        if (result) {
187
                dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
188
                        __func__, __LINE__, ps3_result(result));
189
                return result;
190
        }
191
 
192
        trig->rx = size - val;
193
 
194
        dev_dbg(&dev->core, "%s:%d: tx %lxh, rx %lxh\n", __func__, __LINE__,
195
                trig->tx, trig->rx);
196
 
197
        return result;
198
}
199
 
200
int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
201
        unsigned int rx)
202
{
203
        int result;
204
        unsigned long size;
205
 
206
        result = lv1_set_virtual_uart_param(dev->port_number,
207
                PARAM_TX_TRIGGER, tx);
208
 
209
        if (result) {
210
                dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
211
                        __func__, __LINE__, ps3_result(result));
212
                return result;
213
        }
214
 
215
        result = lv1_get_virtual_uart_param(dev->port_number,
216
                PARAM_RX_BUF_SIZE, &size);
217
 
218
        if (result) {
219
                dev_dbg(&dev->core, "%s:%d: tx_buf_size failed: %s\n",
220
                        __func__, __LINE__, ps3_result(result));
221
                return result;
222
        }
223
 
224
        result = lv1_set_virtual_uart_param(dev->port_number,
225
                PARAM_RX_TRIGGER, size - rx);
226
 
227
        if (result) {
228
                dev_dbg(&dev->core, "%s:%d: rx_trigger failed: %s\n",
229
                        __func__, __LINE__, ps3_result(result));
230
                return result;
231
        }
232
 
233
        dev_dbg(&dev->core, "%s:%d: tx %xh, rx %xh\n", __func__, __LINE__,
234
                tx, rx);
235
 
236
        return result;
237
}
238
 
239
static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
240
        u64 *bytes_waiting)
241
{
242
        int result;
243
 
244
        result = lv1_get_virtual_uart_param(dev->port_number,
245
                PARAM_RX_BYTES, bytes_waiting);
246
 
247
        if (result)
248
                dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n",
249
                        __func__, __LINE__, ps3_result(result));
250
 
251
        dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__,
252
                *bytes_waiting);
253
        return result;
254
}
255
 
256
/**
257
 * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
258
 * @dev: The struct ps3_system_bus_device instance.
259
 * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
260
 */
261
 
262
static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
263
        unsigned long mask)
264
{
265
        int result;
266
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
267
 
268
        dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
269
 
270
        priv->interrupt_mask = mask;
271
 
272
        result = lv1_set_virtual_uart_param(dev->port_number,
273
                PARAM_INTERRUPT_MASK, priv->interrupt_mask);
274
 
275
        if (result)
276
                dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
277
                        __func__, __LINE__, ps3_result(result));
278
 
279
        return result;
280
}
281
 
282
static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
283
        unsigned long *status)
284
{
285
        int result;
286
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
287
        u64 tmp;
288
 
289
        result = lv1_get_virtual_uart_param(dev->port_number,
290
                PARAM_INTERRUPT_STATUS, &tmp);
291
 
292
        if (result)
293
                dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
294
                        __func__, __LINE__, ps3_result(result));
295
 
296
        *status = tmp & priv->interrupt_mask;
297
 
298
        dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
299
                __func__, __LINE__, priv->interrupt_mask, tmp, *status);
300
 
301
        return result;
302
}
303
 
304
int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
305
{
306
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
307
 
308
        return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
309
                : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
310
                | INTERRUPT_MASK_TX);
311
}
312
 
313
int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
314
{
315
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
316
 
317
        return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
318
                : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
319
                | INTERRUPT_MASK_RX);
320
}
321
 
322
int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
323
{
324
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
325
 
326
        return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
327
                : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
328
                | INTERRUPT_MASK_DISCONNECT);
329
}
330
 
331
int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
332
{
333
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
334
 
335
        return (priv->interrupt_mask & INTERRUPT_MASK_TX)
336
                ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
337
                & ~INTERRUPT_MASK_TX) : 0;
338
}
339
 
340
int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
341
{
342
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
343
 
344
        return (priv->interrupt_mask & INTERRUPT_MASK_RX)
345
                ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
346
                & ~INTERRUPT_MASK_RX) : 0;
347
}
348
 
349
int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
350
{
351
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
352
 
353
        return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
354
                ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
355
                & ~INTERRUPT_MASK_DISCONNECT) : 0;
356
}
357
 
358
/**
359
 * ps3_vuart_raw_write - Low level write helper.
360
 * @dev: The struct ps3_system_bus_device instance.
361
 *
362
 * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
363
 */
364
 
365
static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
366
        const void* buf, unsigned int bytes, unsigned long *bytes_written)
367
{
368
        int result;
369
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
370
 
371
        result = lv1_write_virtual_uart(dev->port_number,
372
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
373
 
374
        if (result) {
375
                dev_dbg(&dev->core, "%s:%d: lv1_write_virtual_uart failed: "
376
                        "%s\n", __func__, __LINE__, ps3_result(result));
377
                return result;
378
        }
379
 
380
        priv->stats.bytes_written += *bytes_written;
381
 
382
        dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
383
                *bytes_written, bytes, priv->stats.bytes_written);
384
 
385
        return result;
386
}
387
 
388
/**
389
 * ps3_vuart_raw_read - Low level read helper.
390
 * @dev: The struct ps3_system_bus_device instance.
391
 *
392
 * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
393
 */
394
 
395
static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
396
        unsigned int bytes, unsigned long *bytes_read)
397
{
398
        int result;
399
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
400
 
401
        dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
402
 
403
        result = lv1_read_virtual_uart(dev->port_number,
404
                ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
405
 
406
        if (result) {
407
                dev_dbg(&dev->core, "%s:%d: lv1_read_virtual_uart failed: %s\n",
408
                        __func__, __LINE__, ps3_result(result));
409
                return result;
410
        }
411
 
412
        priv->stats.bytes_read += *bytes_read;
413
 
414
        dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
415
                *bytes_read, bytes, priv->stats.bytes_read);
416
 
417
        return result;
418
}
419
 
420
/**
421
 * ps3_vuart_clear_rx_bytes - Discard bytes received.
422
 * @dev: The struct ps3_system_bus_device instance.
423
 * @bytes: Max byte count to discard, zero = all pending.
424
 *
425
 * Used to clear pending rx interrupt source.  Will not block.
426
 */
427
 
428
void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
429
        unsigned int bytes)
430
{
431
        int result;
432
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
433
        u64 bytes_waiting;
434
        void* tmp;
435
 
436
        result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting);
437
 
438
        BUG_ON(result);
439
 
440
        bytes = bytes ? min(bytes, (unsigned int)bytes_waiting) : bytes_waiting;
441
 
442
        dev_dbg(&dev->core, "%s:%d: %u\n", __func__, __LINE__, bytes);
443
 
444
        if (!bytes)
445
                return;
446
 
447
        /* Add some extra space for recently arrived data. */
448
 
449
        bytes += 128;
450
 
451
        tmp = kmalloc(bytes, GFP_KERNEL);
452
 
453
        if (!tmp)
454
                return;
455
 
456
        ps3_vuart_raw_read(dev, tmp, bytes, &bytes_waiting);
457
 
458
        kfree(tmp);
459
 
460
        /* Don't include these bytes in the stats. */
461
 
462
        priv->stats.bytes_read -= bytes_waiting;
463
}
464
EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
465
 
466
/**
467
 * struct list_buffer - An element for a port device fifo buffer list.
468
 */
469
 
470
struct list_buffer {
471
        struct list_head link;
472
        const unsigned char *head;
473
        const unsigned char *tail;
474
        unsigned long dbg_number;
475
        unsigned char data[];
476
};
477
 
478
/**
479
 * ps3_vuart_write - the entry point for writing data to a port
480
 * @dev: The struct ps3_system_bus_device instance.
481
 *
482
 * If the port is idle on entry as much of the incoming data is written to
483
 * the port as the port will accept.  Otherwise a list buffer is created
484
 * and any remaning incoming data is copied to that buffer.  The buffer is
485
 * then enqueued for transmision via the transmit interrupt.
486
 */
487
 
488
int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
489
        unsigned int bytes)
490
{
491
        static unsigned long dbg_number;
492
        int result;
493
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
494
        unsigned long flags;
495
        struct list_buffer *lb;
496
 
497
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
498
                bytes, bytes);
499
 
500
        spin_lock_irqsave(&priv->tx_list.lock, flags);
501
 
502
        if (list_empty(&priv->tx_list.head)) {
503
                unsigned long bytes_written;
504
 
505
                result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
506
 
507
                spin_unlock_irqrestore(&priv->tx_list.lock, flags);
508
 
509
                if (result) {
510
                        dev_dbg(&dev->core,
511
                                "%s:%d: ps3_vuart_raw_write failed\n",
512
                                __func__, __LINE__);
513
                        return result;
514
                }
515
 
516
                if (bytes_written == bytes) {
517
                        dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n",
518
                                __func__, __LINE__, bytes);
519
                        return 0;
520
                }
521
 
522
                bytes -= bytes_written;
523
                buf += bytes_written;
524
        } else
525
                spin_unlock_irqrestore(&priv->tx_list.lock, flags);
526
 
527
        lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
528
 
529
        if (!lb) {
530
                return -ENOMEM;
531
        }
532
 
533
        memcpy(lb->data, buf, bytes);
534
        lb->head = lb->data;
535
        lb->tail = lb->data + bytes;
536
        lb->dbg_number = ++dbg_number;
537
 
538
        spin_lock_irqsave(&priv->tx_list.lock, flags);
539
        list_add_tail(&lb->link, &priv->tx_list.head);
540
        ps3_vuart_enable_interrupt_tx(dev);
541
        spin_unlock_irqrestore(&priv->tx_list.lock, flags);
542
 
543
        dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
544
                __func__, __LINE__, lb->dbg_number, bytes);
545
 
546
        return 0;
547
}
548
EXPORT_SYMBOL_GPL(ps3_vuart_write);
549
 
550
/**
551
 * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
552
 * @dev: The struct ps3_system_bus_device instance.
553
 * @bytes_queued: Number of bytes queued to the buffer list.
554
 *
555
 * Must be called with priv->rx_list.lock held.
556
 */
557
 
558
static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
559
        u64 *bytes_queued)
560
{
561
        static unsigned long dbg_number;
562
        int result;
563
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
564
        struct list_buffer *lb;
565
        u64 bytes;
566
 
567
        *bytes_queued = 0;
568
 
569
        result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
570
        BUG_ON(result);
571
 
572
        if (result)
573
                return -EIO;
574
 
575
        if (!bytes)
576
                return 0;
577
 
578
        /* Add some extra space for recently arrived data. */
579
 
580
        bytes += 128;
581
 
582
        lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
583
 
584
        if (!lb)
585
                return -ENOMEM;
586
 
587
        ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
588
 
589
        lb->head = lb->data;
590
        lb->tail = lb->data + bytes;
591
        lb->dbg_number = ++dbg_number;
592
 
593
        list_add_tail(&lb->link, &priv->rx_list.head);
594
        priv->rx_list.bytes_held += bytes;
595
 
596
        dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
597
                __func__, __LINE__, lb->dbg_number, bytes);
598
 
599
        *bytes_queued = bytes;
600
 
601
        return 0;
602
}
603
 
604
/**
605
 * ps3_vuart_read - The entry point for reading data from a port.
606
 *
607
 * Queue data waiting at the port, and if enough bytes to satisfy the request
608
 * are held in the buffer list those bytes are dequeued and copied to the
609
 * caller's buffer.  Emptied list buffers are retiered.  If the request cannot
610
 * be statified by bytes held in the list buffers -EAGAIN is returned.
611
 */
612
 
613
int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
614
        unsigned int bytes)
615
{
616
        int result;
617
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
618
        unsigned long flags;
619
        struct list_buffer *lb, *n;
620
        unsigned long bytes_read;
621
 
622
        dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
623
                bytes, bytes);
624
 
625
        spin_lock_irqsave(&priv->rx_list.lock, flags);
626
 
627
        /* Queue rx bytes here for polled reads. */
628
 
629
        while (priv->rx_list.bytes_held < bytes) {
630
                u64 tmp;
631
 
632
                result = ps3_vuart_queue_rx_bytes(dev, &tmp);
633
                if (result || !tmp) {
634
                        dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
635
                                __func__, __LINE__,
636
                                bytes - priv->rx_list.bytes_held);
637
                        spin_unlock_irqrestore(&priv->rx_list.lock, flags);
638
                        return -EAGAIN;
639
                }
640
        }
641
 
642
        list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
643
                bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
644
 
645
                memcpy(buf, lb->head, bytes_read);
646
                buf += bytes_read;
647
                bytes -= bytes_read;
648
                priv->rx_list.bytes_held -= bytes_read;
649
 
650
                if (bytes_read < lb->tail - lb->head) {
651
                        lb->head += bytes_read;
652
                        dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
653
                                "bytes\n", __func__, __LINE__, lb->dbg_number,
654
                                bytes_read);
655
                        spin_unlock_irqrestore(&priv->rx_list.lock, flags);
656
                        return 0;
657
                }
658
 
659
                dev_dbg(&dev->core, "%s:%d: buf_%lu: free, dequeued %lxh "
660
                        "bytes\n", __func__, __LINE__, lb->dbg_number,
661
                        bytes_read);
662
 
663
                list_del(&lb->link);
664
                kfree(lb);
665
        }
666
 
667
        spin_unlock_irqrestore(&priv->rx_list.lock, flags);
668
        return 0;
669
}
670
EXPORT_SYMBOL_GPL(ps3_vuart_read);
671
 
672
/**
673
 * ps3_vuart_work - Asynchronous read handler.
674
 */
675
 
676
static void ps3_vuart_work(struct work_struct *work)
677
{
678
        struct ps3_system_bus_device *dev =
679
                ps3_vuart_work_to_system_bus_dev(work);
680
        struct ps3_vuart_port_driver *drv =
681
                ps3_system_bus_dev_to_vuart_drv(dev);
682
 
683
        BUG_ON(!drv);
684
        drv->work(dev);
685
}
686
 
687
int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
688
{
689
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
690
        unsigned long flags;
691
 
692
        if (priv->rx_list.work.trigger) {
693
                dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
694
                        __func__, __LINE__);
695
                return -EAGAIN;
696
        }
697
 
698
        BUG_ON(!bytes);
699
 
700
        PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
701
 
702
        spin_lock_irqsave(&priv->rx_list.lock, flags);
703
        if (priv->rx_list.bytes_held >= bytes) {
704
                dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
705
                        __func__, __LINE__, bytes);
706
                schedule_work(&priv->rx_list.work.work);
707
                spin_unlock_irqrestore(&priv->rx_list.lock, flags);
708
                return 0;
709
        }
710
 
711
        priv->rx_list.work.trigger = bytes;
712
        spin_unlock_irqrestore(&priv->rx_list.lock, flags);
713
 
714
        dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
715
                __LINE__, bytes, bytes);
716
 
717
        return 0;
718
}
719
EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
720
 
721
void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
722
{
723
        to_port_priv(dev)->rx_list.work.trigger = 0;
724
}
725
EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
726
 
727
/**
728
 * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
729
 *
730
 * Services the transmit interrupt for the port.  Writes as much data from the
731
 * buffer list as the port will accept.  Retires any emptied list buffers and
732
 * adjusts the final list buffer state for a partial write.
733
 */
734
 
735
static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
736
{
737
        int result = 0;
738
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
739
        unsigned long flags;
740
        struct list_buffer *lb, *n;
741
        unsigned long bytes_total = 0;
742
 
743
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
744
 
745
        spin_lock_irqsave(&priv->tx_list.lock, flags);
746
 
747
        list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
748
 
749
                unsigned long bytes_written;
750
 
751
                result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head,
752
                        &bytes_written);
753
 
754
                if (result) {
755
                        dev_dbg(&dev->core,
756
                                "%s:%d: ps3_vuart_raw_write failed\n",
757
                                __func__, __LINE__);
758
                        break;
759
                }
760
 
761
                bytes_total += bytes_written;
762
 
763
                if (bytes_written < lb->tail - lb->head) {
764
                        lb->head += bytes_written;
765
                        dev_dbg(&dev->core,
766
                                "%s:%d cleared buf_%lu, %lxh bytes\n",
767
                                __func__, __LINE__, lb->dbg_number,
768
                                bytes_written);
769
                        goto port_full;
770
                }
771
 
772
                dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
773
                        lb->dbg_number);
774
 
775
                list_del(&lb->link);
776
                kfree(lb);
777
        }
778
 
779
        ps3_vuart_disable_interrupt_tx(dev);
780
port_full:
781
        spin_unlock_irqrestore(&priv->tx_list.lock, flags);
782
        dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
783
                __func__, __LINE__, bytes_total);
784
        return result;
785
}
786
 
787
/**
788
 * ps3_vuart_handle_interrupt_rx - third stage receive interrupt handler
789
 *
790
 * Services the receive interrupt for the port.  Creates a list buffer and
791
 * copies all waiting port data to that buffer and enqueues the buffer in the
792
 * buffer list.  Buffer list data is dequeued via ps3_vuart_read.
793
 */
794
 
795
static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
796
{
797
        int result;
798
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
799
        unsigned long flags;
800
        u64 bytes;
801
 
802
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
803
 
804
        spin_lock_irqsave(&priv->rx_list.lock, flags);
805
        result = ps3_vuart_queue_rx_bytes(dev, &bytes);
806
 
807
        if (result) {
808
                spin_unlock_irqrestore(&priv->rx_list.lock, flags);
809
                return result;
810
        }
811
 
812
        if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
813
                >= priv->rx_list.work.trigger) {
814
                dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
815
                        __func__, __LINE__, priv->rx_list.work.trigger);
816
                priv->rx_list.work.trigger = 0;
817
                schedule_work(&priv->rx_list.work.work);
818
        }
819
 
820
        spin_unlock_irqrestore(&priv->rx_list.lock, flags);
821
        return result;
822
}
823
 
824
static int ps3_vuart_handle_interrupt_disconnect(
825
        struct ps3_system_bus_device *dev)
826
{
827
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
828
        BUG_ON("no support");
829
        return -1;
830
}
831
 
832
/**
833
 * ps3_vuart_handle_port_interrupt - second stage interrupt handler
834
 *
835
 * Services any pending interrupt types for the port.  Passes control to the
836
 * third stage type specific interrupt handler.  Returns control to the first
837
 * stage handler after one iteration.
838
 */
839
 
840
static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
841
{
842
        int result;
843
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
844
        unsigned long status;
845
 
846
        result = ps3_vuart_get_interrupt_status(dev, &status);
847
 
848
        if (result)
849
                return result;
850
 
851
        dev_dbg(&dev->core, "%s:%d: status: %lxh\n", __func__, __LINE__,
852
                status);
853
 
854
        if (status & INTERRUPT_MASK_DISCONNECT) {
855
                priv->stats.disconnect_interrupts++;
856
                result = ps3_vuart_handle_interrupt_disconnect(dev);
857
                if (result)
858
                        ps3_vuart_disable_interrupt_disconnect(dev);
859
        }
860
 
861
        if (status & INTERRUPT_MASK_TX) {
862
                priv->stats.tx_interrupts++;
863
                result = ps3_vuart_handle_interrupt_tx(dev);
864
                if (result)
865
                        ps3_vuart_disable_interrupt_tx(dev);
866
        }
867
 
868
        if (status & INTERRUPT_MASK_RX) {
869
                priv->stats.rx_interrupts++;
870
                result = ps3_vuart_handle_interrupt_rx(dev);
871
                if (result)
872
                        ps3_vuart_disable_interrupt_rx(dev);
873
        }
874
 
875
        return 0;
876
}
877
 
878
struct vuart_bus_priv {
879
        struct ports_bmp *bmp;
880
        unsigned int virq;
881
        struct semaphore probe_mutex;
882
        int use_count;
883
        struct ps3_system_bus_device *devices[PORT_COUNT];
884
} static vuart_bus_priv;
885
 
886
/**
887
 * ps3_vuart_irq_handler - first stage interrupt handler
888
 *
889
 * Loops finding any interrupting port and its associated instance data.
890
 * Passes control to the second stage port specific interrupt handler.  Loops
891
 * until all outstanding interrupts are serviced.
892
 */
893
 
894
static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
895
{
896
        struct vuart_bus_priv *bus_priv = _private;
897
 
898
        BUG_ON(!bus_priv);
899
 
900
        while (1) {
901
                unsigned int port;
902
 
903
                dump_ports_bmp(bus_priv->bmp);
904
 
905
                port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
906
 
907
                if (port == BITS_PER_LONG)
908
                        break;
909
 
910
                BUG_ON(port >= PORT_COUNT);
911
                BUG_ON(!bus_priv->devices[port]);
912
 
913
                ps3_vuart_handle_port_interrupt(bus_priv->devices[port]);
914
        }
915
 
916
        return IRQ_HANDLED;
917
}
918
 
919
static int ps3_vuart_bus_interrupt_get(void)
920
{
921
        int result;
922
 
923
        pr_debug(" -> %s:%d\n", __func__, __LINE__);
924
 
925
        vuart_bus_priv.use_count++;
926
 
927
        BUG_ON(vuart_bus_priv.use_count > 2);
928
 
929
        if (vuart_bus_priv.use_count != 1) {
930
                return 0;
931
        }
932
 
933
        BUG_ON(vuart_bus_priv.bmp);
934
 
935
        vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
936
 
937
        if (!vuart_bus_priv.bmp) {
938
                pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
939
                result = -ENOMEM;
940
                goto fail_bmp_malloc;
941
        }
942
 
943
        result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
944
                &vuart_bus_priv.virq);
945
 
946
        if (result) {
947
                pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
948
                        __func__, __LINE__, result);
949
                result = -EPERM;
950
                goto fail_alloc_irq;
951
        }
952
 
953
        result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
954
                IRQF_DISABLED, "vuart", &vuart_bus_priv);
955
 
956
        if (result) {
957
                pr_debug("%s:%d: request_irq failed (%d)\n",
958
                        __func__, __LINE__, result);
959
                goto fail_request_irq;
960
        }
961
 
962
        pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
963
        return result;
964
 
965
fail_request_irq:
966
        ps3_vuart_irq_destroy(vuart_bus_priv.virq);
967
        vuart_bus_priv.virq = NO_IRQ;
968
fail_alloc_irq:
969
        kfree(vuart_bus_priv.bmp);
970
        vuart_bus_priv.bmp = NULL;
971
fail_bmp_malloc:
972
        vuart_bus_priv.use_count--;
973
        pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
974
        return result;
975
}
976
 
977
static int ps3_vuart_bus_interrupt_put(void)
978
{
979
        pr_debug(" -> %s:%d\n", __func__, __LINE__);
980
 
981
        vuart_bus_priv.use_count--;
982
 
983
        BUG_ON(vuart_bus_priv.use_count < 0);
984
 
985
        if (vuart_bus_priv.use_count != 0)
986
                return 0;
987
 
988
        free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
989
 
990
        ps3_vuart_irq_destroy(vuart_bus_priv.virq);
991
        vuart_bus_priv.virq = NO_IRQ;
992
 
993
        kfree(vuart_bus_priv.bmp);
994
        vuart_bus_priv.bmp = NULL;
995
 
996
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
997
        return 0;
998
}
999
 
1000
static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
1001
{
1002
        int result;
1003
        struct ps3_vuart_port_driver *drv;
1004
        struct ps3_vuart_port_priv *priv = NULL;
1005
 
1006
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
1007
 
1008
        drv = ps3_system_bus_dev_to_vuart_drv(dev);
1009
 
1010
        dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
1011
                drv->core.core.name);
1012
 
1013
        BUG_ON(!drv);
1014
 
1015
        if (dev->port_number >= PORT_COUNT) {
1016
                BUG();
1017
                return -EINVAL;
1018
        }
1019
 
1020
        down(&vuart_bus_priv.probe_mutex);
1021
 
1022
        result = ps3_vuart_bus_interrupt_get();
1023
 
1024
        if (result)
1025
                goto fail_setup_interrupt;
1026
 
1027
        if (vuart_bus_priv.devices[dev->port_number]) {
1028
                dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
1029
                        __LINE__, dev->port_number);
1030
                result = -EBUSY;
1031
                goto fail_busy;
1032
        }
1033
 
1034
        vuart_bus_priv.devices[dev->port_number] = dev;
1035
 
1036
        /* Setup dev->driver_priv. */
1037
 
1038
        dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
1039
                GFP_KERNEL);
1040
 
1041
        if (!dev->driver_priv) {
1042
                result = -ENOMEM;
1043
                goto fail_dev_malloc;
1044
        }
1045
 
1046
        priv = to_port_priv(dev);
1047
 
1048
        INIT_LIST_HEAD(&priv->tx_list.head);
1049
        spin_lock_init(&priv->tx_list.lock);
1050
 
1051
        INIT_LIST_HEAD(&priv->rx_list.head);
1052
        spin_lock_init(&priv->rx_list.lock);
1053
 
1054
        INIT_WORK(&priv->rx_list.work.work, NULL);
1055
        priv->rx_list.work.trigger = 0;
1056
        priv->rx_list.work.dev = dev;
1057
 
1058
        /* clear stale pending interrupts */
1059
 
1060
        ps3_vuart_clear_rx_bytes(dev, 0);
1061
 
1062
        ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
1063
 
1064
        ps3_vuart_set_triggers(dev, 1, 1);
1065
 
1066
        if (drv->probe)
1067
                result = drv->probe(dev);
1068
        else {
1069
                result = 0;
1070
                dev_info(&dev->core, "%s:%d: no probe method\n", __func__,
1071
                        __LINE__);
1072
        }
1073
 
1074
        if (result) {
1075
                dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
1076
                        __func__, __LINE__);
1077
                goto fail_probe;
1078
        }
1079
 
1080
        up(&vuart_bus_priv.probe_mutex);
1081
 
1082
        return result;
1083
 
1084
fail_probe:
1085
        ps3_vuart_set_interrupt_mask(dev, 0);
1086
        kfree(dev->driver_priv);
1087
        dev->driver_priv = NULL;
1088
fail_dev_malloc:
1089
        vuart_bus_priv.devices[dev->port_number] = NULL;
1090
fail_busy:
1091
        ps3_vuart_bus_interrupt_put();
1092
fail_setup_interrupt:
1093
        up(&vuart_bus_priv.probe_mutex);
1094
        dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
1095
        return result;
1096
}
1097
 
1098
/**
1099
 * ps3_vuart_cleanup - common cleanup helper.
1100
 * @dev: The struct ps3_system_bus_device instance.
1101
 *
1102
 * Cleans interrupts and HV resources.  Must be called with
1103
 * vuart_bus_priv.probe_mutex held.  Used by ps3_vuart_remove and
1104
 * ps3_vuart_shutdown.  After this call, polled reading will still work.
1105
 */
1106
 
1107
static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
1108
{
1109
        dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
1110
 
1111
        ps3_vuart_cancel_async(dev);
1112
        ps3_vuart_set_interrupt_mask(dev, 0);
1113
        ps3_vuart_bus_interrupt_put();
1114
        return 0;
1115
}
1116
 
1117
/**
1118
 * ps3_vuart_remove - Completely clean the device instance.
1119
 * @dev: The struct ps3_system_bus_device instance.
1120
 *
1121
 * Cleans all memory, interrupts and HV resources.  After this call the
1122
 * device can no longer be used.
1123
 */
1124
 
1125
static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
1126
{
1127
        struct ps3_vuart_port_priv *priv = to_port_priv(dev);
1128
        struct ps3_vuart_port_driver *drv;
1129
 
1130
        BUG_ON(!dev);
1131
 
1132
        down(&vuart_bus_priv.probe_mutex);
1133
 
1134
        dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
1135
                dev->match_id);
1136
 
1137
        if (!dev->core.driver) {
1138
                dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1139
                        __LINE__);
1140
                up(&vuart_bus_priv.probe_mutex);
1141
                return 0;
1142
        }
1143
 
1144
        drv = ps3_system_bus_dev_to_vuart_drv(dev);
1145
 
1146
        BUG_ON(!drv);
1147
 
1148
        if (drv->remove) {
1149
                drv->remove(dev);
1150
        } else {
1151
                dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
1152
                __LINE__);
1153
                BUG();
1154
        }
1155
 
1156
        ps3_vuart_cleanup(dev);
1157
 
1158
        vuart_bus_priv.devices[dev->port_number] = NULL;
1159
        kfree(priv);
1160
        priv = NULL;
1161
 
1162
        dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
1163
        up(&vuart_bus_priv.probe_mutex);
1164
        return 0;
1165
}
1166
 
1167
/**
1168
 * ps3_vuart_shutdown - Cleans interrupts and HV resources.
1169
 * @dev: The struct ps3_system_bus_device instance.
1170
 *
1171
 * Cleans interrupts and HV resources.  After this call the
1172
 * device can still be used in polling mode.  This behavior required
1173
 * by sys-manager to be able to complete the device power operation
1174
 * sequence.
1175
 */
1176
 
1177
static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
1178
{
1179
        struct ps3_vuart_port_driver *drv;
1180
 
1181
        BUG_ON(!dev);
1182
 
1183
        down(&vuart_bus_priv.probe_mutex);
1184
 
1185
        dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
1186
                dev->match_id);
1187
 
1188
        if (!dev->core.driver) {
1189
                dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1190
                        __LINE__);
1191
                up(&vuart_bus_priv.probe_mutex);
1192
                return 0;
1193
        }
1194
 
1195
        drv = ps3_system_bus_dev_to_vuart_drv(dev);
1196
 
1197
        BUG_ON(!drv);
1198
 
1199
        if (drv->shutdown)
1200
                drv->shutdown(dev);
1201
        else if (drv->remove) {
1202
                dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
1203
                        __func__, __LINE__);
1204
                drv->remove(dev);
1205
        } else {
1206
                dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
1207
                        __LINE__);
1208
                BUG();
1209
        }
1210
 
1211
        ps3_vuart_cleanup(dev);
1212
 
1213
        dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
1214
 
1215
        up(&vuart_bus_priv.probe_mutex);
1216
        return 0;
1217
}
1218
 
1219
static int __init ps3_vuart_bus_init(void)
1220
{
1221
        pr_debug("%s:%d:\n", __func__, __LINE__);
1222
 
1223
        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
1224
                return -ENODEV;
1225
 
1226
        init_MUTEX(&vuart_bus_priv.probe_mutex);
1227
 
1228
        return 0;
1229
}
1230
 
1231
static void __exit ps3_vuart_bus_exit(void)
1232
{
1233
        pr_debug("%s:%d:\n", __func__, __LINE__);
1234
}
1235
 
1236
core_initcall(ps3_vuart_bus_init);
1237
module_exit(ps3_vuart_bus_exit);
1238
 
1239
/**
1240
 * ps3_vuart_port_driver_register - Add a vuart port device driver.
1241
 */
1242
 
1243
int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
1244
{
1245
        int result;
1246
 
1247
        pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1248
 
1249
        BUG_ON(!drv->core.match_id);
1250
        BUG_ON(!drv->core.core.name);
1251
 
1252
        drv->core.probe = ps3_vuart_probe;
1253
        drv->core.remove = ps3_vuart_remove;
1254
        drv->core.shutdown = ps3_vuart_shutdown;
1255
 
1256
        result = ps3_system_bus_driver_register(&drv->core);
1257
        return result;
1258
}
1259
EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
1260
 
1261
/**
1262
 * ps3_vuart_port_driver_unregister - Remove a vuart port device driver.
1263
 */
1264
 
1265
void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
1266
{
1267
        pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1268
        ps3_system_bus_driver_unregister(&drv->core);
1269
}
1270
EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.