blob: b6fc32d6cf65f212eff9180f9c76c8fd90713feb [file] [log] [blame]
Uwe Hermannb80dbf02007-04-22 19:08:13 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003 *
4 * Copyright (C) 2004 Linux Networx
5 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +00006 * Copyright (C) 2009 coresystems GmbH
Uwe Hermannb80dbf02007-04-22 19:08:13 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Uwe Hermannb80dbf02007-04-22 19:08:13 +000016 */
17
Eric Biedermana9e632c2004-11-18 22:38:08 +000018#include <console/console.h>
Eric Biedermana9e632c2004-11-18 22:38:08 +000019#include <device/pci.h>
20#include <device/pci_ids.h>
21#include <device/pci_ops.h>
22
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030023const struct pci_bus_operations *pci_bus_default_ops(device_t dev)
24{
Kyösti Mälkki6f66f412016-12-01 22:08:18 +020025 if (IS_ENABLED(CONFIG_NO_MMCONF_SUPPORT))
26 return &pci_cf8_conf1;
27
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030028 return &pci_ops_mmconf;
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030029}
30
Edward O'Callaghan016732f2014-10-29 03:04:40 +110031static const struct pci_bus_operations *pci_bus_ops(struct bus *bus, struct device *dev)
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030032{
33 const struct pci_bus_operations *bops;
34 bops = NULL;
35 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->ops_pci_bus) {
36 bops = bus->dev->ops->ops_pci_bus(dev);
37 }
38 if (!bops)
39 bops = pci_bus_default_ops(dev);
40 return bops;
41}
42
Uwe Hermannc1ee4292010-10-17 19:01:48 +000043/*
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030044 * The only consumer of the return value of get_pbus() is pci_bus_ops().
45 * pci_bus_ops() can handle being passed NULL and auto-picks working ops.
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000046 */
Edward O'Callaghan016732f2014-10-29 03:04:40 +110047static struct bus *get_pbus(struct device *dev)
Eric Biedermana9e632c2004-11-18 22:38:08 +000048{
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000049 struct bus *pbus = NULL;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000050
51 if (!dev)
Carl-Daniel Hailfinger87e70502009-06-05 11:41:51 +000052 die("get_pbus: dev is NULL!\n");
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000053 else
54 pbus = dev->bus;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000055
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030056 while (pbus && pbus->dev && !pci_bus_ops(pbus, dev)) {
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000057 if (pbus == pbus->dev->bus) {
Uwe Hermanne4870472010-11-04 23:23:47 +000058 printk(BIOS_ALERT, "%s in endless loop looking for a "
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030059 "parent bus with pci_bus_ops for %s, breaking "
Uwe Hermanne4870472010-11-04 23:23:47 +000060 "out.\n", __func__, dev_path(dev));
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000061 break;
62 }
Eric Biedermana9e632c2004-11-18 22:38:08 +000063 pbus = pbus->dev->bus;
64 }
Uwe Hermanne4870472010-11-04 23:23:47 +000065
66 if (!pbus || !pbus->dev || !pbus->dev->ops
67 || !pbus->dev->ops->ops_pci_bus) {
68 /* This can happen before the device tree is fully set up. */
69
70 // printk(BIOS_EMERG, "%s: Cannot find PCI bus operations.\n",
71 // dev_path(dev));
72
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000073 pbus = NULL;
Eric Biedermana9e632c2004-11-18 22:38:08 +000074 }
Uwe Hermanne4870472010-11-04 23:23:47 +000075
Eric Biedermana9e632c2004-11-18 22:38:08 +000076 return pbus;
77}
78
Edward O'Callaghan016732f2014-10-29 03:04:40 +110079u8 pci_read_config8(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000080{
81 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030082 return pci_bus_ops(pbus, dev)->read8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000083 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000084}
85
Edward O'Callaghan016732f2014-10-29 03:04:40 +110086u16 pci_read_config16(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000087{
88 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030089 return pci_bus_ops(pbus, dev)->read16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000090 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000091}
92
Edward O'Callaghan016732f2014-10-29 03:04:40 +110093u32 pci_read_config32(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000094{
95 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030096 return pci_bus_ops(pbus, dev)->read32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000097 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000098}
99
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100100void pci_write_config8(struct device *dev, unsigned int where, u8 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000101{
102 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300103 pci_bus_ops(pbus, dev)->write8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000104 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000105}
106
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100107void pci_write_config16(struct device *dev, unsigned int where, u16 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000108{
109 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300110 pci_bus_ops(pbus, dev)->write16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000111 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000112}
113
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100114void pci_write_config32(struct device *dev, unsigned int where, u32 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000115{
116 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300117 pci_bus_ops(pbus, dev)->write32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000118 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000119}