LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH 0/2] mpc5200: tidy up the device tree bindings
From: Grant Likely @ 2008-01-18 17:04 UTC (permalink / raw)
  To: linuxppc-dev, jrigby, matt, tnt

These two patches make the device tree bindings for 5200 platforms more
robust and match closer with the generic names recommended practice.

Please review and comment.

Cheers,
g.

--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* [RFC/PATCH 1/2] [POWERPC] mpc5200: normalize compatible property bindings
From: Grant Likely @ 2008-01-18 17:04 UTC (permalink / raw)
  To: linuxppc-dev, jrigby, matt, tnt
In-Reply-To: <20080118170324.10592.47360.stgit@trillian.secretlab.ca>

From: Grant Likely <grant.likely@secretlab.ca>

Update MPC5200 drivers to also look for compatible properties in the
form "fsl,mpc5200-*" to better conform to open firmware generic names
recommended practice as published here:

http://www.openfirmware.org/1275/practice/gnames/gnamv14a.html

This patch should *not* break compatibility with older device trees
which do not use the 'fsl,' prefix.  The drivers will still bind against
the older names also.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/powerpc/platforms/52xx/lite5200.c       |   14 +++++++-
 arch/powerpc/platforms/52xx/lite5200_pm.c    |    8 ++++-
 arch/powerpc/platforms/52xx/mpc52xx_common.c |   43 ++++++++++++++++----------
 arch/powerpc/platforms/52xx/mpc52xx_pci.c    |    9 ++++-
 arch/powerpc/platforms/52xx/mpc52xx_pic.c    |   14 +++++++-
 arch/powerpc/platforms/52xx/mpc52xx_pm.c     |    8 ++++-
 arch/powerpc/sysdev/bestcomm/bestcomm.c      |   13 +++++---
 drivers/ata/pata_mpc52xx.c                   |    6 +---
 drivers/net/fec_mpc52xx.c                    |    6 +---
 drivers/net/fec_mpc52xx_phy.c                |    8 ++---
 drivers/serial/mpc52xx_uart.c                |    4 ++
 drivers/spi/mpc52xx_psc_spi.c                |    5 ++-
 drivers/usb/host/ohci-ppc-of.c               |    2 +
 13 files changed, 94 insertions(+), 46 deletions(-)

diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 5a8d190..f8ba5f2 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -44,9 +44,14 @@ lite5200_fix_clock_config(void)
 {
 	struct device_node *np;
 	struct mpc52xx_cdm  __iomem *cdm;
+	struct of_device_id cdm_ids[] = {
+		{ .compatible = "fsl,mpc5200-cdm", },
+		{ .compatible = "mpc5200-cdm", },
+		{}
+	};
 
 	/* Map zones */
-	np = of_find_compatible_node(NULL, NULL, "mpc5200-cdm");
+	np = of_find_matching_node(NULL, cdm_ids);
 	cdm = of_iomap(np, 0);
 	of_node_put(np);
 	if (!cdm) {
@@ -79,9 +84,14 @@ lite5200_fix_port_config(void)
 {
 	struct device_node *np;
 	struct mpc52xx_gpio __iomem *gpio;
+	struct of_device_id gpio_ids[] = {
+		{ .compatible = "fsl,mpc5200-gpio", },
+		{ .compatible = "mpc5200-gpio", },
+		{}
+	};
 	u32 port_config;
 
-	np = of_find_compatible_node(NULL, NULL, "mpc5200-gpio");
+	np = of_find_matching_node(NULL, gpio_ids);
 	gpio = of_iomap(np, 0);
 	of_node_put(np);
 	if (!gpio) {
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c
index c3ada1e..1679662 100644
--- a/arch/powerpc/platforms/52xx/lite5200_pm.c
+++ b/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -43,6 +43,12 @@ static int lite5200_pm_set_target(suspend_state_t state)
 static int lite5200_pm_prepare(void)
 {
 	struct device_node *np;
+	struct of_device_id immr_ids[] = {
+		{ .compatible = "fsl,mpc5200-immr", },
+		{ .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
+		{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
+		{}
+	};
 
 	/* deep sleep? let mpc52xx code handle that */
 	if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
@@ -52,7 +58,7 @@ static int lite5200_pm_prepare(void)
 		return -EINVAL;
 
 	/* map registers */
-	np = of_find_compatible_node(NULL, NULL, "mpc5200");
+	np = of_find_matching_node(NULL, immr_ids);
 	mbar = of_iomap(np, 0);
 	of_node_put(np);
 	if (!mbar) {
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 6695593..0211890 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -64,8 +64,13 @@ mpc5200_setup_xlb_arbiter(void)
 {
 	struct device_node *np;
 	struct mpc52xx_xlb  __iomem *xlb;
+	struct of_device_id xlb_ids[] = {
+		{ .compatible = "fsl,mpc5200-xlb", },
+		{ .compatible = "mpc5200-xlb", },
+		{}
+	};
 
-	np = of_find_compatible_node(NULL, NULL, "mpc5200-xlb");
+	np = of_find_matching_node(NULL, xlb_ids);
 	xlb = of_iomap(np, 0);
 	of_node_put(np);
 	if (!xlb) {
@@ -88,6 +93,9 @@ mpc5200_setup_xlb_arbiter(void)
 	iounmap(xlb);
 }
 
+/*
+ * Match table used by mpc52xx_declare_of_platform_devices
+ */
 static struct of_device_id mpc52xx_bus_ids[] __initdata= {
 	{ .compatible = "fsl,mpc5200-immr", },
 	{ .compatible = "fsl,lpb", },
@@ -95,9 +103,14 @@ static struct of_device_id mpc52xx_bus_ids[] __initdata= {
 	/* depreciated matches; shouldn't be used in new device trees */
 	{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
 	{ .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
-	{},
+	{}
 };
 
+/**
+ * mpc52xx_declare_of_platform_devices: register internal devices and children
+ *					of the localplus bus to the of_platform
+ *					bus.
+ */
 void __init
 mpc52xx_declare_of_platform_devices(void)
 {
@@ -107,33 +120,31 @@ mpc52xx_declare_of_platform_devices(void)
 			"Error while probing of_platform bus\n");
 }
 
+/*
+ * match tables used by mpc52xx_map_wdt()
+ */
+static struct of_device_id mpc52xx_gpt_ids[] __initdata = {
+	{ .compatible = "fsl,mpc5200-gpt", },
+	{ .compatible = "mpc5200-gpt", }, /* old */
+	{}
+};
+
 void __init
 mpc52xx_map_wdt(void)
 {
-	const void *has_wdt;
 	struct device_node *np;
-
 	/* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
 	 * possibly from a interrupt context. wdt is only implement
 	 * on a gpt0, so check has-wdt property before mapping.
 	 */
-	for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") {
-		has_wdt = of_get_property(np, "fsl,has-wdt", NULL);
-		if (has_wdt) {
+	for_each_matching_node(np, mpc52xx_gpt_ids) {
+		if (of_get_property(np, "fsl,has-wdt", NULL) ||
+		    of_get_property(np, "has-wdt", NULL)) {
 			mpc52xx_wdt = of_iomap(np, 0);
 			of_node_put(np);
 			return;
 		}
 	}
-	for_each_compatible_node(np, NULL, "mpc5200-gpt") {
-		has_wdt = of_get_property(np, "has-wdt", NULL);
-		if (has_wdt) {
-			mpc52xx_wdt = of_iomap(np, 0);
-			of_node_put(np);
-			return;
-		}
-
-	}
 }
 
 void
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 4b79398..0e71722 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -410,10 +410,13 @@ mpc52xx_add_bridge(struct device_node *node)
 void __init mpc52xx_setup_pci(void)
 {
 	struct device_node *pci;
+	struct of_device_id pci_ids[] = {
+		{ .type = "pci", .compatible = "fsl,mpc5200-pci", },
+		{ .type = "pci", .compatible = "mpc5200-pci", },
+		{}
+	};
 
-	pci = of_find_compatible_node(NULL, NULL, "fsl,mpc5200-pci");
-	if (!pci)
-		pci = of_find_compatible_node(NULL, NULL, "mpc5200-pci");
+	pci = of_find_matching_node(NULL, pci_ids);
 	if (!pci)
 		return;
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 07e8987..3f9d3cb 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -365,15 +365,25 @@ void __init mpc52xx_init_irq(void)
 	u32 intr_ctrl;
 	struct device_node *picnode;
 	struct device_node *np;
+	struct of_device_id pic_ids[] = {
+		{ .compatible = "fsl,mpc5200-pic", },
+		{ .compatible = "mpc5200-pic", },
+		{}
+	};
+	struct of_device_id sdma_ids[] = {
+		{ .compatible = "fsl,mpc5200-bestcomm", },
+		{ .compatible = "mpc5200-bestcomm", },
+		{}
+	};
 
 	/* Remap the necessary zones */
-	picnode = of_find_compatible_node(NULL, NULL, "mpc5200-pic");
+	picnode = of_find_matching_node(NULL, pic_ids);
 	intr = of_iomap(picnode, 0);
 	if (!intr)
 		panic(__FILE__	": find_and_map failed on 'mpc5200-pic'. "
 				"Check node !");
 
-	np = of_find_compatible_node(NULL, NULL, "mpc5200-bestcomm");
+	np = of_find_matching_node(NULL, sdma_ids);
 	sdma = of_iomap(np, 0);
 	of_node_put(np);
 	if (!sdma)
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
index 52f0277..722c8d4 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -60,9 +60,15 @@ int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
 int mpc52xx_pm_prepare(void)
 {
 	struct device_node *np;
+	struct of_device_id immr_ids[] = {
+		{ .compatible = "fsl,mpc5200-immr", },
+		{ .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
+		{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
+		{}
+	};
 
 	/* map the whole register space */
-	np = of_find_compatible_node(NULL, NULL, "mpc5200");
+	np = of_find_matching_node(NULL, immr_ids);
 	mbar = of_iomap(np, 0);
 	of_node_put(np);
 	if (!mbar) {
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
index 740ad73..c6b04c6 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -363,6 +363,11 @@ mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *ofn_sram;
 	struct resource res_bcom;
+	struct of_device_id sram_ids[] = {
+		{ .compatible = "fsl,mpc5200-sram", },
+		{ .compatible = "mpc5200-sram", },
+		{}
+	};
 
 	int rv;
 
@@ -373,7 +378,7 @@ mpc52xx_bcom_probe(struct of_device *op, const struct of_device_id *match)
 	of_node_get(op->node);
 
 	/* Prepare SRAM */
-	ofn_sram = of_find_compatible_node(NULL, "sram", "mpc5200-sram");
+	ofn_sram = of_find_matching_node(NULL, sram_ids);
 	if (!ofn_sram) {
 		printk(KERN_ERR DRIVER_NAME ": "
 			"No SRAM found in device tree\n");
@@ -478,10 +483,8 @@ mpc52xx_bcom_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc52xx_bcom_of_match[] = {
-	{
-		.type		= "dma-controller",
-		.compatible	= "mpc5200-bestcomm",
-	},
+	{ .type = "dma-controller", .compatible = "fsl,mpc5200-bestcomm", },
+	{ .type = "dma-controller", .compatible = "mpc5200-bestcomm", },
 	{},
 };
 
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 50c56e2..1a7ca37 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -494,10 +494,8 @@ mpc52xx_ata_resume(struct of_device *op)
 
 
 static struct of_device_id mpc52xx_ata_of_match[] = {
-	{
-		.type		= "ata",
-		.compatible	= "mpc5200-ata",
-	},
+	{ .compatible = "fsl,mpc5200-ata", },
+	{ .compatible = "mpc5200-ata", },
 	{},
 };
 
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 79f7ead..2700482 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -1056,10 +1056,8 @@ static int mpc52xx_fec_of_resume(struct of_device *op)
 #endif
 
 static struct of_device_id mpc52xx_fec_match[] = {
-	{
-		.type		= "network",
-		.compatible	= "mpc5200-fec",
-	},
+	{ .type = "network", .compatible = "fsl,mpc5200-fec", },
+	{ .type = "network", .compatible = "mpc5200-fec", },
 	{ }
 };
 
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
index ba6e8b2..1837584 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -177,11 +177,9 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of)
 
 
 static struct of_device_id mpc52xx_fec_mdio_match[] = {
-	{
-		.type = "mdio",
-		.compatible = "mpc5200b-fec-phy",
-	},
-	{},
+	{ .compatible = "fsl,mpc5200b-mdio", },
+	{ .compatible = "mpc5200b-fec-phy", },
+	{}
 };
 
 struct of_platform_driver mpc52xx_fec_mdio_driver = {
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index a269ae1..06f4316 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -130,7 +130,9 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);
 
 #if defined(CONFIG_PPC_MERGE)
 static const struct of_device_id mpc52xx_uart_of_match[] = {
-	{ .type = "serial", .compatible = "mpc5200-psc-uart", },
+	{ .type = "serial", .compatible = "fsl,mpc5200-psc-uart", },
+	{ .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */
+	{ .type = "serial", .compatible = "mpc5200-serial", }, /* efika */
 	{},
 };
 #endif
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index d398c93..a3ebc63 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -628,8 +628,9 @@ static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc52xx_psc_spi_of_match[] = {
-	{ .type = "spi", .compatible = "mpc5200-psc-spi", },
-	{},
+	{ .compatible = "fsl,mpc5200-psc-spi", },
+	{ .compatible = "mpc5200-psc-spi", }, /* old */
+	{}
 };
 
 MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 0c3e6b7..a672527 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -136,6 +136,8 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
 	ohci = hcd_to_ohci(hcd);
 	if (is_bigendian) {
 		ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+		if (of_device_is_compatible(dn, "fsl,mpc5200-ohci"))
+			ohci->flags |= OHCI_QUIRK_FRAME_NO;
 		if (of_device_is_compatible(dn, "mpc5200-ohci"))
 			ohci->flags |= OHCI_QUIRK_FRAME_NO;
 	}

^ permalink raw reply related

* [RFC/PATCH 2/2] [POWERPC] Efika: prune fixups and make them more carefull
From: Grant Likely @ 2008-01-18 17:05 UTC (permalink / raw)
  To: linuxppc-dev, jrigby, matt, tnt
In-Reply-To: <20080118170324.10592.47360.stgit@trillian.secretlab.ca>

From: Grant Likely <grant.likely@secretlab.ca>

Prune back Efika fixups to only include changes that are actually required
to get a working system.  Most of the drivers can accept the compatible
properties, even if they don't match the what is recommented in the generic
names recommended practice document.

This patch also adds extra checks so that fixups are not performed blindly.
Instead, the code first verifies that the device tree is faulty before
making any changes.  This way, if the Efika firmware is updated to fix
these issues, then the fixups will no longer get applied.

At this point; here is the list of fixups needed for the efika:
1. If the device_type property on the root node is 'chrp', then Linux won't
   boot.  Change device_type to 'efika' to avoid this condition
2. Add full interrupt list to the bestcomm node.  In actual fact, the
   bestcomm interrupts property is technically correct, it just doesn't
   expose the same granularity as the device driver expects.  All other
   5200 device trees provide a separate irq number for each bestcomm
   channel.  Rather than hack the driver, it's simpler to fix it up
3. /builtin/sound node is missing an interrupts property
4. /builtin/ethernet node is missing a phy-handle property and the
   device driver doesn't know what to do without one.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/powerpc/kernel/prom_init.c |  149 +++++++++++++++++++++------------------
 1 files changed, 79 insertions(+), 70 deletions(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 5d89a21..5ab4c84 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2142,82 +2142,34 @@ static void __init fixup_device_tree_pmac(void)
 #endif
 
 #ifdef CONFIG_PPC_EFIKA
-/* The current fw of the Efika has a device tree needs quite a few
- * fixups to be compliant with the mpc52xx bindings. It's currently
- * unknown if it will ever be compliant (come on bPlan ...) so we do fixups.
- * NOTE that we (barely) tolerate it because the EFIKA was out before
- * the bindings were finished, for any new boards -> RTFM ! */
-
-struct subst_entry {
-	char *path;
-	char *property;
-	void *value;
-	int value_len;
-};
-
-static void __init fixup_device_tree_efika(void)
+/*
+ * The MPC5200 FEC driver requires an phy-handle property to tell it how
+ * to talk to the phy.  If the phy-handle property is missing, then this
+ * function is called to add the appropriate nodes and link it to the
+ * ethernet node.
+ */
+static void __init fixup_device_tree_efika_add_phy(void)
 {
-	/* Substitution table */
-	#define prop_cstr(x) x, sizeof(x)
-	int prop_sound_irq[3] = { 2, 2, 0 };
-	int prop_bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
-	                             3,4,0, 3,5,0, 3,6,0, 3,7,0,
-	                             3,8,0, 3,9,0, 3,10,0, 3,11,0,
-	                             3,12,0, 3,13,0, 3,14,0, 3,15,0 };
-	struct subst_entry efika_subst_table[] = {
-		{ "/",			"device_type",	prop_cstr("efika") },
-		{ "/builtin",		"device_type",	prop_cstr("soc") },
-		{ "/builtin/ata",	"compatible",	prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
-		{ "/builtin/bestcomm",	"compatible",	prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
-		{ "/builtin/bestcomm",	"interrupts",	prop_bcomm_irq, sizeof(prop_bcomm_irq) },
-		{ "/builtin/ethernet",	"compatible",	prop_cstr("mpc5200b-fec\0mpc5200-fec") },
-		{ "/builtin/pic",	"compatible",	prop_cstr("mpc5200b-pic\0mpc5200-pic") },
-		{ "/builtin/serial",	"compatible",	prop_cstr("mpc5200b-psc-uart\0mpc5200-psc-uart") },
-		{ "/builtin/sound",	"compatible",	prop_cstr("mpc5200b-psc-ac97\0mpc5200-psc-ac97") },
-		{ "/builtin/sound",	"interrupts",	prop_sound_irq, sizeof(prop_sound_irq) },
-		{ "/builtin/sram",	"compatible",	prop_cstr("mpc5200b-sram\0mpc5200-sram") },
-		{ "/builtin/sram",	"device_type",	prop_cstr("sram") },
-		{}
-	};
-	#undef prop_cstr
-
-	/* Vars */
 	u32 node;
 	char prop[64];
-	int rv, i;
+	int rv;
 
-	/* Check if we're really running on a EFIKA */
-	node = call_prom("finddevice", 1, 1, ADDR("/"));
+	/* Check if /builtin/ethernet exists - bail if it doesn't */
+	node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
 	if (!PHANDLE_VALID(node))
 		return;
 
-	rv = prom_getprop(node, "model", prop, sizeof(prop));
-	if (rv == PROM_ERROR)
-		return;
-	if (strcmp(prop, "EFIKA5K2"))
+	/* Check if the phy-handle property exists - bail if it does */
+	rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
+	if (!rv)
 		return;
 
-	prom_printf("Applying EFIKA device tree fixups\n");
-
-	/* Process substitution table */
-	for (i=0; efika_subst_table[i].path; i++) {
-		struct subst_entry *se = &efika_subst_table[i];
-
-		node = call_prom("finddevice", 1, 1, ADDR(se->path));
-		if (!PHANDLE_VALID(node)) {
-			prom_printf("fixup_device_tree_efika: ",
-				"skipped entry %x - not found\n", i);
-			continue;
-		}
-
-		rv = prom_setprop(node, se->path, se->property,
-					se->value, se->value_len );
-		if (rv == PROM_ERROR)
-			prom_printf("fixup_device_tree_efika: ",
-				"skipped entry %x - setprop error\n", i);
-	}
+	/*
+	 * At this point the ethernet device doesn't have a phy described.
+	 * Now we need to add the missing phy node and linkage
+	 */
 
-	/* Make sure ethernet mdio bus node exists */
+	/* Check for an MDIO bus node - if missing then create one */
 	node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
 	if (!PHANDLE_VALID(node)) {
 		prom_printf("Adding Ethernet MDIO node\n");
@@ -2226,8 +2178,8 @@ static void __init fixup_device_tree_efika(void)
 			" new-device"
 				" 1 encode-int s\" #address-cells\" property"
 				" 0 encode-int s\" #size-cells\" property"
-				" s\" mdio\" 2dup device-name device-type"
-				" s\" mpc5200b-fec-phy\" encode-string"
+				" s\" mdio\" device-name"
+				" s\" fsl,mpc5200b-mdio\" encode-string"
 				" s\" compatible\" property"
 				" 0xf0003000 0x400 reg"
 				" 0x2 encode-int"
@@ -2237,8 +2189,10 @@ static void __init fixup_device_tree_efika(void)
 			" finish-device");
 	};
 
-	/* Make sure ethernet phy device node exist */
-	node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio/ethernet-phy"));
+	/* Check for a PHY device node - if missing then create one and
+	 * give it's phandle to the ethernet node */
+	node = call_prom("finddevice", 1, 1,
+			 ADDR("/builtin/mdio/ethernet-phy"));
 	if (!PHANDLE_VALID(node)) {
 		prom_printf("Adding Ethernet PHY node\n");
 		call_prom("interpret", 1, 1,
@@ -2254,7 +2208,62 @@ static void __init fixup_device_tree_efika(void)
 				" s\" phy-handle\" property"
 			" device-end");
 	}
+}
+
+static void __init fixup_device_tree_efika(void)
+{
+	int sound_irq[3] = { 2, 2, 0 };
+	int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
+				3,4,0, 3,5,0, 3,6,0, 3,7,0,
+				3,8,0, 3,9,0, 3,10,0, 3,11,0,
+				3,12,0, 3,13,0, 3,14,0, 3,15,0 };
+	u32 node;
+	char prop[64];
+	int rv, len;
+
+	/* Check if we're really running on a EFIKA */
+	node = call_prom("finddevice", 1, 1, ADDR("/"));
+	if (!PHANDLE_VALID(node))
+		return;
+
+	rv = prom_getprop(node, "model", prop, sizeof(prop));
+	if (rv == PROM_ERROR)
+		return;
+	if (strcmp(prop, "EFIKA5K2"))
+		return;
+
+	prom_printf("Applying EFIKA device tree fixups\n");
+
+	/* Claiming to be 'chrp' is death */
+	node = call_prom("finddevice", 1, 1, ADDR("/"));
+	rv = prom_getprop(node, "device_type", prop, sizeof(prop));
+	if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
+		prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
+
+	/* Fixup bestcomm interrupts property */
+	node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
+	if (PHANDLE_VALID(node)) {
+		len = prom_getproplen(node, "interrupts");
+		if (len == 12) {
+			prom_printf("Fixing bestcomm interrupts property\n");
+			prom_setprop(node, "/builtin/bestcom", "interrupts",
+				     bcomm_irq, sizeof(bcomm_irq));
+		}
+	}
+
+	/* Fixup sound interrupts property */
+	node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
+	if (PHANDLE_VALID(node)) {
+		rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
+		if (rv == PROM_ERROR) {
+			prom_printf("Adding sound interrupts property\n");
+			prom_setprop(node, "/builtin/sound", "interrupts",
+				     sound_irq, sizeof(sound_irq));
+		}
+	}
 
+	/* Make sure ethernet phy-handle property exists */
+	fixup_device_tree_efika_add_phy();
 }
 #else
 #define fixup_device_tree_efika()

^ permalink raw reply related

* Re: 2.6.24-rc8-mm1: powerpc oopses
From: Mariusz Kozlowski @ 2008-01-18 17:23 UTC (permalink / raw)
  To: Matt Mackall; +Cc: linuxppc-dev, Andrew Morton, paulus, linux-kernel
In-Reply-To: <1200617237.3839.32.camel@cinder.waste.org>

Hello,

> > Do we need `offset' at all?
> 
> Looks like no.
> 
> I wonder if there's a good argument for adding a pte_offset_val() which
> would let us do:
> 
> pteval = pte_offset_val(pmd, addr);
> 
> and shrink the map/unmap window and overhead here and possibly
> elsewhere?
> 
> Anyway, updated but still untested patch now with revealing comment:

I patched the ppc32 kernel with this and run tests on /proc.
This patch helps. No more BUGs and oopses :)

Thanks,

	Mariusz

> diff -r 5595adaea70f fs/proc/task_mmu.c
> --- a/fs/proc/task_mmu.c	Thu Jan 17 13:26:54 2008 -0600
> +++ b/fs/proc/task_mmu.c	Thu Jan 17 18:45:57 2008 -0600
> @@ -584,18 +585,19 @@
>  	pte_t *pte;
>  	int err = 0;
>  
> -	pte = pte_offset_map(pmd, addr);
> -	for (; addr != end; pte++, addr += PAGE_SIZE) {
> +	for (; addr != end; addr += PAGE_SIZE) {
>  		u64 pfn = PM_NOT_PRESENT;
> +		pte = pte_offset_map(pmd, addr);
>  		if (is_swap_pte(*pte))
>  			pfn = swap_pte_to_pagemap_entry(*pte);
>  		else if (pte_present(*pte))
>  			pfn = pte_pfn(*pte);
> +		/* unmap so we're not in atomic when we copy to userspace */
> +		pte_unmap(pte);
>  		err = add_to_pagemap(addr, pfn, pm);
>  		if (err)
>  			return err;
>  	}
> -	pte_unmap(pte - 1);
>  
>  	cond_resched();

^ permalink raw reply

* Re: [PATCH/RFCv2] [POWERPC] Add support for freescale watchdog to CPM serial driver.
From: Jochen Friedrich @ 2008-01-18 17:33 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, Stephen Rothwell, linux-kernel
In-Reply-To: <4790DC33.2070104@freescale.com>

Scott Wood schrieb:

>> +void watchdog_poke(void)
>> +{
>> +    if (wdt) {
>> +        out_be16(&wdt->swsrr, 0x556c);
>> +        out_be16(&wdt->swsrr, 0xaa39);
>> +    }
>> +}
> 
> This should be a function pointer, to allow for other watchdog types.

Thanks for the comments. Stephen Rothwell also asked if the filename watchdog.c is too generic.
I think the pq watchdog is easy enough to keep it in the generic watchdog.c file, but the
function pointer definitely is the way to go. I'll resubmit.

Thanks,
Jochen

^ permalink raw reply

* Re: 2.6.24-rc8-mm1: powerpc oopses
From: Matt Mackall @ 2008-01-18 17:33 UTC (permalink / raw)
  To: Mariusz Kozlowski; +Cc: linuxppc-dev, Andrew Morton, paulus, linux-kernel
In-Reply-To: <200801181823.07718.m.kozlowski@tuxland.pl>


On Fri, 2008-01-18 at 18:23 +0100, Mariusz Kozlowski wrote:
> Hello,
> 
> > > Do we need `offset' at all?
> > 
> > Looks like no.
> > 
> > I wonder if there's a good argument for adding a pte_offset_val() which
> > would let us do:
> > 
> > pteval = pte_offset_val(pmd, addr);
> > 
> > and shrink the map/unmap window and overhead here and possibly
> > elsewhere?
> > 
> > Anyway, updated but still untested patch now with revealing comment:
> 
> I patched the ppc32 kernel with this and run tests on /proc.
> This patch helps. No more BUGs and oopses :)

Thanks, Andrew's already queued it up.

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply

* Re: Problems with PCI on 8280
From: Scott Wood @ 2008-01-18 17:07 UTC (permalink / raw)
  To: Rune Torgersen; +Cc: linuxppc-dev
In-Reply-To: <DCEAAC0833DD314AB0B58112AD99B93B039BA0D8@ismail.innsys.innovsys.com>

On Thu, Jan 17, 2008 at 06:27:46PM -0600, Rune Torgersen wrote:
> BTW. there is a bug in the inbound window size calculation. The mem_log2
> variable sould be the shift value, not 1<< shift. and on the next line the
> window size mask sould be anded with 0x000f_ffff before or'ed with
> 0xa000_0000

D'oh.  Thanks for spotting it!

-Scott

^ permalink raw reply

* Re: MPIC ISU
From: vb @ 2008-01-18 18:44 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-embedded
In-Reply-To: <57351E05-13DE-48F0-B0E5-28AADEF288A1@kernel.crashing.org>

Kumar,

thank you for your reply!

On Jan 18, 2008 7:54 AM, Kumar Gala <galak@kernel.crashing.org> wrote:
>
> >
> > What is it, at the very least - what does ISU stand for?
> >
> > I would really appreciate any hints,
>
> Interrupt service unit.  I believe its an IBM concept.
>
> For 8245 can you look at what the linkstation port is doing and mimic
> that.  I believe its an 8245 or 8241 so it should be close to what you
> need.
>

what platform is linkstation and what kernel version can I find it in?


TIA,
/vb

>          mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY |
> MPIC_WANTS_RESET, 4, 32, " EPIC     ");
>          BUG_ON(mpic == NULL);
>
>          /* PCI IRQs */
>          mpic_assign_isu(mpic, 0, paddr + 0x10200);
>
>          /* I2C */
>          mpic_assign_isu(mpic, 1, paddr + 0x11000);
>
>          /* ttyS0, ttyS1 */
>          mpic_assign_isu(mpic, 2, paddr + 0x11100);
>
>          mpic_init(mpic);
>
> - k
>

^ permalink raw reply

* Re: [PATCH/RFCv2] [POWERPC] Add support for freescale watchdog to CPM serial driver.
From: Jochen Friedrich @ 2008-01-18 18:47 UTC (permalink / raw)
  To: Alan Cox; +Cc: Scott Wood, linuxppc-dev, linux-kernel
In-Reply-To: <20080118183905.2d5d8474@lxorguk.ukuu.org.uk>

Hi Alan,

>> If a freescale watchdog device node is present, reset the watchdog
>> while waiting for serial input.
> 
> Why ? We normally rely on user space for watchdog management as only the
> fact user space is behaving really proves a box is happy ?

This is in the boot wrapper code, not in the linux kernel.

Thanks,
Jochen

^ permalink raw reply

* Re: crash in kmem_cache_init
From: Christoph Lameter @ 2008-01-18 18:47 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev, Pekka Enberg, linux-kernel, Linux MM
In-Reply-To: <20080117211511.GA25320@aepfle.de>

On Thu, 17 Jan 2008, Olaf Hering wrote:

> early_node_map[1] active PFN ranges
>     1:        0 ->   892928
> Could not find start_pfn for node 0

Corrupted min_pfn?

^ permalink raw reply

* Re: crash in kmem_cache_init
From: Christoph Lameter @ 2008-01-18 18:42 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev, Pekka Enberg, linux-kernel, Linux MM
In-Reply-To: <20080118065621.GA27495@aepfle.de>

On Fri, 18 Jan 2008, Olaf Hering wrote:

> calls cache_grow with nodeid 0
> > [c00000000075bbd0] [c0000000000f82d0] .cache_alloc_refill+0x234/0x2c0
> calls cache_grow with nodeid 0
> > [c00000000075bbe0] [c0000000000f7f38] .____cache_alloc_node+0x17c/0x1e8
> 
> calls cache_grow with nodeid 1
> > [c00000000075bbe0] [c0000000000f7d68] .fallback_alloc+0x1a0/0x1f4

Hmmm... fallback_alloc should not be called during bootstrap.

^ permalink raw reply

* Re: crash in kmem_cache_init
From: Christoph Lameter @ 2008-01-18 18:51 UTC (permalink / raw)
  To: Olaf Hering
  Cc: Mel Gorman, linuxppc-dev, Pekka Enberg, linux-kernel, Linux MM
In-Reply-To: <20080117211511.GA25320@aepfle.de>

On Thu, 17 Jan 2008, Olaf Hering wrote:

>   Normal     892928 ->   892928
> Movable zone start PFN for each node
> early_node_map[1] active PFN ranges
>     1:        0 ->   892928
> Could not find start_pfn for node 0

We only have a single node that is node 1? And then we initialize nodes 0 
to 3?

> Memory: 3496633k/3571712k available (6188k kernel code, 75080k reserved, 1324k data, 1220k bss, 304k init)
> cache_grow(2778) swapper(0):c0,j4294937299 cachep c0000000006a4fb8 nodeid 0 l3 c0000000005fddf0
> cache_grow(2778) swapper(0):c0,j4294937299 cachep c0000000006a4fb8 nodeid 1 l3 c0000000005fddf0
> cache_grow(2778) swapper(0):c0,j4294937299 cachep c0000000006a4fb8 nodeid 2 l3 c0000000005fddf0
> cache_grow(2778) swapper(0):c0,j4294937299 cachep c0000000006a4fb8 nodeid 3 l3 c0000000005fddf0

???

^ permalink raw reply

* Re: [PATCH/RFCv2] [POWERPC] Add support for freescale watchdog to CPM serial driver.
From: Alan Cox @ 2008-01-18 18:39 UTC (permalink / raw)
  To: Jochen Friedrich; +Cc: Scott Wood, linuxppc-dev, linux-kernel
In-Reply-To: <478F4AE3.5090803@scram.de>

On Thu, 17 Jan 2008 13:32:35 +0100
Jochen Friedrich <jochen@scram.de> wrote:

> If a freescale watchdog device node is present, reset the watchdog
> while waiting for serial input.

Why ? We normally rely on user space for watchdog management as only the
fact user space is behaving really proves a box is happy ?

Alan

^ permalink raw reply

* l2cr missing from /proc
From: Bob Brose @ 2008-01-18 18:53 UTC (permalink / raw)
  To: linuxppc-dev

Why is l2cr missing from the /proc filesystem in recent 2.6 kernels?
Is it a bug or design decision?

It wasn't necessary since one could set it via a kernel arg however
now that I'm trying to turn on cache in a 7455 and setting l3cr isn't
supported from the command line I was wondering if l3cr was in /proc
as well but has also gone missing (since I see l3cr code in the kernel
source).

^ permalink raw reply

* [patch 00/16] PS3 patch collection for 2.6.25
From: Geoff Levand @ 2008-01-18 20:29 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Paul,

I collected together all the unapplied PS3 patches into a series
and re-based them to your for-2.6.25 branch.

Patches #14 and #15 are new, but just code cleanups.  All other patches
have already been reviewed on the ML and have no outstanding comments
or requests.

Please apply for 2.6.25.  If you like, I can re-base or breakup the
series as you like.

-Geoff

[01/16] POWERPC: Add Cell SPRN bookmark register
[02/16] PS3: Make bus_id and dev_id u64
[03/16] PS3: Add ps3_repository_find_device_by_id()
[04/16] PS3: Use the HVs storage device notification mechanism properly
[05/16] PS3: Add repository polling loop to work around timing bug
[06/16] PS3: Kill unused ps3_repository_bump_device()
[07/16] PS3: Refactor ps3_repository_find_device()
[08/16] PS3: Checkpatch cleanups for drivers/ps3/ps3-sys-manager.c
[09/16] PS3: Checkpatch cleanups for drivers/ps3/ps3-vuart.c
[10/16] PS3: Checkpatch cleanups for arch/powerpc/platforms/ps3/repository.c
[11/16] PS3: Add logical performance monitor repository routines
[12/16] PS3: Add logical performance monitor device support
[13/16] PS3: Add logical performance monitor driver support
[14/16] PS3: Vuart change semaphore to mutex
[15/16] PS3: Revove use lpar address workaround
[16/16] PS3: Update ps3_defconfig



-- 

^ permalink raw reply

* RE: Adding new driver in Linux 2.6 - read fails with -1
From: Jenkins, Clive @ 2008-01-18 20:15 UTC (permalink / raw)
  To: Ramkumar J; +Cc: linuxppc-embedded
In-Reply-To: <4f8c3030801180428k51645960sf0e1765f82eae1d8@mail.gmail.com>

> From: Ramkumar J [mailto:ramkumarj2000@gmail.com]=20
> Sent: 18 January 2008 12:29
> To: Jenkins, Clive
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: Adding new driver in Linux 2.6 - read fails with -1
> [...]
>=20
> Hi,
>=20
> Thanks a lot for replying. I will try using the perror() function and
> modify the  busy-loop through wait-for functions. Also, the way I have
> accessed the memory  mapped IO, is to ioremap() the physical address
> and then use readl() functions.  Is this correct.=20
>=20
> Following is the link to the driver file,
> http://www.geocities.com/ramkumarj_2000/impulse-stream.c
> http://www.geocities.com/ramkumarj_2000/1.txt as impulse-stream.h
>
> This is intermediate layer and part of my application space,
> http://www.geocities.com/ramkumarj_2000/co_stream_linux.c
>=20
> The application is,
> http://www.geocities.com/ramkumarj_2000/HelloWorld.c
> http://www.geocities.com/ramkumarj_2000/HelloWorld_sw.c
>=20
> Logs at,
> http://www.geocities.com/ramkumarj_2000/logs.txt
> http://www.geocities.com/ramkumarj_2000/kernellog.txt
>=20
> My apologies for the dirty code. To add some background, it starts
> from the main() in HelloWorld.c and it proceeds calling the
> hear_hello() in HelloWorld_sw.c . The co_stream_* functions are
> defined in intermediate layer co_stream_linux.c and co_stream_open
> is defined to nothing in one header file. The open and ioctl call
> ( modified a little in the driver now for debugging) map from
> co_stream_attach.=20
> co_stream_read is read and co_stream_write is the write to driver.
=20
> Though the logs indicate the call of release function before the
> read, I m not quite sure about this as the read not being called
> have failed to get inside the kernel messages.

I still can't see everything because the header files are not shown.

But anyway, it is getting too complex. I think you need to cut the code
down to the mininum that causes the error if you want help from the
list.

A couple of hints regarding the driver's read method:
1. If you really want to copy different data sizes into the same
variable
then use a union.
2. *(char*)buffer=3Dx puts x where buffer points to; I think you wanted
to put x into the variable buffer: *(char*)&buffer =3D x, but this is
not very clear -- better to use a union.
3. copy_{to,from)_user() return values that should be checked. Always
check function return values (except maybe printf and printk), and
display all error information.

Clive

^ permalink raw reply

* [patch 03/16] PS3: Add ps3_repository_find_device_by_id()
From: Geoff Levand @ 2008-01-18 20:30 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

The storage probe feature of the PS3 hypervisor returns device IDs. Add
the corresponding repository routine ps3_repository_find_device_by_id()
which can be used to retrieve the device info from the repository.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/platform.h   |    2 
 arch/powerpc/platforms/ps3/repository.c |   77 ++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -153,6 +153,8 @@ static inline struct ps3_repository_devi
 	return repo;
 }
 int ps3_repository_find_device(struct ps3_repository_device *repo);
+int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
+				     u64 bus_id, u64 dev_id);
 int ps3_repository_find_devices(enum ps3_bus_type bus_type,
 	int (*callback)(const struct ps3_repository_device *repo));
 int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -389,6 +389,83 @@ int ps3_repository_find_device(struct ps
 	return 0;
 }
 
+int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
+				     u64 bus_id, u64 dev_id)
+{
+	int result = -ENODEV;
+	struct ps3_repository_device tmp;
+	unsigned int num_dev;
+
+	pr_debug(" -> %s:%u: find device by id %lu:%lu\n", __func__, __LINE__,
+		 bus_id, dev_id);
+
+	for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
+		result = ps3_repository_read_bus_id(tmp.bus_index,
+						    &tmp.bus_id);
+		if (result) {
+			pr_debug("%s:%u read_bus_id(%u) failed\n", __func__,
+				 __LINE__, tmp.bus_index);
+			return result;
+		}
+
+		if (tmp.bus_id == bus_id)
+			goto found_bus;
+
+		pr_debug("%s:%u: skip, bus_id %lu\n", __func__, __LINE__,
+			 tmp.bus_id);
+	}
+	pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
+	return result;
+
+found_bus:
+	result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
+	if (result) {
+		pr_debug("%s:%u read_bus_type(%u) failed\n", __func__,
+			 __LINE__, tmp.bus_index);
+		return result;
+	}
+
+	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
+	if (result) {
+		pr_debug("%s:%u read_bus_num_dev failed\n", __func__,
+			 __LINE__);
+		return result;
+	}
+
+	for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
+		result = ps3_repository_read_dev_id(tmp.bus_index,
+						    tmp.dev_index,
+						    &tmp.dev_id);
+		if (result) {
+			pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__,
+				 __LINE__, tmp.bus_index, tmp.dev_index);
+			return result;
+		}
+
+		if (tmp.dev_id == dev_id)
+			goto found_dev;
+
+		pr_debug("%s:%u: skip, dev_id %lu\n", __func__, __LINE__,
+			 tmp.dev_id);
+	}
+	pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__);
+	return result;
+
+found_dev:
+	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
+					      &tmp.dev_type);
+	if (result) {
+		pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__);
+		return result;
+	}
+
+	pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%lu:%lu)\n",
+		 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
+		 tmp.dev_index, tmp.bus_id, tmp.dev_id);
+	*repo = tmp;
+	return 0;
+}
+
 int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,
 	int (*callback)(const struct ps3_repository_device *repo))
 {

-- 

^ permalink raw reply

* [patch 04/16] PS3: Use the HVs storage device notification mechanism properly
From: Geoff Levand @ 2008-01-18 20:30 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

The PS3 hypervisor has a storage device notification mechanism to wait until a
storage device is ready. Unfortunately the storage device probing code used
this mechanism in an incorrect way, needing a polling loop and handling of
devices that are not yet ready.

This change corrects this by:
  - First waiting for the reception of an asynchronous notification that a new
    storage device became ready,
  - Then looking up the storage device in the device repository.

On shutdown, the storage probe thread is stopped and the storage notification
device is closed using a reboot notifier.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/device-init.c |  422 ++++++++++++++++---------------
 arch/powerpc/platforms/ps3/platform.h    |    2 
 arch/powerpc/platforms/ps3/repository.c  |   29 --
 3 files changed, 221 insertions(+), 232 deletions(-)

--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 
 #include <asm/firmware.h>
 #include <asm/lv1call.h>
@@ -238,166 +239,6 @@ static int __init ps3_setup_vuart_device
 	return result;
 }
 
-static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,
-				       unsigned int timeout)
-{
-	int result = -1;
-	unsigned int retries = 0;
-	u64 status;
-
-	for (retries = 0; retries < timeout; retries++) {
-		result = lv1_storage_check_async_status(dev_id, tag, &status);
-		if (!result)
-			break;
-
-		msleep(1);
-	}
-
-	if (result)
-		pr_debug("%s:%u: check_async_status: %s, status %lx\n",
-			 __func__, __LINE__, ps3_result(result), status);
-
-	return result;
-}
-
-/**
- * ps3_storage_wait_for_device - Wait for a storage device to become ready.
- * @repo: The repository device to wait for.
- *
- * Uses the hypervisor's storage device notification mechanism to wait until
- * a storage device is ready.  The device notification mechanism uses a
- * psuedo device (id = -1) to asynchronously notify the guest when storage
- * devices become ready.  The notification device has a block size of 512
- * bytes.
- */
-
-static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo)
-{
-	int error = -ENODEV;
-	int result;
-	const u64 notification_dev_id = (u64)-1LL;
-	const unsigned int timeout = HZ;
-	u64 lpar;
-	u64 tag;
-	void *buf;
-	enum ps3_notify_type {
-		notify_device_ready = 0,
-		notify_region_probe = 1,
-		notify_region_update = 2,
-	};
-	struct {
-		u64 operation_code;	/* must be zero */
-		u64 event_mask;		/* OR of 1UL << enum ps3_notify_type */
-	} *notify_cmd;
-	struct {
-		u64 event_type;		/* enum ps3_notify_type */
-		u64 bus_id;
-		u64 dev_id;
-		u64 dev_type;
-		u64 dev_port;
-	} *notify_event;
-
-	pr_debug(" -> %s:%u: (%lu:%lu:%u)\n", __func__, __LINE__, repo->bus_id,
-		 repo->dev_id, repo->dev_type);
-
-	buf = kzalloc(512, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	lpar = ps3_mm_phys_to_lpar(__pa(buf));
-	notify_cmd = buf;
-	notify_event = buf;
-
-	result = lv1_open_device(repo->bus_id, notification_dev_id, 0);
-	if (result) {
-		printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,
-		       __LINE__, ps3_result(result));
-		goto fail_free;
-	}
-
-	/* Setup and write the request for device notification. */
-
-	notify_cmd->operation_code = 0; /* must be zero */
-	notify_cmd->event_mask = 1UL << notify_region_probe;
-
-	result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,
-				   &tag);
-	if (result) {
-		printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,
-		       ps3_result(result));
-		goto fail_close;
-	}
-
-	/* Wait for the write completion */
-
-	result = ps3stor_wait_for_completion(notification_dev_id, tag,
-					     timeout);
-	if (result) {
-		printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,
-		       __LINE__, ps3_result(result));
-		goto fail_close;
-	}
-
-	/* Loop here processing the requested notification events. */
-
-	while (1) {
-		memset(notify_event, 0, sizeof(*notify_event));
-
-		result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,
-					  lpar, &tag);
-		if (result) {
-			printk(KERN_ERR "%s:%u: write failed %s\n", __func__,
-			       __LINE__, ps3_result(result));
-			break;
-		}
-
-		result = ps3stor_wait_for_completion(notification_dev_id, tag,
-						     timeout);
-		if (result) {
-			printk(KERN_ERR "%s:%u: read not completed %s\n",
-			       __func__, __LINE__, ps3_result(result));
-			break;
-		}
-
-		pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, "
-			 "port %lu\n", __func__, __LINE__, repo->bus_index,
-			 repo->dev_index, repo->dev_type,
-			 notify_event->event_type, notify_event->dev_port);
-
-		if (notify_event->event_type != notify_region_probe ||
-		    notify_event->bus_id != repo->bus_id) {
-			pr_debug("%s:%u: bad notify_event: event %lu, "
-				 "dev_id %lu, dev_type %lu\n",
-				 __func__, __LINE__, notify_event->event_type,
-				 notify_event->dev_id, notify_event->dev_type);
-			break;
-		}
-
-		if (notify_event->dev_id == repo->dev_id &&
-		    notify_event->dev_type == repo->dev_type) {
-			pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__,
-				 __LINE__, repo->bus_index, repo->dev_index,
-				 repo->dev_type);
-			error = 0;
-			break;
-		}
-
-		if (notify_event->dev_id == repo->dev_id &&
-		    notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
-			pr_debug("%s:%u: no access: dev_id %lu\n", __func__,
-				 __LINE__, repo->dev_id);
-			break;
-		}
-	}
-
-fail_close:
-	lv1_close_device(repo->bus_id, notification_dev_id);
-fail_free:
-	kfree(buf);
-	pr_debug(" <- %s:%u\n", __func__, __LINE__);
-	return error;
-}
-
 static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
 				 enum ps3_match_id match_id)
 {
@@ -449,16 +290,6 @@ static int ps3_setup_storage_dev(const s
 		goto fail_find_interrupt;
 	}
 
-	/* FIXME: Arrange to only do this on a 'cold' boot */
-
-	result = ps3_storage_wait_for_device(repo);
-	if (result) {
-		printk(KERN_ERR "%s:%u: storage_notification failed %d\n",
-		       __func__, __LINE__, result);
-		result = -ENODEV;
-		goto fail_probe_notification;
-	}
-
 	for (i = 0; i < num_regions; i++) {
 		unsigned int id;
 		u64 start, size;
@@ -494,7 +325,6 @@ static int ps3_setup_storage_dev(const s
 
 fail_device_register:
 fail_read_region:
-fail_probe_notification:
 fail_find_interrupt:
 	kfree(p);
 fail_malloc:
@@ -659,62 +489,248 @@ static int ps3_register_repository_devic
 	return result;
 }
 
+
+#define PS3_NOTIFICATION_DEV_ID		ULONG_MAX
+#define PS3_NOTIFICATION_INTERRUPT_ID	0
+
+struct ps3_notification_device {
+	struct ps3_system_bus_device sbd;
+	spinlock_t lock;
+	u64 tag;
+	u64 lv1_status;
+	struct completion done;
+};
+
+enum ps3_notify_type {
+	notify_device_ready = 0,
+	notify_region_probe = 1,
+	notify_region_update = 2,
+};
+
+struct ps3_notify_cmd {
+	u64 operation_code;		/* must be zero */
+	u64 event_mask;			/* OR of 1UL << enum ps3_notify_type */
+};
+
+struct ps3_notify_event {
+	u64 event_type;			/* enum ps3_notify_type */
+	u64 bus_id;
+	u64 dev_id;
+	u64 dev_type;
+	u64 dev_port;
+};
+
+static irqreturn_t ps3_notification_interrupt(int irq, void *data)
+{
+	struct ps3_notification_device *dev = data;
+	int res;
+	u64 tag, status;
+
+	spin_lock(&dev->lock);
+	res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag,
+					   &status);
+	if (tag != dev->tag)
+		pr_err("%s:%u: tag mismatch, got %lx, expected %lx\n",
+		       __func__, __LINE__, tag, dev->tag);
+
+	if (res) {
+		pr_err("%s:%u: res %d status 0x%lx\n", __func__, __LINE__, res,
+		       status);
+	} else {
+		pr_debug("%s:%u: completed, status 0x%lx\n", __func__,
+			 __LINE__, status);
+		dev->lv1_status = status;
+		complete(&dev->done);
+	}
+	spin_unlock(&dev->lock);
+	return IRQ_HANDLED;
+}
+
+static int ps3_notification_read_write(struct ps3_notification_device *dev,
+				       u64 lpar, int write)
+{
+	const char *op = write ? "write" : "read";
+	unsigned long flags;
+	int res;
+
+	init_completion(&dev->done);
+	spin_lock_irqsave(&dev->lock, flags);
+	res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
+					&dev->tag)
+		    : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar,
+				       &dev->tag);
+	spin_unlock_irqrestore(&dev->lock, flags);
+	if (res) {
+		pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res);
+		return -EPERM;
+	}
+	pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);
+
+	res = wait_event_interruptible(dev->done.wait,
+				       dev->done.done || kthread_should_stop());
+	if (kthread_should_stop())
+		res = -EINTR;
+	if (res) {
+		pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op);
+		return res;
+	}
+
+	if (dev->lv1_status) {
+		pr_err("%s:%u: %s not completed, status 0x%lx\n", __func__,
+		       __LINE__, op, dev->lv1_status);
+		return -EIO;
+	}
+	pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op);
+
+	return 0;
+}
+
+static struct task_struct *probe_task;
+
 /**
  * ps3_probe_thread - Background repository probing at system startup.
  *
  * This implementation only supports background probing on a single bus.
+ * It uses the hypervisor's storage device notification mechanism to wait until
+ * a storage device is ready.  The device notification mechanism uses a
+ * pseudo device to asynchronously notify the guest when storage devices become
+ * ready.  The notification device has a block size of 512 bytes.
  */
 
 static int ps3_probe_thread(void *data)
 {
-	struct ps3_repository_device *repo = data;
-	int result;
-	unsigned int ms = 250;
+	struct ps3_notification_device dev;
+	struct ps3_repository_device repo;
+	int res;
+	unsigned int irq;
+	u64 lpar;
+	void *buf;
+	struct ps3_notify_cmd *notify_cmd;
+	struct ps3_notify_event *notify_event;
 
 	pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
 
-	do {
-		try_to_freeze();
+	buf = kzalloc(512, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
-		pr_debug("%s:%u: probing...\n", __func__, __LINE__);
+	lpar = ps3_mm_phys_to_lpar(__pa(buf));
+	notify_cmd = buf;
+	notify_event = buf;
 
-		do {
-			result = ps3_repository_find_device(repo);
+	/* dummy system bus device */
+	dev.sbd.bus_id = (u64)data;
+	dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;
+	dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;
+
+	res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0);
+	if (res) {
+		pr_err("%s:%u: lv1_open_device failed %s\n", __func__,
+		       __LINE__, ps3_result(res));
+		goto fail_free;
+	}
 
-			if (result == -ENODEV)
-				pr_debug("%s:%u: nothing new\n", __func__,
-					__LINE__);
-			else if (result)
-				pr_debug("%s:%u: find device error.\n",
-					__func__, __LINE__);
-			else {
-				pr_debug("%s:%u: found device (%u:%u:%u)\n",
-					 __func__, __LINE__, repo->bus_index,
-					 repo->dev_index, repo->dev_type);
-				ps3_register_repository_device(repo);
-				ps3_repository_bump_device(repo);
-				ms = 250;
-			}
-		} while (!result);
+	res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY,
+					      &irq);
+	if (res) {
+		pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
+		       __func__, __LINE__, res);
+	       goto fail_close_device;
+	}
+
+	spin_lock_init(&dev.lock);
+
+	res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
+			  "ps3_notification", &dev);
+	if (res) {
+		pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
+		       res);
+		goto fail_sb_event_receive_port_destroy;
+	}
 
