LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 03/11] powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips
From: Timur Tabi @ 2010-10-08 19:28 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1286564813-21209-3-git-send-email-galak@kernel.crashing.org>

On Fri, Oct 8, 2010 at 2:06 PM, Kumar Gala <galak@kernel.crashing.org> wrot=
e:

> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.=
c
> index 32012a2..4d0b249 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
> @@ -417,10 +417,18 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P201=
0E, quirk_fsl_pcie_header);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_h=
eader);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_=
header);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_h=
eader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_he=
ader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_hea=
der);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_he=
ader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_hea=
der);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_=
header);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_h=
eader);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_=
header);
> =A0DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_h=
eader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_he=
ader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_hea=
der);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_he=
ader);
> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_hea=
der);

Do we really need to add an entry for each new chip?  This table now
has almost three dozen entries, and they all same the same thing.
Can't we just assume that if the vendor ID is 0x1957, that we should
default to quirk_fsl_pcie_header unless there's another entry
somewhere else?

--=20
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [PATCH 03/11] powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips
From: Kumar Gala @ 2010-10-08 19:24 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1286564813-21209-3-git-send-email-galak@kernel.crashing.org>


On Oct 8, 2010, at 2:06 PM, Kumar Gala wrote:

> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
> arch/powerpc/sysdev/fsl_pci.c |    8 ++++++++
> include/linux/pci_ids.h       |    8 ++++++++
> 2 files changed, 16 insertions(+), 0 deletions(-)

applied to next

- k

^ permalink raw reply

* Re: [PATCH 03/11] powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips
From: Kumar Gala @ 2010-10-08 20:20 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev
In-Reply-To: <AANLkTimRGqcDOeR92m0CQZHTxSNSm=D8sZni0zw-He11@mail.gmail.com>


On Oct 8, 2010, at 2:28 PM, Timur Tabi wrote:

> On Fri, Oct 8, 2010 at 2:06 PM, Kumar Gala <galak@kernel.crashing.org> =
wrote:
>=20
>> diff --git a/arch/powerpc/sysdev/fsl_pci.c =
b/arch/powerpc/sysdev/fsl_pci.c
>> index 32012a2..4d0b249 100644
>> --- a/arch/powerpc/sysdev/fsl_pci.c
>> +++ b/arch/powerpc/sysdev/fsl_pci.c
>> @@ -417,10 +417,18 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, =
PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, =
quirk_fsl_pcie_header);
>>  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, =
quirk_fsl_pcie_header);
>> +DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, =
quirk_fsl_pcie_header);
>=20
> Do we really need to add an entry for each new chip?  This table now
> has almost three dozen entries, and they all same the same thing.
> Can't we just assume that if the vendor ID is 0x1957, that we should
> default to quirk_fsl_pcie_header unless there's another entry
> somewhere else?

Unfortunately we can't assume if 0x1957 is other FSL devices that are =
not PPC SoC would use that Vendor ID.

I'll ponder if we can handle this some other more generic way to do =
detection, but for now we'll keep adding to the list.

- k=

^ permalink raw reply

* [PATCH v2 1/3] Powerpc/4xx: Add suspend and idle support
From: Victor Gallardo @ 2010-10-08 20:25 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Victor Gallardo

Add suspend/resume support for 4xx compatible CPUs.
See /sys/power/state for available power states
configured in.

Add two different idle states (idle-wait and idle-doze)
controlled via sysfs. Default is idle-wait.
	cat /sys/devices/system/cpu/cpu0/idle
	[wait] doze

To save additional power, use idle-doze.
	echo doze > /sys/devices/system/cpu/cpu0/idle
	cat /sys/devices/system/cpu/cpu0/idle
	wait [doze]

Signed-off-by: Victor Gallardo <vgallardo@apm.com>
---
 v2: Add additional comments as suggested by Josh Boyer

 Documentation/powerpc/dts-bindings/4xx/cpm.txt |   43 +++
 arch/powerpc/Kconfig                           |   13 +-
 arch/powerpc/platforms/44x/Makefile            |    5 +-
 arch/powerpc/sysdev/Makefile                   |    1 +
 arch/powerpc/sysdev/ppc4xx_cpm.c               |  339 ++++++++++++++++++++++++
 5 files changed, 397 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/4xx/cpm.txt
 create mode 100644 arch/powerpc/sysdev/ppc4xx_cpm.c

diff --git a/Documentation/powerpc/dts-bindings/4xx/cpm.txt b/Documentation/powerpc/dts-bindings/4xx/cpm.txt
new file mode 100644
index 0000000..9635df8
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/4xx/cpm.txt
@@ -0,0 +1,52 @@
+PPC4xx Clock Power Management (CPM) node
+
+Required properties:
+	- compatible		: compatible list, currently only "ibm,cpm"
+	- dcr-access-method	: "native"
+	- dcr-reg		: < DCR register range >
+
+Optional properties:
+	- er-offset		: All 4xx SoCs with a CPM controller have
+				  one of two different order for the CPM
+				  registers. Some have the CPM registers
+				  in the following order (ER,FR,SR). The
+				  others have them in the following order
+				  (SR,ER,FR). For the second case set
+				  er-offset = <1>.
+	- unused-units		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set to turn off unused
+				  devices.
+	- idle-doze		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set to turn off unused
+				  devices. This is usually just CPM[CPU].
+	- standby		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set on standby and
+				  restored on resume.
+	- suspend		: specifier consist of one cell. For each
+				  bit in the cell, the corresponding bit
+				  in CPM will be set on suspend (mem) and
+				  restored on resume. Note, for standby
+				  and suspend the corresponding bits can
+				  be different or the same. Usually for
+				  standby only class 2 and 3 units are set.
+				  However, the interface does not care.
+				  If they are the same, the additional
+				  power saving will be seeing if support
+				  is available to put the DDR in self
+				  refresh mode and any additional power
+				  saving techniques for the specific SoC.
+
+Example:
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x160 0x003>;
+		er-offset = <0>;
+		unused-units = <0x00000100>;
+		idle-doze = <0x02000000>;
+		standby = <0xfeff0000>;
+		suspend = <0xfeff791d>;
+};
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..10b2f15 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -210,7 +210,7 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   PPC_85xx || PPC_86xx || PPC_PSERIES
+		   PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x
 
 config PPC_DCR_NATIVE
 	bool
@@ -596,13 +596,11 @@ config EXTRA_TARGETS
 
 	  If unsure, leave blank
 
-if !44x || BROKEN
 config ARCH_WANTS_FREEZER_CONTROL
 	def_bool y
 	depends on ADB_PMU
 
 source kernel/power/Kconfig
-endif
 
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
@@ -683,6 +681,15 @@ config FSL_PMC
 	  Freescale MPC85xx/MPC86xx power management controller support
 	  (suspend/resume). For MPC83xx see platforms/83xx/suspend.c
 
+config PPC4xx_CPM
+	bool
+	default y
+	depends on SUSPEND && (44x || 40x)
+	help
+	  PPC4xx Clock Power Management (CPM) support (suspend/resume).
+	  It also enables support for two different idle states (idle-wait
+	  and idle-doze).
+
 config 4xx_SOC
 	bool
 
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 82ff326..c04d16d 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -1,4 +1,7 @@
-obj-$(CONFIG_44x)	:= misc_44x.o idle.o
+obj-$(CONFIG_44x)	+= misc_44x.o
+ifneq ($(CONFIG_PPC4xx_CPM),y)
+obj-$(CONFIG_44x)	+= idle.o
+endif
 obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o
 obj-$(CONFIG_EBONY)	+= ebony.o
 obj-$(CONFIG_SAM440EP) 	+= sam440ep.o
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5642924..a9728d1 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_OF_RTC)		+= of_rtc.o
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_4xx)		+= ppc4xx_pci.o
 endif
+obj-$(CONFIG_PPC4xx_CPM)	+= ppc4xx_cpm.o
 obj-$(CONFIG_PPC4xx_GPIO)	+= ppc4xx_gpio.o
 
 obj-$(CONFIG_CPM)		+= cpm_common.o
