.. | .. |
---|
77 | 77 | struct thermal_zone_device *tz; |
---|
78 | 78 | const struct rockchip_pvtm_info *info; |
---|
79 | 79 | const struct rockchip_pvtm_ops *ops; |
---|
| 80 | + struct dentry *dentry; |
---|
80 | 81 | }; |
---|
81 | 82 | |
---|
82 | 83 | static LIST_HEAD(pvtm_list); |
---|
83 | 84 | |
---|
84 | 85 | #ifdef CONFIG_DEBUG_FS |
---|
85 | | - |
---|
86 | | -static struct dentry *rootdir; |
---|
| 86 | +static struct dentry *rockchip_pvtm_debugfs_root; |
---|
87 | 87 | |
---|
88 | 88 | static int pvtm_value_show(struct seq_file *s, void *data) |
---|
89 | 89 | { |
---|
.. | .. |
---|
125 | 125 | .release = single_release, |
---|
126 | 126 | }; |
---|
127 | 127 | |
---|
128 | | -static int __init pvtm_debug_init(void) |
---|
| 128 | +static int rockchip_pvtm_debugfs_init(void) |
---|
129 | 129 | { |
---|
130 | | - struct dentry *dentry, *d; |
---|
131 | | - struct rockchip_pvtm *pvtm; |
---|
132 | | - |
---|
133 | | - rootdir = debugfs_create_dir("pvtm", NULL); |
---|
134 | | - if (!rootdir) { |
---|
| 130 | + rockchip_pvtm_debugfs_root = debugfs_create_dir("pvtm", NULL); |
---|
| 131 | + if (IS_ERR_OR_NULL(rockchip_pvtm_debugfs_root)) { |
---|
135 | 132 | pr_err("Failed to create pvtm debug directory\n"); |
---|
| 133 | + rockchip_pvtm_debugfs_root = NULL; |
---|
136 | 134 | return -ENOMEM; |
---|
137 | | - } |
---|
138 | | - |
---|
139 | | - if (list_empty(&pvtm_list)) { |
---|
140 | | - pr_info("pvtm list NULL\n"); |
---|
141 | | - return 0; |
---|
142 | | - } |
---|
143 | | - |
---|
144 | | - list_for_each_entry(pvtm, &pvtm_list, node) { |
---|
145 | | - dentry = debugfs_create_dir(pvtm->info->name, rootdir); |
---|
146 | | - if (!dentry) { |
---|
147 | | - dev_err(pvtm->dev, "failed to creat pvtm %s debug dir\n", |
---|
148 | | - pvtm->info->name); |
---|
149 | | - return -ENOMEM; |
---|
150 | | - } |
---|
151 | | - |
---|
152 | | - d = debugfs_create_file("value", 0444, dentry, |
---|
153 | | - (void *)pvtm, &pvtm_value_fops); |
---|
154 | | - if (!d) { |
---|
155 | | - dev_err(pvtm->dev, "failed to pvtm %s value node\n", |
---|
156 | | - pvtm->info->name); |
---|
157 | | - return -ENOMEM; |
---|
158 | | - } |
---|
159 | 135 | } |
---|
160 | 136 | |
---|
161 | 137 | return 0; |
---|
162 | 138 | } |
---|
163 | 139 | |
---|
164 | | -late_initcall(pvtm_debug_init); |
---|
| 140 | +static void rockchip_pvtm_debugfs_exit(void) |
---|
| 141 | +{ |
---|
| 142 | + debugfs_remove_recursive(rockchip_pvtm_debugfs_root); |
---|
| 143 | +} |
---|
165 | 144 | |
---|
| 145 | +static int rockchip_pvtm_add_debugfs(struct rockchip_pvtm *pvtm) |
---|
| 146 | +{ |
---|
| 147 | + struct dentry *d; |
---|
| 148 | + |
---|
| 149 | + if (!rockchip_pvtm_debugfs_root) |
---|
| 150 | + return 0; |
---|
| 151 | + |
---|
| 152 | + pvtm->dentry = debugfs_create_dir(pvtm->info->name, |
---|
| 153 | + rockchip_pvtm_debugfs_root); |
---|
| 154 | + if (!pvtm->dentry) { |
---|
| 155 | + dev_err(pvtm->dev, "failed to create pvtm %s debug dir\n", |
---|
| 156 | + pvtm->info->name); |
---|
| 157 | + return -ENOMEM; |
---|
| 158 | + } |
---|
| 159 | + |
---|
| 160 | + d = debugfs_create_file("value", 0444, pvtm->dentry, |
---|
| 161 | + (void *)pvtm, &pvtm_value_fops); |
---|
| 162 | + if (!d) { |
---|
| 163 | + dev_err(pvtm->dev, "failed to pvtm %s value node\n", |
---|
| 164 | + pvtm->info->name); |
---|
| 165 | + debugfs_remove_recursive(pvtm->dentry); |
---|
| 166 | + return -ENOMEM; |
---|
| 167 | + } |
---|
| 168 | + |
---|
| 169 | + return 0; |
---|
| 170 | +} |
---|
| 171 | +#else |
---|
| 172 | +static inline int rockchip_pvtm_debugfs_init(void) |
---|
| 173 | +{ |
---|
| 174 | + return 0; |
---|
| 175 | +} |
---|
| 176 | + |
---|
| 177 | +static inline void rockchip_pvtm_debugfs_exit(void) |
---|
| 178 | +{ |
---|
| 179 | +} |
---|
| 180 | + |
---|
| 181 | +static inline int rockchip_pvtm_add_debugfs(struct rockchip_pvtm *pvtm) |
---|
| 182 | +{ |
---|
| 183 | + return 0; |
---|
| 184 | +} |
---|
166 | 185 | #endif |
---|
167 | 186 | |
---|
168 | 187 | static int rockchip_pvtm_reset(struct rockchip_pvtm *pvtm) |
---|
.. | .. |
---|
332 | 351 | clk_bulk_disable_unprepare(pvtm->num_clks, pvtm->clks); |
---|
333 | 352 | |
---|
334 | 353 | return val; |
---|
| 354 | +} |
---|
| 355 | + |
---|
| 356 | +static void rv1106_core_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm, |
---|
| 357 | + unsigned int ring_sel) |
---|
| 358 | +{ |
---|
| 359 | + writel_relaxed(wr_mask_bit(ring_sel + 4, 0x2, 0x7), pvtm->base + pvtm->con); |
---|
335 | 360 | } |
---|
336 | 361 | |
---|
337 | 362 | static void rv1126_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm, |
---|
.. | .. |
---|
582 | 607 | }, |
---|
583 | 608 | }; |
---|
584 | 609 | |
---|
| 610 | +static const struct rockchip_pvtm_info rk3588_bigcore0_pvtm_infos[] = { |
---|
| 611 | + PVTM(0, "bigcore0", 7, 0, 1, 0x4, 0, 0x4), |
---|
| 612 | +}; |
---|
| 613 | + |
---|
| 614 | +static const struct rockchip_pvtm_data rk3588_bigcore0_pvtm = { |
---|
| 615 | + .con = 0x4, |
---|
| 616 | + .sta = 0x80, |
---|
| 617 | + .num_pvtms = ARRAY_SIZE(rk3588_bigcore0_pvtm_infos), |
---|
| 618 | + .infos = rk3588_bigcore0_pvtm_infos, |
---|
| 619 | + .ops = { |
---|
| 620 | + .get_value = rv1126_pvtm_get_value, |
---|
| 621 | + .set_ring_sel = rv1126_pvtm_set_ring_sel, |
---|
| 622 | + }, |
---|
| 623 | +}; |
---|
| 624 | + |
---|
| 625 | +static const struct rockchip_pvtm_info rk3588_bigcore1_pvtm_infos[] = { |
---|
| 626 | + PVTM(1, "bigcore1", 7, 0, 1, 0x4, 0, 0x4), |
---|
| 627 | +}; |
---|
| 628 | + |
---|
| 629 | +static const struct rockchip_pvtm_data rk3588_bigcore1_pvtm = { |
---|
| 630 | + .con = 0x4, |
---|
| 631 | + .sta = 0x80, |
---|
| 632 | + .num_pvtms = ARRAY_SIZE(rk3588_bigcore1_pvtm_infos), |
---|
| 633 | + .infos = rk3588_bigcore1_pvtm_infos, |
---|
| 634 | + .ops = { |
---|
| 635 | + .get_value = rv1126_pvtm_get_value, |
---|
| 636 | + .set_ring_sel = rv1126_pvtm_set_ring_sel, |
---|
| 637 | + }, |
---|
| 638 | +}; |
---|
| 639 | + |
---|
| 640 | +static const struct rockchip_pvtm_info rk3588_litcore_pvtm_infos[] = { |
---|
| 641 | + PVTM(2, "litcore", 7, 0, 1, 0x4, 0, 0x4), |
---|
| 642 | +}; |
---|
| 643 | + |
---|
| 644 | +static const struct rockchip_pvtm_data rk3588_litcore_pvtm = { |
---|
| 645 | + .con = 0x4, |
---|
| 646 | + .sta = 0x80, |
---|
| 647 | + .num_pvtms = ARRAY_SIZE(rk3588_litcore_pvtm_infos), |
---|
| 648 | + .infos = rk3588_litcore_pvtm_infos, |
---|
| 649 | + .ops = { |
---|
| 650 | + .get_value = rv1126_pvtm_get_value, |
---|
| 651 | + .set_ring_sel = rv1126_pvtm_set_ring_sel, |
---|
| 652 | + }, |
---|
| 653 | +}; |
---|
| 654 | + |
---|
| 655 | +static const struct rockchip_pvtm_info rk3588_npu_pvtm_infos[] = { |
---|
| 656 | + PVTM(3, "npu", 2, 0, 1, 0x4, 0, 0x4), |
---|
| 657 | +}; |
---|
| 658 | + |
---|
| 659 | +static const struct rockchip_pvtm_data rk3588_npu_pvtm = { |
---|
| 660 | + .con = 0x4, |
---|
| 661 | + .sta = 0x80, |
---|
| 662 | + .num_pvtms = ARRAY_SIZE(rk3588_npu_pvtm_infos), |
---|
| 663 | + .infos = rk3588_npu_pvtm_infos, |
---|
| 664 | + .ops = { |
---|
| 665 | + .get_value = rv1126_pvtm_get_value, |
---|
| 666 | + .set_ring_sel = rv1126_pvtm_set_ring_sel, |
---|
| 667 | + }, |
---|
| 668 | +}; |
---|
| 669 | + |
---|
| 670 | +static const struct rockchip_pvtm_info rk3588_gpu_pvtm_infos[] = { |
---|
| 671 | + PVTM(4, "gpu", 2, 0, 1, 0x4, 0, 0x4), |
---|
| 672 | +}; |
---|
| 673 | + |
---|
| 674 | +static const struct rockchip_pvtm_data rk3588_gpu_pvtm = { |
---|
| 675 | + .con = 0x4, |
---|
| 676 | + .sta = 0x80, |
---|
| 677 | + .num_pvtms = ARRAY_SIZE(rk3588_gpu_pvtm_infos), |
---|
| 678 | + .infos = rk3588_gpu_pvtm_infos, |
---|
| 679 | + .ops = { |
---|
| 680 | + .get_value = rv1126_pvtm_get_value, |
---|
| 681 | + .set_ring_sel = rv1126_pvtm_set_ring_sel, |
---|
| 682 | + }, |
---|
| 683 | +}; |
---|
| 684 | + |
---|
| 685 | +static const struct rockchip_pvtm_info rk3588_pmu_pvtm_infos[] = { |
---|
| 686 | + PVTM(5, "pmu", 1, 0, 1, 0x4, 0, 0x4), |
---|
| 687 | +}; |
---|
| 688 | + |
---|
| 689 | +static const struct rockchip_pvtm_data rk3588_pmu_pvtm = { |
---|
| 690 | + .con = 0x4, |
---|
| 691 | + .sta = 0x80, |
---|
| 692 | + .num_pvtms = ARRAY_SIZE(rk3588_pmu_pvtm_infos), |
---|
| 693 | + .infos = rk3588_pmu_pvtm_infos, |
---|
| 694 | + .ops = { |
---|
| 695 | + .get_value = rv1126_pvtm_get_value, |
---|
| 696 | + }, |
---|
| 697 | +}; |
---|
| 698 | + |
---|
| 699 | +static const struct rockchip_pvtm_info rv1106_corepvtm_infos[] = { |
---|
| 700 | + PVTM(0, "core", 2, 0, 1, 0x4, 0, 0x4), |
---|
| 701 | +}; |
---|
| 702 | + |
---|
| 703 | +static const struct rockchip_pvtm_data rv1106_corepvtm = { |
---|
| 704 | + .con = 0x4, |
---|
| 705 | + .sta = 0x80, |
---|
| 706 | + .num_pvtms = ARRAY_SIZE(rv1106_corepvtm_infos), |
---|
| 707 | + .infos = rv1106_corepvtm_infos, |
---|
| 708 | + .ops = { |
---|
| 709 | + .get_value = rv1126_pvtm_get_value, |
---|
| 710 | + .set_ring_sel = rv1106_core_pvtm_set_ring_sel, |
---|
| 711 | + }, |
---|
| 712 | +}; |
---|
| 713 | + |
---|
| 714 | +static const struct rockchip_pvtm_info rv1106_pmupvtm_infos[] = { |
---|
| 715 | + PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4), |
---|
| 716 | +}; |
---|
| 717 | + |
---|
| 718 | +static const struct rockchip_pvtm_data rv1106_pmupvtm = { |
---|
| 719 | + .con = 0x4, |
---|
| 720 | + .sta = 0x80, |
---|
| 721 | + .num_pvtms = ARRAY_SIZE(rv1106_pmupvtm_infos), |
---|
| 722 | + .infos = rv1106_pmupvtm_infos, |
---|
| 723 | + .ops = { |
---|
| 724 | + .get_value = rv1126_pvtm_get_value, |
---|
| 725 | + }, |
---|
| 726 | +}; |
---|
| 727 | + |
---|
585 | 728 | static const struct rockchip_pvtm_info rv1126_cpupvtm_infos[] = { |
---|
586 | 729 | PVTM(0, "cpu", 7, 0, 1, 0x4, 0, 0x4), |
---|
587 | 730 | }; |
---|
.. | .. |
---|
691 | 834 | .data = (void *)&rk3568_npupvtm, |
---|
692 | 835 | }, |
---|
693 | 836 | #endif |
---|
| 837 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 838 | + { |
---|
| 839 | + .compatible = "rockchip,rk3588-bigcore0-pvtm", |
---|
| 840 | + .data = (void *)&rk3588_bigcore0_pvtm, |
---|
| 841 | + }, |
---|
| 842 | + { |
---|
| 843 | + .compatible = "rockchip,rk3588-bigcore1-pvtm", |
---|
| 844 | + .data = (void *)&rk3588_bigcore1_pvtm, |
---|
| 845 | + }, |
---|
| 846 | + { |
---|
| 847 | + .compatible = "rockchip,rk3588-litcore-pvtm", |
---|
| 848 | + .data = (void *)&rk3588_litcore_pvtm, |
---|
| 849 | + }, |
---|
| 850 | + { |
---|
| 851 | + .compatible = "rockchip,rk3588-gpu-pvtm", |
---|
| 852 | + .data = (void *)&rk3588_gpu_pvtm, |
---|
| 853 | + }, |
---|
| 854 | + { |
---|
| 855 | + .compatible = "rockchip,rk3588-npu-pvtm", |
---|
| 856 | + .data = (void *)&rk3588_npu_pvtm, |
---|
| 857 | + }, |
---|
| 858 | + { |
---|
| 859 | + .compatible = "rockchip,rk3588-pmu-pvtm", |
---|
| 860 | + .data = (void *)&rk3588_pmu_pvtm, |
---|
| 861 | + }, |
---|
| 862 | +#endif |
---|
| 863 | +#ifdef CONFIG_CPU_RV1106 |
---|
| 864 | + { |
---|
| 865 | + .compatible = "rockchip,rv1106-core-pvtm", |
---|
| 866 | + .data = (void *)&rv1106_corepvtm, |
---|
| 867 | + }, |
---|
| 868 | + { |
---|
| 869 | + .compatible = "rockchip,rv1106-pmu-pvtm", |
---|
| 870 | + .data = (void *)&rv1106_pmupvtm, |
---|
| 871 | + }, |
---|
| 872 | +#endif |
---|
694 | 873 | #ifdef CONFIG_CPU_RV1126 |
---|
695 | 874 | { |
---|
696 | 875 | .compatible = "rockchip,rv1126-cpu-pvtm", |
---|
.. | .. |
---|
731 | 910 | { |
---|
732 | 911 | struct rockchip_pvtm *pvtm; |
---|
733 | 912 | const char *tz_name; |
---|
734 | | - u32 id, index, i; |
---|
| 913 | + u32 id, index; |
---|
| 914 | + int i; |
---|
735 | 915 | |
---|
736 | 916 | if (of_property_read_u32(node, "reg", &id)) { |
---|
737 | 917 | dev_err(dev, "%s: failed to retrieve pvtm id\n", node->name); |
---|
.. | .. |
---|
765 | 945 | pvtm->num_clks = of_clk_get_parent_count(node); |
---|
766 | 946 | if (pvtm->num_clks <= 0) { |
---|
767 | 947 | dev_err(dev, "%s: does not have clocks\n", node->name); |
---|
768 | | - return NULL; |
---|
| 948 | + goto clk_num_err; |
---|
769 | 949 | } |
---|
770 | 950 | pvtm->clks = devm_kcalloc(dev, pvtm->num_clks, sizeof(*pvtm->clks), |
---|
771 | 951 | GFP_KERNEL); |
---|
772 | 952 | if (!pvtm->clks) |
---|
773 | | - return NULL; |
---|
| 953 | + goto clk_num_err; |
---|
774 | 954 | for (i = 0; i < pvtm->num_clks; i++) { |
---|
775 | 955 | pvtm->clks[i].clk = of_clk_get(node, i); |
---|
776 | 956 | if (IS_ERR(pvtm->clks[i].clk)) { |
---|
777 | 957 | dev_err(dev, "%s: failed to get clk at index %d\n", |
---|
778 | 958 | node->name, i); |
---|
779 | | - return NULL; |
---|
| 959 | + goto clk_err; |
---|
780 | 960 | } |
---|
781 | 961 | } |
---|
782 | 962 | |
---|
.. | .. |
---|
784 | 964 | if (IS_ERR(pvtm->rst)) |
---|
785 | 965 | dev_dbg(dev, "%s: failed to get reset\n", node->name); |
---|
786 | 966 | |
---|
| 967 | + rockchip_pvtm_add_debugfs(pvtm); |
---|
| 968 | + |
---|
787 | 969 | return pvtm; |
---|
788 | | -} |
---|
789 | 970 | |
---|
790 | | -static void rockchip_del_pvtm(const struct rockchip_pvtm_data *data) |
---|
791 | | -{ |
---|
792 | | - struct rockchip_pvtm *pvtm, *tmp; |
---|
793 | | - int i; |
---|
| 971 | +clk_err: |
---|
| 972 | + while (--i >= 0) |
---|
| 973 | + clk_put(pvtm->clks[i].clk); |
---|
| 974 | + devm_kfree(dev, pvtm->clks); |
---|
| 975 | +clk_num_err: |
---|
| 976 | + devm_kfree(dev, pvtm); |
---|
794 | 977 | |
---|
795 | | - if (list_empty(&pvtm_list)) |
---|
796 | | - return; |
---|
797 | | - |
---|
798 | | - for (i = 0; i < data->num_pvtms; i++) { |
---|
799 | | - list_for_each_entry_safe(pvtm, tmp, &pvtm_list, node) { |
---|
800 | | - if (pvtm->info->id == data->infos[i].id) |
---|
801 | | - list_del(&pvtm->node); |
---|
802 | | - } |
---|
803 | | - } |
---|
| 978 | + return NULL; |
---|
804 | 979 | } |
---|
805 | 980 | |
---|
806 | 981 | static int rockchip_pvtm_probe(struct platform_device *pdev) |
---|
.. | .. |
---|
832 | 1007 | for_each_available_child_of_node(np, node) { |
---|
833 | 1008 | pvtm = rockchip_pvtm_init(dev, node, match->data, grf, base); |
---|
834 | 1009 | if (!pvtm) { |
---|
835 | | - dev_err(dev, "failed to handle node %s\n", node->name); |
---|
836 | | - goto error; |
---|
| 1010 | + dev_err(dev, "failed to handle node %s\n", |
---|
| 1011 | + node->full_name); |
---|
| 1012 | + continue; |
---|
837 | 1013 | } |
---|
838 | 1014 | list_add(&pvtm->node, &pvtm_list); |
---|
| 1015 | + dev_info(dev, "%s probed\n", node->full_name); |
---|
839 | 1016 | } |
---|
840 | 1017 | |
---|
841 | 1018 | return 0; |
---|
842 | | - |
---|
843 | | -error: |
---|
844 | | - rockchip_del_pvtm(match->data); |
---|
845 | | - |
---|
846 | | - return -EINVAL; |
---|
847 | 1019 | } |
---|
848 | 1020 | |
---|
849 | 1021 | static struct platform_driver rockchip_pvtm_driver = { |
---|
.. | .. |
---|
854 | 1026 | }, |
---|
855 | 1027 | }; |
---|
856 | 1028 | |
---|
857 | | -module_platform_driver(rockchip_pvtm_driver); |
---|
| 1029 | +static int __init rockchip_pvtm_module_init(void) |
---|
| 1030 | +{ |
---|
| 1031 | + rockchip_pvtm_debugfs_init(); |
---|
| 1032 | + |
---|
| 1033 | + return platform_driver_register(&rockchip_pvtm_driver); |
---|
| 1034 | +} |
---|
| 1035 | +module_init(rockchip_pvtm_module_init); |
---|
| 1036 | + |
---|
| 1037 | +static void __exit rockchip_pvtm_module_exit(void) |
---|
| 1038 | +{ |
---|
| 1039 | + rockchip_pvtm_debugfs_exit(); |
---|
| 1040 | + platform_driver_unregister(&rockchip_pvtm_driver); |
---|
| 1041 | +} |
---|
| 1042 | +module_exit(rockchip_pvtm_module_exit); |
---|
858 | 1043 | |
---|
859 | 1044 | MODULE_DESCRIPTION("Rockchip PVTM driver"); |
---|
860 | 1045 | MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>"); |
---|