blob: 6ddb49363f62536ceabfef9e9c7e9dab926530c0 [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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Uwe Hermannb80dbf02007-04-22 19:08:13 +000020 */
21
Eric Biedermana9e632c2004-11-18 22:38:08 +000022#include <console/console.h>
23#include <arch/pciconf.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
26#include <device/pci_ops.h>
27
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030028const struct pci_bus_operations *pci_bus_default_ops(device_t dev)
29{
30#if CONFIG_MMCONF_SUPPORT_DEFAULT
31 return &pci_ops_mmconf;
32#else
33 return &pci_cf8_conf1;
34#endif
35}
36
Edward O'Callaghan016732f2014-10-29 03:04:40 +110037static const struct pci_bus_operations *pci_bus_ops(struct bus *bus, struct device *dev)
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030038{
39 const struct pci_bus_operations *bops;
40 bops = NULL;
41 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->ops_pci_bus) {
42 bops = bus->dev->ops->ops_pci_bus(dev);
43 }
44 if (!bops)
45 bops = pci_bus_default_ops(dev);
46 return bops;
47}
48
Uwe Hermannc1ee4292010-10-17 19:01:48 +000049/*
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030050 * The only consumer of the return value of get_pbus() is pci_bus_ops().
51 * pci_bus_ops() can handle being passed NULL and auto-picks working ops.
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000052 */
Edward O'Callaghan016732f2014-10-29 03:04:40 +110053static struct bus *get_pbus(struct device *dev)
Eric Biedermana9e632c2004-11-18 22:38:08 +000054{
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000055 struct bus *pbus = NULL;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000056
57 if (!dev)
Carl-Daniel Hailfinger87e70502009-06-05 11:41:51 +000058 die("get_pbus: dev is NULL!\n");
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000059 else
60 pbus = dev->bus;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000061
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030062 while (pbus && pbus->dev && !pci_bus_ops(pbus, dev)) {
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000063 if (pbus == pbus->dev->bus) {
Uwe Hermanne4870472010-11-04 23:23:47 +000064 printk(BIOS_ALERT, "%s in endless loop looking for a "
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030065 "parent bus with pci_bus_ops for %s, breaking "
Uwe Hermanne4870472010-11-04 23:23:47 +000066 "out.\n", __func__, dev_path(dev));
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000067 break;
68 }
Eric Biedermana9e632c2004-11-18 22:38:08 +000069 pbus = pbus->dev->bus;
70 }
Uwe Hermanne4870472010-11-04 23:23:47 +000071
72 if (!pbus || !pbus->dev || !pbus->dev->ops
73 || !pbus->dev->ops->ops_pci_bus) {
74 /* This can happen before the device tree is fully set up. */
75
76 // printk(BIOS_EMERG, "%s: Cannot find PCI bus operations.\n",
77 // dev_path(dev));
78
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000079 pbus = NULL;
Eric Biedermana9e632c2004-11-18 22:38:08 +000080 }
Uwe Hermanne4870472010-11-04 23:23:47 +000081
Eric Biedermana9e632c2004-11-18 22:38:08 +000082 return pbus;
83}
84
Edward O'Callaghan016732f2014-10-29 03:04:40 +110085u8 pci_read_config8(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000086{
87 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030088 return pci_bus_ops(pbus, dev)->read8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000089 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000090}
91
Edward O'Callaghan016732f2014-10-29 03:04:40 +110092u16 pci_read_config16(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000093{
94 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030095 return pci_bus_ops(pbus, dev)->read16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000096 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000097}
98
Edward O'Callaghan016732f2014-10-29 03:04:40 +110099u32 pci_read_config32(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000100{
101 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300102 return pci_bus_ops(pbus, dev)->read32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000103 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000104}
105
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100106void pci_write_config8(struct device *dev, unsigned int where, u8 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000107{
108 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300109 pci_bus_ops(pbus, dev)->write8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000110 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000111}
112
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100113void pci_write_config16(struct device *dev, unsigned int where, u16 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000114{
115 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300116 pci_bus_ops(pbus, dev)->write16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000117 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000118}
119
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100120void pci_write_config32(struct device *dev, unsigned int where, u32 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000121{
122 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300123 pci_bus_ops(pbus, dev)->write32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000124 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000125}
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000126
Stefan Reinauer08670622009-06-30 15:17:49 +0000127#if CONFIG_MMCONF_SUPPORT
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100128u8 pci_mmio_read_config8(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000129{
130 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000131 return pci_ops_mmconf.read8(pbus, dev->bus->secondary,
132 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000133}
134
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100135u16 pci_mmio_read_config16(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000136{
137 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000138 return pci_ops_mmconf.read16(pbus, dev->bus->secondary,
139 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000140}
141
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100142u32 pci_mmio_read_config32(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000143{
144 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000145 return pci_ops_mmconf.read32(pbus, dev->bus->secondary,
146 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000147}
148
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100149void pci_mmio_write_config8(struct device *dev, unsigned int where, u8 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000150{
151 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000152 pci_ops_mmconf.write8(pbus, dev->bus->secondary, dev->path.pci.devfn,
153 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000154}
155
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100156void pci_mmio_write_config16(struct device *dev, unsigned int where, u16 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000157{
158 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000159 pci_ops_mmconf.write16(pbus, dev->bus->secondary, dev->path.pci.devfn,
160 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000161}
162
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100163void pci_mmio_write_config32(struct device *dev, unsigned int where, u32 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000164{
165 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000166 pci_ops_mmconf.write32(pbus, dev->bus->secondary, dev->path.pci.devfn,
167 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000168}
Uwe Hermanne4870472010-11-04 23:23:47 +0000169
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000170#endif