diff --git a/arch/powerpc/sysdev/ppc4xx_cpm.c b/arch/powerpc/sysdev/ppc4xx_cpm.c
new file mode 100644
index 0000000..d47a7ed
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_cpm.c
@@ -0,0 +1,346 @@
+/*
+ * PowerPC 4xx Clock and Power Management
+ *
+ * Copyright (C) 2010, Applied Micro Circuits Corporation
+ * Victor Gallardo (vgallardo@apm.com)
+ *
+ * Based on arch/powerpc/platforms/44x/idle.c:
+ * Jerone Young <jyoung5@us.ibm.com>
+ * Copyright 2008 IBM Corp.
+ *
+ * Based on arch/powerpc/sysdev/fsl_pmc.c:
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Copyright 2009  MontaVista Software, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/sysfs.h>
+#include <linux/cpu.h>
+#include <linux/suspend.h>
+#include <asm/dcr.h>
+#include <asm/dcr-native.h>
+#include <asm/machdep.h>
+
+#define CPM_ER	0
+#define CPM_FR	1
+#define CPM_SR	2
+
+#define CPM_IDLE_WAIT	0
+#define CPM_IDLE_DOZE	1
+
+struct cpm {
+	dcr_host_t	dcr_host;
+	unsigned int	dcr_offset[3];
+	unsigned int	powersave_off;
+	unsigned int	unused;
+	unsigned int	idle_doze;
+	unsigned int	standby;
+	unsigned int	suspend;
+};
+
+static struct cpm cpm;
+
+struct cpm_idle_mode {
+	unsigned int enabled;
+	const char  *name;
+};
+
+static struct cpm_idle_mode idle_mode[] = {
+	[CPM_IDLE_WAIT] = { 1, "wait" }, /* default */
+	[CPM_IDLE_DOZE] = { 0, "doze" },
+};
+
+static unsigned int cpm_set(unsigned int cpm_reg, unsigned int mask)
+{
+	unsigned int value;
+
+	/* CPM controller supports 3 different types of sleep interface
+	 * known as class 1, 2 and 3. For class 1 units, they are
+	 * unconditionally put to sleep when the corresponding CPM bit is
+	 * set. For class 2 and 3 units this is not case; if they can be
+	 * put to to sleep, they will. Here we do not verify, we just
+	 * set them and expect them to eventually go off when they can.
+	 */
+	value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]);
+	dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value | mask);
+
+	/* return old state, to restore later if needed */
+	return value;
+}
+
+static void cpm_idle_wait(void)
+{
+	unsigned long msr_save;
+
+	/* save off initial state */
+	msr_save = mfmsr();
+	/* sync required when CPM0_ER[CPU] is set */
+	mb();
+	/* set wait state MSR */
+	mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
+	isync();
+	/* return to initial state */
+	mtmsr(msr_save);
+	isync();
+}
+
+static void cpm_idle_sleep(unsigned int mask)
+{
+	unsigned int er_save;
+
+	/* update CPM_ER state */
+	er_save = cpm_set(CPM_ER, mask);
+
+	/* go to wait state so that CPM0_ER[CPU] can take effect */
+	cpm_idle_wait();
+
+	/* restore CPM_ER state */
+	dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save);
+}
+
+static void cpm_idle_doze(void)
+{
+	cpm_idle_sleep(cpm.idle_doze);
+}
+
+static void cpm_idle_config(int mode)
+{
+	int i;
+
+	if (idle_mode[mode].enabled)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++)
+		idle_mode[i].enabled = 0;
+
+	idle_mode[mode].enabled = 1;
+}
+
+static ssize_t cpm_idle_show(struct kobject *kobj,
+			     struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
+		if (idle_mode[i].enabled)
+			s += sprintf(s, "[%s] ", idle_mode[i].name);
+		else
+			s += sprintf(s, "%s ", idle_mode[i].name);
+	}
+
+	*(s-1) = '\n'; /* convert the last space to a newline */
+
+	return s - buf;
+}
+
+static ssize_t cpm_idle_store(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      const char *buf, size_t n)
+{
+	int i;
+	char *p;
+	int len;
+
+	p = memchr(buf, '\n', n);
+	len = p ? p - buf : n;
+
+	for (i = 0; i < ARRAY_SIZE(idle_mode); i++) {
+		if (strncmp(buf, idle_mode[i].name, len) == 0) {
+			cpm_idle_config(i);
+			return n;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static struct kobj_attribute cpm_idle_attr =
+	__ATTR(idle, 0644, cpm_idle_show, cpm_idle_store);
+
+static void cpm_idle_config_sysfs(void)
+{
+	struct sys_device *sys_dev;
+	unsigned long ret;
+
+	sys_dev = get_cpu_sysdev(0);
+
+	ret = sysfs_create_file(&sys_dev->kobj,
+				&cpm_idle_attr.attr);
+	if (ret)
+		printk(KERN_WARNING
+		       "cpm: failed to create idle sysfs entry\n");
+}
+
+static void cpm_idle(void)
+{
+	if (idle_mode[CPM_IDLE_DOZE].enabled)
+		cpm_idle_doze();
+	else
+		cpm_idle_wait();
+}
+
+static int cpm_suspend_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return !!cpm.standby;
+	case PM_SUSPEND_MEM:
+		return !!cpm.suspend;
+	default:
+		return 0;
+	}
+}
+
+static void cpm_suspend_standby(unsigned int mask)
+{
+	unsigned long tcr_save;
+
+	/* disable decrement interrupt */
+	tcr_save = mfspr(SPRN_TCR);
+	mtspr(SPRN_TCR, tcr_save & ~TCR_DIE);
+
+	/* go to sleep state */
+	cpm_idle_sleep(mask);
+
+	/* restore decrement interrupt */
+	mtspr(SPRN_TCR, tcr_save);
+}
+
+static int cpm_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		cpm_suspend_standby(cpm.standby);
+		break;
+	case PM_SUSPEND_MEM:
+		cpm_suspend_standby(cpm.suspend);
+		break;
+	}
+
+	return 0;
+}
+
+static struct platform_suspend_ops cpm_suspend_ops = {
+	.valid		= cpm_suspend_valid,
+	.enter		= cpm_suspend_enter,
+};
+
+static int cpm_get_uint_property(struct device_node *np,
+				 const char *name)
+{
+	int len;
+	const unsigned int *prop = of_get_property(np, name, &len);
+
+	if (prop == NULL || len < sizeof(u32))
+		return 0;
+
+	return *prop;
+}
+
+static int __init cpm_init(void)
+{
+	struct device_node *np;
+	int dcr_base, dcr_len;
+	int ret = 0;
+
+	if (!cpm.powersave_off) {
+		cpm_idle_config(CPM_IDLE_WAIT);
+		ppc_md.power_save = &cpm_idle;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,cpm");
+	if (!np) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dcr_base = dcr_resource_start(np, 0);
+	dcr_len = dcr_resource_len(np, 0);
+
+	if (dcr_base == 0 || dcr_len == 0) {
+		printk(KERN_ERR "cpm: could not parse dcr property for %s\n",
+		       np->full_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	cpm.dcr_host = dcr_map(np, dcr_base, dcr_len);
+
+	if (!DCR_MAP_OK(cpm.dcr_host)) {
+		printk(KERN_ERR "cpm: failed to map dcr property for %s\n",
+		       np->full_name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* All 4xx SoCs with a CPM controller have one of two
+	 * different order for the CPM registers. Some have the
+	 * CPM registers in the following order (ER,FR,SR). The
+	 * others have them in the following order (SR,ER,FR).
+	 */
+
+	if (cpm_get_uint_property(np, "er-offset") == 0) {
+		cpm.dcr_offset[CPM_ER] = 0;
+		cpm.dcr_offset[CPM_FR] = 1;
+		cpm.dcr_offset[CPM_SR] = 2;
+	} else {
+		cpm.dcr_offset[CPM_ER] = 1;
+		cpm.dcr_offset[CPM_FR] = 2;
+		cpm.dcr_offset[CPM_SR] = 0;
+	}
+
+	/* Now let's see what IPs to turn off for the following modes */
+
+	cpm.unused = cpm_get_uint_property(np, "unused-units");
+	cpm.idle_doze = cpm_get_uint_property(np, "idle-doze");
+	cpm.standby = cpm_get_uint_property(np, "standby");
+	cpm.suspend = cpm_get_uint_property(np, "suspend");
+
+	/* If some IPs are unused let's turn them off now */
+
+	if (cpm.unused) {
+		cpm_set(CPM_ER, cpm.unused);
+		cpm_set(CPM_FR, cpm.unused);
+	}
+
+	/* Now let's export interfaces */
+
+	if (!cpm.powersave_off && cpm.idle_doze)
+		cpm_idle_config_sysfs();
+
+	if (cpm.standby || cpm.suspend)
+		suspend_set_ops(&cpm_suspend_ops);
+out:
+	if (np)
+		of_node_put(np);
+	return ret;
+}
+
+late_initcall(cpm_init);
+
+static int __init cpm_powersave_off(char *arg)
+{
+	cpm.powersave_off = 1;
+	return 0;
+}
+__setup("powersave=off", cpm_powersave_off);
-- 
1.6.1.rc3

^ permalink raw reply related

* [PATCH v2 2/3] powerpc/4xx: Add Canyonlands suspend and idle support
From: Victor Gallardo @ 2010-10-08 20:25 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Victor Gallardo

- Add Clock Power Management (CPM) node to dts tree
- Add idle-doze entry in CPM node
- Add standby entry in CPM node
- Add PM and SUSPEND support by default in defconfig
- Remove UART2 and UART3 as they are unused, this will
  allow CPM to put unused-units (UART2 and UART3) to sleep.

Signed-off-by: Victor Gallardo <vgallardo@apm.com>
---
 arch/powerpc/boot/dts/canyonlands.dts          |   31 +++++++-----------------
 arch/powerpc/configs/44x/canyonlands_defconfig |    3 ++
 2 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index a303703..5b27a4b 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -105,6 +105,15 @@
 		dcr-reg = <0x00c 0x002>;
 	};
 
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x160 0x003>;
+		unused-units = <0x00000100>;
+		idle-doze = <0x02000000>;
+		standby = <0xfeff791d>;
+	};
+
 	L2C0: l2c {
 		compatible = "ibm,l2-cache-460ex", "ibm,l2-cache";
 		dcr-reg = <0x020 0x008		/* Internal SRAM DCR's */
@@ -270,28 +279,6 @@
 				interrupts = <0x1 0x4>;
 			};
 
-			UART2: serial@ef600500 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600500 0x00000008>;
-				virtual-reg = <0xef600500>;
-				clock-frequency = <0>; /* Filled in by U-Boot */
-				current-speed = <0>; /* Filled in by U-Boot */
-				interrupt-parent = <&UIC1>;
-				interrupts = <28 0x4>;
-			};
-
-			UART3: serial@ef600600 {
-				device_type = "serial";
-				compatible = "ns16550";
-				reg = <0xef600600 0x00000008>;
-				virtual-reg = <0xef600600>;
-				clock-frequency = <0>; /* Filled in by U-Boot */
-				current-speed = <0>; /* Filled in by U-Boot */
-				interrupt-parent = <&UIC1>;
-				interrupts = <29 0x4>;
-			};
-
 			IIC0: i2c@ef600700 {
 				compatible = "ibm,iic-460ex", "ibm,iic";
 				reg = <0xef600700 0x00000014>;
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index 45c64d8..17e4dd9 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -42,6 +42,9 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_NDFC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_PPC4xx_CPM=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
-- 
1.6.1.rc3

^ permalink raw reply related

* [PATCH v2 3/3] powerpc/4xx: Add Kilauea suspend and idle support
From: Victor Gallardo @ 2010-10-08 20:26 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Victor Gallardo

- Add Clock Power Management (CPM) node to dts tree
- Add idle-doze entry in CPM node
- Add standby entry in CPM node
- Add PM and SUSPEND support by default in defconfig
- Add NO_HZ and CONFIG_HIGH_RES_TIMERS support by
  default in defconfig

Signed-off-by: Victor Gallardo <vgallardo@apm.com>
---
 arch/powerpc/boot/dts/kilauea.dts          |    9 +++++++++
 arch/powerpc/configs/40x/kilauea_defconfig |    5 +++++
 2 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
index 083e68e..89edb16 100644
--- a/arch/powerpc/boot/dts/kilauea.dts
+++ b/arch/powerpc/boot/dts/kilauea.dts
@@ -82,6 +82,15 @@
 		interrupt-parent = <&UIC0>;
 	};
 
+	CPM0: cpm {
+		compatible = "ibm,cpm";
+		dcr-access-method = "native";
+		dcr-reg = <0x0b0 0x003>;
+		unused-units = <0x00000000>;
+		idle-doze = <0x02000000>;
+		standby = <0xe3e74800>;
+	};
+
 	plb {
 		compatible = "ibm,plb-405ex", "ibm,plb4";
 		#address-cells = <1>;
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
index 4e19ee7..34b8c1a 100644
--- a/arch/powerpc/configs/40x/kilauea_defconfig
+++ b/arch/powerpc/configs/40x/kilauea_defconfig
@@ -12,6 +12,8 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_KILAUEA=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_WALNUT is not set
 CONFIG_SPARSE_IRQ=y
 CONFIG_PCI=y
@@ -42,6 +44,9 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_NDFC=y
 CONFIG_PROC_DEVICETREE=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_PPC4xx_CPM=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=35000
 # CONFIG_MISC_DEVICES is not set
-- 
1.6.1.rc3

^ permalink raw reply related

* Re: [PATCH 07/11] powerpc/fsl-booke: Add support for FSL 64-bit e5500 core
From: Scott Wood @ 2010-10-08 20:55 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <1286564813-21209-7-git-send-email-galak@kernel.crashing.org>

On Fri, 8 Oct 2010 14:06:49 -0500
Kumar Gala <galak@kernel.crashing.org> wrote:

> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
> index d361f81..19083b3 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -132,13 +132,18 @@ config PPC_E500MC
>  	select PPC_FPU
>  	depends on E500
>  
> +config PPC_E5500
> +	bool
> +	select PPC_FPU
> +	select PPC_E500MC if PPC32

Currently E500MC implies E500.  With this, E5500 would not imply E500
-- hence all the ifdefs with E500 || E5500 that this adds.  When would
we want to ifdef E500 or E500MC but not E5500?

Given how similar e500mc and e5500 are, I think we should just use
CONFIG_E500MC for it.  Any 32/64-bit distinctions would just check
CONFIG_PPC64, CONFIG_BOOK3E_64, or similar.

-Scott

^ permalink raw reply

* Re: [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2010-10-08 23:31 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.1010081102090.19518@localhost.localdomain>

On Fri, 2010-10-08 at 11:04 -0500, Kumar Gala wrote:
> Ben,
> 
> This isn't critical, but it does fix having the ppc64e_defconfig
> build cleanly.

BTW. Do you have a -next for me ? It's past time :-)

Cheers,
Ben.

> - k
> 
> The following changes since commit 6b0cd00bc396daf5c2dcf17a8d82055335341f46:
> 
>   Merge branch 'hwpoison-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6 (2010-10-07 13:59:32 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git merge
> 
> Kumar Gala (1):
>       powerpc/ppc64e: Fix link problem when building ppc64e_defconfig
> 
>  arch/powerpc/platforms/85xx/smp.c |    7 +++++++
>  1 files changed, 7 insertions(+), 0 deletions(-)

^ permalink raw reply

* Re: [RFC PATCH 02/11] ppc: allow direct and iommu to coexist
From: Benjamin Herrenschmidt @ 2010-10-08 23:38 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: FUJITA Tomonori, linux-kernel, miltonm, Paul Mackerras,
	Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-3-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Replace the union with just the multiple fields, ifdef on CONFIG_PPC64.
> 
> Future pseries boxes will allow a 64 bit dma mapping covering all
> memory, coexisting with a smaller iommu window in 32 bit pci space.
> 
> The cell fixed mapping would also like both to coexist.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
> I used the ifdef guard of CONFIG_PPC64 according to the current makefile
> for iommu.c.  One set is burried in the middle of iommu.h.

I dislike the ifdef's ...

Also, why remove the union ? IE. Do we really them to co-exist for a
given device ? I'm doing something similar for another (not released
yet) processor where I'm flicking between direct and iommu at
set_dma_mask time, it's easy enough to change the union content.

Cheers,
Ben.

> ---
>  arch/powerpc/include/asm/device.h      |   14 ++++++--------
>  arch/powerpc/include/asm/dma-mapping.h |    4 ++--
>  arch/powerpc/include/asm/iommu.h       |    6 ++++--
>  3 files changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
> index 16d25c0..ed883ea 100644
> --- a/arch/powerpc/include/asm/device.h
> +++ b/arch/powerpc/include/asm/device.h
> @@ -19,14 +19,12 @@ struct dev_archdata {
>  	/* DMA operations on that device */
>  	struct dma_map_ops	*dma_ops;
>  
> -	/*
> -	 * When an iommu is in use, dma_data is used as a ptr to the base of the
> -	 * iommu_table.  Otherwise, it is a simple numerical offset.
> -	 */
> -	union {
> -		dma_addr_t	dma_offset;
> -		void		*iommu_table_base;
> -	} dma_data;
> +	/* dma_offset is used by swiotlb and direct dma ops, but no iommu */
> +	dma_addr_t	dma_offset;
> +
> +#ifdef CONFIG_PPC64
> +	void		*iommu_table_base;
> +#endif
>  
>  #ifdef CONFIG_SWIOTLB
>  	dma_addr_t		max_direct_dma_addr;
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 8c9c6ad..644103a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -100,7 +100,7 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
>  static inline dma_addr_t get_dma_offset(struct device *dev)
>  {
>  	if (dev)
> -		return dev->archdata.dma_data.dma_offset;
> +		return dev->archdata.dma_offset;
>  
>  	return PCI_DRAM_OFFSET;
>  }
> @@ -108,7 +108,7 @@ static inline dma_addr_t get_dma_offset(struct device *dev)
>  static inline void set_dma_offset(struct device *dev, dma_addr_t off)
>  {
>  	if (dev)
> -		dev->archdata.dma_data.dma_offset = off;
> +		dev->archdata.dma_offset = off;
>  }
>  
>  /* this will be removed soon */
> diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
> index edfc980..0f605a4 100644
> --- a/arch/powerpc/include/asm/iommu.h
> +++ b/arch/powerpc/include/asm/iommu.h
> @@ -70,15 +70,17 @@ struct iommu_table {
>  
>  struct scatterlist;
>  
> +#ifdef CONFIG_PPC64
>  static inline void set_iommu_table_base(struct device *dev, void *base)
>  {
> -	dev->archdata.dma_data.iommu_table_base = base;
> +	dev->archdata.iommu_table_base = base;
>  }
>  
>  static inline void *get_iommu_table_base(struct device *dev)
>  {
> -	return dev->archdata.dma_data.iommu_table_base;
> +	return dev->archdata.iommu_table_base;
>  }
> +#endif
>  
>  /* Frees table for an individual device node */
>  extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-08 23:43 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Anton Vorontsov, miltonm, linux-kernel, FUJITA Tomonori,
	Paul Mackerras, Scott Wood, Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-4-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Also allow the coherent ops to be iommu if only the coherent mask is too
> small, mostly for driver that do not set set the coherent mask but also
> don't use the coherent api.

You are doing the transition at map_sg time which is a hot path, I don't
like that. Also you add all those "choose" variants of the dma ops...
not very nice at all.

You may want to look at the patches I posted to the list a while back
for doing direct DMA on Bimini:

> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
>  arch/powerpc/include/asm/dma-mapping.h |    2 +
>  arch/powerpc/kernel/Makefile           |    2 +-
>  arch/powerpc/kernel/dma-choose64.c     |  167 ++++++++++++++++++++++++++++++++
>  3 files changed, 170 insertions(+), 1 deletions(-)
>  create mode 100644 arch/powerpc/kernel/dma-choose64.c
> 
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 644103a..9ffb16a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -68,6 +68,8 @@ static inline unsigned long device_to_mask(struct device *dev)
>   */
>  #ifdef CONFIG_PPC64
>  extern struct dma_map_ops dma_iommu_ops;
> +extern struct dma_map_ops dma_choose64_ops;
> +extern struct dma_map_ops dma_iommu_coherent_ops;
>  #endif
>  extern struct dma_map_ops dma_direct_ops;
>  
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index 1dda701..21b8ea1 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -82,7 +82,7 @@ obj-y				+= time.o prom.o traps.o setup-common.o \
>  				   udbg.o misc.o io.o dma.o \
>  				   misc_$(CONFIG_WORD_SIZE).o
>  obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
> -obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
> +obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o dma-choose64.o
>  obj-$(CONFIG_KGDB)		+= kgdb.o
>  obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)	+= prom_init.o
>  obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
> diff --git a/arch/powerpc/kernel/dma-choose64.c b/arch/powerpc/kernel/dma-choose64.c
> new file mode 100644
> index 0000000..17c716f
> --- /dev/null
> +++ b/arch/powerpc/kernel/dma-choose64.c
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
> + *
> + * Provide default implementations of the DMA mapping callbacks for
> + * directly mapped busses.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/bug.h>
> +
> +/*
> + * DMA operations that choose between a 64-bit direct mapping and and iommu
> + *
> + * This set of dma ops chooses between directing to a static 1:1 mapping
> + * that may require a 64 bit address and a iommu based on the declared
> + * streaming and coherent masks for the device.  The choice is made on
> + * the first dma map call.
> + */
> +
> +/* first BUG ops for calls out of sequence */
> +
> +void *dma_bug_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	BUG();
> +
> +	return NULL;
> +}
> +
> +void dma_bug_free_coherent(struct device *dev, size_t size,
> +			      void *vaddr, dma_addr_t dma_handle)
> +{
> +	BUG();
> +}
> +
> +static int dma_bug_dma_supported(struct device *dev, u64 mask)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +static int dma_bug_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +
> +static void dma_bug_unmap_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction direction,
> +				struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +static dma_addr_t dma_bug_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return DMA_ERROR_CODE;
> +}
> +
> +
> +static void dma_bug_unmap_page(struct device *dev,
> +					 dma_addr_t dma_address,
> +					 size_t size,
> +					 enum dma_data_direction direction,
> +					 struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +
> +static struct dma_map_ops *choose(struct device *dev)
> +{
> +	if (dma_direct_ops.dma_supported(dev, device_to_mask(dev))) {
> +		if (dma_direct_ops.dma_supported(dev, dev->coherent_dma_mask))
> +			return &dma_direct_ops;
> +		return &dma_iommu_coherent_ops;
> +	}
> +	return &dma_iommu_ops;
> +}
> +
> +void *dma_choose64_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->alloc_coherent(dev, size, dma_handle, flag);
> +}
> +
> +static int dma_choose64_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_sg(dev, sgl, nents, direction, attrs);
> +}
> +
> +
> +static int dma_choose64_dma_supported(struct device *dev, u64 mask)
> +{
> +	return dma_direct_ops.dma_supported(dev, mask) ||
> +		dma_iommu_ops.dma_supported(dev, mask);
> +}
> +
> +static dma_addr_t dma_choose64_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_page(dev, page, offset, size, dir, attrs);
> +}
> +
> +struct dma_map_ops dma_choose64_ops = {
> +	.alloc_coherent	= dma_choose64_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_choose64_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_choose64_dma_supported,
> +	.map_page	= dma_choose64_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_choose64_ops);
> +
> +/* set these up to BUG() until we initialze them in the arch initcall below */
> +struct dma_map_ops dma_iommu_coherent_ops = {
> +	.alloc_coherent	= dma_bug_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_bug_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_bug_dma_supported,
> +	.map_page	= dma_bug_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_iommu_coherent_ops);
> +
> +static int setup_choose64_ops(void)
> +{
> +	dma_iommu_coherent_ops = dma_direct_ops;
> +	dma_iommu_coherent_ops.alloc_coherent = dma_iommu_ops.alloc_coherent;
> +	dma_iommu_coherent_ops.free_coherent = dma_iommu_ops.free_coherent;
> +
> +	/* should we be stricter? */
> +	dma_iommu_coherent_ops.dma_supported = dma_choose64_dma_supported;
> +
> +	return 0;
> +}
> +arch_initcall(setup_choose64_ops);

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-08 23:44 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Anton Vorontsov, miltonm, linux-kernel, FUJITA Tomonori,
	Paul Mackerras, Scott Wood, Andrew Morton, linuxppc-dev
