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 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
   8 *
   9 * Licensed under the GNU/GPL. See COPYING for details.
  10 */
  11
  12#include <linux/export.h>
  13#include <linux/platform_device.h>
  14#include <linux/ssb/ssb.h>
  15#include <linux/ssb/ssb_embedded.h>
  16#include <linux/ssb/ssb_driver_pci.h>
  17#include <linux/ssb/ssb_driver_gige.h>
  18#include <linux/pci.h>
  19
  20#include "ssb_private.h"
  21
  22
  23int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
  24{
  25        if (ssb_chipco_available(&bus->chipco)) {
  26                ssb_chipco_watchdog_timer_set(&bus->chipco, ticks);
  27                return 0;
  28        }
  29        if (ssb_extif_available(&bus->extif)) {
  30                ssb_extif_watchdog_timer_set(&bus->extif, ticks);
  31                return 0;
  32        }
  33        return -ENODEV;
  34}
  35EXPORT_SYMBOL(ssb_watchdog_timer_set);
  36
  37int ssb_watchdog_register(struct ssb_bus *bus)
  38{
  39        struct bcm47xx_wdt wdt = {};
  40        struct platform_device *pdev;
  41
  42        if (ssb_chipco_available(&bus->chipco)) {
  43                wdt.driver_data = &bus->chipco;
  44                wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
  45                wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
  46                wdt.max_timer_ms = bus->chipco.max_timer_ms;
  47        } else if (ssb_extif_available(&bus->extif)) {
  48                wdt.driver_data = &bus->extif;
  49                wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
  50                wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
  51                wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
  52        } else {
  53                return -ENODEV;
  54        }
  55
  56        pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
  57                                             bus->busnumber, &wdt,
  58                                             sizeof(wdt));
  59        if (IS_ERR(pdev)) {
  60                ssb_dprintk(KERN_INFO PFX
  61                            "can not register watchdog device, err: %li\n",
  62                            PTR_ERR(pdev));
  63                return PTR_ERR(pdev);
  64        }
  65
  66        bus->watchdog = pdev;
  67        return 0;
  68}
  69
  70u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
  71{
  72        unsigned long flags;
  73        u32 res = 0;
  74
  75        spin_lock_irqsave(&bus->gpio_lock, flags);
  76        if (ssb_chipco_available(&bus->chipco))
  77                res = ssb_chipco_gpio_in(&bus->chipco, mask);
  78        else if (ssb_extif_available(&bus->extif))
  79                res = ssb_extif_gpio_in(&bus->extif, mask);
  80        else
  81                SSB_WARN_ON(1);
  82        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  83
  84        return res;
  85}
  86EXPORT_SYMBOL(ssb_gpio_in);
  87
  88u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
  89{
  90        unsigned long flags;
  91        u32 res = 0;
  92
  93        spin_lock_irqsave(&bus->gpio_lock, flags);
  94        if (ssb_chipco_available(&bus->chipco))
  95                res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
  96        else if (ssb_extif_available(&bus->extif))
  97                res = ssb_extif_gpio_out(&bus->extif, mask, value);
  98        else
  99                SSB_WARN_ON(1);
 100        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 101
 102        return res;
 103}
 104EXPORT_SYMBOL(ssb_gpio_out);
 105
 106u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
 107{
 108        unsigned long flags;
 109        u32 res = 0;
 110
 111        spin_lock_irqsave(&bus->gpio_lock, flags);
 112        if (ssb_chipco_available(&bus->chipco))
 113                res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
 114        else if (ssb_extif_available(&bus->extif))
 115                res = ssb_extif_gpio_outen(&bus->extif, mask, value);
 116        else
 117                SSB_WARN_ON(1);
 118        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 119
 120        return res;
 121}
 122EXPORT_SYMBOL(ssb_gpio_outen);
 123
 124u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
 125{
 126        unsigned long flags;
 127        u32 res = 0;
 128
 129        spin_lock_irqsave(&bus->gpio_lock, flags);
 130        if (ssb_chipco_available(&bus->chipco))
 131                res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
 132        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 133
 134        return res;
 135}
 136EXPORT_SYMBOL(ssb_gpio_control);
 137
 138u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
 139{
 140        unsigned long flags;
 141        u32 res = 0;
 142
 143        spin_lock_irqsave(&bus->gpio_lock, flags);
 144        if (ssb_chipco_available(&bus->chipco))
 145                res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
 146        else if (ssb_extif_available(&bus->extif))
 147                res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
 148        else
 149                SSB_WARN_ON(1);
 150        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 151
 152        return res;
 153}
 154EXPORT_SYMBOL(ssb_gpio_intmask);
 155
 156u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
 157{
 158        unsigned long flags;
 159        u32 res = 0;
 160
 161        spin_lock_irqsave(&bus->gpio_lock, flags);
 162        if (ssb_chipco_available(&bus->chipco))
 163                res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
 164        else if (ssb_extif_available(&bus->extif))
 165                res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
 166        else
 167                SSB_WARN_ON(1);
 168        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 169
 170        return res;
 171}
 172EXPORT_SYMBOL(ssb_gpio_polarity);
 173
 174#ifdef CONFIG_SSB_DRIVER_GIGE
 175static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
 176{
 177        struct pci_dev *pdev = (struct pci_dev *)data;
 178        struct ssb_device *dev;
 179        unsigned int i;
 180        int res;
 181
 182        for (i = 0; i < bus->nr_devices; i++) {
 183                dev = &(bus->devices[i]);
 184                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 185                        continue;
 186                if (!dev->dev ||
 187                    !dev->dev->driver ||
 188                    !device_is_registered(dev->dev))
 189                        continue;
 190                res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
 191                if (res >= 0)
 192                        return res;
 193        }
 194
 195        return -ENODEV;
 196}
 197#endif /* CONFIG_SSB_DRIVER_GIGE */
 198
 199int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
 200{
 201        int err;
 202
 203        err = ssb_pcicore_plat_dev_init(dev);
 204        if (!err)
 205                return 0;
 206#ifdef CONFIG_SSB_DRIVER_GIGE
 207        err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
 208        if (err >= 0)
 209                return err;
 210#endif
 211        /* This is not a PCI device on any SSB device. */
 212
 213        return -ENODEV;
 214}
 215
 216#ifdef CONFIG_SSB_DRIVER_GIGE
 217static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
 218{
 219        const struct pci_dev *pdev = (const struct pci_dev *)data;
 220        struct ssb_device *dev;
 221        unsigned int i;
 222        int res;
 223
 224        for (i = 0; i < bus->nr_devices; i++) {
 225                dev = &(bus->devices[i]);
 226                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 227                        continue;
 228                if (!dev->dev ||
 229                    !dev->dev->driver ||
 230                    !device_is_registered(dev->dev))
 231                        continue;
 232                res = ssb_gige_map_irq(dev, pdev);
 233                if (res >= 0)
 234                        return res;
 235        }
 236
 237        return -ENODEV;
 238}
 239#endif /* CONFIG_SSB_DRIVER_GIGE */
 240
 241int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 242{
 243        int res;
 244
 245        /* Check if this PCI device is a device on a SSB bus or device
 246         * and return the IRQ number for it. */
 247
 248        res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
 249        if (res >= 0)
 250                return res;
 251#ifdef CONFIG_SSB_DRIVER_GIGE
 252        res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
 253        if (res >= 0)
 254                return res;
 255#endif
 256        /* This is not a PCI device on any SSB device. */
 257
 258        return -ENODEV;
 259}
 260
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.