blob: fed17fc0c48588d7869ea84bd455b7abc5bcb5cc [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>
19#include <arch/pciconf.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
23
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030024const struct pci_bus_operations *pci_bus_default_ops(device_t dev)
25{
26#if CONFIG_MMCONF_SUPPORT_DEFAULT
27 return &pci_ops_mmconf;
28#else
29 return &pci_cf8_conf1;
30#endif
31}
32
Edward O'Callaghan016732f2014-10-29 03:04:40 +110033static const struct pci_bus_operations *pci_bus_ops(struct bus *bus, struct device *dev)
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030034{
35 const struct pci_bus_operations *bops;
36 bops = NULL;
37 if (bus && bus->dev && bus->dev->ops && bus->dev->ops->ops_pci_bus) {
38 bops = bus->dev->ops->ops_pci_bus(dev);
39 }
40 if (!bops)
41 bops = pci_bus_default_ops(dev);
42 return bops;
43}
44
Uwe Hermannc1ee4292010-10-17 19:01:48 +000045/*
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030046 * The only consumer of the return value of get_pbus() is pci_bus_ops().
47 * pci_bus_ops() can handle being passed NULL and auto-picks working ops.
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000048 */
Edward O'Callaghan016732f2014-10-29 03:04:40 +110049static struct bus *get_pbus(struct device *dev)
Eric Biedermana9e632c2004-11-18 22:38:08 +000050{
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000051 struct bus *pbus = NULL;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000052
53 if (!dev)
Carl-Daniel Hailfinger87e70502009-06-05 11:41:51 +000054 die("get_pbus: dev is NULL!\n");
Stefan Reinauer4d933dd2009-07-21 21:36:41 +000055 else
56 pbus = dev->bus;
Rudolf Marek3a8565a2009-03-26 21:45:26 +000057
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030058 while (pbus && pbus->dev && !pci_bus_ops(pbus, dev)) {
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000059 if (pbus == pbus->dev->bus) {
Uwe Hermanne4870472010-11-04 23:23:47 +000060 printk(BIOS_ALERT, "%s in endless loop looking for a "
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030061 "parent bus with pci_bus_ops for %s, breaking "
Uwe Hermanne4870472010-11-04 23:23:47 +000062 "out.\n", __func__, dev_path(dev));
Carl-Daniel Hailfingerbba113e2009-03-05 19:33:12 +000063 break;
64 }
Eric Biedermana9e632c2004-11-18 22:38:08 +000065 pbus = pbus->dev->bus;
66 }
Uwe Hermanne4870472010-11-04 23:23:47 +000067
68 if (!pbus || !pbus->dev || !pbus->dev->ops
69 || !pbus->dev->ops->ops_pci_bus) {
70 /* This can happen before the device tree is fully set up. */
71
72 // printk(BIOS_EMERG, "%s: Cannot find PCI bus operations.\n",
73 // dev_path(dev));
74
Carl-Daniel Hailfinger00003ae2009-09-22 00:09:41 +000075 pbus = NULL;
Eric Biedermana9e632c2004-11-18 22:38:08 +000076 }
Uwe Hermanne4870472010-11-04 23:23:47 +000077
Eric Biedermana9e632c2004-11-18 22:38:08 +000078 return pbus;
79}
80
Edward O'Callaghan016732f2014-10-29 03:04:40 +110081u8 pci_read_config8(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000082{
83 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030084 return pci_bus_ops(pbus, dev)->read8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000085 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000086}
87
Edward O'Callaghan016732f2014-10-29 03:04:40 +110088u16 pci_read_config16(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000089{
90 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030091 return pci_bus_ops(pbus, dev)->read16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000092 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +000093}
94
Edward O'Callaghan016732f2014-10-29 03:04:40 +110095u32 pci_read_config32(struct device *dev, unsigned int where)
Eric Biedermana9e632c2004-11-18 22:38:08 +000096{
97 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +030098 return pci_bus_ops(pbus, dev)->read32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +000099 dev->path.pci.devfn, where);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000100}
101
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100102void pci_write_config8(struct device *dev, unsigned int where, u8 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000103{
104 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300105 pci_bus_ops(pbus, dev)->write8(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000106 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000107}
108
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100109void pci_write_config16(struct device *dev, unsigned int where, u16 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000110{
111 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300112 pci_bus_ops(pbus, dev)->write16(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000113 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000114}
115
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100116void pci_write_config32(struct device *dev, unsigned int where, u32 val)
Eric Biedermana9e632c2004-11-18 22:38:08 +0000117{
118 struct bus *pbus = get_pbus(dev);
Kyösti Mälkkiaad07472013-07-04 17:17:45 +0300119 pci_bus_ops(pbus, dev)->write32(pbus, dev->bus->secondary,
Uwe Hermanne4870472010-11-04 23:23:47 +0000120 dev->path.pci.devfn, where, val);
Eric Biedermana9e632c2004-11-18 22:38:08 +0000121}
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000122
Stefan Reinauer08670622009-06-30 15:17:49 +0000123#if CONFIG_MMCONF_SUPPORT
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100124u8 pci_mmio_read_config8(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000125{
126 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000127 return pci_ops_mmconf.read8(pbus, dev->bus->secondary,
128 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000129}
130
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100131u16 pci_mmio_read_config16(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000132{
133 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000134 return pci_ops_mmconf.read16(pbus, dev->bus->secondary,
135 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000136}
137
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100138u32 pci_mmio_read_config32(struct device *dev, unsigned int where)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000139{
140 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000141 return pci_ops_mmconf.read32(pbus, dev->bus->secondary,
142 dev->path.pci.devfn, where);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000143}
144
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100145void pci_mmio_write_config8(struct device *dev, unsigned int where, u8 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000146{
147 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000148 pci_ops_mmconf.write8(pbus, dev->bus->secondary, dev->path.pci.devfn,
149 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000150}
151
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100152void pci_mmio_write_config16(struct device *dev, unsigned int where, u16 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000153{
154 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000155 pci_ops_mmconf.write16(pbus, dev->bus->secondary, dev->path.pci.devfn,
156 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000157}
158
Edward O'Callaghan016732f2014-10-29 03:04:40 +1100159void pci_mmio_write_config32(struct device *dev, unsigned int where, u32 val)
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000160{
161 struct bus *pbus = get_pbus(dev);
Uwe Hermanne4870472010-11-04 23:23:47 +0000162 pci_ops_mmconf.write32(pbus, dev->bus->secondary, dev->path.pci.devfn,
163 where, val);
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000164}
Uwe Hermanne4870472010-11-04 23:23:47 +0000165
Stefan Reinauer43b29cf2009-03-06 19:11:52 +0000166#endif