* [RFC v4 1/6] MIPS: add dma_alloc_coherent()
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-06-30 19:59 ` [RFC v4 2/6] PCI: initial commit Antony Pavlov
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
arch/mips/include/asm/dma-mapping.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
new file mode 100644
index 0000000..555efa5
--- /dev/null
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <xfuncs.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <malloc.h>
+
+static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+
+ ret = xmemalign(PAGE_SIZE, size);
+
+ *dma_handle = CPHYSADDR(ret);
+
+ return (void *)CKSEG1ADDR(ret);
+}
+
+static inline void dma_free_coherent(void *vaddr)
+{
+ free(vaddr);
+}
+
+#endif /* _ASM_DMA_MAPPING_H */
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC v4 2/6] PCI: initial commit
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
2014-06-30 19:59 ` [RFC v4 1/6] MIPS: add dma_alloc_coherent() Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-07-02 6:12 ` Sascha Hauer
2014-06-30 19:59 ` [RFC v4 3/6] commands: add 'lspci' command Antony Pavlov
` (4 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
used shorten version of linux-2.6.39 pci_ids.h
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/pci/Kconfig | 29 ++++
drivers/pci/Makefile | 8 ++
drivers/pci/bus.c | 110 +++++++++++++++
drivers/pci/pci.c | 285 +++++++++++++++++++++++++++++++++++++++
include/linux/mod_devicetable.h | 20 +++
include/linux/pci.h | 292 ++++++++++++++++++++++++++++++++++++++++
include/linux/pci_ids.h | 136 +++++++++++++++++++
include/linux/pci_regs.h | 110 +++++++++++++++
10 files changed, 992 insertions(+)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 53e1e97..12a9d8c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -27,5 +27,6 @@ source "drivers/pinctrl/Kconfig"
source "drivers/bus/Kconfig"
source "drivers/regulator/Kconfig"
source "drivers/reset/Kconfig"
+source "drivers/pci/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ef3604f..1990e86 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -26,3 +26,4 @@ obj-y += pinctrl/
obj-y += bus/
obj-$(CONFIG_REGULATOR) += regulator/
obj-$(CONFIG_RESET_CONTROLLER) += reset/
+obj-$(CONFIG_PCI) += pci/
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
new file mode 100644
index 0000000..9e46592
--- /dev/null
+++ b/drivers/pci/Kconfig
@@ -0,0 +1,29 @@
+config HW_HAS_PCI
+ bool
+
+if HW_HAS_PCI
+
+menu "PCI bus options"
+
+config PCI
+ bool "Support for PCI controller"
+ depends on HW_HAS_PCI
+ help
+ Find out whether you have a PCI motherboard. PCI is the name of a
+ bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. If you have PCI, say Y, otherwise N.
+
+
+config PCI_DEBUG
+ bool "PCI Debugging"
+ depends on PCI
+ help
+ Say Y here if you want the PCI core to produce a bunch of debug
+ messages to the system log. Select this if you are having a
+ problem with PCI support and want to see more of what is going on.
+
+ When in doubt, say N.
+
+endmenu
+
+endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
new file mode 100644
index 0000000..c7d43c3
--- /dev/null
+++ b/drivers/pci/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the PCI bus specific drivers.
+#
+obj-y += pci.o bus.o
+
+ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
+
+CPPFLAGS += $(ccflags-y)
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
new file mode 100644
index 0000000..8215ee5
--- /dev/null
+++ b/drivers/pci/bus.c
@@ -0,0 +1,110 @@
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/pci.h>
+
+/**
+ * pci_match_one_device - Tell if a PCI device structure has a matching
+ * PCI device id structure
+ * @id: single PCI device id structure to match
+ * @dev: the PCI device structure to match against
+ *
+ * Returns the matching pci_device_id structure or %NULL if there is no match.
+ */
+static inline const struct pci_device_id *
+pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
+{
+ if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
+ (id->device == PCI_ANY_ID || id->device == dev->device) &&
+ (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
+ (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
+ !((id->class ^ dev->class) & id->class_mask))
+ return id;
+ return NULL;
+}
+
+static int pci_match(struct device_d *dev, struct driver_d *drv)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_driver *pdrv = to_pci_driver(drv);
+ struct pci_device_id *id;
+
+ for (id = (struct pci_device_id *)pdrv->id_table; id->vendor; id++)
+ if (pci_match_one_device(id, pdev)) {
+ dev->priv = id;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int pci_probe(struct device_d *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_driver *pdrv = to_pci_driver(dev->driver);
+
+ return pdrv->probe(pdev, dev->priv);
+}
+
+static void pci_remove(struct device_d *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_driver *pdrv = to_pci_driver(dev->driver);
+
+ pdrv->remove(pdev);
+}
+
+struct bus_type pci_bus = {
+ .name = "pci",
+ .match = pci_match,
+ .probe = pci_probe,
+ .remove = pci_remove,
+};
+
+static int pci_bus_init(void)
+{
+ return bus_register(&pci_bus);
+}
+pure_initcall(pci_bus_init);
+
+int pci_register_driver(struct pci_driver *pdrv)
+{
+ struct driver_d *drv = &pdrv->driver;
+
+ if (!pdrv->id_table)
+ return -EIO;
+
+ drv->name = pdrv->name;
+ drv->bus = &pci_bus;
+
+ return register_driver(drv);
+}
+
+int pci_register_device(struct pci_dev *pdev)
+{
+ char str[6];
+ struct device_d *dev = &pdev->dev;
+ int ret;
+
+ strcpy(dev->name, "pci");
+ dev->bus = &pci_bus;
+ dev->id = DEVICE_ID_DYNAMIC;
+
+ ret = register_device(dev);
+
+ if (ret)
+ return ret;
+
+ sprintf(str, "%02x", pdev->devfn);
+ dev_add_param_fixed(dev, "devfn", str);
+ sprintf(str, "%04x", (pdev->class >> 8) & 0xffff);
+ dev_add_param_fixed(dev, "class", str);
+ sprintf(str, "%04x", pdev->vendor);
+ dev_add_param_fixed(dev, "vendor", str);
+ sprintf(str, "%04x", pdev->device);
+ dev_add_param_fixed(dev, "device", str);
+ sprintf(str, "%04x", pdev->revision);
+ dev_add_param_fixed(dev, "revision", str);
+
+ return 0;
+}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
new file mode 100644
index 0000000..554cf64
--- /dev/null
+++ b/drivers/pci/pci.c
@@ -0,0 +1,285 @@
+#include <common.h>
+#include <linux/pci.h>
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static struct pci_controller *hose_head, **hose_tail = &hose_head;
+
+LIST_HEAD(pci_root_buses);
+EXPORT_SYMBOL(pci_root_buses);
+
+static struct pci_bus *pci_alloc_bus(void)
+{
+ struct pci_bus *b;
+
+ b = kzalloc(sizeof(*b), GFP_KERNEL);
+ if (b) {
+ INIT_LIST_HEAD(&b->node);
+ INIT_LIST_HEAD(&b->children);
+ INIT_LIST_HEAD(&b->devices);
+ INIT_LIST_HEAD(&b->slots);
+ INIT_LIST_HEAD(&b->resources);
+ }
+ return b;
+}
+
+void register_pci_controller(struct pci_controller *hose)
+{
+ struct pci_bus *bus;
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+
+ bus = pci_alloc_bus();
+ hose->bus = bus;
+ bus->ops = hose->pci_ops;
+ bus->resource[0] = hose->mem_resource;
+ bus->resource[1] = hose->io_resource;
+
+ pci_scan_bus(bus);
+
+ list_add_tail(&bus->node, &pci_root_buses);
+
+ return;
+}
+
+/*
+ * Wrappers for all PCI configuration access functions. They just check
+ * alignment, do locking and call the low-level functions pointed to
+ * by pci_dev->ops.
+ */
+
+#define PCI_byte_BAD 0
+#define PCI_word_BAD (pos & 1)
+#define PCI_dword_BAD (pos & 3)
+
+#define PCI_OP_READ(size,type,len) \
+int pci_bus_read_config_##size \
+ (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
+{ \
+ int res; \
+ u32 data = 0; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ res = bus->ops->read(bus, devfn, pos, len, &data); \
+ *value = (type)data; \
+ return res; \
+}
+
+#define PCI_OP_WRITE(size,type,len) \
+int pci_bus_write_config_##size \
+ (struct pci_bus *bus, unsigned int devfn, int pos, type value) \
+{ \
+ int res; \
+ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
+ res = bus->ops->write(bus, devfn, pos, len, value); \
+ return res; \
+}
+
+PCI_OP_READ(byte, u8, 1)
+PCI_OP_READ(word, u16, 2)
+PCI_OP_READ(dword, u32, 4)
+PCI_OP_WRITE(byte, u8, 1)
+PCI_OP_WRITE(word, u16, 2)
+PCI_OP_WRITE(dword, u32, 4)
+
+EXPORT_SYMBOL(pci_bus_read_config_byte);
+EXPORT_SYMBOL(pci_bus_read_config_word);
+EXPORT_SYMBOL(pci_bus_read_config_dword);
+EXPORT_SYMBOL(pci_bus_write_config_byte);
+EXPORT_SYMBOL(pci_bus_write_config_word);
+EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+static struct pci_dev *alloc_pci_dev(void)
+{
+ struct pci_dev *dev;
+
+ dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ INIT_LIST_HEAD(&dev->bus_list);
+
+ return dev;
+}
+
+unsigned int pci_scan_bus(struct pci_bus *bus)
+{
+ unsigned int devfn, l, max, class;
+ unsigned char cmd, tmp, hdr_type, is_multi = 0;
+ struct pci_dev *dev;
+ resource_size_t last_mem;
+ resource_size_t last_io;
+
+ /* FIXME: use res_start() */
+ last_mem = bus->resource[0]->start;
+ last_io = bus->resource[1]->start;
+
+ DBG("pci_scan_bus for bus %d\n", bus->number);
+ DBG(" last_io = 0x%08x, last_mem = 0x%08x\n", last_io, last_mem);
+ max = bus->secondary;
+
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ int bar;
+ u32 old_bar, mask;
+ int size;
+
+ if (PCI_FUNC(devfn) && !is_multi) {
+ /* not a multi-function device */
+ continue;
+ }
+ if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
+ continue;
+ if (!PCI_FUNC(devfn))
+ is_multi = hdr_type & 0x80;
+
+ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l) ||
+ /* some broken boards return 0 if a slot is empty: */
+ l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
+ continue;
+
+ dev = alloc_pci_dev();
+ if (!dev)
+ return 0;
+
+ dev->bus = bus;
+ dev->devfn = devfn;
+ dev->vendor = l & 0xffff;
+ dev->device = (l >> 16) & 0xffff;
+
+ /* non-destructively determine if device can be a master: */
+ pci_read_config_byte(dev, PCI_COMMAND, &cmd);
+ pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
+ pci_read_config_byte(dev, PCI_COMMAND, &tmp);
+ pci_write_config_byte(dev, PCI_COMMAND, cmd);
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+ dev->revision = class & 0xff;
+ class >>= 8; /* upper 3 bytes */
+ dev->class = class;
+ class >>= 8;
+ dev->hdr_type = hdr_type;
+
+ DBG("PCI: class = %08x, hdr_type = %08x\n", class, hdr_type);
+
+ switch (hdr_type & 0x7f) { /* header type */
+ case PCI_HEADER_TYPE_NORMAL: /* standard header */
+ if (class == PCI_CLASS_BRIDGE_PCI)
+ goto bad;
+
+ /*
+ * read base address registers, again pcibios_fixup() can
+ * tweak these
+ */
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &l);
+ dev->rom_address = (l == 0xffffffff) ? 0 : l;
+ break;
+ default: /* unknown header */
+ bad:
+ printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
+ bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
+ continue;
+ }
+
+ DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device);
+
+ list_add_tail(&dev->bus_list, &bus->devices);
+ pci_register_device(dev);
+
+ if (class == PCI_CLASS_BRIDGE_HOST) {
+ DBG("PCI: skip pci host bridge\n");
+ continue;
+ }
+
+ for (bar = 0; bar < 6; bar++) {
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &old_bar);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, old_bar);
+
+ if (mask == 0 || mask == 0xffffffff) {
+ DBG(" PCI: pbar%d set bad mask\n", bar);
+ continue;
+ }
+
+ if (mask & 0x01) { /* IO */
+ size = -(mask & 0xfffffffe);
+ DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
+ last_io += size;
+
+ } else { /* MEM */
+ size = -(mask & 0xfffffff0);
+ DBG(" PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
+ last_mem += size;
+ }
+ }
+ }
+
+ /*
+ * We've scanned the bus and so we know all about what's on
+ * the other side of any bridges that may be on this bus plus
+ * any devices.
+ *
+ * Return how far we've got finding sub-buses.
+ */
+ DBG("PCI: pci_scan_bus returning with max=%02x\n", max);
+
+ return max;
+}
+
+static void __pci_set_master(struct pci_dev *dev, bool enable)
+{
+ u16 old_cmd, cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &old_cmd);
+ if (enable)
+ cmd = old_cmd | PCI_COMMAND_MASTER;
+ else
+ cmd = old_cmd & ~PCI_COMMAND_MASTER;
+ if (cmd != old_cmd) {
+ dev_dbg(&dev->dev, "%s bus mastering\n",
+ enable ? "enabling" : "disabling");
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+}
+
+/**
+ * pci_set_master - enables bus-mastering for device dev
+ * @dev: the PCI device to enable
+ */
+void pci_set_master(struct pci_dev *dev)
+{
+ __pci_set_master(dev, true);
+}
+EXPORT_SYMBOL(pci_set_master);
+
+/**
+ * pci_clear_master - disables bus-mastering for device dev
+ * @dev: the PCI device to disable
+ */
+void pci_clear_master(struct pci_dev *dev)
+{
+ __pci_set_master(dev, false);
+}
+EXPORT_SYMBOL(pci_clear_master);
+
+/**
+ * pci_enable_device - Initialize device before it's used by a driver.
+ * @dev: PCI device to be initialized
+ */
+int pci_enable_device(struct pci_dev *dev)
+{
+ u32 t;
+
+ pci_read_config_dword(dev, PCI_COMMAND, &t);
+ return pci_write_config_dword(dev, PCI_COMMAND, t
+ | PCI_COMMAND_IO
+ | PCI_COMMAND_MEMORY
+ );
+}
+EXPORT_SYMBOL(pci_enable_device);
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
new file mode 100644
index 0000000..c822075
--- /dev/null
+++ b/include/linux/mod_devicetable.h
@@ -0,0 +1,20 @@
+/*
+ * Device tables which are exported to userspace via
+ * scripts/mod/file2alias.c. You must keep that file in sync with this
+ * header.
+ */
+
+#ifndef LINUX_MOD_DEVICETABLE_H
+#define LINUX_MOD_DEVICETABLE_H
+
+#include <linux/types.h>
+
+#define PCI_ANY_ID (~0)
+
+struct pci_device_id {
+ __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
+ __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+ __u32 class, class_mask; /* (class,subclass,prog-if) triplet */
+};
+
+#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
new file mode 100644
index 0000000..759aea6
--- /dev/null
+++ b/include/linux/pci.h
@@ -0,0 +1,292 @@
+/*
+ * pci.h
+ *
+ * PCI defines and function prototypes
+ * Copyright 1994, Drew Eckhardt
+ * Copyright 1997--1999 Martin Mares <mj@ucw.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ */
+#ifndef LINUX_PCI_H
+#define LINUX_PCI_H
+
+#include <linux/mod_devicetable.h>
+
+#include <linux/pci_regs.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+#include <errno.h>
+#include <io.h>
+
+#include <linux/pci_ids.h>
+
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 7:3 = slot
+ * 2:0 = function
+ */
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+/*
+ * For PCI devices, the region numbers are assigned this way:
+ */
+enum {
+ /* #0-5: standard PCI resources */
+ PCI_STD_RESOURCES,
+ PCI_STD_RESOURCE_END = 5,
+
+ /* #6: expansion ROM resource */
+ PCI_ROM_RESOURCE,
+
+ /* device specific resources */
+#ifdef CONFIG_PCI_IOV
+ PCI_IOV_RESOURCES,
+ PCI_IOV_RESOURCE_END = PCI_IOV_RESOURCES + PCI_SRIOV_NUM_BARS - 1,
+#endif
+
+ /* resources assigned to buses behind the bridge */
+#define PCI_BRIDGE_RESOURCE_NUM 4
+
+ PCI_BRIDGE_RESOURCES,
+ PCI_BRIDGE_RESOURCE_END = PCI_BRIDGE_RESOURCES +
+ PCI_BRIDGE_RESOURCE_NUM - 1,
+
+ /* total resources associated with a PCI device */
+ PCI_NUM_RESOURCES,
+
+ /* preserve this for compatibility */
+ DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES,
+};
+
+/*
+ * Error values that may be returned by PCI functions.
+ */
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+/*
+ * The pci_dev structure is used to describe PCI devices.
+ */
+struct pci_dev {
+ struct list_head bus_list; /* node in per-bus list */
+ struct pci_bus *bus; /* bus this device is on */
+ struct pci_bus *subordinate; /* bus this device bridges to */
+
+ void *sysdata; /* hook for sys-specific extension */
+ struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
+ struct pci_slot *slot; /* Physical slot this device is in */
+
+ struct device_d dev;
+
+ unsigned int devfn; /* encoded device & function index */
+ unsigned short vendor;
+ unsigned short device;
+ unsigned short subsystem_vendor;
+ unsigned short subsystem_device;
+ unsigned int class; /* 3 bytes: (base,sub,prog-if) */
+ u8 revision; /* PCI revision, low byte of class word */
+ u8 hdr_type; /* PCI header type (`multi' flag masked out) */
+
+ struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
+
+ /* Base registers for this device, can be adjusted by
+ * pcibios_fixup() as necessary.
+ */
+ unsigned long base_address[6];
+ unsigned long rom_address;
+};
+#define to_pci_dev(dev) container_of(dev, struct pci_dev, dev)
+
+struct pci_bus {
+ struct list_head node; /* node in list of buses */
+ struct pci_bus *parent; /* parent bus this bridge is on */
+ struct list_head children; /* list of child buses */
+ struct list_head devices; /* list of devices on this bus */
+ struct pci_dev *self; /* bridge device as seen by parent */
+ struct list_head slots; /* list of slots on this bus */
+ struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
+ struct list_head resources; /* address space routed to this bus */
+
+ struct pci_ops *ops; /* configuration access functions */
+ void *sysdata; /* hook for sys-specific extension */
+ struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
+
+ unsigned char number; /* bus number */
+ unsigned char primary; /* number of primary bridge */
+ unsigned char secondary; /* number of secondary bridge */
+ unsigned char subordinate; /* max number of subordinate buses */
+
+ char name[48];
+};
+
+/* Low-level architecture-dependent routines */
+
+struct pci_ops {
+ int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
+ int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
+
+ /* return memory address for pci resource */
+ int (*res_start)(struct pci_bus *bus, resource_size_t res_addr);
+};
+
+extern struct pci_ops *pci_ops;
+
+/*
+ * Each pci channel is a top-level PCI bus seem by CPU. A machine with
+ * multiple PCI channels may have multiple PCI host controllers or a
+ * single controller supporting multiple channels.
+ */
+struct pci_controller {
+ struct pci_controller *next;
+ struct pci_bus *bus;
+
+ struct pci_ops *pci_ops;
+ struct resource *mem_resource;
+ unsigned long mem_offset;
+ struct resource *io_resource;
+ unsigned long io_offset;
+ unsigned long io_map_base;
+
+ unsigned int index;
+
+ /* Optional access methods for reading/writing the bus number
+ of the PCI controller */
+ int (*get_busno)(void);
+ void (*set_busno)(int busno);
+};
+
+struct pci_driver {
+ struct list_head node;
+ const char *name;
+ const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
+ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
+ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
+ struct driver_d driver;
+};
+
+#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
+
+/**
+ * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table
+ * @_table: device table name
+ *
+ * This macro is used to create a struct pci_device_id array (a device table)
+ * in a generic manner.
+ */
+#define DEFINE_PCI_DEVICE_TABLE(_table) \
+ const struct pci_device_id _table[]
+
+/**
+ * PCI_DEVICE - macro used to describe a specific pci device
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific device. The subvendor and subdevice fields will be set to
+ * PCI_ANY_ID.
+ */
+#define PCI_DEVICE(vend, dev) \
+ .vendor = (vend), .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+
+/**
+ * PCI_DEVICE_CLASS - macro used to describe a specific pci device class
+ * @dev_class: the class, subclass, prog-if triple for this device
+ * @dev_class_mask: the class mask for this device
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific PCI class. The vendor, device, subvendor, and subdevice
+ * fields will be set to PCI_ANY_ID.
+ */
+#define PCI_DEVICE_CLASS(dev_class, dev_class_mask) \
+ .class = (dev_class), .class_mask = (dev_class_mask), \
+ .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+
+/**
+ * PCI_VDEVICE - macro used to describe a specific pci device in short form
+ * @vend: the vendor name
+ * @dev: the 16 bit PCI Device ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific PCI device. The subvendor, and subdevice fields will be set
+ * to PCI_ANY_ID. The macro allows the next field to follow as the device
+ * private data.
+ */
+
+#define PCI_VDEVICE(vend, dev) \
+ .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0
+
+int pci_register_driver(struct pci_driver *pdrv);
+int pci_register_device(struct pci_dev *pdev);
+
+extern struct list_head pci_root_buses; /* list of all known PCI buses */
+
+extern unsigned int pci_scan_bus(struct pci_bus *bus);
+extern void register_pci_controller(struct pci_controller *hose);
+
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 *val);
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 *val);
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *val);
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 val);
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 val);
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 val);
+
+static inline int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
+{
+ return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
+}
+static inline int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
+{
+ return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
+}
+static inline int pci_read_config_dword(const struct pci_dev *dev, int where,
+ u32 *val)
+{
+ return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
+}
+static inline int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
+{
+ return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
+}
+static inline int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
+{
+ return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
+}
+static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
+ u32 val)
+{
+ return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
+}
+
+void pci_set_master(struct pci_dev *dev);
+void pci_clear_master(struct pci_dev *dev);
+int pci_enable_device(struct pci_dev *dev);
+
+#endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
new file mode 100644
index 0000000..49e2954
--- /dev/null
+++ b/include/linux/pci_ids.h
@@ -0,0 +1,136 @@
+/*
+ * PCI Class, Vendor and Device IDs
+ *
+ * Please keep sorted.
+ *
+ * Do not add new entries to this file unless the definitions
+ * are shared between multiple drivers.
+ */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_SATA 0x0106
+#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601
+#define PCI_CLASS_STORAGE_SAS 0x0107
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_3D 0x0302
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_PHONE 0x0402
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_RACEWAY 0x0608
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
+#define PCI_CLASS_COMMUNICATION_MODEM 0x0703
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_PIC_IOAPIC 0x080010
+#define PCI_CLASS_SYSTEM_PIC_IOXAPIC 0x080020
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804
+#define PCI_CLASS_SYSTEM_SDHCI 0x0805
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_SCANNER 0x0903
+#define PCI_CLASS_INPUT_GAMEPORT 0x0904
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a80
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_MIPS 0x0b30
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_FIREWIRE_OHCI 0x0c0010
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300
+#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310
+#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320
+#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
+
+#define PCI_BASE_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10
+#define PCI_CLASS_WIRELESS_WHCI 0x0d1010
+
+#define PCI_BASE_CLASS_INTELLIGENT 0x0e
+#define PCI_CLASS_INTELLIGENT_I2O 0x0e00
+
+#define PCI_BASE_CLASS_SATELLITE 0x0f
+#define PCI_CLASS_SATELLITE_TV 0x0f00
+#define PCI_CLASS_SATELLITE_AUDIO 0x0f01
+#define PCI_CLASS_SATELLITE_VOICE 0x0f03
+#define PCI_CLASS_SATELLITE_DATA 0x0f04
+
+#define PCI_BASE_CLASS_CRYPT 0x10
+#define PCI_CLASS_CRYPT_NETWORK 0x1000
+#define PCI_CLASS_CRYPT_ENTERTAINMENT 0x1001
+#define PCI_CLASS_CRYPT_OTHER 0x1080
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_CLASS_SP_DPIO 0x1100
+#define PCI_CLASS_SP_OTHER 0x1180
+
+#define PCI_CLASS_OTHERS 0xff
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
new file mode 100644
index 0000000..14a3ed3
--- /dev/null
+++ b/include/linux/pci_regs.h
@@ -0,0 +1,110 @@
+/*
+ * pci_regs.h
+ *
+ * PCI standard defines
+ * Copyright 1994, Drew Eckhardt
+ * Copyright 1997--1999 Martin Mares <mj@ucw.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ *
+ * For HyperTransport information, please consult the following manuals
+ * from http://www.hypertransport.org
+ *
+ * The HyperTransport I/O Link Specification
+ */
+
+#ifndef LINUX_PCI_REGS_H
+#define LINUX_PCI_REGS_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_INTERRUPT 0x08 /* Interrupt status */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 MHz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
+#endif /* LINUX_PCI_REGS_H */
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC v4 2/6] PCI: initial commit
2014-06-30 19:59 ` [RFC v4 2/6] PCI: initial commit Antony Pavlov
@ 2014-07-02 6:12 ` Sascha Hauer
0 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2014-07-02 6:12 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
On Mon, Jun 30, 2014 at 11:59:45PM +0400, Antony Pavlov wrote:
> used shorten version of linux-2.6.39 pci_ids.h
>
> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> ---
> drivers/Kconfig | 1 +
> drivers/Makefile | 1 +
> drivers/pci/Kconfig | 29 ++++
> drivers/pci/Makefile | 8 ++
> drivers/pci/bus.c | 110 +++++++++++++++
> drivers/pci/pci.c | 285 +++++++++++++++++++++++++++++++++++++++
> include/linux/mod_devicetable.h | 20 +++
> include/linux/pci.h | 292 ++++++++++++++++++++++++++++++++++++++++
> include/linux/pci_ids.h | 136 +++++++++++++++++++
> include/linux/pci_regs.h | 110 +++++++++++++++
> 10 files changed, 992 insertions(+)
>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 53e1e97..12a9d8c 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -27,5 +27,6 @@ source "drivers/pinctrl/Kconfig"
> source "drivers/bus/Kconfig"
> source "drivers/regulator/Kconfig"
> source "drivers/reset/Kconfig"
> +source "drivers/pci/Kconfig"
>
> endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index ef3604f..1990e86 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -26,3 +26,4 @@ obj-y += pinctrl/
> obj-y += bus/
> obj-$(CONFIG_REGULATOR) += regulator/
> obj-$(CONFIG_RESET_CONTROLLER) += reset/
> +obj-$(CONFIG_PCI) += pci/
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> new file mode 100644
> index 0000000..9e46592
> --- /dev/null
> +++ b/drivers/pci/Kconfig
> @@ -0,0 +1,29 @@
> +config HW_HAS_PCI
> + bool
> +
> +if HW_HAS_PCI
> +
> +menu "PCI bus options"
> +
> +config PCI
> + bool "Support for PCI controller"
> + depends on HW_HAS_PCI
> + help
> + Find out whether you have a PCI motherboard. PCI is the name of a
> + bus system, i.e. the way the CPU talks to the other stuff inside
> + your box. If you have PCI, say Y, otherwise N.
> +
> +
> +config PCI_DEBUG
> + bool "PCI Debugging"
> + depends on PCI
> + help
> + Say Y here if you want the PCI core to produce a bunch of debug
> + messages to the system log. Select this if you are having a
> + problem with PCI support and want to see more of what is going on.
> +
> + When in doubt, say N.
> +
> +endmenu
> +
> +endif
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> new file mode 100644
> index 0000000..c7d43c3
> --- /dev/null
> +++ b/drivers/pci/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Makefile for the PCI bus specific drivers.
> +#
> +obj-y += pci.o bus.o
> +
> +ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
> +
> +CPPFLAGS += $(ccflags-y)
> diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
> new file mode 100644
> index 0000000..8215ee5
> --- /dev/null
> +++ b/drivers/pci/bus.c
> @@ -0,0 +1,110 @@
> +#include <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <linux/pci.h>
> +
> +/**
> + * pci_match_one_device - Tell if a PCI device structure has a matching
> + * PCI device id structure
> + * @id: single PCI device id structure to match
> + * @dev: the PCI device structure to match against
> + *
> + * Returns the matching pci_device_id structure or %NULL if there is no match.
> + */
> +static inline const struct pci_device_id *
> +pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
> +{
> + if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
> + (id->device == PCI_ANY_ID || id->device == dev->device) &&
> + (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
> + (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
> + !((id->class ^ dev->class) & id->class_mask))
> + return id;
> + return NULL;
> +}
> +
> +static int pci_match(struct device_d *dev, struct driver_d *drv)
> +{
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct pci_driver *pdrv = to_pci_driver(drv);
> + struct pci_device_id *id;
> +
> + for (id = (struct pci_device_id *)pdrv->id_table; id->vendor; id++)
> + if (pci_match_one_device(id, pdev)) {
> + dev->priv = id;
> + return 0;
> + }
> +
> + return -1;
> +}
> +
> +static int pci_probe(struct device_d *dev)
> +{
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct pci_driver *pdrv = to_pci_driver(dev->driver);
> +
> + return pdrv->probe(pdev, dev->priv);
> +}
> +
> +static void pci_remove(struct device_d *dev)
> +{
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct pci_driver *pdrv = to_pci_driver(dev->driver);
> +
> + pdrv->remove(pdev);
> +}
> +
> +struct bus_type pci_bus = {
> + .name = "pci",
> + .match = pci_match,
> + .probe = pci_probe,
> + .remove = pci_remove,
> +};
> +
> +static int pci_bus_init(void)
> +{
> + return bus_register(&pci_bus);
> +}
> +pure_initcall(pci_bus_init);
> +
> +int pci_register_driver(struct pci_driver *pdrv)
> +{
> + struct driver_d *drv = &pdrv->driver;
> +
> + if (!pdrv->id_table)
> + return -EIO;
> +
> + drv->name = pdrv->name;
> + drv->bus = &pci_bus;
> +
> + return register_driver(drv);
> +}
> +
> +int pci_register_device(struct pci_dev *pdev)
> +{
> + char str[6];
> + struct device_d *dev = &pdev->dev;
> + int ret;
> +
> + strcpy(dev->name, "pci");
> + dev->bus = &pci_bus;
> + dev->id = DEVICE_ID_DYNAMIC;
> +
> + ret = register_device(dev);
> +
> + if (ret)
> + return ret;
> +
> + sprintf(str, "%02x", pdev->devfn);
> + dev_add_param_fixed(dev, "devfn", str);
> + sprintf(str, "%04x", (pdev->class >> 8) & 0xffff);
> + dev_add_param_fixed(dev, "class", str);
> + sprintf(str, "%04x", pdev->vendor);
> + dev_add_param_fixed(dev, "vendor", str);
> + sprintf(str, "%04x", pdev->device);
> + dev_add_param_fixed(dev, "device", str);
> + sprintf(str, "%04x", pdev->revision);
> + dev_add_param_fixed(dev, "revision", str);
> +
> + return 0;
> +}
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> new file mode 100644
> index 0000000..554cf64
> --- /dev/null
> +++ b/drivers/pci/pci.c
> @@ -0,0 +1,285 @@
> +#include <common.h>
> +#include <linux/pci.h>
> +
> +#ifdef DEBUG
> +#define DBG(x...) printk(x)
> +#else
> +#define DBG(x...)
> +#endif
Can we use the standard debug() macro instead please? Also a
#define pr_fmt(fmt) "PCI: " fmt
helps giving the PCI messages some context.
> + default: /* unknown header */
> + bad:
> + printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
> + bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
With the pr_fmt this could become:
pr_err("%02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
> + struct list_head resources; /* address space routed to this bus */
> +
> + struct pci_ops *ops; /* configuration access functions */
> + void *sysdata; /* hook for sys-specific extension */
> + struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
Doesn't this give a warning? We do no have struct proc_dir_entry
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC v4 3/6] commands: add 'lspci' command
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
2014-06-30 19:59 ` [RFC v4 1/6] MIPS: add dma_alloc_coherent() Antony Pavlov
2014-06-30 19:59 ` [RFC v4 2/6] PCI: initial commit Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-06-30 19:59 ` [RFC v4 4/6] net: add RealTek RTL-8139 PCI Ethernet driver Antony Pavlov
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
commands/Kconfig | 8 ++++++++
commands/Makefile | 1 +
commands/lspci.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+)
diff --git a/commands/Kconfig b/commands/Kconfig
index eed6fbd..c98dbc5 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -207,6 +207,14 @@ config CMD_REGULATOR
the regulator command lists the currently registered regulators and
their current state.
+config CMD_LSPCI
+ bool
+ depends on PCI
+ prompt "lspci command"
+ default y
+ help
+ The lspci command allows to list all PCI devices.
+
config CMD_VERSION
tristate
default y
diff --git a/commands/Makefile b/commands/Makefile
index a84d333..d42aca5 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -99,3 +99,4 @@ obj-$(CONFIG_CMD_READF) += readf.o
obj-$(CONFIG_CMD_MENUTREE) += menutree.o
obj-$(CONFIG_CMD_2048) += 2048.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
+obj-$(CONFIG_CMD_LSPCI) += lspci.o
diff --git a/commands/lspci.c b/commands/lspci.c
new file mode 100644
index 0000000..c00b57f
--- /dev/null
+++ b/commands/lspci.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <linux/pci.h>
+
+static int do_lspci(int argc, char *argv[])
+{
+ struct pci_bus *root_bus;
+ struct pci_dev *dev;
+
+ if (list_empty(&pci_root_buses)) {
+ printf("No PCI bus detected\n");
+ return 1;
+ }
+
+ list_for_each_entry(root_bus, &pci_root_buses, node) {
+ list_for_each_entry(dev, &root_bus->devices, bus_list) {
+ printf("%02x: %04x: %04x:%04x (rev %02x)\n",
+ dev->devfn,
+ (dev->class >> 8) & 0xffff,
+ dev->vendor,
+ dev->device,
+ dev->revision);
+ }
+ }
+
+ return 0;
+}
+
+BAREBOX_CMD_START(lspci)
+ .cmd = do_lspci,
+ BAREBOX_CMD_DESC("Show PCI info")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC v4 4/6] net: add RealTek RTL-8139 PCI Ethernet driver
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
` (2 preceding siblings ...)
2014-06-30 19:59 ` [RFC v4 3/6] commands: add 'lspci' command Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-07-02 6:18 ` Sascha Hauer
2014-06-30 19:59 ` [RFC v4 5/6] MIPS: add PCI support for GT64120-based Malta board Antony Pavlov
` (2 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
This driver is based on Linux 2.6.39 8139too driver.
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/net/Kconfig | 8 +
drivers/net/Makefile | 1 +
drivers/net/rtl8139.c | 616 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci_ids.h | 5 +
4 files changed, 630 insertions(+)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7a0d5e1..975c927 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -130,6 +130,14 @@ config DRIVER_NET_ORION
select PHYLIB
select MDIO_MVEBU
+config DRIVER_NET_RTL8139
+ bool "RealTek RTL-8139 PCI Ethernet driver"
+ depends on PCI
+ select PHYLIB
+ help
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the RTL 8139 chips.
+
config DRIVER_NET_SMC911X
bool "smc911x ethernet driver"
select PHYLIB
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 65f0d8b..d907061 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_NET_MICREL) += ksz8864rmn.o
obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
obj-$(CONFIG_DRIVER_NET_ORION) += orion-gbe.o
+obj-$(CONFIG_DRIVER_NET_RTL8139) += rtl8139.o
obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
new file mode 100644
index 0000000..82c3585
--- /dev/null
+++ b/drivers/net/rtl8139.c
@@ -0,0 +1,616 @@
+#include <common.h>
+#include <net.h>
+#include <malloc.h>
+#include <init.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <io.h>
+#include <linux/phy.h>
+#include <linux/pci.h>
+
+#include <asm/dma-mapping.h>
+
+#define RTL8139_DEBUG
+#undef RTL8139_DEBUG
+
+/*
+ * Receive ring size
+ * Warning: 64K ring has hardware issues and may lock up.
+ */
+#define RX_BUF_IDX 0 /* 8K ring */
+#define RX_BUF_LEN (8192 << RX_BUF_IDX)
+#define RX_BUF_PAD 16
+#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
+
+#if RX_BUF_LEN == 65536
+#define RX_BUF_TOT_LEN RX_BUF_LEN
+#else
+#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
+#endif
+
+/* Number of Tx descriptor registers. */
+#define NUM_TX_DESC 4
+
+/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
+#define MAX_ETH_FRAME_SIZE 1536
+
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE
+#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
+
+/* PCI Tuning Parameters
+ Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */
+#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */
+#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
+#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */
+
+struct rtl8139_priv {
+ struct eth_device edev;
+ void __iomem *base;
+ struct pci_dev *pci_dev;
+ unsigned char *rx_ring;
+ unsigned int cur_rx; /* RX buf index of next pkt */
+ dma_addr_t rx_ring_dma;
+
+ u32 rx_config;
+ unsigned int tx_flag;
+ unsigned long cur_tx;
+ unsigned long dirty_tx;
+ unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
+ unsigned char *tx_bufs; /* Tx bounce buffer region. */
+ dma_addr_t tx_bufs_dma;
+
+ struct mii_bus miibus;
+};
+
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+
+/* Registers */
+#define MAC0 0x00
+#define MAR0 0x08
+#define TxStatus0 0x10
+
+enum TxStatusBits {
+ TxHostOwns = 0x2000,
+ TxUnderrun = 0x4000,
+ TxStatOK = 0x8000,
+ TxOutOfWindow = 0x20000000,
+ TxAborted = 0x40000000,
+ TxCarrierLost = 0x80000000,
+};
+
+#define TxAddr0 0x20
+#define RxBuf 0x30
+#define ChipCmd 0x37
+#define CmdReset 0x10
+#define CmdRxEnb 0x08
+#define CmdTxEnb 0x04
+#define RxBufEmpty 0x01
+#define RxBufPtr 0x38
+#define RxBufAddr 0x3A
+#define IntrMask 0x3C
+#define IntrStatus 0x3E
+#define PCIErr 0x8000
+#define PCSTimeout 0x4000
+#define RxFIFOOver 0x0040
+#define RxUnderrun 0x0020
+#define RxOverflow 0x0010
+#define TxErr 0x0008
+#define TxOK 0x0004
+#define RxErr 0x0002
+#define RxOK 0x0001
+#define RxAckBits (RxFIFOOver | RxOverflow | RxOK)
+
+#define TxConfig 0x40
+/* Bits in TxConfig. */
+enum tx_config_bits {
+ /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
+ TxIFGShift = 24,
+ TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
+ TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
+ TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
+ TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
+
+ TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
+ TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */
+ TxClearAbt = (1 << 0), /* Clear abort (WO) */
+ TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */
+ TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */
+
+ TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
+};
+
+#define RxConfig 0x44
+ /* rx fifo threshold */
+#define RxCfgFIFOShift 13
+#define RxCfgFIFONone (7 << RxCfgFIFOShift)
+ /* Max DMA burst */
+#define RxCfgDMAShift 8
+#define RxCfgDMAUnlimited (7 << RxCfgDMAShift)
+ /* rx ring buffer length */
+#define RxCfgRcv8K 0
+#define RxCfgRcv16K (1 << 11)
+#define RxCfgRcv32K (1 << 12)
+#define RxCfgRcv64K ((1 << 11) | (1 << 12))
+ /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */
+#define RxNoWrap (1 << 7)
+#define AcceptErr 0x20
+#define AcceptRunt 0x10
+#define AcceptBroadcast 0x08
+#define AcceptMulticast 0x04
+#define AcceptMyPhys 0x02
+#define AcceptAllPhys 0x01
+
+#define RxMissed 0x4C
+#define Cfg9346 0x50
+#define Cfg9346_Lock 0x00
+#define Cfg9346_Unlock 0xC0
+#define BasicModeCtrl 0x62
+#define BasicModeStatus 0x64
+#define NWayAdvert 0x66
+#define NWayLPAR 0x68
+#define NWayExpansion 0x6a
+
+static const char mii_2_8139_map[8] = {
+ BasicModeCtrl,
+ BasicModeStatus,
+ 0,
+ 0,
+ NWayAdvert,
+ NWayLPAR,
+ NWayExpansion,
+ 0
+};
+
+/* write MMIO register */
+#define RTL_W8(priv, reg, val) writeb(val, ((char *)(priv->base) + reg))
+#define RTL_W16(priv, reg, val) writew(val, ((char *)(priv->base) + reg))
+#define RTL_W32(priv, reg, val) writel(val, ((char *)(priv->base) + reg))
+
+/* read MMIO register */
+#define RTL_R8(priv, reg) readb(((char *)(priv->base) + reg))
+#define RTL_R16(priv, reg) readw(((char *)(priv->base) + reg))
+#define RTL_R32(priv, reg) readl(((char *)(priv->base) + reg))
+
+/* write MMIO register, with flush */
+/* Flush avoids rtl8139 bug w/ posted MMIO writes */
+static inline void RTL_W8_F(struct rtl8139_priv *priv, int reg, int val)
+{
+ RTL_W8(priv, reg, val);
+ RTL_R8(priv, reg);
+}
+
+static inline void RTL_W16_F(struct rtl8139_priv *priv, int reg, int val)
+{
+ RTL_W16(priv, reg, val);
+ RTL_R16(priv, reg);
+}
+
+static inline void RTL_W32_F(struct rtl8139_priv *priv, int reg, int val)
+{
+ RTL_W32(priv, reg, val);
+ RTL_R32(priv, reg);
+}
+
+static const unsigned int rtl8139_rx_config =
+ RxCfgRcv8K | RxNoWrap |
+ (RX_FIFO_THRESH << RxCfgFIFOShift) |
+ (RX_DMA_BURST << RxCfgDMAShift);
+
+static const unsigned int rtl8139_tx_config =
+ TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
+
+static void rtl8139_chip_reset(struct rtl8139_priv *priv)
+{
+ int i;
+
+ /* Soft reset the chip. */
+ RTL_W8(priv, ChipCmd, CmdReset);
+
+ /* Check that the chip has finished the reset. */
+ for (i = 1000; i > 0; i--) {
+ if ((RTL_R8(priv, ChipCmd) & CmdReset) == 0)
+ break;
+ udelay(10);
+ }
+}
+
+static void __set_rx_mode(struct rtl8139_priv *priv)
+{
+ u32 mc_filter[2]; /* Multicast hash filter */
+ int rx_mode;
+ u32 tmp;
+
+ rx_mode =
+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+ AcceptAllPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+
+ /* We can safely update without stopping the chip. */
+ tmp = rtl8139_rx_config | rx_mode;
+ if (priv->rx_config != tmp) {
+ RTL_W32_F(priv, RxConfig, tmp);
+ priv->rx_config = tmp;
+ }
+
+ RTL_W32_F(priv, MAR0 + 0, mc_filter[0]);
+ RTL_W32_F(priv, MAR0 + 4, mc_filter[1]);
+}
+
+/* Start the hardware at open or resume. */
+static void rtl8139_hw_start(struct rtl8139_priv *priv)
+{
+ u32 i;
+ u8 tmp;
+
+ rtl8139_chip_reset(priv);
+
+ /* unlock Config[01234] and BMCR register writes */
+ RTL_W8_F(priv, Cfg9346, Cfg9346_Unlock);
+
+ /* FIXME */
+#if 0
+ /* Restore our idea of the MAC address. */
+ RTL_W32_F(priv, MAC0 + 0, *(__le32 *) (dev->dev_addr + 0));
+ RTL_W32_F(priv, MAC0 + 4, *(__le16 *) (dev->dev_addr + 4));
+#endif
+
+ priv->cur_rx = 0;
+
+ /* init Rx ring buffer DMA address */
+ RTL_W32_F(priv, RxBuf, priv->rx_ring_dma);
+
+ /* Must enable Tx/Rx before setting transfer thresholds! */
+ RTL_W8(priv, ChipCmd, CmdRxEnb | CmdTxEnb);
+
+ priv->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
+ RTL_W32(priv, RxConfig, priv->rx_config);
+ RTL_W32(priv, TxConfig, rtl8139_tx_config);
+
+ /* Lock Config[01234] and BMCR register writes */
+ RTL_W8(priv, Cfg9346, Cfg9346_Lock);
+
+ /* init Tx buffer DMA addresses */
+ for (i = 0; i < NUM_TX_DESC; i++)
+ RTL_W32_F(priv, TxAddr0 + (i * 4), priv->tx_bufs_dma + (priv->tx_buf[i] - priv->tx_bufs));
+
+ RTL_W32(priv, RxMissed, 0);
+
+ __set_rx_mode(priv);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16(priv, IntrMask, 0);
+
+ /* make sure RxTx has started */
+ tmp = RTL_R8(priv, ChipCmd);
+ if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))
+ RTL_W8(priv, ChipCmd, CmdRxEnb | CmdTxEnb);
+}
+
+static inline void rtl8139_tx_clear(struct rtl8139_priv *priv)
+{
+ priv->cur_tx = 0;
+ priv->dirty_tx = 0;
+
+ /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void rtl8139_init_ring(struct rtl8139_priv *priv)
+{
+ int i;
+
+ priv->cur_rx = 0;
+ priv->cur_tx = 0;
+ priv->dirty_tx = 0;
+
+ for (i = 0; i < NUM_TX_DESC; i++)
+ priv->tx_buf[i] = &priv->tx_bufs[i * TX_BUF_SIZE];
+}
+
+static int rtl8139_phy_read(struct mii_bus *bus, int phy_addr, int reg)
+{
+ struct rtl8139_priv *priv = bus->priv;
+ int val;
+
+ val = 0xffff;
+
+ if (phy_addr == 0) { /* Really a 8139. Use internal registers. */
+ val = reg < 8 && mii_2_8139_map[reg] ?
+ RTL_R16(priv, mii_2_8139_map[reg]) : 0;
+ }
+
+ return val;
+}
+
+static int rtl8139_phy_write(struct mii_bus *bus, int phy_addr,
+ int reg, u16 val)
+{
+ struct rtl8139_priv *priv = bus->priv;
+
+ if (phy_addr == 0) { /* Really a 8139. Use internal registers. */
+ if (reg == 0) {
+ RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
+ RTL_W16(priv, BasicModeCtrl, val);
+ RTL_W8(priv, Cfg9346, Cfg9346_Lock);
+ } else if (reg < 8 && mii_2_8139_map[reg]) {
+ RTL_W16(priv, mii_2_8139_map[reg], val);
+ }
+ }
+
+ return 0;
+}
+
+static int rtl8139_get_ethaddr(struct eth_device *edev, unsigned char *m)
+{
+ struct rtl8139_priv *priv = edev->priv;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ m[i] = RTL_R8(priv, (MAC0 + i));
+ }
+
+ return 0;
+}
+
+static int rtl8139_set_ethaddr(struct eth_device *edev,
+ unsigned char *mac_addr)
+{
+ struct rtl8139_priv *priv = edev->priv;
+ int i;
+
+ RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
+
+ for (i = 0; i < 6; i++) {
+ RTL_W8(priv, (MAC0 + i), mac_addr[i]);
+ RTL_R8(priv, mac_addr[i]);
+ }
+
+ RTL_W8(priv, Cfg9346, Cfg9346_Lock);
+
+ return 0;
+}
+
+static int rtl8139_init_dev(struct eth_device *edev)
+{
+ struct rtl8139_priv *priv = edev->priv;
+
+ rtl8139_chip_reset(priv);
+ pci_set_master(priv->pci_dev);
+
+ return 0;
+}
+
+static int rtl8139_eth_open(struct eth_device *edev)
+{
+ struct rtl8139_priv *priv = edev->priv;
+ int ret;
+
+ priv->tx_bufs = dma_alloc_coherent(TX_BUF_TOT_LEN, &priv->tx_bufs_dma);
+ priv->rx_ring = dma_alloc_coherent(RX_BUF_TOT_LEN, &priv->rx_ring_dma);
+ priv->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+
+ rtl8139_init_ring(priv);
+ rtl8139_hw_start(priv);
+
+ ret = phy_device_connect(edev, &priv->miibus, 0, NULL, 0,
+ PHY_INTERFACE_MODE_NA);
+
+ return ret;
+}
+
+static void rtl8139_eth_halt(struct eth_device *edev)
+{
+ struct rtl8139_priv *priv = edev->priv;
+
+ /* Stop the chip's Tx and Rx DMA processes. */
+ RTL_W8(priv, ChipCmd, 0);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16(priv, IntrMask, 0);
+
+ pci_clear_master(priv->pci_dev);
+
+ /* Green! Put the chip in low-power mode. */
+ RTL_W8(priv, Cfg9346, Cfg9346_Unlock);
+}
+
+static void rtl8139_tx_interrupt(struct rtl8139_priv *priv)
+{
+ unsigned long dirty_tx, tx_left;
+
+ dirty_tx = priv->dirty_tx;
+ tx_left = priv->cur_tx - dirty_tx;
+ while (tx_left > 0) {
+ int entry = dirty_tx % NUM_TX_DESC;
+ int txstatus;
+
+ txstatus = RTL_R32(priv, TxStatus0 + (entry * sizeof(u32)));
+
+ if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
+ break; /* It still hasn't been Txed */
+
+ /* Note: TxCarrierLost is always asserted at 100mbps. */
+ if (txstatus & (TxOutOfWindow | TxAborted)) {
+ /* There was an major error, log it. */
+ printk("Transmit error, Tx status %08x\n", txstatus);
+ if (txstatus & TxAborted) {
+ RTL_W32(priv, TxConfig, TxClearAbt);
+ RTL_W16(priv, IntrStatus, TxErr);
+ }
+ } else {
+ if (txstatus & TxUnderrun) {
+ /* Add 64 to the Tx FIFO threshold. */
+ if (priv->tx_flag < 0x00300000)
+ priv->tx_flag += 0x00020000;
+ }
+ }
+
+ dirty_tx++;
+ tx_left--;
+ }
+
+ if (priv->dirty_tx != dirty_tx) {
+ priv->dirty_tx = dirty_tx;
+ }
+}
+
+static int rtl8139_eth_send(struct eth_device *edev, void *packet,
+ int packet_length)
+{
+ struct rtl8139_priv *priv = edev->priv;
+
+ unsigned int entry;
+
+ rtl8139_tx_interrupt(priv);
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = priv->cur_tx % NUM_TX_DESC;
+
+ /* Note: the chip doesn't have auto-pad! */
+ if (likely(packet_length < TX_BUF_SIZE)) {
+ if (packet_length < ETH_ZLEN)
+ memset(priv->tx_buf[entry], 0, ETH_ZLEN);
+ memcpy(priv->tx_buf[entry], packet, packet_length);
+ } else {
+ printk("packet too long\n");
+ return 0;
+ }
+
+ /*
+ * Writing to TxStatus triggers a DMA transfer of the data
+ * copied to tp->tx_buf[entry] above.
+ */
+ if (packet_length < ETH_ZLEN) {
+ packet_length = ETH_ZLEN;
+ }
+ RTL_W32_F(priv, (TxStatus0 + (entry * sizeof(u32))),
+ (priv->tx_flag | packet_length));
+
+ priv->cur_tx++;
+
+ return 0;
+}
+
+static const u16 rtl8139_intr_mask =
+ PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
+ TxErr | TxOK | RxErr | RxOK;
+
+static int rtl8139_eth_rx(struct eth_device *edev)
+{
+ struct rtl8139_priv *priv = edev->priv;
+ unsigned char *rx_ring = priv->rx_ring;
+ unsigned int cur_rx = priv->cur_rx;
+ unsigned int rx_size = 0;
+
+ u32 ring_offset = cur_rx % RX_BUF_LEN;
+ u32 rx_status;
+ unsigned int pkt_size;
+
+ rtl8139_tx_interrupt(priv);
+
+ if (RTL_R8(priv, ChipCmd) & RxBufEmpty) {
+ /* no data */
+ return 0;
+ }
+
+ rx_status = le32_to_cpu(*(__le32 *) (rx_ring + ring_offset));
+ rx_size = rx_status >> 16;
+ pkt_size = rx_size - 4;
+
+ net_receive(edev, &rx_ring[ring_offset + 4], pkt_size);
+
+ cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+ cur_rx = cur_rx & (RX_BUF_LEN - 1); /* FIXME */
+ RTL_W16(priv, RxBufPtr, (u16) (cur_rx - 16));
+
+ priv->cur_rx = cur_rx;
+
+ return pkt_size /* size */;
+}
+
+static int rtl8139_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct eth_device *edev;
+ struct rtl8139_priv *priv;
+ int ret;
+ u32 bar;
+ struct pci_bus *bus = pdev->bus;
+ struct device_d *dev = &pdev->dev;
+
+ /* enable pci device */
+ pci_enable_device(pdev);
+
+ priv = xzalloc(sizeof(struct rtl8139_priv));
+
+ edev = &priv->edev;
+ dev->type_data = edev;
+ edev->priv = priv;
+
+ priv->pci_dev = pdev;
+
+ priv->miibus.read = rtl8139_phy_read;
+ priv->miibus.write = rtl8139_phy_write;
+ priv->miibus.priv = priv;
+ priv->miibus.parent = &edev->dev;
+
+ /* FIXME: pci_resource_start() */
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &bar);
+
+ /* FIXME: use pci_iomap() */
+ priv->base = (void *)bus->ops->res_start(bus, bar);
+
+ printk("found rtl8139 (rev %02x) at %02x: %04x (base=%p)\n",
+ pdev->revision,
+ pdev->devfn,
+ (pdev->class >> 8) & 0xffff,
+ priv->base);
+
+ edev->init = rtl8139_init_dev;
+ edev->open = rtl8139_eth_open;
+ edev->send = rtl8139_eth_send;
+ edev->recv = rtl8139_eth_rx;
+ edev->get_ethaddr = rtl8139_get_ethaddr;
+ edev->set_ethaddr = rtl8139_set_ethaddr;
+ edev->halt = rtl8139_eth_halt;
+ edev->parent = dev;
+
+ ret = eth_register(edev);
+ if (ret)
+ goto eth_err;
+
+ ret = mdiobus_register(&priv->miibus);
+ if (ret)
+ goto mdio_err;
+
+ return 0;
+
+mdio_err:
+ eth_unregister(edev);
+
+eth_err:
+ free(priv);
+
+ return ret;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139), },
+ { },
+};
+
+static struct pci_driver rtl8139_eth_driver = {
+ .name = "rtl8139_eth",
+ .id_table = rtl8139_pci_tbl,
+ .probe = rtl8139_probe,
+};
+
+static int rtl8139_init(void)
+{
+ return pci_register_driver(&rtl8139_eth_driver);
+}
+device_initcall(rtl8139_init);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 49e2954..17ac7fd 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -134,3 +134,8 @@
#define PCI_CLASS_SP_OTHER 0x1180
#define PCI_CLASS_OTHERS 0xff
+
+/* Vendors and devices. Sort key: vendor first, device next. */
+
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_DEVICE_ID_REALTEK_8139 0x8139
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC v4 4/6] net: add RealTek RTL-8139 PCI Ethernet driver
2014-06-30 19:59 ` [RFC v4 4/6] net: add RealTek RTL-8139 PCI Ethernet driver Antony Pavlov
@ 2014-07-02 6:18 ` Sascha Hauer
0 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2014-07-02 6:18 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
On Mon, Jun 30, 2014 at 11:59:47PM +0400, Antony Pavlov wrote:
> This driver is based on Linux 2.6.39 8139too driver.
>
> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> ---
> drivers/net/Kconfig | 8 +
> drivers/net/Makefile | 1 +
> drivers/net/rtl8139.c | 616 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci_ids.h | 5 +
> 4 files changed, 630 insertions(+)
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 7a0d5e1..975c927 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -130,6 +130,14 @@ config DRIVER_NET_ORION
> select PHYLIB
> select MDIO_MVEBU
>
> +config DRIVER_NET_RTL8139
> + bool "RealTek RTL-8139 PCI Ethernet driver"
> + depends on PCI
> + select PHYLIB
> + help
> + This is a driver for the Fast Ethernet PCI network cards based on
> + the RTL 8139 chips.
> +
> config DRIVER_NET_SMC911X
> bool "smc911x ethernet driver"
> select PHYLIB
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 65f0d8b..d907061 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_NET_MICREL) += ksz8864rmn.o
> obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
> obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
> obj-$(CONFIG_DRIVER_NET_ORION) += orion-gbe.o
> +obj-$(CONFIG_DRIVER_NET_RTL8139) += rtl8139.o
> obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
> obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
> obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
> diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
> new file mode 100644
> index 0000000..82c3585
> --- /dev/null
> +++ b/drivers/net/rtl8139.c
> @@ -0,0 +1,616 @@
> +#include <common.h>
> +#include <net.h>
> +#include <malloc.h>
> +#include <init.h>
> +#include <xfuncs.h>
> +#include <errno.h>
> +#include <io.h>
> +#include <linux/phy.h>
> +#include <linux/pci.h>
> +
> +#include <asm/dma-mapping.h>
> +
> +#define RTL8139_DEBUG
> +#undef RTL8139_DEBUG
> +
> +/*
> + * Receive ring size
> + * Warning: 64K ring has hardware issues and may lock up.
> + */
> +#define RX_BUF_IDX 0 /* 8K ring */
> +#define RX_BUF_LEN (8192 << RX_BUF_IDX)
> +#define RX_BUF_PAD 16
> +#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
> +
> +#if RX_BUF_LEN == 65536
> +#define RX_BUF_TOT_LEN RX_BUF_LEN
> +#else
> +#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
> +#endif
> +
> +/* Number of Tx descriptor registers. */
> +#define NUM_TX_DESC 4
> +
> +/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
> +#define MAX_ETH_FRAME_SIZE 1536
> +
> +/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
> +#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE
> +#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC)
> +
> +/* PCI Tuning Parameters
> + Threshold is bytes transferred to chip before transmission starts. */
> +#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
> +
> +/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */
> +#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */
> +#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */
> +#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
> +#define TX_RETRY 8 /* 0-15. retries = 16 + (TX_RETRY * 16) */
> +
> +struct rtl8139_priv {
> + struct eth_device edev;
> + void __iomem *base;
> + struct pci_dev *pci_dev;
> + unsigned char *rx_ring;
> + unsigned int cur_rx; /* RX buf index of next pkt */
> + dma_addr_t rx_ring_dma;
> +
> + u32 rx_config;
> + unsigned int tx_flag;
> + unsigned long cur_tx;
> + unsigned long dirty_tx;
> + unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
> + unsigned char *tx_bufs; /* Tx bounce buffer region. */
> + dma_addr_t tx_bufs_dma;
> +
> + struct mii_bus miibus;
> +};
> +
> +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
> +
> +/* Registers */
> +#define MAC0 0x00
> +#define MAR0 0x08
> +#define TxStatus0 0x10
> +
> +enum TxStatusBits {
> + TxHostOwns = 0x2000,
> + TxUnderrun = 0x4000,
> + TxStatOK = 0x8000,
> + TxOutOfWindow = 0x20000000,
> + TxAborted = 0x40000000,
> + TxCarrierLost = 0x80000000,
> +};
> +
> +#define TxAddr0 0x20
> +#define RxBuf 0x30
> +#define ChipCmd 0x37
> +#define CmdReset 0x10
> +#define CmdRxEnb 0x08
> +#define CmdTxEnb 0x04
> +#define RxBufEmpty 0x01
> +#define RxBufPtr 0x38
> +#define RxBufAddr 0x3A
> +#define IntrMask 0x3C
> +#define IntrStatus 0x3E
> +#define PCIErr 0x8000
> +#define PCSTimeout 0x4000
> +#define RxFIFOOver 0x0040
> +#define RxUnderrun 0x0020
> +#define RxOverflow 0x0010
> +#define TxErr 0x0008
> +#define TxOK 0x0004
> +#define RxErr 0x0002
> +#define RxOK 0x0001
> +#define RxAckBits (RxFIFOOver | RxOverflow | RxOK)
> +
> +#define TxConfig 0x40
> +/* Bits in TxConfig. */
> +enum tx_config_bits {
> + /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
> + TxIFGShift = 24,
> + TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
> + TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
> + TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
> + TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
> +
> + TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
> + TxCRC = (1 << 16), /* DISABLE Tx pkt CRC append */
> + TxClearAbt = (1 << 0), /* Clear abort (WO) */
> + TxDMAShift = 8, /* DMA burst value (0-7) is shifted X many bits */
> + TxRetryShift = 4, /* TXRR value (0-15) is shifted X many bits */
> +
> + TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
> +};
> +
> +#define RxConfig 0x44
> + /* rx fifo threshold */
> +#define RxCfgFIFOShift 13
> +#define RxCfgFIFONone (7 << RxCfgFIFOShift)
> + /* Max DMA burst */
> +#define RxCfgDMAShift 8
> +#define RxCfgDMAUnlimited (7 << RxCfgDMAShift)
> + /* rx ring buffer length */
> +#define RxCfgRcv8K 0
> +#define RxCfgRcv16K (1 << 11)
> +#define RxCfgRcv32K (1 << 12)
> +#define RxCfgRcv64K ((1 << 11) | (1 << 12))
> + /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */
> +#define RxNoWrap (1 << 7)
> +#define AcceptErr 0x20
> +#define AcceptRunt 0x10
> +#define AcceptBroadcast 0x08
> +#define AcceptMulticast 0x04
> +#define AcceptMyPhys 0x02
> +#define AcceptAllPhys 0x01
> +
> +#define RxMissed 0x4C
> +#define Cfg9346 0x50
> +#define Cfg9346_Lock 0x00
> +#define Cfg9346_Unlock 0xC0
> +#define BasicModeCtrl 0x62
> +#define BasicModeStatus 0x64
> +#define NWayAdvert 0x66
> +#define NWayLPAR 0x68
> +#define NWayExpansion 0x6a
> +
> +static const char mii_2_8139_map[8] = {
> + BasicModeCtrl,
> + BasicModeStatus,
> + 0,
> + 0,
> + NWayAdvert,
> + NWayLPAR,
> + NWayExpansion,
> + 0
> +};
> +
> +/* write MMIO register */
> +#define RTL_W8(priv, reg, val) writeb(val, ((char *)(priv->base) + reg))
> +#define RTL_W16(priv, reg, val) writew(val, ((char *)(priv->base) + reg))
> +#define RTL_W32(priv, reg, val) writel(val, ((char *)(priv->base) + reg))
> +
> +/* read MMIO register */
> +#define RTL_R8(priv, reg) readb(((char *)(priv->base) + reg))
> +#define RTL_R16(priv, reg) readw(((char *)(priv->base) + reg))
> +#define RTL_R32(priv, reg) readl(((char *)(priv->base) + reg))
> +
> +/* write MMIO register, with flush */
> +/* Flush avoids rtl8139 bug w/ posted MMIO writes */
> +static inline void RTL_W8_F(struct rtl8139_priv *priv, int reg, int val)
> +{
> + RTL_W8(priv, reg, val);
> + RTL_R8(priv, reg);
> +}
> +
> +static inline void RTL_W16_F(struct rtl8139_priv *priv, int reg, int val)
> +{
> + RTL_W16(priv, reg, val);
> + RTL_R16(priv, reg);
> +}
> +
> +static inline void RTL_W32_F(struct rtl8139_priv *priv, int reg, int val)
> +{
> + RTL_W32(priv, reg, val);
> + RTL_R32(priv, reg);
> +}
> +
> +static const unsigned int rtl8139_rx_config =
> + RxCfgRcv8K | RxNoWrap |
> + (RX_FIFO_THRESH << RxCfgFIFOShift) |
> + (RX_DMA_BURST << RxCfgDMAShift);
> +
> +static const unsigned int rtl8139_tx_config =
> + TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
> +
> +static void rtl8139_chip_reset(struct rtl8139_priv *priv)
> +{
> + int i;
> +
> + /* Soft reset the chip. */
> + RTL_W8(priv, ChipCmd, CmdReset);
> +
> + /* Check that the chip has finished the reset. */
> + for (i = 1000; i > 0; i--) {
> + if ((RTL_R8(priv, ChipCmd) & CmdReset) == 0)
> + break;
> + udelay(10);
> + }
> +}
> +
> +static void __set_rx_mode(struct rtl8139_priv *priv)
> +{
> + u32 mc_filter[2]; /* Multicast hash filter */
> + int rx_mode;
> + u32 tmp;
> +
> + rx_mode =
> + AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
> + AcceptAllPhys;
> + mc_filter[1] = mc_filter[0] = 0xffffffff;
> +
> + /* We can safely update without stopping the chip. */
> + tmp = rtl8139_rx_config | rx_mode;
> + if (priv->rx_config != tmp) {
> + RTL_W32_F(priv, RxConfig, tmp);
> + priv->rx_config = tmp;
> + }
> +
> + RTL_W32_F(priv, MAR0 + 0, mc_filter[0]);
> + RTL_W32_F(priv, MAR0 + 4, mc_filter[1]);
> +}
> +
> +/* Start the hardware at open or resume. */
> +static void rtl8139_hw_start(struct rtl8139_priv *priv)
> +{
> + u32 i;
> + u8 tmp;
> +
> + rtl8139_chip_reset(priv);
> +
> + /* unlock Config[01234] and BMCR register writes */
> + RTL_W8_F(priv, Cfg9346, Cfg9346_Unlock);
> +
> + /* FIXME */
> +#if 0
> + /* Restore our idea of the MAC address. */
> + RTL_W32_F(priv, MAC0 + 0, *(__le32 *) (dev->dev_addr + 0));
> + RTL_W32_F(priv, MAC0 + 4, *(__le16 *) (dev->dev_addr + 4));
> +#endif
Is this something that needs fixing? The MAC Address should be
configured correctly without this code, right?
> + priv->miibus.read = rtl8139_phy_read;
> + priv->miibus.write = rtl8139_phy_write;
> + priv->miibus.priv = priv;
> + priv->miibus.parent = &edev->dev;
> +
> + /* FIXME: pci_resource_start() */
> + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &bar);
> +
> + /* FIXME: use pci_iomap() */
> + priv->base = (void *)bus->ops->res_start(bus, bar);
barebox has resources. Can't we use them here? What's missing?
> +
> + printk("found rtl8139 (rev %02x) at %02x: %04x (base=%p)\n",
> + pdev->revision,
> + pdev->devfn,
> + (pdev->class >> 8) & 0xffff,
> + priv->base);
dev_info
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC v4 5/6] MIPS: add PCI support for GT64120-based Malta board
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
` (3 preceding siblings ...)
2014-06-30 19:59 ` [RFC v4 4/6] net: add RealTek RTL-8139 PCI Ethernet driver Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-06-30 19:59 ` [RFC v4 6/6] MIPS: qemu-malta_defconfig: enable PCI & network stuff Antony Pavlov
2014-07-02 6:05 ` [RFC v4 0/6] barebox PCI support Sascha Hauer
6 siblings, 0 replies; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
arch/mips/Kconfig | 1 +
arch/mips/include/asm/gt64120.h | 53 +++++
arch/mips/mach-malta/Makefile | 1 +
arch/mips/mach-malta/include/mach/mach-gt64120.h | 2 +
arch/mips/mach-malta/pci.c | 236 +++++++++++++++++++++++
5 files changed, 293 insertions(+)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d4e9e1c..bc68c67 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -45,6 +45,7 @@ config MACH_MIPS_MALTA
select SYS_SUPPORTS_BIG_ENDIAN
select HAS_DEBUG_LL
select GPIOLIB
+ select HW_HAS_PCI
config MACH_MIPS_AR231X
bool "Atheros ar231x-based boards"
diff --git a/arch/mips/include/asm/gt64120.h b/arch/mips/include/asm/gt64120.h
index 6b2ad0f..7e783c8 100644
--- a/arch/mips/include/asm/gt64120.h
+++ b/arch/mips/include/asm/gt64120.h
@@ -18,6 +18,8 @@
#ifndef _ASM_GT64120_H
#define _ASM_GT64120_H
+#define MSK(n) ((1 << (n)) - 1)
+
#define GT_DEF_BASE 0x14000000
/*
@@ -34,4 +36,55 @@
#define GT_PCI0M1LD_OFS 0x080
#define GT_PCI0M1HD_OFS 0x088
+#define GT_PCI0IOREMAP_OFS 0x0f0
+#define GT_PCI0M0REMAP_OFS 0x0f8
+#define GT_PCI0M1REMAP_OFS 0x100
+
+/* Interrupts. */
+#define GT_INTRCAUSE_OFS 0xc18
+
+/* PCI Internal. */
+#define GT_PCI0_CMD_OFS 0xc00
+#define GT_PCI0_CFGADDR_OFS 0xcf8
+#define GT_PCI0_CFGDATA_OFS 0xcfc
+
+#define GT_PCI_DCRM_SHF 21
+#define GT_PCI_LD_SHF 0
+#define GT_PCI_LD_MSK (MSK(15) << GT_PCI_LD_SHF)
+#define GT_PCI_HD_SHF 0
+#define GT_PCI_HD_MSK (MSK(7) << GT_PCI_HD_SHF)
+#define GT_PCI_REMAP_SHF 0
+#define GT_PCI_REMAP_MSK (MSK(11) << GT_PCI_REMAP_SHF)
+
+#define GT_INTRCAUSE_MASABORT0_SHF 18
+#define GT_INTRCAUSE_MASABORT0_MSK (MSK(1) << GT_INTRCAUSE_MASABORT0_SHF)
+#define GT_INTRCAUSE_MASABORT0_BIT GT_INTRCAUSE_MASABORT0_MSK
+
+#define GT_INTRCAUSE_TARABORT0_SHF 19
+#define GT_INTRCAUSE_TARABORT0_MSK (MSK(1) << GT_INTRCAUSE_TARABORT0_SHF)
+#define GT_INTRCAUSE_TARABORT0_BIT GT_INTRCAUSE_TARABORT0_MSK
+
+#define GT_PCI0_CFGADDR_REGNUM_SHF 2
+#define GT_PCI0_CFGADDR_REGNUM_MSK (MSK(6) << GT_PCI0_CFGADDR_REGNUM_SHF)
+#define GT_PCI0_CFGADDR_FUNCTNUM_SHF 8
+#define GT_PCI0_CFGADDR_FUNCTNUM_MSK (MSK(3) << GT_PCI0_CFGADDR_FUNCTNUM_SHF)
+#define GT_PCI0_CFGADDR_DEVNUM_SHF 11
+#define GT_PCI0_CFGADDR_DEVNUM_MSK (MSK(5) << GT_PCI0_CFGADDR_DEVNUM_SHF)
+#define GT_PCI0_CFGADDR_BUSNUM_SHF 16
+#define GT_PCI0_CFGADDR_BUSNUM_MSK (MSK(8) << GT_PCI0_CFGADDR_BUSNUM_SHF)
+#define GT_PCI0_CFGADDR_CONFIGEN_SHF 31
+#define GT_PCI0_CFGADDR_CONFIGEN_MSK (MSK(1) << GT_PCI0_CFGADDR_CONFIGEN_SHF)
+#define GT_PCI0_CFGADDR_CONFIGEN_BIT GT_PCI0_CFGADDR_CONFIGEN_MSK
+
+/*
+ * Because of an error/peculiarity in the Galileo chip, we need to swap the
+ * bytes when running bigendian. We also provide non-swapping versions.
+ */
+#define __GT_READ(ofs) \
+ (*(volatile u32 *)(GT64120_BASE+(ofs)))
+#define __GT_WRITE(ofs, data) \
+ do { *(volatile u32 *)(GT64120_BASE+(ofs)) = (data); } while (0)
+#define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs))
+#define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data))
+
#endif /* _ASM_GT64120_H */
diff --git a/arch/mips/mach-malta/Makefile b/arch/mips/mach-malta/Makefile
index f3cc668..0c5a701 100644
--- a/arch/mips/mach-malta/Makefile
+++ b/arch/mips/mach-malta/Makefile
@@ -1 +1,2 @@
obj-y += reset.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/mach-malta/include/mach/mach-gt64120.h b/arch/mips/mach-malta/include/mach/mach-gt64120.h
index ed1e23e..8f20fcf 100644
--- a/arch/mips/mach-malta/include/mach/mach-gt64120.h
+++ b/arch/mips/mach-malta/include/mach/mach-gt64120.h
@@ -10,4 +10,6 @@
#define MIPS_GT_BASE 0x1be00000
+#define GT64120_BASE 0xbbe00000
+
#endif /* _ASM_MACH_MIPS_MACH_GT64120_DEP_H */
diff --git a/arch/mips/mach-malta/pci.c b/arch/mips/mach-malta/pci.c
new file mode 100644
index 0000000..9035175
--- /dev/null
+++ b/arch/mips/mach-malta/pci.c
@@ -0,0 +1,236 @@
+#include <common.h>
+#include <types.h>
+#include <driver.h>
+#include <init.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include <linux/pci.h>
+#include <asm/gt64120.h>
+
+#include <mach/mach-gt64120.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+static struct resource gt64120_mem_resource = {
+ .name = "GT-64120 PCI MEM",
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource gt64120_io_resource = {
+ .name = "GT-64120 PCI I/O",
+ .flags = IORESOURCE_IO,
+};
+
+static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
+{
+ unsigned char busnum = bus->number;
+ u32 intr;
+
+ if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
+ return -1; /* Because of a bug in the galileo (for slot 31). */
+
+ /* Clear cause register bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else
+ __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else {
+ if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ *data = GT_READ(GT_PCI0_CFGDATA_OFS);
+ } else
+ *data = __GT_READ(GT_PCI0_CFGDATA_OFS);
+ }
+
+ /* Check for master or target abort */
+ intr = GT_READ(GT_INTRCAUSE_OFS);
+
+ if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
+ /* Error occurred */
+
+ /* Clear bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int gt64xxx_pci0_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ u32 data = 0;
+
+ if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if (size == 4)
+ data = val;
+ else {
+ if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus,
+ devfn, where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/* function returns memory address for begin of pci resource */
+static int gt64xxx_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+ return KSEG0ADDR(res_addr);
+}
+
+struct pci_ops gt64xxx_pci0_ops = {
+ .read = gt64xxx_pci0_pcibios_read,
+ .write = gt64xxx_pci0_pcibios_write,
+
+ .res_start = gt64xxx_res_start,
+};
+
+static struct pci_controller gt64120_controller = {
+ .pci_ops = >64xxx_pci0_ops,
+ .io_resource = >64120_io_resource,
+ .mem_resource = >64120_mem_resource,
+};
+
+static int pcibios_init(void)
+{
+ resource_size_t start, end, map, start1, end1, map1, mask, res_end;
+
+ /*
+ * Due to a bug in the Galileo system controller, we need
+ * to setup the PCI BAR for the Galileo internal registers.
+ * This should be done in the bios/bootprom and will be
+ * fixed in a later revision of YAMON (the MIPS boards
+ * boot prom).
+ */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
+ (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
+ ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ /* Perform the write */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
+
+ /* Here is linux code. It assumes, that firmware
+ (pbl in case of barebox) made the work... */
+
+ /* Set up resource ranges from the controller's registers. */
+ start = GT_READ(GT_PCI0M0LD_OFS);
+ end = GT_READ(GT_PCI0M0HD_OFS);
+ map = GT_READ(GT_PCI0M0REMAP_OFS);
+ end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
+ start1 = GT_READ(GT_PCI0M1LD_OFS);
+ end1 = GT_READ(GT_PCI0M1HD_OFS);
+ map1 = GT_READ(GT_PCI0M1REMAP_OFS);
+ end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
+
+ mask = ~(start ^ end);
+
+ /* We don't support remapping with a discontiguous mask. */
+ BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
+ mask != ~((mask & -mask) - 1));
+ gt64120_mem_resource.start = start;
+ gt64120_mem_resource.end = end;
+ gt64120_controller.mem_offset = (start & mask) - (map & mask);
+ /* Addresses are 36-bit, so do shifts in the destinations. */
+ gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
+ gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
+ gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
+ gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
+
+ start = GT_READ(GT_PCI0IOLD_OFS);
+ end = GT_READ(GT_PCI0IOHD_OFS);
+ map = GT_READ(GT_PCI0IOREMAP_OFS);
+ end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
+ mask = ~(start ^ end);
+
+ /* We don't support remapping with a discontiguous mask. */
+ BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
+ mask != ~((mask & -mask) - 1));
+ gt64120_io_resource.start = map & mask;
+ res_end = (map & mask) | ~mask;
+ gt64120_controller.io_offset = 0;
+ /* Addresses are 36-bit, so do shifts in the destinations. */
+ gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
+ gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
+ gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+ GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+ GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+
+ /* Fix up PCI I/O mapping if necessary (for Atlas). */
+ start = GT_READ(GT_PCI0IOLD_OFS);
+ map = GT_READ(GT_PCI0IOREMAP_OFS);
+ if ((start & map) != 0) {
+ map &= ~start;
+ GT_WRITE(GT_PCI0IOREMAP_OFS, map);
+ }
+
+ register_pci_controller(>64120_controller);
+
+ return 0;
+}
+postcore_initcall(pcibios_init);
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC v4 6/6] MIPS: qemu-malta_defconfig: enable PCI & network stuff
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
` (4 preceding siblings ...)
2014-06-30 19:59 ` [RFC v4 5/6] MIPS: add PCI support for GT64120-based Malta board Antony Pavlov
@ 2014-06-30 19:59 ` Antony Pavlov
2014-07-02 6:05 ` [RFC v4 0/6] barebox PCI support Sascha Hauer
6 siblings, 0 replies; 10+ messages in thread
From: Antony Pavlov @ 2014-06-30 19:59 UTC (permalink / raw)
To: barebox
qemu usage:
# ifconfig br0:1 172.20.0.1
# qemu-system-mips -nodefaults -nographic -M malta -m 256 \
-serial stdio -monitor null \
-bios ./barebox-flash-image \
-net nic,vlan=0,model=rtl8139 \
-net tap,vlan=0,script=net_br0.sh
...
barebox:/ eth0.ipaddr=172.20.0.2
barebox:/ eth0.serverip=172.20.0.1
barebox:/ ping 172.20.0.1
phy0: Link is up - 100/Full
host 172.20.0.1 is alive
barebox:/
Sample net_br0.sh (for connecting to br0 interface, so you can
connect barebox to your real network):
#!/bin/sh
brctl addif br0 $1
ifconfig $1 up
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
arch/mips/configs/qemu-malta_defconfig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig
index 78f175d..6ee302d 100644
--- a/arch/mips/configs/qemu-malta_defconfig
+++ b/arch/mips/configs/qemu-malta_defconfig
@@ -32,6 +32,7 @@ CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_GETOPT=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
CONFIG_CMD_PING=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_ECHO_E=y
@@ -56,6 +57,7 @@ CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_DRIVER_NET_RTL8139=y
# CONFIG_SPI is not set
CONFIG_I2C=y
CONFIG_I2C_GPIO=y
@@ -66,6 +68,8 @@ CONFIG_DRIVER_CFI=y
# CONFIG_DRIVER_CFI_BANK_WIDTH_2 is not set
CONFIG_CFI_BUFFER_WRITE=y
CONFIG_GPIO_MALTA_FPGA_I2C=y
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
CONFIG_FS_CRAMFS=y
CONFIG_FS_TFTP=y
CONFIG_FS_FAT=y
--
1.9.2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC v4 0/6] barebox PCI support
2014-06-30 19:59 [RFC v4 0/6] barebox PCI support Antony Pavlov
` (5 preceding siblings ...)
2014-06-30 19:59 ` [RFC v4 6/6] MIPS: qemu-malta_defconfig: enable PCI & network stuff Antony Pavlov
@ 2014-07-02 6:05 ` Sascha Hauer
6 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2014-07-02 6:05 UTC (permalink / raw)
To: Antony Pavlov; +Cc: barebox
Hi Antony,
I have some minor stuff to fix, but otherwise it looks good and Lukas
also indicated he is fine with this series. So it's time to remove the
RFC tag and to apply this series.
Sascha
On Mon, Jun 30, 2014 at 11:59:43PM +0400, Antony Pavlov wrote:
> This patchseries introduce simple PCI bus support for barebox.
>
> Changes since RFC v3:
>
> * rebase over latest 'next';
> * use list for pci_root_buses;
> * move common PCI Kconfig stuff from arch/mips to drivers/pci;
> * make pci_*_write_config_* PCIe-friendly (use 'int' type for
> config register address);
> * drop some unused stuff;
> * change lspci "no pci" error message to "No PCI bus detected";
> * rtl8139: use dma_alloc_coherent();
> * rtl8139: use pci_set_master() & pci_clear_master().
>
> TODOs for RFC v3:
>
> * no PCI bridges support;
> * introduce pci_resource_start();
> * introduce pci_iomap();
> * clean '#if 0'.
>
> This patchseries can be found on github:
>
> https://github.com/frantony/barebox/tree/pci.20140630
>
> Antony Pavlov (6):
> MIPS: add dma_alloc_coherent()
> PCI: initial commit
> commands: add 'lspci' command
> net: add RealTek RTL-8139 PCI Ethernet driver
> MIPS: add PCI support for GT64120-based Malta board
> MIPS: qemu-malta_defconfig: enable PCI & network stuff
>
> arch/mips/Kconfig | 1 +
> arch/mips/configs/qemu-malta_defconfig | 4 +
> arch/mips/include/asm/dma-mapping.h | 25 +
> arch/mips/include/asm/gt64120.h | 53 ++
> arch/mips/mach-malta/Makefile | 1 +
> arch/mips/mach-malta/include/mach/mach-gt64120.h | 2 +
> arch/mips/mach-malta/pci.c | 236 +++++++++
> commands/Kconfig | 8 +
> commands/Makefile | 1 +
> commands/lspci.c | 52 ++
> drivers/Kconfig | 1 +
> drivers/Makefile | 1 +
> drivers/net/Kconfig | 8 +
> drivers/net/Makefile | 1 +
> drivers/net/rtl8139.c | 616 +++++++++++++++++++++++
> drivers/pci/Kconfig | 29 ++
> drivers/pci/Makefile | 8 +
> drivers/pci/bus.c | 110 ++++
> drivers/pci/pci.c | 285 +++++++++++
> include/linux/mod_devicetable.h | 20 +
> include/linux/pci.h | 292 +++++++++++
> include/linux/pci_ids.h | 141 ++++++
> include/linux/pci_regs.h | 110 ++++
> 23 files changed, 2005 insertions(+)
> create mode 100644 arch/mips/include/asm/dma-mapping.h
> create mode 100644 arch/mips/mach-malta/pci.c
> create mode 100644 commands/lspci.c
> create mode 100644 drivers/net/rtl8139.c
> create mode 100644 drivers/pci/Kconfig
> create mode 100644 drivers/pci/Makefile
> create mode 100644 drivers/pci/bus.c
> create mode 100644 drivers/pci/pci.c
> create mode 100644 include/linux/mod_devicetable.h
> create mode 100644 include/linux/pci.h
> create mode 100644 include/linux/pci_ids.h
> create mode 100644 include/linux/pci_regs.h
>
> --
> 1.9.2
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 10+ messages in thread