|
7 | 7 |
|
8 | 8 | #include <linux/bits.h>
|
9 | 9 | #include <linux/init.h>
|
| 10 | +#include <linux/mm.h> |
10 | 11 | #include <linux/pm.h>
|
11 | 12 | #include <linux/reboot.h>
|
12 | 13 | #include <asm/sbi.h>
|
@@ -571,6 +572,66 @@ long sbi_get_mimpid(void)
|
571 | 572 | }
|
572 | 573 | EXPORT_SYMBOL_GPL(sbi_get_mimpid);
|
573 | 574 |
|
| 575 | +bool sbi_debug_console_available; |
| 576 | + |
| 577 | +int sbi_debug_console_write(const char *bytes, unsigned int num_bytes) |
| 578 | +{ |
| 579 | + phys_addr_t base_addr; |
| 580 | + struct sbiret ret; |
| 581 | + |
| 582 | + if (!sbi_debug_console_available) |
| 583 | + return -EOPNOTSUPP; |
| 584 | + |
| 585 | + if (is_vmalloc_addr(bytes)) |
| 586 | + base_addr = page_to_phys(vmalloc_to_page(bytes)) + |
| 587 | + offset_in_page(bytes); |
| 588 | + else |
| 589 | + base_addr = __pa(bytes); |
| 590 | + if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes)) |
| 591 | + num_bytes = PAGE_SIZE - offset_in_page(bytes); |
| 592 | + |
| 593 | + if (IS_ENABLED(CONFIG_32BIT)) |
| 594 | + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, |
| 595 | + num_bytes, lower_32_bits(base_addr), |
| 596 | + upper_32_bits(base_addr), 0, 0, 0); |
| 597 | + else |
| 598 | + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, |
| 599 | + num_bytes, base_addr, 0, 0, 0, 0); |
| 600 | + |
| 601 | + if (ret.error == SBI_ERR_FAILURE) |
| 602 | + return -EIO; |
| 603 | + return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value; |
| 604 | +} |
| 605 | + |
| 606 | +int sbi_debug_console_read(char *bytes, unsigned int num_bytes) |
| 607 | +{ |
| 608 | + phys_addr_t base_addr; |
| 609 | + struct sbiret ret; |
| 610 | + |
| 611 | + if (!sbi_debug_console_available) |
| 612 | + return -EOPNOTSUPP; |
| 613 | + |
| 614 | + if (is_vmalloc_addr(bytes)) |
| 615 | + base_addr = page_to_phys(vmalloc_to_page(bytes)) + |
| 616 | + offset_in_page(bytes); |
| 617 | + else |
| 618 | + base_addr = __pa(bytes); |
| 619 | + if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes)) |
| 620 | + num_bytes = PAGE_SIZE - offset_in_page(bytes); |
| 621 | + |
| 622 | + if (IS_ENABLED(CONFIG_32BIT)) |
| 623 | + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ, |
| 624 | + num_bytes, lower_32_bits(base_addr), |
| 625 | + upper_32_bits(base_addr), 0, 0, 0); |
| 626 | + else |
| 627 | + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ, |
| 628 | + num_bytes, base_addr, 0, 0, 0, 0); |
| 629 | + |
| 630 | + if (ret.error == SBI_ERR_FAILURE) |
| 631 | + return -EIO; |
| 632 | + return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value; |
| 633 | +} |
| 634 | + |
574 | 635 | void __init sbi_init(void)
|
575 | 636 | {
|
576 | 637 | int ret;
|
@@ -612,6 +673,11 @@ void __init sbi_init(void)
|
612 | 673 | sbi_srst_reboot_nb.priority = 192;
|
613 | 674 | register_restart_handler(&sbi_srst_reboot_nb);
|
614 | 675 | }
|
| 676 | + if ((sbi_spec_version >= sbi_mk_version(2, 0)) && |
| 677 | + (sbi_probe_extension(SBI_EXT_DBCN) > 0)) { |
| 678 | + pr_info("SBI DBCN extension detected\n"); |
| 679 | + sbi_debug_console_available = true; |
| 680 | + } |
615 | 681 | } else {
|
616 | 682 | __sbi_set_timer = __sbi_set_timer_v01;
|
617 | 683 | __sbi_send_ipi = __sbi_send_ipi_v01;
|
|
0 commit comments