55
55
#define IMX95_PE0_GEN_CTRL_3 0x1058
56
56
#define IMX95_PCIE_LTSSM_EN BIT(0)
57
57
58
+ #define IMX95_PE0_LUT_ACSCTRL 0x1008
59
+ #define IMX95_PEO_LUT_RWA BIT(16)
60
+ #define IMX95_PE0_LUT_ENLOC GENMASK(4, 0)
61
+
62
+ #define IMX95_PE0_LUT_DATA1 0x100c
63
+ #define IMX95_PE0_LUT_VLD BIT(31)
64
+ #define IMX95_PE0_LUT_DAC_ID GENMASK(10, 8)
65
+ #define IMX95_PE0_LUT_STREAM_ID GENMASK(5, 0)
66
+
67
+ #define IMX95_PE0_LUT_DATA2 0x1010
68
+ #define IMX95_PE0_LUT_REQID GENMASK(31, 16)
69
+ #define IMX95_PE0_LUT_MASK GENMASK(15, 0)
70
+
71
+ #define IMX95_SID_MASK GENMASK(5, 0)
72
+ #define IMX95_MAX_LUT 32
73
+
58
74
#define to_imx_pcie (x ) dev_get_drvdata((x)->dev)
59
75
60
76
enum imx_pcie_variants {
@@ -87,6 +103,7 @@ enum imx_pcie_variants {
87
103
* workaround suspend resume on some devices which are affected by this errata.
88
104
*/
89
105
#define IMX_PCIE_FLAG_BROKEN_SUSPEND BIT(9)
106
+ #define IMX_PCIE_FLAG_HAS_LUT BIT(10)
90
107
91
108
#define imx_check_flag (pci , val ) (pci->drvdata->flags & val)
92
109
@@ -139,6 +156,9 @@ struct imx_pcie {
139
156
struct device * pd_pcie_phy ;
140
157
struct phy * phy ;
141
158
const struct imx_pcie_drvdata * drvdata ;
159
+
160
+ /* Ensure that only one device's LUT is configured at any given time */
161
+ struct mutex lock ;
142
162
};
143
163
144
164
/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
@@ -930,6 +950,184 @@ static void imx_pcie_stop_link(struct dw_pcie *pci)
930
950
imx_pcie_ltssm_disable (dev );
931
951
}
932
952
953
+ static int imx_pcie_add_lut (struct imx_pcie * imx_pcie , u16 rid , u8 sid )
954
+ {
955
+ struct dw_pcie * pci = imx_pcie -> pci ;
956
+ struct device * dev = pci -> dev ;
957
+ u32 data1 , data2 ;
958
+ int free = -1 ;
959
+ int i ;
960
+
961
+ if (sid >= 64 ) {
962
+ dev_err (dev , "Invalid SID for index %d\n" , sid );
963
+ return - EINVAL ;
964
+ }
965
+
966
+ guard (mutex )(& imx_pcie -> lock );
967
+
968
+ /*
969
+ * Iterate through all LUT entries to check for duplicate RID and
970
+ * identify the first available entry. Configure this available entry
971
+ * immediately after verification to avoid rescanning it.
972
+ */
973
+ for (i = 0 ; i < IMX95_MAX_LUT ; i ++ ) {
974
+ regmap_write (imx_pcie -> iomuxc_gpr ,
975
+ IMX95_PE0_LUT_ACSCTRL , IMX95_PEO_LUT_RWA | i );
976
+ regmap_read (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_DATA1 , & data1 );
977
+
978
+ if (!(data1 & IMX95_PE0_LUT_VLD )) {
979
+ if (free < 0 )
980
+ free = i ;
981
+ continue ;
982
+ }
983
+
984
+ regmap_read (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_DATA2 , & data2 );
985
+
986
+ /* Do not add duplicate RID */
987
+ if (rid == FIELD_GET (IMX95_PE0_LUT_REQID , data2 )) {
988
+ dev_warn (dev , "Existing LUT entry available for RID (%d)" , rid );
989
+ return 0 ;
990
+ }
991
+ }
992
+
993
+ if (free < 0 ) {
994
+ dev_err (dev , "LUT entry is not available\n" );
995
+ return - ENOSPC ;
996
+ }
997
+
998
+ data1 = FIELD_PREP (IMX95_PE0_LUT_DAC_ID , 0 );
999
+ data1 |= FIELD_PREP (IMX95_PE0_LUT_STREAM_ID , sid );
1000
+ data1 |= IMX95_PE0_LUT_VLD ;
1001
+ regmap_write (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_DATA1 , data1 );
1002
+
1003
+ data2 = IMX95_PE0_LUT_MASK ; /* Match all bits of RID */
1004
+ data2 |= FIELD_PREP (IMX95_PE0_LUT_REQID , rid );
1005
+ regmap_write (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_DATA2 , data2 );
1006
+
1007
+ regmap_write (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_ACSCTRL , free );
1008
+
1009
+ return 0 ;
1010
+ }
1011
+
1012
+ static void imx_pcie_remove_lut (struct imx_pcie * imx_pcie , u16 rid )
1013
+ {
1014
+ u32 data2 ;
1015
+ int i ;
1016
+
1017
+ guard (mutex )(& imx_pcie -> lock );
1018
+
1019
+ for (i = 0 ; i < IMX95_MAX_LUT ; i ++ ) {
1020
+ regmap_write (imx_pcie -> iomuxc_gpr ,
1021
+ IMX95_PE0_LUT_ACSCTRL , IMX95_PEO_LUT_RWA | i );
1022
+ regmap_read (imx_pcie -> iomuxc_gpr , IMX95_PE0_LUT_DATA2 , & data2 );
1023
+ if (FIELD_GET (IMX95_PE0_LUT_REQID , data2 ) == rid ) {
1024
+ regmap_write (imx_pcie -> iomuxc_gpr ,
1025
+ IMX95_PE0_LUT_DATA1 , 0 );
1026
+ regmap_write (imx_pcie -> iomuxc_gpr ,
1027
+ IMX95_PE0_LUT_DATA2 , 0 );
1028
+ regmap_write (imx_pcie -> iomuxc_gpr ,
1029
+ IMX95_PE0_LUT_ACSCTRL , i );
1030
+
1031
+ break ;
1032
+ }
1033
+ }
1034
+ }
1035
+
1036
+ static int imx_pcie_enable_device (struct pci_host_bridge * bridge ,
1037
+ struct pci_dev * pdev )
1038
+ {
1039
+ struct imx_pcie * imx_pcie = to_imx_pcie (to_dw_pcie_from_pp (bridge -> sysdata ));
1040
+ u32 sid_i , sid_m , rid = pci_dev_id (pdev );
1041
+ struct device_node * target ;
1042
+ struct device * dev ;
1043
+ int err_i , err_m ;
1044
+ u32 sid = 0 ;
1045
+
1046
+ dev = imx_pcie -> pci -> dev ;
1047
+
1048
+ target = NULL ;
1049
+ err_i = of_map_id (dev -> of_node , rid , "iommu-map" , "iommu-map-mask" ,
1050
+ & target , & sid_i );
1051
+ if (target ) {
1052
+ of_node_put (target );
1053
+ } else {
1054
+ /*
1055
+ * "target == NULL && err_i == 0" means RID out of map range.
1056
+ * Use 1:1 map RID to streamID. Hardware can't support this
1057
+ * because the streamID is only 6 bits
1058
+ */
1059
+ err_i = - EINVAL ;
1060
+ }
1061
+
1062
+ target = NULL ;
1063
+ err_m = of_map_id (dev -> of_node , rid , "msi-map" , "msi-map-mask" ,
1064
+ & target , & sid_m );
1065
+
1066
+ /*
1067
+ * err_m target
1068
+ * 0 NULL RID out of range. Use 1:1 map RID to
1069
+ * streamID, Current hardware can't
1070
+ * support it, so return -EINVAL.
1071
+ * != 0 NULL msi-map does not exist, use built-in MSI
1072
+ * 0 != NULL Get correct streamID from RID
1073
+ * != 0 != NULL Invalid combination
1074
+ */
1075
+ if (!err_m && !target )
1076
+ return - EINVAL ;
1077
+ else if (target )
1078
+ of_node_put (target ); /* Find streamID map entry for RID in msi-map */
1079
+
1080
+ /*
1081
+ * msi-map iommu-map
1082
+ * N N DWC MSI Ctrl
1083
+ * Y Y ITS + SMMU, require the same SID
1084
+ * Y N ITS
1085
+ * N Y DWC MSI Ctrl + SMMU
1086
+ */
1087
+ if (err_i && err_m )
1088
+ return 0 ;
1089
+
1090
+ if (!err_i && !err_m ) {
1091
+ /*
1092
+ * Glue Layer
1093
+ * <==========>
1094
+ * ┌─────┐ ┌──────────┐
1095
+ * │ LUT │ 6-bit streamID │ │
1096
+ * │ │─────────────────►│ MSI │
1097
+ * └─────┘ 2-bit ctrl ID │ │
1098
+ * ┌───────────►│ │
1099
+ * (i.MX95) │ │ │
1100
+ * 00 PCIe0 │ │ │
1101
+ * 01 ENETC │ │ │
1102
+ * 10 PCIe1 │ │ │
1103
+ * │ └──────────┘
1104
+ * The MSI glue layer auto adds 2 bits controller ID ahead of
1105
+ * streamID, so mask these 2 bits to get streamID. The
1106
+ * IOMMU glue layer doesn't do that.
1107
+ */
1108
+ if (sid_i != (sid_m & IMX95_SID_MASK )) {
1109
+ dev_err (dev , "iommu-map and msi-map entries mismatch!\n" );
1110
+ return - EINVAL ;
1111
+ }
1112
+ }
1113
+
1114
+ if (!err_i )
1115
+ sid = sid_i ;
1116
+ else if (!err_m )
1117
+ sid = sid_m & IMX95_SID_MASK ;
1118
+
1119
+ return imx_pcie_add_lut (imx_pcie , rid , sid );
1120
+ }
1121
+
1122
+ static void imx_pcie_disable_device (struct pci_host_bridge * bridge ,
1123
+ struct pci_dev * pdev )
1124
+ {
1125
+ struct imx_pcie * imx_pcie ;
1126
+
1127
+ imx_pcie = to_imx_pcie (to_dw_pcie_from_pp (bridge -> sysdata ));
1128
+ imx_pcie_remove_lut (imx_pcie , pci_dev_id (pdev ));
1129
+ }
1130
+
933
1131
static int imx_pcie_host_init (struct dw_pcie_rp * pp )
934
1132
{
935
1133
struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
@@ -946,6 +1144,11 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
946
1144
}
947
1145
}
948
1146
1147
+ if (pp -> bridge && imx_check_flag (imx_pcie , IMX_PCIE_FLAG_HAS_LUT )) {
1148
+ pp -> bridge -> enable_device = imx_pcie_enable_device ;
1149
+ pp -> bridge -> disable_device = imx_pcie_disable_device ;
1150
+ }
1151
+
949
1152
imx_pcie_assert_core_reset (imx_pcie );
950
1153
951
1154
if (imx_pcie -> drvdata -> init_phy )
@@ -1330,6 +1533,8 @@ static int imx_pcie_probe(struct platform_device *pdev)
1330
1533
imx_pcie -> pci = pci ;
1331
1534
imx_pcie -> drvdata = of_device_get_match_data (dev );
1332
1535
1536
+ mutex_init (& imx_pcie -> lock );
1537
+
1333
1538
/* Find the PHY if one is defined, only imx7d uses it */
1334
1539
np = of_parse_phandle (node , "fsl,imx7d-pcie-phy" , 0 );
1335
1540
if (np ) {
@@ -1627,7 +1832,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
1627
1832
},
1628
1833
[IMX95 ] = {
1629
1834
.variant = IMX95 ,
1630
- .flags = IMX_PCIE_FLAG_HAS_SERDES ,
1835
+ .flags = IMX_PCIE_FLAG_HAS_SERDES |
1836
+ IMX_PCIE_FLAG_HAS_LUT ,
1631
1837
.clk_names = imx8mq_clks ,
1632
1838
.clks_cnt = ARRAY_SIZE (imx8mq_clks ),
1633
1839
.ltssm_off = IMX95_PE0_GEN_CTRL_3 ,
0 commit comments