blob: 224303d2b40120cb1a498fdc69b42c2b0253d1d2 [file] [log] [blame]
Will Deaconce292992013-11-22 16:14:41 +00001/*
2 * Simple, generic PCI host controller driver targetting firmware-initialised
3 * systems and virtual machines (e.g. the PCI emulation provided by kvmtool).
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2014 ARM Limited
18 *
19 * Author: Will Deacon <will.deacon@arm.com>
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of_address.h>
25#include <linux/of_pci.h>
26#include <linux/platform_device.h>
27
28struct gen_pci_cfg_bus_ops {
29 u32 bus_shift;
30 void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int);
31};
32
33struct gen_pci_cfg_windows {
34 struct resource res;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +010035 struct resource *bus_range;
Will Deaconce292992013-11-22 16:14:41 +000036 void __iomem **win;
37
38 const struct gen_pci_cfg_bus_ops *ops;
39};
40
Jayachandran C499733e2015-08-05 02:23:38 +053041/*
42 * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
43 * sysdata. Add pci_sys_data as the first element in struct gen_pci so
44 * that when we use a gen_pci pointer as sysdata, it is also a pointer to
45 * a struct pci_sys_data.
46 */
Will Deaconce292992013-11-22 16:14:41 +000047struct gen_pci {
Jayachandran C499733e2015-08-05 02:23:38 +053048#ifdef CONFIG_ARM
49 struct pci_sys_data sys;
50#endif
Will Deaconce292992013-11-22 16:14:41 +000051 struct pci_host_bridge host;
52 struct gen_pci_cfg_windows cfg;
53 struct list_head resources;
54};
55
56static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
57 unsigned int devfn,
58 int where)
59{
Jayachandran C499733e2015-08-05 02:23:38 +053060 struct gen_pci *pci = bus->sysdata;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +010061 resource_size_t idx = bus->number - pci->cfg.bus_range->start;
Will Deaconce292992013-11-22 16:14:41 +000062
63 return pci->cfg.win[idx] + ((devfn << 8) | where);
64}
65
66static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = {
67 .bus_shift = 16,
68 .map_bus = gen_pci_map_cfg_bus_cam,
69};
70
71static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
72 unsigned int devfn,
73 int where)
74{
Jayachandran C499733e2015-08-05 02:23:38 +053075 struct gen_pci *pci = bus->sysdata;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +010076 resource_size_t idx = bus->number - pci->cfg.bus_range->start;
Will Deaconce292992013-11-22 16:14:41 +000077
78 return pci->cfg.win[idx] + ((devfn << 12) | where);
79}
80
81static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = {
82 .bus_shift = 20,
83 .map_bus = gen_pci_map_cfg_bus_ecam,
84};
85
Will Deaconce292992013-11-22 16:14:41 +000086static struct pci_ops gen_pci_ops = {
Rob Herring21186722015-01-09 20:34:46 -060087 .read = pci_generic_config_read,
88 .write = pci_generic_config_write,
Will Deaconce292992013-11-22 16:14:41 +000089};
90
91static const struct of_device_id gen_pci_of_match[] = {
92 { .compatible = "pci-host-cam-generic",
93 .data = &gen_pci_cfg_cam_bus_ops },
94
95 { .compatible = "pci-host-ecam-generic",
96 .data = &gen_pci_cfg_ecam_bus_ops },
97
98 { },
99};
100MODULE_DEVICE_TABLE(of, gen_pci_of_match);
101
Will Deaconce292992013-11-22 16:14:41 +0000102static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
103{
Will Deaconce292992013-11-22 16:14:41 +0000104 pci_free_resource_list(&pci->resources);
105}
106
107static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
108{
Will Deaconce292992013-11-22 16:14:41 +0000109 int err, res_valid = 0;
110 struct device *dev = pci->host.dev.parent;
111 struct device_node *np = dev->of_node;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100112 resource_size_t iobase;
Jiang Liu14d76b62015-02-05 13:44:44 +0800113 struct resource_entry *win;
Will Deaconce292992013-11-22 16:14:41 +0000114
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100115 err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
116 &iobase);
117 if (err)
118 return err;
Will Deaconce292992013-11-22 16:14:41 +0000119
Jiang Liu14d76b62015-02-05 13:44:44 +0800120 resource_list_for_each_entry(win, &pci->resources) {
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100121 struct resource *parent, *res = win->res;
Will Deaconce292992013-11-22 16:14:41 +0000122
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100123 switch (resource_type(res)) {
Will Deaconce292992013-11-22 16:14:41 +0000124 case IORESOURCE_IO:
125 parent = &ioport_resource;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100126 err = pci_remap_iospace(res, iobase);
127 if (err) {
128 dev_warn(dev, "error %d: failed to map resource %pR\n",
129 err, res);
130 continue;
131 }
Will Deaconce292992013-11-22 16:14:41 +0000132 break;
133 case IORESOURCE_MEM:
134 parent = &iomem_resource;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100135 res_valid |= !(res->flags & IORESOURCE_PREFETCH);
Will Deaconce292992013-11-22 16:14:41 +0000136 break;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100137 case IORESOURCE_BUS:
138 pci->cfg.bus_range = res;
Will Deaconce292992013-11-22 16:14:41 +0000139 default:
Will Deaconce292992013-11-22 16:14:41 +0000140 continue;
141 }
142
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100143 err = devm_request_resource(dev, parent, res);
Will Deaconce292992013-11-22 16:14:41 +0000144 if (err)
145 goto out_release_res;
Will Deaconce292992013-11-22 16:14:41 +0000146 }
147
148 if (!res_valid) {
149 dev_err(dev, "non-prefetchable memory resource required\n");
150 err = -EINVAL;
151 goto out_release_res;
152 }
153
154 return 0;
155
156out_release_res:
157 gen_pci_release_of_pci_ranges(pci);
158 return err;
159}
160
161static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
162{
163 int err;
164 u8 bus_max;
165 resource_size_t busn;
166 struct resource *bus_range;
167 struct device *dev = pci->host.dev.parent;
168 struct device_node *np = dev->of_node;
169
Will Deaconce292992013-11-22 16:14:41 +0000170 err = of_address_to_resource(np, 0, &pci->cfg.res);
171 if (err) {
172 dev_err(dev, "missing \"reg\" property\n");
173 return err;
174 }
175
Will Deaconce292992013-11-22 16:14:41 +0000176 /* Limit the bus-range to fit within reg */
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100177 bus_max = pci->cfg.bus_range->start +
Will Deaconce292992013-11-22 16:14:41 +0000178 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100179 pci->cfg.bus_range->end = min_t(resource_size_t,
180 pci->cfg.bus_range->end, bus_max);
Will Deaconce292992013-11-22 16:14:41 +0000181
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100182 pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
Lorenzo Pieralisia5525b22014-10-23 16:23:06 +0100183 sizeof(*pci->cfg.win), GFP_KERNEL);
184 if (!pci->cfg.win)
185 return -ENOMEM;
186
Will Deaconce292992013-11-22 16:14:41 +0000187 /* Map our Configuration Space windows */
188 if (!devm_request_mem_region(dev, pci->cfg.res.start,
189 resource_size(&pci->cfg.res),
190 "Configuration Space"))
191 return -ENOMEM;
192
Lorenzo Pieralisidbf98262014-10-23 16:23:07 +0100193 bus_range = pci->cfg.bus_range;
Will Deaconce292992013-11-22 16:14:41 +0000194 for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
195 u32 idx = busn - bus_range->start;
196 u32 sz = 1 << pci->cfg.ops->bus_shift;
197
198 pci->cfg.win[idx] = devm_ioremap(dev,
199 pci->cfg.res.start + busn * sz,
200 sz);
201 if (!pci->cfg.win[idx])
202 return -ENOMEM;
203 }
204
Will Deaconce292992013-11-22 16:14:41 +0000205 return 0;
206}
207
Will Deaconce292992013-11-22 16:14:41 +0000208static int gen_pci_probe(struct platform_device *pdev)
209{
210 int err;
211 const char *type;
212 const struct of_device_id *of_id;
Will Deaconce292992013-11-22 16:14:41 +0000213 struct device *dev = &pdev->dev;
214 struct device_node *np = dev->of_node;
215 struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
Jayachandran C499733e2015-08-05 02:23:38 +0530216 struct pci_bus *bus, *child;
Will Deaconce292992013-11-22 16:14:41 +0000217
218 if (!pci)
219 return -ENOMEM;
220
221 type = of_get_property(np, "device_type", NULL);
222 if (!type || strcmp(type, "pci")) {
223 dev_err(dev, "invalid \"device_type\" %s\n", type);
224 return -EINVAL;
225 }
226
Marc Zyngiera07245d2015-09-04 17:50:09 +0100227 of_pci_check_probe_only();
Will Deaconce292992013-11-22 16:14:41 +0000228
229 of_id = of_match_node(gen_pci_of_match, np);
230 pci->cfg.ops = of_id->data;
Rob Herring21186722015-01-09 20:34:46 -0600231 gen_pci_ops.map_bus = pci->cfg.ops->map_bus;
Will Deaconce292992013-11-22 16:14:41 +0000232 pci->host.dev.parent = dev;
233 INIT_LIST_HEAD(&pci->host.windows);
234 INIT_LIST_HEAD(&pci->resources);
235
236 /* Parse our PCI ranges and request their resources */
237 err = gen_pci_parse_request_of_pci_ranges(pci);
238 if (err)
239 return err;
240
241 /* Parse and map our Configuration Space windows */
242 err = gen_pci_parse_map_cfg_windows(pci);
243 if (err) {
244 gen_pci_release_of_pci_ranges(pci);
245 return err;
246 }
247
Jayachandran C499733e2015-08-05 02:23:38 +0530248 /* Do not reassign resources if probe only */
249 if (!pci_has_flag(PCI_PROBE_ONLY))
250 pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
251
252 bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources);
253 if (!bus) {
254 dev_err(dev, "Scanning rootbus failed");
255 return -ENODEV;
256 }
257
258 pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
259
260 if (!pci_has_flag(PCI_PROBE_ONLY)) {
261 pci_bus_size_bridges(bus);
262 pci_bus_assign_resources(bus);
263
264 list_for_each_entry(child, &bus->children, node)
265 pcie_bus_configure_settings(child);
266 }
267
268 pci_bus_add_devices(bus);
Will Deaconce292992013-11-22 16:14:41 +0000269 return 0;
270}
271
272static struct platform_driver gen_pci_driver = {
273 .driver = {
274 .name = "pci-host-generic",
Will Deaconce292992013-11-22 16:14:41 +0000275 .of_match_table = gen_pci_of_match,
276 },
277 .probe = gen_pci_probe,
278};
279module_platform_driver(gen_pci_driver);
280
281MODULE_DESCRIPTION("Generic PCI host driver");
282MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
Bjorn Helgaaseed65422014-07-15 15:07:46 -0600283MODULE_LICENSE("GPL v2");