In-Reply-To: <1286559192-10898-4-git-send-email-nacc@us.ibm.com>

On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> Also allow the coherent ops to be iommu if only the coherent mask is too
> small, mostly for driver that do not set set the coherent mask but also
> don't use the coherent api.

You are doing the transition at map_sg time which is a hot path, I don't
like that. Also you add all those "choose" variants of the dma ops...
not very nice at all.

You may want to look at the patches I posted to the list a while back
for doing direct DMA on Bimini:

[PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()
[PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe

Cheers,
Ben.

> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> ---
>  arch/powerpc/include/asm/dma-mapping.h |    2 +
>  arch/powerpc/kernel/Makefile           |    2 +-
>  arch/powerpc/kernel/dma-choose64.c     |  167 ++++++++++++++++++++++++++++++++
>  3 files changed, 170 insertions(+), 1 deletions(-)
>  create mode 100644 arch/powerpc/kernel/dma-choose64.c
> 
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 644103a..9ffb16a 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -68,6 +68,8 @@ static inline unsigned long device_to_mask(struct device *dev)
>   */
>  #ifdef CONFIG_PPC64
>  extern struct dma_map_ops dma_iommu_ops;
> +extern struct dma_map_ops dma_choose64_ops;
> +extern struct dma_map_ops dma_iommu_coherent_ops;
>  #endif
>  extern struct dma_map_ops dma_direct_ops;
>  
> diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
> index 1dda701..21b8ea1 100644
> --- a/arch/powerpc/kernel/Makefile
> +++ b/arch/powerpc/kernel/Makefile
> @@ -82,7 +82,7 @@ obj-y				+= time.o prom.o traps.o setup-common.o \
>  				   udbg.o misc.o io.o dma.o \
>  				   misc_$(CONFIG_WORD_SIZE).o
>  obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
> -obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
> +obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o dma-choose64.o
>  obj-$(CONFIG_KGDB)		+= kgdb.o
>  obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)	+= prom_init.o
>  obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
> diff --git a/arch/powerpc/kernel/dma-choose64.c b/arch/powerpc/kernel/dma-choose64.c
> new file mode 100644
> index 0000000..17c716f
> --- /dev/null
> +++ b/arch/powerpc/kernel/dma-choose64.c
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
> + *
> + * Provide default implementations of the DMA mapping callbacks for
> + * directly mapped busses.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/bug.h>
> +
> +/*
> + * DMA operations that choose between a 64-bit direct mapping and and iommu
> + *
> + * This set of dma ops chooses between directing to a static 1:1 mapping
> + * that may require a 64 bit address and a iommu based on the declared
> + * streaming and coherent masks for the device.  The choice is made on
> + * the first dma map call.
> + */
> +
> +/* first BUG ops for calls out of sequence */
> +
> +void *dma_bug_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	BUG();
> +
> +	return NULL;
> +}
> +
> +void dma_bug_free_coherent(struct device *dev, size_t size,
> +			      void *vaddr, dma_addr_t dma_handle)
> +{
> +	BUG();
> +}
> +
> +static int dma_bug_dma_supported(struct device *dev, u64 mask)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +static int dma_bug_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return 0;
> +}
> +
> +
> +static void dma_bug_unmap_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction direction,
> +				struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +static dma_addr_t dma_bug_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	BUG();
> +
> +	return DMA_ERROR_CODE;
> +}
> +
> +
> +static void dma_bug_unmap_page(struct device *dev,
> +					 dma_addr_t dma_address,
> +					 size_t size,
> +					 enum dma_data_direction direction,
> +					 struct dma_attrs *attrs)
> +{
> +	BUG();
> +}
> +
> +
> +static struct dma_map_ops *choose(struct device *dev)
> +{
> +	if (dma_direct_ops.dma_supported(dev, device_to_mask(dev))) {
> +		if (dma_direct_ops.dma_supported(dev, dev->coherent_dma_mask))
> +			return &dma_direct_ops;
> +		return &dma_iommu_coherent_ops;
> +	}
> +	return &dma_iommu_ops;
> +}
> +
> +void *dma_choose64_alloc_coherent(struct device *dev, size_t size,
> +				dma_addr_t *dma_handle, gfp_t flag)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->alloc_coherent(dev, size, dma_handle, flag);
> +}
> +
> +static int dma_choose64_map_sg(struct device *dev, struct scatterlist *sgl,
> +			     int nents, enum dma_data_direction direction,
> +			     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_sg(dev, sgl, nents, direction, attrs);
> +}
> +
> +
> +static int dma_choose64_dma_supported(struct device *dev, u64 mask)
> +{
> +	return dma_direct_ops.dma_supported(dev, mask) ||
> +		dma_iommu_ops.dma_supported(dev, mask);
> +}
> +
> +static dma_addr_t dma_choose64_map_page(struct device *dev,
> +					     struct page *page,
> +					     unsigned long offset,
> +					     size_t size,
> +					     enum dma_data_direction dir,
> +					     struct dma_attrs *attrs)
> +{
> +	struct dma_map_ops *new = choose(dev);
> +
> +	set_dma_ops(dev, new);
> +	return new->map_page(dev, page, offset, size, dir, attrs);
> +}
> +
> +struct dma_map_ops dma_choose64_ops = {
> +	.alloc_coherent	= dma_choose64_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_choose64_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_choose64_dma_supported,
> +	.map_page	= dma_choose64_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_choose64_ops);
> +
> +/* set these up to BUG() until we initialze them in the arch initcall below */
> +struct dma_map_ops dma_iommu_coherent_ops = {
> +	.alloc_coherent	= dma_bug_alloc_coherent,
> +	.free_coherent	= dma_bug_free_coherent,
> +	.map_sg		= dma_bug_map_sg,
> +	.unmap_sg	= dma_bug_unmap_sg,
> +	.dma_supported	= dma_bug_dma_supported,
> +	.map_page	= dma_bug_map_page,
> +	.unmap_page	= dma_bug_unmap_page,
> +};
> +EXPORT_SYMBOL(dma_iommu_coherent_ops);
> +
> +static int setup_choose64_ops(void)
> +{
> +	dma_iommu_coherent_ops = dma_direct_ops;
> +	dma_iommu_coherent_ops.alloc_coherent = dma_iommu_ops.alloc_coherent;
> +	dma_iommu_coherent_ops.free_coherent = dma_iommu_ops.free_coherent;
> +
> +	/* should we be stricter? */
> +	dma_iommu_coherent_ops.dma_supported = dma_choose64_dma_supported;
> +
> +	return 0;
> +}
> +arch_initcall(setup_choose64_ops);

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-09 15:52 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101007152626.4e834d43@udp111988uds.am.freescale.net>

