Skip to content

Commit

Permalink
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-…
Browse files Browse the repository at this point in the history
…linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (25 commits)
  MIPS: Use GCC __builtin_prefetch() to implement prefetch().
  MIPS: Octeon: Serial port fixes for OCTEON simulator.
  MIPS: Octeon: Get rid of early serial.
  MIPS: AR7: prevent race between clock initialization and devices registration
  MIPS: AR7: use ar7_has_high_vlynq() to determine watchdog base address
  MIPS: BCM63xx: Avoid namespace clash on GPIO_DIR_{IN,OUT}
  MIPS: MTX-1: Update defconfig
  MIPS: BCM47xx: Update defconfig
  MIPS: RB532: Update defconfig
  MIPS: AR7: Update defconfig
  RTC: rtc-cmos: Fix binary mode support
  MIPS: Oprofile: Loongson: Cleanup the comments
  MIPS: Oprofile: Loongson: Cleanup of the macros
  MIPS: Oprofile: Loongson: Remove unused variable from loongson2_cpu_setup()
  MIPS: Oprofile: Loongson: Remove useless parentheses
  MIPS: Oprofile: Loongson: Unify macro for setting events
  MIPS: nofpu and nodsp only affect CPU0
  MIPS: Clean up tables for bootmem allocation
  MIPS: Coding style cleanups of access of FCSR rounding mode bits
  MIPS: Loongson 2F: Add gpio/gpioilb support
  ...
  • Loading branch information
Linus Torvalds committed May 21, 2010
2 parents 0fc377b + 0453fb3 commit 6969a43
Show file tree
Hide file tree
Showing 38 changed files with 3,355 additions and 3,789 deletions.
2 changes: 2 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,8 @@ config CPU_LOONGSON2F
bool "Loongson 2F"
depends on SYS_HAS_CPU_LOONGSON2F
select CPU_LOONGSON2
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
The Loongson 2F processor implements the MIPS III instruction set
with many extensions.
Expand Down
101 changes: 72 additions & 29 deletions arch/mips/alchemy/common/dbdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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();
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down
174 changes: 90 additions & 84 deletions arch/mips/alchemy/common/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/sysdev.h>

#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
Expand Down Expand Up @@ -216,90 +218,6 @@ struct au1xxx_irqmap au1200_irqmap[] __initdata = {
};


#ifdef CONFIG_PM

/*
* Save/restore the interrupt controller state.
* Called from the save/restore core registers as part of the
* au_sleep function in power.c.....maybe I should just pm_register()
* them instead?
*/
static unsigned int sleep_intctl_config0[2];
static unsigned int sleep_intctl_config1[2];
static unsigned int sleep_intctl_config2[2];
static unsigned int sleep_intctl_src[2];
static unsigned int sleep_intctl_assign[2];
static unsigned int sleep_intctl_wake[2];
static unsigned int sleep_intctl_mask[2];

void save_au1xxx_intctl(void)
{
sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
sleep_intctl_src[0] = au_readl(IC0_SRCRD);
sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
sleep_intctl_mask[0] = au_readl(IC0_MASKRD);

sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
sleep_intctl_src[1] = au_readl(IC1_SRCRD);
sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
}

/*
* For most restore operations, we clear the entire register and
* then set the bits we found during the save.
*/
void restore_au1xxx_intctl(void)
{
au_writel(0xffffffff, IC0_MASKCLR); au_sync();

au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
au_writel(0xffffffff, IC0_SRCCLR); au_sync();
au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
au_writel(0xffffffff, IC0_WAKECLR); au_sync();
au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
au_writel(0x00000000, IC0_TESTBIT); au_sync();

au_writel(0xffffffff, IC1_MASKCLR); au_sync();

au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
au_writel(0xffffffff, IC1_SRCCLR); au_sync();
au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
au_writel(0xffffffff, IC1_WAKECLR); au_sync();
au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
au_writel(0x00000000, IC1_TESTBIT); au_sync();

au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();

au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
}
#endif /* CONFIG_PM */


