| .. | .. |
|---|
| 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>"); |
|---|