Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

remoteproc: zynqmp: parse TCM from device tree

ZynqMP TCM information was fixed in driver. Now ZynqMP TCM information
is available in device-tree. Parse TCM information in driver
as per new bindings.

Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
Link: https://lore.kernel.org/r/20240412183708.4036007-5-tanmay.shah@amd.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

authored by

Tanmay Shah and committed by
Mathieu Poirier
72c350c9 9e1b2a07

+120 -7
+120 -7
drivers/remoteproc/xlnx_r5_remoteproc.c
··· 74 74 }; 75 75 76 76 /* 77 - * Hardcoded TCM bank values. This will be removed once TCM bindings are 78 - * accepted for system-dt specifications and upstreamed in linux kernel 77 + * Hardcoded TCM bank values. This will stay in driver to maintain backward 78 + * compatibility with device-tree that does not have TCM information. 79 79 */ 80 80 static const struct mem_bank_data zynqmp_tcm_banks_split[] = { 81 81 {0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */ ··· 761 761 return ERR_PTR(ret); 762 762 } 763 763 764 + static int zynqmp_r5_get_tcm_node_from_dt(struct zynqmp_r5_cluster *cluster) 765 + { 766 + int i, j, tcm_bank_count, ret, tcm_pd_idx, pd_count; 767 + struct of_phandle_args out_args; 768 + struct zynqmp_r5_core *r5_core; 769 + struct platform_device *cpdev; 770 + struct mem_bank_data *tcm; 771 + struct device_node *np; 772 + struct resource *res; 773 + u64 abs_addr, size; 774 + struct device *dev; 775 + 776 + for (i = 0; i < cluster->core_count; i++) { 777 + r5_core = cluster->r5_cores[i]; 778 + dev = r5_core->dev; 779 + np = r5_core->np; 780 + 781 + pd_count = of_count_phandle_with_args(np, "power-domains", 782 + "#power-domain-cells"); 783 + 784 + if (pd_count <= 0) { 785 + dev_err(dev, "invalid power-domains property, %d\n", pd_count); 786 + return -EINVAL; 787 + } 788 + 789 + /* First entry in power-domains list is for r5 core, rest for TCM. */ 790 + tcm_bank_count = pd_count - 1; 791 + 792 + if (tcm_bank_count <= 0) { 793 + dev_err(dev, "invalid TCM count %d\n", tcm_bank_count); 794 + return -EINVAL; 795 + } 796 + 797 + r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count, 798 + sizeof(struct mem_bank_data *), 799 + GFP_KERNEL); 800 + if (!r5_core->tcm_banks) 801 + return -ENOMEM; 802 + 803 + r5_core->tcm_bank_count = tcm_bank_count; 804 + for (j = 0, tcm_pd_idx = 1; j < tcm_bank_count; j++, tcm_pd_idx++) { 805 + tcm = devm_kzalloc(dev, sizeof(struct mem_bank_data), 806 + GFP_KERNEL); 807 + if (!tcm) 808 + return -ENOMEM; 809 + 810 + r5_core->tcm_banks[j] = tcm; 811 + 812 + /* Get power-domains id of TCM. */ 813 + ret = of_parse_phandle_with_args(np, "power-domains", 814 + "#power-domain-cells", 815 + tcm_pd_idx, &out_args); 816 + if (ret) { 817 + dev_err(r5_core->dev, 818 + "failed to get tcm %d pm domain, ret %d\n", 819 + tcm_pd_idx, ret); 820 + return ret; 821 + } 822 + tcm->pm_domain_id = out_args.args[0]; 823 + of_node_put(out_args.np); 824 + 825 + /* Get TCM address without translation. */ 826 + ret = of_property_read_reg(np, j, &abs_addr, &size); 827 + if (ret) { 828 + dev_err(dev, "failed to get reg property\n"); 829 + return ret; 830 + } 831 + 832 + /* 833 + * Remote processor can address only 32 bits 834 + * so convert 64-bits into 32-bits. This will discard 835 + * any unwanted upper 32-bits. 836 + */ 837 + tcm->da = (u32)abs_addr; 838 + tcm->size = (u32)size; 839 + 840 + cpdev = to_platform_device(dev); 841 + res = platform_get_resource(cpdev, IORESOURCE_MEM, j); 842 + if (!res) { 843 + dev_err(dev, "failed to get tcm resource\n"); 844 + return -EINVAL; 845 + } 846 + 847 + tcm->addr = (u32)res->start; 848 + tcm->bank_name = (char *)res->name; 849 + res = devm_request_mem_region(dev, tcm->addr, tcm->size, 850 + tcm->bank_name); 851 + if (!res) { 852 + dev_err(dev, "failed to request tcm resource\n"); 853 + return -EINVAL; 854 + } 855 + } 856 + } 857 + 858 + return 0; 859 + } 860 + 764 861 /** 765 862 * zynqmp_r5_get_tcm_node() 766 863 * Ideally this function should parse tcm node and store information ··· 936 839 struct zynqmp_r5_core *r5_core; 937 840 int ret, i; 938 841 939 - ret = zynqmp_r5_get_tcm_node(cluster); 940 - if (ret < 0) { 941 - dev_err(dev, "can't get tcm node, err %d\n", ret); 842 + r5_core = cluster->r5_cores[0]; 843 + 844 + /* Maintain backward compatibility for zynqmp by using hardcode TCM address. */ 845 + if (of_find_property(r5_core->np, "reg", NULL)) 846 + ret = zynqmp_r5_get_tcm_node_from_dt(cluster); 847 + else 848 + ret = zynqmp_r5_get_tcm_node(cluster); 849 + 850 + if (ret) { 851 + dev_err(dev, "can't get tcm, err %d\n", ret); 942 852 return ret; 943 853 } 944 854 ··· 1010 906 * fail driver probe if either of that is not set in dts. 1011 907 */ 1012 908 if (cluster_mode == LOCKSTEP_MODE) { 1013 - tcm_mode = PM_RPU_TCM_COMB; 1014 909 fw_reg_val = PM_RPU_MODE_LOCKSTEP; 1015 910 } else if (cluster_mode == SPLIT_MODE) { 1016 - tcm_mode = PM_RPU_TCM_SPLIT; 1017 911 fw_reg_val = PM_RPU_MODE_SPLIT; 1018 912 } else { 1019 913 dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode); 1020 914 return -EINVAL; 915 + } 916 + 917 + if (of_find_property(dev_node, "xlnx,tcm-mode", NULL)) { 918 + ret = of_property_read_u32(dev_node, "xlnx,tcm-mode", (u32 *)&tcm_mode); 919 + if (ret) 920 + return ret; 921 + } else { 922 + if (cluster_mode == LOCKSTEP_MODE) 923 + tcm_mode = PM_RPU_TCM_COMB; 924 + else 925 + tcm_mode = PM_RPU_TCM_SPLIT; 1021 926 } 1022 927 1023 928 /*