diff options
author | Thomas Petazzoni <thomas.petazzoni@bootlin.com> | 2018-08-03 10:38:47 -0400 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2018-08-08 10:57:50 -0400 |
commit | 42342073e38b50113354944cd51dcfed28d857a1 (patch) | |
tree | 6d9860369e86f64e71b922a1cc5d853a5b43d4a4 | |
parent | 5a553d6ba103e28247f4e2d10bcc25545cd4d9cb (diff) |
PCI: mvebu: Convert to use pci_host_bridge directly
Rather than using the ARM-specific pci_common_init_dev() API, use the
pci_host_bridge logic directly.
Unfortunately, we can't use devm_of_pci_get_host_bridge_resources(),
because the DT binding for describing PCIe apertures for this PCI
controller is a bit special, and we cannot retrieve them from the
'ranges' property. Therefore, we still have some special code to
handle this.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-rw-r--r-- | drivers/pci/controller/pci-mvebu.c | 136 |
1 files changed, 63 insertions, 73 deletions
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 05f863435e5e..9055f03596ef 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,26 +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 | /* | 891 | /* |
941 | * Looks up the list of register addresses encoded into the reg = | 892 | * Looks up the list of register addresses encoded into the reg = |
942 | * <...> property for one that matches the given port/lane. Once | 893 | * <...> property for one that matches the given port/lane. Once |
@@ -1190,28 +1141,39 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port) | |||
1190 | clk_disable_unprepare(port->clk); | 1141 | clk_disable_unprepare(port->clk); |
1191 | } | 1142 | } |
1192 | 1143 | ||
1193 | static int mvebu_pcie_probe(struct platform_device *pdev) | 1144 | /* |
1145 | * We can't use devm_of_pci_get_host_bridge_resources() because we | ||
1146 | * need to parse our special DT properties encoding the MEM and IO | ||
1147 | * apertures. | ||
1148 | */ | ||
1149 | static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) | ||
1194 | { | 1150 | { |
1195 | struct device *dev = &pdev->dev; | 1151 | struct device *dev = &pcie->pdev->dev; |
1196 | struct mvebu_pcie *pcie; | ||
1197 | struct device_node *np = dev->of_node; | 1152 | struct device_node *np = dev->of_node; |
1198 | struct device_node *child; | 1153 | unsigned int i; |
1199 | int num, i, ret; | 1154 | int ret; |
1200 | 1155 | ||
1201 | pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | 1156 | INIT_LIST_HEAD(&pcie->resources); |
1202 | if (!pcie) | ||
1203 | return -ENOMEM; | ||
1204 | 1157 | ||
1205 | pcie->pdev = pdev; | 1158 | /* Get the bus range */ |
1206 | platform_set_drvdata(pdev, pcie); | 1159 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
1160 | if (ret) { | ||
1161 | dev_err(dev, "failed to parse bus-range property: %d\n", ret); | ||
1162 | return ret; | ||
1163 | } | ||
1164 | pci_add_resource(&pcie->resources, &pcie->busn); | ||
1207 | 1165 | ||
1208 | /* Get the PCIe memory and I/O aperture */ | 1166 | /* Get the PCIe memory aperture */ |
1209 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | 1167 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); |
1210 | if (resource_size(&pcie->mem) == 0) { | 1168 | if (resource_size(&pcie->mem) == 0) { |
1211 | dev_err(dev, "invalid memory aperture size\n"); | 1169 | dev_err(dev, "invalid memory aperture size\n"); |
1212 | return -EINVAL; | 1170 | return -EINVAL; |
1213 | } | 1171 | } |
1214 | 1172 | ||
1173 | pcie->mem.name = "PCI MEM"; | ||
1174 | pci_add_resource(&pcie->resources, &pcie->mem); | ||
1175 | |||
1176 | /* Get the PCIe IO aperture */ | ||
1215 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); | 1177 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
1216 | 1178 | ||
1217 | if (resource_size(&pcie->io) != 0) { | 1179 | if (resource_size(&pcie->io) != 0) { |
@@ -1220,19 +1182,38 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1220 | pcie->realio.end = min_t(resource_size_t, | 1182 | pcie->realio.end = min_t(resource_size_t, |
1221 | IO_SPACE_LIMIT - SZ_64K, | 1183 | IO_SPACE_LIMIT - SZ_64K, |
1222 | resource_size(&pcie->io) - 1); | 1184 | resource_size(&pcie->io) - 1); |
1185 | pcie->realio.name = "PCI I/O"; | ||
1223 | 1186 | ||
1224 | for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K) | 1187 | for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K) |
1225 | pci_ioremap_io(i, pcie->io.start + i); | 1188 | pci_ioremap_io(i, pcie->io.start + i); |
1226 | } else | ||
1227 | pcie->realio = pcie->io; | ||
1228 | 1189 | ||
1229 | /* Get the bus range */ | 1190 | pci_add_resource(&pcie->resources, &pcie->realio); |
1230 | ret = of_pci_parse_bus_range(np, &pcie->busn); | ||
1231 | if (ret) { | ||
1232 | dev_err(dev, "failed to parse bus-range property: %d\n", ret); | ||
1233 | return ret; | ||
1234 | } | 1191 | } |
1235 | 1192 | ||
1193 | return devm_request_pci_bus_resources(dev, &pcie->resources); | ||
1194 | } | ||
1195 | |||
1196 | static int mvebu_pcie_probe(struct platform_device *pdev) | ||
1197 | { | ||
1198 | struct device *dev = &pdev->dev; | ||
1199 | struct mvebu_pcie *pcie; | ||
1200 | struct pci_host_bridge *bridge; | ||
1201 | struct device_node *np = dev->of_node; | ||
1202 | struct device_node *child; | ||
1203 | int num, i, ret; | ||
1204 | |||
1205 | bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct mvebu_pcie)); | ||
1206 | if (!bridge) | ||
1207 | return -ENOMEM; | ||
1208 | |||
1209 | pcie = pci_host_bridge_priv(bridge); | ||
1210 | pcie->pdev = pdev; | ||
1211 | platform_set_drvdata(pdev, pcie); | ||
1212 | |||
1213 | ret = mvebu_pcie_parse_request_resources(pcie); | ||
1214 | if (ret) | ||
1215 | return ret; | ||
1216 | |||
1236 | num = of_get_available_child_count(np); | 1217 | num = of_get_available_child_count(np); |
1237 | 1218 | ||
1238 | pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL); | 1219 | pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL); |
@@ -1275,15 +1256,24 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1275 | continue; | 1256 | continue; |
1276 | } | 1257 | } |
1277 | 1258 | ||
1259 | mvebu_pcie_setup_hw(port); | ||
1278 | mvebu_pcie_set_local_dev_nr(port, 1); | 1260 | mvebu_pcie_set_local_dev_nr(port, 1); |
1279 | mvebu_sw_pci_bridge_init(port); | 1261 | mvebu_sw_pci_bridge_init(port); |
1280 | } | 1262 | } |
1281 | 1263 | ||
1282 | pcie->nports = i; | 1264 | pcie->nports = i; |
1283 | 1265 | ||
1284 | mvebu_pcie_enable(pcie); | 1266 | list_splice_init(&pcie->resources, &bridge->windows); |
1285 | 1267 | bridge->dev.parent = dev; | |
1286 | return 0; | 1268 | bridge->sysdata = pcie; |
1269 | bridge->busnr = 0; | ||
1270 | bridge->ops = &mvebu_pcie_ops; | ||
1271 | bridge->map_irq = of_irq_parse_and_map_pci; | ||
1272 | bridge->swizzle_irq = pci_common_swizzle; | ||
1273 | bridge->align_resource = mvebu_pcie_align_resource; | ||
1274 | bridge->msi = pcie->msi; | ||
1275 | |||
1276 | return pci_host_probe(bridge); | ||
1287 | } | 1277 | } |
1288 | 1278 | ||
1289 | static const struct of_device_id mvebu_pcie_of_match_table[] = { | 1279 | static const struct of_device_id mvebu_pcie_of_match_table[] = { |