.. | .. |
---|
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" |
---|
28 | 26 | #include "mpp_common.h" |
---|
29 | 27 | #include "mpp_iommu.h" |
---|
| 28 | +#include <soc/rockchip/rockchip_iommu.h> |
---|
30 | 29 | |
---|
31 | 30 | #define VDPU1_DRIVER_NAME "mpp_vdpu1" |
---|
32 | 31 | |
---|
.. | .. |
---|
268 | 267 | offset = task->reg[idx] >> 10 << 4; |
---|
269 | 268 | } |
---|
270 | 269 | mem_region = mpp_task_attach_fd(&task->mpp_task, fd); |
---|
271 | | - if (IS_ERR(mem_region)) |
---|
| 270 | + if (IS_ERR(mem_region)) { |
---|
| 271 | + mpp_err("reg[%03d]: %08x fd %d attach failed\n", |
---|
| 272 | + idx, task->reg[idx], fd); |
---|
272 | 273 | goto fail; |
---|
| 274 | + } |
---|
273 | 275 | |
---|
274 | 276 | iova = mem_region->iova; |
---|
275 | 277 | mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", |
---|
.. | .. |
---|
569 | 571 | return 0; |
---|
570 | 572 | } |
---|
571 | 573 | |
---|
| 574 | +static int vdpu_3036_init(struct mpp_dev *mpp) |
---|
| 575 | +{ |
---|
| 576 | + vdpu_init(mpp); |
---|
| 577 | + set_bit(mpp->var->device_type, &mpp->queue->dev_active_flags); |
---|
| 578 | + return 0; |
---|
| 579 | +} |
---|
| 580 | + |
---|
572 | 581 | static int vdpu_clk_on(struct mpp_dev *mpp) |
---|
573 | 582 | { |
---|
574 | 583 | struct vdpu_dev *dec = to_vdpu_dev(mpp); |
---|
.. | .. |
---|
685 | 694 | static int vdpu_soft_reset(struct mpp_dev *mpp) |
---|
686 | 695 | { |
---|
687 | 696 | u32 val; |
---|
| 697 | + u32 ret; |
---|
688 | 698 | |
---|
689 | 699 | mpp_write(mpp, VDPU1_REG_SOFT_RESET, 1); |
---|
690 | | - udelay(2); |
---|
691 | | - val = mpp_read(mpp, VDPU1_REG_SOFT_RESET); |
---|
| 700 | + ret = readl_relaxed_poll_timeout(mpp->reg_base + VDPU1_REG_SOFT_RESET, |
---|
| 701 | + val, !val, 0, 5); |
---|
692 | 702 | |
---|
693 | | - return val; |
---|
| 703 | + return ret; |
---|
694 | 704 | } |
---|
695 | 705 | |
---|
696 | 706 | static int vdpu_reset(struct mpp_dev *mpp) |
---|
.. | .. |
---|
701 | 711 | /* soft reset first */ |
---|
702 | 712 | ret = vdpu_soft_reset(mpp); |
---|
703 | 713 | if (ret && dec->rst_a && dec->rst_h) { |
---|
| 714 | + mpp_err("soft reset failed, use cru reset!\n"); |
---|
704 | 715 | mpp_debug(DEBUG_RESET, "reset in\n"); |
---|
705 | 716 | |
---|
706 | 717 | /* Don't skip this or iommu won't work after reset */ |
---|
.. | .. |
---|
719 | 730 | return 0; |
---|
720 | 731 | } |
---|
721 | 732 | |
---|
| 733 | +static int vdpu_3036_set_grf(struct mpp_dev *mpp) |
---|
| 734 | +{ |
---|
| 735 | + int grf_changed; |
---|
| 736 | + struct mpp_dev *loop = NULL, *n; |
---|
| 737 | + struct mpp_taskqueue *queue = mpp->queue; |
---|
| 738 | + bool pd_is_on; |
---|
| 739 | + |
---|
| 740 | + grf_changed = mpp_grf_is_changed(mpp->grf_info); |
---|
| 741 | + if (grf_changed) { |
---|
| 742 | + |
---|
| 743 | + /* |
---|
| 744 | + * in this case, devices share the queue also share the same pd&clk, |
---|
| 745 | + * so use mpp->dev's pd to control all the process is okay |
---|
| 746 | + */ |
---|
| 747 | + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); |
---|
| 748 | + if (!pd_is_on) |
---|
| 749 | + rockchip_pmu_pd_on(mpp->dev); |
---|
| 750 | + mpp->hw_ops->clk_on(mpp); |
---|
| 751 | + |
---|
| 752 | + list_for_each_entry_safe(loop, n, &queue->dev_list, queue_link) { |
---|
| 753 | + if (test_bit(loop->var->device_type, &queue->dev_active_flags)) { |
---|
| 754 | + mpp_set_grf(loop->grf_info); |
---|
| 755 | + if (loop->hw_ops->clk_on) |
---|
| 756 | + loop->hw_ops->clk_on(loop); |
---|
| 757 | + if (loop->hw_ops->reset) |
---|
| 758 | + loop->hw_ops->reset(loop); |
---|
| 759 | + rockchip_iommu_disable(loop->dev); |
---|
| 760 | + if (loop->hw_ops->clk_off) |
---|
| 761 | + loop->hw_ops->clk_off(loop); |
---|
| 762 | + clear_bit(loop->var->device_type, &queue->dev_active_flags); |
---|
| 763 | + } |
---|
| 764 | + } |
---|
| 765 | + |
---|
| 766 | + mpp_set_grf(mpp->grf_info); |
---|
| 767 | + rockchip_iommu_enable(mpp->dev); |
---|
| 768 | + set_bit(mpp->var->device_type, &queue->dev_active_flags); |
---|
| 769 | + |
---|
| 770 | + mpp->hw_ops->clk_off(mpp); |
---|
| 771 | + if (!pd_is_on) |
---|
| 772 | + rockchip_pmu_pd_off(mpp->dev); |
---|
| 773 | + } |
---|
| 774 | + |
---|
| 775 | + return 0; |
---|
| 776 | +} |
---|
| 777 | + |
---|
722 | 778 | static struct mpp_hw_ops vdpu_v1_hw_ops = { |
---|
723 | 779 | .init = vdpu_init, |
---|
724 | 780 | .clk_on = vdpu_clk_on, |
---|
.. | .. |
---|
726 | 782 | .set_freq = vdpu_set_freq, |
---|
727 | 783 | .reduce_freq = vdpu_reduce_freq, |
---|
728 | 784 | .reset = vdpu_reset, |
---|
| 785 | + .set_grf = vdpu_3036_set_grf, |
---|
| 786 | +}; |
---|
| 787 | + |
---|
| 788 | +static struct mpp_hw_ops vdpu_3036_hw_ops = { |
---|
| 789 | + .init = vdpu_3036_init, |
---|
| 790 | + .clk_on = vdpu_clk_on, |
---|
| 791 | + .clk_off = vdpu_clk_off, |
---|
| 792 | + .set_freq = vdpu_set_freq, |
---|
| 793 | + .reduce_freq = vdpu_reduce_freq, |
---|
| 794 | + .reset = vdpu_reset, |
---|
| 795 | + .set_grf = vdpu_3036_set_grf, |
---|
729 | 796 | }; |
---|
730 | 797 | |
---|
731 | 798 | static struct mpp_hw_ops vdpu_3288_hw_ops = { |
---|
.. | .. |
---|
766 | 833 | .dev_ops = &vdpu_v1_dev_ops, |
---|
767 | 834 | }; |
---|
768 | 835 | |
---|
| 836 | +static const struct mpp_dev_var vdpu_3036_data = { |
---|
| 837 | + .device_type = MPP_DEVICE_VDPU1, |
---|
| 838 | + .hw_info = &vdpu_v1_hw_info, |
---|
| 839 | + .trans_info = vdpu_v1_trans, |
---|
| 840 | + .hw_ops = &vdpu_3036_hw_ops, |
---|
| 841 | + .dev_ops = &vdpu_v1_dev_ops, |
---|
| 842 | +}; |
---|
| 843 | + |
---|
769 | 844 | static const struct mpp_dev_var vdpu_3288_data = { |
---|
770 | 845 | .device_type = MPP_DEVICE_VDPU1, |
---|
771 | 846 | .hw_info = &vdpu_v1_hw_info, |
---|
.. | .. |
---|
801 | 876 | .data = &vdpu_3288_data, |
---|
802 | 877 | }, |
---|
803 | 878 | #endif |
---|
| 879 | +#ifdef CONFIG_CPU_RK3036 |
---|
| 880 | + { |
---|
| 881 | + .compatible = "rockchip,vpu-decoder-rk3036", |
---|
| 882 | + .data = &vdpu_3036_data, |
---|
| 883 | + }, |
---|
| 884 | +#endif |
---|
804 | 885 | #ifdef CONFIG_CPU_RK3368 |
---|
805 | 886 | { |
---|
806 | 887 | .compatible = "rockchip,vpu-decoder-rk3368", |
---|
.. | .. |
---|
826 | 907 | dec = devm_kzalloc(dev, sizeof(struct vdpu_dev), GFP_KERNEL); |
---|
827 | 908 | if (!dec) |
---|
828 | 909 | return -ENOMEM; |
---|
829 | | - platform_set_drvdata(pdev, dec); |
---|
830 | | - |
---|
831 | 910 | mpp = &dec->mpp; |
---|
| 911 | + platform_set_drvdata(pdev, mpp); |
---|
| 912 | + |
---|
832 | 913 | if (pdev->dev.of_node) { |
---|
833 | 914 | match = of_match_node(mpp_vdpu1_dt_match, pdev->dev.of_node); |
---|
834 | 915 | if (match) |
---|
835 | 916 | mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 917 | + |
---|
| 918 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vdpu"); |
---|
836 | 919 | } |
---|
837 | 920 | |
---|
838 | 921 | ret = mpp_dev_probe(mpp, pdev); |
---|
.. | .. |
---|
868 | 951 | static int vdpu_remove(struct platform_device *pdev) |
---|
869 | 952 | { |
---|
870 | 953 | struct device *dev = &pdev->dev; |
---|
871 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
---|
| 954 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
872 | 955 | |
---|
873 | 956 | dev_info(dev, "remove device\n"); |
---|
874 | | - mpp_dev_remove(&dec->mpp); |
---|
875 | | - vdpu_procfs_remove(&dec->mpp); |
---|
| 957 | + mpp_dev_remove(mpp); |
---|
| 958 | + vdpu_procfs_remove(mpp); |
---|
876 | 959 | |
---|
877 | 960 | return 0; |
---|
878 | 961 | } |
---|
879 | | - |
---|
880 | | -static void vdpu_shutdown(struct platform_device *pdev) |
---|
881 | | -{ |
---|
882 | | - int ret; |
---|
883 | | - int val; |
---|
884 | | - struct device *dev = &pdev->dev; |
---|
885 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
---|
886 | | - struct mpp_dev *mpp = &dec->mpp; |
---|
887 | | - |
---|
888 | | - dev_info(dev, "shutdown device\n"); |
---|
889 | | - |
---|
890 | | - atomic_inc(&mpp->srv->shutdown_request); |
---|
891 | | - ret = readx_poll_timeout(atomic_read, |
---|
892 | | - &mpp->task_count, |
---|
893 | | - val, val == 0, 20000, 200000); |
---|
894 | | - if (ret == -ETIMEDOUT) |
---|
895 | | - dev_err(dev, "wait total running time out\n"); |
---|
896 | | -} |
---|
897 | | - |
---|
898 | | -static int vdpu_runtime_suspend(struct device *dev) |
---|
899 | | -{ |
---|
900 | | - struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
901 | | - struct mpp_grf_info *info = mpp->grf_info; |
---|
902 | | - struct mpp_taskqueue *queue = mpp->queue; |
---|
903 | | - |
---|
904 | | - if (cpu_is_rk3528() && info && info->mem_offset) { |
---|
905 | | - mutex_lock(&queue->ref_lock); |
---|
906 | | - if (!atomic_dec_if_positive(&queue->runtime_cnt)) { |
---|
907 | | - regmap_write(info->grf, info->mem_offset, |
---|
908 | | - info->val_mem_off); |
---|
909 | | - } |
---|
910 | | - mutex_unlock(&queue->ref_lock); |
---|
911 | | - } |
---|
912 | | - |
---|
913 | | - return 0; |
---|
914 | | -} |
---|
915 | | - |
---|
916 | | -static int vdpu_runtime_resume(struct device *dev) |
---|
917 | | -{ |
---|
918 | | - struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
919 | | - struct mpp_grf_info *info = mpp->grf_info; |
---|
920 | | - struct mpp_taskqueue *queue = mpp->queue; |
---|
921 | | - |
---|
922 | | - if (cpu_is_rk3528() && info && info->mem_offset) { |
---|
923 | | - mutex_lock(&queue->ref_lock); |
---|
924 | | - regmap_write(info->grf, info->mem_offset, |
---|
925 | | - info->val_mem_on); |
---|
926 | | - atomic_inc(&queue->runtime_cnt); |
---|
927 | | - mutex_unlock(&queue->ref_lock); |
---|
928 | | - } |
---|
929 | | - |
---|
930 | | - return 0; |
---|
931 | | -} |
---|
932 | | - |
---|
933 | | -static const struct dev_pm_ops vdpu_pm_ops = { |
---|
934 | | - .runtime_suspend = vdpu_runtime_suspend, |
---|
935 | | - .runtime_resume = vdpu_runtime_resume, |
---|
936 | | -}; |
---|
937 | 962 | |
---|
938 | 963 | struct platform_driver rockchip_vdpu1_driver = { |
---|
939 | 964 | .probe = vdpu_probe, |
---|
940 | 965 | .remove = vdpu_remove, |
---|
941 | | - .shutdown = vdpu_shutdown, |
---|
| 966 | + .shutdown = mpp_dev_shutdown, |
---|
942 | 967 | .driver = { |
---|
943 | 968 | .name = VDPU1_DRIVER_NAME, |
---|
944 | | - .pm = &vdpu_pm_ops, |
---|
945 | 969 | .of_match_table = of_match_ptr(mpp_vdpu1_dt_match), |
---|
946 | 970 | }, |
---|
947 | 971 | }; |
---|