| .. | .. |
|---|
| 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> |
|---|
| 25 | 23 | #include <soc/rockchip/pm_domains.h> |
|---|
| 26 | 24 | |
|---|
| 27 | 25 | #include "mpp_debug.h" |
|---|
| .. | .. |
|---|
| 113 | 111 | #endif |
|---|
| 114 | 112 | struct reset_control *rst_a; |
|---|
| 115 | 113 | struct reset_control *rst_h; |
|---|
| 116 | | - struct regmap *grf; |
|---|
| 117 | 114 | }; |
|---|
| 118 | 115 | |
|---|
| 119 | 116 | static struct mpp_hw_info vdpu_v2_hw_info = { |
|---|
| .. | .. |
|---|
| 230 | 227 | offset = task->reg[idx] >> 10 << 4; |
|---|
| 231 | 228 | } |
|---|
| 232 | 229 | mem_region = mpp_task_attach_fd(&task->mpp_task, fd); |
|---|
| 233 | | - if (IS_ERR(mem_region)) |
|---|
| 230 | + if (IS_ERR(mem_region)) { |
|---|
| 231 | + mpp_err("reg[%3d]: %08x fd %d attach failed\n", |
|---|
| 232 | + idx, task->reg[idx], fd); |
|---|
| 234 | 233 | return -EFAULT; |
|---|
| 234 | + } |
|---|
| 235 | 235 | |
|---|
| 236 | 236 | iova = mem_region->iova; |
|---|
| 237 | 237 | mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", |
|---|
| .. | .. |
|---|
| 380 | 380 | mpp_debug_leave(); |
|---|
| 381 | 381 | |
|---|
| 382 | 382 | return 0; |
|---|
| 383 | +} |
|---|
| 384 | + |
|---|
| 385 | +static int vdpu_px30_run(struct mpp_dev *mpp, |
|---|
| 386 | + struct mpp_task *mpp_task) |
|---|
| 387 | +{ |
|---|
| 388 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
|---|
| 389 | + return vdpu_run(mpp, mpp_task); |
|---|
| 383 | 390 | } |
|---|
| 384 | 391 | |
|---|
| 385 | 392 | static int vdpu_finish(struct mpp_dev *mpp, |
|---|
| .. | .. |
|---|
| 619 | 626 | static int vdpu_soft_reset(struct mpp_dev *mpp) |
|---|
| 620 | 627 | { |
|---|
| 621 | 628 | u32 val; |
|---|
| 629 | + u32 ret; |
|---|
| 622 | 630 | |
|---|
| 623 | 631 | mpp_write(mpp, VDPU2_REG_SOFT_RESET, 1); |
|---|
| 624 | | - udelay(2); |
|---|
| 625 | | - val = mpp_read(mpp, VDPU2_REG_SOFT_RESET); |
|---|
| 626 | | - |
|---|
| 627 | | - return val; |
|---|
| 632 | + ret = readl_relaxed_poll_timeout(mpp->reg_base + VDPU2_REG_SOFT_RESET, |
|---|
| 633 | + val, !val, 0, 5); |
|---|
| 634 | + return ret; |
|---|
| 628 | 635 | } |
|---|
| 629 | 636 | |
|---|
| 630 | 637 | static int vdpu_reset(struct mpp_dev *mpp) |
|---|
| .. | .. |
|---|
| 639 | 646 | ret = vdpu_soft_reset(mpp); |
|---|
| 640 | 647 | if (ret && dec->rst_a && dec->rst_h) { |
|---|
| 641 | 648 | /* Don't skip this or iommu won't work after reset */ |
|---|
| 649 | + mpp_err("soft reset failed, use cru reset!\n"); |
|---|
| 642 | 650 | mpp_debug(DEBUG_RESET, "reset in\n"); |
|---|
| 643 | 651 | mpp_pmu_idle_request(mpp, true); |
|---|
| 644 | 652 | mpp_safe_reset(dec->rst_a); |
|---|
| .. | .. |
|---|
| 682 | 690 | .free_task = vdpu_free_task, |
|---|
| 683 | 691 | }; |
|---|
| 684 | 692 | |
|---|
| 693 | +static struct mpp_dev_ops vdpu_px30_dev_ops = { |
|---|
| 694 | + .alloc_task = vdpu_alloc_task, |
|---|
| 695 | + .run = vdpu_px30_run, |
|---|
| 696 | + .irq = vdpu_irq, |
|---|
| 697 | + .isr = vdpu_isr, |
|---|
| 698 | + .finish = vdpu_finish, |
|---|
| 699 | + .result = vdpu_result, |
|---|
| 700 | + .free_task = vdpu_free_task, |
|---|
| 701 | +}; |
|---|
| 702 | + |
|---|
| 685 | 703 | static const struct mpp_dev_var vdpu_v2_data = { |
|---|
| 686 | 704 | .device_type = MPP_DEVICE_VDPU2, |
|---|
| 687 | 705 | .hw_info = &vdpu_v2_hw_info, |
|---|
| .. | .. |
|---|
| 695 | 713 | .hw_info = &vdpu_v2_hw_info, |
|---|
| 696 | 714 | .trans_info = vdpu_v2_trans, |
|---|
| 697 | 715 | .hw_ops = &vdpu_px30_hw_ops, |
|---|
| 698 | | - .dev_ops = &vdpu_v2_dev_ops, |
|---|
| 716 | + .dev_ops = &vdpu_px30_dev_ops, |
|---|
| 699 | 717 | }; |
|---|
| 700 | 718 | |
|---|
| 701 | 719 | static const struct of_device_id mpp_vdpu2_dt_match[] = { |
|---|
| .. | .. |
|---|
| 724 | 742 | dec = devm_kzalloc(dev, sizeof(struct vdpu_dev), GFP_KERNEL); |
|---|
| 725 | 743 | if (!dec) |
|---|
| 726 | 744 | return -ENOMEM; |
|---|
| 727 | | - platform_set_drvdata(pdev, dec); |
|---|
| 728 | | - |
|---|
| 729 | 745 | mpp = &dec->mpp; |
|---|
| 746 | + platform_set_drvdata(pdev, mpp); |
|---|
| 730 | 747 | |
|---|
| 731 | 748 | if (pdev->dev.of_node) { |
|---|
| 732 | 749 | match = of_match_node(mpp_vdpu2_dt_match, |
|---|
| 733 | 750 | pdev->dev.of_node); |
|---|
| 734 | 751 | if (match) |
|---|
| 735 | 752 | mpp->var = (struct mpp_dev_var *)match->data; |
|---|
| 753 | + |
|---|
| 754 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vdpu"); |
|---|
| 736 | 755 | } |
|---|
| 737 | 756 | |
|---|
| 738 | 757 | ret = mpp_dev_probe(mpp, pdev); |
|---|
| .. | .. |
|---|
| 768 | 787 | static int vdpu_remove(struct platform_device *pdev) |
|---|
| 769 | 788 | { |
|---|
| 770 | 789 | struct device *dev = &pdev->dev; |
|---|
| 771 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
|---|
| 790 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 772 | 791 | |
|---|
| 773 | 792 | dev_info(dev, "remove device\n"); |
|---|
| 774 | | - mpp_dev_remove(&dec->mpp); |
|---|
| 775 | | - vdpu_procfs_remove(&dec->mpp); |
|---|
| 793 | + mpp_dev_remove(mpp); |
|---|
| 794 | + vdpu_procfs_remove(mpp); |
|---|
| 776 | 795 | |
|---|
| 777 | 796 | return 0; |
|---|
| 778 | 797 | } |
|---|
| 779 | | - |
|---|
| 780 | | -static void vdpu_shutdown(struct platform_device *pdev) |
|---|
| 781 | | -{ |
|---|
| 782 | | - int ret; |
|---|
| 783 | | - int val; |
|---|
| 784 | | - struct device *dev = &pdev->dev; |
|---|
| 785 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
|---|
| 786 | | - struct mpp_dev *mpp = &dec->mpp; |
|---|
| 787 | | - |
|---|
| 788 | | - dev_info(dev, "shutdown device\n"); |
|---|
| 789 | | - |
|---|
| 790 | | - atomic_inc(&mpp->srv->shutdown_request); |
|---|
| 791 | | - ret = readx_poll_timeout(atomic_read, |
|---|
| 792 | | - &mpp->task_count, |
|---|
| 793 | | - val, val == 0, 20000, 200000); |
|---|
| 794 | | - if (ret == -ETIMEDOUT) |
|---|
| 795 | | - dev_err(dev, "wait total running time out\n"); |
|---|
| 796 | | -} |
|---|
| 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 | 798 | |
|---|
| 838 | 799 | struct platform_driver rockchip_vdpu2_driver = { |
|---|
| 839 | 800 | .probe = vdpu_probe, |
|---|
| 840 | 801 | .remove = vdpu_remove, |
|---|
| 841 | | - .shutdown = vdpu_shutdown, |
|---|
| 802 | + .shutdown = mpp_dev_shutdown, |
|---|
| 842 | 803 | .driver = { |
|---|
| 843 | 804 | .name = VDPU2_DRIVER_NAME, |
|---|
| 844 | | - .pm = &vdpu_pm_ops, |
|---|
| 845 | 805 | .of_match_table = of_match_ptr(mpp_vdpu2_dt_match), |
|---|
| 846 | 806 | }, |
|---|
| 847 | 807 | }; |
|---|