Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Sonics Silicon Backplane
0003  * Embedded systems support code
0004  *
0005  * Copyright 2005-2008, Broadcom Corporation
0006  * Copyright 2006-2008, Michael Buesch <m@bues.ch>
0007  * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
0008  *
0009  * Licensed under the GNU/GPL. See COPYING for details.
0010  */
0011 
0012 #include "ssb_private.h"
0013 
0014 #include <linux/export.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/ssb/ssb.h>
0017 #include <linux/ssb/ssb_embedded.h>
0018 #include <linux/ssb/ssb_driver_pci.h>
0019 #include <linux/ssb/ssb_driver_gige.h>
0020 #include <linux/pci.h>
0021 
0022 
0023 int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
0024 {
0025     if (ssb_chipco_available(&bus->chipco)) {
0026         ssb_chipco_watchdog_timer_set(&bus->chipco, ticks);
0027         return 0;
0028     }
0029     if (ssb_extif_available(&bus->extif)) {
0030         ssb_extif_watchdog_timer_set(&bus->extif, ticks);
0031         return 0;
0032     }
0033     return -ENODEV;
0034 }
0035 EXPORT_SYMBOL(ssb_watchdog_timer_set);
0036 
0037 int ssb_watchdog_register(struct ssb_bus *bus)
0038 {
0039     struct bcm47xx_wdt wdt = {};
0040     struct platform_device *pdev;
0041 
0042     if (ssb_chipco_available(&bus->chipco)) {
0043         wdt.driver_data = &bus->chipco;
0044         wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
0045         wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
0046         wdt.max_timer_ms = bus->chipco.max_timer_ms;
0047     } else if (ssb_extif_available(&bus->extif)) {
0048         wdt.driver_data = &bus->extif;
0049         wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
0050         wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
0051         wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
0052     } else {
0053         return -ENODEV;
0054     }
0055 
0056     pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
0057                          bus->busnumber, &wdt,
0058                          sizeof(wdt));
0059     if (IS_ERR(pdev)) {
0060         pr_debug("can not register watchdog device, err: %li\n",
0061              PTR_ERR(pdev));
0062         return PTR_ERR(pdev);
0063     }
0064 
0065     bus->watchdog = pdev;
0066     return 0;
0067 }
0068 
0069 u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
0070 {
0071     unsigned long flags;
0072     u32 res = 0;
0073 
0074     spin_lock_irqsave(&bus->gpio_lock, flags);
0075     if (ssb_chipco_available(&bus->chipco))
0076         res = ssb_chipco_gpio_in(&bus->chipco, mask);
0077     else if (ssb_extif_available(&bus->extif))
0078         res = ssb_extif_gpio_in(&bus->extif, mask);
0079     else
0080         WARN_ON(1);
0081     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0082 
0083     return res;
0084 }
0085 EXPORT_SYMBOL(ssb_gpio_in);
0086 
0087 u32 ssb_gpio_out(struct ssb_bus *bus, u32 mask, u32 value)
0088 {
0089     unsigned long flags;
0090     u32 res = 0;
0091 
0092     spin_lock_irqsave(&bus->gpio_lock, flags);
0093     if (ssb_chipco_available(&bus->chipco))
0094         res = ssb_chipco_gpio_out(&bus->chipco, mask, value);
0095     else if (ssb_extif_available(&bus->extif))
0096         res = ssb_extif_gpio_out(&bus->extif, mask, value);
0097     else
0098         WARN_ON(1);
0099     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0100 
0101     return res;
0102 }
0103 EXPORT_SYMBOL(ssb_gpio_out);
0104 
0105 u32 ssb_gpio_outen(struct ssb_bus *bus, u32 mask, u32 value)
0106 {
0107     unsigned long flags;
0108     u32 res = 0;
0109 
0110     spin_lock_irqsave(&bus->gpio_lock, flags);
0111     if (ssb_chipco_available(&bus->chipco))
0112         res = ssb_chipco_gpio_outen(&bus->chipco, mask, value);
0113     else if (ssb_extif_available(&bus->extif))
0114         res = ssb_extif_gpio_outen(&bus->extif, mask, value);
0115     else
0116         WARN_ON(1);
0117     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0118 
0119     return res;
0120 }
0121 EXPORT_SYMBOL(ssb_gpio_outen);
0122 
0123 u32 ssb_gpio_control(struct ssb_bus *bus, u32 mask, u32 value)
0124 {
0125     unsigned long flags;
0126     u32 res = 0;
0127 
0128     spin_lock_irqsave(&bus->gpio_lock, flags);
0129     if (ssb_chipco_available(&bus->chipco))
0130         res = ssb_chipco_gpio_control(&bus->chipco, mask, value);
0131     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0132 
0133     return res;
0134 }
0135 EXPORT_SYMBOL(ssb_gpio_control);
0136 
0137 u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value)
0138 {
0139     unsigned long flags;
0140     u32 res = 0;
0141 
0142     spin_lock_irqsave(&bus->gpio_lock, flags);
0143     if (ssb_chipco_available(&bus->chipco))
0144         res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value);
0145     else if (ssb_extif_available(&bus->extif))
0146         res = ssb_extif_gpio_intmask(&bus->extif, mask, value);
0147     else
0148         WARN_ON(1);
0149     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0150 
0151     return res;
0152 }
0153 EXPORT_SYMBOL(ssb_gpio_intmask);
0154 
0155 u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
0156 {
0157     unsigned long flags;
0158     u32 res = 0;
0159 
0160     spin_lock_irqsave(&bus->gpio_lock, flags);
0161     if (ssb_chipco_available(&bus->chipco))
0162         res = ssb_chipco_gpio_polarity(&bus->chipco, mask, value);
0163     else if (ssb_extif_available(&bus->extif))
0164         res = ssb_extif_gpio_polarity(&bus->extif, mask, value);
0165     else
0166         WARN_ON(1);
0167     spin_unlock_irqrestore(&bus->gpio_lock, flags);
0168 
0169     return res;
0170 }
0171 EXPORT_SYMBOL(ssb_gpio_polarity);
0172 
0173 #ifdef CONFIG_SSB_DRIVER_GIGE
0174 static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
0175 {
0176     struct pci_dev *pdev = (struct pci_dev *)data;
0177     struct ssb_device *dev;
0178     unsigned int i;
0179     int res;
0180 
0181     for (i = 0; i < bus->nr_devices; i++) {
0182         dev = &(bus->devices[i]);
0183         if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
0184             continue;
0185         if (!dev->dev ||
0186             !dev->dev->driver ||
0187             !device_is_registered(dev->dev))
0188             continue;
0189         res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
0190         if (res >= 0)
0191             return res;
0192     }
0193 
0194     return -ENODEV;
0195 }
0196 #endif /* CONFIG_SSB_DRIVER_GIGE */
0197 
0198 int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
0199 {
0200     int err;
0201 
0202     err = ssb_pcicore_plat_dev_init(dev);
0203     if (!err)
0204         return 0;
0205 #ifdef CONFIG_SSB_DRIVER_GIGE
0206     err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
0207     if (err >= 0)
0208         return err;
0209 #endif
0210     /* This is not a PCI device on any SSB device. */
0211 
0212     return -ENODEV;
0213 }
0214 
0215 #ifdef CONFIG_SSB_DRIVER_GIGE
0216 static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
0217 {
0218     const struct pci_dev *pdev = (const struct pci_dev *)data;
0219     struct ssb_device *dev;
0220     unsigned int i;
0221     int res;
0222 
0223     for (i = 0; i < bus->nr_devices; i++) {
0224         dev = &(bus->devices[i]);
0225         if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
0226             continue;
0227         if (!dev->dev ||
0228             !dev->dev->driver ||
0229             !device_is_registered(dev->dev))
0230             continue;
0231         res = ssb_gige_map_irq(dev, pdev);
0232         if (res >= 0)
0233             return res;
0234     }
0235 
0236     return -ENODEV;
0237 }
0238 #endif /* CONFIG_SSB_DRIVER_GIGE */
0239 
0240 int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
0241 {
0242     int res;
0243 
0244     /* Check if this PCI device is a device on a SSB bus or device
0245      * and return the IRQ number for it. */
0246 
0247     res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
0248     if (res >= 0)
0249         return res;
0250 #ifdef CONFIG_SSB_DRIVER_GIGE
0251     res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
0252     if (res >= 0)
0253         return res;
0254 #endif
0255     /* This is not a PCI device on any SSB device. */
0256 
0257     return -ENODEV;
0258 }