-		pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms);
+	/* Setup and write the request for device notification. */
+	notify_cmd->operation_code = 0; /* must be zero */
+	notify_cmd->event_mask = 1UL << notify_region_probe;
 
-		if ( ms > 60000)
+	res = ps3_notification_read_write(&dev, lpar, 1);
+	if (res)
+		goto fail_free_irq;
+
+	/* Loop here processing the requested notification events. */
+	do {
+		try_to_freeze();
+
+		memset(notify_event, 0, sizeof(*notify_event));
+
+		res = ps3_notification_read_write(&dev, lpar, 0);
+		if (res)
 			break;
 
-		msleep_interruptible(ms);
+		pr_debug("%s:%u: notify event type 0x%lx bus id %lu dev id %lu"
+			 " type %lu port %lu\n", __func__, __LINE__,
+			 notify_event->event_type, notify_event->bus_id,
+			 notify_event->dev_id, notify_event->dev_type,
+			 notify_event->dev_port);
 
-		/* An exponential backoff. */
-		ms <<= 1;
+		if (notify_event->event_type != notify_region_probe ||
+		    notify_event->bus_id != dev.sbd.bus_id) {
+			pr_warning("%s:%u: bad notify_event: event %lu, "
+				   "dev_id %lu, dev_type %lu\n",
+				   __func__, __LINE__, notify_event->event_type,
+				   notify_event->dev_id,
+				   notify_event->dev_type);
+			continue;
+		}
+
+		res = ps3_repository_find_device_by_id(&repo, dev.sbd.bus_id,
+						       notify_event->dev_id);
+		if (res) {
+			pr_warning("%s:%u: device %lu:%lu not found\n",
+				   __func__, __LINE__, dev.sbd.bus_id,
+				   notify_event->dev_id);
+			continue;
+		}
+
+		pr_debug("%s:%u: device %lu:%lu found\n", __func__, __LINE__,
+			 dev.sbd.bus_id, notify_event->dev_id);
+		ps3_register_repository_device(&repo);
 
 	} while (!kthread_should_stop());
 
