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_dbg("can not register watchdog device, err: %li\n",
  61                        PTR_ERR(pdev));
  62                return PTR_ERR(pdev);
  63        }
  64
  65        bus->watchdog = pdev;
  66        return 0;
  67}
  68
  69u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
  70{
  71        unsigned long flags;
  72        u32 res = 0;
  73
  74        spin_lock_irqsave(&bus->gpio_lock, flags);
  75        if (ssb_chipco_available(&bus->chipco))
  76                res = ssb_chipco_gpio_in(&bus->chipco, mask);
  77        else if (ssb_extif_available(&bus->extif))
  78                res = ssb_extif_gpio_in(&bus->extif, mask);
  79        else
  80                SSB_WARN_ON(1);
  81        spin_unlock_irqrestore(&bus->gpio_lock, flags);
  82
  83        return res;
  84}
  85EXPORT_SYMBOL(ssb_gpio_in);
  86
  87u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
  88{
  89        unsigned long flags;
  90        u32 res = 0;
  91
  92        spin_lock_irqsave(&bus->gpio_lock, flags);
  93        if (ssb_chipco_available(&bus->chipco))
  94                res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
  95        else if (ssb_extif_available(&bus->extif))
  96                res = ssb_extif_gpio_out(&bus->extif, mask, value);
  97        else
  98                SSB_WARN_ON(1);
  99        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 100
 101        return res;
 102}
 103EXPORT_SYMBOL(ssb_gpio_out);
 104
 105u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
 106{
 107        unsigned long flags;
 108        u32 res = 0;
 109
 110        spin_lock_irqsave(&bus->gpio_lock, flags);
 111        if (ssb_chipco_available(&bus->chipco))
 112                res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
 113        else if (ssb_extif_available(&bus->extif))
 114                res = ssb_extif_gpio_outen(&bus->extif, mask, value);
 115        else
 116                SSB_WARN_ON(1);
 117        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 118
 119        return res;
 120}
 121EXPORT_SYMBOL(ssb_gpio_outen);
 122
 123u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
 124{
 125        unsigned long flags;
 126        u32 res = 0;
 127
 128        spin_lock_irqsave(&bus->gpio_lock, flags);
 129        if (ssb_chipco_available(&bus->chipco))
 130                res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
 131        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 132
 133        return res;
 134}
 135EXPORT_SYMBOL(ssb_gpio_control);
 136
 137u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
 138{
 139        unsigned long flags;
 140        u32 res = 0;
 141
 142        spin_lock_irqsave(&bus->gpio_lock, flags);
 143        if (ssb_chipco_available(&bus->chipco))
 144                res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
 145        else if (ssb_extif_available(&bus->extif))
 146                res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
 147        else
 148                SSB_WARN_ON(1);
 149        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 150
 151        return res;
 152}
 153EXPORT_SYMBOL(ssb_gpio_intmask);
 154
 155u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
 156{
 157        unsigned long flags;
 158        u32 res = 0;
 159
 160        spin_lock_irqsave(&bus->gpio_lock, flags);
 161        if (ssb_chipco_available(&bus->chipco))
 162                res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
 163        else if (ssb_extif_available(&bus->extif))
 164                res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
 165        else
 166                SSB_WARN_ON(1);
 167        spin_unlock_irqrestore(&bus->gpio_lock, flags);
 168
 169        return res;
 170}
 171EXPORT_SYMBOL(ssb_gpio_polarity);
 172
 173#ifdef CONFIG_SSB_DRIVER_GIGE
 174static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
 175{
 176        struct pci_dev *pdev = (struct pci_dev *)data;
 177        struct ssb_device *dev;
 178        unsigned int i;
 179        int res;
 180
 181        for (i = 0; i < bus->nr_devices; i++) {
 182                dev = &(bus->devices[i]);
 183                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 184                        continue;
 185                if (!dev->dev ||
 186                    !dev->dev->driver ||
 187                    !device_is_registered(dev->dev))
 188                        continue;
 189                res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
 190                if (res >= 0)
 191                        return res;
 192        }
 193
 194        return -ENODEV;
 195}
 196#endif /* CONFIG_SSB_DRIVER_GIGE */
 197
 198int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
 199{
 200        int err;
 201
 202        err = ssb_pcicore_plat_dev_init(dev);
 203        if (!err)
 204                return 0;
 205#ifdef CONFIG_SSB_DRIVER_GIGE
 206        err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
 207        if (err >= 0)
 208                return err;
 209#endif
 210        /* This is not a PCI device on any SSB device. */
 211
 212        return -ENODEV;
 213}
 214
 215#ifdef CONFIG_SSB_DRIVER_GIGE
 216static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
 217{
 218        const struct pci_dev *pdev = (const struct pci_dev *)data;
 219        struct ssb_device *dev;
 220        unsigned int i;
 221        int res;
 222
 223        for (i = 0; i < bus->nr_devices; i++) {
 224                dev = &(bus->devices[i]);
 225                if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
 226                        continue;
 227                if (!dev->dev ||
 228                    !dev->dev->driver ||
 229                    !device_is_registered(dev->dev))
 230                        continue;
 231                res = ssb_gige_map_irq(dev, pdev);
 232                if (res >= 0)
 233                        return res;
 234        }
 235
 236        return -ENODEV;
 237}
 238#endif /* CONFIG_SSB_DRIVER_GIGE */
 239
 240int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 241{
 242        int res;
 243
 244        /* Check if this PCI device is a device on a SSB bus or device
 245         * and return the IRQ number for it. */
 246
 247        res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
 248        if (res >= 0)
 249                return res;
 250#ifdef CONFIG_SSB_DRIVER_GIGE
 251        res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
 252        if (res >= 0)
 253                return res;
 254#endif
 255        /* This is not a PCI device on any SSB device. */
 256
 257        return -ENODEV;
 258}
 259
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.