* Re: Porting a driver to powerpc using FDT
From: Grant Likely @ 2010-06-17 14:55 UTC (permalink / raw)
To: Chris Alfred; +Cc: linuxppc-dev
In-Reply-To: <DC0A9AAD98D847FC97F74D4B04C4E898@kos>
On Wed, Jun 16, 2010 at 10:25 PM, Chris Alfred
<c.alfred@internode.on.net> wrote:
>>>>> dsa_of_init is successfully called; but dsa_of_probe is not
>>>>> called.
>>>>
>>>> That means the node is not being used to register an of_device. I
>>>> need some more information to suggest how best to fix this.
>>>
>>>> What SoC are you using?
>>>> What file in arch/powerpc/platforms/* is used to setup your
>>>> machine?
>>>
>>> We are using the MPC5200. Very similar to the Lite5200.
>>
>> So you're board is driver by
>> arch/powerpc/platforms/52xx/mpc5200_simple.c then?
>
> The Lite5200 is based on arch/powerpc/platforms/52xx/lite5200.c
>
> We have only done a text search/replace lite5200 to jkc5200.
> Based on your email, we have now also changed fsl,jkc5200n8 to
> jkc,jkc5200n8
Unless you need to add a bunch of board specific setup, you shouldn't
need to do this. It should be sufficient to add jkc,jkc5200n8 to the
list of boards in mpc5200_simple.c. The Lite5200 has a separate board
file because the original u-boot firmware for it didn't setup clocks
or port_config correctly. Almost every other board uses
mpc5200_simple.c
media5200 is the other exception because it needs to add a whole other
irq controller.
>> As mentioned, drop the reg property and be more specific in the
>> compatible value.
>
> Done, changed fsl,jkc5200n8 to jkc,jkc5200n8
>
>> If you do the
>> following, then it should start working:
>>
>> virtual-devices {
>> =A0 =A0 =A0 =A0 compatible =3D "simple-bus";
>> =A0 =A0 =A0 =A0 dsa {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "<vendor>,jkc5200n8-dsa";
>> =A0 =A0 =A0 =A0 };
>> };
>
> Where did "simple-bus" come from?
>
> Did you mean "mpc5200-simple-platform" from:
>
> =A0 =A0define_machine(mpc5200_simple_platform) {
> =A0 =A0 .name =A0=3D "mpc5200-simple-platform",
No, mpc5200-simple-platform is just a name shown to users. It doesn't
actually match against anything in the device tree.
"simple-bus" means that a node represents a simple transparent bridge
device. Linux uses that value to decide that the bus node contains
device nodes that it should register. Take a look at the ePAPR spec.
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: Porting a driver to powerpc using FDT
From: Grant Likely @ 2010-06-17 16:37 UTC (permalink / raw)
To: Chris Alfred; +Cc: linuxppc-dev
In-Reply-To: <6EAB45775B71486B8E72844E797E1D0F@kos>
Hi Chris, thanks for the write up. Some comments below, and I'm also
in the process of writing better documentation for all of this. You
can find it here:
http://devicetree.org/Device_Tree_Usage
That page describes how the device tree is structured. I'm about to
start another page on how Linux uses the device tree. That page
should cover the same topics that you describe below.
On Thu, Jun 17, 2010 at 5:11 AM, Chris Alfred <c.alfred@internode.on.net> w=
rote:
>> virtual-devices {
>> =A0 =A0 =A0 =A0 compatible =3D "simple-bus";
>> =A0 =A0 =A0 =A0 dsa {
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "<vendor>,jkc5200n8-dsa";
>> =A0 =A0 =A0 =A0 };
>> };
>
> Ok, after correcting the names, the basic OF driver is probed.
>
> Now to try and use probe to register the DSA platform driver with the
> OF driver as its parent.
>
>
> =3D=3D=3D=3D=3D=3D=3D
>
> For those interested in how to get a very basic OF (uses FDT) driver
> going, the steps I did are below.
>
> 'myvendor' is your company name, and 'mydevice' is the name of the
> device - use better names in real code.
>
> (1) The .dts file - this is the Flattened Device Tree (FDT)
> descriptor:
>
> =A0 =A0/ {
> =A0 =A0 =A0 =A0...
>
> =A0 =A0 =A0 =A0 virtual-device {
> =A0 =A0 =A0 =A0 =A0compatible =3D "simple-bus";
> =A0 =A0 =A0 =A0 =A0mydevice0 {
> =A0 =A0 =A0 =A0 =A0 compatible =3D "myvendor,mydevice";
> =A0 =A0 =A0 =A0 =A0};
> =A0 =A0 =A0 =A0 };
>
> =A0 =A0 =A0 =A0...
> =A0 =A0};
>
> =A0 =A0For my board "simple-bus" is an already defined bus in the .dts.
> In my case the .dts had:
This comment raised warning flags for me. Can you post your new
current device tree? It sounds like you put your DSA device into the
localbus node. You shouldn't need to do that. Many nodes in a single
tree can claim compatibility with "simple-bus".
>
> =A0 =A0/ {
> =A0 =A0 =A0 =A0...
>
> =A0 =A0 =A0 =A0localbus {
> =A0 =A0 =A0 =A0 =A0compatible =3D
> "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
>
> =A0 =A0 =A0 =A0 =A0...
> =A0 =A0 =A0 =A0 };
>
> =A0 =A0 =A0 =A0...
> =A0 =A0};
>
> (2) Create the OF driver:
>
> =A0 =A0#include <linux/of.h>
> =A0 =A0#include <linux/kernel.h>
> =A0 =A0#include <linux/of_platform.h>
>
> =A0 =A0static int __devinit mydevice_probe(struct of_device *ofdev, const
> struct of_device_id *match)
> =A0 =A0{
> =A0 =A0 printk("mydevice_probe\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
> =A0 =A0static int mydevice_remove(struct of_device *ofdev)
__devexit
> =A0 =A0{
> =A0 =A0 printk("mydevice_remove\n");
> =A0 =A0 return 0;
> =A0 =A0}
>
>
> =A0 =A0static const struct of_device_id mydevice_match[] =3D {
> =A0 =A0 {
> =A0 =A0 =A0.compatible =3D "myvendor,mydevice",
> =A0 =A0 },
> =A0 =A0 {}
> =A0 =A0};
>
> =A0 =A0static struct of_platform_driver mydevice_driver =3D {
> =A0 =A0 .name =3D "mydevice-driver",
> =A0 =A0 .match_table =3D mydevice_match,
> =A0 =A0 .probe =3D mydevice_probe,
> =A0 =A0 .remove =3D mydevice_remove,
> =A0 =A0};
.remove =3D __devexit_P(mydevice_remove),
>
> =A0 =A0static int __init mydevice_driver_init(void)
> =A0 =A0{
> =A0 =A0 printk("mydevice_drver_init\n");
>
> =A0 =A0 if (of_register_platform_driver(&mydevice_driver))
> =A0 =A0 =A0printk(KERN_ERR "Unable to register platform driver\n");
>
> =A0 =A0 return 0;
> =A0 =A0}
> =A0 =A0module_init(mydevice_driver_init);
Should actually be:
static int __init mydevice_driver_init(void)
{
printk("mydevice_drver_init\n");
return of_register_platform_driver(&mydevice_driver);
}
module_init(mydevice_driver_init);
The driver core will report an error if registration fails.
>
> =A0 =A0static void __exit mydevice_driver_cleanup(void)
> =A0 =A0{
> =A0 =A0 printk("mydevice_driver_cleanup\n");
>
> =A0 =A0 of_unregister_platform_driver(&mydevice_driver);
> =A0 =A0}
> =A0 =A0module_exit(mydevice_driver_cleanup);
>
> =A0 =A0MODULE_DESCRIPTION("mydevice driver");
> =A0 =A0MODULE_AUTHOR("name <email>");
> =A0 =A0MODULE_LICENSE("GPL v2");
> =A0 =A0MODULE_ALIAS("platform:mydevice-driver");
>
> (3) Change the appropriate Makefile and Kconfig to compile the OF
> driver.
>
> During kernel boot you should see the lines:
>
> =A0 =A0mydevice_driver_init
> =A0 =A0mydevice_probe
>
> If not, you probably have one of the strings (text in " ") incorrect.
>
> In /sys/bus/of_platform/drivers, you should have a directory named
> 'mydevice-driver'.
>
> In /sys/bus/of_platform/drivers/mydevice-driver you should have a
> directory named 'mydevice0.1'. The name 'mydevice0' comes from the
> .dts above.
which will be a symlink to the actual device location in the internal
Linux device hierarchy.
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> Brief explaination of how I think this is all tied together:
>
> (1) The Flattened Device Tree is included with the compiled kernel
> image.
Generally not. Usually the device tree is passed in via u-boot.
There is a form (cuImage) that links the dtb into the kernel, but that
is not recommended, and is only used for supporting old version of
u-boot that cannot pass the dtb at boot.
> (2) The module_init(...) macro is like declaring a 'main' for drivers.
> The kernel calls all of the functions declared in the module_init(...)
> macros during startup.
yes.
> (3) When a device driver is registered via
> of_register_platform_driver(), this invokes a scan of the FDT to find
> matches with strings in the .match_table. If a match is found, the
> .probe is called for the created device instance.
Not quite. Registering drivers does not cause a scan of the DT.
Instead, it looks in the list of registered devices to see if there is
anything to bind against. The devices are actually registered at boot
time in the function of_platform_bus_probe() which on the mpc5200 is
called by the function mpc52xx_declare_of_platform_devices().
Drivers won't bind against anything that isn't already registered as a
device in the Linux device model.
Cheers,
g.
^ permalink raw reply
* Fixed-link PHY question
From: Gary Thomas @ 2010-06-17 17:56 UTC (permalink / raw)
To: Linux PPC Development
I'm working with 2.6.33.3 on a MPC8358. I'm trying to get it
to talk to a Marvell (DSA) switch which uses special drivers
and addressing to act like a PHY. I have this working fine
on some older (2.6.28) systems by using a fixed-link PHY
descriptor in my device tree (using the TSEC on 8347).
The GETH driver calls 'of_phy_connect_fixed_link' which
always gives me this error:
PHY 0:01 not found
net eth1: Could not attach to PHY
How can I get the GETH driver to just accept the pseudo
PHY connection specified by
fixed-link = <1 1 1000 0 0>;
Thanks
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: Fixed-link PHY question
From: Gary Thomas @ 2010-06-17 18:50 UTC (permalink / raw)
To: Linux PPC Development
In-Reply-To: <4C1A61D9.4020306@mlbassoc.com>
On 06/17/2010 11:56 AM, Gary Thomas wrote:
> I'm working with 2.6.33.3 on a MPC8358. I'm trying to get it
> to talk to a Marvell (DSA) switch which uses special drivers
> and addressing to act like a PHY. I have this working fine
> on some older (2.6.28) systems by using a fixed-link PHY
> descriptor in my device tree (using the TSEC on 8347).
>
> The GETH driver calls 'of_phy_connect_fixed_link' which
> always gives me this error:
> PHY 0:01 not found
> net eth1: Could not attach to PHY
>
> How can I get the GETH driver to just accept the pseudo
> PHY connection specified by
> fixed-link = <1 1 1000 0 0>;
Figured it out - my ethernet node in the device tree has
to be called 'ethernet' for the fixed PHY emulation to see
the fixed-link properties.
Seems rather limited, but I don't have time to change it.
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* [PATCHv2 0/2] powerpc: pSeries Partition Hibernation
From: Brian King @ 2010-06-17 21:53 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
Here is a refresh of partition hibernation support for pSeries.
It includes a fix for a regression in the partition migration
support. Barring any objections, I think these patches should
be ready to merge.
Overview
---------
Partition Hibernation on pSeries is a new platform feature that
allows for long term suspension of a logical partition much like
suspending a laptop to disk. The primary difference is that writing
the memory image out to disk is driven by system firmware and the
Virtual I/O Server rather than from the LPAR itself. Partition
hibernation on Power is initiated from the Hardware Management Console.
The user selects the partition, then selects the suspend function.
This results in a command (drmgr) getting sent to the Linux partition,
indicating it should prepare for suspension. A "stream id" is sent
to the Linux LPAR which is used by the OS to correlate with firmware.
In the Linux LPAR, the drmgr command then writes this stream id to
a new sysfs file: /sys/devices/system/power/hibernate. The kernel
then takes over, calling H_VASI_ENABLE with the stream id as
long as firmware indicates it is suspending but not ready for
the client LPAR to enter the final phase of the suspension.
Once H_VASI_ENABLE returns a state of H_VASI_SUSPENDING, the client
OS is expected to enter the final phase of hibernation. To do this,
we then simply invoke the pm_suspend code and mimic suspend to ram.
We mimic suspend to ram rather than suspend to disk, since firmware
and the VIOS takes care of writing everything out to disk. We are
then able to leverage all the existing suspend code in the kernel.
Once we enter the prepare_late phase of suspend, we set a flag which
we check when disable_nonboot_cpus gets called. When the nonboot
CPU gets offlined and placed into the inactive state, we hook
into pseries_mach_cpu_die in order to call H_JOIN, since the
nonboot CPUs need to be in H_JOIN state when we finally suspend.
Once all the nonboot CPUs have been offlined and are in H_JOIN,
and we get to the "enter" state, we make the ibm,suspend-me RTAS
call on the remaining CPU which then completes the hibernation.
When we resume, there is very little platform code required to
execute. enable_nonboot_cpus already sends an H_PROD as part
of bringing up the nonboot cpus, so this will kick the CPU out
of H_JOIN. I've already added resume handlers to the virtual
I/O drivers to check for any dropped interrupts. drmgr then
handles updating the device tree just like it does today
for live partition migration.
These patches have been tested with repeated suspend/resume
cycles. Partition migration has also been regression tested
since the first patch touches that path.
--
Brian King
Linux on Power Virtualization
IBM Linux Technology Center
^ permalink raw reply
* [PATCHv2 1/2] powerpc: Migration code reorganization / hibernation prep
From: Brian King @ 2010-06-17 21:54 UTC (permalink / raw)
To: benh; +Cc: brking, linuxppc-dev
Partition hibernation will use some of the same code as is
currently used for Live Partition Migration. This function
further abstracts this code such that code outside of rtas.c
can utilize it. It also changes the error field in the suspend
me data structure to be an atomic type, since it is set and
checked on different cpus without any barriers or locking.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 1
arch/powerpc/include/asm/rtas.h | 10 +++
arch/powerpc/kernel/rtas.c | 105 +++++++++++++++++++++++++-------------
3 files changed, 81 insertions(+), 35 deletions(-)
diff -puN arch/powerpc/include/asm/rtas.h~powerpc_rtas_hibernate_prep arch/powerpc/include/asm/rtas.h
--- linux-2.6/arch/powerpc/include/asm/rtas.h~powerpc_rtas_hibernate_prep 2010-06-16 13:49:29.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/rtas.h 2010-06-16 13:49:29.000000000 -0500
@@ -63,6 +63,14 @@ struct rtas_t {
struct device_node *dev; /* virtual address pointer */
};
+struct rtas_suspend_me_data {
+ atomic_t working; /* number of cpus accessing this struct */
+ atomic_t done;
+ int token; /* ibm,suspend-me */
+ atomic_t error;
+ struct completion *complete; /* wait on this until working == 0 */
+};
+
/* RTAS event classes */
#define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */
#define RTAS_EPOW_WARNING 0x40000000 /* set bit 1 */
@@ -174,6 +182,8 @@ extern int rtas_set_indicator(int indica
extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
extern void rtas_progress(char *s, unsigned short hex);
extern void rtas_initialize(void);
+extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
struct rtc_time;
extern unsigned long rtas_get_boot_time(void);
diff -puN arch/powerpc/kernel/rtas.c~powerpc_rtas_hibernate_prep arch/powerpc/kernel/rtas.c
--- linux-2.6/arch/powerpc/kernel/rtas.c~powerpc_rtas_hibernate_prep 2010-06-16 13:49:29.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/kernel/rtas.c 2010-06-16 15:29:44.000000000 -0500
@@ -47,14 +47,6 @@ struct rtas_t rtas = {
};
EXPORT_SYMBOL(rtas);
-struct rtas_suspend_me_data {
- atomic_t working; /* number of cpus accessing this struct */
- atomic_t done;
- int token; /* ibm,suspend-me */
- int error;
- struct completion *complete; /* wait on this until working == 0 */
-};
-
DEFINE_SPINLOCK(rtas_data_buf_lock);
EXPORT_SYMBOL(rtas_data_buf_lock);
@@ -714,14 +706,53 @@ void rtas_os_term(char *str)
static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
#ifdef CONFIG_PPC_PSERIES
-static void rtas_percpu_suspend_me(void *info)
+static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_when_done)
+{
+ u16 slb_size = mmu_slb_size;
+ int rc = H_MULTI_THREADS_ACTIVE;
+ int cpu;
+
+ slb_set_size(SLB_MIN_SIZE);
+ printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id());
+
+ while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) &&
+ !atomic_read(&data->error))
+ rc = rtas_call(data->token, 0, 1, NULL);
+
+ if (rc || atomic_read(&data->error)) {
+ printk(KERN_DEBUG "ibm,suspend-me returned %d\n", rc);
+ slb_set_size(slb_size);
+ }
+
+ if (atomic_read(&data->error))
+ rc = atomic_read(&data->error);
+
+ atomic_set(&data->error, rc);
+
+ if (wake_when_done) {
+ atomic_set(&data->done, 1);
+
+ for_each_online_cpu(cpu)
+ plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
+ }
+
+ if (atomic_dec_return(&data->working) == 0)
+ complete(data->complete);
+
+ return rc;
+}
+
+int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data)
+{
+ atomic_inc(&data->working);
+ return __rtas_suspend_last_cpu(data, 0);
+}
+
+static int __rtas_suspend_cpu(struct rtas_suspend_me_data *data, int wake_when_done)
{
long rc = H_SUCCESS;
unsigned long msr_save;
- u16 slb_size = mmu_slb_size;
int cpu;
- struct rtas_suspend_me_data *data =
- (struct rtas_suspend_me_data *)info;
atomic_inc(&data->working);
@@ -729,7 +760,7 @@ static void rtas_percpu_suspend_me(void
msr_save = mfmsr();
mtmsr(msr_save & ~(MSR_EE));
- while (rc == H_SUCCESS && !atomic_read(&data->done))
+ while (rc == H_SUCCESS && !atomic_read(&data->done) && !atomic_read(&data->error))
rc = plpar_hcall_norets(H_JOIN);
mtmsr(msr_save);
@@ -741,33 +772,37 @@ static void rtas_percpu_suspend_me(void
/* All other cpus are in H_JOIN, this cpu does
* the suspend.
*/
- slb_set_size(SLB_MIN_SIZE);
- printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
- smp_processor_id());
- data->error = rtas_call(data->token, 0, 1, NULL);
-
- if (data->error) {
- printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
- data->error);
- slb_set_size(slb_size);
- }
+ return __rtas_suspend_last_cpu(data, wake_when_done);
} else {
printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
smp_processor_id(), rc);
- data->error = rc;
+ atomic_set(&data->error, rc);
}
- atomic_set(&data->done, 1);
+ if (wake_when_done) {
+ atomic_set(&data->done, 1);
- /* This cpu did the suspend or got an error; in either case,
- * we need to prod all other other cpus out of join state.
- * Extra prods are harmless.
- */
- for_each_online_cpu(cpu)
- plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
+ /* This cpu did the suspend or got an error; in either case,
+ * we need to prod all other other cpus out of join state.
+ * Extra prods are harmless.
+ */
+ for_each_online_cpu(cpu)
+ plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
+ }
out:
if (atomic_dec_return(&data->working) == 0)
complete(data->complete);
+ return rc;
+}
+
+int rtas_suspend_cpu(struct rtas_suspend_me_data *data)
+{
+ return __rtas_suspend_cpu(data, 0);
+}
+
+static void rtas_percpu_suspend_me(void *info)
+{
+ __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
}
static int rtas_ibm_suspend_me(struct rtas_args *args)
@@ -802,22 +837,22 @@ static int rtas_ibm_suspend_me(struct rt
atomic_set(&data.working, 0);
atomic_set(&data.done, 0);
+ atomic_set(&data.error, 0);
data.token = rtas_token("ibm,suspend-me");
- data.error = 0;
data.complete = &done;
/* Call function on all CPUs. One of us will make the
* rtas call
*/
if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
- data.error = -EINVAL;
+ atomic_set(&data.error, -EINVAL);
wait_for_completion(&done);
- if (data.error != 0)
+ if (atomic_read(&data.error) != 0)
printk(KERN_ERR "Error doing global join\n");
- return data.error;
+ return atomic_read(&data.error);
}
#else /* CONFIG_PPC_PSERIES */
static int rtas_ibm_suspend_me(struct rtas_args *args)
diff -puN arch/powerpc/include/asm/hvcall.h~powerpc_rtas_hibernate_prep arch/powerpc/include/asm/hvcall.h
--- linux-2.6/arch/powerpc/include/asm/hvcall.h~powerpc_rtas_hibernate_prep 2010-06-16 13:49:29.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/hvcall.h 2010-06-16 13:49:29.000000000 -0500
@@ -74,6 +74,7 @@
#define H_NOT_ENOUGH_RESOURCES -44
#define H_R_STATE -45
#define H_RESCINDEND -46
+#define H_MULTI_THREADS_ACTIVE -9005
/* Long Busy is a condition that can be returned by the firmware
_
^ permalink raw reply
* [PATCHv2 2/2] powerpc: Partition hibernation support
From: Brian King @ 2010-06-17 21:54 UTC (permalink / raw)
To: benh; +Cc: brking, linuxppc-dev
Enables support for HMC initiated partition hibernation. This is
a firmware assisted hibernation, since the firmware handles writing
the memory out to disk, along with other partition information,
so we just mimic suspend to ram.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 2
arch/powerpc/include/asm/machdep.h | 1
arch/powerpc/platforms/pseries/Makefile | 4
arch/powerpc/platforms/pseries/hotplug-cpu.c | 3
arch/powerpc/platforms/pseries/suspend.c | 214 +++++++++++++++++++++++++++
5 files changed, 223 insertions(+), 1 deletion(-)
diff -puN /dev/null arch/powerpc/platforms/pseries/suspend.c
--- /dev/null 2009-12-15 17:58:07.000000000 -0600
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/suspend.c 2010-06-16 13:49:30.000000000 -0500
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2010 Brian King IBM Corporation
+ *
+ * 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/delay.h>
+#include <linux/suspend.h>
+#include <asm/firmware.h>
+#include <asm/hvcall.h>
+#include <asm/machdep.h>
+#include <asm/mmu.h>
+#include <asm/rtas.h>
+
+static u64 stream_id;
+static struct sys_device suspend_sysdev;
+static DECLARE_COMPLETION(suspend_work);
+static struct rtas_suspend_me_data suspend_data;
+static atomic_t suspending;
+
+/**
+ * pseries_suspend_begin - First phase of hibernation
+ *
+ * Check to ensure we are in a valid state to hibernate
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int pseries_suspend_begin(suspend_state_t state)
+{
+ long vasi_state, rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ /* Make sure the state is valid */
+ rc = plpar_hcall(H_VASI_STATE, retbuf, stream_id);
+
+ vasi_state = retbuf[0];
+
+ if (rc) {
+ pr_err("pseries_suspend_begin: vasi_state returned %ld\n",rc);
+ return rc;
+ } else if (vasi_state == H_VASI_ENABLED) {
+ return -EAGAIN;
+ } else if (vasi_state != H_VASI_SUSPENDING) {
+ pr_err("pseries_suspend_begin: vasi_state returned state %ld\n",
+ vasi_state);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * pseries_suspend_cpu - Suspend a single CPU
+ *
+ * Makes the H_JOIN call to suspend the CPU
+ *
+ **/
+static int pseries_suspend_cpu(void)
+{
+ if (atomic_read(&suspending))
+ return rtas_suspend_cpu(&suspend_data);
+ return 0;
+}
+
+/**
+ * pseries_suspend_enter - Final phase of hibernation
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int pseries_suspend_enter(suspend_state_t state)
+{
+ int rc = rtas_suspend_last_cpu(&suspend_data);
+
+ atomic_set(&suspending, 0);
+ atomic_set(&suspend_data.done, 1);
+ return rc;
+}
+
+/**
+ * pseries_prepare_late - Prepare to suspend all other CPUs
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int pseries_prepare_late(void)
+{
+ atomic_set(&suspending, 1);
+ atomic_set(&suspend_data.working, 0);
+ atomic_set(&suspend_data.done, 0);
+ atomic_set(&suspend_data.error, 0);
+ suspend_data.complete = &suspend_work;
+ INIT_COMPLETION(suspend_work);
+ return 0;
+}
+
+/**
+ * store_hibernate - Initiate partition hibernation
+ * @classdev: sysdev class struct
+ * @attr: class device attribute struct
+ * @buf: buffer
+ * @count: buffer size
+ *
+ * Write the stream ID received from the HMC to this file
+ * to trigger hibernating the partition
+ *
+ * Return value:
+ * number of bytes printed to buffer / other on failure
+ **/
+static ssize_t store_hibernate(struct sysdev_class *classdev,
+ struct sysdev_class_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ stream_id = simple_strtoul(buf, NULL, 16);
+
+ do {
+ rc = pseries_suspend_begin(PM_SUSPEND_MEM);
+ if (rc == -EAGAIN)
+ ssleep(1);
+ } while (rc == -EAGAIN);
+
+ if (!rc)
+ rc = pm_suspend(PM_SUSPEND_MEM);
+
+ stream_id = 0;
+
+ if (!rc)
+ rc = count;
+ return rc;
+}
+
+static SYSDEV_CLASS_ATTR(hibernate, S_IWUSR, NULL, store_hibernate);
+
+static struct sysdev_class suspend_sysdev_class = {
+ .name = "power",
+};
+
+static struct platform_suspend_ops pseries_suspend_ops = {
+ .valid = suspend_valid_only_mem,
+ .begin = pseries_suspend_begin,
+ .prepare_late = pseries_prepare_late,
+ .enter = pseries_suspend_enter,
+};
+
+/**
+ * pseries_suspend_sysfs_register - Register with sysfs
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int pseries_suspend_sysfs_register(struct sys_device *sysdev)
+{
+ int rc;
+
+ if ((rc = sysdev_class_register(&suspend_sysdev_class)))
+ return rc;
+
+ sysdev->id = 0;
+ sysdev->cls = &suspend_sysdev_class;
+
+ if ((rc = sysdev_class_create_file(&suspend_sysdev_class, &attr_hibernate)))
+ goto class_unregister;
+
+ return 0;
+
+class_unregister:
+ sysdev_class_unregister(&suspend_sysdev_class);
+ return rc;
+}
+
+/**
+ * pseries_suspend_init - initcall for pSeries suspend
+ *
+ * Return value:
+ * 0 on success / other on failure
+ **/
+static int __init pseries_suspend_init(void)
+{
+ int rc;
+
+ if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR))
+ return 0;
+
+ suspend_data.token = rtas_token("ibm,suspend-me");
+ if (suspend_data.token == RTAS_UNKNOWN_SERVICE)
+ return 0;
+
+ if ((rc = pseries_suspend_sysfs_register(&suspend_sysdev)))
+ return rc;
+
+ ppc_md.suspend_disable_cpu = pseries_suspend_cpu;
+ suspend_set_ops(&pseries_suspend_ops);
+ return 0;
+}
+
+__initcall(pseries_suspend_init);
diff -puN arch/powerpc/Kconfig~powerpc_allarch_pseries_hibernation arch/powerpc/Kconfig
--- linux-2.6/arch/powerpc/Kconfig~powerpc_allarch_pseries_hibernation 2010-06-16 13:49:30.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/Kconfig 2010-06-16 13:49:30.000000000 -0500
@@ -218,7 +218,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_85xx || PPC_86xx || PPC_PSERIES
config PPC_DCR_NATIVE
bool
diff -puN arch/powerpc/platforms/pseries/Makefile~powerpc_allarch_pseries_hibernation arch/powerpc/platforms/pseries/Makefile
--- linux-2.6/arch/powerpc/platforms/pseries/Makefile~powerpc_allarch_pseries_hibernation 2010-06-16 13:49:30.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/Makefile 2010-06-16 13:49:30.000000000 -0500
@@ -26,3 +26,7 @@ obj-$(CONFIG_HCALL_STATS) += hvCall_inst
obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_DTL) += dtl.o
+
+ifeq ($(CONFIG_PPC_PSERIES),y)
+obj-$(CONFIG_SUSPEND) += suspend.o
+endif
diff -puN arch/powerpc/include/asm/machdep.h~powerpc_allarch_pseries_hibernation arch/powerpc/include/asm/machdep.h
--- linux-2.6/arch/powerpc/include/asm/machdep.h~powerpc_allarch_pseries_hibernation 2010-06-16 13:49:30.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/include/asm/machdep.h 2010-06-16 13:49:30.000000000 -0500
@@ -266,6 +266,7 @@ struct machdep_calls {
void (*suspend_disable_irqs)(void);
void (*suspend_enable_irqs)(void);
#endif
+ int (*suspend_disable_cpu)(void);
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
ssize_t (*cpu_probe)(const char *, size_t);
diff -puN arch/powerpc/platforms/pseries/hotplug-cpu.c~powerpc_allarch_pseries_hibernation arch/powerpc/platforms/pseries/hotplug-cpu.c
--- linux-2.6/arch/powerpc/platforms/pseries/hotplug-cpu.c~powerpc_allarch_pseries_hibernation 2010-06-16 13:49:30.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/hotplug-cpu.c 2010-06-16 13:49:30.000000000 -0500
@@ -116,6 +116,9 @@ static void pseries_mach_cpu_die(void)
if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
set_cpu_current_state(cpu, CPU_STATE_INACTIVE);
+ if (ppc_md.suspend_disable_cpu)
+ ppc_md.suspend_disable_cpu();
+
cede_latency_hint = 2;
get_lppaca()->idle = 1;
_
^ permalink raw reply
* Re: Porting a driver to powerpc using FDT
From: Chris Alfred @ 2010-06-17 22:15 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <AANLkTilWdUcjK29QAJki75miWQt7Hzv8KWOXrtCvtPi8@mail.gmail.com>
>> (1) The .dts file - this is the Flattened Device Tree (FDT)
>> descriptor:
>>
>> / {
>> ...
>>
>> virtual-device {
>> compatible = "simple-bus";
>> mydevice0 {
>> compatible = "myvendor,mydevice";
>> };
>> };
>>
>> ...
>> };
>>
>> For my board "simple-bus" is an already defined bus in the .dts.
>> In my case the .dts had:
>
> This comment raised warning flags for me. Can you post your new
> current device tree? It sounds like you put your DSA device into
> the
> localbus node. You shouldn't need to do that. Many nodes in a
> single
> tree can claim compatibility with "simple-bus".
I guess my example structure was not clear. virtual-device is not
inside localbus. My current .dts is below.
/dts-v1/;
/ {
model = "jkc,jkc5200n8";
compatible = "jkc,jkc5200n8";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&mpc5200_pic>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,5200@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <32>;
i-cache-line-size = <32>;
d-cache-size = <0x4000>; // L1, 16K
i-cache-size = <0x4000>; // L1, 16K
timebase-frequency = <0>; // from bootloader
bus-frequency = <0>; // from bootloader
clock-frequency = <0>; // from bootloader
};
};
memory {
device_type = "memory";
reg = <0x00000000 0x10000000>; // 256MB
};
soc5200@f0000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,mpc5200b-immr";
ranges = <0 0xf0000000 0x0000c000>;
reg = <0xf0000000 0x00000100>;
bus-frequency = <0>; // from bootloader
system-frequency = <0>; // from bootloader
cdm@200 {
compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
reg = <0x200 0x38>;
};
mpc5200_pic: interrupt-controller@500 {
// 5200 interrupts are encoded into two levels;
interrupt-controller;
#interrupt-cells = <3>;
compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
reg = <0x500 0x80>;
};
timer@600 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x600 0x10>;
interrupts = <1 9 0>;
fsl,has-wdt;
};
timer@610 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x610 0x10>;
interrupts = <1 10 0>;
};
timer@620 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x620 0x10>;
interrupts = <1 11 0>;
};
timer@630 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x630 0x10>;
interrupts = <1 12 0>;
};
timer@640 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x640 0x10>;
interrupts = <1 13 0>;
};
timer@650 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x650 0x10>;
interrupts = <1 14 0>;
};
timer@660 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x660 0x10>;
interrupts = <1 15 0>;
};
timer@670 { // General Purpose Timer
compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
reg = <0x670 0x10>;
interrupts = <1 16 0>;
};
rtc@800 { // Real time clock
compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
reg = <0x800 0x100>;
interrupts = <1 5 0 1 6 0>;
};
can@900 {
compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
interrupts = <2 17 0>;
reg = <0x900 0x80>;
};
can@980 {
compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
interrupts = <2 18 0>;
reg = <0x980 0x80>;
};
gpio_simple: gpio@b00 {
compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
reg = <0xb00 0x40>;
interrupts = <1 7 0>;
gpio-controller;
#gpio-cells = <2>;
};
gpio_wkup: gpio@c00 {
compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
reg = <0xc00 0x40>;
interrupts = <1 8 0 0 3 0>;
gpio-controller;
#gpio-cells = <2>;
};
spi@f00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
reg = <0xf00 0x20>;
interrupts = <2 13 0 2 14 0>;
interrupt-parent = <&mpc5200_pic>;
switch0: ethernet-switch@0 {
compatible = "micrel,spi-ks8995-dsa";
spi-max-frequency = <1000000>;
reg = <0>;
};
};
usb@1000 {
compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
reg = <0x1000 0xff>;
interrupts = <2 6 0>;
};
dma-controller@1200 {
compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
reg = <0x1200 0x80>;
interrupts = <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>;
};
xlb@1f00 {
compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
reg = <0x1f00 0x100>;
};
serial@2000 { // PSC1
compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
cell-index = <0>;
reg = <0x2000 0x100>;
interrupts = <2 1 0>;
};
// PSC2 in ac97 mode example
ac97@2200 { // PSC2
compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
cell-index = <1>;
reg = <0x2200 0x100>;
interrupts = <2 2 0>;
};
// PSC3 in CODEC mode example
i2s@2400 { // PSC3
compatible = "fsl,mpc5200b-psc-i2s"; //not 5200 compatible
cell-index = <2>;
reg = <0x2400 0x100>;
interrupts = <2 3 0>;
};
ethernet0: ethernet@3000 {
compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
reg = <0x3000 0x400>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <2 5 0>;
phy-handle = <&phy0>;
};
mdio0: mdio@3000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
reg = <0x3000 0x400>; // fec range, since we need to setup fec
interrupts
interrupts = <2 5 0>; // these are for "mii command finished", not
link changes & co.
phy0: ethernet-phy@1 {
reg = <1>;
};
};
ata@3a00 {
compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
reg = <0x3a00 0x100>;
interrupts = <2 7 0>;
};
i2c@3d00 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d00 0x40>;
interrupts = <2 15 0>;
};
i2c@3d40 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
reg = <0x3d40 0x40>;
interrupts = <2 16 0>;
};
sram@8000 {
compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
reg = <0x8000 0x4000>;
};
};
pci@f0000d00 {
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
reg = <0xf0000d00 0x100>;
interrupt-map-mask = <0xf800 0 0 7>;
interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
0xc000 0 0 2 &mpc5200_pic 1 1 3
0xc000 0 0 3 &mpc5200_pic 1 2 3
0xc000 0 0 4 &mpc5200_pic 1 3 3
0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
0xc800 0 0 2 &mpc5200_pic 1 2 3
0xc800 0 0 3 &mpc5200_pic 1 3 3
0xc800 0 0 4 &mpc5200_pic 0 0 3>;
clock-frequency = <0>; // From boot loader
interrupts = <2 8 0 2 9 0 2 10 0>;
bus-range = <0 0>;
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
};
virtual-device {
compatible = "simple-bus";
dsa {
compatible = "jkc,jkc5200n8-dsa-of";
ethernet-handle = <ðernet0>;
mdio-handle = <&mdio0>;
// TODO: incomplete, in design
};
};
localbus {
compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0xff000000 0x01000000 /* CS0: Flash */
1 0 0x10000000 0x10000000>; /* CS1: USB ISP1761 */
flash@0,0 {
compatible = "cfi-flash";
reg = <0 0 0x01000000>;
bank-width = <2>;
#size-cells = <1>;
#address-cells = <1>;
// fe000000 aliased at ff000000
partition@0 {
label = "spare";
reg = <0x00000000 0x00f00000>;
};
partition@f00000 {
label = "u-boot";
reg = <0x00f00000 0x00040000>;
};
partition@f40000 {
label = "u-boot-env";
reg = <0x00f40000 0x00020000>;
};
partition@f60000 {
label = "spare2";
reg = <0x00f60000 0x000a0000>;
};
};
isp1761@1,0 {
compatible = "nxp,usb-isp1761";
reg = <1 0 0x10000000>;
bus-width = <16>;
big-endian;
interrupts = <1 1 3>; /* HC INT */
};
};
};
^ permalink raw reply
* Re: [PATCH 5/5] of/irq: merge of_irq_map_one()
From: Grant Likely @ 2010-06-17 23:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Stephen Rothwell, Michal Simek, microblaze-uclinux,
devicetree-discuss, linuxppc-dev
In-Reply-To: <1276219072.1962.82.camel@pasglop>
On Thu, Jun 10, 2010 at 7:17 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Thu, 2010-06-10 at 17:36 -0600, Grant Likely wrote:
>>
>> Okay. =A0I had been trying to avoid #ifdefs in the common code, but
>> you're probably right. =A0I'll rework.
>
> Not even ifdef's ... just move the quirk map there. You can always
> #define the quirk variable to 0 on archs that have no quirks, to
> make it compile away if you believe it represents bloat, but they
> are simple well localized things so I doubt it matters.
They're pretty small, but powermac32 is the only code that actually
uses the quirk facility. Everything else parses sanely it would
appear. I'd rather have them localized to the powermac code and
eliminate the quirks from the common code.
If other platforms show up with bad irq mappings, then I want to take
the approach of fixing the data rather than adding more quirks cases.
Anyway, let me try my hand at reworking to be a lot clearer and see
what it looks like.
g.
^ permalink raw reply
* Re: [PATCH 5/5] of/irq: merge of_irq_map_one()
From: Benjamin Herrenschmidt @ 2010-06-17 23:57 UTC (permalink / raw)
To: Grant Likely
Cc: Stephen Rothwell, Michal Simek, microblaze-uclinux,
devicetree-discuss, linuxppc-dev
In-Reply-To: <AANLkTin5K0IL5iKj9i9qBucSpQz2-p5wIvUtC4iU0jUP@mail.gmail.com>
On Thu, 2010-06-17 at 17:11 -0600, Grant Likely wrote:
> On Thu, Jun 10, 2010 at 7:17 PM, Benjamin Herrenschmidt
> <benh@kernel.crashing.org> wrote:
> > On Thu, 2010-06-10 at 17:36 -0600, Grant Likely wrote:
> >>
> >> Okay. I had been trying to avoid #ifdefs in the common code, but
> >> you're probably right. I'll rework.
> >
> > Not even ifdef's ... just move the quirk map there. You can always
> > #define the quirk variable to 0 on archs that have no quirks, to
> > make it compile away if you believe it represents bloat, but they
> > are simple well localized things so I doubt it matters.
>
> They're pretty small, but powermac32 is the only code that actually
> uses the quirk facility. Everything else parses sanely it would
> appear. I'd rather have them localized to the powermac code and
> eliminate the quirks from the common code.
Maybe, but the way you end up gutting out some internal functions of the
parser so they can be overriden by the arch is just plain gross :-) And
more bloat than just having a localized quirk test which can easily
compile to nothing when powermac isn't built.
IE. I'd rather you then add some kind of of_irq_map_fixup() or something
like that in the generic code that can be an empty inline when powermac
isn't there, and be defined by powerpc to do the right thing then,
rather than move the core of the function to a separate weak version.
Because the day you fix a bug in the weak variant, or change a calling
convention, you'll forget to also update the "overrides" in the arch.
> If other platforms show up with bad irq mappings, then I want to take
> the approach of fixing the data rather than adding more quirks cases.
>
> Anyway, let me try my hand at reworking to be a lot clearer and see
> what it looks like.
Ben.
^ permalink raw reply
* [PATCH] powerpc: Linux cannot run with 0 cores
From: Anton Blanchard @ 2010-06-18 0:33 UTC (permalink / raw)
To: benh, paulmck; +Cc: linuxppc-dev
If we configure with CONFIG_SMP=n or set NR_CPUS less than the number of
SMT threads we will set the max cores property to 0 in the
ibm,client-architecture-support structure. On new versions of firmware that
understand this property it obliges and terminates our partition.
Use DIV_ROUND_UP so we handle not only the CONFIG_SMP=n case but also the
case where NR_CPUS isn't a multiple of the number of SMT threads.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-2.6/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/prom_init.c 2010-06-17 09:08:20.000000000 +1000
+++ linux-2.6/arch/powerpc/kernel/prom_init.c 2010-06-17 09:10:02.000000000 +1000
@@ -872,7 +872,7 @@ static void __init prom_send_capabilitie
"ibm_architecture_vec structure inconsistent: 0x%x !\n",
*cores);
} else {
- *cores = NR_CPUS / prom_count_smt_threads();
+ *cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
prom_printf("Max number of cores passed to firmware: 0x%x\n",
(unsigned long)*cores);
}
^ permalink raw reply
* Re: [PATCH 5/5] of/irq: merge of_irq_map_one()
From: Grant Likely @ 2010-06-18 0:39 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Stephen Rothwell, Michal Simek, microblaze-uclinux,
devicetree-discuss, linuxppc-dev
In-Reply-To: <1276819045.8826.45.camel@pasglop>
On Thu, Jun 17, 2010 at 5:57 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Thu, 2010-06-17 at 17:11 -0600, Grant Likely wrote:
>> On Thu, Jun 10, 2010 at 7:17 PM, Benjamin Herrenschmidt
>> <benh@kernel.crashing.org> wrote:
>> > On Thu, 2010-06-10 at 17:36 -0600, Grant Likely wrote:
>> >>
>> >> Okay. =A0I had been trying to avoid #ifdefs in the common code, but
>> >> you're probably right. =A0I'll rework.
>> >
>> > Not even ifdef's ... just move the quirk map there. You can always
>> > #define the quirk variable to 0 on archs that have no quirks, to
>> > make it compile away if you believe it represents bloat, but they
>> > are simple well localized things so I doubt it matters.
>>
>> They're pretty small, but powermac32 is the only code that actually
>> uses the quirk facility. =A0Everything else parses sanely it would
>> appear. =A0I'd rather have them localized to the powermac code and
>> eliminate the quirks from the common code.
>
> Maybe, but the way you end up gutting out some internal functions of the
> parser so they can be overriden by the arch is just plain gross :-)
Heh, I won't dispute that. Give me a day or so. If I can't come up
with anything better, then I'll just move it all over.
g.
^ permalink raw reply
* Re: [PATCH]460EX on-chip SATA driver<kernel 2.6.33><resubmission>
From: Jassi Brar @ 2010-06-18 4:34 UTC (permalink / raw)
To: Rupjyoti Sarmah; +Cc: linux-ide, sr, jgarzik, linux-kernel, linuxppc-dev
In-Reply-To: <201006041226.o54CQH2V017366@amcc.com>
On Fri, Jun 4, 2010 at 9:26 PM, Rupjyoti Sarmah <rsarmah@amcc.com> wrote:
> This patch enables the on-chip DWC SATA controller of the AppliedMicro processor 460EX.
Doesn't this DWC sata IP provide AHCI ? Just curious.
^ permalink raw reply
* [PATCH 1/3] fsl_rio: fix compile errors
From: Li Yang @ 2010-06-18 5:29 UTC (permalink / raw)
To: galak, linuxppc-dev
Fixes the following compile problem on E500 platforms:
arch/powerpc/sysdev/fsl_rio.c: In function 'fsl_rio_mcheck_exception':
arch/powerpc/sysdev/fsl_rio.c:248: error: 'MCSR_MASK' undeclared (first use in this function)
Also fixes the compile problem on non-E500 platforms.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 30e1626..f908ba6 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -240,12 +240,13 @@ struct rio_priv {
static void __iomem *rio_regs_win;
+#ifdef CONFIG_E500
static int (*saved_mcheck_exception)(struct pt_regs *regs);
static int fsl_rio_mcheck_exception(struct pt_regs *regs)
{
const struct exception_table_entry *entry = NULL;
- unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK);
+ unsigned long reason = mfspr(SPRN_MCSR);
if (reason & MCSR_BUS_RBERR) {
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
@@ -269,6 +270,7 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
else
return cur_cpu_spec->machine_check(regs);
}
+#endif
/**
* fsl_rio_doorbell_send - Send a MPC85xx doorbell message
@@ -1517,8 +1519,10 @@ int fsl_rio_setup(struct of_device *dev)
fsl_rio_doorbell_init(port);
fsl_rio_port_write_init(port);
+#ifdef CONFIG_E500
saved_mcheck_exception = ppc_md.machine_check_exception;
ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
+#endif
/* Ensure that RFXE is set */
mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
--
1.6.4
^ permalink raw reply related
* [PATCH 2/3] fsl_rio: fix machine check exception for e500mc
From: Li Yang @ 2010-06-18 5:29 UTC (permalink / raw)
To: galak, linuxppc-dev
In-Reply-To: <1276838958-28947-1-git-send-email-leoli@freescale.com>
The original code only covers e500 v1/v2.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index f908ba6..954a754 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -248,7 +248,8 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
const struct exception_table_entry *entry = NULL;
unsigned long reason = mfspr(SPRN_MCSR);
- if (reason & MCSR_BUS_RBERR) {
+ /* covers both e500v1/v2 and e500mc */
+ if (reason & (MCSR_BUS_RBERR | MCSR_LD)) {
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
/* Check if we are prepared to handle this fault */
--
1.6.4
^ permalink raw reply related
* [PATCH 3/3] fsl_rio: fix non-standard HID1 register access
From: Li Yang @ 2010-06-18 5:29 UTC (permalink / raw)
To: galak, linuxppc-dev
In-Reply-To: <1276838958-28947-2-git-send-email-leoli@freescale.com>
The access to HID1 register is only legitimate for e500 v1/v2 cores.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 954a754..785a882 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1523,9 +1523,12 @@ int fsl_rio_setup(struct of_device *dev)
#ifdef CONFIG_E500
saved_mcheck_exception = ppc_md.machine_check_exception;
ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
-#endif
- /* Ensure that RFXE is set */
+
+#ifndef CONFIG_E500MC
+ /* Ensure that RFXE is set on e500 v1/v2 */
mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
+#endif /* !E500MC */
+#endif /* E500 */
return 0;
err:
--
1.6.4
^ permalink raw reply related
* Re: [PATCH 3/3] fsl_rio: fix non-standard HID1 register access
From: Geert Uytterhoeven @ 2010-06-18 5:46 UTC (permalink / raw)
To: Li Yang; +Cc: linuxppc-dev
In-Reply-To: <1276838958-28947-3-git-send-email-leoli@freescale.com>
On Fri, Jun 18, 2010 at 07:29, Li Yang <leoli@freescale.com> wrote:
> The access to HID1 register is only legitimate for e500 v1/v2 cores.
>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> =C2=A0arch/powerpc/sysdev/fsl_rio.c | =C2=A0 =C2=A07 +++++--
> =C2=A01 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.=
c
> index 954a754..785a882 100644
> --- a/arch/powerpc/sysdev/fsl_rio.c
> +++ b/arch/powerpc/sysdev/fsl_rio.c
> @@ -1523,9 +1523,12 @@ int fsl_rio_setup(struct of_device *dev)
> =C2=A0#ifdef CONFIG_E500
> =C2=A0 =C2=A0 =C2=A0 =C2=A0saved_mcheck_exception =3D ppc_md.machine_chec=
k_exception;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0ppc_md.machine_check_exception =3D fsl_rio_mch=
eck_exception;
> -#endif
> - =C2=A0 =C2=A0 =C2=A0 /* Ensure that RFXE is set */
> +
> +#ifndef CONFIG_E500MC
> + =C2=A0 =C2=A0 =C2=A0 /* Ensure that RFXE is set on e500 v1/v2 */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000))=
;
> +#endif /* !E500MC */
> +#endif /* E500 */
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> =C2=A0err:
This prevents you from building a kernel for both normal E500 and E500MC.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 3/3] fsl_rio: fix non-standard HID1 register access
From: Kumar Gala @ 2010-06-18 5:51 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linuxppc-dev
In-Reply-To: <AANLkTind1zMrnldhZmeacglmVyfX8VN2qO_JJlkPAe0v@mail.gmail.com>
On Jun 18, 2010, at 12:46 AM, Geert Uytterhoeven wrote:
> On Fri, Jun 18, 2010 at 07:29, Li Yang <leoli@freescale.com> wrote:
>> The access to HID1 register is only legitimate for e500 v1/v2 cores.
>>
>> Signed-off-by: Li Yang <leoli@freescale.com>
>> ---
>> arch/powerpc/sysdev/fsl_rio.c | 7 +++++--
>> 1 files changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
>> index 954a754..785a882 100644
>> --- a/arch/powerpc/sysdev/fsl_rio.c
>> +++ b/arch/powerpc/sysdev/fsl_rio.c
>> @@ -1523,9 +1523,12 @@ int fsl_rio_setup(struct of_device *dev)
>> #ifdef CONFIG_E500
>> saved_mcheck_exception = ppc_md.machine_check_exception;
>> ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
>> -#endif
>> - /* Ensure that RFXE is set */
>> +
>> +#ifndef CONFIG_E500MC
>> + /* Ensure that RFXE is set on e500 v1/v2 */
>> mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
>> +#endif /* !E500MC */
>> +#endif /* E500 */
>>
>> return 0;
>> err:
>
> This prevents you from building a kernel for both normal E500 and E500MC.
>
> Gr{oetje,eeting}s,
Also, not a fan of the magic number 0x20000.
- k
^ permalink raw reply
* [PATCH v2 1/4] fsl_rio: fix compile errors
From: Li Yang @ 2010-06-18 6:24 UTC (permalink / raw)
To: galak, linuxppc-dev
Fixes the following compile problem on E500 platforms:
arch/powerpc/sysdev/fsl_rio.c: In function 'fsl_rio_mcheck_exception':
arch/powerpc/sysdev/fsl_rio.c:248: error: 'MCSR_MASK' undeclared (first use in this function)
Also fixes the compile problem on non-E500 platforms.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 30e1626..f908ba6 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -240,12 +240,13 @@ struct rio_priv {
static void __iomem *rio_regs_win;
+#ifdef CONFIG_E500
static int (*saved_mcheck_exception)(struct pt_regs *regs);
static int fsl_rio_mcheck_exception(struct pt_regs *regs)
{
const struct exception_table_entry *entry = NULL;
- unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK);
+ unsigned long reason = mfspr(SPRN_MCSR);
if (reason & MCSR_BUS_RBERR) {
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
@@ -269,6 +270,7 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
else
return cur_cpu_spec->machine_check(regs);
}
+#endif
/**
* fsl_rio_doorbell_send - Send a MPC85xx doorbell message
@@ -1517,8 +1519,10 @@ int fsl_rio_setup(struct of_device *dev)
fsl_rio_doorbell_init(port);
fsl_rio_port_write_init(port);
+#ifdef CONFIG_E500
saved_mcheck_exception = ppc_md.machine_check_exception;
ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
+#endif
/* Ensure that RFXE is set */
mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
--
1.6.4
^ permalink raw reply related
* [PATCH v2 2/4] fsl_rio: fix machine check exception for e500mc
From: Li Yang @ 2010-06-18 6:24 UTC (permalink / raw)
To: galak, linuxppc-dev
In-Reply-To: <1276842263-4186-1-git-send-email-leoli@freescale.com>
The original code only covers e500 v1/v2.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index f908ba6..954a754 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -248,7 +248,8 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
const struct exception_table_entry *entry = NULL;
unsigned long reason = mfspr(SPRN_MCSR);
- if (reason & MCSR_BUS_RBERR) {
+ /* covers both e500v1/v2 and e500mc */
+ if (reason & (MCSR_BUS_RBERR | MCSR_LD)) {
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
/* Check if we are prepared to handle this fault */
--
1.6.4
^ permalink raw reply related
* [PATCH v2 4/4] fsl_rio: fix non-standard HID1 register access
From: Li Yang @ 2010-06-18 6:24 UTC (permalink / raw)
To: galak, linuxppc-dev
In-Reply-To: <1276842263-4186-3-git-send-email-leoli@freescale.com>
The access to HID1 register is only legitimate for e500 v1/v2 cores.
Also fixes magic number.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/sysdev/fsl_rio.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 954a754..aa9a21d 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1523,9 +1523,12 @@ int fsl_rio_setup(struct of_device *dev)
#ifdef CONFIG_E500
saved_mcheck_exception = ppc_md.machine_check_exception;
ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
-#endif
- /* Ensure that RFXE is set */
- mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
+
+#ifndef CONFIG_PPC_E500MC
+ /* Ensure that RFXE is set on e500 v1/v2 */
+ mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | HID1_RFXE));
+#endif /* !PPC_E500MC */
+#endif /* E500 */
return 0;
err:
--
1.6.4
^ permalink raw reply related
* [PATCH v2 3/4] powerpc: add e500 HID1 bit definition
From: Li Yang @ 2010-06-18 6:24 UTC (permalink / raw)
To: galak, linuxppc-dev
In-Reply-To: <1276842263-4186-2-git-send-email-leoli@freescale.com>
Also make 74xx HID1 definition conditional.
Signed-off-by: Li Yang <leoli@freescale.com>
---
arch/powerpc/include/asm/reg.h | 2 ++
arch/powerpc/include/asm/reg_booke.h | 16 ++++++++++++++++
2 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index d62fdf4..235d356 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -283,6 +283,7 @@
#define HID0_NOPTI (1<<0) /* No-op dcbt and dcbst instr. */
#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#ifdef CONFIG_6xx
#define HID1_EMCP (1<<31) /* 7450 Machine Check Pin Enable */
#define HID1_DFS (1<<22) /* 7447A Dynamic Frequency Scaling */
#define HID1_PC0 (1<<16) /* 7450 PLL_CFG[0] */
@@ -292,6 +293,7 @@
#define HID1_SYNCBE (1<<11) /* 7450 ABE for sync, eieio */
#define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */
#define HID1_PS (1<<16) /* 750FX PLL selection */
+#endif
#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
#define SPRN_HID2_GEKKO 0x398 /* Gekko HID2 Register */
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 2360317..6d393f7 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -245,6 +245,22 @@
store or cache line push */
#endif
+/* Bit definitions for the HID1 */
+#ifdef CONFIG_E500
+#ifndef CONFIG_PPC_E500MC
+/* e500v1/v2 */
+#define HID1_PLL_CFG_MASK 0xfc000000UL /* PLL_CFG input pins */
+#define HID1_RFXE 0x00020000UL /* Read fault exception enable */
+#define HID1_R1DPE 0x00008000UL /* R1 data bus parity enable */
+#define HID1_R2DPE 0x00004000UL /* R2 data bus parity enable */
+#define HID1_ASTME 0x00002000UL /* Address bus streaming mode enable */
+#define HID1_ABE 0x00001000UL /* Address broadcast enable */
+#define HID1_MPXTT 0x00000400UL /* MPX re-map transfer type */
+#define HID1_ATS 0x00000080UL /* Atomic status */
+#define HID1_MID_MASK 0x0000000fUL /* MID input pins */
+#endif
+#endif
+
/* Bit definitions for the DBSR. */
/*
* DBSR bits which have conflicting definitions on true Book E versus IBM 40x.
--
1.6.4
^ permalink raw reply related
* Re: [PATCH 1/2] mtd: m25p80: Rework probing/JEDEC code
From: Anton Vorontsov @ 2010-06-18 13:32 UTC (permalink / raw)
To: Barry Song
Cc: David Brownell, Artem Bityutskiy, linux-kernel, linuxppc-dev,
linux-mtd, uclinux-dist-devel, Andrew Morton, David Woodhouse
In-Reply-To: <AANLkTikg60s6ZRSEDCq9PQK1z7hJtBDk6t4VE1lYDv8u@mail.gmail.com>
On Sat, Jun 12, 2010 at 02:27:12PM +0800, Barry Song wrote:
> On Wed, Aug 19, 2009 at 5:46 AM, Anton Vorontsov
> <avorontsov@ru.mvista.com> wrote:
> >
> > Previosly the driver always tried JEDEC probing, assuming that non-JEDEC
> > chips will return '0'. But truly non-JEDEC chips (like CAT25) won't do
> > that, their behaviour on RDID command is undefined, so the driver should
> > not call jedec_probe() for these chips.
> >
> > Also, be less strict on error conditions, don't fail to probe if JEDEC
> > found a chip that is different from what platform code told, instead
> > just print some warnings and use an information obtained via JEDEC. In
> This patch caused a problem:
> even though the external flash doesn't exist, it will still pass the
> probe() and be registerred into kernel and given the partition table.
> You may refer to this bug report:
> http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=5975&start=0
Thanks for the report.
There's little we can do about it. Platform code asked us
to register the device, and JEDEC probing of M25Pxx chips isn't
reliable (thanks to various vendors that make these JEDEC and
non-JEDEC variants), so the best thing we can do is to register
the chip anyway.
OTOH, if the board pulls MISO line up, then the following patch
should help.
If this won't work, we'll have to add some flag to the platform
data, i.e. to force JEDEC probing, and not trust platform data.
Not-yet-Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
---
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 81e49a9..a307929 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -16,6 +16,7 @@
*/
#include <linux/init.h>
+#include <linux/errno.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -723,7 +724,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
dev_name(&spi->dev), tmp);
- return NULL;
+ return ERR_PTR(tmp);
}
jedec = id[0];
jedec = jedec << 8;
@@ -737,7 +738,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
* exist for non-JEDEC chips, but for compatibility they return ID 0.
*/
if (jedec == 0)
- return NULL;
+ return ERR_PTR(-EEXIST);
ext_jedec = id[3] << 8 | id[4];
@@ -749,7 +750,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
return &m25p_ids[tmp];
}
}
- return NULL;
+ return ERR_PTR(-ENODEV);
}
@@ -794,9 +795,11 @@ static int __devinit m25p_probe(struct spi_device *spi)
const struct spi_device_id *jid;
jid = jedec_probe(spi);
- if (!jid) {
+ if (IS_ERR(jid) && PTR_ERR(jid) == -EEXIST) {
dev_info(&spi->dev, "non-JEDEC variant of %s\n",
id->name);
+ } else if (IS_ERR(jid)) {
+ return PTR_ERR(jid);
} else if (jid != id) {
/*
* JEDEC knows better, so overwrite platform ID. We
^ permalink raw reply related
* [PATCH] serial: Add missing call to init UCC UART port timeout
From: Chuck Meade @ 2010-06-18 13:22 UTC (permalink / raw)
To: linuxppc-dev, Chuck Meade (PTR Group)
From: Chuck Meade <chuck@ThePTRGroup.com>
The UCC UART driver is missing a call to uart_update_timeout().
Without this call, attempting to close the port after outputting large
amounts of data (i.e. using tty and uart buffering) results in long
timeouts before the port will actually be shut down.
For example, cat a large file to a UCC UART port. With the current
driver, the port will stay open for 30 seconds after the last byte
of data is output. But with this patch, the port is closed as
expected, just after the data has been output (tx fifos empty).
Signed-off-by: Chuck Meade <chuck@ThePTRGroup.com>
---
drivers/serial/ucc_uart.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 907b06f..a136030 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -961,6 +961,9 @@ static void qe_uart_set_termios(struct uart_port *port,
/* Do we really need a spinlock here? */
spin_lock_irqsave(&port->lock, flags);
+ /* Update the per-port timeout. */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
out_be16(&uccp->upsmr, upsmr);
if (soft_uart) {
out_be16(&uccup->supsmr, supsmr);
--
1.5.6.3
^ permalink raw reply related
* Re: [lm-sensors] [PATCH] hwmon: (tmp421) Add nfactor support (2nd attempt)
From: Andre Prendel @ 2010-06-18 14:53 UTC (permalink / raw)
To: Jean Delvare; +Cc: linuxppc-dev, lm-sensors
In-Reply-To: <20100520193556.GB2153@andre-laptop>
On Thu, May 20, 2010 at 09:35:56PM +0200, Andre Prendel wrote:
> On Thu, May 20, 2010 at 03:07:05PM -0400, Jeff Angielski wrote:
> > On 05/20/2010 02:50 PM, Andre Prendel wrote:
> > > You made a careless mistake, see below. Please fix this and resend the patch
> > > again. Then I added my Acked-by and I think Jean will schedule the patch for
> > > 2.6.35 (after another review of course :))
> >
> > You sir, would be correct... *sigh* I tried using the scripts/Lindent on it to
> > be sure there were no coding style issues but that messed up even your original
> > code.
>
> /scripts/checkpatch.pl is the key ;)
>
> > In any event, here it is again:
>
> Acked-by: Andre Prendel <andre.prendel@gmx.de>
Hi Jean,
Any News on this patch?
> >
> > >From 9acd29ff48c64e58a7f5cdb888c86e737c56281c Mon Sep 17 00:00:00 2001
> > From: Jeff Angielski <jeff@theptrgroup.com>
> > Date: Mon, 10 May 2010 10:26:34 -0400
> > Subject: [PATCH] hwmon: (tmp421) Add nfactor support
> >
> > Add support for reading and writing the n-factor correction
> > registers. This is needed to compensate for the characteristics
> > of a particular sensor hanging off of the remote channels.
> >
> > Signed-off-by: Jeff Angielski <jeff@theptrgroup.com>
> > ---
> > Documentation/hwmon/tmp421 | 19 +++++++++++++++++++
> > drivers/hwmon/tmp421.c | 41 +++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 60 insertions(+), 0 deletions(-)
> >
> > diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
> > index 0cf07f8..668228a 100644
> > --- a/Documentation/hwmon/tmp421
> > +++ b/Documentation/hwmon/tmp421
> > @@ -17,6 +17,7 @@ Supported chips:
> >
> > Authors:
> > Andre Prendel <andre.prendel@gmx.de>
> > + Jeff Angielski <jeff@theptrgroup.com>
> >
> > Description
> > -----------
> > @@ -34,3 +35,21 @@ the temperature values via the following sysfs files:
> >
> > temp[1-4]_input
> > temp[2-4]_fault
> > +
> > +The chips allow the user to adjust the n-factor value that is used
> > +when converting the remote channel measurements to temperature. The
> > +adjustment has a range of -128 to +127 that yields an effective
> > +n-factor range of 0.706542 to 1.747977. The power on reset value
> > +for the adjustment is 0 which results in an n-factor of 1.008.
> > +
> > +The effective n-factor is calculated according to the following
> > +equation:
> > +
> > +n_factor = (1.008 * 300) / (300 - nfactor_adjust)
> > +
> > +The driver exports the n-factor adjustment value via the following
> > +sysfs files:
> > +
> > +temp[2-4]_n_adjust
> > +
> > +
> > diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
> > index 738c472..dfd62be 100644
> > --- a/drivers/hwmon/tmp421.c
> > +++ b/drivers/hwmon/tmp421.c
> > @@ -49,6 +49,7 @@ enum chips { tmp421, tmp422, tmp423 };
> >
> > static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 };
> > static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
> > +static const u8 TMP421_N_CORRECT[3] = { 0x21, 0x22, 0x23 };
> >
> > /* Flags */
> > #define TMP421_CONFIG_SHUTDOWN 0x40
> > @@ -76,6 +77,7 @@ struct tmp421_data {
> > int channels;
> > u8 config;
> > s16 temp[4];
> > + s8 n_adjust[3];
> > };
> >
> > static int temp_from_s16(s16 reg)
> > @@ -115,6 +117,10 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
> > data->temp[i] |= i2c_smbus_read_byte_data(client,
> > TMP421_TEMP_LSB[i]);
> > }
> > + for (i = 1; i < data->channels; i++) {
> > + data->n_adjust[i - 1] = i2c_smbus_read_byte_data(client,
> > + TMP421_N_CORRECT[i - 1]);
> > + }
> > data->last_updated = jiffies;
> > data->valid = 1;
> > }
> > @@ -157,6 +163,32 @@ static ssize_t show_fault(struct device *dev,
> > return sprintf(buf, "0\n");
> > }
> >
> > +static ssize_t show_n_adjust(struct device *dev,
> > + struct device_attribute *devattr, char *buf)
> > +{
> > + int index = to_sensor_dev_attr(devattr)->index;
> > + struct tmp421_data *data = tmp421_update_device(dev);
> > +
> > + return sprintf(buf, "%d\n", data->n_adjust[index - 1]);
> > +}
> > +
> > +static ssize_t set_n_adjust(struct device *dev,
> > + struct device_attribute *devattr,
> > + const char *buf, size_t count)
> > +{
> > + struct i2c_client *client = to_i2c_client(dev);
> > + struct tmp421_data *data = i2c_get_clientdata(client);
> > + int index = to_sensor_dev_attr(devattr)->index;
> > + int n_adjust = simple_strtol(buf, NULL, 10);
> > +
> > + mutex_lock(&data->update_lock);
> > + i2c_smbus_write_byte_data(client, TMP421_N_CORRECT[index - 1],
> > + SENSORS_LIMIT(n_adjust, -128, 127));
> > + mutex_unlock(&data->update_lock);
> > +
> > + return count;
> > +}
> > +
> > static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> > int n)
> > {
> > @@ -177,19 +209,28 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> > static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
> > static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
> > static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
> > +static SENSOR_DEVICE_ATTR(temp2_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > + show_n_adjust, set_n_adjust, 1);
> > static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
> > static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
> > +static SENSOR_DEVICE_ATTR(temp3_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > + show_n_adjust, set_n_adjust, 2);
> > static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
> > static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
> > +static SENSOR_DEVICE_ATTR(temp4_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > + show_n_adjust, set_n_adjust, 3);
> >
> > static struct attribute *tmp421_attr[] = {
> > &sensor_dev_attr_temp1_input.dev_attr.attr,
> > &sensor_dev_attr_temp2_input.dev_attr.attr,
> > &sensor_dev_attr_temp2_fault.dev_attr.attr,
> > + &sensor_dev_attr_temp2_n_adjust.dev_attr.attr,
> > &sensor_dev_attr_temp3_input.dev_attr.attr,
> > &sensor_dev_attr_temp3_fault.dev_attr.attr,
> > + &sensor_dev_attr_temp3_n_adjust.dev_attr.attr,
> > &sensor_dev_attr_temp4_input.dev_attr.attr,
> > &sensor_dev_attr_temp4_fault.dev_attr.attr,
> > + &sensor_dev_attr_temp4_n_adjust.dev_attr.attr,
> > NULL
> > };
> >
> > --
> > 1.7.0.4
> >
> >
> > --
> > Jeff Angielski
> > The PTR Group
> > www.theptrgroup.com
> >
> > _______________________________________________
> > lm-sensors mailing list
> > lm-sensors@lm-sensors.org
> > http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
>
> _______________________________________________
> lm-sensors mailing list
> lm-sensors@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox