* Re: [PATCH v5] qe: add ability to upload QE firmware
From: Arnd Bergmann @ 2007-12-12 22:05 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Timur Tabi
In-Reply-To: <11970422334145-git-send-email-timur@freescale.com>
On Friday 07 December 2007, Timur Tabi wrote:
> Define the layout of a binary blob that contains a QE firmware and instru=
ctions
> on how to upload it. =A0Add function qe_upload_firmware() to parse the bl=
ob
> and perform the actual upload. =A0Fully define 'struct rsp' in immap_qe.h=
to
> include the actual RISC Special Registers. =A0Added description of a new
> QE firmware node to booting-without-of.txt.
All the comments I had were addressed, mostly by convincing me that the
code was correct to start with, so
> Signed-off-by: Timur Tabi <timur@freescale.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: Patches added to for-2.6.25 and master branches of powerpc.git
From: Geoff Levand @ 2007-12-12 21:10 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18270.8249.393061.840667@cargo.ozlabs.ibm.com>
Hi Paul,
This one seems to have got skipped:
http://ozlabs.org/pipermail/linuxppc-dev/2007-November/046765.html
-Geoff
^ permalink raw reply
* Re: [PATCH RFC 0/7] "NAND on UPM" and related patches
From: Scott Wood @ 2007-12-12 21:13 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <47604D6E.1050200@freescale.com>
Scott Wood wrote:
> Anton Vorontsov wrote:
>> As the compromise I might suggest this: forbid pattern_start/pattern_end
>> from the ISRs (by marking them as might_sleep()), and replace _irqsave
>> spinlock with simple spinlock.
>
> No, you cannot use a bare spinlock with IRQs enabled. You'll deadlock
> on SMP, and you'll have races with preemption enabled.
Sorry, brain fart... obviously, with preemption on it'd disable
preemption even with a plain spinlock, and on SMP without preemption
it's not an issue.
Still, all you're getting rid of is the MSR twiddling, which should be
pretty minor.
-Scott
^ permalink raw reply
* Re: [PATCH RFC 0/7] "NAND on UPM" and related patches
From: Scott Wood @ 2007-12-12 21:06 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20071212205838.GA16425@localhost.localdomain>
Anton Vorontsov wrote:
> As the compromise I might suggest this: forbid pattern_start/pattern_end
> from the ISRs (by marking them as might_sleep()), and replace _irqsave
> spinlock with simple spinlock.
No, you cannot use a bare spinlock with IRQs enabled. You'll deadlock
on SMP, and you'll have races with preemption enabled.
> Given that, personally I'd want to lockless variant to stay.
>
> So, you still want to get rid of it?
Yes, in the absence of benchmarking that shows it makes a real
difference. Premature optimization being the root of all evil, and what
not.
-Scott
^ permalink raw reply
* Re: [PATCH RFC 0/7] "NAND on UPM" and related patches
From: Anton Vorontsov @ 2007-12-12 20:58 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <47601245.2090907@freescale.com>
On Wed, Dec 12, 2007 at 10:54:29AM -0600, Scott Wood wrote:
> Anton Vorontsov wrote:
> >On Wed, Dec 12, 2007 at 10:40:35AM -0600, Scott Wood wrote:
> >>Not enough to be worth the complexity compared to the overhead of NAND
> >>access -- especially in the likely case of a non-SMP build.
> >
> >I'm allowing UPM access from the IRQ handlers (because nothing prevents
> >this, so why deny?). Thus locks are needed even on non-SMP build,
>
> No, it just needs to disable interrupts.
> Which is what locks do on non-SMP.
> The overhead of this is not worth 30 lines of code to avoid.
Well, speaking of overhead. There could be a lot of fsl_upm_run_pattern
calls between _start and _end. In NAND case it's maximum 3, plus
they're indirect (i.e. NAND layer calls them via pointers to cmdfunc,
and cmdfunc calls run_patterns). Each out_X is another sync, and all
that time we're holding a lock with local IRQs disabled.
fsl upm infrastructure isn't only for NAND though, so I might imagine
use cases when there might be more run_patterns between start and end.
As the compromise I might suggest this: forbid pattern_start/pattern_end
from the ISRs (by marking them as might_sleep()), and replace _irqsave
spinlock with simple spinlock.
That way on UP we don't lose anything, but on SMP we still have an
overhead in case of single used UPM. :-/
Given that, personally I'd want to lockless variant to stay.
So, you still want to get rid of it?
Much thanks,
--
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH] IB/ehca: Serialize HCA-related hCalls if necessary
From: Roland Dreier @ 2007-12-12 20:29 UTC (permalink / raw)
To: Joachim Fenkes
Cc: Arnd Bergmann, LKML, OF-EWG, LinuxPPC-Dev, Christoph Raisch,
Marcus Eder, OF-General, Stefan Roscher
In-Reply-To: <200712101859.11218.fenkes@de.ibm.com>
thanks, applied.
With your next batch of patches for 2.6.25, could you clean up:
> --- a/drivers/infiniband/hw/ehca/hcp_if.c
> +++ b/drivers/infiniband/hw/ehca/hcp_if.c
> @@ -89,6 +89,7 @@
> #define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
>
> static DEFINE_SPINLOCK(hcall_lock);
> +extern int ehca_lock_hcalls;
and move that extern declaration into an appropriate header file?
Thanks...
^ permalink raw reply
* Re: [PATCH] IB/ehca: Return correct #SGEs for SRQ
From: Roland Dreier @ 2007-12-12 20:26 UTC (permalink / raw)
To: Joachim Fenkes
Cc: LKML, OF-EWG, LinuxPPC-Dev, Christoph Raisch, Marcus Eder,
OF-General, Stefan Roscher
In-Reply-To: <200712101220.57876.fenkes@de.ibm.com>
thanks, applied.
^ permalink raw reply
* Re: [ewg] Re: [PATCH] IB/ehca: Serialize HCA-related hCalls on POWER5
From: Roland Dreier @ 2007-12-12 19:09 UTC (permalink / raw)
To: Or Gerlitz
Cc: Arnd Bergmann, Joachim Fenkes, LKML, linuxppc-dev,
Christoph Raisch, OF-General, Stefan Roscher
In-Reply-To: <475FD0A1.3090304@voltaire.com>
> What is the fix you suggest, to add a device query that tells you for
> which verbs the documentation does not apply? or enhance the code of the
> map_phys_fmr verb within the ehca driver to return error if called
> from non-sleepable context?
I think the right fix for iSER would be to make iSER work even for
devices that don't support FMRs. For example cxgb3 doesn't implement
FMRs so if anyone ever updates iSER to work on iWARP and not just IB,
then this is something that has to be tackled anyway. Then ehca could
just get rid of the FMR support it has.
^ permalink raw reply
* Re: apm_emulation regression
From: Johannes Berg @ 2007-12-12 18:03 UTC (permalink / raw)
To: benh; +Cc: Rafael J. Wysocki, linuxppc-dev list, linux-pm, ralf
In-Reply-To: <1197427530.8385.59.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 1383 bytes --]
On Wed, 2007-12-12 at 13:45 +1100, Benjamin Herrenschmidt wrote:
> I only just noticed a huge regression that was introduced when we moved
> PowerPC to the generic APM emulation code instead of our own. I'm in
> large part to blame since I acked the patch...
>
> Basically, what we lost is the mechanism for notifying user applications
> and waiting for their ACK before proceeding to system suspend. The new
> generic code will still do that ... only when the actual suspend request
> initiates from an APM suspend ioctl.
Indeed.
> For any other suspend (via our private PMU ioctl or via the sysfs
> interface), userspace will -not- be notified.
Right.
> That basically means X will break. That's why X broke on the latest
> ubuntu until I whacked some new scripts in them to force console
> switching, among other things. Possibly other apps that relied
> on /dev/apm_bios to be notified of system suspend/resume broke as well.
Ah. I guess I never noticed because I had the scripts to do console
switching all along.
> Now the question is that is it still work trying to fix it ? That would
> probably require APM emulation hooking at a fairly high level into the
> generic PM code to trigger the signaling & waiting of processes before
> freeze & device suspend among others...
Yeah, bit icky... but doable. Rafael, any ideas?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* [PATCH 8/8] gianfar: Magic Packet and suspend/resume support.
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus, jgarzik; +Cc: linuxppc-dev, netdev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Jeff, can you ack this to go through Paul's tree
(assuming nothing wrong with it)?
drivers/net/gianfar.c | 137 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/gianfar.h | 13 +++-
drivers/net/gianfar_ethtool.c | 41 ++++++++++++-
3 files changed, 185 insertions(+), 6 deletions(-)
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0431e9e..2c1b8d5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -142,6 +142,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
+static void gfar_halt_nodisable(struct net_device *dev);
void gfar_halt(struct net_device *dev);
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
@@ -216,6 +217,7 @@ static int gfar_probe(struct platform_device *pdev)
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
+ spin_lock_init(&priv->bflock);
platform_set_drvdata(pdev, dev);
@@ -393,6 +395,122 @@ static int gfar_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ netif_device_detach(dev);
+
+ if (netif_running(dev)) {
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ gfar_halt_nodisable(dev);
+
+ /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+ tempval = gfar_read(&priv->regs->maccfg1);
+
+ tempval &= ~MACCFG1_TX_EN;
+
+ if (!magic_packet)
+ tempval &= ~MACCFG1_RX_EN;
+
+ gfar_write(&priv->regs->maccfg1, tempval);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_disable(&priv->napi);
+#endif
+
+ if (magic_packet) {
+ /* Enable interrupt on Magic Packet */
+ gfar_write(&priv->regs->imask, IMASK_MAG);
+
+ /* Enable Magic Packet mode */
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+ } else {
+ phy_stop(priv->phydev);
+ }
+ }
+
+ if (!magic_packet || !netif_running(dev)) {
+ /* The device with the MDIO in its register block must
+ * not be put to sleep if any other network devices
+ * using the same MDIO are active. Ideally, some sort
+ * of reference counting could be done, but for now
+ * just don't put the MDIO-containing dev to sleep
+ * at all.
+ */
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MDIO)) {
+ fsl_sleep_device(&priv->einfo->sleep);
+ priv->suspended = 1;
+ }
+ }
+
+ return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ if (priv->suspended) {
+ fsl_wake_device(&priv->einfo->sleep);
+ priv->suspended = 0;
+ }
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+ if (!magic_packet && priv->phydev)
+ phy_start(priv->phydev);
+
+ /* Disable Magic Packet mode, in case something
+ * else woke us up.
+ */
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval &= ~MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+
+ gfar_start(dev);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+ netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_enable(&priv->napi);
+#endif
+
+ return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
/* Reads the controller's registers to determine what interface
* connects it to the PHY.
@@ -547,7 +665,7 @@ static void init_registers(struct net_device *dev)
/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->regs;
@@ -570,6 +688,14 @@ void gfar_halt(struct net_device *dev)
(IEVENT_GRSC | IEVENT_GTSC)))
cpu_relax();
}
+}
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->regs;
+ u32 tempval;
/* Disable Rx and Tx */
tempval = gfar_read(®s->maccfg1);
@@ -1909,7 +2035,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
u32 events = gfar_read(&priv->regs->ievent);
/* Clear IEVENT */
- gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+ gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+ /* Magic Packet is not an error. */
+ if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ (events & IEVENT_MAG))
+ events &= ~IEVENT_MAG;
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1979,6 +2110,8 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
static struct platform_driver gfar_driver = {
.probe = gfar_probe,
.remove = gfar_remove,
+ .suspend = gfar_suspend,
+ .resume = gfar_resume,
.driver = {
.name = "fsl-gianfar",
},
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 46cd773..922ed36 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -162,6 +162,7 @@ extern const char gfar_driver_version[];
#define MACCFG2_GMII 0x00000200
#define MACCFG2_HUGEFRAME 0x00000020
#define MACCFG2_LENGTHCHECK 0x00000010
+#define MACCFG2_MPEN 0x00000008
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
@@ -234,6 +235,7 @@ extern const char gfar_driver_version[];
#define IEVENT_CRL 0x00020000
#define IEVENT_XFUN 0x00010000
#define IEVENT_RXB0 0x00008000
+#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
#define IEVENT_FIR 0x00000008
@@ -245,7 +247,8 @@ extern const char gfar_driver_version[];
#define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -263,6 +266,7 @@ extern const char gfar_driver_version[];
#define IMASK_CRL 0x00020000
#define IMASK_XFUN 0x00010000
#define IMASK_RXB0 0x00008000
+#define IMASK_MAG 0x00000800
#define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080
#define IMASK_FIR 0x00000008
@@ -726,10 +730,15 @@ struct gfar_private {
unsigned int fifo_starve;
unsigned int fifo_starve_off;
+ /* Bitfield update lock */
+ spinlock_t bflock;
+
unsigned char vlan_enable:1,
rx_csum_enable:1,
extended_hash:1,
- bd_stash_en:1;
+ bd_stash_en:1,
+ wol_en:1, /* Wake-on-LAN enabled */
+ suspended:1;
unsigned short padding;
unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147..fb7d3cc 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
int err = 0;
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
if (dev->flags & IFF_UP) {
- unsigned long flags;
-
/* Halt TX and RX, and process the frames which
* have already been received */
spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
stop_gfar(dev);
}
+ spin_lock_irqsave(&priv->bflock, flags);
priv->rx_csum_enable = data;
+ spin_unlock_irqrestore(&priv->bflock, flags);
if (dev->flags & IFF_UP)
err = startup_gfar(dev);
@@ -564,6 +565,38 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
priv->msg_enable = data;
}
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+ } else {
+ wol->supported = wol->wolopts = 0;
+ }
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ wol->wolopts != 0)
+ return -EINVAL;
+
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->bflock, flags);
+ priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+ spin_unlock_irqrestore(&priv->bflock, flags);
+
+ return 0;
+}
+#endif
const struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@ const struct ethtool_ops gfar_ethtool_ops = {
.set_tx_csum = gfar_set_tx_csum,
.get_msglevel = gfar_get_msglevel,
.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+ .get_wol = gfar_get_wol,
+ .set_wol = gfar_set_wol,
+#endif
};
--
1.5.3.7
^ permalink raw reply related
* [PATCH 5/8] mpc83xx: Power Management support
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
Basic PM support for 83xx. Standby is implemented as sleep.
Suspend-to-RAM is implemented as "deep sleep" (with the processor
turned off) on 831x.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/platforms/83xx/Kconfig | 5 +
arch/powerpc/platforms/83xx/Makefile | 1 +
arch/powerpc/platforms/83xx/suspend-asm.S | 531 +++++++++++++++++++++++++++++
arch/powerpc/platforms/83xx/suspend.c | 423 +++++++++++++++++++++++
arch/powerpc/sysdev/fsl_soc.c | 33 ++
arch/powerpc/sysdev/fsl_soc.h | 10 +
arch/powerpc/sysdev/ipic.c | 71 ++++
include/asm-powerpc/reg.h | 4 +
include/linux/fsl_devices.h | 24 ++
9 files changed, 1102 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/83xx/suspend-asm.S
create mode 100644 arch/powerpc/platforms/83xx/suspend.c
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index ec305f1..901dbaf 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -75,3 +75,8 @@ config PPC_MPC836x
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
default y if MPC836x_MDS
+
+config PPC_83xx_SUSPEND
+ bool
+ default y
+ depends on PPC_83xx && SUSPEND
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 5a98f88..944369e 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -3,6 +3,7 @@
#
obj-y := misc.o usb.o
obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/suspend-asm.S b/arch/powerpc/platforms/83xx/suspend-asm.S
new file mode 100644
index 0000000..bfff3bd
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend-asm.S
@@ -0,0 +1,531 @@
+/*
+ * Enter and leave sleep state on MPC83xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+
+#define SS_MEMSAVE 0x00
+#define SS_HID 0x08 /* 3 HIDs */
+#define SS_IABR 0x14 /* 2 IABRs */
+#define SS_IBCR 0x1c
+#define SS_DABR 0x20 /* 2 DABRs */
+#define SS_DBCR 0x28
+#define SS_SP 0x2c
+#define SS_SR 0x30 /* 16 segment registers */
+#define SS_CURRENT 0x70
+#define SS_MSR 0x74
+#define SS_SDR1 0x78
+#define SS_LR 0x7c
+#define SS_SPRG 0x80 /* 4 SPRGs */
+#define SS_DBAT 0x90 /* 8 DBATs */
+#define SS_IBAT 0xd0 /* 8 IBATs */
+#define SS_TB 0x110
+#define SS_CR 0x118
+#define SS_GPREG 0x11c /* r12-r31 */
+#define STATE_SAVE_SIZE 0x16c
+
+ .section .data
+ .align 5
+
+mpc83xx_sleep_save_area:
+ .space STATE_SAVE_SIZE
+immrbase:
+ .long 0
+
+ .section .text
+ .align 5
+
+ /* r3 = physical address of IMMR */
+_GLOBAL(mpc83xx_enter_deep_sleep)
+ /* Re-use the state saving/restoring code in
+ * arch/powerpc/kernel/swsusp_32.S, but have
+ * it call us instead of swsusp_save.
+ */
+
+ lis r4, immrbase@ha
+ stw r3, immrbase@l(r4)
+
+ /* The first 2 words of memory are used to communicate with the
+ * bootloader, to tell it how to resume.
+ *
+ * The first word is the magic number 0xf5153ae5, and the second
+ * is the pointer to mpc83xx_deep_resume.
+ *
+ * The original content of these two words is saved in the state
+ * save area.
+ */
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+
+ lis r4, KERNELBASE@h
+ lwz r5, 0(r4)
+ lwz r6, 4(r4)
+
+ stw r5, SS_MEMSAVE+0(r3)
+ stw r6, SS_MEMSAVE+4(r3)
+
+ mfspr r5, SPRN_HID0
+ mfspr r6, SPRN_HID1
+ mfspr r7, SPRN_HID2
+
+ stw r5, SS_HID+0(r3)
+ stw r6, SS_HID+4(r3)
+ stw r7, SS_HID+8(r3)
+
+ mfspr r4, SPRN_IABR
+ mfspr r5, SPRN_IABR2
+ mfspr r6, SPRN_IBCR
+ mfspr r7, SPRN_DABR
+ mfspr r8, SPRN_DABR2
+ mfspr r9, SPRN_DBCR
+
+ stw r4, SS_IABR+0(r3)
+ stw r5, SS_IABR+4(r3)
+ stw r6, SS_IBCR(r3)
+ stw r7, SS_DABR+0(r3)
+ stw r8, SS_DABR+4(r3)
+ stw r9, SS_DBCR(r3)
+
+ mfspr r4, SPRN_SPRG0
+ mfspr r5, SPRN_SPRG1
+ mfspr r6, SPRN_SPRG2
+ mfspr r7, SPRN_SPRG3
+ mfsdr1 r8
+
+ stw r4, SS_SPRG+0(r3)
+ stw r5, SS_SPRG+4(r3)
+ stw r6, SS_SPRG+8(r3)
+ stw r7, SS_SPRG+12(r3)
+ stw r8, SS_SDR1(r3)
+
+ mfspr r4, SPRN_DBAT0U
+ mfspr r5, SPRN_DBAT0L
+ mfspr r6, SPRN_DBAT1U
+ mfspr r7, SPRN_DBAT1L
+
+ stw r4, SS_DBAT+0x00(r3)
+ stw r5, SS_DBAT+0x04(r3)
+ stw r6, SS_DBAT+0x08(r3)
+ stw r7, SS_DBAT+0x0c(r3)
+
+ mfspr r4, SPRN_DBAT2U
+ mfspr r5, SPRN_DBAT2L
+ mfspr r6, SPRN_DBAT3U
+ mfspr r7, SPRN_DBAT3L
+
+ stw r4, SS_DBAT+0x10(r3)
+ stw r5, SS_DBAT+0x14(r3)
+ stw r6, SS_DBAT+0x18(r3)
+ stw r7, SS_DBAT+0x1c(r3)
+
+ mfspr r4, SPRN_DBAT4U
+ mfspr r5, SPRN_DBAT4L
+ mfspr r6, SPRN_DBAT5U
+ mfspr r7, SPRN_DBAT5L
+
+ stw r4, SS_DBAT+0x20(r3)
+ stw r5, SS_DBAT+0x24(r3)
+ stw r6, SS_DBAT+0x28(r3)
+ stw r7, SS_DBAT+0x2c(r3)
+
+ mfspr r4, SPRN_DBAT6U
+ mfspr r5, SPRN_DBAT6L
+ mfspr r6, SPRN_DBAT7U
+ mfspr r7, SPRN_DBAT7L
+
+ stw r4, SS_DBAT+0x30(r3)
+ stw r5, SS_DBAT+0x34(r3)
+ stw r6, SS_DBAT+0x38(r3)
+ stw r7, SS_DBAT+0x3c(r3)
+
+ mfspr r4, SPRN_IBAT0U
+ mfspr r5, SPRN_IBAT0L
+ mfspr r6, SPRN_IBAT1U
+ mfspr r7, SPRN_IBAT1L
+
+ stw r4, SS_IBAT+0x00(r3)
+ stw r5, SS_IBAT+0x04(r3)
+ stw r6, SS_IBAT+0x08(r3)
+ stw r7, SS_IBAT+0x0c(r3)
+
+ mfspr r4, SPRN_IBAT2U
+ mfspr r5, SPRN_IBAT2L
+ mfspr r6, SPRN_IBAT3U
+ mfspr r7, SPRN_IBAT3L
+
+ stw r4, SS_IBAT+0x10(r3)
+ stw r5, SS_IBAT+0x14(r3)
+ stw r6, SS_IBAT+0x18(r3)
+ stw r7, SS_IBAT+0x1c(r3)
+
+ mfspr r4, SPRN_IBAT4U
+ mfspr r5, SPRN_IBAT4L
+ mfspr r6, SPRN_IBAT5U
+ mfspr r7, SPRN_IBAT5L
+
+ stw r4, SS_IBAT+0x20(r3)
+ stw r5, SS_IBAT+0x24(r3)
+ stw r6, SS_IBAT+0x28(r3)
+ stw r7, SS_IBAT+0x2c(r3)
+
+ mfspr r4, SPRN_IBAT6U
+ mfspr r5, SPRN_IBAT6L
+ mfspr r6, SPRN_IBAT7U
+ mfspr r7, SPRN_IBAT7L
+
+ stw r4, SS_IBAT+0x30(r3)
+ stw r5, SS_IBAT+0x34(r3)
+ stw r6, SS_IBAT+0x38(r3)
+ stw r7, SS_IBAT+0x3c(r3)
+
+ mfmsr r4
+ mflr r5
+ mfcr r6
+
+ stw r4, SS_MSR(r3)
+ stw r5, SS_LR(r3)
+ stw r6, SS_CR(r3)
+ stw r1, SS_SP(r3)
+ stw r2, SS_CURRENT(r3)
+
+1: mftbu r4
+ mftb r5
+ mftbu r6
+ cmpw r4, r6
+ bne 1b
+
+ stw r4, SS_TB+0(r3)
+ stw r5, SS_TB+4(r3)
+
+ stmw r12, SS_GPREG(r3)
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: mfsrin r5, r4
+ stwu r5, 4(r6)
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ /* Disable machine checks and critical exceptions */
+ mfmsr r4
+ rlwinm r4, r4, 0, ~MSR_CE
+ rlwinm r4, r4, 0, ~MSR_ME
+ mtmsr r4
+ isync
+
+#define TMP_VIRT_IMMR 0xf0000000
+#define DEFAULT_IMMR_VALUE 0xff400000
+#define IMMRBAR_BASE 0x0000
+
+ lis r4, immrbase@ha
+ lwz r4, immrbase@l(r4)
+
+ /* Use DBAT0 to address the current IMMR space */
+
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT0L, r4
+ lis r8, TMP_VIRT_IMMR@h
+ ori r4, r8, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT0U, r4
+ isync
+
+ /* Use DBAT1 to address the original IMMR space */
+
+ lis r4, DEFAULT_IMMR_VALUE@h
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT1L, r4
+ lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
+ ori r4, r9, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT1U, r4
+ isync
+
+ /* Use DBAT2 to address the beginning of RAM. This isn't done
+ * using the normal virtual mapping, because with page debugging
+ * enabled it will be read-only. */
+
+ li r4, 0x0002
+ mtspr SPRN_DBAT2L, r4
+ lis r4, KERNELBASE@h
+ ori r4, r4, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT2U, r4
+ isync
+
+ /* Flush the cache with our BAT, as there will be TLB misses
+ * otherwise if page debugging is enabled, and these misses
+ * will disturb the PLRU algorithm.
+ */
+
+ bl __flush_disable_L1
+
+ lis r6, 0xf515
+ ori r6, r6, 0x3ae5
+
+ lis r7, mpc83xx_deep_resume@h
+ ori r7, r7, mpc83xx_deep_resume@l
+ tophys(r7, r7)
+
+ lis r5, KERNELBASE@h
+ stw r6, 0(r5)
+ stw r7, 4(r5)
+
+ /* Reset BARs */
+
+ li r4, 0
+ stw r4, 0x0024(r8)
+ stw r4, 0x002c(r8)
+ stw r4, 0x0034(r8)
+ stw r4, 0x003c(r8)
+ stw r4, 0x0064(r8)
+ stw r4, 0x006c(r8)
+
+ /* Rev 1 of the 8313 has problems with wakeup events that are
+ * pending during the transition to deep sleep state (such as if
+ * the PCI host sets the state to D3 and then D0 in rapid
+ * succession). This check shrinks the race window somewhat.
+ *
+ * See erratum PCI23, though the problem is not limited
+ * to PCI.
+ */
+
+ lwz r3, 0x0b04(r8)
+ andi. r3, r3, 1
+ bne- mpc83xx_deep_resume
+
+ /* Move IMMR back to the default location, following the
+ * procedure specified in the MPC8313 manual.
+ */
+ lwz r4, IMMRBAR_BASE(r8)
+ isync
+ lis r4, DEFAULT_IMMR_VALUE@h
+ stw r4, IMMRBAR_BASE(r8)
+ lis r4, KERNELBASE@h
+ lwz r4, 0(r4)
+ isync
+ lwz r4, IMMRBAR_BASE(r9)
+ mr r8, r9
+ isync
+
+ /* Check the Reset Configuration Word to see whether flash needs
+ * to be mapped at a low address or a high address.
+ */
+
+ lwz r4, 0x0904(r8)
+ andis. r4, r4, 0x0400
+ li r4, 0
+ beq boot_low
+ lis r4, 0xff80
+boot_low:
+ stw r4, 0x0020(r8)
+ lis r7, 0x8000
+ ori r7, r7, 0x0016
+
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+ oris r5, r5, HID0_SLEEP@h
+ mtspr SPRN_HID0, r5
+ isync
+
+ mfmsr r5
+ oris r5, r5, MSR_POW@h
+
+ /* Enable the flash mapping at the appropriate address. This
+ * mapping will override the RAM mapping, so there's no need to
+ * disable the latter. This must be done inside the same cache
+ * line as setting MSR_POW, so that no instruction fetches from
+ * RAM happen after the flash mapping is turned on.
+ */
+
+ .align 5
+ stw r7, 0x0024(r8)
+ sync
+ isync
+ mtmsr r5
+ isync
+1: b 1b
+
+mpc83xx_deep_resume:
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+ tophys(r4, r4)
+ mtsrr0 r4
+
+ mfmsr r4
+ rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
+ mtsrr1 r4
+
+ rfi
+
+1: tlbia
+ bl __inval_enable_L1
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+ tophys(r3, r3)
+
+ lwz r5, SS_MEMSAVE+0(r3)
+ lwz r6, SS_MEMSAVE+4(r3)
+
+ stw r5, 0(0)
+ stw r6, 4(0)
+
+ lwz r5, SS_HID+0(r3)
+ lwz r6, SS_HID+4(r3)
+ lwz r7, SS_HID+8(r3)
+
+ mtspr SPRN_HID0, r5
+ mtspr SPRN_HID1, r6
+ mtspr SPRN_HID2, r7
+
+ lwz r4, SS_IABR+0(r3)
+ lwz r5, SS_IABR+4(r3)
+ lwz r6, SS_IBCR(r3)
+ lwz r7, SS_DABR+0(r3)
+ lwz r8, SS_DABR+4(r3)
+ lwz r9, SS_DBCR(r3)
+
+ mtspr SPRN_IABR, r4
+ mtspr SPRN_IABR2, r5
+ mtspr SPRN_IBCR, r6
+ mtspr SPRN_DABR, r7
+ mtspr SPRN_DABR2, r8
+ mtspr SPRN_DBCR, r9
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: lwzu r5, 4(r6)
+ mtsrin r5, r4
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ lwz r4, SS_DBAT+0x00(r3)
+ lwz r5, SS_DBAT+0x04(r3)
+ lwz r6, SS_DBAT+0x08(r3)
+ lwz r7, SS_DBAT+0x0c(r3)
+
+ mtspr SPRN_DBAT0U, r4
+ mtspr SPRN_DBAT0L, r5
+ mtspr SPRN_DBAT1U, r6
+ mtspr SPRN_DBAT1L, r7
+
+ lwz r4, SS_DBAT+0x10(r3)
+ lwz r5, SS_DBAT+0x14(r3)
+ lwz r6, SS_DBAT+0x18(r3)
+ lwz r7, SS_DBAT+0x1c(r3)
+
+ mtspr SPRN_DBAT2U, r4
+ mtspr SPRN_DBAT2L, r5
+ mtspr SPRN_DBAT3U, r6
+ mtspr SPRN_DBAT3L, r7
+
+ lwz r4, SS_DBAT+0x20(r3)
+ lwz r5, SS_DBAT+0x24(r3)
+ lwz r6, SS_DBAT+0x28(r3)
+ lwz r7, SS_DBAT+0x2c(r3)
+
+ mtspr SPRN_DBAT4U, r4
+ mtspr SPRN_DBAT4L, r5
+ mtspr SPRN_DBAT5U, r6
+ mtspr SPRN_DBAT5L, r7
+
+ lwz r4, SS_DBAT+0x30(r3)
+ lwz r5, SS_DBAT+0x34(r3)
+ lwz r6, SS_DBAT+0x38(r3)
+ lwz r7, SS_DBAT+0x3c(r3)
+
+ mtspr SPRN_DBAT6U, r4
+ mtspr SPRN_DBAT6L, r5
+ mtspr SPRN_DBAT7U, r6
+ mtspr SPRN_DBAT7L, r7
+
+ lwz r4, SS_IBAT+0x00(r3)
+ lwz r5, SS_IBAT+0x04(r3)
+ lwz r6, SS_IBAT+0x08(r3)
+ lwz r7, SS_IBAT+0x0c(r3)
+
+ mtspr SPRN_IBAT0U, r4
+ mtspr SPRN_IBAT0L, r5
+ mtspr SPRN_IBAT1U, r6
+ mtspr SPRN_IBAT1L, r7
+
+ lwz r4, SS_IBAT+0x10(r3)
+ lwz r5, SS_IBAT+0x14(r3)
+ lwz r6, SS_IBAT+0x18(r3)
+ lwz r7, SS_IBAT+0x1c(r3)
+
+ mtspr SPRN_IBAT2U, r4
+ mtspr SPRN_IBAT2L, r5
+ mtspr SPRN_IBAT3U, r6
+ mtspr SPRN_IBAT3L, r7
+
+ lwz r4, SS_IBAT+0x20(r3)
+ lwz r5, SS_IBAT+0x24(r3)
+ lwz r6, SS_IBAT+0x28(r3)
+ lwz r7, SS_IBAT+0x2c(r3)
+
+ mtspr SPRN_IBAT4U, r4
+ mtspr SPRN_IBAT4L, r5
+ mtspr SPRN_IBAT5U, r6
+ mtspr SPRN_IBAT5L, r7
+
+ lwz r4, SS_IBAT+0x30(r3)
+ lwz r5, SS_IBAT+0x34(r3)
+ lwz r6, SS_IBAT+0x38(r3)
+ lwz r7, SS_IBAT+0x3c(r3)
+
+ mtspr SPRN_IBAT6U, r4
+ mtspr SPRN_IBAT6L, r5
+ mtspr SPRN_IBAT7U, r6
+ mtspr SPRN_IBAT7L, r7
+
+ lwz r4, SS_SPRG+0(r3)
+ lwz r5, SS_SPRG+4(r3)
+ lwz r6, SS_SPRG+8(r3)
+ lwz r7, SS_SPRG+12(r3)
+ lwz r8, SS_SDR1(r3)
+
+ mtspr SPRN_SPRG0, r4
+ mtspr SPRN_SPRG1, r5
+ mtspr SPRN_SPRG2, r6
+ mtspr SPRN_SPRG3, r7
+ mtsdr1 r8
+
+ lwz r4, SS_MSR(r3)
+ lwz r5, SS_LR(r3)
+ lwz r6, SS_CR(r3)
+ lwz r1, SS_SP(r3)
+ lwz r2, SS_CURRENT(r3)
+
+ mtsrr1 r4
+ mtsrr0 r5
+ mtcr r6
+
+ li r4, 0
+ mtspr SPRN_TBWL, r4
+
+ lwz r4, SS_TB+0(r3)
+ lwz r5, SS_TB+4(r3)
+
+ mtspr SPRN_TBWU, r4
+ mtspr SPRN_TBWL, r5
+
+ lmw r12, SS_GPREG(r3)
+
+ /* Kick decrementer */
+ li r0, 1
+ mtdec r0
+
+ rfi
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
new file mode 100644
index 0000000..61bca38
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -0,0 +1,423 @@
+/*
+ * MPC83xx suspend support
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/suspend.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc6xx.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */
+#define PMCCR1_NEXT_STATE_SHIFT 2
+#define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/
+#define IMMR_RCW_OFFSET 0x900
+#define RCW_PCI_HOST 0x80000000
+
+void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
+
+struct mpc83xx_pmc {
+ u32 config;
+#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
+#define PMCCR_SLPEN 1 /* System low power enable */
+
+ u32 event;
+ u32 mask;
+/* All but PMCI are deep-sleep only */
+#define PMCER_GPIO 0x100
+#define PMCER_PCI 0x080
+#define PMCER_USB 0x040
+#define PMCER_ETSEC1 0x020
+#define PMCER_ETSEC2 0x010
+#define PMCER_TIMER 0x008
+#define PMCER_INT1 0x004
+#define PMCER_INT2 0x002
+#define PMCER_PMCI 0x001
+#define PMCER_ALL 0x1FF
+
+ /* deep-sleep only */
+ u32 config1;
+#define PMCCR1_USE_STATE 0x80000000
+#define PMCCR1_PME_EN 0x00000080
+#define PMCCR1_ASSERT_PME 0x00000040
+#define PMCCR1_POWER_OFF 0x00000020
+
+ /* deep-sleep only */
+ u32 config2;
+};
+
+struct mpc83xx_rcw {
+ u32 rcwlr;
+ u32 rcwhr;
+};
+
+struct mpc83xx_clock {
+ u32 spmr;
+ u32 occr;
+ u32 sccr;
+};
+
+struct pmc_type {
+ int has_deep_sleep;
+};
+
+static struct of_device *pmc_dev;
+static int has_deep_sleep, deep_sleeping;
+static int pmc_irq;
+static struct mpc83xx_pmc __iomem *pmc_regs;
+static struct mpc83xx_clock __iomem *clock_regs;
+static int is_pci_agent, wake_from_pci;
+static phys_addr_t immrbase;
+static int pci_pm_state;
+static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
+
+static u32 saved_sccr;
+static DEFINE_SPINLOCK(device_sleep_lock);
+
+void fsl_sleep_device(struct fsl_sleep_platform_data *data)
+{
+ if (clock_regs && data->sccr_mask) {
+ unsigned long flags;
+ u32 sccr;
+
+ spin_lock_irqsave(&device_sleep_lock, flags);
+ sccr = in_be32(&clock_regs->sccr);
+
+ saved_sccr &= ~data->sccr_mask;
+ saved_sccr |= sccr & data->sccr_mask;
+
+ out_be32(&clock_regs->sccr, sccr & ~data->sccr_mask);
+ spin_unlock_irqrestore(&device_sleep_lock, flags);
+ }
+}
+EXPORT_SYMBOL(fsl_sleep_device);
+
+void fsl_wake_device(struct fsl_sleep_platform_data *data)
+{
+ if (clock_regs && data->sccr_mask) {
+ unsigned long flags;
+ u32 sccr;
+
+ spin_lock_irqsave(&device_sleep_lock, flags);
+
+ sccr = in_be32(&clock_regs->sccr);
+ sccr |= saved_sccr & data->sccr_mask;
+ out_be32(&clock_regs->sccr, sccr);
+
+ spin_unlock_irqrestore(&device_sleep_lock, flags);
+ }
+}
+EXPORT_SYMBOL(fsl_wake_device);
+
+int fsl_deep_sleep(void)
+{
+ return deep_sleeping;
+}
+
+static int mpc83xx_change_state(void)
+{
+ u32 curr_state;
+ u32 reg_cfg1 = in_be32(&pmc_regs->config1);
+
+ if (is_pci_agent) {
+ pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
+ PMCCR1_NEXT_STATE_SHIFT;
+ curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
+
+ if (curr_state != pci_pm_state) {
+ reg_cfg1 &= ~PMCCR1_CURR_STATE;
+ reg_cfg1 |= pci_pm_state;
+ out_be32(&pmc_regs->config1, reg_cfg1);
+
+ wake_up(&agent_wq);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
+{
+ u32 event = in_be32(&pmc_regs->event);
+ int ret = IRQ_NONE;
+
+ if (mpc83xx_change_state())
+ ret = IRQ_HANDLED;
+
+ if (event) {
+ out_be32(&pmc_regs->event, event);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static int mpc83xx_suspend_enter(suspend_state_t state)
+{
+ int ret = -EAGAIN;
+
+ /* Don't go to sleep if there's a race where pci_pm_state changes
+ * between the agent thread checking it and the PM code disabling
+ * interrupts.
+ */
+ if (wake_from_pci) {
+ if (pci_pm_state != (deep_sleeping ? 3 : 2))
+ goto out;
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
+ }
+
+ /* Put the system into low-power mode and the RAM
+ * into self-refresh mode once the core goes to
+ * sleep.
+ */
+
+ out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
+
+ /* If it has deep sleep (i.e. it's an 831x or compatible),
+ * disable power to the core upon entering sleep mode. This will
+ * require going through the boot firmware upon a wakeup event.
+ */
+
+ if (deep_sleeping) {
+ out_be32(&pmc_regs->mask, PMCER_ALL);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
+
+ enable_kernel_fp();
+
+ mpc83xx_enter_deep_sleep(immrbase);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
+
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+ } else {
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ mpc6xx_enter_standby();
+ }
+
+ ret = 0;
+
+out:
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
+
+ return ret;
+}
+
+static void mpc83xx_suspend_finish(void)
+{
+ deep_sleeping = 0;
+}
+
+static int mpc83xx_suspend_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
+}
+
+static int mpc83xx_suspend_set_target(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ deep_sleeping = 0;
+ return 0;
+
+ case PM_SUSPEND_MEM:
+ if (has_deep_sleep)
+ deep_sleeping = 1;
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int agent_thread_fn(void *data)
+{
+ while (1) {
+ wait_event_interruptible(agent_wq, pci_pm_state >= 2);
+ try_to_freeze();
+
+ if (signal_pending(current) || pci_pm_state < 2)
+ continue;
+
+ /* With a preemptible kernel (or SMP), this could race with a
+ * userspace-driven suspend request. It's probably best to
+ * avoid mixing the two with such a configuration (or else fix
+ * it by adding a mutex to state_store that we can synchronize
+ * with).
+ */
+
+ wake_from_pci = 1;
+
+ pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
+ PM_SUSPEND_STANDBY);
+
+ wake_from_pci = 0;
+ }
+
+ return 0;
+}
+
+void mpc83xx_set_agent(void)
+{
+ out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ kthread_run(agent_thread_fn, NULL, "PCI power mgt");
+}
+
+static int mpc83xx_is_pci_agent(void)
+{
+ struct mpc83xx_rcw __iomem *rcw_regs;
+ int ret;
+
+ rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
+ sizeof(struct mpc83xx_rcw));
+
+ if (!rcw_regs)
+ return -ENOMEM;
+
+ ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
+
+ iounmap(rcw_regs);
+ return ret;
+}
+
+static struct platform_suspend_ops mpc83xx_suspend_ops = {
+ .valid = mpc83xx_suspend_valid,
+ .set_target = mpc83xx_suspend_set_target,
+ .enter = mpc83xx_suspend_enter,
+ .finish = mpc83xx_suspend_finish,
+};
+
+static int pmc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ struct resource res;
+ struct pmc_type *type = match->data;
+ int ret = 0;
+
+ has_deep_sleep = type->has_deep_sleep;
+ immrbase = get_immrbase();
+ pmc_dev = ofdev;
+
+ is_pci_agent = mpc83xx_is_pci_agent();
+ if (is_pci_agent < 0)
+ return is_pci_agent;
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return -ENODEV;
+
+ pmc_irq = irq_of_parse_and_map(np, 0);
+ if (pmc_irq != NO_IRQ) {
+ ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
+ "pmc", ofdev);
+
+ if (ret)
+ return -EBUSY;
+ }
+
+ pmc_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!pmc_regs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_address_to_resource(np, 1, &res);
+ if (ret) {
+ ret = -ENODEV;
+ goto out_pmc;
+ }
+
+ clock_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!clock_regs) {
+ ret = -ENOMEM;
+ goto out_pmc;
+ }
+
+ if (is_pci_agent)
+ mpc83xx_set_agent();
+
+ suspend_set_ops(&mpc83xx_suspend_ops);
+ return 0;
+
+out_pmc:
+ iounmap(pmc_regs);
+out:
+ if (pmc_irq != NO_IRQ)
+ free_irq(pmc_irq, ofdev);
+
+ return ret;
+}
+
+static int pmc_remove(struct of_device *ofdev)
+{
+ return -EPERM;
+};
+
+static struct pmc_type pmc_types[] = {
+ {
+ .has_deep_sleep = 1,
+ },
+ {
+ .has_deep_sleep = 0,
+ }
+};
+
+static struct of_device_id pmc_match[] = {
+ {
+ .compatible = "fsl,mpc8313-pmc",
+ .data = &pmc_types[0],
+ },
+ {
+ .compatible = "fsl,mpc8349-pmc",
+ .data = &pmc_types[1],
+ },
+ {}
+};
+
+static struct of_platform_driver pmc_driver = {
+ .name = "mpc83xx-pmc",
+ .match_table = pmc_match,
+ .probe = pmc_probe,
+ .remove = pmc_remove
+};
+
+static int pmc_init(void)
+{
+ return of_register_platform_driver(&pmc_driver);
+}
+
+module_init(pmc_init);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index e1ba33c..d5fd916 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -151,6 +151,33 @@ u32 get_baudrate(void)
EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */
+int fsl_sleep_init(struct fsl_sleep_platform_data *sleep,
+ struct device_node *node)
+{
+ int proplen, ret = -ENODEV;
+ const u32 *sleepdata = of_get_property(node, "sleep", &proplen);
+ struct device_node *sleep_controller;
+
+ if (!sleepdata || proplen != 8)
+ return -ENODEV;
+
+ sleep_controller = of_find_node_by_phandle(sleepdata[0]);
+ if (!sleep_controller)
+ return -ENODEV;
+
+ /* There can only be one fsl,mpc83xx-pmc device in the system;
+ * it is assumed that it is the one that the pmc driver matches.
+ */
+ if (of_device_is_compatible(sleep_controller, "fsl,mpc83xx-pmc")) {
+ sleep->sccr_mask = sleepdata[1];
+ ret = 0;
+ }
+
+ of_node_put(sleep_controller);
+ return ret;
+}
+EXPORT_SYMBOL(fsl_sleep_init);
+
static int __init gfar_mdio_of_init(void)
{
struct device_node *np;
@@ -321,6 +348,8 @@ static int __init gfar_of_init(void)
of_node_put(phy);
of_node_put(mdio);
+ fsl_sleep_init(&gfar_data.sleep, np);
+
ret =
platform_device_add_data(gfar_dev, &gfar_data,
sizeof(struct
@@ -576,6 +605,8 @@ static int __init fsl_usb_of_init(void)
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
+ fsl_sleep_init(&usb_data.sleep, np);
+
ret =
platform_device_add_data(usb_dev_mph, &usb_data,
sizeof(struct
@@ -640,6 +671,8 @@ static int __init fsl_usb_of_init(void)
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
+ fsl_sleep_init(&usb_data.sleep, np);
+
if (usb_dev_dr_host) {
usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 74c4a96..fb52d39 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -10,12 +10,22 @@ extern u32 get_baudrate(void);
extern u32 fsl_get_sys_freq(void);
struct spi_board_info;
+struct fsl_sleep_platform_data;
+struct device_node;
extern int fsl_spi_init(struct spi_board_info *board_infos,
unsigned int num_board_infos,
void (*activate_cs)(u8 cs, u8 polarity),
void (*deactivate_cs)(u8 cs, u8 polarity));
+int fsl_sleep_init(struct fsl_sleep_platform_data *sleep,
+ struct device_node *node);
+
+/* Calls to fsl_sleep_dev and fsl_wake_dev cannot be nested. */
+void fsl_sleep_dev(struct fsl_sleep_platform_data *sleep);
+void fsl_wake_dev(struct fsl_sleep_platform_data *sleep);
+
extern void fsl_rstcr_restart(char *cmd);
+
#endif
#endif
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 05a56e5..e2388cf 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
+#include <linux/fsl_devices.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -724,8 +725,78 @@ unsigned int ipic_get_irq(void)
return irq_linear_revmap(primary_ipic->irqhost, irq);
}
+#ifdef CONFIG_PM
+static struct {
+ u32 sicfr;
+ u32 siprr[2];
+ u32 simsr[2];
+ u32 sicnr;
+ u32 smprr[2];
+ u32 semsr;
+ u32 secnr;
+ u32 sermr;
+ u32 sercr;
+} ipic_saved_state;
+
+static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
+ ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
+ ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
+ ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
+ ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
+ ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
+ ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
+ ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
+ ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
+ ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
+ ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
+ ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
+
+ if (fsl_deep_sleep()) {
+ /* In deep sleep, make sure there can be no
+ * pending interrupts, as this can cause
+ * problems on 831x.
+ */
+ ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
+ ipic_write(ipic->regs, IPIC_SEMSR, 0);
+ ipic_write(ipic->regs, IPIC_SERMR, 0);
+ }
+
+ return 0;
+}
+
+static int ipic_resume(struct sys_device *sdev)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
+ ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
+ ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
+ ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
+ ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
+ ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
+ ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
+ ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
+ ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
+ ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
+ ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
+
+ return 0;
+}
+#else
+#define ipic_suspend NULL
+#define ipic_resume NULL
+#endif
+
static struct sysdev_class ipic_sysclass = {
set_kset_name("ipic"),
+ .suspend = ipic_suspend,
+ .resume = ipic_resume,
};
static struct sys_device device_ipic = {
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 1f68504..68968c1 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -149,7 +149,9 @@
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define DABR_TRANSLATION (1UL << 2)
+#define SPRN_DABR2 0x13D /* 83xx */
#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_DBCR 0x136 /* 83xx Data Breakpoint Control Reg */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
#define DSISR_NOHPTE 0x40000000 /* no translation found */
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
@@ -255,6 +257,8 @@
#define HID1_PS (1<<16) /* 750FX PLL selection */
#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#define SPRN_IABR2 0x3FA /* 83xx */
+#define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */
#define SPRN_HID4 0x3F4 /* 970 HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */
#define SPRN_HID6 0x3F9 /* BE HID 6 */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 1831b19..5cec939 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -45,10 +45,27 @@
*
*/
+struct fsl_sleep_platform_data {
+ /*
+ * The bits set in this mask will be cleared in the SCCR
+ * when put to sleep, and restored on wakeup.
+ */
+ u32 sccr_mask;
+};
+
+/*
+ * Calls to fsl_sleep_device do not nest -- if you call
+ * sleep twice without an intervening wake, you will not
+ * be able to wake the device again.
+ */
+void fsl_sleep_device(struct fsl_sleep_platform_data *data);
+void fsl_wake_device(struct fsl_sleep_platform_data *data);
+
struct gianfar_platform_data {
/* device specific information */
u32 device_flags;
/* board specific information */
+ struct fsl_sleep_platform_data sleep;
u32 board_flags;
u32 bus_id;
u32 phy_id;
@@ -104,6 +121,7 @@ struct fsl_usb2_platform_data {
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
+ struct fsl_sleep_platform_data sleep;
};
/* Flags in fsl_usb2_mph_platform_data */
@@ -126,5 +144,11 @@ struct mpc8xx_pcmcia_ops {
int(*voltage_set)(int slot, int vcc, int vpp);
};
+/* Returns non-zero if the current suspend operation would
+ * lead to a deep sleep (i.e. power removed from the core,
+ * instead of just the clock).
+ */
+int fsl_deep_sleep(void);
+
#endif /* _FSL_DEVICE_H_ */
#endif /* __KERNEL__ */
--
1.5.3.7
^ permalink raw reply related
* [PATCH 7/8] gianfar: Add flags for magic packet and MDIO.
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
The magic packet flag indicates that the hardware has this
capability. The MDIO flag indicates that this device's
registers contain active MDIO registers, and thus this
device should not be put to sleep.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/sysdev/fsl_soc.c | 7 +++++++
include/linux/fsl_devices.h | 2 ++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index d5fd916..032b8e8 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -324,6 +324,9 @@ static int __init gfar_of_init(void)
else
gfar_data.interface = PHY_INTERFACE_MODE_MII;
+ if (of_get_property(np, "fsl,magic-packet", NULL))
+ gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
@@ -345,6 +348,10 @@ static int __init gfar_of_init(void)
gfar_data.phy_id = *id;
gfar_data.bus_id = res.start;
+ if (res.start >= gfar_dev->resource[0].start &&
+ res.start < gfar_dev->resource[0].end)
+ gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MDIO;
+
of_node_put(phy);
of_node_put(mdio);
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 5cec939..81fcc67 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -87,6 +87,8 @@ struct gianfar_mdio_data {
#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
+#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
+#define FSL_GIANFAR_DEV_HAS_MDIO 0x00000200
/* Flags in gianfar_platform_data */
#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* set or use a timer */
--
1.5.3.7
^ permalink raw reply related
* [PATCH 6/8] mpc83xx: timer driver for PM wakeup
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
This is a driver for the mpc83xx's GTM4 timer. It's functionality
is limited to providing a wakeup source for suspend-to-RAM.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/platforms/83xx/Kconfig | 9 +
arch/powerpc/platforms/83xx/Makefile | 1 +
arch/powerpc/platforms/83xx/timer.c | 299 ++++++++++++++++++++++++++++++++++
3 files changed, 309 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/83xx/timer.c
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 901dbaf..800f547 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -80,3 +80,12 @@ config PPC_83xx_SUSPEND
bool
default y
depends on PPC_83xx && SUSPEND
+
+config MPC83xx_GTM
+ tristate "83xx General-Purpose Timers for PM wakeup"
+ help
+ This enables a driver for the GTM4 timer, to be used
+ as a wakeup source for suspend-to-RAM. To arm the
+ timer, write the number of seconds until expiration
+ to the "timeout" file in the device's sysfs directory.
+ To disarm, write 0 to the "timeout" file.
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 944369e..bcc1003 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -4,6 +4,7 @@
obj-y := misc.o usb.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
+obj-$(CONFIG_MPC83xx_GTM) += timer.o
obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/timer.c b/arch/powerpc/platforms/83xx/timer.c
new file mode 100644
index 0000000..7fc6048
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/timer.c
@@ -0,0 +1,299 @@
+/*
+ * MPC83xx Global Timer4 support
+ *
+ * This driver is currently specific to timer 4 in 16-bit mode,
+ * as that is all that can be used as a wakeup source for deep sleep
+ * on the MPC8313.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define MDR_ICLK_DIV16 0x0004
+
+struct gtm_regs {
+ u8 cfr1; /* Timer1/2 Configuration */
+ #define CFR1_PCAS 0x80 /* Pair Cascade mode */
+ #define CFR1_BCM 0x40 /* Backward compatible mode */
+ #define CFR1_STP2 0x20 /* Stop timer */
+ #define CFR1_RST2 0x10 /* Reset timer */
+ #define CFR1_GM2 0x08 /* Gate mode for pin 2 */
+ #define CFR1_GM1 0x04 /* Gate mode for pin 1 */
+ #define CFR1_STP1 0x02 /* Stop timer */
+ #define CFR1_RST1 0x01 /* Reset timer */
+ #define CFR1_RES ~(CFR1_PCAS | CFR1_STP2 | CFR1_RST2 | CFR1_GM2 |\
+ CFR1_GM1 | CFR1_STP1 | CFR1_RST1)
+
+ u8 res0[3];
+ u8 cfr2; /* Timer3/4 Configuration */
+ #define CFR2_PCAS 0x80 /* Pair Cascade mode */
+ #define CFR2_SCAS 0x40 /* Super Cascade mode */
+ #define CFR2_STP4 0x20 /* Stop timer */
+ #define CFR2_RST4 0x10 /* Reset timer */
+ #define CFR2_GM4 0x08 /* Gate mode for pin 4 */
+ #define CFR2_GM3 0x04 /* Gate mode for pin 3 */
+ #define CFR2_STP3 0x02 /* Stop timer */
+ #define CFR2_RST3 0x01 /* Reset timer */
+
+ u8 res1[11];
+ u16 mdr1; /* Timer1 Mode Register */
+ #define MDR_SPS 0xff00 /* Secondary Prescaler value (256) */
+ #define MDR_CE 0x00c0 /* Capture edge and enable interrupt */
+ #define MDR_OM 0x0020 /* Output mode */
+ #define MDR_ORI 0x0010 /* Output reference interrupt enable */
+ #define MDR_FRR 0x0008 /* Free run/restart */
+ #define MDR_ICLK 0x0006 /* Input clock source for the timer */
+ #define MDR_GE 0x0001 /* Gate enable */
+
+ u16 mdr2; /* Timer2 Mode Register */
+ u16 rfr1; /* Timer1 Reference Register */
+ u16 rfr2; /* Timer2 Reference Register */
+ u16 cpr1; /* Timer1 Capture Register */
+ u16 cpr2; /* Timer2 Capture Register */
+ u16 cnr1; /* Timer1 Counter Register */
+ u16 cnr2; /* Timer2 Counter Register */
+ u16 mdr3; /* Timer3 Mode Register */
+ u16 mdr4; /* Timer4 Mode Register */
+ u16 rfr3; /* Timer3 Reference Register */
+ u16 rfr4; /* Timer4 Reference Register */
+ u16 cpr3; /* Timer3 Capture Register */
+ u16 cpr4; /* Timer4 Capture Register */
+ u16 cnr3; /* Timer3 Counter Register */
+ u16 cnr4; /* Timer4 Counter Register */
+ u16 evr1; /* Timer1 Event Register */
+ u16 evr2; /* Timer2 Event Register */
+ u16 evr3; /* Timer3 Event Register */
+ u16 evr4; /* Timer4 Event Register */
+ #define GTEVR_REF 0x0002 /* Output reference event */
+ #define GTEVR_CAP 0x0001 /* Counter Capture event */
+ #define GTEVR_RES ~(EVR_CAP|EVR_REF)
+
+ u16 psr1; /* Timer1 Prescaler Register */
+ u16 psr2; /* Timer2 Prescaler Register */
+ u16 psr3; /* Timer3 Prescaler Register */
+ u16 psr4; /* Timer4 Prescaler Register */
+ #define GTPSR_PPS 0x00FF /* Primary Prescaler Bits (256). */
+ #define GTPSR_RES ~(GTPSR_PPS)
+};
+
+struct gtm_priv {
+ struct gtm_regs __iomem *regs;
+ int irq;
+ int ticks_per_sec;
+ spinlock_t lock;
+};
+
+static irqreturn_t fsl_gtm_isr(int irq, void *dev_id)
+{
+ struct gtm_priv *priv = dev_id;
+ unsigned long flags;
+ u16 event;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ event = in_be16(&priv->regs->evr4);
+ out_be16(&priv->regs->evr4, event);
+
+ if (event & GTEVR_REF)
+ out_8(&priv->regs->cfr2, CFR2_STP4);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return event ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static ssize_t gtm_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct gtm_priv *priv = dev_get_drvdata(dev);
+ unsigned long interval = simple_strtoul(buf, NULL, 0);
+
+ if (interval > 0xffff) {
+ dev_dbg(dev, "gtm: interval %lu (in ns) too long\n", interval);
+ return -EINVAL;
+ }
+
+ interval *= priv->ticks_per_sec;
+
+ if (interval > 0xffff) {
+ dev_dbg(dev, "gtm: interval %lu (in ticks) too long\n",
+ interval);
+ return -EINVAL;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ /* reset timer 4 */
+ out_8(&priv->regs->cfr2, CFR2_STP3 | CFR2_STP4);
+
+ if (interval != 0) {
+ out_8(&priv->regs->cfr2, CFR2_GM4 | CFR2_RST4 | CFR2_STP4);
+ /* clear events */
+ out_be16(&priv->regs->evr4, GTEVR_REF | GTEVR_CAP);
+ /* maximum primary prescale (256) */
+ out_be16(&priv->regs->psr4, GTPSR_PPS);
+ /* clear current counter */
+ out_be16(&priv->regs->cnr4, 0x0);
+ /* set count limit */
+ out_be16(&priv->regs->rfr4, interval);
+ out_be16(&priv->regs->mdr4, MDR_SPS | MDR_ORI | MDR_FRR |
+ MDR_ICLK_DIV16);
+ /* start timer */
+ out_8(&priv->regs->cfr2, CFR2_GM4 | CFR2_STP3 | CFR2_RST4);
+ }
+
+ spin_unlock_irq(&priv->lock);
+ return count;
+}
+
+static ssize_t gtm_timeout_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct gtm_priv *priv = dev_get_drvdata(dev);
+ int timeout = 0;
+
+ spin_lock_irq(&priv->lock);
+
+ if (!(in_8(&priv->regs->cfr2) & CFR2_STP4)) {
+ timeout = in_be16(&priv->regs->rfr4) -
+ in_be16(&priv->regs->cnr4);
+ timeout += priv->ticks_per_sec - 1;
+ timeout /= priv->ticks_per_sec;
+ }
+
+ spin_unlock_irq(&priv->lock);
+ return sprintf(buf, "%u\n", timeout);
+}
+
+static DEVICE_ATTR(timeout, 0660, gtm_timeout_show, gtm_timeout_store);
+
+static int __devinit gtm_probe(struct of_device *dev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = dev->node;
+ struct resource res;
+ int ret = 0;
+ u32 busfreq = fsl_get_sys_freq();
+ struct gtm_priv *priv;
+
+ if (busfreq == 0) {
+ dev_err(&dev->dev, "gtm: No bus frequency in device tree.\n");
+ return -ENODEV;
+ }
+
+ priv = kmalloc(sizeof(struct gtm_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ dev_set_drvdata(&dev->dev, priv);
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ goto out;
+
+ priv->irq = irq_of_parse_and_map(np, 0);
+ if (priv->irq == NO_IRQ) {
+ dev_err(&dev->dev, "mpc83xx-gtm exists in device tree "
+ "without an IRQ.\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = request_irq(priv->irq, fsl_gtm_isr, 0, "gtm timer", priv);
+ if (ret)
+ goto out;
+
+ priv->regs = ioremap(res.start, sizeof(struct gtm_regs));
+ if (!priv->regs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Disable the unused clocks to save power. */
+ out_8(&priv->regs->cfr1, CFR1_STP1 | CFR1_STP2);
+ out_8(&priv->regs->cfr2, CFR2_STP3 | CFR2_STP4);
+
+ /*
+ * Maximum prescaling is used (input clock/16, 256 primary prescaler,
+ * 256 secondary prescaler) to maximize the timer's range. With a
+ * bus clock of 133MHz, this yields a maximum interval of 516
+ * seconds while retaining subsecond precision. Since only
+ * timer 4 is supported for wakeup on the 8313, and timer 4
+ * is the LSB when chained, we can't use chaining to increase
+ * the range.
+ */
+ priv->ticks_per_sec = busfreq / (16*256*256);
+
+ ret = device_create_file(&dev->dev, &dev_attr_timeout);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit gtm_remove(struct of_device *dev)
+{
+ struct gtm_priv *priv = dev_get_drvdata(&dev->dev);
+
+ device_remove_file(&dev->dev, &dev_attr_timeout);
+ free_irq(priv->irq, priv);
+ iounmap(priv->regs);
+
+ dev_set_drvdata(&dev->dev, NULL);
+ kfree(priv);
+ return 0;
+}
+
+static struct of_device_id gtm_match[] = {
+ {
+ .compatible = "fsl,mpc8313-gtm",
+ },
+ {},
+};
+
+static struct of_platform_driver gtm_driver = {
+ .name = "mpc83xx-gtm",
+ .match_table = gtm_match,
+ .probe = gtm_probe,
+ .remove = __devexit_p(gtm_remove)
+};
+
+static int __init gtm_init(void)
+{
+ return of_register_platform_driver(>m_driver);
+}
+
+static void __exit gtm_exit(void)
+{
+ of_unregister_platform_driver(>m_driver);
+}
+
+module_init(gtm_init);
+module_exit(gtm_exit);
--
1.5.3.7
^ permalink raw reply related
* [PATCH 4/8] fsl_soc: Factor fsl_get_sys_freq() out of the wdt init.
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/sysdev/fsl_soc.c | 44 ++++++++++++++++++++++------------------
arch/powerpc/sysdev/fsl_soc.h | 1 +
2 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3ace747..e1ba33c 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -66,6 +66,27 @@ phys_addr_t get_immrbase(void)
EXPORT_SYMBOL(get_immrbase);
+u32 fsl_get_sys_freq(void)
+{
+ struct device_node *soc = of_find_node_by_type(NULL, "soc");
+ const u32 *freq;
+ u32 ret = 0;
+
+ if (!soc)
+ goto err;
+
+ freq = of_get_property(soc, "bus-frequency", NULL);
+ if (!freq)
+ goto err;
+
+ ret = *freq;
+
+err:
+ of_node_put(soc);
+ return ret;
+}
+EXPORT_SYMBOL(fsl_get_sys_freq);
+
#if defined(CONFIG_CPM2) || defined(CONFIG_8xx)
static u32 brgfreq = -1;
@@ -450,9 +471,9 @@ arch_initcall(fsl_i2c_of_init);
static int __init mpc83xx_wdt_init(void)
{
struct resource r;
- struct device_node *soc, *np;
+ struct device_node *np;
struct platform_device *dev;
- const unsigned int *freq;
+ u32 freq = fsl_get_sys_freq();
int ret;
np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
@@ -462,19 +483,6 @@ static int __init mpc83xx_wdt_init(void)
goto nodev;
}
- soc = of_find_node_by_type(NULL, "soc");
-
- if (!soc) {
- ret = -ENODEV;
- goto nosoc;
- }
-
- freq = of_get_property(soc, "bus-frequency", NULL);
- if (!freq) {
- ret = -ENODEV;
- goto err;
- }
-
memset(&r, 0, sizeof(r));
ret = of_address_to_resource(np, 0, &r);
@@ -487,20 +495,16 @@ static int __init mpc83xx_wdt_init(void)
goto err;
}
- ret = platform_device_add_data(dev, freq, sizeof(int));
+ ret = platform_device_add_data(dev, &freq, sizeof(int));
if (ret)
goto unreg;
- of_node_put(soc);
of_node_put(np);
-
return 0;
unreg:
platform_device_unregister(dev);
err:
- of_node_put(soc);
-nosoc:
of_node_put(np);
nodev:
return ret;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 63e7db3..74c4a96 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -7,6 +7,7 @@
extern phys_addr_t get_immrbase(void);
extern u32 get_brgfreq(void);
extern u32 get_baudrate(void);
+extern u32 fsl_get_sys_freq(void);
struct spi_board_info;
--
1.5.3.7
^ permalink raw reply related
* [PATCH 3/8] Add 6xx-style HID0_SLEEP support.
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/sysdev/6xx-suspend.S | 52 +++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/Makefile | 4 +++
include/asm-powerpc/mpc6xx.h | 6 ++++
3 files changed, 62 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/6xx-suspend.S
create mode 100644 include/asm-powerpc/mpc6xx.h
diff --git a/arch/powerpc/sysdev/6xx-suspend.S b/arch/powerpc/sysdev/6xx-suspend.S
new file mode 100644
index 0000000..21cda08
--- /dev/null
+++ b/arch/powerpc/sysdev/6xx-suspend.S
@@ -0,0 +1,52 @@
+/*
+ * Enter and leave sleep state on chips with 6xx-style HID0
+ * power management bits, which don't leave sleep state via reset.
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+
+_GLOBAL(mpc6xx_enter_standby)
+ mflr r4
+
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+ oris r5, r5, HID0_SLEEP@h
+ mtspr SPRN_HID0, r5
+ isync
+
+ lis r5, ret_from_standby@h
+ ori r5, r5, ret_from_standby@l
+ mtlr r5
+
+ rlwinm r5, r1, 0, 0, 31-THREAD_SHIFT
+ lwz r6, TI_LOCAL_FLAGS(r5)
+ ori r6, r6, _TLF_SLEEPING
+ stw r6, TI_LOCAL_FLAGS(r5)
+
+ mfmsr r5
+ ori r5, r5, MSR_EE
+ oris r5, r5, MSR_POW@h
+ sync
+ mtmsr r5
+ isync
+
+1: b 1b
+
+ret_from_standby:
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~HID0_SLEEP
+ mtspr SPRN_HID0, r5
+
+ mtlr r4
+ blr
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 99a77d7..df2b885 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -37,3 +37,7 @@ obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
endif
+
+ifeq ($(CONFIG_SUSPEND),y)
+obj-$(CONFIG_6xx) += 6xx-suspend.o
+endif
diff --git a/include/asm-powerpc/mpc6xx.h b/include/asm-powerpc/mpc6xx.h
new file mode 100644
index 0000000..effc229
--- /dev/null
+++ b/include/asm-powerpc/mpc6xx.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_POWERPC_MPC6xx_H
+#define __ASM_POWERPC_MPC6xx_H
+
+void mpc6xx_enter_standby(void);
+
+#endif
--
1.5.3.7
^ permalink raw reply related
* [PATCH 2/8] pm: Add TLF_SLEEPING hack to delay interrupt delivery when waking from sleep.
From: Scott Wood @ 2007-12-12 17:35 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>
The e300 core (and probably most other 6xx chips) can only come out of
sleep mode with an interrupt. However, interrupts are logically disabled
by the power management layer.
This hack extends the existing doze/nap hack to also suppress the running
of the interrupt handler when in sleep mode.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/kernel/entry_32.S | 6 ++--
arch/powerpc/kernel/idle_6xx.S | 41 ++++++++++++++++++++++++++++++++++++-
include/asm-powerpc/thread_info.h | 2 +
3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 69a91bd..4099a6f 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -138,8 +138,8 @@ transfer_to_handler:
#ifdef CONFIG_6xx
tophys(r9,r9) /* check local flags */
lwz r12,TI_LOCAL_FLAGS(r9)
- mtcrf 0x01,r12
- bt- 31-TLF_NAPPING,4f
+ andi. r8, r12, _TLF_NAPPING | _TLF_SLEEPING
+ bne- 4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
@@ -154,7 +154,7 @@ transfer_to_handler_cont:
RFI /* jump to handler, enable MMU */
#ifdef CONFIG_6xx
-4: rlwinm r12,r12,0,~_TLF_NAPPING
+4: rlwinm r12,r12,0,~(_TLF_NAPPING | _TLF_SLEEPING)
stw r12,TI_LOCAL_FLAGS(r9)
b power_save_6xx_restore
#endif
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 01bcd52..341f474 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -147,16 +147,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
isync
b 1b
+#ifdef CONFIG_SUSPEND
+ret_from_sleep:
+ .long ret_from_except
+ .long ret_from_except
+#endif
+
/*
* Return from NAP/DOZE mode, restore some CPU specific registers,
* we are called with DR/IR still off and r2 containing physical
* address of current. R11 points to the exception frame (physical
- * address). We have to preserve r10.
+ * address). r8 contains _TLF_NAPPING or _TLF_SLEEPING. We have to
+ * preserve r10.
*/
_GLOBAL(power_save_6xx_restore)
lwz r9,_LINK(r11) /* interrupted in ppc6xx_idle: */
+#ifdef CONFIG_SUSPEND
+ andi. r12, r8, _TLF_SLEEPING
+#endif
stw r9,_NIP(r11) /* make it do a blr */
+#ifdef CONFIG_SUSPEND
+ bne- sleep_6xx_restore
+#endif
+
#ifdef CONFIG_SMP
mfspr r12,SPRN_SPRG3
lwz r11,TI_CPU(r12) /* get cpu number * 4 */
@@ -185,6 +199,31 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
b transfer_to_handler_cont
+#ifdef CONFIG_SUSPEND
+sleep_6xx_restore:
+ /*
+ * SLEEP mode is invoked through the PM subsystem, which means
+ * that interrupts should be disabled. However, the hardware
+ * requires them to be enabled to wake up. To prevent the
+ * interrupt from being visible to Linux, return immediately
+ * rather than run the interrupt handler.
+ */
+ lis r9, ret_from_sleep@h
+ ori r9, r9, ret_from_sleep@l
+ tophys(r9, r9)
+ mtlr r9
+
+ /*
+ * Disable interrupts, so that the interrupt doesn't happen
+ * again until the PM code sets MSR[EE].
+ */
+ lwz r9, _MSR(r11)
+ rlwinm r9, r9, 0, ~MSR_EE
+ stw r9, _MSR(r11)
+
+ b transfer_to_handler_cont
+#endif
+
.data
_GLOBAL(nap_save_msscr0)
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 40d5f98..f7cb48b 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -151,8 +151,10 @@ static inline struct thread_info *current_thread_info(void)
/* Bits in local_flags */
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+#define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */
#define _TLF_NAPPING (1 << TLF_NAPPING)
+#define _TLF_SLEEPING (1 << TLF_SLEEPING)
#endif /* __KERNEL__ */
--
1.5.3.7
^ permalink raw reply related
* Re: cpu frequency governor regression (?)
From: Johannes Berg @ 2007-12-12 17:35 UTC (permalink / raw)
To: Dave Jones; +Cc: Rafael J. Wysocki, linuxppc-dev list, linux-pm, cpufreq
In-Reply-To: <20071212173001.GA18973@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 743 bytes --]
Hi,
> bizarre. It should default back to whatever CONFIG_CPU_FREQ_DEFAULT_* option
> was set. (Arguably a bug in itself, as we don't track & restore them
> on resume, so if you changed from the default after booting: splat)
Hah ok, but it's still odd that it changes to a different one.
> Why you're getting the performance governor is puzzling though.
> Can you enable CONFIG_CPU_FREQ_DEBUG=y, and boot with cpufreq.debug=7
> and send the log from a transition across hibernate?
Sure. I'll do it tonight and send it tomorrow.
> Also, does /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
> have performance in *all* the cpus?
My four CPUs can only change together so I don't think that is relevant.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* [PATCH 1/8] Implement arch disable/enable irq hooks.
From: Scott Wood @ 2007-12-12 17:35 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
These hooks ensure that a decrementer interrupt is not pending when
suspending; otherwise, problems may occur. For example, with deep sleep
on the 831x, a pending decrementer will cause a system freeze because the
SoC thinks the decrementer interrupt would have woken the system, but the
core must have interrupts disabled due to the setup required for deep
sleep.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Paul, please apply this series for 2.6.25 if all is well.
arch/powerpc/kernel/time.c | 41 +++++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/machdep.h | 13 +++++++++++++
2 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a925a8e..509f481 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -623,6 +623,47 @@ void wakeup_decrementer(void)
set_dec(ticks);
}
+#ifdef CONFIG_SUSPEND
+void generic_suspend_disable_irqs(void)
+{
+ preempt_disable();
+
+ /* Disable the decrementer, so that it doesn't interfere
+ * with suspending.
+ */
+
+ set_dec(0x7fffffff);
+ hard_irq_disable();
+ set_dec(0x7fffffff);
+}
+
+void generic_suspend_enable_irqs(void)
+{
+ wakeup_decrementer();
+
+ hard_irq_enable();
+ preempt_enable();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_disable_irqs(void)
+{
+ if (ppc_md.suspend_disable_irqs)
+ ppc_md.suspend_disable_irqs();
+ else
+ generic_suspend_disable_irqs();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_enable_irqs(void)
+{
+ if (ppc_md.suspend_enable_irqs)
+ ppc_md.suspend_enable_irqs();
+ else
+ generic_suspend_enable_irqs();
+}
+#endif
+
#ifdef CONFIG_SMP
void __init smp_space_timers(unsigned int max_cpus)
{
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6968f43..15ba15a 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -253,6 +253,16 @@ struct machdep_calls {
*/
void (*machine_kexec)(struct kimage *image);
#endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_SUSPEND
+ /* These are called to disable and enable, respectively, IRQs when
+ * entering a suspend state. If NULL, then the generic versions
+ * will be called. The generic versions disable/enable the
+ * decrementer along with interrupts.
+ */
+ void (*suspend_disable_irqs)(void);
+ void (*suspend_enable_irqs)(void);
+#endif
};
extern void power4_idle(void);
@@ -326,5 +336,8 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
ppc_md.log_error(buf, err_type, fatal);
}
+void generic_suspend_disable_irqs(void);
+void generic_suspend_enable_irqs(void);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MACHDEP_H */
--
1.5.3.7
^ permalink raw reply related
* Re: cpu frequency governor regression (?)
From: Dave Jones @ 2007-12-12 17:30 UTC (permalink / raw)
To: Johannes Berg; +Cc: Rafael J. Wysocki, linuxppc-dev list, linux-pm, cpufreq
In-Reply-To: <1197399165.2214.15.camel@johannes.berg>
On Tue, Dec 11, 2007 at 07:52:45PM +0100, Johannes Berg wrote:
> Hi,
>
> No idea who to bother with this and maybe it's just a
> misconfiguration... Apologies if my guesses are totally wrong.
>
> I'm currently on 2.6.24-rc3 (+wireless-2.6#everything) but couldn't find
> any patches between that and 2.6.24-rc5 that seemed relevant.
>
> On my quad powermac, I'm seeing the cpufreq governor changed by a
> hibernation cycle. My default governor is "userspace", which is driven
> by powernowd (because the latency is too high "ondemand" doesn't like my
> machine) but after a hibernation cycle I'm having the governor set to
> "performance".
bizarre. It should default back to whatever CONFIG_CPU_FREQ_DEFAULT_* option
was set. (Arguably a bug in itself, as we don't track & restore them
on resume, so if you changed from the default after booting: splat)
Why you're getting the performance governor is puzzling though.
Can you enable CONFIG_CPU_FREQ_DEBUG=y, and boot with cpufreq.debug=7
and send the log from a transition across hibernate?
Also, does /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
have performance in *all* the cpus?
Dave
--
http://www.codemonkey.org.uk
^ permalink raw reply
* RE: Linux 2.6 from git.xilinx and XUPV2P
From: Stephen Neuendorffer @ 2007-12-12 17:19 UTC (permalink / raw)
To: greenlean, linuxppc-embedded
In-Reply-To: <14299307.post@talk.nabble.com>
The xparameters file is specific to your hardware design.
You should change the name of the generated xparameters file to match
xparameters_xupv2p.h=20
Unfortunately, it's sort of an historical artifact that it was done this
way... In reality, all the different xparameters files should really
just be one, since only one can be active at a time.
The last error sounds like you haven't actually generated an elf file?
have you tried running objdump on it?
Steve
> -----Original Message-----
> From:=20
> linuxppc-embedded-bounces+stephen=3Dneuendorffer.name@ozlabs.org
> =20
> [mailto:linuxppc-embedded-bounces+stephen=3Dneuendorffer.name@oz
> labs.org] On Behalf Of greenlean
> Sent: Wednesday, December 12, 2007 9:05 AM
> To: linuxppc-embedded@ozlabs.org
> Subject: Re: Linux 2.6 from git.xilinx and XUPV2P
>=20
>=20
>=20
>=20
> greenlean wrote:
> >=20
> > Thanks both for the response, I've allready visited some of=20
> the links.=20
> >=20
> > Yes, you was right it's easear than I think, my problem was=20
> the .config
> > file. Now, I have generated it from ml300_defconfig and=20
> after some changes
> > it compiles, but I've two question:
> >=20
> > * I've chosen as platform the XUPV2P in Machine Type,=20
> instead of ML300,
> > so the xparameters file that I'm using is the=20
> xparameters_xupv2p.h, but
> > the xparameters file generated by the EDK is=20
> xparameters_ml300 despite I
> > told it to use XUPV2P, so I can't overwrite it...=20
> >=20
> > Should I use the xparameters_ml300 generated by EDK or the
> > xparameters_xupv2p included in the git kernel tree?. I=20
> can't compile with
> > the edk's xparameters_ml300 file because there's some=20
> definition that the
> > compiler can't find, so I'm using the xparameters_xupv2p.
> >=20
> > * Second, if I compile using the xparameters_xupv2p, when=20
> I do the dow
> > command to download the image to the board, the xmd shell tell me:
> > =20
> > XMD% dow zImage.elf
> > Failed to download ELF file
> >=20
> > ERROR(1053): UNABLE to Read Elf File. The Elf File=20
> Maybe Corrupted
> > : zImage.elf
> > Maybe this error is due to the above asumption??. I'll post=20
> this second
> > one on xilinx-support maybe it's realted with my system.....
> >=20
> >=20
> >=20
>=20
> --=20
> View this message in context:=20
> http://www.nabble.com/Linux-2.6-from-git.xilinx-and-XUPV2P-tp1
> 4274035p14299307.html
> Sent from the linuxppc-embedded mailing list archive at Nabble.com.
>=20
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>=20
>=20
^ permalink raw reply
* cpu frequency governor regression (?)
From: Johannes Berg @ 2007-12-11 18:52 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: davej, linuxppc-dev list, linux-pm, cpufreq
[-- Attachment #1: Type: text/plain, Size: 877 bytes --]
Hi,
No idea who to bother with this and maybe it's just a
misconfiguration... Apologies if my guesses are totally wrong.
I'm currently on 2.6.24-rc3 (+wireless-2.6#everything) but couldn't find
any patches between that and 2.6.24-rc5 that seemed relevant.
On my quad powermac, I'm seeing the cpufreq governor changed by a
hibernation cycle. My default governor is "userspace", which is driven
by powernowd (because the latency is too high "ondemand" doesn't like my
machine) but after a hibernation cycle I'm having the governor set to
"performance".
I have no idea what code is resetting this and why this would happen,
maybe the fact that the CPUs are taken offline/online again is
responsible? It's well possible that there's a bug in our cpufreq driver
though I thought I fixed the multi-cpu issues it had. Any help would be
appreciated.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: [PATCH RFC 1/7] [POWERPC] Implement GPIO API embryo
From: Anton Vorontsov @ 2007-12-12 17:10 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20071212164847.GC4329@loki.buserror.net>
On Wed, Dec 12, 2007 at 10:48:47AM -0600, Scott Wood wrote:
> On Mon, Dec 10, 2007 at 11:48:25PM +0300, Anton Vorontsov wrote:
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 232c298..596982f 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -73,6 +73,10 @@ config GENERIC_FIND_NEXT_BIT
> > bool
> > default y
> >
> > +config GENERIC_GPIO
> > + bool
> > + default n
> > +
>
> default n is the default. No need to explicitly state it.
Thanks, fill fix.
> > +
> > +int __of_parse_gpio_bank_pin(struct device_node *np, int index,
> > + int bank_width, int max_bank)
>
> Why the leading underscores?
This is low-level helper/library function, used by gpio controllers to
parse "bank pin" gpio = <> scheme. To denote that this isn't some kind
of API leading underscores are used.
> > diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h
> > new file mode 100644
> > index 0000000..f7513ff
> > --- /dev/null
> > +++ b/include/asm-powerpc/gpio.h
> > @@ -0,0 +1,51 @@
> > +/*
> > + * Generic GPIO API implementation for PowerPC.
>
> Is there anything really powerpc specific here, or should it go under
> drivers/of?
Because <asm/gpio.h> should be used by all architectures to match
generic GPIO API. asm-sh/gpio.h asm-arm/gpio.h asm-avr32/gpio.h
and so on.
The only thing I can place into of.h is
- - - -
/*
* OF specific gpio_chip handler.
*/
struct of_gpio_chip {
int (*xlate)(struct device_node *np, int index);
};
- - - -
But frankly speaking, of_gpio_chip could be architecture-specific
too.
--
Anton Vorontsov
email: cbou@mail.ru
backup email: ya-cbou@yandex.ru
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: Linux 2.6 from git.xilinx and XUPV2P
From: greenlean @ 2007-12-12 17:05 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <14274035.post@talk.nabble.com>
greenlean wrote:
>
> Thanks both for the response, I've allready visited some of the links.
>
> Yes, you was right it's easear than I think, my problem was the .config
> file. Now, I have generated it from ml300_defconfig and after some changes
> it compiles, but I've two question:
>
> * I've chosen as platform the XUPV2P in Machine Type, instead of ML300,
> so the xparameters file that I'm using is the xparameters_xupv2p.h, but
> the xparameters file generated by the EDK is xparameters_ml300 despite I
> told it to use XUPV2P, so I can't overwrite it...
>
> Should I use the xparameters_ml300 generated by EDK or the
> xparameters_xupv2p included in the git kernel tree?. I can't compile with
> the edk's xparameters_ml300 file because there's some definition that the
> compiler can't find, so I'm using the xparameters_xupv2p.
>
> * Second, if I compile using the xparameters_xupv2p, when I do the dow
> command to download the image to the board, the xmd shell tell me:
>
> XMD% dow zImage.elf
> Failed to download ELF file
>
> ERROR(1053): UNABLE to Read Elf File. The Elf File Maybe Corrupted
> : zImage.elf
> Maybe this error is due to the above asumption??. I'll post this second
> one on xilinx-support maybe it's realted with my system.....
>
>
>
--
View this message in context: http://www.nabble.com/Linux-2.6-from-git.xilinx-and-XUPV2P-tp14274035p14299307.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [RFC] ehea: kdump support using new shutdown hook
From: Dave Jones @ 2007-12-12 17:04 UTC (permalink / raw)
To: Thomas Klein
Cc: Michael Neuling, Jan-Bernd Themann, netdev, linux-kernel,
linux-ppc, Christoph Raisch, Paul Mackerras, Marcus Eder,
Stefan Roscher
In-Reply-To: <200712121753.43543.osstklei@de.ibm.com>
On Wed, Dec 12, 2007 at 05:53:43PM +0100, Thomas Klein wrote:
> +static void ehea_update_adapter_handles(struct ehea_adapter *adapter)
> +{
> + int i, k;
> + int j = 0;
> +
> + memset(adapter->res_handles, sizeof(adapter->res_handles), 0);
arguments wrong way around.
Dave
--
http://www.codemonkey.org.uk
^ permalink raw reply
* Re: [PATCH RFC 7/7] [POWERPC] MPC8360E-RDK: add support for NAND on UPM
From: Scott Wood @ 2007-12-12 16:59 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev
In-Reply-To: <20071210204951.GG32278@localhost.localdomain>
On Mon, Dec 10, 2007 at 11:49:51PM +0300, Anton Vorontsov wrote:
> + localbus@e0005000 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "fsl,mpc8360erdk-localbus",
> + "fsl,mpc8360e-localbus",
> + "fsl,pq2pro-localbus";
The board name shouldn't be in there.
> + reg = <0xe0005000 0xd8>;
> + ranges = <1 0 0x60000000 1>;
> +
> + nand-flash@1,0 {
> + compatible = "STMicro,NAND512W3A2BN6E", "fsl,upm-nand";
Technically, if the vendor part begins with a capital letter it's supposed
to be either a stock symbol or an OUI.
-Scott
^ 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