First of all - where is all of this documented? There seems to be a great
deal of "oral tradition" type knowledge here, but is any of it actually
written down somewhere? (see below for examples)

> On Thu, 7 Oct 2010 15:12:26 -0500
> This is asking for the 256th specifier in the interrupts property in
> the mpic node -- not what you want.

That was from some of the previous emails in this thread.

> Ideally you would have a node for your device with an interrupt
> specifier that you could look up with irq_of_parse_and_map().

OK, and how do these devices come into being? From what I can tell, they
are defined by uBoot, and if uBoot doesn't define it, then you are out of
luck.

But even assuming you can define these nodes at run time, as far as I can
see, you are right back to the question of "and how do I know what the
mappings are so I can create the node?" You haven't answered the question,
you've just moved where you are asking it.


> The vector/priority register (MSIVPR0) is at offset
> 0x51c00.  Each interrupt source is 32 bytes.  The first interrupt
> source is at 0x50000.
>
> So the interrupt number is (0x51c00 - 0x50000) / 32 = 224.

OK, so that's how you get the MPIC IRQ number. It's a pity that the key
piece of information - "MPIC IRQ Numbers are defined by the interrupt
vector table starting at 0x50000 and incrementing by 0x20 - see table 9.3
of the MPD8641D manual for details" wasn't spelled out anywhere I could
find.

