brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 8254ed2 Raw
259 lines · c
1/*2 * Sonics Silicon Backplane3 * Embedded systems support code4 *5 * Copyright 2005-2008, Broadcom Corporation6 * 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 "ssb_private.h"13 14#include <linux/export.h>15#include <linux/platform_device.h>16#include <linux/ssb/ssb.h>17#include <linux/ssb/ssb_embedded.h>18#include <linux/ssb/ssb_driver_pci.h>19#include <linux/ssb/ssb_driver_gige.h>20#include <linux/pci.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		pr_debug("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	else80		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	else98		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	else116		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	else148		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	else166		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_GIGE174static 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_GIGE206	err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);207	if (err >= 0)208		return err;209#endif210	/* This is not a PCI device on any SSB device. */211 212	return -ENODEV;213}214 215#ifdef CONFIG_SSB_DRIVER_GIGE216static 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 device245	 * 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_GIGE251	res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);252	if (res >= 0)253		return res;254#endif255	/* This is not a PCI device on any SSB device. */256 257	return -ENODEV;258}259