summaryrefslogtreecommitdiffstats
path: root/arch/mips/alchemy/common/dbdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/alchemy/common/dbdma.c')
-rw-r--r--arch/mips/alchemy/common/dbdma.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 99ae84ce5af..ca0506a8585 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -36,6 +36,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/sysdev.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -174,10 +175,6 @@ static dbdev_tab_t dbdev_tab[] = {
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
-#ifdef CONFIG_PM
-static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][6];
-#endif
-
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
@@ -960,29 +957,37 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
return nbytes;
}
-#ifdef CONFIG_PM
-void au1xxx_dbdma_suspend(void)
+
+struct alchemy_dbdma_sysdev {
+ struct sys_device sysdev;
+ u32 pm_regs[NUM_DBDMA_CHANS + 1][6];
+};
+
+static int alchemy_dbdma_suspend(struct sys_device *dev,
+ pm_message_t state)
{
+ struct alchemy_dbdma_sysdev *sdev =
+ container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
- au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
- au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
- au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
- au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
+ sdev->pm_regs[0][0] = au_readl(addr + 0x00);
+ sdev->pm_regs[0][1] = au_readl(addr + 0x04);
+ sdev->pm_regs[0][2] = au_readl(addr + 0x08);
+ sdev->pm_regs[0][3] = au_readl(addr + 0x0c);
/* save channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
- au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
- au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
- au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
- au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
- au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
- au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
+ sdev->pm_regs[i][0] = au_readl(addr + 0x00);
+ sdev->pm_regs[i][1] = au_readl(addr + 0x04);
+ sdev->pm_regs[i][2] = au_readl(addr + 0x08);
+ sdev->pm_regs[i][3] = au_readl(addr + 0x0c);
+ sdev->pm_regs[i][4] = au_readl(addr + 0x10);
+ sdev->pm_regs[i][5] = au_readl(addr + 0x14);
/* halt channel */
- au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
+ au_writel(sdev->pm_regs[i][0] & ~1, addr + 0x00);
au_sync();
while (!(au_readl(addr + 0x14) & 1))
au_sync();
@@ -992,32 +997,65 @@ void au1xxx_dbdma_suspend(void)
/* disable channel interrupts */
au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
au_sync();
+
+ return 0;
}
-void au1xxx_dbdma_resume(void)
+static int alchemy_dbdma_resume(struct sys_device *dev)
{
+ struct alchemy_dbdma_sysdev *sdev =
+ container_of(dev, struct alchemy_dbdma_sysdev, sysdev);
int i;
u32 addr;
addr = DDMA_GLOBAL_BASE;
- au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
- au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
- au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
- au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
+ au_writel(sdev->pm_regs[0][0], addr + 0x00);
+ au_writel(sdev->pm_regs[0][1], addr + 0x04);
+ au_writel(sdev->pm_regs[0][2], addr + 0x08);
+ au_writel(sdev->pm_regs[0][3], addr + 0x0c);
/* restore channel configurations */
for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
- au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
- au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
- au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
- au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
- au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
- au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
+ au_writel(sdev->pm_regs[i][0], addr + 0x00);
+ au_writel(sdev->pm_regs[i][1], addr + 0x04);
+ au_writel(sdev->pm_regs[i][2], addr + 0x08);
+ au_writel(sdev->pm_regs[i][3], addr + 0x0c);
+ au_writel(sdev->pm_regs[i][4], addr + 0x10);
+ au_writel(sdev->pm_regs[i][5], addr + 0x14);
au_sync();
addr += 0x100; /* next channel base */
}
+
+ return 0;
+}
+
+static struct sysdev_class alchemy_dbdma_sysdev_class = {
+ .name = "dbdma",
+ .suspend = alchemy_dbdma_suspend,
+ .resume = alchemy_dbdma_resume,
+};
+
+static int __init alchemy_dbdma_sysdev_init(void)
+{
+ struct alchemy_dbdma_sysdev *sdev;
+ int ret;
+
+ ret = sysdev_class_register(&alchemy_dbdma_sysdev_class);
+ if (ret)
+ return ret;
+
+ sdev = kzalloc(sizeof(struct alchemy_dbdma_sysdev), GFP_KERNEL);
+ if (!sdev)
+ return -ENOMEM;
+
+ sdev->sysdev.id = -1;
+ sdev->sysdev.cls = &alchemy_dbdma_sysdev_class;
+ ret = sysdev_register(&sdev->sysdev);
+ if (ret)
+ kfree(sdev);
+
+ return ret;
}
-#endif /* CONFIG_PM */
static int __init au1xxx_dbdma_init(void)
{
@@ -1046,6 +1084,11 @@ static int __init au1xxx_dbdma_init(void)
else {
dbdma_initialized = 1;
printk(KERN_INFO "Alchemy DBDMA initialized\n");
+ ret = alchemy_dbdma_sysdev_init();
+ if (ret) {
+ printk(KERN_ERR "DBDMA PM init failed\n");
+ ret = 0;
+ }
}
return ret;