Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Alchemy: add sysdev for IRQ PM.

Use a sysdev to implement PM methods for the Au1000 interrupt controllers.

Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
To: Linux-MIPS <linux-mips@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/1114/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Manuel Lauss and committed by
Ralf Baechle
0f0d85bc 7b5fcd69

+122 -91
+90 -84
arch/mips/alchemy/common/irq.c
··· 29 29 #include <linux/init.h> 30 30 #include <linux/interrupt.h> 31 31 #include <linux/irq.h> 32 + #include <linux/slab.h> 33 + #include <linux/sysdev.h> 32 34 33 35 #include <asm/irq_cpu.h> 34 36 #include <asm/mipsregs.h> ··· 216 214 { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, 217 215 { -1, }, 218 216 }; 219 - 220 - 221 - #ifdef CONFIG_PM 222 - 223 - /* 224 - * Save/restore the interrupt controller state. 225 - * Called from the save/restore core registers as part of the 226 - * au_sleep function in power.c.....maybe I should just pm_register() 227 - * them instead? 228 - */ 229 - static unsigned int sleep_intctl_config0[2]; 230 - static unsigned int sleep_intctl_config1[2]; 231 - static unsigned int sleep_intctl_config2[2]; 232 - static unsigned int sleep_intctl_src[2]; 233 - static unsigned int sleep_intctl_assign[2]; 234 - static unsigned int sleep_intctl_wake[2]; 235 - static unsigned int sleep_intctl_mask[2]; 236 - 237 - void save_au1xxx_intctl(void) 238 - { 239 - sleep_intctl_config0[0] = au_readl(IC0_CFG0RD); 240 - sleep_intctl_config1[0] = au_readl(IC0_CFG1RD); 241 - sleep_intctl_config2[0] = au_readl(IC0_CFG2RD); 242 - sleep_intctl_src[0] = au_readl(IC0_SRCRD); 243 - sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD); 244 - sleep_intctl_wake[0] = au_readl(IC0_WAKERD); 245 - sleep_intctl_mask[0] = au_readl(IC0_MASKRD); 246 - 247 - sleep_intctl_config0[1] = au_readl(IC1_CFG0RD); 248 - sleep_intctl_config1[1] = au_readl(IC1_CFG1RD); 249 - sleep_intctl_config2[1] = au_readl(IC1_CFG2RD); 250 - sleep_intctl_src[1] = au_readl(IC1_SRCRD); 251 - sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD); 252 - sleep_intctl_wake[1] = au_readl(IC1_WAKERD); 253 - sleep_intctl_mask[1] = au_readl(IC1_MASKRD); 254 - } 255 - 256 - /* 257 - * For most restore operations, we clear the entire register and 258 - * then set the bits we found during the save. 259 - */ 260 - void restore_au1xxx_intctl(void) 261 - { 262 - au_writel(0xffffffff, IC0_MASKCLR); au_sync(); 263 - 264 - au_writel(0xffffffff, IC0_CFG0CLR); au_sync(); 265 - au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync(); 266 - au_writel(0xffffffff, IC0_CFG1CLR); au_sync(); 267 - au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync(); 268 - au_writel(0xffffffff, IC0_CFG2CLR); au_sync(); 269 - au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync(); 270 - au_writel(0xffffffff, IC0_SRCCLR); au_sync(); 271 - au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync(); 272 - au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync(); 273 - au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync(); 274 - au_writel(0xffffffff, IC0_WAKECLR); au_sync(); 275 - au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync(); 276 - au_writel(0xffffffff, IC0_RISINGCLR); au_sync(); 277 - au_writel(0xffffffff, IC0_FALLINGCLR); au_sync(); 278 - au_writel(0x00000000, IC0_TESTBIT); au_sync(); 279 - 280 - au_writel(0xffffffff, IC1_MASKCLR); au_sync(); 281 - 282 - au_writel(0xffffffff, IC1_CFG0CLR); au_sync(); 283 - au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync(); 284 - au_writel(0xffffffff, IC1_CFG1CLR); au_sync(); 285 - au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync(); 286 - au_writel(0xffffffff, IC1_CFG2CLR); au_sync(); 287 - au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync(); 288 - au_writel(0xffffffff, IC1_SRCCLR); au_sync(); 289 - au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync(); 290 - au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync(); 291 - au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync(); 292 - au_writel(0xffffffff, IC1_WAKECLR); au_sync(); 293 - au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync(); 294 - au_writel(0xffffffff, IC1_RISINGCLR); au_sync(); 295 - au_writel(0xffffffff, IC1_FALLINGCLR); au_sync(); 296 - au_writel(0x00000000, IC1_TESTBIT); au_sync(); 297 - 298 - au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync(); 299 - 300 - au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync(); 301 - } 302 - #endif /* CONFIG_PM */ 303 217 304 218 305 219 static void au1x_ic0_unmask(unsigned int irq_nr) ··· 553 635 break; 554 636 } 555 637 } 638 + 639 + struct alchemy_ic_sysdev { 640 + struct sys_device sysdev; 641 + void __iomem *base; 642 + unsigned long pmdata[7]; 643 + }; 644 + 645 + static int alchemy_ic_suspend(struct sys_device *dev, pm_message_t state) 646 + { 647 + struct alchemy_ic_sysdev *icdev = 648 + container_of(dev, struct alchemy_ic_sysdev, sysdev); 649 + 650 + icdev->pmdata[0] = __raw_readl(icdev->base + IC_CFG0RD); 651 + icdev->pmdata[1] = __raw_readl(icdev->base + IC_CFG1RD); 652 + icdev->pmdata[2] = __raw_readl(icdev->base + IC_CFG2RD); 653 + icdev->pmdata[3] = __raw_readl(icdev->base + IC_SRCRD); 654 + icdev->pmdata[4] = __raw_readl(icdev->base + IC_ASSIGNRD); 655 + icdev->pmdata[5] = __raw_readl(icdev->base + IC_WAKERD); 656 + icdev->pmdata[6] = __raw_readl(icdev->base + IC_MASKRD); 657 + 658 + return 0; 659 + } 660 + 661 + static int alchemy_ic_resume(struct sys_device *dev) 662 + { 663 + struct alchemy_ic_sysdev *icdev = 664 + container_of(dev, struct alchemy_ic_sysdev, sysdev); 665 + 666 + __raw_writel(0xffffffff, icdev->base + IC_MASKCLR); 667 + __raw_writel(0xffffffff, icdev->base + IC_CFG0CLR); 668 + __raw_writel(0xffffffff, icdev->base + IC_CFG1CLR); 669 + __raw_writel(0xffffffff, icdev->base + IC_CFG2CLR); 670 + __raw_writel(0xffffffff, icdev->base + IC_SRCCLR); 671 + __raw_writel(0xffffffff, icdev->base + IC_ASSIGNCLR); 672 + __raw_writel(0xffffffff, icdev->base + IC_WAKECLR); 673 + __raw_writel(0xffffffff, icdev->base + IC_RISINGCLR); 674 + __raw_writel(0xffffffff, icdev->base + IC_FALLINGCLR); 675 + __raw_writel(0x00000000, icdev->base + IC_TESTBIT); 676 + wmb(); 677 + __raw_writel(icdev->pmdata[0], icdev->base + IC_CFG0SET); 678 + __raw_writel(icdev->pmdata[1], icdev->base + IC_CFG1SET); 679 + __raw_writel(icdev->pmdata[2], icdev->base + IC_CFG2SET); 680 + __raw_writel(icdev->pmdata[3], icdev->base + IC_SRCSET); 681 + __raw_writel(icdev->pmdata[4], icdev->base + IC_ASSIGNSET); 682 + __raw_writel(icdev->pmdata[5], icdev->base + IC_WAKESET); 683 + wmb(); 684 + 685 + __raw_writel(icdev->pmdata[6], icdev->base + IC_MASKSET); 686 + wmb(); 687 + 688 + return 0; 689 + } 690 + 691 + static struct sysdev_class alchemy_ic_sysdev_class = { 692 + .name = "ic", 693 + .suspend = alchemy_ic_suspend, 694 + .resume = alchemy_ic_resume, 695 + }; 696 + 697 + static int __init alchemy_ic_sysdev_init(void) 698 + { 699 + struct alchemy_ic_sysdev *icdev; 700 + unsigned long icbase[2] = { IC0_PHYS_ADDR, IC1_PHYS_ADDR }; 701 + int err, i; 702 + 703 + err = sysdev_class_register(&alchemy_ic_sysdev_class); 704 + if (err) 705 + return err; 706 + 707 + for (i = 0; i < 2; i++) { 708 + icdev = kzalloc(sizeof(struct alchemy_ic_sysdev), GFP_KERNEL); 709 + if (!icdev) 710 + return -ENOMEM; 711 + 712 + icdev->base = ioremap(icbase[i], 0x1000); 713 + 714 + icdev->sysdev.id = i; 715 + icdev->sysdev.cls = &alchemy_ic_sysdev_class; 716 + err = sysdev_register(&icdev->sysdev); 717 + if (err) { 718 + kfree(icdev); 719 + return err; 720 + } 721 + } 722 + 723 + return 0; 724 + } 725 + device_initcall(alchemy_ic_sysdev_init);
-5
arch/mips/alchemy/common/power.c
··· 106 106 sleep_usb[1] = au_readl(0xb4020024); /* OTG_MUX */ 107 107 #endif 108 108 109 - /* Save interrupt controller state. */ 110 - save_au1xxx_intctl(); 111 - 112 109 /* Clocks and PLLs. */ 113 110 sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0); 114 111 sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1); ··· 196 199 au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync(); 197 200 au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync(); 198 201 } 199 - 200 - restore_au1xxx_intctl(); 201 202 202 203 #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) 203 204 au1xxx_dbdma_resume();
+32 -2
arch/mips/include/asm/mach-au1x00/au1000.h
··· 190 190 /* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */ 191 191 void au1xxx_save_and_sleep(void); 192 192 void au_sleep(void); 193 - void save_au1xxx_intctl(void); 194 - void restore_au1xxx_intctl(void); 195 193 196 194 197 195 /* SOC Interrupt numbers */ ··· 832 834 #define MEM_STNAND_ADDR 0x4 833 835 #define MEM_STNAND_DATA 0x20 834 836 #endif 837 + 838 + 839 + /* Interrupt Controller register offsets */ 840 + #define IC_CFG0RD 0x40 841 + #define IC_CFG0SET 0x40 842 + #define IC_CFG0CLR 0x44 843 + #define IC_CFG1RD 0x48 844 + #define IC_CFG1SET 0x48 845 + #define IC_CFG1CLR 0x4C 846 + #define IC_CFG2RD 0x50 847 + #define IC_CFG2SET 0x50 848 + #define IC_CFG2CLR 0x54 849 + #define IC_REQ0INT 0x54 850 + #define IC_SRCRD 0x58 851 + #define IC_SRCSET 0x58 852 + #define IC_SRCCLR 0x5C 853 + #define IC_REQ1INT 0x5C 854 + #define IC_ASSIGNRD 0x60 855 + #define IC_ASSIGNSET 0x60 856 + #define IC_ASSIGNCLR 0x64 857 + #define IC_WAKERD 0x68 858 + #define IC_WAKESET 0x68 859 + #define IC_WAKECLR 0x6C 860 + #define IC_MASKRD 0x70 861 + #define IC_MASKSET 0x70 862 + #define IC_MASKCLR 0x74 863 + #define IC_RISINGRD 0x78 864 + #define IC_RISINGCLR 0x78 865 + #define IC_FALLINGRD 0x7C 866 + #define IC_FALLINGCLR 0x7C 867 + #define IC_TESTBIT 0x80 868 + 835 869 836 870 /* Interrupt Controller 0 */ 837 871 #define IC0_CFG0RD 0xB0400040