Commit 3ea675fc7bbc15f8a1b3b97d801bee2e9b4261e5
1 parent
8d2b169fd7
Exists in
imx_3.0.35_4.1.0
ENGR00298393 pcie: rc can access mem of ep
- setup one new outbound memory region at rc side, used to let imx6 pcie rc can access the memory of imx6 pcie ep in imx6 pcie rc ep validation system. - set the default address of the ddr memory to be 0x4000_0000 - change the test region size to be 15MB. NOTE: - default address 0x4000_0000 of ep side would be accessed in this demo. Test howto: step1: EP side: 1.1: echo 0x40000000 > /sys/devices/platform/imx-pcie/ep_bar0_addr 1.2: memtool -32 0x40000000 4 E Reading 0x4 count starting at address 0x40000000 0x40000000: EFE9EDF4 7583FB39 39EAFFEA FBDCFD78 step2: RC side: memtool -32 0x01000000=58D454DA memtool -32 0x01000004=7332095B step3: EP side: memtool -32 0x40000000 4 E Reading 0x4 count starting at address 0x40000000 0x40000000: 58D454DA 7332095B 39EAFFEA FBDCFD78 Signed-off-by: Richard Zhu <r65037@freescale.com>
Showing 1 changed file with 81 additions and 42 deletions Side-by-side Diff
arch/arm/mach-mx6/pcie.c
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | * |
4 | 4 | * PCIe host controller driver for IMX6 SOCs |
5 | 5 | * |
6 | - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. | |
6 | + * Copyright (C) 2012-2014 Freescale Semiconductor, Inc. All Rights Reserved. | |
7 | 7 | * |
8 | 8 | * Bits taken from arch/arm/mach-dove/pcie.c |
9 | 9 | * |
10 | 10 | |
11 | 11 | |
... | ... | @@ -163,16 +163,17 @@ |
163 | 163 | #define PCIE_CONF_REG(r) ((r) & ~0x3) |
164 | 164 | |
165 | 165 | /* |
166 | - * The default values of the RC's reserved ddr memory | |
167 | - * used to verify EP mode. | |
166 | + * The default value of the reserved ddr memory | |
167 | + * used to verify EP/RC memory space access operations. | |
168 | 168 | * BTW, here is the layout of the 1G ddr on SD boards |
169 | 169 | * 0x1000_0000 ~ 0x4FFF_FFFF |
170 | 170 | */ |
171 | -static u32 rc_ddr_test_region = 0x40000000; | |
172 | -static u32 rc_ddr_test_region_size = (SZ_16M - SZ_16K); | |
171 | +static u32 ddr_test_region = 0x40000000; | |
172 | +/* The upper 1MB space is reserved for CFG, MSI, and so on usage */ | |
173 | +static u32 ddr_test_region_size = (SZ_16M - SZ_1M); | |
173 | 174 | |
174 | 175 | #ifdef EP_SELF_IO_TEST |
175 | -static void *rc_ddr_test_reg1, *rc_ddr_test_reg2; | |
176 | +static void *ddr_test_reg1, *ddr_test_reg2; | |
176 | 177 | static void __iomem *pcie_arb_base_addr; |
177 | 178 | static struct timeval tv1, tv2, tv3; |
178 | 179 | static u32 tv_count1, tv_count2; |
179 | 180 | |
... | ... | @@ -396,10 +397,10 @@ |
396 | 397 | writel(0, dbi_base + ATU_VIEWPORT_R); |
397 | 398 | writel(PCIE_ARB_BASE_ADDR, dbi_base + ATU_REGION_LOWBASE_R); |
398 | 399 | writel(0, dbi_base + ATU_REGION_UPBASE_R); |
399 | - writel(PCIE_ARB_BASE_ADDR + rc_ddr_test_region_size, | |
400 | + writel(PCIE_ARB_BASE_ADDR + ddr_test_region_size, | |
400 | 401 | dbi_base + ATU_REGION_LIMIT_ADDR_R); |
401 | 402 | |
402 | - writel(rc_ddr_test_region, | |
403 | + writel(ddr_test_region, | |
403 | 404 | dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); |
404 | 405 | writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); |
405 | 406 | writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R); |
... | ... | @@ -424,6 +425,24 @@ |
424 | 425 | writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); |
425 | 426 | writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R); |
426 | 427 | writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); |
428 | + | |
429 | +#ifdef CONFIG_IMX_PCIE_RC_MODE_IN_EP_RC_SYS | |
430 | + /* | |
431 | + * region1 outbound used to access target mem | |
432 | + * in imx6 pcie ep/rc validation system | |
433 | + */ | |
434 | + writel(1, dbi_base + ATU_VIEWPORT_R); | |
435 | + writel(PCIE_ARB_BASE_ADDR, | |
436 | + dbi_base + ATU_REGION_LOWBASE_R); | |
437 | + writel(PCIE_ARB_BASE_ADDR + SZ_8M, | |
438 | + dbi_base + ATU_REGION_LIMIT_ADDR_R); | |
439 | + writel(0, dbi_base + ATU_REGION_UPBASE_R); | |
440 | + | |
441 | + writel(ddr_test_region, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); | |
442 | + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); | |
443 | + writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R); | |
444 | + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); | |
445 | +#endif | |
427 | 446 | } |
428 | 447 | |
429 | 448 | #ifdef CONFIG_PCI_MSI |
430 | 449 | |
431 | 450 | |
432 | 451 | |
... | ... | @@ -875,15 +894,33 @@ |
875 | 894 | } |
876 | 895 | |
877 | 896 | #ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS |
878 | -static ssize_t imx_pcie_rc_memw_info(struct device *dev, | |
897 | +static ssize_t imx_pcie_bar0_addr_info(struct device *dev, | |
879 | 898 | struct device_attribute *devattr, char *buf) |
880 | 899 | { |
900 | + return sprintf(buf, "imx-pcie-bar0-addr-info start 0x%08x\n", | |
901 | + readl(dbi_base + PCI_BASE_ADDRESS_0)); | |
902 | +} | |
903 | + | |
904 | +static ssize_t imx_pcie_bar0_addr_start(struct device *dev, | |
905 | + struct device_attribute *attr, const char *buf, size_t count) | |
906 | +{ | |
907 | + u32 bar_start; | |
908 | + | |
909 | + sscanf(buf, "%x\n", &bar_start); | |
910 | + writel(bar_start, dbi_base + PCI_BASE_ADDRESS_0); | |
911 | + | |
912 | + return count; | |
913 | +} | |
914 | + | |
915 | +static ssize_t imx_pcie_memw_info(struct device *dev, | |
916 | + struct device_attribute *devattr, char *buf) | |
917 | +{ | |
881 | 918 | return sprintf(buf, "imx-pcie-rc-memw-info start 0x%08x, size 0x%08x\n", |
882 | - rc_ddr_test_region, rc_ddr_test_region_size); | |
919 | + ddr_test_region, ddr_test_region_size); | |
883 | 920 | } |
884 | 921 | |
885 | 922 | static ssize_t |
886 | -imx_pcie_rc_memw_start(struct device *dev, struct device_attribute *attr, | |
923 | +imx_pcie_memw_start(struct device *dev, struct device_attribute *attr, | |
887 | 924 | const char *buf, size_t count) |
888 | 925 | { |
889 | 926 | u32 memw_start; |
... | ... | @@ -896,8 +933,8 @@ |
896 | 933 | return -1; |
897 | 934 | } |
898 | 935 | |
899 | - if (rc_ddr_test_region != memw_start) { | |
900 | - rc_ddr_test_region = memw_start; | |
936 | + if (ddr_test_region != memw_start) { | |
937 | + ddr_test_region = memw_start; | |
901 | 938 | /* Re-setup the iATU */ |
902 | 939 | imx_pcie_regions_setup(dev, dbi_base); |
903 | 940 | } |
904 | 941 | |
905 | 942 | |
... | ... | @@ -906,21 +943,21 @@ |
906 | 943 | } |
907 | 944 | |
908 | 945 | static ssize_t |
909 | -imx_pcie_rc_memw_size(struct device *dev, struct device_attribute *attr, | |
946 | +imx_pcie_memw_size(struct device *dev, struct device_attribute *attr, | |
910 | 947 | const char *buf, size_t count) |
911 | 948 | { |
912 | 949 | u32 memw_size; |
913 | 950 | |
914 | 951 | sscanf(buf, "%x\n", &memw_size); |
915 | 952 | |
916 | - if ((memw_size > (SZ_16M - SZ_16K)) || (memw_size < SZ_64K)) { | |
917 | - dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_16KB].\n"); | |
953 | + if ((memw_size > (SZ_16M - SZ_1M)) || (memw_size < SZ_64K)) { | |
954 | + dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_1MB].\n"); | |
918 | 955 | dev_info(dev, "For example: echo 0x800000 > /sys/..."); |
919 | 956 | return -1; |
920 | 957 | } |
921 | 958 | |
922 | - if (rc_ddr_test_region_size != memw_size) { | |
923 | - rc_ddr_test_region_size = memw_size; | |
959 | + if (ddr_test_region_size != memw_size) { | |
960 | + ddr_test_region_size = memw_size; | |
924 | 961 | /* Re-setup the iATU */ |
925 | 962 | imx_pcie_regions_setup(dev, dbi_base); |
926 | 963 | } |
927 | 964 | |
928 | 965 | |
... | ... | @@ -928,19 +965,22 @@ |
928 | 965 | return count; |
929 | 966 | } |
930 | 967 | |
931 | -static DEVICE_ATTR(rc_memw_info, S_IRUGO, imx_pcie_rc_memw_info, NULL); | |
932 | -static DEVICE_ATTR(rc_memw_start_set, S_IWUGO, NULL, imx_pcie_rc_memw_start); | |
933 | -static DEVICE_ATTR(rc_memw_size_set, S_IWUGO, NULL, imx_pcie_rc_memw_size); | |
968 | +static DEVICE_ATTR(memw_info, S_IRUGO, imx_pcie_memw_info, NULL); | |
969 | +static DEVICE_ATTR(memw_start_set, S_IWUGO, NULL, imx_pcie_memw_start); | |
970 | +static DEVICE_ATTR(memw_size_set, S_IWUGO, NULL, imx_pcie_memw_size); | |
971 | +static DEVICE_ATTR(ep_bar0_addr, S_IRWXUGO, imx_pcie_bar0_addr_info, | |
972 | + imx_pcie_bar0_addr_start); | |
934 | 973 | |
935 | 974 | static struct attribute *imx_pcie_attrs[] = { |
936 | 975 | /* |
937 | - * The start address, and the limitation (64KB ~ (16MB - 16KB)) | |
976 | + * The start address, and the limitation (64KB ~ (16MB - 1MB)) | |
938 | 977 | * of the ddr mem window reserved by RC, and used for EP to access. |
939 | 978 | * BTW, these attrs are only configured at EP side. |
940 | 979 | */ |
941 | - &dev_attr_rc_memw_info.attr, | |
942 | - &dev_attr_rc_memw_start_set.attr, | |
943 | - &dev_attr_rc_memw_size_set.attr, | |
980 | + &dev_attr_memw_info.attr, | |
981 | + &dev_attr_memw_start_set.attr, | |
982 | + &dev_attr_memw_size_set.attr, | |
983 | + &dev_attr_ep_bar0_addr.attr, | |
944 | 984 | NULL |
945 | 985 | }; |
946 | 986 | |
947 | 987 | |
948 | 988 | |
949 | 989 | |
950 | 990 | |
... | ... | @@ -1032,30 +1072,30 @@ |
1032 | 1072 | if (pdata->type_ep) { |
1033 | 1073 | #ifdef EP_SELF_IO_TEST |
1034 | 1074 | /* Prepare the test regions and data */ |
1035 | - rc_ddr_test_reg1 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL); | |
1036 | - if (!rc_ddr_test_reg1) | |
1075 | + ddr_test_reg1 = kzalloc(ddr_test_region_size, GFP_KERNEL); | |
1076 | + if (!ddr_test_reg1) | |
1037 | 1077 | pr_err("PCIe EP: can't alloc the test region1.\n"); |
1038 | 1078 | |
1039 | - rc_ddr_test_reg2 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL); | |
1040 | - if (!rc_ddr_test_reg2) { | |
1041 | - kfree(rc_ddr_test_reg1); | |
1079 | + ddr_test_reg2 = kzalloc(ddr_test_region_size, GFP_KERNEL); | |
1080 | + if (!ddr_test_reg2) { | |
1081 | + kfree(ddr_test_reg1); | |
1042 | 1082 | pr_err("PCIe EP: can't alloc the test region2.\n"); |
1043 | 1083 | } |
1044 | 1084 | |
1045 | 1085 | pcie_arb_base_addr = ioremap_cached(PCIE_ARB_BASE_ADDR, |
1046 | - rc_ddr_test_region_size); | |
1086 | + ddr_test_region_size); | |
1047 | 1087 | |
1048 | 1088 | if (!pcie_arb_base_addr) { |
1049 | 1089 | pr_err("error with ioremap in function %s\n", __func__); |
1050 | 1090 | ret = PTR_ERR(pcie_arb_base_addr); |
1051 | - kfree(rc_ddr_test_reg2); | |
1052 | - kfree(rc_ddr_test_reg1); | |
1091 | + kfree(ddr_test_reg2); | |
1092 | + kfree(ddr_test_reg1); | |
1053 | 1093 | goto err_base; |
1054 | 1094 | } |
1055 | 1095 | |
1056 | - for (i = 0; i < rc_ddr_test_region_size; i = i + 4) { | |
1057 | - writel(0xE6600D00 + i, rc_ddr_test_reg1 + i); | |
1058 | - writel(0xDEADBEAF, rc_ddr_test_reg2 + i); | |
1096 | + for (i = 0; i < ddr_test_region_size; i = i + 4) { | |
1097 | + writel(0xE6600D00 + i, ddr_test_reg1 + i); | |
1098 | + writel(0xDEADBEAF, ddr_test_reg2 + i); | |
1059 | 1099 | } |
1060 | 1100 | #endif |
1061 | 1101 | |
... | ... | @@ -1070,8 +1110,8 @@ |
1070 | 1110 | } else { |
1071 | 1111 | pr_info("PCIe EP: ERROR link is down, exit!\n"); |
1072 | 1112 | #ifdef EP_SELF_IO_TEST |
1073 | - kfree(rc_ddr_test_reg2); | |
1074 | - kfree(rc_ddr_test_reg1); | |
1113 | + kfree(ddr_test_reg2); | |
1114 | + kfree(ddr_test_reg1); | |
1075 | 1115 | iounmap(pcie_arb_base_addr); |
1076 | 1116 | #endif |
1077 | 1117 | goto err_link_down; |
1078 | 1118 | |
1079 | 1119 | |
... | ... | @@ -1084,16 +1124,16 @@ |
1084 | 1124 | do_gettimeofday(&tv1); |
1085 | 1125 | |
1086 | 1126 | memcpy((unsigned long *)pcie_arb_base_addr, |
1087 | - (unsigned long *)rc_ddr_test_reg1, 0xFFC000); | |
1127 | + (unsigned long *)ddr_test_reg1, 0xFFC000); | |
1088 | 1128 | |
1089 | 1129 | do_gettimeofday(&tv2); |
1090 | 1130 | |
1091 | - memcpy((unsigned long *)rc_ddr_test_reg2, | |
1131 | + memcpy((unsigned long *)ddr_test_reg2, | |
1092 | 1132 | (unsigned long *)pcie_arb_base_addr, 0xFFC000); |
1093 | 1133 | |
1094 | 1134 | do_gettimeofday(&tv3); |
1095 | 1135 | |
1096 | - if (memcmp(rc_ddr_test_reg2, rc_ddr_test_reg1, 0xFFC000) != 0) { | |
1136 | + if (memcmp(ddr_test_reg2, ddr_test_reg1, 0xFFC000) != 0) { | |
1097 | 1137 | pr_info("PCIe EP: Data transfer is failed.\n"); |
1098 | 1138 | } else { |
1099 | 1139 | tv_count1 = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC |
... | ... | @@ -1112,7 +1152,6 @@ |
1112 | 1152 | /(tv_count2)); |
1113 | 1153 | } |
1114 | 1154 | #endif |
1115 | - | |
1116 | 1155 | } else { |
1117 | 1156 | /* add the pcie port */ |
1118 | 1157 | add_pcie_port(base, dbi_base, pdata); |