Given the data I had: the kernel sources, the MPD8641D manual, and not
much else, I had three unknowns:
* a table of config registers, that could map an set of events into an
arbitrary vector number.
* The standard kernel "request_irq" API that takes that arbitrary vector
number
* A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
for all intents, undocumented (just "here's the parameters", no
description of when and how to use them), that took a ???? and returned a
???? (because, with the documentation I had, that's basically all I could
say about them).

There was no documentation that said how to compute the MPIC interrupt
vector, no documentation that said which API to use to convert that to an
kernel IRQ, nothing.

> BTW, the MSIs are already described in an msi node in the device tree.

As I stated previously - not that I can see. Neither does
/proc/device_tree contain such a listing, nor does doing a
"of_find_node_by_name(0,"msi");" nor "of_find_node_by_type(0,"msi");" find
them.

It may be they are defined in PCI Root Complex mode, but again - I am
writing code to handle Endpoint mode, which, as far as I can tell from the
kernel sources, is NOT handled in any standardized way.


Again, it would be nice were this sort of thing documented somewhere. If
it is, I'd love a link - I've tried every combination of search terms I
can think of to find it to no avail.

If it isn't documented, might I suggest that either a) creating a
dedicated "Programming PPC Embedded devices and their components under
Linux" be created, or b) an appropriate chapter or chapters be drafted and
submitted to the Linux Device Drivers book.


Don't take this message the wrong way - I do want to say "THANK YOU FOR
THE HELP!" - I am just trying to point out why somebody with a fair amount
of Linux kernel experience and a great deal of general embedded experience
is having great trouble doing a simple thing.

I'll try creating a mapping, binding to it, and seeing what happens.

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: david.hagood @ 2010-10-09 17:03 UTC (permalink / raw)
  To: Scott Wood; +Cc: david.hagood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20101007152626.4e834d43@udp111988uds.am.freescale.net>

OK, using 224 as the MPIC interrupt number, and attempting to map it via
irq_create_mapping(0,224) gives me a kernel seg fault:

Unable to handle kernel paging request for data at address 0x00000000
Faulting instruction address: 0xc0016540
Oops: Kernel access of bad area, sig: 11 [#1]
PREEMPT SMP NR_CPUS=2 EP8641A
Modules linked in: Endpoint_driver(+)
NIP: c0016540 LR: c0050b38 CTR: c00163b8
REGS: ef8c1ab0 TRAP: 0300   Not tainted  (2.6.26.2-ep1.10)
MSR: 00001032 <ME,IR,DR>  CR: 24024482  XER: 00000000
DAR: 00000000, DSISR: 40000000
TASK = eedec6a0[60] 'insmod' THREAD: ef8c0000 CPU: 1
GPR00: 00000000 ef8c1b60 eedec6a0 ffffffea 00000000 00000000 c035c17c
000000e0
GPR08: 00400000 00000000 c035c020 00000000 24024422 100a7264 00000000
00000095
GPR16: 00000095 00000000 0000000d 00000124 f102fd98 00000000 c004a4fc
f102c000
GPR24: 0000001a f1038400 00000000 c031e610 fffffffa 00009032 c031e5e0
000000e0
NIP [c0016540] mpic_set_irq_type+0x188/0x1c4
LR [c0050b38] set_irq_type+0x84/0xc8
Call Trace:
[ef8c1b60] [c0050b1c] set_irq_type+0x68/0xc8 (unreliable)
[ef8c1b80] [c001572c] mpic_host_map+0xec/0xf4
[ef8c1b90] [c00064a0] irq_setup_virq+0x60/0x98
[ef8c1bb0] [c00065dc] irq_create_mapping+0x104/0x114
[ef8c1bd0] [f1034798] Endpoint_device_ctor+0x258/0x3b8 [Endpoint_driver]

Reading the source (since these calls don't seem to have any other
documentation), it *looks* like it ought to be valid to call
irq_create_mapping with a null irq_host *host - which is good, since I
can't see anything obvious that would give me some other irq_host (again,
since none of this seems to be documented anywhere).

I am assuming the default host used by the system would be correct.

However, then I get this fault.

^ permalink raw reply

* Pegasos i8042 broken again
From: pacman @ 2010-10-10  1:37 UTC (permalink / raw)
  To: linuxppc-dev

Pegasos has no keyboard again. I blame commit
540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs in
the device-tree but doesn't fall back to the old hardcoded 1 and 12 in all
failure cases.

Specifically, the case where the device-tree contains nothing matching
pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of falls
through to the old code, but leaves the IRQs set to 0.

The last time something like this happened, I submitted a patch:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
which got committed, but afterward I was scolded for working around a bug
instead of fixing it in nvramrc.

This time I just won't send my workaround patch, at least until it's decided
that the kernel should be made to understand the device-tree as is.

If it's decided instead that the firmware should be patched... well I just
don't feel comfortable inventing my own patch for nvramrc, since it's written
in a language I don't know and presumably could brick the machine if I get it
wrong. Also I'm not even sure what the kernel is expecting to find there.

-- 
Alan Curry

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: Benjamin Herrenschmidt @ 2010-10-10  7:35 UTC (permalink / raw)
  To: pacman; +Cc: linuxppc-dev
In-Reply-To: <20101010013755.1697.qmail@kosh.dhis.org>

On Sat, 2010-10-09 at 20:37 -0500, pacman@kosh.dhis.org wrote:
> Pegasos has no keyboard again. I blame commit
> 540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs in
> the device-tree but doesn't fall back to the old hardcoded 1 and 12 in all
> failure cases.
> 
> Specifically, the case where the device-tree contains nothing matching
> pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of falls
> through to the old code, but leaves the IRQs set to 0.
> 
> The last time something like this happened, I submitted a patch:
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
> which got committed, but afterward I was scolded for working around a bug
> instead of fixing it in nvramrc.
> 
> This time I just won't send my workaround patch, at least until it's decided
> that the kernel should be made to understand the device-tree as is.
> 
> If it's decided instead that the firmware should be patched... well I just
> don't feel comfortable inventing my own patch for nvramrc, since it's written
> in a language I don't know and presumably could brick the machine if I get it
> wrong. Also I'm not even sure what the kernel is expecting to find there. 

Those things really suck. They absolutely refuse to fix their FW for
reasons I never quite managed to figure out.

At this stage, I'd say the best is to add yet another pegasos workaround
in prom_init that adds the missing compatible property.

Cheers,
Ben.

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Eran Liberty @ 2010-10-10 10:02 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <948C4143-91C1-45AD-9E0A-82E3F394B181@kernel.crashing.org>