static void au1x_ic0_unmask(unsigned int irq_nr)
{
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
Expand Down Expand Up @@ -635,3 +553,91 @@ void __init arch_init_irq(void)
break;
}
}

struct alchemy_ic_sysdev {
struct sys_device sysdev;
void __iomem *base;
unsigned long pmdata[7];
};

static int alchemy_ic_suspend(struct sys_device *dev, pm_message_t state)
{
struct alchemy_ic_sysdev *icdev =
container_of(dev, struct alchemy_ic_sysdev, sysdev);

icdev->pmdata[0] = __raw_readl(icdev->base + IC_CFG0RD);
icdev->pmdata[1] = __raw_readl(icdev->base + IC_CFG1RD);
icdev->pmdata[2] = __raw_readl(icdev->base + IC_CFG2RD);
icdev->pmdata[3] = __raw_readl(icdev->base + IC_SRCRD);
icdev->pmdata[4] = __raw_readl(icdev->base + IC_ASSIGNRD);
icdev->pmdata[5] = __raw_readl(icdev->base + IC_WAKERD);
icdev->pmdata[6] = __raw_readl(icdev->base + IC_MASKRD);

return 0;
}

static int alchemy_ic_resume(struct sys_device *dev)
{
struct alchemy_ic_sysdev *icdev =
container_of(dev, struct alchemy_ic_sysdev, sysdev);

__raw_writel(0xffffffff, icdev->base + IC_MASKCLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG0CLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG1CLR);
__raw_writel(0xffffffff, icdev->base + IC_CFG2CLR);
__raw_writel(0xffffffff, icdev->base + IC_SRCCLR);
__raw_writel(0xffffffff, icdev->base + IC_ASSIGNCLR);
__raw_writel(0xffffffff, icdev->base + IC_WAKECLR);
__raw_writel(0xffffffff, icdev->base + IC_RISINGCLR);
__raw_writel(0xffffffff, icdev->base + IC_FALLINGCLR);
__raw_writel(0x00000000, icdev->base + IC_TESTBIT);
wmb();
__raw_writel(icdev->pmdata[0], icdev->base + IC_CFG0SET);
__raw_writel(icdev->pmdata[1], icdev->base + IC_CFG1SET);
__raw_writel(icdev->pmdata[2], icdev->base + IC_CFG2SET);
__raw_writel(icdev->pmdata[3], icdev->base + IC_SRCSET);
__raw_writel(icdev->pmdata[4], icdev->base + IC_ASSIGNSET);
__raw_writel(icdev->pmdata[5], icdev->base + IC_WAKESET);
wmb();

__raw_writel(icdev->pmdata[6], icdev->base + IC_MASKSET);
wmb();

return 0;
}

static struct sysdev_class alchemy_ic_sysdev_class = {
.name = "ic",
.suspend = alchemy_ic_suspend,
.resume = alchemy_ic_resume,
};

static int __init alchemy_ic_sysdev_init(void)
{
struct alchemy_ic_sysdev *icdev;
unsigned long icbase[2] = { IC0_PHYS_ADDR, IC1_PHYS_ADDR };
int err, i;

err = sysdev_class_register(&alchemy_ic_sysdev_class);
if (err)
return err;

for (i = 0; i < 2; i++) {
icdev = kzalloc(sizeof(struct alchemy_ic_sysdev), GFP_KERNEL);
if (!icdev)
return -ENOMEM;

icdev->base = ioremap(icbase[i], 0x1000);

icdev->sysdev.id = i;
icdev->sysdev.cls = &alchemy_ic_sysdev_class;
err = sysdev_register(&icdev->sysdev);
if (err) {
kfree(icdev);
return err;
}
}

return 0;
}
device_initcall(alchemy_ic_sysdev_init);
Loading

0 comments on commit 6969a43

Please sign in to comment.