+fail_free_irq:
+	free_irq(irq, &dev);
+fail_sb_event_receive_port_destroy:
+	ps3_sb_event_receive_port_destroy(&dev.sbd, irq);
+fail_close_device:
+	lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id);
+fail_free:
+	kfree(buf);
+
+	probe_task = NULL;
+
 	pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__);
 
 	return 0;
 }
 
 /**
+ * ps3_stop_probe_thread - Stops the background probe thread.
+ *
+ */
+
+static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code,
+				 void *data)
+{
+	if (probe_task)
+		kthread_stop(probe_task);
+	return 0;
+}
+
+static struct notifier_block nb = {
+	.notifier_call = ps3_stop_probe_thread
+};
+
+/**
  * ps3_start_probe_thread - Starts the background probe thread.
  *
  */
@@ -723,7 +739,7 @@ static int __init ps3_start_probe_thread
 {
 	int result;
 	struct task_struct *task;
-	static struct ps3_repository_device repo; /* must be static */
+	struct ps3_repository_device repo;
 
 	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 
@@ -746,7 +762,8 @@ static int __init ps3_start_probe_thread
 		return -ENODEV;
 	}
 
-	task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type);
+	task = kthread_run(ps3_probe_thread, (void *)repo.bus_id,
+			   "ps3-probe-%u", bus_type);
 
 	if (IS_ERR(task)) {
 		result = PTR_ERR(task);
@@ -755,6 +772,9 @@ static int __init ps3_start_probe_thread
 		return result;
 	}
 