Kumar Gala wrote:
> On Oct 7, 2010, at 7:30 AM, Eran Liberty wrote:
>
>   
>> Dear Penguins,
>>
>> SHORT:
>> There is a BUG in the current code design / Freescale P2020/85xx PCIe design that prevent it from registering to the PCIe AER... or that I have missed something :) ..
>>
>> LESS SHORT:
>> I am in the process of a Freescale P2020 based board bring up. P2020 is basically two 85xx processors and their peripherals share most features.
>>
>> PCIe has a very extensive error reporting section and the Kernel already has a very nice looking Advanced Error Reporting driver.
>>
>> I encounter difficulties trying to connect the P2020/85xx PCIe device to this AER service driver.
>>
>> My technical findings follows:
>>
>> - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>> - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
>> "/*
>> * Don't use service devices that require interrupts if there is
>> * no way to generate them.
>> */"
>>
>> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>> - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>> - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>> - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
>>
>> Failing all those the probe fails and the AER service is not activated for the PCIE device.
>>
>> QUESTION:
>> 1. What am I missing?
>> 2. Has anyone enabled the AER PCIe service for P2020/MPC85xx?
>> 3. Should the PCIe ROOT end report MSI capabilities or should the device end report itself as bridge ???
>>
>> -- Liberty
>>     
>
> Do you have some code that enables AER on P2020.  If so it might be easier to see what's going on.
>
>
>   
> - k
>
>
The code that enables the AER is the problem. The kernel fails to probe 
my devices into the AER sevice. I can brutally hack my kernel to 
register the AER service. I copy the dev->irq and dev->pin from the 
child device to the bridge device. This will get the bridge device 
registered BUT it is not working and this hack is surly not a solution.

Here is a snap shot of my un-hacked devices, hopefully it will clarify 
the situation:

~ # ls -la /sys/bus/pci/devices/
drwxr-xr-x    2 root     root            0 Jan  3 17:25 .
drwxr-xr-x    5 root     root            0 Jan  3 17:25 ..
lrwxrwxrwx    1 root     root            0 Jan  3 17:25 0001:01:00.0 -> 
../../../devices/pci0001:01/0001:01:00.0
lrwxrwxrwx    1 root     root            0 Jan  3 17:25 0001:02:00.0 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:02:00.0

