.. | .. |
---|
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 | }; |
---|