+	probe_task = task;
+	register_reboot_notifier(&nb);
+
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 	return 0;
 }
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -89,8 +89,6 @@ enum ps3_dev_type {
 	PS3_DEV_TYPE_STOR_ROM = TYPE_ROM,	/* 5 */
 	PS3_DEV_TYPE_SB_GPIO = 6,
 	PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC,	/* 14 */
-	PS3_DEV_TYPE_STOR_DUMMY = 32,
-	PS3_DEV_TYPE_NOACCESS = 255,
 };
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -344,35 +344,6 @@ int ps3_repository_find_device(struct ps
 		return result;
 	}
 
-	if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) {
-		/*
-		 * A storage device may show up in the repository before the
-		 * hypervisor has finished probing its type and regions
-		 */
-		unsigned int num_regions;
-
-		if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) {
-			pr_debug("%s:%u storage device not ready\n", __func__,
-				 __LINE__);
-			return -ENODEV;
-		}
-
-		result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index,
-								  tmp.dev_index,
-								  &num_regions);
-		if (result) {
-			pr_debug("%s:%d read_stor_dev_num_regions failed\n",
-				 __func__, __LINE__);
-			return result;
-		}
-
-		if (!num_regions) {
-			pr_debug("%s:%u storage device has no regions yet\n",
-				 __func__, __LINE__);
-			return -ENODEV;
-		}
-	}
-
 	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
 		&tmp.dev_id);
 

