linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/1] new module for amba axi on-chip interconnect
@ 2011-03-29  9:40 Arend van Spriel
  2011-03-29  9:40 ` [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module Arend van Spriel
                   ` (4 more replies)
  0 siblings, 5 replies; 19+ messages in thread
From: Arend van Spriel @ 2011-03-29  9:40 UTC (permalink / raw)
  To: linux-kernel, akpm, rmk+kernel; +Cc: gregkh, linux-wireless, devel

GUIDANCE NEEDED:
This patch puts the module at proposed location. Please provide your
guidance if there is a better location within the linux tree for this
module.

This module has been isolated from the brcm80211 driver currently
located in staging and provided to other drivers for chipsets using
the AMBA AXI on-chip interconnect with ARM Device Management Plugin
(DMP) silicon IP, which provides system discovery (chip being the
system) and basic core function (disable, reset, etc.).

The module has previously been posted on the linux-wireless list and
comments by Randy Dunlap have been taken in. Also the SubmitChecklist
has been followed.

Arend van Spriel (1):
  drivers: brcmaxi: provide amba axi functionality in separate module

 drivers/Kconfig            |    2 +
 drivers/Makefile           |    1 +
 drivers/brcmaxi/Kconfig    |   23 ++
 drivers/brcmaxi/Makefile   |   25 ++
 drivers/brcmaxi/axi.c      |  786 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/brcmaxi/axi_priv.h |   51 +++
 drivers/brcmaxi/pci.c      |  118 +++++++
 include/brcmaxi/amba.h     |   87 +++++
 include/brcmaxi/axi.h      |  310 +++++++++++++++++
 include/brcmaxi/pci.h      |  112 +++++++
 10 files changed, 1515 insertions(+), 0 deletions(-)
 create mode 100644 drivers/brcmaxi/Kconfig
 create mode 100644 drivers/brcmaxi/Makefile
 create mode 100644 drivers/brcmaxi/axi.c
 create mode 100644 drivers/brcmaxi/axi_priv.h
 create mode 100644 drivers/brcmaxi/pci.c
 create mode 100644 include/brcmaxi/amba.h
 create mode 100644 include/brcmaxi/axi.h
 create mode 100644 include/brcmaxi/pci.h



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
@ 2011-03-29  9:40 ` Arend van Spriel
  2011-03-29 10:45   ` Jiri Slaby
  2011-03-29 13:14 ` [PATCH 0/1] new module for amba axi on-chip interconnect Greg KH
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: Arend van Spriel @ 2011-03-29  9:40 UTC (permalink / raw)
  To: linux-kernel, akpm, rmk+kernel; +Cc: gregkh, linux-wireless, devel

The open-source community is looking for a library which will detect
cores in a chip using axi backplane. This is an initial delivery of
what it could look like. Tested it with the Broadcom open-source
mac80211 wireless driver located in drivers/staging/brcm80211.

Reviewed-by: Randy Dunlap <rdunlap@xenotime.net>
Reviewed-by: Henry Ptasinski <henryp@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/Kconfig            |    2 +
 drivers/Makefile           |    1 +
 drivers/brcmaxi/Kconfig    |   23 ++
 drivers/brcmaxi/Makefile   |   25 ++
 drivers/brcmaxi/axi.c      |  786 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/brcmaxi/axi_priv.h |   51 +++
 drivers/brcmaxi/pci.c      |  118 +++++++
 include/brcmaxi/amba.h     |   87 +++++
 include/brcmaxi/axi.h      |  310 +++++++++++++++++
 include/brcmaxi/pci.h      |  112 +++++++
 10 files changed, 1515 insertions(+), 0 deletions(-)
 create mode 100644 drivers/brcmaxi/Kconfig
 create mode 100644 drivers/brcmaxi/Makefile
 create mode 100644 drivers/brcmaxi/axi.c
 create mode 100644 drivers/brcmaxi/axi_priv.h
 create mode 100644 drivers/brcmaxi/pci.c
 create mode 100644 include/brcmaxi/amba.h
 create mode 100644 include/brcmaxi/axi.h
 create mode 100644 include/brcmaxi/pci.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 177c7d1..8617526 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,6 +68,8 @@ source "drivers/watchdog/Kconfig"
 
 source "drivers/ssb/Kconfig"
 
+source "drivers/brcmaxi/Kconfig"
+
 source "drivers/mfd/Kconfig"
 
 source "drivers/regulator/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a125e0b..c970b92 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_HID)		+= hid/
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_OF)		+= of/
 obj-$(CONFIG_SSB)		+= ssb/
+obj-$(CONFIG_BRCMAXI)		+= brcmaxi/
 obj-$(CONFIG_VHOST_NET)		+= vhost/
 obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
diff --git a/drivers/brcmaxi/Kconfig b/drivers/brcmaxi/Kconfig
new file mode 100644
index 0000000..d5e384b
--- /dev/null
+++ b/drivers/brcmaxi/Kconfig
@@ -0,0 +1,23 @@
+menuconfig BRCMAXI
+	tristate "Broadcom AXI utility function module"
+	---help---
+	  This module provides utility functions for detecting, enabling,
+	  initializing, and configuring cores on Broadcom chips which are
+	  using the AMBA AXI bus.
+	  
+	  The module is called brcmaxi.ko.
+
+config BRCMAXI_AMBA
+	bool "Broadcom AXI direct access"
+	default y
+	depends on BRCMAXI
+	---help---
+	  Selecting Y here allows direct access to the cores on the AMBA
+	  AXI backplane.
+
+config BRCMAXI_PCI
+	bool "Broadcom AXI over PCI"
+	depends on BRCMAXI
+	---help---
+	  Selecting Y here allows access to cores on AMBA AXI backplane
+	  through the PCI host interface.
diff --git a/drivers/brcmaxi/Makefile b/drivers/brcmaxi/Makefile
new file mode 100644
index 0000000..91f7797
--- /dev/null
+++ b/drivers/brcmaxi/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for Broadcom AMBA AXI utility module
+#
+# Copyright (c) 2011 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+MODULEPFX := brcmaxi
+
+ccflags-$(CONFIG_DEBUG_KERNEL)		+= -DDEBUG
+
+obj-$(CONFIG_BRCMAXI)			+= $(MODULEPFX).o
+
+$(MODULEPFX)-y				+= axi.o
+$(MODULEPFX)-$(CONFIG_BRCMAXI_PCI)	+= pci.o
diff --git a/drivers/brcmaxi/axi.c b/drivers/brcmaxi/axi.c
new file mode 100644
index 0000000..9243d64
--- /dev/null
+++ b/drivers/brcmaxi/axi.c
@@ -0,0 +1,786 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <brcmaxi/axi.h>
+
+#include "axi_priv.h"
+
+#define AXI_DESCRIPTION "Broadcom AXI utility library"
+
+MODULE_DESCRIPTION(AXI_DESCRIPTION);
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* Core enumeration ROM registers */
+#define	ER_EROMENTRY		0x000
+#define	ER_REMAPCONTROL		0xe00
+#define	ER_REMAPSELECT		0xe04
+#define	ER_MASTERSELECT		0xe10
+#define	ER_ITCR			0xf00
+#define	ER_ITIP			0xf04
+
+/* Core enumeration ROM entries */
+#define	ER_TAG			0xe
+#define	ER_TAG1			0x6
+#define	ER_VALID		1
+#define	ER_CI			0
+#define	ER_MP			2
+#define	ER_ADD			4
+#define	ER_END			0xe
+#define	ER_BAD			0xffffffff
+
+/* Core enumeration ROM CompIdentA */
+#define	CIA_MFG_MASK		0xfff00000
+#define	CIA_MFG_SHIFT		20
+#define	CIA_CID_MASK		0x000fff00
+#define	CIA_CID_SHIFT		8
+#define	CIA_CCL_MASK		0x000000f0
+#define	CIA_CCL_SHIFT		4
+
+/* Core enumeration ROM CompIdentB */
+#define	CIB_REV_MASK		0xff000000
+#define	CIB_REV_SHIFT		24
+#define	CIB_NSW_MASK		0x00f80000
+#define	CIB_NSW_SHIFT		19
+#define	CIB_NMW_MASK		0x0007c000
+#define	CIB_NMW_SHIFT		14
+#define	CIB_NSP_MASK		0x00003e00
+#define	CIB_NSP_SHIFT		9
+#define	CIB_NMP_MASK		0x000001f0
+#define	CIB_NMP_SHIFT		4
+
+/* Core enumeration ROM MasterPortDesc */
+#define	MPD_MUI_MASK		0x0000ff00
+#define	MPD_MUI_SHIFT		8
+#define	MPD_MP_MASK		0x000000f0
+#define	MPD_MP_SHIFT		4
+
+/* Core enumeration ROM AddrDesc */
+#define	AD_ADDR_MASK		0xfffff000
+#define	AD_SP_MASK		0x00000f00
+#define	AD_SP_SHIFT		8
+#define	AD_ST_MASK		0x000000c0
+#define	AD_ST_SHIFT		6
+#define	AD_ST_SLAVE		0x00000000
+#define	AD_ST_BRIDGE		0x00000040
+#define	AD_ST_SWRAP		0x00000080
+#define	AD_ST_MWRAP		0x000000c0
+#define	AD_SZ_MASK		0x00000030
+#define	AD_SZ_SHIFT		4
+#define	AD_SZ_4K		0x00000000
+#define	AD_SZ_8K		0x00000010
+#define	AD_SZ_16K		0x00000020
+#define	AD_SZ_SZD		0x00000030
+#define	AD_AG32			0x00000008
+#define	AD_ADDR_ALIGN		0x00000fff
+#define	AD_SZ_BASE		0x00001000	/* 4KB */
+
+/* Core enumeration ROM SizeDesc */
+#define	SD_SZ_MASK		0xfffff000
+#define	SD_SG32			0x00000008
+#define	SD_SZ_ALIGN		0x00000fff
+
+/* resetctrl */
+#define	AIRC_RESET		1
+
+/* definition for specifying padding fields */
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+
+/*
+ * struct aidmp - device management plugin "wrapper" registers.
+ */
+struct aidmp {
+	u32 oobselina30;	/* 0x000 */
+	u32 oobselina74;	/* 0x004 */
+	u32 PAD[6];
+	u32 oobselinb30;	/* 0x020 */
+	u32 oobselinb74;	/* 0x024 */
+	u32 PAD[6];
+	u32 oobselinc30;	/* 0x040 */
+	u32 oobselinc74;	/* 0x044 */
+	u32 PAD[6];
+	u32 oobselind30;	/* 0x060 */
+	u32 oobselind74;	/* 0x064 */
+	u32 PAD[38];
+	u32 oobselouta30;	/* 0x100 */
+	u32 oobselouta74;	/* 0x104 */
+	u32 PAD[6];
+	u32 oobseloutb30;	/* 0x120 */
+	u32 oobseloutb74;	/* 0x124 */
+	u32 PAD[6];
+	u32 oobseloutc30;	/* 0x140 */
+	u32 oobseloutc74;	/* 0x144 */
+	u32 PAD[6];
+	u32 oobseloutd30;	/* 0x160 */
+	u32 oobseloutd74;	/* 0x164 */
+	u32 PAD[38];
+	u32 oobsynca;	/* 0x200 */
+	u32 oobseloutaen;	/* 0x204 */
+	u32 PAD[6];
+	u32 oobsyncb;	/* 0x220 */
+	u32 oobseloutben;	/* 0x224 */
+	u32 PAD[6];
+	u32 oobsyncc;	/* 0x240 */
+	u32 oobseloutcen;	/* 0x244 */
+	u32 PAD[6];
+	u32 oobsyncd;	/* 0x260 */
+	u32 oobseloutden;	/* 0x264 */
+	u32 PAD[38];
+	u32 oobaextwidth;	/* 0x300 */
+	u32 oobainwidth;	/* 0x304 */
+	u32 oobaoutwidth;	/* 0x308 */
+	u32 PAD[5];
+	u32 oobbextwidth;	/* 0x320 */
+	u32 oobbinwidth;	/* 0x324 */
+	u32 oobboutwidth;	/* 0x328 */
+	u32 PAD[5];
+	u32 oobcextwidth;	/* 0x340 */
+	u32 oobcinwidth;	/* 0x344 */
+	u32 oobcoutwidth;	/* 0x348 */
+	u32 PAD[5];
+	u32 oobdextwidth;	/* 0x360 */
+	u32 oobdinwidth;	/* 0x364 */
+	u32 oobdoutwidth;	/* 0x368 */
+	u32 PAD[37];
+	u32 ioctrlset;	/* 0x400 */
+	u32 ioctrlclear;	/* 0x404 */
+	u32 ioctrl;		/* 0x408 */
+	u32 PAD[61];
+	u32 iostatus;	/* 0x500 */
+	u32 PAD[127];
+	u32 ioctrlwidth;	/* 0x700 */
+	u32 iostatuswidth;	/* 0x704 */
+	u32 PAD[62];
+	u32 resetctrl;	/* 0x800 */
+	u32 resetstatus;	/* 0x804 */
+	u32 resetreadid;	/* 0x808 */
+	u32 resetwriteid;	/* 0x80c */
+	u32 PAD[60];
+	u32 errlogctrl;	/* 0x900 */
+	u32 errlogdone;	/* 0x904 */
+	u32 errlogstatus;	/* 0x908 */
+	u32 errlogaddrlo;	/* 0x90c */
+	u32 errlogaddrhi;	/* 0x910 */
+	u32 errlogid;	/* 0x914 */
+	u32 errloguser;	/* 0x918 */
+	u32 errlogflags;	/* 0x91c */
+	u32 PAD[56];
+	u32 intstatus;	/* 0xa00 */
+	u32 PAD[127];
+	u32 config;		/* 0xe00 */
+	u32 PAD[63];
+	u32 itcr;		/* 0xf00 */
+	u32 PAD[3];
+	u32 itipooba;	/* 0xf10 */
+	u32 itipoobb;	/* 0xf14 */
+	u32 itipoobc;	/* 0xf18 */
+	u32 itipoobd;	/* 0xf1c */
+	u32 PAD[4];
+	u32 itipoobaout;	/* 0xf30 */
+	u32 itipoobbout;	/* 0xf34 */
+	u32 itipoobcout;	/* 0xf38 */
+	u32 itipoobdout;	/* 0xf3c */
+	u32 PAD[4];
+	u32 itopooba;	/* 0xf50 */
+	u32 itopoobb;	/* 0xf54 */
+	u32 itopoobc;	/* 0xf58 */
+	u32 itopoobd;	/* 0xf5c */
+	u32 PAD[4];
+	u32 itopoobain;	/* 0xf70 */
+	u32 itopoobbin;	/* 0xf74 */
+	u32 itopoobcin;	/* 0xf78 */
+	u32 itopoobdin;	/* 0xf7c */
+	u32 PAD[4];
+	u32 itopreset;	/* 0xf90 */
+	u32 PAD[15];
+	u32 peripherialid4;	/* 0xfd0 */
+	u32 peripherialid5;	/* 0xfd4 */
+	u32 peripherialid6;	/* 0xfd8 */
+	u32 peripherialid7;	/* 0xfdc */
+	u32 peripherialid0;	/* 0xfe0 */
+	u32 peripherialid1;	/* 0xfe4 */
+	u32 peripherialid2;	/* 0xfe8 */
+	u32 peripherialid3;	/* 0xfec */
+	u32 componentid0;	/* 0xff0 */
+	u32 componentid1;	/* 0xff4 */
+	u32 componentid2;	/* 0xff8 */
+	u32 componentid3;	/* 0xffc */
+};
+
+/* register access macros */
+#ifdef __LITTLE_ENDIAN
+#ifndef __mips__
+#define R_REG(r) \
+	(sizeof(*(r)) == sizeof(u8) ? \
+		readb((volatile u8*)(r)) : \
+	sizeof(*(r)) == sizeof(u16) ? \
+		readw((volatile u16*)(r)) : \
+	readl((volatile u32*)(r)))
+
+#else	/* __mips__ */
+#define R_REG(r) \
+	({ \
+		__typeof(*(r)) __reg_val; \
+		__asm__ __volatile__("sync"); \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			__reg_val = readb((volatile u8*)(r)); \
+			break; \
+		case sizeof(u16): \
+			__reg_val = readw((volatile u16*)(r)); \
+			break; \
+		case sizeof(u32): \
+			__reg_val = readl((volatile u32*)(r)); \
+			break; \
+		} \
+		__asm__ __volatile__("sync"); \
+		__reg_val; \
+	})
+#endif	/* __mips__ */
+#define W_REG(r, v) \
+	do { \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			writeb((u8)(v), (volatile u8*)(r)); break; \
+		case sizeof(u16): \
+			writew((u16)(v), (volatile u16*)(r)); break; \
+		case sizeof(u32): \
+			writel((u32)(v), (volatile u32*)(r)); break; \
+		} \
+	} while (0)
+#else	/* __LITTLE_ENDIAN */
+#define R_REG(r) \
+	({ \
+		__typeof(*(r)) __reg_val; \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			__reg_val = readb((volatile u8*)((r)^3)); \
+			break; \
+		case sizeof(u16): \
+			__reg_val = readw((volatile u16*)((r)^2)); \
+			break; \
+		case sizeof(u32): \
+			__reg_val = readl((volatile u32*)(r)); \
+			break; \
+		} \
+		__reg_val; \
+	})
+#define W_REG(r, v) \
+	do { \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8):	\
+			writeb((u8)(v), \
+			(volatile u8*)((r)^3)); break; \
+		case sizeof(u16):	\
+			writew((u16)(v), \
+			(volatile u16*)((r)^2)); break; \
+		case sizeof(u32):	\
+			writel((u32)(v), \
+			(volatile u32*)(r)); break; \
+		} \
+	} while (0)
+#endif	/* __LITTLE_ENDIAN */
+
+static void *find_core_handler(struct axi_instance *aih,
+			       u32 mfg_id, u32 core_id)
+{
+	const struct axi_core_handler *handler = aih->handler_list;
+	int i;
+
+	for (i = 0; i < aih->num_handler; i++, handler++) {
+		if ((handler->mfg_id != AXI_ANY_ID) &&
+		    (handler->mfg_id != mfg_id))
+			continue;
+		if ((handler->core_id != AXI_ANY_ID) &&
+		    (handler->mfg_id != mfg_id) &&
+		    (handler->core_id != core_id))
+			continue;
+
+		return handler->handler;
+	}
+
+	return NULL;
+}
+
+/*
+ * get_erom_ent - axi core enumeration rom parsing
+ * @eromptr: pointer progressing through enumeration rom.
+ * @mask: mask used on entry to check with provided match.
+ * @match: entry to find in enumeration rom.
+ *
+ * @returns enumeration rom entry
+ */
+static u32
+get_erom_ent(u32 **eromptr, u32 mask, u32 match)
+{
+	u32 ent;
+	uint inv = 0, nom = 0;
+
+	while (true) {
+		ent = R_REG(*eromptr);
+		(*eromptr)++;
+
+		if (mask == 0)
+			break;
+
+		if ((ent & ER_VALID) == 0) {
+			inv++;
+			continue;
+		}
+
+		if (ent == (ER_END | ER_VALID))
+			break;
+
+		if ((ent & mask) == match)
+			break;
+
+		nom++;
+	}
+
+	if (inv + nom) {
+		pr_debug("%d invalid and %d non-matching entries\n",
+		       inv, nom);
+	}
+	pr_debug("%s: Returning ent 0x%08x\n", __func__, ent);
+	return ent;
+}
+
+/*
+ * get_asd - retrieve address descriptor from axi enumeration rom
+ * @eromptr: pointer progressing through enumeration rom.
+ * @sp: slave port for which the descriptor is retrieved.
+ * @ad: address descriptor for which the descriptor is retrieved.
+ * @st: slave type for which the descriptor is retrieved.
+ * @addrl: low part of physical address.
+ * @addrh: high part of physical address.
+ * @sizel: low part of physical area size.
+ * @sizeh: high part of physical area size.
+ */
+static u32
+get_asd(u32 **eromptr, uint sp, uint ad, uint st,
+	u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh)
+{
+	u32 asd, sz, szd;
+
+	asd = get_erom_ent(eromptr, ER_VALID, ER_VALID);
+	if (((asd & ER_TAG1) != ER_ADD) ||
+	    (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
+	    ((asd & AD_ST_MASK) != st)) {
+		/* This is not what we want, "push" it back */
+		(*eromptr)--;
+		return 0;
+	}
+	*addrl = asd & AD_ADDR_MASK;
+	if (asd & AD_AG32)
+		*addrh = get_erom_ent(eromptr, 0, 0);
+	else
+		*addrh = 0;
+	*sizeh = 0;
+	sz = asd & AD_SZ_MASK;
+	if (sz == AD_SZ_SZD) {
+		szd = get_erom_ent(eromptr, 0, 0);
+		*sizel = szd & SD_SZ_MASK;
+		if (szd & SD_SG32)
+			*sizeh = get_erom_ent(eromptr, 0, 0);
+	} else
+		*sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
+
+	pr_debug("  SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
+	       sp, ad, st, *sizeh, *sizel, *addrh, *addrl);
+
+	return asd;
+}
+
+struct axi_local *axi_create(u32 priv_len)
+{
+	struct axi_local *inst;
+	int size = ALIGN(sizeof(*inst), 4) + priv_len;
+
+	inst = kzalloc(size, GFP_ATOMIC);
+	try_module_get(THIS_MODULE);
+
+	return inst;
+}
+struct axi_instance *axi_open(void *regs, u32 erombase, u32 priv_len)
+{
+	struct axi_local *inst = axi_create(priv_len);
+
+	/* fill public fields */
+	inst->pub.regs = regs;
+	inst->pub.priv = (char *)inst + ALIGN(sizeof(*inst), 4);
+
+	inst->enum_rom_ptr = ioremap_nocache((unsigned long)erombase,
+					     AXI_CORE_SIZE);
+
+	return &inst->pub;
+}
+
+void axi_close(struct axi_instance *aih)
+{
+	kfree(aih);
+	module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL(axi_close);
+
+int axi_scan(struct axi_instance *aih)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = NULL;
+	u32 *eromlim, *eromptr = ail->enum_rom_ptr;
+	int numcores = 0;
+
+	eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32));
+
+	pr_debug("axi_scan: erom: ptr = 0x%p, limit = 0x%p\n",
+		 eromptr, eromlim);
+
+	while (eromptr < eromlim) {
+		bool (*handler)(struct axi_instance *ai, struct axi_core *core);
+		u32 cia, cib, cid, mfg, crev;
+		u32 n_master_wrap, n_slave_wrap, n_master_port, n_slave_port;
+		u32 mst_port_desc, addr_space_desc, addrl, addrh, sizel, sizeh;
+		u32 *base;
+		uint i, j;
+		bool br;
+
+		br = false;
+		core = NULL;
+
+		/* Grok a component */
+		cia = get_erom_ent(&eromptr, ER_TAG, ER_CI);
+		if (cia == (ER_END | ER_VALID)) {
+			pr_debug("Found END of erom after %d cores\n",
+				 numcores);
+			return numcores;
+		}
+		base = eromptr - 1;
+		cib = get_erom_ent(&eromptr, 0, 0);
+
+		if ((cib & ER_TAG) != ER_CI) {
+			pr_err("CIA not followed by CIB\n");
+			return 0;
+		}
+
+		cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
+		mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
+		crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
+		n_master_wrap = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
+		n_slave_wrap = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
+		n_master_port = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
+		n_slave_port = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
+
+		pr_debug("Found component 0x%04x/0x%04x rev %d at "
+		       "erom addr 0x%p, with nmw = %d, nsw = %d, nmp = %d & "
+		       "nsp = %d\n", mfg, cid, crev, base, n_master_wrap,
+		       n_slave_wrap, n_master_port, n_slave_port);
+
+		/* ??ignore processor core?? */
+		if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) ||
+		    (n_slave_port == 0))
+			continue;
+
+		/* alloc space to store core information */
+		core = kzalloc(sizeof(struct axi_core), GFP_ATOMIC);
+		if (!core)
+			return 0;
+
+		core->id = cid;
+		core->mfg = mfg;
+		core->rev = crev;
+
+		if ((n_master_wrap + n_slave_wrap) == 0) {
+			/* A component which is not a core */
+			if (cid == OOB_ROUTER_CORE_ID) {
+				addr_space_desc = get_asd(&eromptr, 0, 0,
+					AD_ST_SLAVE, &addrl, &addrh,
+					&sizel, &sizeh);
+				if (addr_space_desc != 0) {
+					core->phys_address = addrl;
+					handler = find_core_handler(aih,
+								     mfg, cid);
+					if (!handler ||
+					    handler(aih, core) == true) {
+						kfree(core);
+					}
+				} else {
+					kfree(core);
+				}
+			}
+			continue;
+		}
+
+		for (i = 0; i < n_master_port; i++) {
+			mst_port_desc =
+				get_erom_ent(&eromptr, ER_VALID, ER_VALID);
+			if ((mst_port_desc & ER_TAG) != ER_MP) {
+				pr_err("Not enough MP entries for "
+				       "component 0x%x\n", cid);
+				goto error;
+			}
+			pr_debug("  Master port %d, mp: %d id: %d\n", i,
+				 (mst_port_desc & MPD_MP_MASK) >> MPD_MP_SHIFT,
+				 (mst_port_desc & MPD_MUI_MASK) >> MPD_MUI_SHIFT
+			);
+		}
+
+		/* First Slave Address Descriptor should be port 0:
+		 * the main register space for the core
+		 */
+		addr_space_desc =
+		    get_asd(&eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh,
+			    &sizel, &sizeh);
+		if (addr_space_desc == 0) {
+			/* Try again to see if it is a bridge */
+			addr_space_desc =
+			    get_asd(&eromptr, 0, 0, AD_ST_BRIDGE, &addrl,
+				    &addrh, &sizel, &sizeh);
+			if (addr_space_desc != 0)
+				br = true;
+			else if ((addrh != 0) || (sizeh != 0)
+				 || (sizel != AXI_CORE_SIZE)) {
+				pr_err("First Slave ASD for core "
+				       "0x%04x malformed (0x%08x)\n",
+				       cid, addr_space_desc);
+				goto error;
+			}
+		}
+
+		core->phys_address = addrl;
+		core->phys_space = sizel;
+
+		/* Get any more ASDs in port 0 */
+		j = 1;
+		do {
+			addr_space_desc =
+			    get_asd(&eromptr, 0, j, AD_ST_SLAVE, &addrl,
+				    &addrh, &sizel, &sizeh);
+			if ((addr_space_desc != 0) && (j == 1) &&
+			    (sizel == AXI_CORE_SIZE)) {
+				core->sec_phys_address = addrl;
+				core->sec_phys_space = sizel;
+			}
+			j++;
+		} while (addr_space_desc != 0);
+
+		/* Go through the ASDs for other slave ports */
+		for (i = 1; i < n_slave_port; i++) {
+			j = 0;
+			do {
+				addr_space_desc =
+				    get_asd(&eromptr, i, j++, AD_ST_SLAVE,
+					    &addrl, &addrh, &sizel, &sizeh);
+			} while (addr_space_desc != 0);
+			if (j == 0) {
+				pr_err("SP %d has no address "
+				       "descriptors\n", i);
+				goto error;
+			}
+		}
+
+		/* Now get master wrappers */
+		for (i = 0; i < n_master_wrap; i++) {
+			addr_space_desc =
+			    get_asd(&eromptr, i, 0, AD_ST_MWRAP, &addrl,
+				    &addrh, &sizel, &sizeh);
+			if (addr_space_desc == 0) {
+				pr_err("Missing descriptor for MW %d\n"
+				       , i);
+				goto error;
+			}
+			if ((sizeh != 0) || (sizel != AXI_CORE_SIZE)) {
+				pr_err("Master wrapper %d is not 4KB\n"
+				       , i);
+				goto error;
+			}
+			if (i == 0)
+				core->wrap_phys_address = addrl;
+		}
+
+		/* And finally slave wrappers */
+		for (i = 0; i < n_slave_wrap; i++) {
+			uint fwp = (n_slave_port == 1) ? 0 : 1;
+			addr_space_desc =
+			    get_asd(&eromptr, fwp + i, 0, AD_ST_SWRAP,
+				    &addrl, &addrh, &sizel, &sizeh);
+			if (addr_space_desc == 0) {
+				pr_err("Missing descriptor for SW %d\n", i);
+				goto error;
+			}
+			if ((sizeh != 0) || (sizel != AXI_CORE_SIZE)) {
+				pr_err("Slave wrapper %d is not 4KB\n", i);
+				goto error;
+			}
+			if ((n_master_wrap == 0) && (i == 0))
+				core->wrap_phys_address = addrl;
+		}
+
+		/* Don't record bridges */
+		if (br)
+			continue;
+
+		/* first core is current core */
+		pci_axi_set_curcore(aih, core);
+
+		/* Done with core */
+		handler = find_core_handler(aih, mfg, cid);
+		if (handler && handler(aih, core) == false)
+			numcores++;
+		else
+			kfree(core);
+	}
+
+	pr_err("Reached end of erom without finding END");
+
+error:
+	kfree(core);
+	return 0;
+}
+EXPORT_SYMBOL(axi_scan);
+
+bool axi_iscoreup(struct axi_core *core)
+{
+	struct aidmp *ai;
+
+	ai = core->wrap;
+
+	return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
+		 SICF_CLOCK_EN)
+		&& ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0));
+}
+
+void axi_core_disable(struct axi_core *core, u32 bits)
+{
+	volatile u32 dummy;
+	struct aidmp *ai;
+
+	ai = core->wrap;
+
+	/* if core is already in reset, just return */
+	if (R_REG(&ai->resetctrl) & AIRC_RESET)
+		return;
+
+	W_REG(&ai->ioctrl, bits);
+	dummy = R_REG(&ai->ioctrl);
+	udelay(10);
+
+	W_REG(&ai->resetctrl, AIRC_RESET);
+	udelay(1);
+}
+
+void axi_core_reset(struct axi_core *core, u32 bits, u32 resetbits)
+{
+	struct aidmp *ai;
+	volatile u32 dummy;
+
+	ai = core->wrap;
+
+	/*
+	 * Must do the disable sequence first to work for
+	 * arbitrary current core state.
+	 */
+	axi_core_disable(core, (bits | resetbits));
+
+	/*
+	 * Now do the initialization sequence.
+	 */
+	W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
+	dummy = R_REG(&ai->ioctrl);
+	W_REG(&ai->resetctrl, 0);
+	udelay(1);
+
+	W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN));
+	dummy = R_REG(&ai->ioctrl);
+	udelay(1);
+}
+
+uint axi_flag(struct axi_core *core)
+{
+	struct aidmp *ai;
+
+	/* TODO: what is with BCM47162 DMP */
+	ai = core->wrap;
+
+	return R_REG(&ai->oobselouta30) & 0x1f;
+}
+
+u32 axi_core_cflags(struct axi_core *core, u32 mask, u32 val)
+{
+	struct aidmp *ai;
+	u32 w;
+
+	/* TODO: what is with BCM47162 DMP */
+	ai = core->wrap;
+
+	WARN_ON((val & ~mask) == 0);
+
+	if (mask || val) {
+		w = ((R_REG(&ai->ioctrl) & ~mask) | val);
+		W_REG(&ai->ioctrl, w);
+	}
+
+	return R_REG(&ai->ioctrl);
+}
+
+u32 axi_core_sflags(struct axi_core *core, u32 mask, u32 val)
+{
+	struct aidmp *ai;
+	u32 w;
+
+	/* TODO: what is with BCM47162 DMP */
+	ai = core->wrap;
+
+	WARN_ON((val & ~mask) == 0);
+	WARN_ON((mask & ~SISF_CORE_BITS) == 0);
+
+	if (mask || val) {
+		w = ((R_REG(&ai->iostatus) & ~mask) | val);
+		W_REG(&ai->iostatus, w);
+	}
+
+	return R_REG(&ai->iostatus);
+}
+
+#ifdef CONFIG_BRCMAXI_AMBA
+EXPORT_SYMBOL(axi_open);
+EXPORT_SYMBOL(axi_iscoreup);
+EXPORT_SYMBOL(axi_core_disable);
+EXPORT_SYMBOL(axi_core_reset);
+EXPORT_SYMBOL(axi_flag);
+EXPORT_SYMBOL(axi_core_cflags);
+EXPORT_SYMBOL(axi_core_sflags);
+#endif
+
+static int __init axi_init(void)
+{
+	pr_info(AXI_DESCRIPTION "\n");
+	return 0;
+}
+
+static void __exit axi_exit(void)
+{
+}
+
+module_init(axi_init);
+module_exit(axi_exit);
diff --git a/drivers/brcmaxi/axi_priv.h b/drivers/brcmaxi/axi_priv.h
new file mode 100644
index 0000000..c2b64f8
--- /dev/null
+++ b/drivers/brcmaxi/axi_priv.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef AXI_PRIV_H_
+#define AXI_PRIV_H_
+
+#include <brcmaxi/axi.h>
+
+/*
+ * struct axi_local - internal instance data
+ *
+ * @pub: &struct axi_instance pointer to public instance data.
+ * @curcore: &struct axi_core pointer to active core.
+ * @bustype: enum axi_bus referring to type of bus between axi and caller.
+ * @enum_rom_ptr: pointer to system discovery enumeration rom.
+ */
+struct axi_local {
+	struct axi_instance pub;
+#ifdef CONFIG_BRCMAXI_PCI
+	struct axi_core *curcore;
+#endif
+	u32 *enum_rom_ptr;
+};
+
+extern struct axi_local *axi_create(u32 priv_len);
+
+#ifdef CONFIG_BRCMAXI_PCI
+static inline void pci_axi_set_curcore(struct axi_instance *aih,
+					      struct axi_core *core)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	if (ail->curcore == NULL)
+		ail->curcore = core;
+}
+#else
+#define pci_axi_set_curcore(a,b)
+#endif
+
+#endif /* AXI_PRIV_H_ */
diff --git a/drivers/brcmaxi/pci.c b/drivers/brcmaxi/pci.c
new file mode 100644
index 0000000..f706806
--- /dev/null
+++ b/drivers/brcmaxi/pci.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <brcmaxi/axi.h>
+#include <brcmaxi/amba.h>
+
+#include "axi_priv.h"
+
+/* backplane address space accessed by BAR0 */
+#define	PCI_BAR0_WIN		0x80
+/* backplane address space accessed by second 4KB of BAR0 */
+#define	PCI_BAR0_WIN2		0xac
+
+struct axi_instance *pci_axi_open(void *pbus, void *regs,
+				  u32 erombase, u32 priv_len)
+{
+	struct axi_local *inst = axi_create(priv_len);
+
+	/* fill public fields */
+	inst->pub.pbus = pbus;
+	inst->pub.regs = regs;
+	inst->pub.priv = (char *)inst + ALIGN(sizeof(*inst), 4);
+
+	/* Now point the window at the core enumeration rom */
+	pci_write_config_dword(inst->pub.pbus, PCI_BAR0_WIN, erombase);
+	inst->enum_rom_ptr = regs;
+
+	return &inst->pub;
+}
+EXPORT_SYMBOL(pci_axi_open);
+
+void *pci_axi_set_active_core(struct axi_instance *aih, struct axi_core *ach)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+
+	u32 addr = ach->phys_address;
+	u32 wrap = ach->sec_phys_address;
+
+	/* point bar0 window */
+	pci_write_config_dword(aih->pbus, PCI_BAR0_WIN, addr);
+	ach->regs = ail->curcore->regs;
+	/* point bar0 2nd 4KB window */
+	pci_write_config_dword(aih->pbus, PCI_BAR0_WIN2, wrap);
+	ach->wrap = ail->curcore->wrap;
+
+	ail->curcore = ach;
+
+	return ach->regs;
+}
+EXPORT_SYMBOL(pci_axi_set_active_core);
+
+bool pci_axi_iscoreup(struct axi_instance *aih)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	return axi_iscoreup(core);
+}
+EXPORT_SYMBOL(pci_axi_iscoreup);
+
+void pci_axi_core_disable(struct axi_instance *aih, u32 bits)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	axi_core_disable(core, bits);
+}
+EXPORT_SYMBOL(pci_axi_core_disable);
+
+void pci_axi_core_reset(struct axi_instance *aih, u32 bits, u32 resetbits)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	axi_core_reset(core, bits, resetbits);
+}
+EXPORT_SYMBOL(pci_axi_core_reset);
+
+uint pci_axi_flag(struct axi_instance *aih)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	return axi_flag(core);
+}
+EXPORT_SYMBOL(pci_axi_flag);
+
+u32 pci_axi_core_cflags(struct axi_instance *aih, u32 mask, u32 val)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	return axi_core_cflags(core, mask, val);
+}
+EXPORT_SYMBOL(pci_axi_core_cflags);
+
+u32 pci_axi_core_sflags(struct axi_instance *aih, u32 mask, u32 val)
+{
+	struct axi_local *ail = (struct axi_local *)aih;
+	struct axi_core *core = ail->curcore;
+
+	return axi_core_sflags(core, mask, val);
+}
+EXPORT_SYMBOL(pci_axi_core_sflags);
diff --git a/include/brcmaxi/amba.h b/include/brcmaxi/amba.h
new file mode 100644
index 0000000..5940cb6
--- /dev/null
+++ b/include/brcmaxi/amba.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef AXI_AMBA_H_
+#define AXI_AMBA_H_
+
+/**
+ * axi_open - create instance.
+ * @regs: pointer to currently mapped register area.
+ * @erom_base: physical address where core enumeration rom is located.
+ * @priv_size: additional memory appended to instance for caller to use.
+ *
+ * Creates the instance filling in the provided details.
+ */
+struct axi_instance *axi_open(void *regs, u32 erom_base, u32 priv_size);
+/**
+ * axi_iscoreup - indicates core is reset and enabled.
+ * @core: &struct axi_core pointer to core of interest.
+ *
+ * Indicates whether the given core has reset and is enabled.
+ */
+bool axi_iscoreup(struct axi_core *core);
+/**
+ * axi_core_disable - disable the core.
+ * @core: &struct axi_core pointer to core of interest.
+ * @bits: core specific bits that are set during reset sequence.
+ *
+ * Disables the given core by reset. This will bring the core in
+ * the disabled state. Initialization is required to enable it again.
+ */
+void axi_core_disable(struct axi_core *core, u32 bits);
+/**
+ * axi_core_reset - reset and enable the core.
+ * @core: &struct axi_core pointer to core of interest.
+ * @bits: core specific bits that are set during and after the reset sequence.
+ * @resetbits: core specific bits that are set only during reset sequence.
+ *
+ * Resets and enables the given core.
+ */
+void axi_core_reset(struct axi_core *core, u32 bits, u32 resetbits);
+/**
+ * axi_flag - get axi flag.
+ * @core: &struct axi_core pointer to core of interest.
+ *
+ * Retrieves the axi flag for the given core.
+ */
+uint axi_flag(struct axi_core *core);
+/**
+ * axi_core_cflags - set core control flags.
+ * @core: &struct axi_core pointer to core of interest.
+ * @mask: mask indicating the bits to clear.
+ * @val: value with bits to set. bits must be within mask.
+ *
+ * Set I/O control flags for the given core. The function returns
+ * the resulting value of the control flags. When called with with
+ * mask and val parameters being 0 the current control flags are
+ * returned.
+ */
+u32 axi_core_cflags(struct axi_core *core, u32 mask, u32 val);
+/**
+ * axi_core_sflags - set core status flags.
+ * @core: &struct axi_core pointer to core of interest.
+ * @mask: mask indicating the bits to clear.
+ * @val: value with bits to set. bits must be within mask.
+ *
+ * Set I/O status flags for the given core. The function returns
+ * the resulting value of the status flags. When called with with
+ * mask and val parameters being 0 the current status flags are
+ * returned.
+ */
+u32 axi_core_sflags(struct axi_core *core, u32 mask, u32 val);
+
+#endif /* AXI_AMBA_H_ */
diff --git a/include/brcmaxi/axi.h b/include/brcmaxi/axi.h
new file mode 100644
index 0000000..f470312
--- /dev/null
+++ b/include/brcmaxi/axi.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef AXI_H_
+#define AXI_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/**
+ * DOC: Introduction
+ *
+ * brcmaxi provides detection of chip cores in chipsets using the AMBA AXI
+ * on-chip interconnect. It also provides basic functions to operate these
+ * cores and obtain/modify common core control and status flags.
+ */
+/**
+ * DOC: Host Interface Support
+ *
+ * The module provides two selectable intefaces. Direct access and by means
+ * of PCI host interface. For access by PCI bus you should use function prefixed
+ * by pci_ instead.
+ */
+/**
+ * DOC: Chip System Discovery
+ *
+ * The discovery of cores in the chip is done parsing through an enumeration
+ * rom located on the chip. After using the @axi_open() function by which the
+ * calling code provides the type of bus present between calling code and the
+ * enumeration rom, physical base address of the enumeration rom and virtual
+ * address of currently mapped memory, the calling code needs to provide a
+ * table of handlers using the macro @AXI_SET_HANDLERS. The argument should
+ * be declared using the macro @AXI_CORE_HANDLER_TABLE. The actual scan is
+ * initiated by calling @axi_scan().
+ *
+ * The user-provided handlers are called for each core that matches.
+ *
+ * NOTE: currently matching is only based on manufacturer and/or core ID.
+ */
+/**
+ * DOC: Core Utility Functions
+ *
+ * When accessing the cores directly over the AMBA AXI backplane the function
+ * with axi_core_ prefix should be used providing the core instance on which
+ * you want to perform the given function. For accessing the cores over a PCI
+ * interface you should use the pci_axi_core_ functions, which are operating on
+ * an active core. This is selected by using @pci_axi_set_active_core(). Before
+ * calling this function the calling code must assure that interrupts from the
+ * currently active core are disabled.
+ *
+ * The mechanism for PCI is needed as for this interface the BAR register window
+ * is changed and the virtual addresses for accessing the cores is the same for
+ * each core.
+ */
+/*
+ * Manufacturer Ids
+ */
+#define	MFGID_ARM			0x43b
+#define	MFGID_BRCM			0x4bf
+#define	MFGID_MIPS			0x4a7
+
+/*
+ * Component Classes
+ *
+ * This is used to have a more specific core identification.
+ */
+#define	CC_SIM				0
+#define	CC_EROM				1
+#define	CC_CORESIGHT			9
+#define	CC_VERIF			0xb
+#define	CC_OPTIMO			0xd
+#define	CC_GEN				0xe
+#define	CC_PRIMECELL			0xf
+
+/* Core Codes */
+#define	NODEV_CORE_ID		0x700	/* Invalid coreid */
+#define	CC_CORE_ID		0x800	/* chipcommon core */
+#define	ILINE20_CORE_ID		0x801	/* iline20 core */
+#define	SRAM_CORE_ID		0x802	/* sram core */
+#define	SDRAM_CORE_ID		0x803	/* sdram core */
+#define	PCI_CORE_ID		0x804	/* pci core */
+#define	MIPS_CORE_ID		0x805	/* mips core */
+#define	ENET_CORE_ID		0x806	/* enet mac core */
+#define	CODEC_CORE_ID		0x807	/* v90 codec core */
+#define	USB_CORE_ID		0x808	/* usb 1.1 host/device core */
+#define	ADSL_CORE_ID		0x809	/* ADSL core */
+#define	ILINE100_CORE_ID	0x80a	/* iline100 core */
+#define	IPSEC_CORE_ID		0x80b	/* ipsec core */
+#define	UTOPIA_CORE_ID		0x80c	/* utopia core */
+#define	PCMCIA_CORE_ID		0x80d	/* pcmcia core */
+#define	SOCRAM_CORE_ID		0x80e	/* internal memory core */
+#define	MEMC_CORE_ID		0x80f	/* memc sdram core */
+#define	OFDM_CORE_ID		0x810	/* OFDM phy core */
+#define	EXTIF_CORE_ID		0x811	/* external interface core */
+#define	D11_CORE_ID		0x812	/* 802.11 MAC core */
+#define	APHY_CORE_ID		0x813	/* 802.11a phy core */
+#define	BPHY_CORE_ID		0x814	/* 802.11b phy core */
+#define	GPHY_CORE_ID		0x815	/* 802.11g phy core */
+#define	MIPS33_CORE_ID		0x816	/* mips3302 core */
+#define	USB11H_CORE_ID		0x817	/* usb 1.1 host core */
+#define	USB11D_CORE_ID		0x818	/* usb 1.1 device core */
+#define	USB20H_CORE_ID		0x819	/* usb 2.0 host core */
+#define	USB20D_CORE_ID		0x81a	/* usb 2.0 device core */
+#define	SDIOH_CORE_ID		0x81b	/* sdio host core */
+#define	ROBO_CORE_ID		0x81c	/* roboswitch core */
+#define	ATA100_CORE_ID		0x81d	/* parallel ATA core */
+#define	SATAXOR_CORE_ID		0x81e	/* serial ATA & XOR DMA core */
+#define	GIGETH_CORE_ID		0x81f	/* gigabit ethernet core */
+#define	PCIE_CORE_ID		0x820	/* pci express core */
+#define	NPHY_CORE_ID		0x821	/* 802.11n 2x2 phy core */
+#define	SRAMC_CORE_ID		0x822	/* SRAM controller core */
+#define	MINIMAC_CORE_ID		0x823	/* MINI MAC/phy core */
+#define	ARM11_CORE_ID		0x824	/* ARM 1176 core */
+#define	ARM7S_CORE_ID		0x825	/* ARM7tdmi-s core */
+#define	LPPHY_CORE_ID		0x826	/* 802.11a/b/g phy core */
+#define	PMU_CORE_ID		0x827	/* PMU core */
+#define	SSNPHY_CORE_ID		0x828	/* 802.11n single-stream phy core */
+#define	SDIOD_CORE_ID		0x829	/* SDIO device core */
+#define	ARMCM3_CORE_ID		0x82a	/* ARM Cortex M3 core */
+#define	HTPHY_CORE_ID		0x82b	/* 802.11n 4x4 phy core */
+#define	MIPS74K_CORE_ID		0x82c	/* mips 74k core */
+#define	GMAC_CORE_ID		0x82d	/* Gigabit MAC core */
+#define	DMEMC_CORE_ID		0x82e	/* DDR1/2 memory controller core */
+#define	PCIERC_CORE_ID		0x82f	/* PCIE Root Complex core */
+#define	OCP_CORE_ID		0x830	/* OCP2OCP bridge core */
+#define	SC_CORE_ID		0x831	/* shared common core */
+#define	AHB_CORE_ID		0x832	/* OCP2AHB bridge core */
+#define	SPIH_CORE_ID		0x833	/* SPI host core */
+#define	I2S_CORE_ID		0x834	/* I2S core */
+#define	DMEMS_CORE_ID		0x835	/* SDR/DDR1 memory controller core */
+#define	DEF_SHIM_COMP		0x837	/* SHIM component in ubus/6362 */
+#define OOB_ROUTER_CORE_ID	0x367	/* OOB router core ID */
+#define	DEF_AI_COMP		0xfff	/* Default component, in ai chips it
+					 * maps all unused address ranges
+					 */
+
+#define AXI_CORE_SIZE		0x1000	/* each core has 4Kbytes registers */
+
+/* match for all values */
+#define AXI_ANY_ID		(~0)
+
+/*
+ * Common core control flags
+ *
+ * used in axi_core_cflags().
+ */
+#define	SICF_BIST_EN		0x8000
+#define	SICF_PME_EN		0x4000
+#define	SICF_CORE_BITS		0x3ffc
+#define	SICF_FGC		0x0002
+#define	SICF_CLOCK_EN		0x0001
+
+/*
+ * Common core status flags
+ *
+ * used in axi_core_sflags().
+ */
+#define	SISF_BIST_DONE		0x8000
+#define	SISF_BIST_ERROR		0x4000
+#define	SISF_GATED_CLK		0x2000
+#define	SISF_DMA64		0x1000
+#define	SISF_CORE_BITS		0x0fff
+
+/**
+ * struct axi_core - core information
+ * @mfg: manufacturer identifier (JEDEC JEP106).
+ * @id: component identifier (manufacturer assigned).
+ * @rev: core revision.
+ * @phys_address: physical backplane address.
+ * @phys_space: size of the area starting at phys_address.
+ * @sec_phys_address: physical backplane address of 2nd register set.
+ * @sec_phys_space: size of the area starting at sec_phys_address.
+ * @wrap_phys_address: physical backplane address of DMP wrapper registers.
+ * @regs: virtual address of mapped phys_address.
+ * @wrap: virtual address of mapped wrap_phys_address.
+ *
+ * The Manufacturer identifier is maintained by JEDEC. For more info refer to
+ * following webpage infocenter.arm.com/help/topic/com.arm.doc.faqs/ka14408.html
+ */
+struct axi_core {
+	u32	mfg;
+	u32	id;
+	u32	rev;
+	u32	phys_address;
+	u32	phys_space;
+	u32	sec_phys_address;
+	u32	sec_phys_space;
+	u32	wrap_phys_address;
+
+	void	*regs;
+	void	*wrap;
+};
+
+/*
+ * forward declaration for handler in axi_core_handler structure.
+ */
+struct axi_instance;
+
+/**
+ * struct axi_core_handler - associates a core with handler callback function
+ * @handler: callback function called for matching core.
+ * @mfg_id: manufacturer identifier of the core.
+ * @core_id: core identifier of the core.
+ * @core_class: component class of the core.
+ *
+ * The structure is to be used by the calling driver to provide a table
+ * of cores which is to be used during the AXI core scan. It is preferred
+ * to use the AXI_CORE_* macros and AXI_SET_CORE_HANDLERS macro.
+ */
+struct axi_core_handler {
+	bool (*handler)(struct axi_instance *ai, struct axi_core *core);
+	u32 mfg_id;
+	u32 core_id;
+	u32 core_class;
+};
+
+/*
+ * example:
+ *
+ * AXI_CORE_HANDLER_TABLE(drv_table) = {
+ * 	{ AXI_CORE(MFGID_MIPS, MIPS74K_CORE_ID, mips74k_handler) },
+ * 	{ AXI_CORE(MFGID_BRCM, D11_CORE_ID, brcm80211_d11core) },
+ * 	{ AXI_CORE(AXI_ANY_ID, AXI_ANY_ID, debug_axi_handler) }
+ * };
+ * The last entry uses the AXI_ANY_ID. The core matching function
+ * will iterate in sequence through the table so any entries after
+ * this one will be rendered useless.
+ */
+#define AXI_CORE_HANDLER_TABLE(_table) \
+	static const struct axi_core_handler _table[]
+
+#define AXI_CORE(mfg, core, _handler) \
+	.handler = (_handler), .core_id = (core), \
+	.mfg_id = (mfg), .core_class = AXI_ANY_ID
+
+#define AXI_CORE_CLASS(mfg, core, _class, _handler) \
+	.handler = (_handler), .core_id = (core) \
+	.mfg_id = (mfg), .core_class = (_class)
+
+#define AXI_SET_CORE_HANDLERS(aih, _table) \
+	axi_set_core_handlers((aih), ARRAY_SIZE(_table), _table)
+
+/**
+ * struct axi_instance - instance data
+ * @pbus: bus access object (ie. struct pci_dev pointer for PCI bus).
+ * @regs: currently mapped register space.
+ * @handler_list: list of handlers for detected cores during axi_scan().
+ * @num_handler: number of handler entries in the handler_list.
+ * @priv: pointer to memory space that can be used by calling driver.
+ */
+struct axi_instance {
+	const struct axi_core_handler *handler_list;
+	size_t num_handler;
+	void *regs;
+#ifdef CONFIG_BRCMAXI_PCI
+	void *pbus;
+#endif
+	void *priv;
+};
+
+/**
+ * axi_set_core_handlers - sets table of handler used in axi_scan()
+ * @aih: &struct axi_instance pointer to instance data.
+ * @n_handler: number of entries in the given handler list.
+ * @list: &struct axi_core_handler pointer to list of handlers.
+ *
+ * Instead of calling this function directly it is recommended to
+ * use the macro AXI_SET_CORE_HANDLERS.
+ */
+static inline void axi_set_core_handlers(struct axi_instance *aih,
+					 size_t n_handler,
+					 const struct axi_core_handler *list)
+{
+	aih->num_handler = n_handler;
+	aih->handler_list = list;
+}
+
+/**
+ * axi_close - release the instance.
+ * @aih: &struct axi_instance pointer to the instance.
+ */
+void axi_close(struct axi_instance *aih);
+/**
+ * axi_scan - scan the chipset for cores.
+ * @aih: &struct axi_instance pointer to the instance.
+ */
+int axi_scan(struct axi_instance *aih);
+
+#ifdef CONFIG_BRCMAXI_AMBA
+#include "amba.h"
+#endif
+#ifdef CONFIG_BRCMAXI_PCI
+#include "pci.h"
+#endif
+
+#endif /* AXI_H_ */
diff --git a/include/brcmaxi/pci.h b/include/brcmaxi/pci.h
new file mode 100644
index 0000000..76d81b8
--- /dev/null
+++ b/include/brcmaxi/pci.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef AXI_PCI_H_
+#define AXI_PCI_H_
+
+/**
+ * pci_axi_open - create instance.
+ * @pbus: pointer to bus device structure.
+ * @regs: pointer to currently mapped register area.
+ * @erom_base: physical address where core enumeration rom is located.
+ * @priv_size: additional memory appended to instance for caller to use.
+ *
+ * Creates the instance filling in the provided details.
+ */
+struct axi_instance *pci_axi_open(void *pbus, void *regs,
+				  u32 erom_base, u32 priv_size);
+/**
+ * pci_axi_close - wrapper for @axi_close()
+ * @inst: &struct axi_instance pointer to the instance.
+ *
+ * Just to keep the same naming convention.
+ */
+static inline void pci_axi_close(struct axi_instance *inst)
+{
+	axi_close(inst);
+}
+/**
+ * axi_set_active_core - activate given core.
+ * @aih: &struct axi_instance pointer to the instance.
+ * @ach: pointer to core to be activated.
+ *
+ * Activating a core will have the other operations
+ * be acted upon the core activated here.
+ */
+void *pci_axi_set_active_core(struct axi_instance *aih, struct axi_core *ach);
+/**
+ * axi_iscoreup - indicates core is reset and enabled.
+ * @aih: &struct axi_instance pointer to the instance.
+ *
+ * Indicates whether the active core has reset and is enabled.
+ * Active core is set using @axi_set_active_core().
+ */
+bool pci_axi_iscoreup(struct axi_instance *aih);
+/**
+ * axi_core_disable - disable the core.
+ * @aih: &struct axi_instance pointer to the instance.
+ * @bits: core specific bits that are set during reset sequence.
+ *
+ * Disables the active core by reset. This will bring the core in
+ * the disabled state. Initialization is required to enable it again.
+ * Active core is set using @axi_set_active_core().
+ */
+void pci_axi_core_disable(struct axi_instance *aih, u32 bits);
+/**
+ * axi_core_reset - reset and enable the core.
+ * @aih: &struct axi_instance pointer to the instance.
+ * @bits: core specific bits that are set during and after the reset sequence.
+ * @resetbits: core specific bits that are set only during reset sequence.
+ *
+ * Resets and enables the active core. Active core is set
+ * using @axi_set_active_core().
+ */
+void pci_axi_core_reset(struct axi_instance *aih, u32 bits, u32 resetbits);
+/**
+ * axi_flag - get axi flag.
+ * @aih: &struct axi_instance pointer to the instance.
+ *
+ * Retrieves the axi flag for the active core. Active core is set
+ * using @axi_set_active_core().
+ */
+uint pci_axi_flag(struct axi_instance *aih);
+/**
+ * axi_core_cflags - set core control flags.
+ * @aih: &struct axi_instance pointer to the instance.
+ * @mask: mask indicating the bits to clear.
+ * @val: value with bits to set. bits must be within mask.
+ *
+ * Set I/O control flags for the active core. Active core is set
+ * using @axi_set_active_core(). The function returns the resulting
+ * value of the control flags. When called with with mask and val
+ * parameters being 0 the current control flags are returned.
+ */
+u32 pci_axi_core_cflags(struct axi_instance *aih, u32 mask, u32 val);
+/**
+ * axi_core_sflags - set core status flags.
+ * @aih: &struct axi_instance pointer to the instance.
+ * @mask: mask indicating the bits to clear.
+ * @val: value with bits to set. bits must be within mask.
+ *
+ * Set I/O status flags for the active core. Active core is set
+ * using @axi_set_active_core(). The function returns the resulting
+ * value of the status flags. When called with with mask and val
+ * parameters being 0 the current status flags are returned.
+ */
+u32 pci_axi_core_sflags(struct axi_instance *aih, u32 mask, u32 val);
+
+#endif /* AXI_PCI_H_ */
-- 
1.7.1



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-29  9:40 ` [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module Arend van Spriel
@ 2011-03-29 10:45   ` Jiri Slaby
  2011-03-30 12:53     ` Arnd Bergmann
  0 siblings, 1 reply; 19+ messages in thread
From: Jiri Slaby @ 2011-03-29 10:45 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: linux-kernel, akpm, rmk+kernel, devel, gregkh, linux-wireless,
	Jiri Slaby

On 03/29/2011 11:40 AM, Arend van Spriel wrote:
> --- /dev/null
> +++ b/drivers/brcmaxi/axi.c
> @@ -0,0 +1,786 @@
...
> +/* resetctrl */
> +#define	AIRC_RESET		1
> +
> +/* definition for specifying padding fields */
> +#define	_PADLINE(line)	pad ## line
> +#define	_XSTR(line)	_PADLINE(line)
> +#define	PAD		_XSTR(__LINE__)
> +
> +/*
> + * struct aidmp - device management plugin "wrapper" registers.
> + */
> +struct aidmp {

This looks like it should be __packed__.

> +	u32 oobselina30;	/* 0x000 */
> +	u32 oobselina74;	/* 0x004 */
> +	u32 PAD[6];
...
> +};
...
> +struct axi_local *axi_create(u32 priv_len)
> +{
> +	struct axi_local *inst;
> +	int size = ALIGN(sizeof(*inst), 4) + priv_len;
> +
> +	inst = kzalloc(size, GFP_ATOMIC);

Hmm, ATOMIC without checking the retval. This is prepared for its first
crash under a high memory pressure.

> +	try_module_get(THIS_MODULE);
> +
> +	return inst;
> +}
> +struct axi_instance *axi_open(void *regs, u32 erombase, u32 priv_len)
> +{
> +	struct axi_local *inst = axi_create(priv_len);
> +
> +	/* fill public fields */
> +	inst->pub.regs = regs;
> +	inst->pub.priv = (char *)inst + ALIGN(sizeof(*inst), 4);
> +
> +	inst->enum_rom_ptr = ioremap_nocache((unsigned long)erombase,
> +					     AXI_CORE_SIZE);

Check retval.

> +	return &inst->pub;
> +}
...

regards,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
  2011-03-29  9:40 ` [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module Arend van Spriel
@ 2011-03-29 13:14 ` Greg KH
  2011-03-29 18:19 ` Russell King
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 19+ messages in thread
From: Greg KH @ 2011-03-29 13:14 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-kernel, akpm, rmk+kernel, linux-wireless, devel

On Tue, Mar 29, 2011 at 11:40:18AM +0200, Arend van Spriel wrote:
> GUIDANCE NEEDED:
> This patch puts the module at proposed location. Please provide your
> guidance if there is a better location within the linux tree for this
> module.
> 
> This module has been isolated from the brcm80211 driver currently
> located in staging and provided to other drivers for chipsets using
> the AMBA AXI on-chip interconnect with ARM Device Management Plugin
> (DMP) silicon IP, which provides system discovery (chip being the
> system) and basic core function (disable, reset, etc.).
> 
> The module has previously been posted on the linux-wireless list and
> comments by Randy Dunlap have been taken in. Also the SubmitChecklist
> has been followed.
> 
> Arend van Spriel (1):
>   drivers: brcmaxi: provide amba axi functionality in separate module
> 
>  drivers/Kconfig            |    2 +
>  drivers/Makefile           |    1 +
>  drivers/brcmaxi/Kconfig    |   23 ++

I thought this was going under drivers/staging/  What changed your mind?
What other drivers are going to use this, I thought the current broadcom
drivers in drivers/net/wireless were not going to need this.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
  2011-03-29  9:40 ` [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module Arend van Spriel
  2011-03-29 13:14 ` [PATCH 0/1] new module for amba axi on-chip interconnect Greg KH
@ 2011-03-29 18:19 ` Russell King
  2011-03-30 13:09   ` Arnd Bergmann
  2011-03-29 18:30 ` Christoph Hellwig
  2011-03-29 18:40 ` Russell King
  4 siblings, 1 reply; 19+ messages in thread
From: Russell King @ 2011-03-29 18:19 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-kernel, akpm, gregkh, linux-wireless, devel

On Tue, Mar 29, 2011 at 11:40:18AM +0200, Arend van Spriel wrote:
> GUIDANCE NEEDED:
> This patch puts the module at proposed location. Please provide your
> guidance if there is a better location within the linux tree for this
> module.
> 
> This module has been isolated from the brcm80211 driver currently
> located in staging and provided to other drivers for chipsets using
> the AMBA AXI on-chip interconnect with ARM Device Management Plugin
> (DMP) silicon IP, which provides system discovery (chip being the
> system) and basic core function (disable, reset, etc.).

What does this do which the 'amba' bus support doesn't?

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
                   ` (2 preceding siblings ...)
  2011-03-29 18:19 ` Russell King
@ 2011-03-29 18:30 ` Christoph Hellwig
  2011-03-29 18:40 ` Russell King
  4 siblings, 0 replies; 19+ messages in thread
From: Christoph Hellwig @ 2011-03-29 18:30 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: linux-kernel, akpm, rmk+kernel, gregkh, linux-wireless, devel

On Tue, Mar 29, 2011 at 11:40:18AM +0200, Arend van Spriel wrote:
> GUIDANCE NEEDED:
> This patch puts the module at proposed location. Please provide your
> guidance if there is a better location within the linux tree for this
> module.
> 
> This module has been isolated from the brcm80211 driver currently
> located in staging and provided to other drivers for chipsets using
> the AMBA AXI on-chip interconnect with ARM Device Management Plugin
> (DMP) silicon IP, which provides system discovery (chip being the
> system) and basic core function (disable, reset, etc.).

Any reason this is not integrated with drivers/amba?


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
                   ` (3 preceding siblings ...)
  2011-03-29 18:30 ` Christoph Hellwig
@ 2011-03-29 18:40 ` Russell King
  4 siblings, 0 replies; 19+ messages in thread
From: Russell King @ 2011-03-29 18:40 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-kernel, akpm, gregkh, linux-wireless, devel

On Tue, Mar 29, 2011 at 11:40:18AM +0200, Arend van Spriel wrote:
> GUIDANCE NEEDED:
> This patch puts the module at proposed location. Please provide your
> guidance if there is a better location within the linux tree for this
> module.
> 
> This module has been isolated from the brcm80211 driver currently
> located in staging and provided to other drivers for chipsets using
> the AMBA AXI on-chip interconnect with ARM Device Management Plugin
> (DMP) silicon IP, which provides system discovery (chip being the
> system) and basic core function (disable, reset, etc.).

Second point is this series has not been copied to the ARM mailing
lists, so almost no one there has any clue that this is being proposed.
Please post it to the ARM kernel mailing list so that all interested
parties can review it, along with an explaination about why the existing
AMBA primecell support can't be augmented to provide whatever functionality
you require.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-29 10:45   ` Jiri Slaby
@ 2011-03-30 12:53     ` Arnd Bergmann
  2011-03-31 13:48       ` Jiri Slaby
  0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2011-03-30 12:53 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Arend van Spriel, linux-kernel, akpm, rmk+kernel, devel, gregkh,
	linux-wireless, Jiri Slaby

On Tuesday 29 March 2011, Jiri Slaby wrote:
> On 03/29/2011 11:40 AM, Arend van Spriel wrote:
> > --- /dev/null
> > +++ b/drivers/brcmaxi/axi.c
> > @@ -0,0 +1,786 @@
> ...
> > +/* resetctrl */
> > +#define	AIRC_RESET		1
> > +
> > +/* definition for specifying padding fields */
> > +#define	_PADLINE(line)	pad ## line
> > +#define	_XSTR(line)	_PADLINE(line)
> > +#define	PAD		_XSTR(__LINE__)
> > +
> > +/*
> > + * struct aidmp - device management plugin "wrapper" registers.
> > + */
> > +struct aidmp {
> 
> This looks like it should be __packed__.

Why that? Adding the packed attribute would enforce byte access but
not change the layout of the structure, so I think that would make
it worse not better.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-29 18:19 ` Russell King
@ 2011-03-30 13:09   ` Arnd Bergmann
  2011-03-30 17:40     ` Russell King - ARM Linux
  0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2011-03-30 13:09 UTC (permalink / raw)
  To: Russell King
  Cc: Arend van Spriel, linux-kernel, akpm, gregkh, linux-wireless,
	devel, linux-arm-kernel

On Tuesday 29 March 2011, Russell King wrote:
> On Tue, Mar 29, 2011 at 11:40:18AM +0200, Arend van Spriel wrote:
> > GUIDANCE NEEDED:
> > This patch puts the module at proposed location. Please provide your
> > guidance if there is a better location within the linux tree for this
> > module.
> > 
> > This module has been isolated from the brcm80211 driver currently
> > located in staging and provided to other drivers for chipsets using
> > the AMBA AXI on-chip interconnect with ARM Device Management Plugin
> > (DMP) silicon IP, which provides system discovery (chip being the
> > system) and basic core function (disable, reset, etc.).
> 
> What does this do which the 'amba' bus support doesn't?

I believe the one thing we really want from this driver is the bus
scan code, which is not present in the amba bus implementation,
as far as I can tell. Today, the amba bus does very little beyond
what the platform bus does, in particular you still need to
register every single device from board specific code.

When the proposed axi_scan() function gets turned into an
amba_bus_register() function, a board file can call that to
add all devices on the bus without listing them individually
and calling amba_device_register() for each one.

Basically everything else is already there in the amba bus,
no need to do it again.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-30 13:09   ` Arnd Bergmann
@ 2011-03-30 17:40     ` Russell King - ARM Linux
  2011-03-30 18:24       ` Arnd Bergmann
  0 siblings, 1 reply; 19+ messages in thread
From: Russell King - ARM Linux @ 2011-03-30 17:40 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arend van Spriel, linux-kernel, akpm, gregkh, linux-wireless,
	devel, linux-arm-kernel

On Wed, Mar 30, 2011 at 03:09:04PM +0200, Arnd Bergmann wrote:
> I believe the one thing we really want from this driver is the bus
> scan code, which is not present in the amba bus implementation,
> as far as I can tell. Today, the amba bus does very little beyond
> what the platform bus does, in particular you still need to
> register every single device from board specific code.
> 
> When the proposed axi_scan() function gets turned into an
> amba_bus_register() function, a board file can call that to
> add all devices on the bus without listing them individually
> and calling amba_device_register() for each one.
> 
> Basically everything else is already there in the amba bus,
> no need to do it again.

The reason we don't do automatic scanning (which we could on the various
ARM platforms) is because of the platform data necessary to make some of
the primecell drivers work.

Unfortunately, these buses are not as simple as PCI, where a device
typically sits on its own card and is totally self-contained.  With
primecell stuff, there's normally some interdependencies between the
various primecells.

That doesn't stop there being an automatic enumeration layer, but such
a layer would need some way of attaching platform specific data to
specific amba devices.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-30 17:40     ` Russell King - ARM Linux
@ 2011-03-30 18:24       ` Arnd Bergmann
  2011-03-30 19:08         ` Russell King - ARM Linux
  0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2011-03-30 18:24 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Russell King - ARM Linux, gregkh, linux-wireless, linux-kernel,
	Arend van Spriel, devel, akpm

On Wednesday 30 March 2011 19:40:10 Russell King - ARM Linux wrote:

> The reason we don't do automatic scanning (which we could on the various
> ARM platforms) is because of the platform data necessary to make some of
> the primecell drivers work.
> 
> Unfortunately, these buses are not as simple as PCI, where a device
> typically sits on its own card and is totally self-contained.  With
> primecell stuff, there's normally some interdependencies between the
> various primecells.
> 
> That doesn't stop there being an automatic enumeration layer, but such
> a layer would need some way of attaching platform specific data to
> specific amba devices.

Right, I understand that this would not completely remove the need for
platform devices, but I think it would be a great step in the right
direction if we could scan all simple devices automatically, or
possibly even all devices in some simple machines.

If we can scan the main resources (memory ranges, interrupts, ...),
that will make it possible to avoid a whole lot of the stuff we currently
do for each new board. It also means we can gradually move away from
statically defined devices, something that Greg has been pushing for
quite some time.

The device tree work has shown that it's possible to describe very
complex hardware in simple data structures, but it would be much
better if we needed neither a device tree nor a board file for this.
As you say, this isn't possible today with the data on available
to the AMBA bus, but I think it would be better to just fill in 
the blanks (and corrections where they are wrong) than to duplicate
all of it as we now do in the kernel.

Ideally, we would point SoC companies to this (or a future extended
version) as the place to add all the required information when
they want the drivers to work out of the box. My impression is that
there is no fundamental difference to buses like PCI or USB, other
than that there is more data required to encode and that there is
a lack of social pressure to get it right. I remember PCI cards
from the 1990s that could not be probed properly and required
setting a lot of module parameters copied from a web site depending
on what hardware you had bought. The reason we don't have that 
as much today is that the manufacturers realized that it's impossible
to write proper drivers if you cannot detect the hardware.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-30 18:24       ` Arnd Bergmann
@ 2011-03-30 19:08         ` Russell King - ARM Linux
  2011-04-01 15:40           ` Arnd Bergmann
  0 siblings, 1 reply; 19+ messages in thread
From: Russell King - ARM Linux @ 2011-03-30 19:08 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, gregkh, linux-wireless, linux-kernel,
	Arend van Spriel, devel, akpm

On Wed, Mar 30, 2011 at 08:24:49PM +0200, Arnd Bergmann wrote:
> On Wednesday 30 March 2011 19:40:10 Russell King - ARM Linux wrote:
> 
> > The reason we don't do automatic scanning (which we could on the various
> > ARM platforms) is because of the platform data necessary to make some of
> > the primecell drivers work.
> > 
> > Unfortunately, these buses are not as simple as PCI, where a device
> > typically sits on its own card and is totally self-contained.  With
> > primecell stuff, there's normally some interdependencies between the
> > various primecells.
> > 
> > That doesn't stop there being an automatic enumeration layer, but such
> > a layer would need some way of attaching platform specific data to
> > specific amba devices.
> 
> Right, I understand that this would not completely remove the need for
> platform devices, but I think it would be a great step in the right
> direction if we could scan all simple devices automatically, or
> possibly even all devices in some simple machines.

I'm not talking about platform devices at all.  I'm talking about the data
which platforms need to supply to their drivers in order for the drivers
to work.

Eg, how the DMA is connected (or indeed whether the DMA signals are even
connected in the first place).  Where the card detect signal is for the
MMC slot for the particular controller we've found, etc.

It's not as simple as (eg) detecting a MMC controller and immediately
pointing it at the GPIO number - the "simple" ARM dev platforms normally
have two MMC controllers so that needs to be distinguished.

This kind of data is precisely why I went down the static declaration
route for all ARM dev platforms, despite most devices being trivially
discoverable.  I couldn't work out a decent way to automatically scan
the devices while ensuring that the right platform specific driver data
was attached to its correct device.

> The device tree work has shown that it's possible to describe very
> complex hardware in simple data structures, but it would be much
> better if we needed neither a device tree nor a board file for this.

The device tree goes against automatic device discovery - unless you
have a shim which runs before the kernel executes to adjust the device
tree appropriately.  Otherwise, I can't see anyway you could cope with
(eg) a platform having MMC controllers at 0x10004000 and 0x10008000,
and another with just one MMC controller at 0x10008000 but using the
card detect lines from 0x10004000.

> I remember PCI cards
> from the 1990s that could not be probed properly and required
> setting a lot of module parameters copied from a web site depending
> on what hardware you had bought. The reason we don't have that 
> as much today is that the manufacturers realized that it's impossible
> to write proper drivers if you cannot detect the hardware.

I think you're going to be waiting a very long time for that to happen.
No SoC vendor adds device IDs to their on-chip devices to allow them to
be automatically discovered - it's only through ARM Ltd's development of
their Primecells, and then vendors integrating those into their SoC (maybe
with their own modifications) that we've started to see this kind of ID
system appearing.

Outside of the Primecell stuff, I'm unaware of anyone adding any kind
of discovery mechanism to SoC based devices.

So, all in all I don't think that the automatic discovery idea is worth
the effort.  All that I can see is it causing lots of problems.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-30 12:53     ` Arnd Bergmann
@ 2011-03-31 13:48       ` Jiri Slaby
  2011-03-31 13:51         ` Russell King
  0 siblings, 1 reply; 19+ messages in thread
From: Jiri Slaby @ 2011-03-31 13:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arend van Spriel, linux-kernel, akpm, rmk+kernel, devel, gregkh,
	linux-wireless, Jiri Slaby

On 03/30/2011 02:53 PM, Arnd Bergmann wrote:
> On Tuesday 29 March 2011, Jiri Slaby wrote:
>> On 03/29/2011 11:40 AM, Arend van Spriel wrote:
>>> --- /dev/null
>>> +++ b/drivers/brcmaxi/axi.c
>>> @@ -0,0 +1,786 @@
>> ...
>>> +/* resetctrl */
>>> +#define	AIRC_RESET		1
>>> +
>>> +/* definition for specifying padding fields */
>>> +#define	_PADLINE(line)	pad ## line
>>> +#define	_XSTR(line)	_PADLINE(line)
>>> +#define	PAD		_XSTR(__LINE__)
>>> +
>>> +/*
>>> + * struct aidmp - device management plugin "wrapper" registers.
>>> + */
>>> +struct aidmp {
>>
>> This looks like it should be __packed__.
> 
> Why that? Adding the packed attribute would enforce byte access but
> not change the layout of the structure, so I think that would make
> it worse not better.

How it can? Packed only tells the compiler to have one byte alignment
steps. And it should not matter here as all the members are 32-bit long.

The structure seems to be something which maps to device registers. So
for documentation purposes it should be packed. And to avoid later
mistakes when the u32 are broken down to u8s and u16s.

regards,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-31 13:48       ` Jiri Slaby
@ 2011-03-31 13:51         ` Russell King
  2011-03-31 14:09           ` Jiri Slaby
  0 siblings, 1 reply; 19+ messages in thread
From: Russell King @ 2011-03-31 13:51 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Arnd Bergmann, Arend van Spriel, linux-kernel, akpm, devel,
	gregkh, linux-wireless, Jiri Slaby

On Thu, Mar 31, 2011 at 03:48:20PM +0200, Jiri Slaby wrote:
> How it can? Packed only tells the compiler to have one byte alignment
> steps. And it should not matter here as all the members are 32-bit long.

It also tells the compiler that it may be misaligned, so to avoid
alignment faults it will use byte loads/stores.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-31 13:51         ` Russell King
@ 2011-03-31 14:09           ` Jiri Slaby
  2011-03-31 14:14             ` Russell King
  0 siblings, 1 reply; 19+ messages in thread
From: Jiri Slaby @ 2011-03-31 14:09 UTC (permalink / raw)
  To: Russell King
  Cc: Arnd Bergmann, Arend van Spriel, linux-kernel, akpm, devel,
	gregkh, linux-wireless, Jiri Slaby

On 03/31/2011 03:51 PM, Russell King wrote:
> On Thu, Mar 31, 2011 at 03:48:20PM +0200, Jiri Slaby wrote:
>> How it can? Packed only tells the compiler to have one byte alignment
>> steps. And it should not matter here as all the members are 32-bit long.
> 
> It also tells the compiler that it may be misaligned, so to avoid
> alignment faults it will use byte loads/stores.

No, it should not (if offsetof % sizeof == 0). Otherwise it's a bug in
the compiler.

Am I missing something?

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-31 14:09           ` Jiri Slaby
@ 2011-03-31 14:14             ` Russell King
  2011-03-31 16:10               ` Jiri Slaby
  0 siblings, 1 reply; 19+ messages in thread
From: Russell King @ 2011-03-31 14:14 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Arnd Bergmann, Arend van Spriel, linux-kernel, akpm, devel,
	gregkh, linux-wireless, Jiri Slaby

On Thu, Mar 31, 2011 at 04:09:32PM +0200, Jiri Slaby wrote:
> On 03/31/2011 03:51 PM, Russell King wrote:
> > On Thu, Mar 31, 2011 at 03:48:20PM +0200, Jiri Slaby wrote:
> >> How it can? Packed only tells the compiler to have one byte alignment
> >> steps. And it should not matter here as all the members are 32-bit long.
> > 
> > It also tells the compiler that it may be misaligned, so to avoid
> > alignment faults it will use byte loads/stores.
> 
> No, it should not (if offsetof % sizeof == 0). Otherwise it's a bug in
> the compiler.
> 
> Am I missing something?

$ cat t1.c
struct foo {
        unsigned long bar;
} __attribute__((packed));

unsigned long baz(struct foo *f)
{
        return f->bar;
}
$ arm-linux-gcc -O2 -S -o - t1.c
...
        .global baz
        .type   baz, %function
baz:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        ldrb    r3, [r0, #0]    @ zero_extendqisi2
        ldrb    r2, [r0, #1]    @ zero_extendqisi2
        ldrb    r1, [r0, #2]    @ zero_extendqisi2
        orr     r3, r3, r2, asl #8
        ldrb    r0, [r0, #3]    @ zero_extendqisi2
        orr     r3, r3, r1, asl #16
        orr     r0, r3, r0, asl #24
        mov     pc, lr
        .size   baz, .-baz
        .ident  "GCC: (GNU) 4.3.5"
        .section        .note.GNU-stack,"",%progbits

It does this because with the packed attribute, it can't make assumptions
about the alignment of 'f'.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-31 14:14             ` Russell King
@ 2011-03-31 16:10               ` Jiri Slaby
  2011-04-01  9:14                 ` Arnd Bergmann
  0 siblings, 1 reply; 19+ messages in thread
From: Jiri Slaby @ 2011-03-31 16:10 UTC (permalink / raw)
  To: Russell King
  Cc: Arnd Bergmann, Arend van Spriel, linux-kernel, akpm, devel,
	gregkh, linux-wireless, Jiri Slaby

On 03/31/2011 04:14 PM, Russell King wrote:
> On Thu, Mar 31, 2011 at 04:09:32PM +0200, Jiri Slaby wrote:
>> On 03/31/2011 03:51 PM, Russell King wrote:
>>> On Thu, Mar 31, 2011 at 03:48:20PM +0200, Jiri Slaby wrote:
>>>> How it can? Packed only tells the compiler to have one byte alignment
>>>> steps. And it should not matter here as all the members are 32-bit long.
>>>
>>> It also tells the compiler that it may be misaligned, so to avoid
>>> alignment faults it will use byte loads/stores.
>>
>> No, it should not (if offsetof % sizeof == 0). Otherwise it's a bug in
>> the compiler.
>>
>> Am I missing something?
> 
> $ cat t1.c
> struct foo {
>         unsigned long bar;
> } __attribute__((packed));
> 
> unsigned long baz(struct foo *f)
> {
>         return f->bar;
> }
> $ arm-linux-gcc -O2 -S -o - t1.c
> ...
>         .global baz
>         .type   baz, %function
> baz:
>         @ args = 0, pretend = 0, frame = 0
>         @ frame_needed = 0, uses_anonymous_args = 0
>         @ link register save eliminated.
>         ldrb    r3, [r0, #0]    @ zero_extendqisi2
>         ldrb    r2, [r0, #1]    @ zero_extendqisi2
>         ldrb    r1, [r0, #2]    @ zero_extendqisi2
>         orr     r3, r3, r2, asl #8
>         ldrb    r0, [r0, #3]    @ zero_extendqisi2
>         orr     r3, r3, r1, asl #16
>         orr     r0, r3, r0, asl #24
>         mov     pc, lr
>         .size   baz, .-baz
>         .ident  "GCC: (GNU) 4.3.5"
>         .section        .note.GNU-stack,"",%progbits
> 
> It does this because with the packed attribute, it can't make assumptions
> about the alignment of 'f'.

I don't see why it couldn't like without the packed attribute. (The
manual says packed attribute for a struct is equivalent to specifying
packed to each member of that struct. It doesn't say anything about the
structure alignment itself.)

Ok, not that I'm fully convinced, but it doesn't matter.

So let's NOT mark it packed.

Anyway the info you sent was useful for me.

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module
  2011-03-31 16:10               ` Jiri Slaby
@ 2011-04-01  9:14                 ` Arnd Bergmann
  0 siblings, 0 replies; 19+ messages in thread
From: Arnd Bergmann @ 2011-04-01  9:14 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Russell King, Arend van Spriel, linux-kernel, akpm, devel, gregkh,
	linux-wireless, Jiri Slaby

On Thursday 31 March 2011, Jiri Slaby wrote:
> I don't see why it couldn't like without the packed attribute. (The
> manual says packed attribute for a struct is equivalent to specifying
> packed to each member of that struct. It doesn't say anything about the
> structure alignment itself.)

To give some more background, any variable that is marked packed is
assumed to be potentially unaligned (byte aligned). If a struct
contains only members with byte alignment, it too is byte aligned.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/1] new module for amba axi on-chip interconnect
  2011-03-30 19:08         ` Russell King - ARM Linux
@ 2011-04-01 15:40           ` Arnd Bergmann
  0 siblings, 0 replies; 19+ messages in thread
From: Arnd Bergmann @ 2011-04-01 15:40 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-arm-kernel, gregkh, linux-wireless, linux-kernel,
	Arend van Spriel, devel, akpm

On Wednesday 30 March 2011, Russell King - ARM Linux wrote:
> On Wed, Mar 30, 2011 at 08:24:49PM +0200, Arnd Bergmann wrote:
> > On Wednesday 30 March 2011 19:40:10 Russell King - ARM Linux wrote:
> > 
> > > The reason we don't do automatic scanning (which we could on the various
> > > ARM platforms) is because of the platform data necessary to make some of
> > > the primecell drivers work.
> > > 
> > > Unfortunately, these buses are not as simple as PCI, where a device
> > > typically sits on its own card and is totally self-contained.  With
> > > primecell stuff, there's normally some interdependencies between the
> > > various primecells.
> > > 
> > > That doesn't stop there being an automatic enumeration layer, but such
> > > a layer would need some way of attaching platform specific data to
> > > specific amba devices.
> > 
> > Right, I understand that this would not completely remove the need for
> > platform devices, but I think it would be a great step in the right
> > direction if we could scan all simple devices automatically, or
> > possibly even all devices in some simple machines.
> 
> I'm not talking about platform devices at all.  I'm talking about the data
> which platforms need to supply to their drivers in order for the drivers
> to work.

Yes, I meant platform_data, not platform_device.

> This kind of data is precisely why I went down the static declaration
> route for all ARM dev platforms, despite most devices being trivially
> discoverable.  I couldn't work out a decent way to automatically scan
> the devices while ensuring that the right platform specific driver data
> was attached to its correct device.

Maybe we can look at this again. The device tree scanning code 
is able to connect properties from the device tree to e.g. PCI
devices that are probed from hardware. It may not be easy to
do, but my feeling is that there is a lot to gain if we manage
to do it.
 
> > The device tree work has shown that it's possible to describe very
> > complex hardware in simple data structures, but it would be much
> > better if we needed neither a device tree nor a board file for this.
> 
> The device tree goes against automatic device discovery - unless you
> have a shim which runs before the kernel executes to adjust the device
> tree appropriately.  Otherwise, I can't see anyway you could cope with
> (eg) a platform having MMC controllers at 0x10004000 and 0x10008000,
> and another with just one MMC controller at 0x10008000 but using the
> card detect lines from 0x10004000.

The device tree is just another way to do automatic device discovery.
Fundamentally there is not much difference between reading data in
a fixed format from a PCI config space, a hardware ROM on AMBA or
a blob passed into the kernel.

The disadvantage of the device tree is that it's harder to get it
to match the actual hardware, while the advantage is that it's
flexible enough to describe the example you just gave.

As I mentioned above, it's possible to describe devices in the
device tree format that are also detected from hardware
scanning, and to combine information from both sources.

If the information in the hardware is complete, as is usually
the case on PCI or USB buses, the device trees we use on other
architectures only list the root node of a bus that gets scanned
in hardware.

> > I remember PCI cards
> > from the 1990s that could not be probed properly and required
> > setting a lot of module parameters copied from a web site depending
> > on what hardware you had bought. The reason we don't have that 
> > as much today is that the manufacturers realized that it's impossible
> > to write proper drivers if you cannot detect the hardware.
> 
> I think you're going to be waiting a very long time for that to happen.
> No SoC vendor adds device IDs to their on-chip devices to allow them to
> be automatically discovered - it's only through ARM Ltd's development of
> their Primecells, and then vendors integrating those into their SoC (maybe
> with their own modifications) that we've started to see this kind of ID
> system appearing.
> 
> Outside of the Primecell stuff, I'm unaware of anyone adding any kind
> of discovery mechanism to SoC based devices.

I'm willing to try to keep pushing for it, once I figure out where ;-)

If we have support for automatic probing of some devices in the kernel,
that might be a way to convince hardware vendors that simply putting
correct information in the hardware can improve their time to market,
which directly translates into money.

	Arnd

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2011-04-01 15:40 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-29  9:40 [PATCH 0/1] new module for amba axi on-chip interconnect Arend van Spriel
2011-03-29  9:40 ` [PATCH 1/1] drivers: brcmaxi: provide amba axi functionality in separate module Arend van Spriel
2011-03-29 10:45   ` Jiri Slaby
2011-03-30 12:53     ` Arnd Bergmann
2011-03-31 13:48       ` Jiri Slaby
2011-03-31 13:51         ` Russell King
2011-03-31 14:09           ` Jiri Slaby
2011-03-31 14:14             ` Russell King
2011-03-31 16:10               ` Jiri Slaby
2011-04-01  9:14                 ` Arnd Bergmann
2011-03-29 13:14 ` [PATCH 0/1] new module for amba axi on-chip interconnect Greg KH
2011-03-29 18:19 ` Russell King
2011-03-30 13:09   ` Arnd Bergmann
2011-03-30 17:40     ` Russell King - ARM Linux
2011-03-30 18:24       ` Arnd Bergmann
2011-03-30 19:08         ` Russell King - ARM Linux
2011-04-01 15:40           ` Arnd Bergmann
2011-03-29 18:30 ` Christoph Hellwig
2011-03-29 18:40 ` Russell King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).