2 * Simple, generic PCI host controller driver targetting firmware-initialised
3 * systems and virtual machines (e.g. the PCI emulation provided by kvmtool).
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.
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.
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/>.
17 * Copyright (C) 2014 ARM Limited
19 * Author: Will Deacon <will.deacon@arm.com>
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>
28 struct gen_pci_cfg_bus_ops
{
30 void __iomem
*(*map_bus
)(struct pci_bus
*, unsigned int, int);
33 struct gen_pci_cfg_windows
{
35 struct resource
*bus_range
;
38 const struct gen_pci_cfg_bus_ops
*ops
;
42 struct pci_host_bridge host
;
43 struct gen_pci_cfg_windows cfg
;
44 struct list_head resources
;
47 static void __iomem
*gen_pci_map_cfg_bus_cam(struct pci_bus
*bus
,
51 struct pci_sys_data
*sys
= bus
->sysdata
;
52 struct gen_pci
*pci
= sys
->private_data
;
53 resource_size_t idx
= bus
->number
- pci
->cfg
.bus_range
->start
;
55 return pci
->cfg
.win
[idx
] + ((devfn
<< 8) | where
);
58 static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops
= {
60 .map_bus
= gen_pci_map_cfg_bus_cam
,
63 static void __iomem
*gen_pci_map_cfg_bus_ecam(struct pci_bus
*bus
,
67 struct pci_sys_data
*sys
= bus
->sysdata
;
68 struct gen_pci
*pci
= sys
->private_data
;
69 resource_size_t idx
= bus
->number
- pci
->cfg
.bus_range
->start
;
71 return pci
->cfg
.win
[idx
] + ((devfn
<< 12) | where
);
74 static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops
= {
76 .map_bus
= gen_pci_map_cfg_bus_ecam
,
79 static int gen_pci_config_read(struct pci_bus
*bus
, unsigned int devfn
,
80 int where
, int size
, u32
*val
)
83 struct pci_sys_data
*sys
= bus
->sysdata
;
84 struct gen_pci
*pci
= sys
->private_data
;
86 addr
= pci
->cfg
.ops
->map_bus(bus
, devfn
, where
);
99 return PCIBIOS_SUCCESSFUL
;
102 static int gen_pci_config_write(struct pci_bus
*bus
, unsigned int devfn
,
103 int where
, int size
, u32 val
)
106 struct pci_sys_data
*sys
= bus
->sysdata
;
107 struct gen_pci
*pci
= sys
->private_data
;
109 addr
= pci
->cfg
.ops
->map_bus(bus
, devfn
, where
);
122 return PCIBIOS_SUCCESSFUL
;
125 static struct pci_ops gen_pci_ops
= {
126 .read
= gen_pci_config_read
,
127 .write
= gen_pci_config_write
,
130 static const struct of_device_id gen_pci_of_match
[] = {
131 { .compatible
= "pci-host-cam-generic",
132 .data
= &gen_pci_cfg_cam_bus_ops
},
134 { .compatible
= "pci-host-ecam-generic",
135 .data
= &gen_pci_cfg_ecam_bus_ops
},
139 MODULE_DEVICE_TABLE(of
, gen_pci_of_match
);
141 static void gen_pci_release_of_pci_ranges(struct gen_pci
*pci
)
143 pci_free_resource_list(&pci
->resources
);
146 static int gen_pci_parse_request_of_pci_ranges(struct gen_pci
*pci
)
148 int err
, res_valid
= 0;
149 struct device
*dev
= pci
->host
.dev
.parent
;
150 struct device_node
*np
= dev
->of_node
;
151 resource_size_t iobase
;
152 struct pci_host_bridge_window
*win
;
154 err
= of_pci_get_host_bridge_resources(np
, 0, 0xff, &pci
->resources
,
159 list_for_each_entry(win
, &pci
->resources
, list
) {
160 struct resource
*parent
, *res
= win
->res
;
162 switch (resource_type(res
)) {
164 parent
= &ioport_resource
;
165 err
= pci_remap_iospace(res
, iobase
);
167 dev_warn(dev
, "error %d: failed to map resource %pR\n",
173 parent
= &iomem_resource
;
174 res_valid
|= !(res
->flags
& IORESOURCE_PREFETCH
);
177 pci
->cfg
.bus_range
= res
;
182 err
= devm_request_resource(dev
, parent
, res
);
184 goto out_release_res
;
188 dev_err(dev
, "non-prefetchable memory resource required\n");
190 goto out_release_res
;
196 gen_pci_release_of_pci_ranges(pci
);
200 static int gen_pci_parse_map_cfg_windows(struct gen_pci
*pci
)
204 resource_size_t busn
;
205 struct resource
*bus_range
;
206 struct device
*dev
= pci
->host
.dev
.parent
;
207 struct device_node
*np
= dev
->of_node
;
209 err
= of_address_to_resource(np
, 0, &pci
->cfg
.res
);
211 dev_err(dev
, "missing \"reg\" property\n");
215 /* Limit the bus-range to fit within reg */
216 bus_max
= pci
->cfg
.bus_range
->start
+
217 (resource_size(&pci
->cfg
.res
) >> pci
->cfg
.ops
->bus_shift
) - 1;
218 pci
->cfg
.bus_range
->end
= min_t(resource_size_t
,
219 pci
->cfg
.bus_range
->end
, bus_max
);
221 pci
->cfg
.win
= devm_kcalloc(dev
, resource_size(pci
->cfg
.bus_range
),
222 sizeof(*pci
->cfg
.win
), GFP_KERNEL
);
226 /* Map our Configuration Space windows */
227 if (!devm_request_mem_region(dev
, pci
->cfg
.res
.start
,
228 resource_size(&pci
->cfg
.res
),
229 "Configuration Space"))
232 bus_range
= pci
->cfg
.bus_range
;
233 for (busn
= bus_range
->start
; busn
<= bus_range
->end
; ++busn
) {
234 u32 idx
= busn
- bus_range
->start
;
235 u32 sz
= 1 << pci
->cfg
.ops
->bus_shift
;
237 pci
->cfg
.win
[idx
] = devm_ioremap(dev
,
238 pci
->cfg
.res
.start
+ busn
* sz
,
240 if (!pci
->cfg
.win
[idx
])
247 static int gen_pci_setup(int nr
, struct pci_sys_data
*sys
)
249 struct gen_pci
*pci
= sys
->private_data
;
250 list_splice_init(&pci
->resources
, &sys
->resources
);
254 static int gen_pci_probe(struct platform_device
*pdev
)
258 const struct of_device_id
*of_id
;
260 struct device
*dev
= &pdev
->dev
;
261 struct device_node
*np
= dev
->of_node
;
262 struct gen_pci
*pci
= devm_kzalloc(dev
, sizeof(*pci
), GFP_KERNEL
);
265 .private_data
= (void **)&pci
,
266 .setup
= gen_pci_setup
,
267 .map_irq
= of_irq_parse_and_map_pci
,
274 type
= of_get_property(np
, "device_type", NULL
);
275 if (!type
|| strcmp(type
, "pci")) {
276 dev_err(dev
, "invalid \"device_type\" %s\n", type
);
280 prop
= of_get_property(of_chosen
, "linux,pci-probe-only", NULL
);
283 pci_add_flags(PCI_PROBE_ONLY
);
285 pci_clear_flags(PCI_PROBE_ONLY
);
288 of_id
= of_match_node(gen_pci_of_match
, np
);
289 pci
->cfg
.ops
= of_id
->data
;
290 pci
->host
.dev
.parent
= dev
;
291 INIT_LIST_HEAD(&pci
->host
.windows
);
292 INIT_LIST_HEAD(&pci
->resources
);
294 /* Parse our PCI ranges and request their resources */
295 err
= gen_pci_parse_request_of_pci_ranges(pci
);
299 /* Parse and map our Configuration Space windows */
300 err
= gen_pci_parse_map_cfg_windows(pci
);
302 gen_pci_release_of_pci_ranges(pci
);
306 pci_common_init_dev(dev
, &hw
);
310 static struct platform_driver gen_pci_driver
= {
312 .name
= "pci-host-generic",
313 .owner
= THIS_MODULE
,
314 .of_match_table
= gen_pci_of_match
,
316 .probe
= gen_pci_probe
,
318 module_platform_driver(gen_pci_driver
);
320 MODULE_DESCRIPTION("Generic PCI host driver");
321 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
322 MODULE_LICENSE("GPL v2");