-- 

^ permalink raw reply

* [patch 02/16] PS3: Make bus_id and dev_id u64
From: Geoff Levand @ 2008-01-18 20:30 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Change the PS3 bus_id and dev_id from type unsigned int to u64.  These
IDs are 64-bit in the repository, and the special storage notification
device has a device ID of ULONG_MAX.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/device-init.c |    4 ++--
 arch/powerpc/platforms/ps3/mm.c          |    8 ++++----
 arch/powerpc/platforms/ps3/platform.h    |   12 ++++++------
 arch/powerpc/platforms/ps3/repository.c  |   21 ++++++++-------------
 arch/powerpc/platforms/ps3/system-bus.c  |   14 +++++++-------
 drivers/net/ps3_gelic_net.c              |    4 ++--
 include/asm-powerpc/ps3.h                |    4 ++--
 7 files changed, 31 insertions(+), 36 deletions(-)

--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -297,7 +297,7 @@ static int ps3_storage_wait_for_device(c
 		u64 dev_port;
 	} *notify_event;
 
-	pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id,
+	pr_debug(" -> %s:%u: (%lu:%lu:%u)\n", __func__, __LINE__, repo->bus_id,
 		 repo->dev_id, repo->dev_type);
 
 	buf = kzalloc(512, GFP_KERNEL);
