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