diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2018-08-15 15:59:15 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-08-15 15:59:15 -0400 |
commit | 323fc7509a2a752207924dee9866a1b4f2838db4 (patch) | |
tree | 5e42ce5793856f3b00a71c627838e327e30b7910 | |
parent | 732c47019de9033a68ba50175b469c9cd105df73 (diff) | |
parent | f23d0d449c169d94cc958196a1d088705ef26ebc (diff) |
Merge branch 'remotes/lorenzo/pci/mvebu'
- Fix mvebu I/O space remapping issues (Thomas Petazzoni)
- Use generic pci_host_bridge in mvebu instead of ARM-specific API
(Thomas Petazzoni)
* remotes/lorenzo/pci/mvebu:
PCI: mvebu: Drop bogus comment above mvebu_pcie_map_registers()
PCI: mvebu: Convert to use pci_host_bridge directly
PCI: mvebu: Use resource_size() to remap I/O space
PCI: mvebu: Only remap I/O space if configured
PCI: mvebu: Fix I/O space end address calculation
PCI: mvebu: Remove redundant platform_set_drvdata() call
-rw-r--r-- | drivers/pci/controller/pci-mvebu.c | 153 |
1 files changed, 68 insertions, 85 deletions
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 23e270839e6a..50eb0729385b 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c | |||
@@ -125,6 +125,7 @@ struct mvebu_pcie { | |||
125 | struct platform_device *pdev; | 125 | struct platform_device *pdev; |
126 | struct mvebu_pcie_port *ports; | 126 | struct mvebu_pcie_port *ports; |
127 | struct msi_controller *msi; | 127 | struct msi_controller *msi; |
128 | struct list_head resources; | ||
128 | struct resource io; | 129 | struct resource io; |
129 | struct resource realio; | 130 | struct resource realio; |
130 | struct resource mem; | 131 | struct resource mem; |
@@ -800,7 +801,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, | |||
800 | static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | 801 | static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, |
801 | int where, int size, u32 val) | 802 | int where, int size, u32 val) |
802 | { | 803 | { |
803 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 804 | struct mvebu_pcie *pcie = bus->sysdata; |
804 | struct mvebu_pcie_port *port; | 805 | struct mvebu_pcie_port *port; |
805 | int ret; | 806 | int ret; |
806 | 807 | ||
@@ -826,7 +827,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
826 | static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | 827 | static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, |
827 | int size, u32 *val) | 828 | int size, u32 *val) |
828 | { | 829 | { |
829 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 830 | struct mvebu_pcie *pcie = bus->sysdata; |
830 | struct mvebu_pcie_port *port; | 831 | struct mvebu_pcie_port *port; |
831 | int ret; | 832 | int ret; |
832 | 833 | ||
@@ -857,36 +858,6 @@ static struct pci_ops mvebu_pcie_ops = { | |||
857 | .write = mvebu_pcie_wr_conf, | 858 | .write = mvebu_pcie_wr_conf, |
858 | }; | 859 | }; |
859 | 860 | ||
860 | static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | ||
861 | { | ||
862 | struct mvebu_pcie *pcie = sys_to_pcie(sys); | ||
863 | int err, i; | ||
864 | |||
865 | pcie->mem.name = "PCI MEM"; | ||
866 | pcie->realio.name = "PCI I/O"; | ||
867 | |||
868 | if (resource_size(&pcie->realio) != 0) | ||
869 | pci_add_resource_offset(&sys->resources, &pcie->realio, | ||
870 | sys->io_offset); | ||
871 | |||
872 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); | ||
873 | pci_add_resource(&sys->resources, &pcie->busn); | ||
874 | |||
875 | err = devm_request_pci_bus_resources(&pcie->pdev->dev, &sys->resources); | ||
876 | if (err) | ||
877 | return 0; | ||
878 | |||
879 | for (i = 0; i < pcie->nports; i++) { | ||
880 | struct mvebu_pcie_port *port = &pcie->ports[i]; | ||
881 | |||
882 | if (!port->base) | ||
883 | continue; | ||
884 | mvebu_pcie_setup_hw(port); | ||
885 | } | ||
886 | |||
887 | return 1; | ||
888 | } | ||
889 | |||
890 | static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | 861 | static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, |
891 | const struct resource *res, | 862 | const struct resource *res, |
892 | resource_size_t start, | 863 | resource_size_t start, |
@@ -917,31 +888,6 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | |||
917 | return start; | 888 | return start; |
918 | } | 889 | } |
919 | 890 | ||
920 | static void mvebu_pcie_enable(struct mvebu_pcie *pcie) | ||
921 | { | ||
922 | struct hw_pci hw; | ||
923 | |||
924 | memset(&hw, 0, sizeof(hw)); | ||
925 | |||
926 | #ifdef CONFIG_PCI_MSI | ||
927 | hw.msi_ctrl = pcie->msi; | ||
928 | #endif | ||
929 | |||
930 | hw.nr_controllers = 1; | ||
931 | hw.private_data = (void **)&pcie; | ||
932 | hw.setup = mvebu_pcie_setup; | ||
933 | hw.map_irq = of_irq_parse_and_map_pci; | ||
934 | hw.ops = &mvebu_pcie_ops; | ||
935 | hw.align_resource = mvebu_pcie_align_resource; | ||
936 | |||
937 | pci_common_init_dev(&pcie->pdev->dev, &hw); | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | * Looks up the list of register addresses encoded into the reg = | ||
942 | * <...> property for one that matches the given port/lane. Once | ||
943 | * found, maps it. | ||
944 | */ | ||
945 | static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, | 891 | static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, |
946 | struct device_node *np, | 892 | struct device_node *np, |
947 | struct mvebu_pcie_port *port) | 893 | struct mvebu_pcie_port *port) |
@@ -1190,46 +1136,79 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port) | |||
1190 | clk_disable_unprepare(port->clk); | 1136 | clk_disable_unprepare(port->clk); |
1191 | } | 1137 | } |
1192 | 1138 | ||
1193 | static int mvebu_pcie_probe(struct platform_device *pdev) | 1139 | /* |
1140 | * We can't use devm_of_pci_get_host_bridge_resources() because we | ||
1141 | * need to parse our special DT properties encoding the MEM and IO | ||
1142 | * apertures. | ||
1143 | */ | ||
1144 | static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) | ||
1194 | { | 1145 | { |
1195 | struct device *dev = &pdev->dev; | 1146 | struct device *dev = &pcie->pdev->dev; |
1196 | struct mvebu_pcie *pcie; | ||
1197 | struct device_node *np = dev->of_node; | 1147 | struct device_node *np = dev->of_node; |
1198 | struct device_node *child; | 1148 | unsigned int i; |
1199 | int num, i, ret; | 1149 | int ret; |
1200 | 1150 | ||
1201 | pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | 1151 | INIT_LIST_HEAD(&pcie->resources); |
1202 | if (!pcie) | ||
1203 | return -ENOMEM; | ||
1204 | 1152 | ||
1205 | pcie->pdev = pdev; | 1153 | /* Get the bus range */ |
1206 | platform_set_drvdata(pdev, pcie); | 1154 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
1155 | if (ret) { | ||
1156 | dev_err(dev, "failed to parse bus-range property: %d\n", ret); | ||
1157 | return ret; | ||
1158 | } | ||
1159 | pci_add_resource(&pcie->resources, &pcie->busn); | ||
1207 | 1160 | ||
1208 | /* Get the PCIe memory and I/O aperture */ | 1161 | /* Get the PCIe memory aperture */ |
1209 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | 1162 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); |
1210 | if (resource_size(&pcie->mem) == 0) { | 1163 | if (resource_size(&pcie->mem) == 0) { |
1211 | dev_err(dev, "invalid memory aperture size\n"); | 1164 | dev_err(dev, "invalid memory aperture size\n"); |
1212 | return -EINVAL; | 1165 | return -EINVAL; |
1213 | } | 1166 | } |
1214 | 1167 | ||
1168 | pcie->mem.name = "PCI MEM"; | ||
1169 | pci_add_resource(&pcie->resources, &pcie->mem); | ||
1170 | |||
1171 | /* Get the PCIe IO aperture */ | ||
1215 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); | 1172 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
1216 | 1173 | ||
1217 | if (resource_size(&pcie->io) != 0) { | 1174 | if (resource_size(&pcie->io) != 0) { |
1218 | pcie->realio.flags = pcie->io.flags; | 1175 | pcie->realio.flags = pcie->io.flags; |
1219 | pcie->realio.start = PCIBIOS_MIN_IO; | 1176 | pcie->realio.start = PCIBIOS_MIN_IO; |
1220 | pcie->realio.end = min_t(resource_size_t, | 1177 | pcie->realio.end = min_t(resource_size_t, |
1221 | IO_SPACE_LIMIT, | 1178 | IO_SPACE_LIMIT - SZ_64K, |
1222 | resource_size(&pcie->io)); | 1179 | resource_size(&pcie->io) - 1); |
1223 | } else | 1180 | pcie->realio.name = "PCI I/O"; |
1224 | pcie->realio = pcie->io; | ||
1225 | 1181 | ||
1226 | /* Get the bus range */ | 1182 | for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K) |
1227 | ret = of_pci_parse_bus_range(np, &pcie->busn); | 1183 | pci_ioremap_io(i, pcie->io.start + i); |
1228 | if (ret) { | 1184 | |
1229 | dev_err(dev, "failed to parse bus-range property: %d\n", ret); | 1185 | pci_add_resource(&pcie->resources, &pcie->realio); |
1230 | return ret; | ||
1231 | } | 1186 | } |
1232 | 1187 | ||
1188 | return devm_request_pci_bus_resources(dev, &pcie->resources); | ||
1189 | } | ||
1190 | |||
1191 | static int mvebu_pcie_probe(struct platform_device *pdev) | ||
1192 | { | ||
1193 | struct device *dev = &pdev->dev; | ||
1194 | struct mvebu_pcie *pcie; | ||
1195 | struct pci_host_bridge *bridge; | ||
1196 | struct device_node *np = dev->of_node; | ||
1197 | struct device_node *child; | ||
1198 | int num, i, ret; | ||
1199 | |||
1200 | bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct mvebu_pcie)); | ||
1201 | if (!bridge) | ||
1202 | return -ENOMEM; | ||
1203 | |||
1204 | pcie = pci_host_bridge_priv(bridge); | ||
1205 | pcie->pdev = pdev; | ||
1206 | platform_set_drvdata(pdev, pcie); | ||
1207 | |||
1208 | ret = mvebu_pcie_parse_request_resources(pcie); | ||
1209 | if (ret) | ||
1210 | return ret; | ||
1211 | |||
1233 | num = of_get_available_child_count(np); | 1212 | num = of_get_available_child_count(np); |
1234 | 1213 | ||
1235 | pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL); | 1214 | pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL); |
@@ -1272,20 +1251,24 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1272 | continue; | 1251 | continue; |
1273 | } | 1252 | } |
1274 | 1253 | ||
1254 | mvebu_pcie_setup_hw(port); | ||
1275 | mvebu_pcie_set_local_dev_nr(port, 1); | 1255 | mvebu_pcie_set_local_dev_nr(port, 1); |
1276 | mvebu_sw_pci_bridge_init(port); | 1256 | mvebu_sw_pci_bridge_init(port); |
1277 | } | 1257 | } |
1278 | 1258 | ||
1279 | pcie->nports = i; | 1259 | pcie->nports = i; |
1280 | 1260 | ||
1281 | for (i = 0; i < (IO_SPACE_LIMIT - SZ_64K); i += SZ_64K) | 1261 | list_splice_init(&pcie->resources, &bridge->windows); |
1282 | pci_ioremap_io(i, pcie->io.start + i); | 1262 | bridge->dev.parent = dev; |
1283 | 1263 | bridge->sysdata = pcie; | |
1284 | mvebu_pcie_enable(pcie); | 1264 | bridge->busnr = 0; |
1285 | 1265 | bridge->ops = &mvebu_pcie_ops; | |
1286 | platform_set_drvdata(pdev, pcie); | 1266 | bridge->map_irq = of_irq_parse_and_map_pci; |
1287 | 1267 | bridge->swizzle_irq = pci_common_swizzle; | |
1288 | return 0; | 1268 | bridge->align_resource = mvebu_pcie_align_resource; |
1269 | bridge->msi = pcie->msi; | ||
1270 | |||
1271 | return pci_host_probe(bridge); | ||
1289 | } | 1272 | } |
1290 | 1273 | ||
1291 | static const struct of_device_id mvebu_pcie_of_match_table[] = { | 1274 | static const struct of_device_id mvebu_pcie_of_match_table[] = { |