@@ -384,7 +384,7 @@ static int ps3_storage_wait_for_device(c
 
 		if (notify_event->dev_id == repo->dev_id &&
 		    notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {
-			pr_debug("%s:%u: no access: dev_id %u\n", __func__,
+			pr_debug("%s:%u: no access: dev_id %lu\n", __func__,
 				 __LINE__, repo->dev_id);
 			break;
 		}
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -359,7 +359,7 @@ static unsigned long dma_sb_lpar_to_bus(
 static void  __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
 	const char *func, int line)
 {
-	DBG("%s:%d: dev        %u:%u\n", func, line, r->dev->bus_id,
+	DBG("%s:%d: dev        %lu:%lu\n", func, line, r->dev->bus_id,
 		r->dev->dev_id);
 	DBG("%s:%d: page_size  %u\n", func, line, r->page_size);
 	DBG("%s:%d: bus_addr   %lxh\n", func, line, r->bus_addr);
@@ -394,7 +394,7 @@ struct dma_chunk {
 static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
 	int line)
 {
-	DBG("%s:%d: r.dev        %u:%u\n", func, line,
+	DBG("%s:%d: r.dev        %lu:%lu\n", func, line,
 		c->region->dev->bus_id, c->region->dev->dev_id);
 	DBG("%s:%d: r.bus_addr   %lxh\n", func, line, c->region->bus_addr);
 	DBG("%s:%d: r.page_size  %u\n", func, line, c->region->page_size);
@@ -658,7 +658,7 @@ static int dma_sb_region_create(struct p
 	BUG_ON(!r);
 
 	if (!r->dev->bus_id) {
-		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+		pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
 			r->dev->bus_id, r->dev->dev_id);
 		return 0;
 	}
@@ -724,7 +724,7 @@ static int dma_sb_region_free(struct ps3
 	BUG_ON(!r);
 
 	if (!r->dev->bus_id) {
-		pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__,
+		pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
 			r->dev->bus_id, r->dev->dev_id);
 		return 0;
 	}
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -95,7 +95,7 @@ enum ps3_dev_type {
 
 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
 	u64 *value);
-int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id);
+int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id);
 int ps3_repository_read_bus_type(unsigned int bus_index,
 	enum ps3_bus_type *bus_type);
 int ps3_repository_read_bus_num_dev(unsigned int bus_index,
@@ -119,7 +119,7 @@ enum ps3_reg_type {
 int ps3_repository_read_dev_str(unsigned int bus_index,
 	unsigned int dev_index, const char *dev_str, u64 *value);
 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
-	unsigned int *dev_id);
+	u64 *dev_id);
 int ps3_repository_read_dev_type(unsigned int bus_index,
 	unsigned int dev_index, enum ps3_dev_type *dev_type);
 int ps3_repository_read_dev_intr(unsigned int bus_index,
@@ -138,12 +138,12 @@ int ps3_repository_read_dev_reg(unsigned
 /* repository bus enumerators */
 
 struct ps3_repository_device {
-	enum ps3_bus_type bus_type;
 	unsigned int bus_index;
-	unsigned int bus_id;
-	enum ps3_dev_type dev_type;
 	unsigned int dev_index;
-	unsigned int dev_id;
+	enum ps3_bus_type bus_type;
+	enum ps3_dev_type dev_type;
+	u64 bus_id;
+	u64 dev_id;
 };
 
 static inline struct ps3_repository_device *ps3_repository_bump_device(
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -168,18 +168,15 @@ int ps3_repository_read_bus_str(unsigned
 		value, 0);
 }
 
-int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id)
+int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
 {
 	int result;
-	u64 v1;
-	u64 v2; /* unused */
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
 		make_field("id", 0),
 		0, 0,
-		&v1, &v2);
-	*bus_id = v1;
+		bus_id, NULL);
 	return result;
 }
 
@@ -225,18 +222,16 @@ int ps3_repository_read_dev_str(unsigned
 }
 
 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
-	unsigned int *dev_id)
+	u64 *dev_id)
 {
 	int result;
-	u64 v1;
 
 	result = read_node(PS3_LPAR_ID_PME,
 		make_first_field("bus", bus_index),
 		make_field("dev", dev_index),
 		make_field("id", 0),
 		0,
-		&v1, 0);
-	*dev_id = v1;
+		dev_id, 0);
 	return result;
 }
 
@@ -332,7 +327,7 @@ int ps3_repository_find_device(struct ps
 		return result;
 	}
 
-	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",
+	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %lu, num_dev %u\n",
 		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
 		num_dev);
 
@@ -387,7 +382,7 @@ int ps3_repository_find_device(struct ps
 		return result;
 	}
 
-	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",
+	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %lu\n",
 		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
 
 	*repo = tmp;
@@ -1034,7 +1029,7 @@ static int dump_device_info(struct ps3_r
 			continue;
 		}
 
-		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
+		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %lu\n", __func__,
 			__LINE__, repo->bus_index, repo->dev_index,
 			repo->dev_type, repo->dev_id);
 
@@ -1091,7 +1086,7 @@ int ps3_repository_dump_bus_info(void)
 			continue;
 		}
 
-		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
+		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
 			__func__, __LINE__, repo.bus_index, repo.bus_type,
 			repo.bus_id, num_dev);
 
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -42,8 +42,8 @@ struct {
 	int gpu;
 } static usage_hack;
 
-static int ps3_is_device(struct ps3_system_bus_device *dev,
-			 unsigned int bus_id, unsigned int dev_id)
+static int ps3_is_device(struct ps3_system_bus_device *dev, u64 bus_id,
+			 u64 dev_id)
 {
 	return dev->bus_id == bus_id && dev->dev_id == dev_id;
 }
@@ -182,8 +182,8 @@ int ps3_open_hv_device(struct ps3_system
 	case PS3_MATCH_ID_SYSTEM_MANAGER:
 		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
 			__LINE__, dev->match_id);
-		pr_debug("%s:%d: bus_id: %u\n", __func__,
-			__LINE__, dev->bus_id);
+		pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
+			dev->bus_id);
 		BUG();
 		return -EINVAL;
 
@@ -220,8 +220,8 @@ int ps3_close_hv_device(struct ps3_syste
 	case PS3_MATCH_ID_SYSTEM_MANAGER:
 		pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
 			__LINE__, dev->match_id);
-		pr_debug("%s:%d: bus_id: %u\n", __func__,
-			__LINE__, dev->bus_id);
+		pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
+			dev->bus_id);
 		BUG();
 		return -EINVAL;
 
@@ -240,7 +240,7 @@ EXPORT_SYMBOL_GPL(ps3_close_hv_device);
 static void _dump_mmio_region(const struct ps3_mmio_region* r,
 	const char* func, int line)
 {
-	pr_debug("%s:%d: dev       %u:%u\n", func, line, r->dev->bus_id,
+	pr_debug("%s:%d: dev       %lu:%lu\n", func, line, r->dev->bus_id,
 		r->dev->dev_id);
 	pr_debug("%s:%d: bus_addr  %lxh\n", func, line, r->bus_addr);
 	pr_debug("%s:%d: len       %lxh\n", func, line, r->len);
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -58,11 +58,11 @@ static inline struct device *ctodev(stru
 {
 	return &card->dev->core;
 }
-static inline unsigned int bus_id(struct gelic_net_card *card)
+static inline u64 bus_id(struct gelic_net_card *card)
 {
 	return card->dev->bus_id;
 }
-static inline unsigned int dev_id(struct gelic_net_card *card)
+static inline u64 dev_id(struct gelic_net_card *card)
 {
 	return card->dev->dev_id;
 }
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -344,8 +344,8 @@ struct ps3_system_bus_device {
 	enum ps3_match_id match_id;
 	enum ps3_system_bus_device_type dev_type;
 
-	unsigned int bus_id;              /* SB */
-	unsigned int dev_id;              /* SB */
+	u64 bus_id;                       /* SB */
+	u64 dev_id;                       /* SB */
 	unsigned int interrupt_id;        /* SB */
 	struct ps3_dma_region *d_region;  /* SB, IOC0 */
 	struct ps3_mmio_region *m_region; /* SB, IOC0*/

-- 

^ permalink raw reply

* [patch 05/16] PS3: Add repository polling loop to work around timing bug
From: Geoff Levand @ 2008-01-18 20:30 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

PS3: Add repository polling loop to work around timing bug

On some firmware versions (e.g. 1.90), the storage device may not show up
in the repository immediately after receiving the notification message.
Add a small polling loop to make sure we don't miss it.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/device-init.c |   46 ++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 13 deletions(-)

--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -489,6 +489,38 @@ static int ps3_register_repository_devic
 	return result;
 }
 
+static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
+{
+	struct ps3_repository_device repo;
+	int res;
+	unsigned int retries;
+	unsigned long rem;
+
+	/*
+	 * On some firmware versions (e.g. 1.90), the device may not show up
+	 * in the repository immediately
+	 */
+	for (retries = 0; retries < 10; retries++) {
+		res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id);
+		if (!res)
+			goto found;
+
+		rem = msleep_interruptible(100);
+		if (rem)
+			break;
+	}
+	pr_warning("%s:%u: device %lu:%lu not found\n", __func__, __LINE__,
+		   bus_id, dev_id);
+	return;
+
+found:
+	if (retries)
+		pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
+			 __func__, __LINE__, bus_id, dev_id, retries);
+
+	ps3_register_repository_device(&repo);
+	return;
+}
 
 #define PS3_NOTIFICATION_DEV_ID		ULONG_MAX
 #define PS3_NOTIFICATION_INTERRUPT_ID	0
@@ -600,7 +632,6 @@ static struct task_struct *probe_task;
 static int ps3_probe_thread(void *data)
 {
 	struct ps3_notification_device dev;
-	struct ps3_repository_device repo;
 	int res;
 	unsigned int irq;
 	u64 lpar;
@@ -682,18 +713,7 @@ static int ps3_probe_thread(void *data)
 			continue;
 		}
 
-		res = ps3_repository_find_device_by_id(&repo, dev.sbd.bus_id,
-						       notify_event->dev_id);
-		if (res) {
-			pr_warning("%s:%u: device %lu:%lu not found\n",
-				   __func__, __LINE__, dev.sbd.bus_id,
-				   notify_event->dev_id);
-			continue;
-		}
-
-		pr_debug("%s:%u: device %lu:%lu found\n", __func__, __LINE__,
-			 dev.sbd.bus_id, notify_event->dev_id);
-		ps3_register_repository_device(&repo);
+		ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);
 
 	} while (!kthread_should_stop());
 