"0001:01:00.0" is the PCIe PCI-PCI bridge side (Freescale's side)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/vendor
0x1957 (PCI_VENDOR_ID_FREESCALE)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/device
0x0071 (PCI_DEVICE_ID_P2020)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/class
0x060400 (PCI_CLASS_BRIDGE_PCI)
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/enable
1
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/irq
0
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/msi_bus
1
~ # cat /sys/bus/pci/devices/0001\:01\:00.0/resource
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x000000000000ffff 0x0000000000000100
0x00000000c0000000 0x00000000dfffffff 0x0000000000000200
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
~ # hexdump  /sys/bus/pci/devices/0001\:01\:00.0/config
0000000 5719 7100 0601 1000 1000 200b 0800 0100 (PCI Compatible 
Configuration Headers)
0000010 0000 f0ff 0000 0000 0002 0200 0000 0000
0000020 00c0 f0df f1ff 0100 0000 0000 0000 0000
0000030 0000 0000 4400 0000 0000 0000 0000 0000
0000040 0000 0000 014c 02fe 0000 0000 1000 4100 (Power Mgmt 
Capabilities) , (0x4C: PCI Express Capabilities)
0000050 0100 0000 3e58 0000 41d4 0300 0800 4100
0000060 c007 0000 c003 4000 0000 0000 0000 0000
0000070 0000 0000 0000 0000 0000 0000 0000 0000
*
0000100 0100 0100 0000 0000 0000 0000 1020 0600 (Advanced Error 
Reporting Capability)
0000110 0000 0000 0000 0000 a000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 0000
*
0000400 0000 0000 1600 0000 e204 0000 0000 0000 (PCI Express Controller 
Internal CSRs)
0000410 0800 0000 0000 0000 0000 0000 4040 0000
0000420 0000 0000 0000 0000 0000 0000 0000 0000
0000430 0000 0000 0000 0000 8300 6300 9ba0 0900
0000440 1000 0000 0000 0000 0000 0000 0000 0000
0000450 ced7 1400 201e fc01 0000 0000 5c0c 0000
0000460 0000 0000 0000 0000 0000 0000 0000 0000
0000470 5719 7100 1000 200b 0000 0000 0100 0000
0000480 443d 0000 0000 0000 f007 0000 0000 0000
0000490 c007 0000 0000 0000 0000 0000 0000 0000
00004a0 0000 0000 0000 0000 0000 0000 0000 0000
00004b0 0000 0000 0000 0000 2804 0180 8520 0000
00004c0 ff00 0000 0000 0000 0000 0000 1100 0000
00004d0 0000 0000 0000 0000 0000 0000 0000 0000
00004e0 0000 0000 0101 0000 0101 0000 0000 0000
00004f0 4a00 0001 0200 0004 0000 0000 0800 0000
0000500 0000 0000 0000 0000 0000 0000 0000 0000
0000510 0000 0000 0000 0000 8300 0000 0000 0000
0000520 0000 0000 0000 0000 0000 0000 0000 0000
*
0000540 0000 0000 0001 0202 0000 0000 0500 0000
0000550 0000 0000 0000 0000 0000 0000 0000 0000
*
0000590 d0cf 3200 0000 0000 0000 0000 0000 0000
00005a0 3f00 0000 0000 0000 0000 0000 0000 0000
00005b0 0000 0000 0000 0000 0000 0000 0000 0000
*
0001000

Now here is the other side of the tunnel, "0001:02:00.0" (our device)
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/vendor
0x1234 (Just a number i picked up and told the HW dudes to put into the 
device... don't look it up :) )
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/device
0x0002
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/class
0xff0000
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/enable
0
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/irq
16
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/msi_bus
~ # cat /sys/bus/pci/devices/0001\:02\:00.0/resource
0x00000000c0000000 0x00000000c007ffff 0x0000000000020200
0x00000000c0080000 0x00000000c00fffff 0x0000000000020200
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
~ # hexdump /sys/bus/pci/devices/0001\:02\:00.0/config
0000000 3412 0200 0600 1000 0100 00ff 0800 0000
0000010 0000 00c0 0000 08c0 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 3412 0200
0000030 0000 0000 5000 0000 0000 0000 0001 0000
0000040 0000 0000 6061 0002 0000 0000 0000 0000
0000050 0578 8400 0000 0000 0000 0000 0000 0000
0000060 0000 0000 0000 0000 1178 0000 0000 0000
0000070 0000 0000 0000 0000 0180 0300 0800 0000
0000080 1000 0100 0180 3c00 3058 0000 41f4 0301
0000090 0000 4110 0000 0400 c003 0000 0000 0000
00000a0 0000 0000 0000 0000 0000 0000 0000 0000
00000b0 0100 0100 0000 0000 0000 0000 0000 0000
00000c0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000100 0200 0180 0000 0000 0000 0000 0000 0000
0000110 0000 0000 ff00 0080 0000 0000 0000 0000
0000120 0000 0000 0000 0000 0000 0000 0000 0000
*
0000800 0100 0100 0000 0000 0000 0000 3120 0600
0000810 0000 0000 0020 0000 0000 0000 0000 0000
0000820 0000 0000 0000 0000 0000 0000 0000 0000
*
0001000

NOW... As it is, under "/sys/bus/pci_express/devices/" you will find no 
devices. Debug prints which I have stuffed into pcie_portdrv_probe() 
shows that: "0001:01:00" is probed and fails to register for lacking a 
suitable interrupt mechanism as described by the previous mail, and 
"0001:02:00" fails to probe since it is not a PCI ROOT port.
As said, if I hack and slash and mainly cheat I can persuade the Kernel 
not to fail the probe and then I get these:

~ # ls -la /sys/bus/pci_express/devices/
drwxr-xr-x    2 root     root            0 Jan  3 17:49 .
drwxr-xr-x    4 root     root            0 Jan  3 17:49 ..
lrwxrwxrwx    1 root     root            0 Jan  3 17:49 
0001:01:00.0:pcie01 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:01:00.0:pcie01
lrwxrwxrwx    1 root     root            0 Jan  3 17:49 
0001:01:00.0:pcie02 -> 
../../../devices/pci0001:01/0001:01:00.0/0001:01:00.0:pcie02

This is NOT functional as I have crippled the kernel on the way but I 
think this is  what I am missing and maybe my goal.

-- Liberty

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: Gerhard Pircher @ 2010-10-10 12:26 UTC (permalink / raw)
  To: pacman; +Cc: linuxppc-dev
In-Reply-To: <1286696147.2463.499.camel@pasglop>


On Sat, 2010-10-09 at 20:37 -0500, pacman@kosh.dhis.org wrote:
> Pegasos has no keyboard again. I blame commit
> 540c6c392f01887dcc96bef0a41e63e6c1334f01, which tries to find i8042 IRQs
> inthe device-tree but doesn't fall back to the old hardcoded 1 and 12 in
> all failure cases.
> 
> Specifically, the case where the device-tree contains nothing matching
> pnpPNP,303 or pnpPNP,f03 doesn't seem to be handled well. It sort of
> falls through to the old code, but leaves the IRQs set to 0.
> 
> The last time something like this happened, I submitted a patch:
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2007-July/039988.html
> which got committed, but afterward I was scolded for working around a
> bug instead of fixing it in nvramrc.
> 
> This time I just won't send my workaround patch, at least until it's
> decided that the kernel should be made to understand the device-tree as
> is.
> If it's decided instead that the firmware should be patched... well I
> just don't feel comfortable inventing my own patch for nvramrc, since
> it's written in a language I don't know and presumably could brick the
> machine if I get it wrong. Also I'm not even sure what the kernel is
> expecting to find there.

Is this a Pegasos 1 or Pegasos 2? I'm just curious, because some Pegasos 1
users told me that newer Linux kernels don't even boot on their machines.

regards,

Gerhard
-- 
Neu: GMX De-Mail - Einfach wie E-Mail, sicher wie ein Brief!  
Jetzt De-Mail-Adresse reservieren: http://portal.gmx.net/de/go/demail

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: FUJITA Tomonori @ 2010-10-10 15:09 UTC (permalink / raw)
  To: benh
  Cc: avorontsov, miltonm, linux-kernel, fujita.tomonori, paulus,
	scottwood, nacc, akpm, linuxppc-dev
In-Reply-To: <1286581493.2463.428.camel@pasglop>

On Sat, 09 Oct 2010 10:44:53 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> > Also allow the coherent ops to be iommu if only the coherent mask is too
> > small, mostly for driver that do not set set the coherent mask but also
> > don't use the coherent api.
> 
> You are doing the transition at map_sg time which is a hot path, I don't
> like that. Also you add all those "choose" variants of the dma ops...
> not very nice at all.

Agreed, looks hacky.


> You may want to look at the patches I posted to the list a while back
> for doing direct DMA on Bimini:
> 
> [PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()

Would it be cleaner if each ppc dma_map_ops has the own set_dma_mask
and dma_set_mask simply calls dma_map_ops->set_dma_mask?


> [PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe

^ permalink raw reply

* Re: Pegasos i8042 broken again
From: pacman @ 2010-10-10 17:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1286696147.2463.499.camel@pasglop>

Benjamin Herrenschmidt writes:
> 
> Those things really suck. They absolutely refuse to fix their FW for
> reasons I never quite managed to figure out.

The last time around, they did release a firmware patch (pegasos-dts-20071018)
to fix up the device tree enough to satisfy the kernel. Now that the kernel
has become dissatisfied again, maybe another patch will appear.

> 
> At this stage, I'd say the best is to add yet another pegasos workaround
> in prom_init that adds the missing compatible property.

This one would be more complex than the other fixes in prom_init. It's not
just the compatible property that's missing. The 8042 node in the device tree
has no children.

-- 
Alan Curry

^ permalink raw reply

* Re: [RFC PATCH 03/11] ppc: Create ops to choose between direct window and iommu based on device mask
From: Benjamin Herrenschmidt @ 2010-10-10 23:41 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: avorontsov, miltonm, linux-kernel, paulus, scottwood, nacc, akpm,
	linuxppc-dev
In-Reply-To: <20101011000903R.fujita.tomonori@lab.ntt.co.jp>

On Mon, 2010-10-11 at 00:09 +0900, FUJITA Tomonori wrote:
> On Sat, 09 Oct 2010 10:44:53 +1100
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> 
> > On Fri, 2010-10-08 at 10:33 -0700, Nishanth Aravamudan wrote:
> > > Also allow the coherent ops to be iommu if only the coherent mask is too
> > > small, mostly for driver that do not set set the coherent mask but also
> > > don't use the coherent api.
> > 
> > You are doing the transition at map_sg time which is a hot path, I don't
> > like that. Also you add all those "choose" variants of the dma ops...
> > not very nice at all.
> 
> Agreed, looks hacky.
> 
> 
> > You may want to look at the patches I posted to the list a while back
> > for doing direct DMA on Bimini:
> > 
> > [PATCH 1/2] powerpc/dma: Add optional platform override of dma_set_mask()
> 
> Would it be cleaner if each ppc dma_map_ops has the own set_dma_mask
> and dma_set_mask simply calls dma_map_ops->set_dma_mask?

I'm not sure I parse what you wrote above :-)

I did try with various methods back then, and what ended up sucking the
less was basically to hookup dma_set_mask() at the arch level.

In fact, it makes sense to the extent that the arch is the one that
knows that there are multiple regions configured potentially with
different capabilities.

You can still do the switch within the dma_ops->set_dma_mask if you want
I suppose, especially if you end up hitting different attribute regions
within a single bus or such but from my experience, it gets really hacky
with multiple ops structures etc...
> 
> > [PATCH 2/2] powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe
> 

Cheers,
Ben.

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Benjamin Herrenschmidt @ 2010-10-11  0:19 UTC (permalink / raw)
  To: Eran Liberty
  Cc: Xianghua Xiao, linuxppc-dev, linux-pci, Tony Li, Linas Vepstas,
	ZHANG WEI
In-Reply-To: <4CADBD7B.3000506@extricom.com>


>  - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. 
>  - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>  - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
> "/*
>   * Don't use service devices that require interrupts if there is
>   * no way to generate them.
>   */"
> 
> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>  - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>  - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>  - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
> 
> Failing all those the probe fails and the AER service is not activated for the PCIE device.

So the question boils down to how does the bridge generate the AER
interrupts. This should be documented in the FSL docs no ? The MSI in
the child/device should be unrelated (it's your device MSI) no ? So the
question is where's the missing interrupt.

If it's a SoC interrupt, coming from the device-tree, then perhaps the
generic AER code should be extended to recognize those.

Cheers,
Ben.

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-11  9:51 UTC (permalink / raw)
  To: david.hagood; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <adaf806ee1c11621dbb51246bef0acd8.squirrel@localhost>

david.hagood@gmail.com wrote:
> First of all - where is all of this documented? There seems to be a great
> deal of "oral tradition" type knowledge here, but is any of it actually
> written down somewhere? (see below for examples)
> 
>> On Thu, 7 Oct 2010 15:12:26 -0500
>> This is asking for the 256th specifier in the interrupts property in
>> the mpic node -- not what you want.
> 
> That was from some of the previous emails in this thread.
> 
>> Ideally you would have a node for your device with an interrupt
>> specifier that you could look up with irq_of_parse_and_map().
> 
> OK, and how do these devices come into being? From what I can tell, they
> are defined by uBoot, and if uBoot doesn't define it, then you are out of
> luck.

You should define MSI device nodes on your target dts. And you can refer to the
file, mpc8572ds.dts.

Often U-Boot dose not generate MSI information and embed that to dtb.

> 
> But even assuming you can define these nodes at run time, as far as I can
> see, you are right back to the question of "and how do I know what the
> mappings are so I can create the node?" You haven't answered the question,
> you've just moved where you are asking it.

I think you can check fsl_msi.c to figure out what you want.
> 
> 
>> The vector/priority register (MSIVPR0) is at offset
>> 0x51c00.  Each interrupt source is 32 bytes.  The first interrupt
>> source is at 0x50000.
>>
>> So the interrupt number is (0x51c00 - 0x50000) / 32 = 224.
> 
> OK, so that's how you get the MPIC IRQ number. It's a pity that the key
> piece of information - "MPIC IRQ Numbers are defined by the interrupt
> vector table starting at 0x50000 and incrementing by 0x20 - see table 9.3
> of the MPD8641D manual for details" wasn't spelled out anywhere I could
> find.
> 
> Given the data I had: the kernel sources, the MPD8641D manual, and not
> much else, I had three unknowns:
> * a table of config registers, that could map an set of events into an
> arbitrary vector number.
> * The standard kernel "request_irq" API that takes that arbitrary vector
> number
> * A set of APIs (irq_of_parse_and_map(), irq_create_mapping) that were,
> for all intents, undocumented (just "here's the parameters", no
> description of when and how to use them), that took a ???? and returned a
> ???? (because, with the documentation I had, that's basically all I could
> say about them).

Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map the
real hardware irq to virtual irq. Then use request_irq() with the virtual irq to
hook your interrupt handler.

> 
> There was no documentation that said how to compute the MPIC interrupt
> vector, no documentation that said which API to use to convert that to an
> kernel IRQ, nothing.

Often most latest classic books/articles always use x86 code as an example to
clarify Linux. So you have to understand something on PPC via codes. But I think
you will benefit more information from the codes than documents :)

> 
>> BTW, the MSIs are already described in an msi node in the device tree.
> 
> As I stated previously - not that I can see. Neither does
> /proc/device_tree contain such a listing, nor does doing a
> "of_find_node_by_name(0,"msi");" nor "of_find_node_by_type(0,"msi");" find
> them.
> 
> It may be they are defined in PCI Root Complex mode, but again - I am
> writing code to handle Endpoint mode, which, as far as I can tell from the
> kernel sources, is NOT handled in any standardized way.

Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
previously said. And sounds Scott will do something to support EP for Freescale
chip.

Looks you want to your host root complex to trigger MSI to mpc8641 EP target? If
so I'm a bit confused since MSIs should be delivered to to the Root Complex
resided on your host.

Tiejun

> 
> 
> Again, it would be nice were this sort of thing documented somewhere. If
> it is, I'd love a link - I've tried every combination of search terms I
> can think of to find it to no avail.
> 
> If it isn't documented, might I suggest that either a) creating a
> dedicated "Programming PPC Embedded devices and their components under
> Linux" be created, or b) an appropriate chapter or chapters be drafted and
> submitted to the Linux Device Drivers book.
> 
> 
> Don't take this message the wrong way - I do want to say "THANK YOU FOR
> THE HELP!" - I am just trying to point out why somebody with a fair amount
> of Linux kernel experience and a great deal of general embedded experience
> is having great trouble doing a simple thing.
> 
> I'll try creating a mapping, binding to it, and seeing what happens.
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: tiejun.chen @ 2010-10-11  9:55 UTC (permalink / raw)
  To: david.hagood; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <8636b70ea34330679bebdaad187ccd68.squirrel@localhost>

david.hagood@gmail.com wrote:
> OK, using 224 as the MPIC interrupt number, and attempting to map it via
> irq_create_mapping(0,224) gives me a kernel seg fault:

This should not be correct without initialing MSI for MPIC host. As I comment on
another email, please refer to the file, arch/powerpc/sysdev/fsl_msi.c.

-Tiejun

> 
> Unable to handle kernel paging request for data at address 0x00000000
> Faulting instruction address: 0xc0016540
> Oops: Kernel access of bad area, sig: 11 [#1]
> PREEMPT SMP NR_CPUS=2 EP8641A
> Modules linked in: Endpoint_driver(+)
> NIP: c0016540 LR: c0050b38 CTR: c00163b8
> REGS: ef8c1ab0 TRAP: 0300   Not tainted  (2.6.26.2-ep1.10)
> MSR: 00001032 <ME,IR,DR>  CR: 24024482  XER: 00000000
> DAR: 00000000, DSISR: 40000000
> TASK = eedec6a0[60] 'insmod' THREAD: ef8c0000 CPU: 1
> GPR00: 00000000 ef8c1b60 eedec6a0 ffffffea 00000000 00000000 c035c17c
> 000000e0
> GPR08: 00400000 00000000 c035c020 00000000 24024422 100a7264 00000000
> 00000095
> GPR16: 00000095 00000000 0000000d 00000124 f102fd98 00000000 c004a4fc
> f102c000
> GPR24: 0000001a f1038400 00000000 c031e610 fffffffa 00009032 c031e5e0
> 000000e0
> NIP [c0016540] mpic_set_irq_type+0x188/0x1c4
> LR [c0050b38] set_irq_type+0x84/0xc8
> Call Trace:
> [ef8c1b60] [c0050b1c] set_irq_type+0x68/0xc8 (unreliable)
> [ef8c1b80] [c001572c] mpic_host_map+0xec/0xf4
> [ef8c1b90] [c00064a0] irq_setup_virq+0x60/0x98
> [ef8c1bb0] [c00065dc] irq_create_mapping+0x104/0x114
> [ef8c1bd0] [f1034798] Endpoint_device_ctor+0x258/0x3b8 [Endpoint_driver]
> 
> Reading the source (since these calls don't seem to have any other
> documentation), it *looks* like it ought to be valid to call
> irq_create_mapping with a null irq_host *host - which is good, since I
> can't see anything obvious that would give me some other irq_host (again,
> since none of this seems to be documented anywhere).
> 
> I am assuming the default host used by the system would be correct.
> 
> However, then I get this fault.
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: Freescale P2020 / 85xx PCIe and Advance Error Reporting (AER) service problem
From: Eran Liberty @ 2010-10-11 10:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linux-pci, linuxppc-dev
In-Reply-To: <1286756363.2463.517.camel@pasglop>

Benjamin Herrenschmidt wrote:
>>  - pcie_portdrv_probe() will be called for every BRIDGE class PCI device. P2020 PCIe is a PCI-PCI BRIDGE class so no problem here. 
>>  - The code will continue to check that we have PCI_CAP_ID_EXP capability, which we have and continue to pcie_port_device_register().
>>  - Now ,the function pcie_port_device_register() will FAIL. It will fail because it will call assign_interrupt_mode(), return with PCIE_PORT_NO_IRQ, and giveup with a reasonable remark in the code
>> "/*
>>   * Don't use service devices that require interrupts if there is
>>   * no way to generate them.
>>   */"
>>
>> So now the question is why calling assign_interrupt_mode() with the P2020 PCIe ROOT device return empty? Well...
>>  - First assign_interrupt_mode() will test for PCIE_PORT_MSIX_MODE. Freescale PCIe does not support this...
>>  - Second attampt is made to discover PCIE_PORT_MSI_MODE, which Freescale should support but the PCIe PCI_CAP_ID_MSI capability is published on the device side of the bridge and NOT on the PCIe ROOT device, which is the one probed and thus fails.
>>  - Last it attempts to look at "dev->pin" in order to set PCIE_PORT_INTx_MODE. On top of being the less recommended way (the old way), The Freescale PCIE ROOT device pin is not set anywhere.
>>
>> Failing all those the probe fails and the AER service is not activated for the PCIE device.
>
> So the question boils down to how does the bridge generate the AER
> interrupts. This should be documented in the FSL docs no ? The MSI in
> the child/device should be unrelated (it's your device MSI) no ? So the
> question is where's the missing interrupt.
>
> If it's a SoC interrupt, coming from the device-tree, then perhaps the
> generic AER code should be extended to recognize those.
>
> Cheers,
> Ben.
>
I agree...

BUT if we take into consideration that:
1. Freescale is a serious dude in the hood and on the whole does a good 
job with its products and their Linux support.
2. The P2020 does state it has an MSI mechanism support (although one is 
not present as a PCIe capability header for some reason)
3. Errors in general and AER are major features in PCIe.
4. PCIe has been here quite a while and it is not new to Freescale or 
anyone else.
I am much more inclined to believe that I have missed something by a 
mile then that Freescale did. I just don't know what I am missing.

My device tree is a clone of "arch/ powerpc/ boot/ dts/ p2020rdb.dts"

It has a PCI node that looks like this:
----------------------------- snip -----------------------------
    pci0: pcie@ffe09000 {
        cell-index = <1>;
        compatible = "fsl,mpc8548-pcie";
        device_type = "pci";
        #interrupt-cells = <1>;
        #size-cells = <2>;
        #address-cells = <3>;
        reg = <0 0xffe09000 0 0x1000>;
        bus-range = <0 255>;
        ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
              0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
        clock-frequency = <33333333>;
        interrupt-parent = <&mpic>;
        interrupts = <25 2>;
        interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
        interrupt-map = <
            /* IDSEL 0x0 */
            0000 0x0 0x0 0x1 &mpic 0x4 0x1
            0000 0x0 0x0 0x2 &mpic 0x5 0x1
            0000 0x0 0x0 0x3 &mpic 0x6 0x1
            0000 0x0 0x0 0x4 &mpic 0x7 0x1
            >;
        pcie@0 {
            reg = <0x0 0x0 0x0 0x0 0x0>;
            #size-cells = <2>;
            #address-cells = <3>;
            device_type = "pci";
            ranges = <0x2000000 0x0 0xa0000000
                  0x2000000 0x0 0xa0000000
                  0x0 0x20000000

                  0x1000000 0x0 0x0
                  0x1000000 0x0 0x0
                  0x0 0x100000>;
        };
    };
----------------------------- snap -----------------------------

and under "soc" it has an MSI node that looks like that:
----------------------------- snip -----------------------------
        msi@41600 {
            compatible = "fsl,p2020-msi", "fsl,mpic-msi";
            reg = <0x41600 0x80>;
            msi-available-ranges = <0 0x100>;
            interrupts = <
                0xe0 0
                0xe1 0
                0xe2 0
                0xe3 0
                0xe4 0
                0xe5 0
                0xe6 0
                0xe7 0>;
            interrupt-parent = <&mpic>;
        };
----------------------------- snap -----------------------------

-- Liberty

^ permalink raw reply

* Re: Questions on interrupt vector assignment on MPC8641D
From: David Hagood @ 2010-10-11 11:30 UTC (permalink / raw)
  To: tiejun.chen; +Cc: Scott Wood, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4CB2DE2B.7040504@windriver.com>

On Mon, 2010-10-11 at 17:51 +0800, tiejun.chen wrote:
> 
> You should define MSI device nodes on your target dts. And you can refer to the
> file, mpc8572ds.dts.
> 
> Often U-Boot dose not generate MSI information and embed that to dtb.
> 
> > 
> > But even assuming you can define these nodes at run time, as far as I can
> > see, you are right back to the question of "and how do I know what the
> > mappings are so I can create the node?" You haven't answered the question,
> > you've just moved where you are asking it.
> 
> I think you can check fsl_msi.c to figure out what you want.
<snip>

> Often most latest classic books/articles always use x86 code as an
example to
> clarify Linux. So you have to understand something on PPC via codes.
But I think
> you will benefit more information from the codes than documents :)
> 

RTFS. That wouldn't be bad advice, if the source were actually
commented. None of these APIS have any meaningful comments in them,
around them, or anywhere near them. You'd think we were back in the old
BASIC days, when comments occupied run-time memory. Code can tell me
WHAT is being done, but not WHY, and not what assumptions are being
made.

So when you say "You should define MSI device nodes on your target dts."
we go right back to my comment of "You haven't answered the question,
you've just moved where you are asking it."

> 
> Firstly you should use irq_of_parse_and_map()/irq_create_mapping() to map the
> real hardware irq to virtual irq. Then use request_irq() with the virtual irq to
> hook your interrupt handler.
And when I do that, I get a segfault as my follow-on mail reports.

> 
> Maybe you can check the file, ppc4xx_pci.c since ppc4xx also can support EP as I
> previously said. And sounds Scott will do something to support EP for Freescale
> chip.
I will look at that file.

> 
> Looks you want to your host root complex to trigger MSI to mpc8641 EP target? If
> so I'm a bit confused since MSIs should be delivered to to the Root Complex
> resided on your host.
I want the host to be able to interrupt the PPC. Since this is PCIe, the
only way that will be working is for the root complex to do a write to
somewhere on the PPC. This is basically the same mechanism as MSI, only
with the PPC as the target of the write rather than the root complex.
Obviously, the rest of the PCI devices will be sending interrupts to the
root complex, some via MSI. That has nothing to do with this discussion.

Since the PPC is in endpoint mode, the MSI hardware on the PPC won't be
used. The hardware is writable from the root complex via the PPC BAR0,
so I see no reason not to reuse it to trigger interrupts on the PPC from
the Root complex.

^ 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