cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

embedded.c (6356B)


      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 "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	else
     80		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		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		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		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		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}