-- 

^ permalink raw reply

* [patch 01/16] POWERPC: Add Cell SPRN bookmark register
From: Geoff Levand @ 2008-01-18 20:29 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <20080118202612.422185192@am.sony.com>

Add a definition for the Cell SPRN bookmark register
to asm-powerpc/regs.h

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 include/asm-powerpc/reg.h |    1 +
 1 file changed, 1 insertion(+)

--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -553,6 +553,7 @@
 #define SPRN_PA6T_BTCR	978	/* Breakpoint and Tagging Control Register */
 #define SPRN_PA6T_IMAAT	979	/* Instruction Match Array Action Table */
 #define SPRN_PA6T_PCCR	1019	/* Power Counter Control Register */
+#define SPRN_BKMK	1020	/* Cell Bookmark Register */
 #define SPRN_PA6T_RPCCR	1021	/* Retire PC Trace Control Register */
 
 

-- 

^ permalink raw reply

* [patch 06/16] PS3: Kill unused ps3_repository_bump_device()
From: Geoff Levand @ 2008-01-18 20:32 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

PS3: Kill unused routine ps3_repository_bump_device().

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/platform.h |    6 ------
 1 files changed, 6 deletions(-)

--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -144,12 +144,6 @@ struct ps3_repository_device {
 	u64 dev_id;
 };
 
-static inline struct ps3_repository_device *ps3_repository_bump_device(
-	struct ps3_repository_device *repo)
-{
-	repo->dev_index++;
-	return repo;
-}
 int ps3_repository_find_device(struct ps3_repository_device *repo);
 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
 				     u64 bus_id, u64 dev_id);

-- 

^ permalink raw reply

* [patch 08/16] PS3: Checkpatch cleanups for drivers/ps3/ps3-sys-manager.c
From: Geoff Levand @ 2008-01-18 20:32 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Cleanup coding errors in drivers/ps3/ps3-sys-manager.c as reported
by checkpatch.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 drivers/ps3/ps3-sys-manager.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

--- a/drivers/ps3/ps3-sys-manager.c
+++ b/drivers/ps3/ps3-sys-manager.c
@@ -452,7 +452,7 @@ static int ps3_sys_manager_handle_event(
 	case PS3_SM_EVENT_THERMAL_ALERT:
 		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
 			__func__, __LINE__, event.value);
-		printk(KERN_INFO "PS3 Thermal Alert Zone %u\n", event.value);
+		pr_info("PS3 Thermal Alert Zone %u\n", event.value);
 		break;
 	case PS3_SM_EVENT_THERMAL_CLEARED:
 		dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
@@ -488,7 +488,7 @@ static int ps3_sys_manager_handle_cmd(st
 	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
 	BUG_ON(result && "need to retry here");
 
-	if(result)
+	if (result)
 		return result;
 
 	if (cmd.version != 1) {
@@ -521,7 +521,7 @@ static int ps3_sys_manager_handle_msg(st
 	result = ps3_vuart_read(dev, &header,
 		sizeof(struct ps3_sys_manager_header));
 
-	if(result)
+	if (result)
 		return result;
 
 	if (header.version != 1) {
@@ -589,9 +589,9 @@ static void ps3_sys_manager_final_power_
 		PS3_SM_WAKE_DEFAULT);
 	ps3_sys_manager_send_request_shutdown(dev);
 
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	pr_emerg("System Halted, OK to turn off power\n");
 
-	while(1)
+	while (1)
 		ps3_sys_manager_handle_msg(dev);
 }
 
@@ -626,9 +626,9 @@ static void ps3_sys_manager_final_restar
 		PS3_SM_WAKE_DEFAULT);
 	ps3_sys_manager_send_request_shutdown(dev);
 
-	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	pr_emerg("System Halted, OK to turn off power\n");
 
-	while(1)
+	while (1)
 		ps3_sys_manager_handle_msg(dev);
 }
 

-- 

^ permalink raw reply

* [patch 07/16] PS3: Refactor ps3_repository_find_device()
From: Geoff Levand @ 2008-01-18 20:32 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

PS3: Refactor ps3_repository_find_device() to use the existing
ps3_repository_read_bus_id() routine.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 arch/powerpc/platforms/ps3/repository.c |   60 +++++++++++---------------------
 1 files changed, 22 insertions(+), 38 deletions(-)

--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -445,50 +445,34 @@ int __devinit ps3_repository_find_device
 
 	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
 
-	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
+	repo.bus_type = bus_type;
+	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
+	if (result) {
+		pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
+		return result;
+	}
 
-		result = ps3_repository_read_bus_type(repo.bus_index,
-			&repo.bus_type);
+	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
+	if (result) {
+		pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
+			 repo.bus_index);
+		return result;
+	}
 
-		if (result) {
-			pr_debug("%s:%d read_bus_type(%u) failed\n",
-				__func__, __LINE__, repo.bus_index);
+	for (repo.dev_index = 0; ; repo.dev_index++) {
+		result = ps3_repository_find_device(&repo);
+		if (result == -ENODEV) {
+			result = 0;
+			break;
+		} else if (result)
 			break;
-		}
-
-		if (repo.bus_type != bus_type) {
-			pr_debug("%s:%d: skip, bus_type %u\n", __func__,
-				__LINE__, repo.bus_type);
-			continue;
-		}
-
-		result = ps3_repository_read_bus_id(repo.bus_index,
-			&repo.bus_id);
 
+		result = callback(&repo);
 		if (result) {
-			pr_debug("%s:%d read_bus_id(%u) failed\n",
-				__func__, __LINE__, repo.bus_index);
-			continue;
-		}
-
-		for (repo.dev_index = 0; ; repo.dev_index++) {
-			result = ps3_repository_find_device(&repo);
-
-			if (result == -ENODEV) {
-				result = 0;
-				break;
-			} else if (result)
-				break;
-
-			result = callback(&repo);
-
-			if (result) {
-				pr_debug("%s:%d: abort at callback\n", __func__,
-					__LINE__);
-				break;
-			}
+			pr_debug("%s:%d: abort at callback\n", __func__,
+				__LINE__);
+			break;
 		}
-		break;
 	}
 
 	pr_debug(" <- %s:%d\n", __func__, __LINE__);

-- 

^ permalink raw reply

* [patch 09/16] PS3: Checkpatch cleanups for drivers/ps3/ps3-vuart.c
From: Geoff Levand @ 2008-01-18 20:32 UTC (permalink / raw)
  To: paulus; +Cc: Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <20080118202612.422185192@am.sony.com>

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Cleanup coding errors in drivers/ps3/ps3-vuart.c as reported by
checkpatch.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 drivers/ps3/ps3-vuart.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

--- a/drivers/ps3/ps3-vuart.c
+++ b/drivers/ps3/ps3-vuart.c
@@ -108,18 +108,18 @@ static struct ps3_vuart_port_priv *to_po
 struct ports_bmp {
 	u64 status;
 	u64 unused[3];
-} __attribute__ ((aligned (32)));
+} __attribute__((aligned(32)));
 
 #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__)
 static void __maybe_unused _dump_ports_bmp(
-	const struct ports_bmp* bmp, const char* func, int line)
+	const struct ports_bmp *bmp, const char *func, int line)
 {
 	pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
 }
 
 #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
 static void __maybe_unused _dump_port_params(unsigned int port_number,
-	const char* func, int line)
+	const char *func, int line)
 {
 #if defined(DEBUG)
 	static const char *strings[] = {
@@ -363,7 +363,7 @@ int ps3_vuart_disable_interrupt_disconne
  */
 
 static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
-	const void* buf, unsigned int bytes, unsigned long *bytes_written)
+	const void *buf, unsigned int bytes, unsigned long *bytes_written)
 {
 	int result;
 	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
@@ -431,7 +431,7 @@ void ps3_vuart_clear_rx_bytes(struct ps3
 	int result;
 	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
 	u64 bytes_waiting;
-	void* tmp;
+	void *tmp;
 
 	result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting);
 
@@ -526,9 +526,8 @@ int ps3_vuart_write(struct ps3_system_bu
 
 	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
 
-	if (!lb) {
+	if (!lb)
 		return -ENOMEM;
-	}
 
 	memcpy(lb->data, buf, bytes);
 	lb->head = lb->data;
@@ -926,9 +925,8 @@ static int ps3_vuart_bus_interrupt_get(v
 
 	BUG_ON(vuart_bus_priv.use_count > 2);
 
-	if (vuart_bus_priv.use_count != 1) {
+	if (vuart_bus_priv.use_count != 1)
 		return 0;
-	}
 
 	BUG_ON(vuart_bus_priv.bmp);
 

-- 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox