| .. | .. |
|---|
| 20 | 20 | #include <linux/uaccess.h> |
|---|
| 21 | 21 | #include <linux/regmap.h> |
|---|
| 22 | 22 | #include <linux/proc_fs.h> |
|---|
| 23 | +#include <linux/mfd/syscon.h> |
|---|
| 24 | +#include <linux/rockchip/cpu.h> |
|---|
| 23 | 25 | #include <soc/rockchip/pm_domains.h> |
|---|
| 24 | 26 | |
|---|
| 25 | 27 | #include "mpp_debug.h" |
|---|
| .. | .. |
|---|
| 69 | 71 | #define VDPU2_DEC_CLOCK_GATE_EN BIT(4) |
|---|
| 70 | 72 | #define VDPU2_DEC_START BIT(0) |
|---|
| 71 | 73 | |
|---|
| 74 | +#define VDPU2_REG_SOFT_RESET 0x0e8 |
|---|
| 75 | +#define VDPU2_REG_SOFT_RESET_INDEX (58) |
|---|
| 76 | + |
|---|
| 72 | 77 | #define VDPU2_REG_DIR_MV_BASE 0x0f8 |
|---|
| 73 | 78 | #define VDPU2_REG_DIR_MV_BASE_INDEX (62) |
|---|
| 74 | 79 | |
|---|
| .. | .. |
|---|
| 108 | 113 | #endif |
|---|
| 109 | 114 | struct reset_control *rst_a; |
|---|
| 110 | 115 | struct reset_control *rst_h; |
|---|
| 116 | + struct regmap *grf; |
|---|
| 111 | 117 | }; |
|---|
| 112 | 118 | |
|---|
| 113 | 119 | static struct mpp_hw_info vdpu_v2_hw_info = { |
|---|
| .. | .. |
|---|
| 340 | 346 | u32 i; |
|---|
| 341 | 347 | u32 reg_en; |
|---|
| 342 | 348 | struct vdpu_task *task = to_vdpu_task(mpp_task); |
|---|
| 349 | + u32 timing_en = mpp->srv->timing_en; |
|---|
| 343 | 350 | |
|---|
| 344 | 351 | mpp_debug_enter(); |
|---|
| 345 | 352 | |
|---|
| .. | .. |
|---|
| 354 | 361 | |
|---|
| 355 | 362 | mpp_write_req(mpp, task->reg, s, e, reg_en); |
|---|
| 356 | 363 | } |
|---|
| 364 | + |
|---|
| 365 | + /* flush tlb before starting hardware */ |
|---|
| 366 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
|---|
| 367 | + |
|---|
| 357 | 368 | /* init current task */ |
|---|
| 358 | 369 | mpp->cur_task = mpp_task; |
|---|
| 370 | + |
|---|
| 371 | + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
|---|
| 372 | + |
|---|
| 359 | 373 | /* Flush the registers */ |
|---|
| 360 | 374 | wmb(); |
|---|
| 361 | 375 | mpp_write(mpp, VDPU2_REG_DEC_EN, |
|---|
| 362 | 376 | task->reg[reg_en] | VDPU2_DEC_START); |
|---|
| 377 | + |
|---|
| 378 | + mpp_task_run_end(mpp_task, timing_en); |
|---|
| 363 | 379 | |
|---|
| 364 | 380 | mpp_debug_leave(); |
|---|
| 365 | 381 | |
|---|
| .. | .. |
|---|
| 456 | 472 | dec->procfs = NULL; |
|---|
| 457 | 473 | return -EIO; |
|---|
| 458 | 474 | } |
|---|
| 475 | + |
|---|
| 476 | + /* for common mpp_dev options */ |
|---|
| 477 | + mpp_procfs_create_common(dec->procfs, mpp); |
|---|
| 478 | + |
|---|
| 459 | 479 | mpp_procfs_create_u32("aclk", 0644, |
|---|
| 460 | 480 | dec->procfs, &dec->aclk_info.debug_rate_hz); |
|---|
| 461 | 481 | mpp_procfs_create_u32("session_buffers", 0644, |
|---|
| .. | .. |
|---|
| 596 | 616 | return IRQ_HANDLED; |
|---|
| 597 | 617 | } |
|---|
| 598 | 618 | |
|---|
| 619 | +static int vdpu_soft_reset(struct mpp_dev *mpp) |
|---|
| 620 | +{ |
|---|
| 621 | + u32 val; |
|---|
| 622 | + |
|---|
| 623 | + mpp_write(mpp, VDPU2_REG_SOFT_RESET, 1); |
|---|
| 624 | + udelay(2); |
|---|
| 625 | + val = mpp_read(mpp, VDPU2_REG_SOFT_RESET); |
|---|
| 626 | + |
|---|
| 627 | + return val; |
|---|
| 628 | +} |
|---|
| 629 | + |
|---|
| 599 | 630 | static int vdpu_reset(struct mpp_dev *mpp) |
|---|
| 600 | 631 | { |
|---|
| 601 | 632 | struct vdpu_dev *dec = to_vdpu_dev(mpp); |
|---|
| 633 | + u32 ret = 0; |
|---|
| 602 | 634 | |
|---|
| 603 | 635 | mpp_write(mpp, VDPU2_REG_DEC_EN, 0); |
|---|
| 604 | 636 | mpp_write(mpp, VDPU2_REG_DEC_INT, 0); |
|---|
| 605 | | - if (dec->rst_a && dec->rst_h) { |
|---|
| 637 | + |
|---|
| 638 | + /* soft reset first */ |
|---|
| 639 | + ret = vdpu_soft_reset(mpp); |
|---|
| 640 | + if (ret && dec->rst_a && dec->rst_h) { |
|---|
| 606 | 641 | /* Don't skip this or iommu won't work after reset */ |
|---|
| 607 | | - rockchip_pmu_idle_request(mpp->dev, true); |
|---|
| 642 | + mpp_debug(DEBUG_RESET, "reset in\n"); |
|---|
| 643 | + mpp_pmu_idle_request(mpp, true); |
|---|
| 608 | 644 | mpp_safe_reset(dec->rst_a); |
|---|
| 609 | 645 | mpp_safe_reset(dec->rst_h); |
|---|
| 610 | 646 | udelay(5); |
|---|
| 611 | 647 | mpp_safe_unreset(dec->rst_a); |
|---|
| 612 | 648 | mpp_safe_unreset(dec->rst_h); |
|---|
| 613 | | - rockchip_pmu_idle_request(mpp->dev, false); |
|---|
| 649 | + mpp_pmu_idle_request(mpp, false); |
|---|
| 650 | + mpp_debug(DEBUG_RESET, "reset out\n"); |
|---|
| 614 | 651 | } |
|---|
| 615 | 652 | |
|---|
| 616 | 653 | return 0; |
|---|
| .. | .. |
|---|
| 758 | 795 | dev_err(dev, "wait total running time out\n"); |
|---|
| 759 | 796 | } |
|---|
| 760 | 797 | |
|---|
| 798 | +static int vdpu_runtime_suspend(struct device *dev) |
|---|
| 799 | +{ |
|---|
| 800 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 801 | + struct mpp_grf_info *info = mpp->grf_info; |
|---|
| 802 | + struct mpp_taskqueue *queue = mpp->queue; |
|---|
| 803 | + |
|---|
| 804 | + if (cpu_is_rk3528() && info && info->mem_offset) { |
|---|
| 805 | + mutex_lock(&queue->ref_lock); |
|---|
| 806 | + if (!atomic_dec_if_positive(&queue->runtime_cnt)) { |
|---|
| 807 | + regmap_write(info->grf, info->mem_offset, |
|---|
| 808 | + info->val_mem_off); |
|---|
| 809 | + } |
|---|
| 810 | + mutex_unlock(&queue->ref_lock); |
|---|
| 811 | + } |
|---|
| 812 | + |
|---|
| 813 | + return 0; |
|---|
| 814 | +} |
|---|
| 815 | + |
|---|
| 816 | +static int vdpu_runtime_resume(struct device *dev) |
|---|
| 817 | +{ |
|---|
| 818 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 819 | + struct mpp_grf_info *info = mpp->grf_info; |
|---|
| 820 | + struct mpp_taskqueue *queue = mpp->queue; |
|---|
| 821 | + |
|---|
| 822 | + if (cpu_is_rk3528() && info && info->mem_offset) { |
|---|
| 823 | + mutex_lock(&queue->ref_lock); |
|---|
| 824 | + regmap_write(info->grf, info->mem_offset, |
|---|
| 825 | + info->val_mem_on); |
|---|
| 826 | + atomic_inc(&queue->runtime_cnt); |
|---|
| 827 | + mutex_unlock(&queue->ref_lock); |
|---|
| 828 | + } |
|---|
| 829 | + |
|---|
| 830 | + return 0; |
|---|
| 831 | +} |
|---|
| 832 | + |
|---|
| 833 | +static const struct dev_pm_ops vdpu_pm_ops = { |
|---|
| 834 | + .runtime_suspend = vdpu_runtime_suspend, |
|---|
| 835 | + .runtime_resume = vdpu_runtime_resume, |
|---|
| 836 | +}; |
|---|
| 837 | + |
|---|
| 761 | 838 | struct platform_driver rockchip_vdpu2_driver = { |
|---|
| 762 | 839 | .probe = vdpu_probe, |
|---|
| 763 | 840 | .remove = vdpu_remove, |
|---|
| 764 | 841 | .shutdown = vdpu_shutdown, |
|---|
| 765 | 842 | .driver = { |
|---|
| 766 | 843 | .name = VDPU2_DRIVER_NAME, |
|---|
| 844 | + .pm = &vdpu_pm_ops, |
|---|
| 767 | 845 | .of_match_table = of_match_ptr(mpp_vdpu2_dt_match), |
|---|
| 768 | 846 | }, |
|---|
| 769 | 847 | }; |
|---|