diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-02-29 11:36:12 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 17:09:43 -0500 |
commit | aab547ce0d1493d400b6468c521a0137cd8c1edf (patch) | |
tree | 84625da40d905669a28a5770de111225667d5f27 /drivers/ssb/embedded.c | |
parent | 69d3b6f491545d326135a1def4e290cd577c9a36 (diff) |
ssb: Add Gigabit Ethernet driver
This adds the Gigabit Ethernet driver for the SSB
Gigabit Ethernet core. This driver actually is a frontend to
the Tigon3 driver. So the real work is done by tg3.
This device is used in the Linksys WRT350N.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb/embedded.c')
-rw-r--r-- | drivers/ssb/embedded.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index d3ade821555c..7dc3a6b41397 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c @@ -10,6 +10,9 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_embedded.h> +#include <linux/ssb/ssb_driver_pci.h> +#include <linux/ssb/ssb_driver_gige.h> +#include <linux/pci.h> #include "ssb_private.h" @@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value) return res; } EXPORT_SYMBOL(ssb_gpio_polarity); + +#ifdef CONFIG_SSB_DRIVER_GIGE +static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data) +{ + struct pci_dev *pdev = (struct pci_dev *)data; + struct ssb_device *dev; + unsigned int i; + int res; + + for (i = 0; i < bus->nr_devices; i++) { + dev = &(bus->devices[i]); + if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT) + continue; + if (!dev->dev || + !dev->dev->driver || + !device_is_registered(dev->dev)) + continue; + res = ssb_gige_pcibios_plat_dev_init(dev, pdev); + if (res >= 0) + return res; + } + + return -ENODEV; +} +#endif /* CONFIG_SSB_DRIVER_GIGE */ + +int ssb_pcibios_plat_dev_init(struct pci_dev *dev) +{ + int err; + + err = ssb_pcicore_plat_dev_init(dev); + if (!err) + return 0; +#ifdef CONFIG_SSB_DRIVER_GIGE + err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback); + if (err >= 0) + return err; +#endif + /* This is not a PCI device on any SSB device. */ + + return -ENODEV; +} + +#ifdef CONFIG_SSB_DRIVER_GIGE +static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data) +{ + const struct pci_dev *pdev = (const struct pci_dev *)data; + struct ssb_device *dev; + unsigned int i; + int res; + + for (i = 0; i < bus->nr_devices; i++) { + dev = &(bus->devices[i]); + if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT) + continue; + if (!dev->dev || + !dev->dev->driver || + !device_is_registered(dev->dev)) + continue; + res = ssb_gige_map_irq(dev, pdev); + if (res >= 0) + return res; + } + + return -ENODEV; +} +#endif /* CONFIG_SSB_DRIVER_GIGE */ + +int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int res; + + /* Check if this PCI device is a device on a SSB bus or device + * and return the IRQ number for it. */ + + res = ssb_pcicore_pcibios_map_irq(dev, slot, pin); + if (res >= 0) + return res; +#ifdef CONFIG_SSB_DRIVER_GIGE + res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback); + if (res >= 0) + return res; +#endif + /* This is not a PCI device on any SSB device. */ + + return -ENODEV; +} |