0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <linux/init.h>
0024 #include <linux/slab.h>
0025 #include <linux/err.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/fs.h>
0028 #include <linux/poll.h>
0029 #include <asm/epapr_hcalls.h>
0030 #include <linux/of.h>
0031 #include <linux/of_irq.h>
0032 #include <linux/platform_device.h>
0033 #include <linux/cdev.h>
0034 #include <linux/console.h>
0035 #include <linux/tty.h>
0036 #include <linux/tty_flip.h>
0037 #include <linux/circ_buf.h>
0038 #include <asm/udbg.h>
0039
0040
0041 #define BUF_SIZE 2048
0042
0043
0044 struct ehv_bc_data {
0045 struct device *dev;
0046 struct tty_port port;
0047 uint32_t handle;
0048 unsigned int rx_irq;
0049 unsigned int tx_irq;
0050
0051 spinlock_t lock;
0052 unsigned char buf[BUF_SIZE];
0053 unsigned int head;
0054 unsigned int tail;
0055
0056 int tx_irq_enabled;
0057 };
0058
0059
0060 static struct ehv_bc_data *bcs;
0061
0062
0063 static unsigned int stdout_bc;
0064
0065
0066 static unsigned int stdout_irq;
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 static void enable_tx_interrupt(struct ehv_bc_data *bc)
0087 {
0088 if (!bc->tx_irq_enabled) {
0089 enable_irq(bc->tx_irq);
0090 bc->tx_irq_enabled = 1;
0091 }
0092 }
0093
0094 static void disable_tx_interrupt(struct ehv_bc_data *bc)
0095 {
0096 if (bc->tx_irq_enabled) {
0097 disable_irq_nosync(bc->tx_irq);
0098 bc->tx_irq_enabled = 0;
0099 }
0100 }
0101
0102
0103
0104
0105
0106
0107
0108 static int find_console_handle(void)
0109 {
0110 struct device_node *np = of_stdout;
0111 const uint32_t *iprop;
0112
0113
0114
0115
0116
0117 if (!np || !of_device_is_compatible(np, "epapr,hv-byte-channel"))
0118 return 0;
0119
0120 stdout_irq = irq_of_parse_and_map(np, 0);
0121 if (stdout_irq == NO_IRQ) {
0122 pr_err("ehv-bc: no 'interrupts' property in %pOF node\n", np);
0123 return 0;
0124 }
0125
0126
0127
0128
0129 iprop = of_get_property(np, "hv-handle", NULL);
0130 if (!iprop) {
0131 pr_err("ehv-bc: no 'hv-handle' property in %pOFn node\n",
0132 np);
0133 return 0;
0134 }
0135 stdout_bc = be32_to_cpu(*iprop);
0136 return 1;
0137 }
0138
0139 static unsigned int local_ev_byte_channel_send(unsigned int handle,
0140 unsigned int *count,
0141 const char *p)
0142 {
0143 char buffer[EV_BYTE_CHANNEL_MAX_BYTES];
0144 unsigned int c = *count;
0145
0146 if (c < sizeof(buffer)) {
0147 memcpy(buffer, p, c);
0148 memset(&buffer[c], 0, sizeof(buffer) - c);
0149 p = buffer;
0150 }
0151 return ev_byte_channel_send(handle, count, p);
0152 }
0153
0154
0155
0156 #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 static void byte_channel_spin_send(const char data)
0167 {
0168 int ret, count;
0169
0170 do {
0171 count = 1;
0172 ret = local_ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE,
0173 &count, &data);
0174 } while (ret == EV_EAGAIN);
0175 }
0176
0177
0178
0179
0180
0181 static void ehv_bc_udbg_putc(char c)
0182 {
0183 if (c == '\n')
0184 byte_channel_spin_send('\r');
0185
0186 byte_channel_spin_send(c);
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 void __init udbg_init_ehv_bc(void)
0201 {
0202 unsigned int rx_count, tx_count;
0203 unsigned int ret;
0204
0205
0206 ret = ev_byte_channel_poll(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE,
0207 &rx_count, &tx_count);
0208 if (ret)
0209 return;
0210
0211 udbg_putc = ehv_bc_udbg_putc;
0212 register_early_udbg_console();
0213
0214 udbg_printf("ehv-bc: early console using byte channel handle %u\n",
0215 CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE);
0216 }
0217
0218 #endif
0219
0220
0221
0222 static struct tty_driver *ehv_bc_driver;
0223
0224
0225
0226
0227
0228
0229
0230 static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s,
0231 unsigned int count)
0232 {
0233 unsigned int len;
0234 int ret = 0;
0235
0236 while (count) {
0237 len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES);
0238 do {
0239 ret = local_ev_byte_channel_send(handle, &len, s);
0240 } while (ret == EV_EAGAIN);
0241 count -= len;
0242 s += len;
0243 }
0244
0245 return ret;
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258 static void ehv_bc_console_write(struct console *co, const char *s,
0259 unsigned int count)
0260 {
0261 char s2[EV_BYTE_CHANNEL_MAX_BYTES];
0262 unsigned int i, j = 0;
0263 char c;
0264
0265 for (i = 0; i < count; i++) {
0266 c = *s++;
0267
0268 if (c == '\n')
0269 s2[j++] = '\r';
0270
0271 s2[j++] = c;
0272 if (j >= (EV_BYTE_CHANNEL_MAX_BYTES - 1)) {
0273 if (ehv_bc_console_byte_channel_send(stdout_bc, s2, j))
0274 return;
0275 j = 0;
0276 }
0277 }
0278
0279 if (j)
0280 ehv_bc_console_byte_channel_send(stdout_bc, s2, j);
0281 }
0282
0283
0284
0285
0286
0287
0288 static struct tty_driver *ehv_bc_console_device(struct console *co, int *index)
0289 {
0290 *index = co->index;
0291
0292 return ehv_bc_driver;
0293 }
0294
0295 static struct console ehv_bc_console = {
0296 .name = "ttyEHV",
0297 .write = ehv_bc_console_write,
0298 .device = ehv_bc_console_device,
0299 .flags = CON_PRINTBUFFER | CON_ENABLED,
0300 };
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 static int __init ehv_bc_console_init(void)
0311 {
0312 if (!find_console_handle()) {
0313 pr_debug("ehv-bc: stdout is not a byte channel\n");
0314 return -ENODEV;
0315 }
0316
0317 #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC
0318
0319
0320
0321 if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE)
0322 pr_warn("ehv-bc: udbg handle %u is not the stdout handle\n",
0323 CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE);
0324 #endif
0325
0326
0327
0328
0329
0330 add_preferred_console(ehv_bc_console.name, ehv_bc_console.index, NULL);
0331 register_console(&ehv_bc_console);
0332
0333 pr_info("ehv-bc: registered console driver for byte channel %u\n",
0334 stdout_bc);
0335
0336 return 0;
0337 }
0338 console_initcall(ehv_bc_console_init);
0339
0340
0341
0342
0343
0344
0345
0346
0347 static irqreturn_t ehv_bc_tty_rx_isr(int irq, void *data)
0348 {
0349 struct ehv_bc_data *bc = data;
0350 unsigned int rx_count, tx_count, len;
0351 int count;
0352 char buffer[EV_BYTE_CHANNEL_MAX_BYTES];
0353 int ret;
0354
0355
0356
0357
0358
0359 ev_byte_channel_poll(bc->handle, &rx_count, &tx_count);
0360 count = tty_buffer_request_room(&bc->port, rx_count);
0361
0362
0363
0364
0365
0366
0367
0368 while (count > 0) {
0369 len = min_t(unsigned int, count, sizeof(buffer));
0370
0371
0372
0373
0374 ev_byte_channel_receive(bc->handle, &len, buffer);
0375
0376
0377
0378
0379
0380
0381 ret = tty_insert_flip_string(&bc->port, buffer, len);
0382
0383
0384
0385
0386
0387
0388
0389 if (ret != len)
0390 break;
0391
0392 count -= len;
0393 }
0394
0395
0396 tty_flip_buffer_push(&bc->port);
0397
0398 return IRQ_HANDLED;
0399 }
0400
0401
0402
0403
0404
0405
0406
0407 static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)
0408 {
0409 unsigned int count;
0410 unsigned int len, ret;
0411 unsigned long flags;
0412
0413 do {
0414 spin_lock_irqsave(&bc->lock, flags);
0415 len = min_t(unsigned int,
0416 CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE),
0417 EV_BYTE_CHANNEL_MAX_BYTES);
0418
0419 ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail);
0420
0421
0422 if (!ret || (ret == EV_EAGAIN))
0423 bc->tail = (bc->tail + len) & (BUF_SIZE - 1);
0424
0425 count = CIRC_CNT(bc->head, bc->tail, BUF_SIZE);
0426 spin_unlock_irqrestore(&bc->lock, flags);
0427 } while (count && !ret);
0428
0429 spin_lock_irqsave(&bc->lock, flags);
0430 if (CIRC_CNT(bc->head, bc->tail, BUF_SIZE))
0431
0432
0433
0434
0435
0436 enable_tx_interrupt(bc);
0437 else
0438 disable_tx_interrupt(bc);
0439 spin_unlock_irqrestore(&bc->lock, flags);
0440 }
0441
0442
0443
0444
0445
0446
0447
0448 static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data)
0449 {
0450 struct ehv_bc_data *bc = data;
0451
0452 ehv_bc_tx_dequeue(bc);
0453 tty_port_tty_wakeup(&bc->port);
0454
0455 return IRQ_HANDLED;
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 static int ehv_bc_tty_write(struct tty_struct *ttys, const unsigned char *s,
0470 int count)
0471 {
0472 struct ehv_bc_data *bc = ttys->driver_data;
0473 unsigned long flags;
0474 unsigned int len;
0475 unsigned int written = 0;
0476
0477 while (1) {
0478 spin_lock_irqsave(&bc->lock, flags);
0479 len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE);
0480 if (count < len)
0481 len = count;
0482 if (len) {
0483 memcpy(bc->buf + bc->head, s, len);
0484 bc->head = (bc->head + len) & (BUF_SIZE - 1);
0485 }
0486 spin_unlock_irqrestore(&bc->lock, flags);
0487 if (!len)
0488 break;
0489
0490 s += len;
0491 count -= len;
0492 written += len;
0493 }
0494
0495 ehv_bc_tx_dequeue(bc);
0496
0497 return written;
0498 }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 static int ehv_bc_tty_open(struct tty_struct *ttys, struct file *filp)
0510 {
0511 struct ehv_bc_data *bc = &bcs[ttys->index];
0512
0513 if (!bc->dev)
0514 return -ENODEV;
0515
0516 return tty_port_open(&bc->port, ttys, filp);
0517 }
0518
0519
0520
0521
0522
0523
0524 static void ehv_bc_tty_close(struct tty_struct *ttys, struct file *filp)
0525 {
0526 struct ehv_bc_data *bc = &bcs[ttys->index];
0527
0528 if (bc->dev)
0529 tty_port_close(&bc->port, ttys, filp);
0530 }
0531
0532
0533
0534
0535
0536
0537
0538
0539 static unsigned int ehv_bc_tty_write_room(struct tty_struct *ttys)
0540 {
0541 struct ehv_bc_data *bc = ttys->driver_data;
0542 unsigned long flags;
0543 unsigned int count;
0544
0545 spin_lock_irqsave(&bc->lock, flags);
0546 count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE);
0547 spin_unlock_irqrestore(&bc->lock, flags);
0548
0549 return count;
0550 }
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564 static void ehv_bc_tty_throttle(struct tty_struct *ttys)
0565 {
0566 struct ehv_bc_data *bc = ttys->driver_data;
0567
0568 disable_irq(bc->rx_irq);
0569 }
0570
0571
0572
0573
0574
0575
0576
0577
0578 static void ehv_bc_tty_unthrottle(struct tty_struct *ttys)
0579 {
0580 struct ehv_bc_data *bc = ttys->driver_data;
0581
0582
0583
0584
0585 enable_irq(bc->rx_irq);
0586 }
0587
0588 static void ehv_bc_tty_hangup(struct tty_struct *ttys)
0589 {
0590 struct ehv_bc_data *bc = ttys->driver_data;
0591
0592 ehv_bc_tx_dequeue(bc);
0593 tty_port_hangup(&bc->port);
0594 }
0595
0596
0597
0598
0599
0600
0601
0602
0603 static const struct tty_operations ehv_bc_ops = {
0604 .open = ehv_bc_tty_open,
0605 .close = ehv_bc_tty_close,
0606 .write = ehv_bc_tty_write,
0607 .write_room = ehv_bc_tty_write_room,
0608 .throttle = ehv_bc_tty_throttle,
0609 .unthrottle = ehv_bc_tty_unthrottle,
0610 .hangup = ehv_bc_tty_hangup,
0611 };
0612
0613
0614
0615
0616
0617
0618
0619
0620 static int ehv_bc_tty_port_activate(struct tty_port *port,
0621 struct tty_struct *ttys)
0622 {
0623 struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port);
0624 int ret;
0625
0626 ttys->driver_data = bc;
0627
0628 ret = request_irq(bc->rx_irq, ehv_bc_tty_rx_isr, 0, "ehv-bc", bc);
0629 if (ret < 0) {
0630 dev_err(bc->dev, "could not request rx irq %u (ret=%i)\n",
0631 bc->rx_irq, ret);
0632 return ret;
0633 }
0634
0635
0636 bc->tx_irq_enabled = 1;
0637
0638 ret = request_irq(bc->tx_irq, ehv_bc_tty_tx_isr, 0, "ehv-bc", bc);
0639 if (ret < 0) {
0640 dev_err(bc->dev, "could not request tx irq %u (ret=%i)\n",
0641 bc->tx_irq, ret);
0642 free_irq(bc->rx_irq, bc);
0643 return ret;
0644 }
0645
0646
0647
0648
0649 disable_tx_interrupt(bc);
0650
0651 return 0;
0652 }
0653
0654 static void ehv_bc_tty_port_shutdown(struct tty_port *port)
0655 {
0656 struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port);
0657
0658 free_irq(bc->tx_irq, bc);
0659 free_irq(bc->rx_irq, bc);
0660 }
0661
0662 static const struct tty_port_operations ehv_bc_tty_port_ops = {
0663 .activate = ehv_bc_tty_port_activate,
0664 .shutdown = ehv_bc_tty_port_shutdown,
0665 };
0666
0667 static int ehv_bc_tty_probe(struct platform_device *pdev)
0668 {
0669 struct device_node *np = pdev->dev.of_node;
0670 struct ehv_bc_data *bc;
0671 const uint32_t *iprop;
0672 unsigned int handle;
0673 int ret;
0674 static unsigned int index = 1;
0675 unsigned int i;
0676
0677 iprop = of_get_property(np, "hv-handle", NULL);
0678 if (!iprop) {
0679 dev_err(&pdev->dev, "no 'hv-handle' property in %pOFn node\n",
0680 np);
0681 return -ENODEV;
0682 }
0683
0684
0685
0686
0687
0688 handle = be32_to_cpu(*iprop);
0689 i = (handle == stdout_bc) ? 0 : index++;
0690 bc = &bcs[i];
0691
0692 bc->handle = handle;
0693 bc->head = 0;
0694 bc->tail = 0;
0695 spin_lock_init(&bc->lock);
0696
0697 bc->rx_irq = irq_of_parse_and_map(np, 0);
0698 bc->tx_irq = irq_of_parse_and_map(np, 1);
0699 if ((bc->rx_irq == NO_IRQ) || (bc->tx_irq == NO_IRQ)) {
0700 dev_err(&pdev->dev, "no 'interrupts' property in %pOFn node\n",
0701 np);
0702 ret = -ENODEV;
0703 goto error;
0704 }
0705
0706 tty_port_init(&bc->port);
0707 bc->port.ops = &ehv_bc_tty_port_ops;
0708
0709 bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i,
0710 &pdev->dev);
0711 if (IS_ERR(bc->dev)) {
0712 ret = PTR_ERR(bc->dev);
0713 dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret);
0714 goto error;
0715 }
0716
0717 dev_set_drvdata(&pdev->dev, bc);
0718
0719 dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n",
0720 ehv_bc_driver->name, i, bc->handle);
0721
0722 return 0;
0723
0724 error:
0725 tty_port_destroy(&bc->port);
0726 irq_dispose_mapping(bc->tx_irq);
0727 irq_dispose_mapping(bc->rx_irq);
0728
0729 memset(bc, 0, sizeof(struct ehv_bc_data));
0730 return ret;
0731 }
0732
0733 static const struct of_device_id ehv_bc_tty_of_ids[] = {
0734 { .compatible = "epapr,hv-byte-channel" },
0735 {}
0736 };
0737
0738 static struct platform_driver ehv_bc_tty_driver = {
0739 .driver = {
0740 .name = "ehv-bc",
0741 .of_match_table = ehv_bc_tty_of_ids,
0742 .suppress_bind_attrs = true,
0743 },
0744 .probe = ehv_bc_tty_probe,
0745 };
0746
0747
0748
0749
0750
0751
0752 static int __init ehv_bc_init(void)
0753 {
0754 struct tty_driver *driver;
0755 struct device_node *np;
0756 unsigned int count = 0;
0757 int ret;
0758
0759 pr_info("ePAPR hypervisor byte channel driver\n");
0760
0761
0762 for_each_compatible_node(np, NULL, "epapr,hv-byte-channel")
0763 count++;
0764
0765 if (!count)
0766 return -ENODEV;
0767
0768
0769
0770
0771
0772
0773 bcs = kcalloc(count, sizeof(struct ehv_bc_data), GFP_KERNEL);
0774 if (!bcs)
0775 return -ENOMEM;
0776
0777 driver = tty_alloc_driver(count, TTY_DRIVER_REAL_RAW |
0778 TTY_DRIVER_DYNAMIC_DEV);
0779 if (IS_ERR(driver)) {
0780 ret = PTR_ERR(driver);
0781 goto err_free_bcs;
0782 }
0783
0784 driver->driver_name = "ehv-bc";
0785 driver->name = ehv_bc_console.name;
0786 driver->type = TTY_DRIVER_TYPE_CONSOLE;
0787 driver->subtype = SYSTEM_TYPE_CONSOLE;
0788 driver->init_termios = tty_std_termios;
0789 tty_set_operations(driver, &ehv_bc_ops);
0790
0791 ret = tty_register_driver(driver);
0792 if (ret) {
0793 pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
0794 goto err_tty_driver_kref_put;
0795 }
0796
0797 ehv_bc_driver = driver;
0798
0799 ret = platform_driver_register(&ehv_bc_tty_driver);
0800 if (ret) {
0801 pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
0802 ret);
0803 goto err_deregister_tty_driver;
0804 }
0805
0806 return 0;
0807
0808 err_deregister_tty_driver:
0809 ehv_bc_driver = NULL;
0810 tty_unregister_driver(driver);
0811 err_tty_driver_kref_put:
0812 tty_driver_kref_put(driver);
0813 err_free_bcs:
0814 kfree(bcs);
0815
0816 return ret;
0817 }
0818 device_initcall(ehv_bc_init);