Skip to contentSkip to conversation

Extend various drivers to run on bi-endian BMIPS hosts

PATCH New Kevin Cernekee 5 participants 20 messages Nov 26, 2014 – May 29, 2015

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover Extend various drivers to run on bi-endian BMIPS hosts

This patch series incorporates the following changes:

- Extend brcmstb reset driver to work on MIPS (currently ARM-only).

- Extend brcmstb GISB bus driver to work on MIPS (currently ARM-only).

- Extend brcmstb GISB bus driver to work on BE systems (currently LE-only).

- Extend both drivers to support the older register layouts used on many of the BMIPS platforms.

- Extend {ohci,ehci}-platform drivers to accept the new "native-endian" DT property, to accommodate BCM7xxx platforms that can be switched between LE/BE with a board jumper.

Dependencies:

power/reset: brcmstb: Register with kernel restart handler (Guenter Roeck)
of: Add helper function to check MMIO register endianness (Kevin Cernekee)

These are both tentatively accepted, but might not be present in the same tree yet. As such, we might want to "review now, merge later."

Kevin Cernekee (9):
power/reset: brcmstb: Make the driver buildable on MIPS power/reset: brcmstb: Use the DT "compatible" string to indicate bit
positions
power/reset: brcmstb: Add support for old 65nm chips
bus: brcmstb_gisb: Make the driver buildable on MIPS
bus: brcmstb_gisb: Introduce wrapper functions for MMIO accesses
bus: brcmstb_gisb: Look up register offsets in a table
bus: brcmstb_gisb: Add register offset tables for older chips
bus: brcmstb_gisb: Honor the "big-endian" and "native-endian" DT
properties
usb: {ohci,ehci}-platform: Use new OF big-endian helper function

 .../devicetree/bindings/arm/brcm-brcmstb.txt       |   4 +-
 .../devicetree/bindings/bus/brcm,gisb-arb.txt      |   6 +-
 Documentation/devicetree/bindings/usb/usb-ehci.txt |   2 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt |   2 +
 drivers/bus/Kconfig                                |   2 +-
 drivers/bus/brcmstb_gisb.c                         | 127 ++++++++++++++++++---
 drivers/power/reset/Kconfig                        |   9 +-
 drivers/power/reset/brcmstb-reboot.c               |  41 +++++--
 drivers/usb/host/ehci-platform.c                   |   2 +-
 drivers/usb/host/ohci-platform.c                   |   2 +-
 10 files changed, 161 insertions(+), 36 deletions(-)
Signature · 1 line
2.1.0
#1 lore raw

PATCH 1/9 power/reset: brcmstb: Make the driver buildable on MIPS

Now that the driver doesn't use any ARM-specific headers, it is safe to build on MIPS or with COMPILE_TEST.

---
 drivers/power/reset/Kconfig | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/power/reset/Kconfig +4 -5
index f65ff49..0379846 100644
@@ -39,14 +39,13 @@ config POWER_RESET_AXXIA
 	  Say Y if you have an Axxia family SoC.
 
 config POWER_RESET_BRCMSTB
-	bool "Broadcom STB reset driver" if COMPILE_TEST
-	depends on ARM
+	bool "Broadcom STB reset driver"
+	depends on ARM || MIPS || COMPILE_TEST
 	default ARCH_BRCMSTB
 	help
-	  This driver provides restart support for ARM-based Broadcom STB
-	  boards.
+	  This driver provides restart support for Broadcom STB boards.
 
-	  Say Y here if you have an ARM-based Broadcom STB board and you wish
+	  Say Y here if you have a Broadcom STB board and you wish
 	  to have restart support.
 
 config POWER_RESET_GPIO
Signature · 1 line
2.1.0
maintainer Applied
#2 lore raw

PATCH 1/9 power/reset: brcmstb: Make the driver buildable on MIPS

Hi,

Quoted 2 lines · Kevin Cernekee

Now that the driver doesn't use any ARM-specific headers, it is safe to build on MIPS or with COMPILE_TEST.

Thanks, applied.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150122/8e86ae8d/attachment.sig>

#3 lore raw

PATCH 2/9 power/reset: brcmstb: Use the DT "compatible" string to indicate bit positions

In reply to Kevin Cernekee

Some of the older chips used different bits to arm and trigger the reset. Add the infrastructure needed to specify this through the "compatible" string.

---
 drivers/power/reset/brcmstb-reboot.c | 35 ++++++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)
drivers/power/reset/brcmstb-reboot.c +28 -7
index 3306241..4e61c3f 100644
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -34,13 +35,20 @@ static struct regmap *regmap;
 static u32 rst_src_en;
 static u32 sw_mstr_rst;
 
+struct reset_reg_mask {
+	u32 rst_src_en_mask;
+	u32 sw_mstr_rst_mask;
+};
+
+static const struct reset_reg_mask *reset_masks;
+
 static int brcmstb_restart_handler(struct notifier_block *this,
 				   unsigned long mode, void *cmd)
 {
 	int rc;
 	u32 tmp;
 
-	rc = regmap_write(regmap, rst_src_en, 1);
+	rc = regmap_write(regmap, rst_src_en, reset_masks->rst_src_en_mask);
 	if (rc) {
 		pr_err("failed to write rst_src_en (%d)\n", rc);
 		return NOTIFY_DONE;
@@ -52,7 +60,7 @@ static int brcmstb_restart_handler(struct notifier_block *this,
 		return NOTIFY_DONE;
 	}
 
-	rc = regmap_write(regmap, sw_mstr_rst, 1);
+	rc = regmap_write(regmap, sw_mstr_rst, reset_masks->sw_mstr_rst_mask);
 	if (rc) {
 		pr_err("failed to write sw_mstr_rst (%d)\n", rc);
 		return NOTIFY_DONE;
@@ -75,10 +83,28 @@ static struct notifier_block brcmstb_restart_nb = {
 	.priority = 128,
 };
 
+static const struct reset_reg_mask reset_bits_40nm = {
+	.rst_src_en_mask = BIT(0),
+	.sw_mstr_rst_mask = BIT(0),
+};
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "brcm,brcmstb-reboot", .data = &reset_bits_40nm },
+	{},
+};
+
 static int brcmstb_reboot_probe(struct platform_device *pdev)
 {
 	int rc;
 	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_node(of_match, np);
+	if (!of_id) {
+		pr_err("failed to look up compatible string\n");
+		return -EINVAL;
+	}
+	reset_masks = of_id->data;
 
 	regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
 	if (IS_ERR(regmap)) {
@@ -108,11 +134,6 @@ static int brcmstb_reboot_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id of_match[] = {
-	{ .compatible = "brcm,brcmstb-reboot", },
-	{},
-};
-
 static struct platform_driver brcmstb_reboot_driver = {
 	.probe = brcmstb_reboot_probe,
 	.driver = {
Signature · 1 line
2.1.0
maintainer Applied
#4 lore raw

PATCH 2/9 power/reset: brcmstb: Use the DT "compatible" string to indicate bit positions

Hi,

Quoted 3 lines · Kevin Cernekee

Some of the older chips used different bits to arm and trigger the reset. Add the infrastructure needed to specify this through the "compatible" string.

Thanks, applied.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150122/873c7223/attachment.sig>

#5 lore raw

PATCH 3/9 power/reset: brcmstb: Add support for old 65nm chips

In reply to Kevin Cernekee

The register bit fields are a little different, so add an entry and a compatible string to accommodate them.

---
 Documentation/devicetree/bindings/arm/brcm-brcmstb.txt | 4 +++-
 drivers/power/reset/brcmstb-reboot.c                   | 6 ++++++
 2 files changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/brcm-brcmstb.txt +3 -1
index 3c436cc..430608e 100644
@@ -79,7 +79,9 @@ reboot
 Required properties
 
     - compatible
-        The string property "brcm,brcmstb-reboot".
+        The string property "brcm,brcmstb-reboot" for 40nm/28nm chips with
+        the new SYS_CTRL interface, or "brcm,bcm7038-reboot" for 65nm
+        chips with the old SUN_TOP_CTRL interface.
 
     - syscon
         A phandle / integer array that points to the syscon node which describes
drivers/power/reset/brcmstb-reboot.c +6 -0
index 4e61c3f..33af4f3 100644
@@ -88,8 +88,14 @@ static const struct reset_reg_mask reset_bits_40nm = {
 	.sw_mstr_rst_mask = BIT(0),
 };
 
+static const struct reset_reg_mask reset_bits_65nm = {
+	.rst_src_en_mask = BIT(3),
+	.sw_mstr_rst_mask = BIT(31),
+};
+
 static const struct of_device_id of_match[] = {
 	{ .compatible = "brcm,brcmstb-reboot", .data = &reset_bits_40nm },
+	{ .compatible = "brcm,bcm7038-reboot", .data = &reset_bits_65nm },
 	{},
 };
 
Signature · 1 line
2.1.0
maintainer Applied
#6 lore raw

PATCH 3/9 power/reset: brcmstb: Add support for old 65nm chips

Hi,

Quoted 2 lines · Kevin Cernekee

The register bit fields are a little different, so add an entry and a compatible string to accommodate them.

Thanks, applied.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150122/9864e5db/attachment.sig>

#7 lore raw

PATCH 4/9 bus: brcmstb_gisb: Make the driver buildable on MIPS

In reply to Kevin Cernekee

BCM7xxx ARM and MIPS platforms share a similar hardware block for reporting GISB errors, so they both benefit from the use of this driver. Conditionally compile the ARM-specific bus error handler so that the GISB error IRQ handler works on other architectures.

---
 drivers/bus/Kconfig        | 2 +-
 drivers/bus/brcmstb_gisb.c | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)
drivers/bus/Kconfig +1 -1
index 603eb1b..b99729e 100644
@@ -6,7 +6,7 @@ menu "Bus devices"
 
 config BRCMSTB_GISB_ARB
 	bool "Broadcom STB GISB bus arbiter"
-	depends on ARM
+	depends on ARM || MIPS
 	help
 	  Driver for the Broadcom Set Top Box System-on-a-chip internal bus
 	  arbiter. This driver provides timeout and target abort error handling
drivers/bus/brcmstb_gisb.c +4 -0
index f2cd6a2d..5da935a 100644
@@ -24,8 +24,10 @@
 #include <linux/of.h>
 #include <linux/bitops.h>
 
+#ifdef CONFIG_ARM
 #include <asm/bug.h>
 #include <asm/signal.h>
+#endif
 
 #define ARB_TIMER			0x008
 #define ARB_ERR_CAP_CLR			0x7e4
@@ -141,6 +143,7 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
 	return 0;
 }
 
+#ifdef CONFIG_ARM
 static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
 				     struct pt_regs *regs)
 {
@@ -165,6 +168,7 @@ void __init brcmstb_hook_fault_code(void)
 	hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
 			"imprecise external abort");
 }
+#endif
 
 static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
 {
Signature · 1 line
2.1.0
#8 lore raw

PATCH 5/9 bus: brcmstb_gisb: Introduce wrapper functions for MMIO accesses

In reply to Kevin Cernekee

These will be used to abstract out chip-to-chip differences.

---
 drivers/bus/brcmstb_gisb.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/bus/brcmstb_gisb.c +17 -7
index 5da935a..8ff403d 100644
@@ -54,6 +54,16 @@ struct brcmstb_gisb_arb_device {
 
 static LIST_HEAD(brcmstb_gisb_arb_device_list);
 
+static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
+{
+	return ioread32(gdev->base + reg);
+}
+
+static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
+{
+	iowrite32(val, gdev->base + reg);
+}
+
 static ssize_t gisb_arb_get_timeout(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
@@ -63,7 +73,7 @@ static ssize_t gisb_arb_get_timeout(struct device *dev,
 	u32 timeout;
 
 	mutex_lock(&gdev->lock);
-	timeout = ioread32(gdev->base + ARB_TIMER);
+	timeout = gisb_read(gdev, ARB_TIMER);
 	mutex_unlock(&gdev->lock);
 
 	return sprintf(buf, "%d", timeout);
@@ -85,7 +95,7 @@ static ssize_t gisb_arb_set_timeout(struct device *dev,
 		return -EINVAL;
 
 	mutex_lock(&gdev->lock);
-	iowrite32(val, gdev->base + ARB_TIMER);
+	gisb_write(gdev, val, ARB_TIMER);
 	mutex_unlock(&gdev->lock);
 
 	return count;
@@ -112,18 +122,18 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
 	const char *m_name;
 	char m_fmt[11];
 
-	cap_status = ioread32(gdev->base + ARB_ERR_CAP_STATUS);
+	cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
 
 	/* Invalid captured address, bail out */
 	if (!(cap_status & ARB_ERR_CAP_STATUS_VALID))
 		return 1;
 
 	/* Read the address and master */
-	arb_addr = ioread32(gdev->base + ARB_ERR_CAP_ADDR) & 0xffffffff;
+	arb_addr = gisb_read(gdev, ARB_ERR_CAP_ADDR) & 0xffffffff;
 #if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
-	arb_addr |= (u64)ioread32(gdev->base + ARB_ERR_CAP_HI_ADDR) << 32;
+	arb_addr |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32;
 #endif
-	master = ioread32(gdev->base + ARB_ERR_CAP_MASTER);
+	master = gisb_read(gdev, ARB_ERR_CAP_MASTER);
 
 	m_name = brcmstb_gisb_master_to_str(gdev, master);
 	if (!m_name) {
@@ -138,7 +148,7 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
 		m_name);
 
 	/* clear the GISB error */
-	iowrite32(ARB_ERR_CAP_CLEAR, gdev->base + ARB_ERR_CAP_CLR);
+	gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
 
 	return 0;
 }
Signature · 1 line
2.1.0
#9 lore raw

PATCH 6/9 bus: brcmstb_gisb: Look up register offsets in a table

In reply to Kevin Cernekee

There are at least 4 incompatible variations of this hardware block, so let's use the ARB_* constants as a table index instead of hardcoding specific register offsets. Also, allow for the possibility of adding old devices that are missing some of the registers.

---
 drivers/bus/brcmstb_gisb.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)
drivers/bus/brcmstb_gisb.c +34 -8
index 8ff403d..ef1e423 100644
@@ -29,23 +29,37 @@
 #include <asm/signal.h>
 #endif
 
-#define ARB_TIMER			0x008
-#define ARB_ERR_CAP_CLR			0x7e4
 #define  ARB_ERR_CAP_CLEAR		(1 << 0)
-#define ARB_ERR_CAP_HI_ADDR		0x7e8
-#define ARB_ERR_CAP_ADDR		0x7ec
-#define ARB_ERR_CAP_DATA		0x7f0
-#define ARB_ERR_CAP_STATUS		0x7f4
 #define  ARB_ERR_CAP_STATUS_TIMEOUT	(1 << 12)
 #define  ARB_ERR_CAP_STATUS_TEA		(1 << 11)
 #define  ARB_ERR_CAP_STATUS_BS_SHIFT	(1 << 2)
 #define  ARB_ERR_CAP_STATUS_BS_MASK	0x3c
 #define  ARB_ERR_CAP_STATUS_WRITE	(1 << 1)
 #define  ARB_ERR_CAP_STATUS_VALID	(1 << 0)
-#define ARB_ERR_CAP_MASTER		0x7f8
+
+enum {
+	ARB_TIMER,
+	ARB_ERR_CAP_CLR,
+	ARB_ERR_CAP_HI_ADDR,
+	ARB_ERR_CAP_ADDR,
+	ARB_ERR_CAP_DATA,
+	ARB_ERR_CAP_STATUS,
+	ARB_ERR_CAP_MASTER,
+};
+
+static const int gisb_offsets_bcm7445[] = {
+	[ARB_TIMER]		= 0x008,
+	[ARB_ERR_CAP_CLR]	= 0x7e4,
+	[ARB_ERR_CAP_HI_ADDR]	= 0x7e8,
+	[ARB_ERR_CAP_ADDR]	= 0x7ec,
+	[ARB_ERR_CAP_DATA]	= 0x7f0,
+	[ARB_ERR_CAP_STATUS]	= 0x7f4,
+	[ARB_ERR_CAP_MASTER]	= 0x7f8,
+};
 
 struct brcmstb_gisb_arb_device {
 	void __iomem	*base;
+	const int	*gisb_offsets;
 	struct mutex	lock;
 	struct list_head next;
 	u32 valid_mask;
@@ -56,11 +70,21 @@ static LIST_HEAD(brcmstb_gisb_arb_device_list);
 
 static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
 {
-	return ioread32(gdev->base + reg);
+	int offset = gdev->gisb_offsets[reg];
+
+	/* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */
+	if (offset == -1)
+		return 1;
+
+	return ioread32(gdev->base + offset);
 }
 
 static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
 {
+	int offset = gdev->gisb_offsets[reg];
+
+	if (offset == -1)
+		return;
 	iowrite32(val, gdev->base + reg);
 }
 
@@ -230,6 +254,8 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
 	if (IS_ERR(gdev->base))
 		return PTR_ERR(gdev->base);
 
+	gdev->gisb_offsets = gisb_offsets_bcm7445;
+
 	err = devm_request_irq(&pdev->dev, timeout_irq,
 				brcmstb_gisb_timeout_handler, 0, pdev->name,
 				gdev);
Signature · 1 line
2.1.0
#10 lore raw

PATCH 7/9 bus: brcmstb_gisb: Add register offset tables for older chips

In reply to Kevin Cernekee

This will select the appropriate register layout based on the DT "compatible" string.

---
 .../devicetree/bindings/bus/brcm,gisb-arb.txt      |  6 ++-
 drivers/bus/brcmstb_gisb.c                         | 52 +++++++++++++++++++---
 2 files changed, 51 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt +5 -1
index e2d501d..1eceefb 100644
@@ -2,7 +2,11 @@ Broadcom GISB bus Arbiter controller
 
 Required properties:
 
-- compatible: should be "brcm,gisb-arb"
+- compatible:
+    "brcm,gisb-arb" or "brcm,bcm7445-gisb-arb" for 28nm chips
+    "brcm,bcm7435-gisb-arb" for newer 40nm chips
+    "brcm,bcm7400-gisb-arb" for older 40nm chips and all 65nm chips
+    "brcm,bcm7038-gisb-arb" for 130nm chips
 - reg: specifies the base physical address and size of the registers
 - interrupt-parent: specifies the phandle to the parent interrupt controller
   this arbiter gets interrupt line from
drivers/bus/brcmstb_gisb.c +46 -6

80 lines not on this page · raw message

Signature · 1 line
2.1.0
#11 lore raw

PATCH 8/9 bus: brcmstb_gisb: Honor the "big-endian" and "native-endian" DT properties

In reply to Kevin Cernekee

On chips strapped for BE, we'll need to use ioread32be/iowrite32be instead of ioread32/iowrite32.

---
 drivers/bus/brcmstb_gisb.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/bus/brcmstb_gisb.c +11 -2
index 172908d..969b992 100644
@@ -90,6 +90,7 @@ static const int gisb_offsets_bcm7445[] = {
 struct brcmstb_gisb_arb_device {
 	void __iomem	*base;
 	const int	*gisb_offsets;
+	bool		big_endian;
 	struct mutex	lock;
 	struct list_head next;
 	u32 valid_mask;
@@ -106,7 +107,10 @@ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
 	if (offset == -1)
 		return 1;
 
-	return ioread32(gdev->base + offset);
+	if (gdev->big_endian)
+		return ioread32be(gdev->base + offset);
+	else
+		return ioread32(gdev->base + offset);
 }
 
 static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
@@ -115,7 +119,11 @@ static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
 
 	if (offset == -1)
 		return;
-	iowrite32(val, gdev->base + reg);
+
+	if (gdev->big_endian)
+		iowrite32be(val, gdev->base + reg);
+	else
+		iowrite32(val, gdev->base + reg);
 }
 
 static ssize_t gisb_arb_get_timeout(struct device *dev,
@@ -300,6 +308,7 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 	gdev->gisb_offsets = of_id->data;
+	gdev->big_endian = of_device_is_big_endian(dn);
 
 	err = devm_request_irq(&pdev->dev, timeout_irq,
 				brcmstb_gisb_timeout_handler, 0, pdev->name,
Signature · 1 line
2.1.0
#12 lore raw

PATCH 8/9 bus: brcmstb_gisb: Honor the "big-endian" and "native-endian" DT properties

Quoted 2 lines · Kevin Cernekee

On chips strapped for BE, we'll need to use ioread32be/iowrite32be instead of ioread32/iowrite32.

Has of_device_is_big_endian() been merged in a tree now, I am not seeing it in Linus' tree, but have not look at Grant's tree yet. Thanks

Quoted 52 lines
---
 drivers/bus/brcmstb_gisb.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/bus/brcmstb_gisb.c +11 -2
index 172908d..969b992 100644
@@ -90,6 +90,7 @@ static const int gisb_offsets_bcm7445[] = {
 struct brcmstb_gisb_arb_device {
 	void __iomem	*base;
 	const int	*gisb_offsets;
+	bool		big_endian;
 	struct mutex	lock;
 	struct list_head next;
 	u32 valid_mask;
@@ -106,7 +107,10 @@ static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
 	if (offset == -1)
 		return 1;
 
-	return ioread32(gdev->base + offset);
+	if (gdev->big_endian)
+		return ioread32be(gdev->base + offset);
+	else
+		return ioread32(gdev->base + offset);
 }
 
 static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
@@ -115,7 +119,11 @@ static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
 
 	if (offset == -1)
 		return;
-	iowrite32(val, gdev->base + reg);
+
+	if (gdev->big_endian)
+		iowrite32be(val, gdev->base + reg);
+	else
+		iowrite32(val, gdev->base + reg);
 }
 
 static ssize_t gisb_arb_get_timeout(struct device *dev,
@@ -300,6 +308,7 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 	gdev->gisb_offsets = of_id->data;
+	gdev->big_endian = of_device_is_big_endian(dn);
 
 	err = devm_request_irq(&pdev->dev, timeout_irq,
 				brcmstb_gisb_timeout_handler, 0, pdev->name,
Signature · 1 line
Florian
#14 lore raw

PATCH 9/9 usb: {ohci, ehci}-platform: Use new OF big-endian helper function

In reply to Kevin Cernekee

This handles the existing "big-endian" case, and in addition, it also does the right thing when "native-endian" is specified.

---
 Documentation/devicetree/bindings/usb/usb-ehci.txt | 2 ++
 Documentation/devicetree/bindings/usb/usb-ohci.txt | 2 ++
 drivers/usb/host/ehci-platform.c                   | 2 +-
 drivers/usb/host/ohci-platform.c                   | 2 +-
 4 files changed, 6 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/usb/usb-ehci.txt +2 -0
index 43c1a4e..9505c31 100644
@@ -12,6 +12,8 @@ Optional properties:
  - big-endian-regs : boolean, set this for hcds with big-endian registers
  - big-endian-desc : boolean, set this for hcds with big-endian descriptors
  - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - native-endian : boolean, enables big-endian-regs + big-endian-desc
+   iff the kernel was compiled for big endian
  - clocks : a list of phandle + clock specifier pairs
  - phys : phandle + phy specifier pair
  - phy-names : "usb"
Documentation/devicetree/bindings/usb/usb-ohci.txt +2 -0
index 19233b7..3bb9673 100644
@@ -9,6 +9,8 @@ Optional properties:
 - big-endian-regs : boolean, set this for hcds with big-endian registers
 - big-endian-desc : boolean, set this for hcds with big-endian descriptors
 - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+- native-endian : boolean, enables big-endian-regs + big-endian-desc
+  iff the kernel was compiled for big endian
 - no-big-frame-no : boolean, set if frame_no lives in bits [15:0] of HCCA
 - num-ports : u32, to override the detected port count
 - clocks : a list of phandle + clock specifier pairs
drivers/usb/host/ehci-platform.c +1 -1
index 2f5b9ce..0da9d70 100644
@@ -187,7 +187,7 @@ static int ehci_platform_probe(struct platform_device *dev)
 		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
 			ehci->big_endian_desc = 1;
 
-		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+		if (of_device_is_big_endian(dev->dev.of_node))
 			ehci->big_endian_mmio = ehci->big_endian_desc = 1;
 
 		priv->phy = devm_phy_get(&dev->dev, "usb");
drivers/usb/host/ohci-platform.c +1 -1
index 7793c3c..029a606 100644
@@ -157,7 +157,7 @@ static int ohci_platform_probe(struct platform_device *dev)
 		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
 			ohci->flags |= OHCI_QUIRK_BE_DESC;
 
-		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+		if (of_device_is_big_endian(dev->dev.of_node))
 			ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
 
 		if (of_property_read_bool(dev->dev.of_node, "no-big-frame-no"))
Signature · 1 line
2.1.0
#15 lore raw

PATCH 9/9 usb: {ohci,ehci}-platform: Use new OF big-endian helper function

Quoted 16 lines · Kevin Cernekee

This handles the existing "big-endian" case, and in addition, it also does the right thing when "native-endian" is specified.

---
  Documentation/devicetree/bindings/usb/usb-ehci.txt | 2 ++
  Documentation/devicetree/bindings/usb/usb-ohci.txt | 2 ++
  drivers/usb/host/ehci-platform.c                   | 2 +-
  drivers/usb/host/ohci-platform.c                   | 2 +-
  4 files changed, 6 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/usb/usb-ehci.txt +0 -0
index 43c1a4e..9505c31 100644

Documentation/devicetree/bindings/usb/usb-ehci.txt Optional properties: · line 16

Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +2 -0
@@ -12,6 +12,8 @@ Optional properties:
   - big-endian-regs : boolean, set this for hcds with big-endian registers
   - big-endian-desc : boolean, set this for hcds with big-endian descriptors
   - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - native-endian : boolean, enables big-endian-regs + big-endian-desc
+   iff the kernel was compiled for big endian

s/iff/if

Documentation/devicetree/bindings/usb/usb-ohci.txt Optional properties: · line 13

Quoted 13 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +0 -0
   - clocks : a list of phandle + clock specifier pairs
   - phys : phandle + phy specifier pair
   - phy-names : "usb"
Documentation/devicetree/bindings/usb/usb-ohci.txt +2 -0
index 19233b7..3bb9673 100644
@@ -9,6 +9,8 @@ Optional properties:
  - big-endian-regs : boolean, set this for hcds with big-endian registers
  - big-endian-desc : boolean, set this for hcds with big-endian descriptors
  - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+- native-endian : boolean, enables big-endian-regs + big-endian-desc
+  iff the kernel was compiled for big endian

s/iff/if

Quoted 29 lines
Documentation/devicetree/bindings/usb/usb-ohci.txt +0 -0
  - no-big-frame-no : boolean, set if frame_no lives in bits [15:0] of HCCA
  - num-ports : u32, to override the detected port count
  - clocks : a list of phandle + clock specifier pairs
drivers/usb/host/ehci-platform.c +1 -1
index 2f5b9ce..0da9d70 100644
@@ -187,7 +187,7 @@ static int ehci_platform_probe(struct platform_device *dev)
  		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
  			ehci->big_endian_desc = 1;
 
-		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+		if (of_device_is_big_endian(dev->dev.of_node))
  			ehci->big_endian_mmio = ehci->big_endian_desc = 1;
 
  		priv->phy = devm_phy_get(&dev->dev, "usb");
drivers/usb/host/ohci-platform.c +1 -1
index 7793c3c..029a606 100644
@@ -157,7 +157,7 @@ static int ohci_platform_probe(struct platform_device *dev)
  		if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
  			ohci->flags |= OHCI_QUIRK_BE_DESC;
 
-		if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+		if (of_device_is_big_endian(dev->dev.of_node))
  			ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
 
  		if (of_property_read_bool(dev->dev.of_node, "no-big-frame-no"))
maintainer
#16 lore raw

PATCH 9/9 usb: {ohci,ehci}-platform: Use new OF big-endian helper function

In reply to Kevin Cernekee
Quoted 16 lines · Kevin Cernekee

This handles the existing "big-endian" case, and in addition, it also does the right thing when "native-endian" is specified.

---
 Documentation/devicetree/bindings/usb/usb-ehci.txt | 2 ++
 Documentation/devicetree/bindings/usb/usb-ohci.txt | 2 ++
 drivers/usb/host/ehci-platform.c                   | 2 +-
 drivers/usb/host/ohci-platform.c                   | 2 +-
 4 files changed, 6 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/usb/usb-ehci.txt +0 -0
index 43c1a4e..9505c31 100644

Documentation/devicetree/bindings/usb/usb-ehci.txt Optional properties: · line 16

Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +2 -0
@@ -12,6 +12,8 @@ Optional properties:
  - big-endian-regs : boolean, set this for hcds with big-endian registers
  - big-endian-desc : boolean, set this for hcds with big-endian descriptors
  - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - native-endian : boolean, enables big-endian-regs + big-endian-desc
+   iff the kernel was compiled for big endian

Is this really a property of the hardware? It appears to depend on the kernel configuration. As such, is it appropriate for DT?

Alan Stern

#17 lore raw

PATCH 9/9 usb: {ohci,ehci}-platform: Use new OF big-endian helper function

Quoted 5 lines · Alan Stern
Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +0 -0
index 43c1a4e..9505c31 100644
@@ -12,6 +12,8 @@ Optional properties:
Quoted 8 lines

Documentation/devicetree/bindings/usb/usb-ehci.txt Optional properties: · line 16

Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +2 -0
  - big-endian-regs : boolean, set this for hcds with big-endian registers
  - big-endian-desc : boolean, set this for hcds with big-endian descriptors
  - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - native-endian : boolean, enables big-endian-regs + big-endian-desc
+   iff the kernel was compiled for big endian

Is this really a property of the hardware? It appears to depend on the kernel configuration. As such, is it appropriate for DT?

Yes, the peripheral registers automatically adjust their endianness to match the CPU. So if the CPU is running an LE kernel, the peripheral needs to be accessed in LE mode; if the CPU is running a BE kernel, the peripheral needs to be accessed in BE mode.

maintainer
#18 lore raw

PATCH 9/9 usb: {ohci,ehci}-platform: Use new OF big-endian helper function

Quoted 15 lines · Kevin Cernekee
Quoted 5 lines · Alan Stern
Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +0 -0
index 43c1a4e..9505c31 100644
@@ -12,6 +12,8 @@ Optional properties:
Quoted 8 lines

Documentation/devicetree/bindings/usb/usb-ehci.txt Optional properties: · line 16

Quoted 5 lines
Documentation/devicetree/bindings/usb/usb-ehci.txt +2 -0
  - big-endian-regs : boolean, set this for hcds with big-endian registers
  - big-endian-desc : boolean, set this for hcds with big-endian descriptors
  - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - native-endian : boolean, enables big-endian-regs + big-endian-desc
+   iff the kernel was compiled for big endian

Is this really a property of the hardware? It appears to depend on the kernel configuration. As such, is it appropriate for DT?

Quoted 4 lines

Yes, the peripheral registers automatically adjust their endianness to match the CPU. So if the CPU is running an LE kernel, the peripheral needs to be accessed in LE mode; if the CPU is running a BE kernel, the peripheral needs to be accessed in BE mode.

Okay, then:

But you might want to update the description slightly to say:

- native-endian : boolean, enables big-endian-regs + big-endian-desc iff the CPU is running in big-endian mode

It's a very minor distinction, since you can't run a kernel that was compiled for little endian if the CPU is running in big-endian mode, but this makes it clear that you're talking about the hardware rather than the software.

Alan Stern

#19 lore raw

cover Extend various drivers to run on bi-endian BMIPS hosts

In reply to Kevin Cernekee

2014-11-25 16:49 GMT-08:00 Kevin Cernekee <[email protected]>:

Quoted 16 lines

This patch series incorporates the following changes:

- Extend brcmstb reset driver to work on MIPS (currently ARM-only).

- Extend brcmstb GISB bus driver to work on MIPS (currently ARM-only).

- Extend brcmstb GISB bus driver to work on BE systems (currently LE-only).

- Extend both drivers to support the older register layouts used on many of the BMIPS platforms.

- Extend {ohci,ehci}-platform drivers to accept the new "native-endian" DT property, to accommodate BCM7xxx platforms that can be switched between LE/BE with a board jumper.

Quoted 7 lines

Dependencies:

power/reset: brcmstb: Register with kernel restart handler (Guenter Roeck)
of: Add helper function to check MMIO register endianness (Kevin Cernekee)

These are both tentatively accepted, but might not be present in the same tree yet. As such, we might want to "review now, merge later."

For the entire series:

I will probably take the brcmstb_gisb.c changes separately and submit them to arm-soc as a "drivers" pull request since this driver has typically been routed that way.

Thanks!

Quoted 30 lines

Kevin Cernekee (9):
power/reset: brcmstb: Make the driver buildable on MIPS power/reset: brcmstb: Use the DT "compatible" string to indicate bit
positions
power/reset: brcmstb: Add support for old 65nm chips
bus: brcmstb_gisb: Make the driver buildable on MIPS
bus: brcmstb_gisb: Introduce wrapper functions for MMIO accesses
bus: brcmstb_gisb: Look up register offsets in a table
bus: brcmstb_gisb: Add register offset tables for older chips
bus: brcmstb_gisb: Honor the "big-endian" and "native-endian" DT
properties
usb: {ohci,ehci}-platform: Use new OF big-endian helper function

 .../devicetree/bindings/arm/brcm-brcmstb.txt       |   4 +-
 .../devicetree/bindings/bus/brcm,gisb-arb.txt      |   6 +-
 Documentation/devicetree/bindings/usb/usb-ehci.txt |   2 +
 Documentation/devicetree/bindings/usb/usb-ohci.txt |   2 +
 drivers/bus/Kconfig                                |   2 +-
 drivers/bus/brcmstb_gisb.c                         | 127 ++++++++++++++++++---
 drivers/power/reset/Kconfig                        |   9 +-
 drivers/power/reset/brcmstb-reboot.c               |  41 +++++--
 drivers/usb/host/ehci-platform.c                   |   2 +-
 drivers/usb/host/ohci-platform.c                   |   2 +-
 10 files changed, 161 insertions(+), 36 deletions(-)

--
2.1.0

Signature · 1 line
Florian