diff options
Diffstat (limited to 'libdde_linux26/lib/src/arch/l4/pci.c')
-rw-r--r-- | libdde_linux26/lib/src/arch/l4/pci.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/libdde_linux26/lib/src/arch/l4/pci.c b/libdde_linux26/lib/src/arch/l4/pci.c new file mode 100644 index 00000000..c393fd3a --- /dev/null +++ b/libdde_linux26/lib/src/arch/l4/pci.c @@ -0,0 +1,206 @@ +#include "local.h" + +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/list.h> +#include <linux/init.h> + +/* will include $(CONTRIB)/drivers/pci/pci.h */ +#include "pci.h" + +DECLARE_INITVAR(dde26_pci); + +/** PCI device descriptor */ +typedef struct l4dde_pci_dev { + struct list_head next; /**< chain info */ + struct ddekit_pci_dev *ddekit_dev; /**< corresponding DDEKit descriptor */ + struct pci_dev *linux_dev; /**< Linux descriptor */ +} l4dde_pci_dev_t; + + +/******************************************************************************************* + ** PCI data ** + *******************************************************************************************/ +/** List of Linux-DDEKit PCIDev mappings */ +static LIST_HEAD(pcidev_mappings); + +/** PCI bus */ +static struct pci_bus *pci_bus = NULL; +static struct pci_bus *pci_bus1 = NULL; + +static int l4dde26_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); +static int l4dde26_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); + +/** PCI operations for our virtual PCI bus */ +static struct pci_ops dde_pcibus_ops = { + .read = l4dde26_pci_read, + .write = l4dde26_pci_write, +}; + + +/******************************************************************************************* + ** Read/write PCI config space. This is simply mapped to the DDEKit functions. ** + *******************************************************************************************/ +static int l4dde26_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) +{ + return ddekit_pci_read(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val); +} + +static int l4dde26_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) +{ + return ddekit_pci_write(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val); +} + +int pci_irq_enable(struct pci_dev *dev) +{ + int irq = dev->irq; + int pin = 0; + int ret; + + DEBUG_MSG("dev %p", dev); + if (!dev) + return -EINVAL; + + pin = (int)dev->pin; + DEBUG_MSG("irq %d, pin %d", dev->irq, dev->pin); + if (!pin) { + dev_warn(&dev->dev, + "No interrupt pin configured for device %s\n", + pci_name(dev)); + return 0; + } + pin--; + + ret = ddekit_pci_irq_enable(dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), pin, &irq); + if (ret) { + dev_warn(&dev->dev, "Interrupt enable failed for device %s (%d)\n", + pci_name(dev), ret); + return -1; + } + + dev_info(&dev->dev, "PCI INT %c -> GSI %d -> IRQ %d\n", + 'A' + pin, irq, dev->irq); + + dev->irq = irq; + return 0; +} + +int __pci_enable_device(struct pci_dev *dev) +{ + WARN_UNIMPL; + return 0; +} + + +/** + * pci_enable_device - Initialize device before it's used by a driver. + * + * Initialize device before it's used by a driver. Ask low-level code + * to enable I/O and memory. Wake up the device if it was suspended. + * Beware, this function can fail. + * + * \param dev PCI device to be initialized + * + */ +int +pci_enable_device(struct pci_dev *dev) +{ + CHECK_INITVAR(dde26_pci); +// WARN_UNIMPL; + return pci_irq_enable(dev); +} + + +/** + * pci_disable_device - Disable PCI device after use + * + * Signal to the system that the PCI device is not in use by the system + * anymore. This only involves disabling PCI bus-mastering, if active. + * + * \param dev PCI device to be disabled + */ +void pci_disable_device(struct pci_dev *dev) +{ + CHECK_INITVAR(dde26_pci); + WARN_UNIMPL; +} + + +void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) +{ + //WARN_UNIMPL; +} + +static unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +int pci_create_sysfs_dev_files(struct pci_dev *pdev) +{ + return 0; +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 1; +} + +void +pcibios_align_resource(void *data, struct resource *res, + resource_size_t size, resource_size_t align) +{ + WARN_UNIMPL; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ +#if 0 + int err; + + if ((err = pcibios_enable_resources(dev, mask)) < 0) + return err; + + return pcibios_enable_irq(dev); +#endif + WARN_UNIMPL; + return -1; +} + +/******************************************************************************************* + ** Initialization function ** + *******************************************************************************************/ + +/** Initialize DDELinux PCI subsystem. + */ +void __init l4dde26_init_pci(void) +{ + ddekit_pci_init(); + + // TODO it's a temporary solution to handle 2 buses. + // we need to find a way to detect buses. + pci_bus = pci_create_bus(NULL, 0, &dde_pcibus_ops, NULL); + Assert(pci_bus); + + pci_do_scan_bus(pci_bus); + + pci_bus1 = pci_create_bus(NULL, 2, &dde_pcibus_ops, NULL); + Assert(pci_bus1); + + pci_do_scan_bus(pci_bus1); + + INITIALIZE_INITVAR(dde26_pci); +} + +arch_initcall(l4dde26_init_pci); |