aboutsummaryrefslogtreecommitdiff
path: root/include/linux/ssb
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/ssb')
-rw-r--r--include/linux/ssb/ssb.h50
-rw-r--r--include/linux/ssb/ssb_driver_chipcommon.h7
-rw-r--r--include/linux/ssb/ssb_driver_gige.h174
-rw-r--r--include/linux/ssb/ssb_driver_pci.h19
4 files changed, 243 insertions, 7 deletions
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index db53defde5e..50dfd0dc409 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -72,10 +72,18 @@ struct ssb_device;
/* Lowlevel read/write operations on the device MMIO.
* Internal, don't use that outside of ssb. */
struct ssb_bus_ops {
+ u8 (*read8)(struct ssb_device *dev, u16 offset);
u16 (*read16)(struct ssb_device *dev, u16 offset);
u32 (*read32)(struct ssb_device *dev, u16 offset);
+ void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
+#ifdef CONFIG_SSB_BLOCKIO
+ void (*block_read)(struct ssb_device *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+ void (*block_write)(struct ssb_device *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width);
+#endif
};
@@ -247,9 +255,9 @@ struct ssb_bus {
/* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
struct pcmcia_device *host_pcmcia;
-#ifdef CONFIG_SSB_PCIHOST
+#ifdef CONFIG_SSB_SPROM
/* Mutex to protect the SPROM writing. */
- struct mutex pci_sprom_mutex;
+ struct mutex sprom_mutex;
#endif
/* ID information about the Chip. */
@@ -262,9 +270,6 @@ struct ssb_bus {
struct ssb_device devices[SSB_MAX_NR_CORES];
u8 nr_devices;
- /* Reference count. Number of suspended devices. */
- u8 suspend_cnt;
-
/* Software ID number for this bus. */
unsigned int busnumber;
@@ -336,6 +341,13 @@ extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
extern void ssb_bus_unregister(struct ssb_bus *bus);
+/* Suspend a SSB bus.
+ * Call this from the parent bus suspend routine. */
+extern int ssb_bus_suspend(struct ssb_bus *bus);
+/* Resume a SSB bus.
+ * Call this from the parent bus resume routine. */
+extern int ssb_bus_resume(struct ssb_bus *bus);
+
extern u32 ssb_clockspeed(struct ssb_bus *bus);
/* Is the device enabled in hardware? */
@@ -348,6 +360,10 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
/* Device MMIO register read/write functions. */
+static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
+{
+ return dev->ops->read8(dev, offset);
+}
static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
{
return dev->ops->read16(dev, offset);
@@ -356,6 +372,10 @@ static inline u32 ssb_read32(struct ssb_device *dev, u16 offset)
{
return dev->ops->read32(dev, offset);
}
+static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
+{
+ dev->ops->write8(dev, offset, value);
+}
static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
{
dev->ops->write16(dev, offset, value);
@@ -364,6 +384,19 @@ static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
{
dev->ops->write32(dev, offset, value);
}
+#ifdef CONFIG_SSB_BLOCKIO
+static inline void ssb_block_read(struct ssb_device *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ dev->ops->block_read(dev, buffer, count, offset, reg_width);
+}
+
+static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ dev->ops->block_write(dev, buffer, count, offset, reg_width);
+}
+#endif /* CONFIG_SSB_BLOCKIO */
/* Translation (routing) bits that need to be ORed to DMA
@@ -416,5 +449,12 @@ extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
extern u32 ssb_admatch_base(u32 adm);
extern u32 ssb_admatch_size(u32 adm);
+/* PCI device mapping and fixup routines.
+ * Called from the architecture pcibios init code.
+ * These are only available on SSB_EMBEDDED configurations. */
+#ifdef CONFIG_SSB_EMBEDDED
+int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
+int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+#endif /* CONFIG_SSB_EMBEDDED */
#endif /* LINUX_SSB_H_ */
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index 536851b946f..7d7e03dcf77 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -367,8 +367,7 @@ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
-#include <linux/pm.h>
-extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
+extern void ssb_chipco_suspend(struct ssb_chipcommon *cc);
extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
@@ -390,6 +389,10 @@ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
u32 ticks);
+void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
+
+u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask);
+
/* Chipcommon GPIO pin access. */
u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h
new file mode 100644
index 00000000000..01fbdf5fef2
--- /dev/null
+++ b/include/linux/ssb/ssb_driver_gige.h
@@ -0,0 +1,174 @@
+#ifndef LINUX_SSB_DRIVER_GIGE_H_
+#define LINUX_SSB_DRIVER_GIGE_H_
+
+#include <linux/ssb/ssb.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+
+#ifdef CONFIG_SSB_DRIVER_GIGE
+
+
+#define SSB_GIGE_PCIIO 0x0000 /* PCI I/O Registers (1024 bytes) */
+#define SSB_GIGE_RESERVED 0x0400 /* Reserved (1024 bytes) */
+#define SSB_GIGE_PCICFG 0x0800 /* PCI config space (256 bytes) */
+#define SSB_GIGE_SHIM_FLUSHSTAT 0x0C00 /* PCI to OCP: Flush status control (32bit) */
+#define SSB_GIGE_SHIM_FLUSHRDA 0x0C04 /* PCI to OCP: Flush read address (32bit) */
+#define SSB_GIGE_SHIM_FLUSHTO 0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
+#define SSB_GIGE_SHIM_BARRIER 0x0C0C /* PCI to OCP: Barrier register (32bit) */
+#define SSB_GIGE_SHIM_MAOCPSI 0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
+#define SSB_GIGE_SHIM_SIOCPMA 0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
+
+/* TM Status High flags */
+#define SSB_GIGE_TMSHIGH_RGMII 0x00010000 /* Have an RGMII PHY-bus */
+/* TM Status Low flags */
+#define SSB_GIGE_TMSLOW_TXBYPASS 0x00080000 /* TX bypass (no delay) */
+#define SSB_GIGE_TMSLOW_RXBYPASS 0x00100000 /* RX bypass (no delay) */
+#define SSB_GIGE_TMSLOW_DLLEN 0x01000000 /* Enable DLL controls */
+
+/* Boardflags (low) */
+#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
+
+
+#define SSB_GIGE_MEM_RES_NAME "SSB Broadcom 47xx GigE memory"
+#define SSB_GIGE_IO_RES_NAME "SSB Broadcom 47xx GigE I/O"
+
+struct ssb_gige {
+ struct ssb_device *dev;
+
+ spinlock_t lock;
+
+ /* True, if the device has an RGMII bus.
+ * False, if the device has a GMII bus. */
+ bool has_rgmii;
+
+ /* The PCI controller device. */
+ struct pci_controller pci_controller;
+ struct pci_ops pci_ops;
+ struct resource mem_resource;
+ struct resource io_resource;
+};
+
+/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
+extern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
+
+/* Convert a pci_dev pointer to a ssb_gige pointer. */
+static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
+{
+ if (!pdev_is_ssb_gige_core(pdev))
+ return NULL;
+ return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
+}
+
+/* Returns whether the PHY is connected by an RGMII bus. */
+static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
+{
+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
+ return (dev ? dev->has_rgmii : 0);
+}
+
+/* Returns whether we have a Roboswitch. */
+static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
+{
+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
+ if (dev)
+ return !!(dev->dev->bus->sprom.boardflags_lo &
+ SSB_GIGE_BFL_ROBOSWITCH);
+ return 0;
+}
+
+/* Returns whether we can only do one DMA at once. */
+static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
+{
+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
+ if (dev)
+ return ((dev->dev->bus->chip_id == 0x4785) &&
+ (dev->dev->bus->chip_rev < 2));
+ return 0;
+}
+
+/* Returns whether we must flush posted writes. */
+static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
+{
+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
+ if (dev)
+ return (dev->dev->bus->chip_id == 0x4785);
+ return 0;
+}
+
+extern char * nvram_get(const char *name);
+/* Get the device MAC address */
+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+{
+#ifdef CONFIG_BCM947XX
+ char *res = nvram_get("et0macaddr");
+ if (res)
+ memcpy(macaddr, res, 6);
+#endif
+}
+
+extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
+ struct pci_dev *pdev);
+extern int ssb_gige_map_irq(struct ssb_device *sdev,
+ const struct pci_dev *pdev);
+
+/* The GigE driver is not a standalone module, because we don't have support
+ * for unregistering the driver. So we could not unload the module anyway. */
+extern int ssb_gige_init(void);
+static inline void ssb_gige_exit(void)
+{
+ /* Currently we can not unregister the GigE driver,
+ * because we can not unregister the PCI bridge. */
+ BUG();
+}
+
+
+#else /* CONFIG_SSB_DRIVER_GIGE */
+/* Gigabit Ethernet driver disabled */
+
+
+static inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
+ struct pci_dev *pdev)
+{
+ return -ENOSYS;
+}
+static inline int ssb_gige_map_irq(struct ssb_device *sdev,
+ const struct pci_dev *pdev)
+{
+ return -ENOSYS;
+}
+static inline int ssb_gige_init(void)
+{
+ return 0;
+}
+static inline void ssb_gige_exit(void)
+{
+}
+
+static inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
+{
+ return 0;
+}
+static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
+{
+ return NULL;
+}
+static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
+{
+ return 0;
+}
+static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
+{
+ return 0;
+}
+static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
+{
+ return 0;
+}
+static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
+{
+ return 0;
+}
+
+#endif /* CONFIG_SSB_DRIVER_GIGE */
+#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h
index 5e25bac4ed3..41e330e51c2 100644
--- a/include/linux/ssb/ssb_driver_pci.h
+++ b/include/linux/ssb/ssb_driver_pci.h
@@ -1,6 +1,11 @@
#ifndef LINUX_SSB_PCICORE_H_
#define LINUX_SSB_PCICORE_H_
+#include <linux/types.h>
+
+struct pci_dev;
+
+
#ifdef CONFIG_SSB_DRIVER_PCICORE
/* PCI core registers. */
@@ -88,6 +93,9 @@ extern void ssb_pcicore_init(struct ssb_pcicore *pc);
extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
struct ssb_device *dev);
+int ssb_pcicore_plat_dev_init(struct pci_dev *d);
+int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+
#else /* CONFIG_SSB_DRIVER_PCICORE */
@@ -107,5 +115,16 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
return 0;
}
+static inline
+int ssb_pcicore_plat_dev_init(struct pci_dev *d)
+{
+ return -ENODEV;
+}
+static inline
+int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return -ENODEV;
+}
+
#endif /* CONFIG_SSB_DRIVER_PCICORE */
#endif /* LINUX_SSB_PCICORE_H_ */