[RFC PATCH] MIPS: Alchemy: sysdem for DBDMA PM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a sysdev for DBDMA PM.

Signed-off-by: Manuel Lauss <manuel.lauss@xxxxxxxxx>
---
Tested on DB1200 (STR while playing audio and SD card activity works fine).

Will probably throw rejects in power.c, hence the RFC.

 arch/mips/alchemy/common/dbdma.c                 |  101 +++++++++++++++------
 arch/mips/alchemy/common/power.c                 |   11 ---
 arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h |    4 -
 3 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 99ae84c..ca0506a 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;
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index cbc9eed..e5916a5 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -36,9 +36,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/mach-au1x00/au1000.h>
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
-#endif
 
 #ifdef CONFIG_PM
 
@@ -108,10 +105,6 @@ static void save_core_regs(void)
 	sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
 	sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
 	sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
-
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-	au1xxx_dbdma_suspend();
-#endif
 }
 
 static void restore_core_regs(void)
@@ -161,10 +154,6 @@ static void restore_core_regs(void)
 	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
 	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
 	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
-
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
-	au1xxx_dbdma_resume();
-#endif
 }
 
 void au_sleep(void)
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
index 8c6b110..c8a553a 100644
--- a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
@@ -358,10 +358,6 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr);
 u32 au1xxx_ddma_add_device(dbdev_tab_t *dev);
 extern void au1xxx_ddma_del_device(u32 devid);
 void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp);
-#ifdef CONFIG_PM
-void au1xxx_dbdma_suspend(void);
-void au1xxx_dbdma_resume(void);
-#endif
 
 /*
  *	Flags for the put_source/put_dest functions.
-- 
1.7.0.4



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux