linux/drivers/ssb/embedded.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane
   3 * Embedded systems support code
   4 *
   5 * Copyright 2005-2008, Broadcom Corporation
   6 * Copyright 2006-2008, Michael Buesch <m@bues.ch>
   7 *
   8 * Licensed under the GNU/GPL. See COPYING for details.
   9 */
  10
  11#include <linux/export.h>
  12#include <linux/ssb/ssb.h>
  13#include <linux/ssb/ssb_embedded.h>
  14#include <linux/ssb/ssb_driver_pci.h>
  15#include <linux/ssb/ssb_driver_gige.h>
  16#include <linux/pci.h>
  17
  18#include "ssb_private.h"
  19
  20
  21int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
  22{
  23        if (ssb_chipco_available(&bus->chipco)) {
  24                ssb_chipco_watchdog_timer_set(&bus->chipco, ticks);
  25                return 0;
  26        }
  27        if (ssb_extif_available(&bus->extif)) {
  28                ssb_extif_watchdog_timer_set(&bus->extif, ticks);
  29                return 0;
  30        }
  31        return -ENODEV;
  32}
  33EXPORT_SYMBOL(ssb_watchdog_timer_set);
  34
  35u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
  36{
  37        unsigned long flags;
  38        u32 res = 0;
  39
  40        spin_lock_irqsave(&bus->gpio_lock, flags);
  41        if (ssb_chipco_available(&bus->chipco))
  42                res = ssb_chipco_gpio_in(&bus->chipco, mask);
  43        else if (ssb_extif_available(&bus->extif))
  44                res = ssb_extif_gpio_in(&bus->extif, mask);
  45        else
  46                SSB_WARN_ON(1);
  47        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  48
  49        return res;
  50}
  51EXPORT_SYMBOL(ssb_gpio_in);
  52
  53u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
  54{
  55        unsigned long flags;
  56        u32 res = 0;
  57
  58        spin_lock_irqsave(&bus->gpio_lock, flags);
  59        if (ssb_chipco_available(&bus->chipco))
  60                res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
  61        else if (ssb_extif_available(&bus->extif))
  62                res = ssb_extif_gpio_out(&bus->extif, mask, value);
  63        else
  64                SSB_WARN_ON(1);
  65        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  66
  67        return res;
  68}
  69EXPORT_SYMBOL(ssb_gpio_out);
  70
  71u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
  72{
  73        unsigned long flags;
  74        u32 res = 0;
  75
  76        spin_lock_irqsave(&bus->gpio_lock, flags);
  77        if (ssb_chipco_available(&bus->chipco))
  78                res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
  79        else if (ssb_extif_available(&bus->extif))
  80                res = ssb_extif_gpio_outen(&bus->extif, mask, value);
  81        else
  82                SSB_WARN_ON(1);
  83        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  84
  85        return res;
  86}
  87EXPORT_SYMBOL(ssb_gpio_outen);
  88
  89u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
  90{
  91        unsigned long flags;
  92        u32 res = 0;
  93
  94        spin_lock_irqsave(&bus->gpio_lock, flags);
  95        if (ssb_chipco_available(&bus->chipco))
  96                res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
  97        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  98
  99        return res;
 100}
 101EXPORT_SYMBOL(ssb_gpio_control);
 102
 103u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
 104{
 105        unsigned long flags;
 106        u32 res = 0;
 107
 108        spin_lock_irqsave(&bus->gpio_lock, flags);
 109        if (ssb_chipco_available(&bus->chipco))
 110                res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
 111        else if (ssb_extif_available(&bus->extif))
 112                res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
 113        else
 114                SSB_WARN_ON(1);
 115        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 116
 117        return res;
 118}
 119EXPORT_SYMBOL(ssb_gpio_intmask);
 120
 121u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
 122{
 123        unsigned long flags;
 124        u32 res = 0;
 125
 126        spin_lock_irqsave(&bus->gpio_lock, flags);
 127        if (ssb_chipco_available(&bus->chipco))
 128                res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
 129        else if (ssb_extif_available(&bus->extif))
 130                res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
 131        else
 132                SSB_WARN_ON(1);
 133        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 134
 135        return res;
 136}
 137EXPORT_SYMBOL(ssb_gpio_polarity);
 138
 139#ifdef CONFIG_SSB_DRIVER_GIGE
 140static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
 141{
 142        struct pci_dev *pdev = (struct pci_dev *)data;
 143        struct ssb_device *dev;
 144        unsigned int i;
 145        int res;
 146
 147        for (i = 0; i < bus->nr_devices; i++) {
 148                dev = &(bus->devices[i]);
 149                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 150                        continue;
 151                if (!dev->dev ||
 152                    !dev->dev->driver ||
 153                    !device_is_registered(dev->dev))
 154                        continue;
 155                res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
 156                if (res >= 0)
 157                        return res;
 158        }
 159
 160        return -ENODEV;
 161}
 162#endif /* CONFIG_SSB_DRIVER_GIGE */
 163
 164int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
 165{
 166        int err;
 167
 168        err = ssb_pcicore_plat_dev_init(dev);
 169        if (!err)
 170                return 0;
 171#ifdef CONFIG_SSB_DRIVER_GIGE
 172        err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
 173        if (err >= 0)
 174                return err;
 175#endif
 176        /* This is not a PCI device on any SSB device. */
 177
 178        return -ENODEV;
 179}
 180
 181#ifdef CONFIG_SSB_DRIVER_GIGE
 182static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
 183{
 184        const struct pci_dev *pdev = (const struct pci_dev *)data;
 185        struct ssb_device *dev;
 186        unsigned int i;
 187        int res;
 188
 189        for (i = 0; i < bus->nr_devices; i++) {
 190                dev = &(bus->devices[i]);
 191                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 192                        continue;
 193                if (!dev->dev ||
 194                    !dev->dev->driver ||
 195                    !device_is_registered(dev->dev))
 196                        continue;
 197                res = ssb_gige_map_irq(dev, pdev);
 198                if (res >= 0)
 199                        return res;
 200        }
 201
 202        return -ENODEV;
 203}
 204#endif /* CONFIG_SSB_DRIVER_GIGE */
 205
 206int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 207{
 208        int res;
 209
 210        /* Check if this PCI device is a device on a SSB bus or device
 211         * and return the IRQ number for it. */
 212
 213        res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
 214        if (res >= 0)
 215                return res;
 216#ifdef CONFIG_SSB_DRIVER_GIGE
 217        res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
 218        if (res >= 0)
 219                return res;
 220#endif
 221        /* This is not a PCI device on any SSB device. */
 222
 223        return -ENODEV;
 224}
 225