📄 au1xxx_pm.patch
字号:
+ au_writel(sleep_ddma[0][3],addr+0xC);++ for(i=1,addr=DDMA_CHANNEL_BASE; i<NUM_DBDMA_CHANS; i++, addr+=0x100 ) {+ au_writel( sleep_ddma[i][0], addr+0x0);+ au_writel( sleep_ddma[i][1], addr+0x4);+ au_writel( sleep_ddma[i][2], addr+0x8);+ au_writel( sleep_ddma[i][3], addr+0xC);+ au_writel( sleep_ddma[i][4], addr+0x10);+ au_writel( sleep_ddma[i][5], addr+0x14);+ au_writel( sleep_ddma[i][6], addr+0x18);+ }++ /* Restore Programmable Serial Controller registers */+ for (i = 0, addr = PSC0_BASE_ADDR; addr < (PSC0_BASE_ADDR + 0x30); i++, addr += 0x04)+ au_writel(sleep_psc[0][i], addr);+ for (i = 0, addr = PSC1_BASE_ADDR; addr < (PSC1_BASE_ADDR + 0x30); i++, addr += 0x04)+ au_writel(sleep_psc[1][i], addr);+ + au_writel(sleep_sys_clksrc , SYS_CLKSRC);+ au_writel(sleep_sys_freqctl0, SYS_FREQCTRL0);+ au_writel(sleep_sys_freqctl1, SYS_FREQCTRL1);++ if (au_readl(PSC0_BASE_ADDR+0x04) == 0x03) {+ u32 stat0;+ do {+ stat0 = au_readl(PSC0_BASE_ADDR+0x14);+ } while ((stat0 & PSC_SMBSTAT_SR) == 0);+ } + + DPRINTK("Restoring MAE FE regs\n");+ /* Save MAE front end registers */+ addr = 0xb4012000;+ au_writel(sleep_mae[0], addr + 0x0000);+ au_writel(sleep_mae[1], addr + 0x0004);+ au_writel(sleep_mae[2], addr + 0x0008);+ au_writel(sleep_mae[3], addr + 0x000C);+ au_writel(sleep_mae[4], addr + 0x0010);+ au_writel(sleep_mae[5], addr + 0x0014);+ au_writel(sleep_mae[6], addr + 0x0018);+ au_writel(sleep_mae[7], addr + 0x001C);+ au_writel(sleep_mae[8], addr + 0x0020);+ au_writel(sleep_mae[9], addr + 0x0024);+ au_writel(sleep_mae[10], addr + 0x0028);+ au_writel(sleep_mae[11], addr + 0x002C);+ au_writel(sleep_mae[12], addr + 0x0038);+ au_writel(sleep_mae[13], addr + 0x003C);+ au_writel(sleep_mae[14], addr + 0x0040);+ au_writel(sleep_mae[15], addr + 0x0044);+ au_writel(sleep_mae[16], addr + 0x0048);+ au_writel(sleep_mae[17], addr + 0x004C);+ au_writel(sleep_mae[18], addr + 0x0050);+ au_writel(sleep_mae[19], addr + 0x0054);+ au_writel(sleep_mae[20], addr + 0x0058);+ au_writel(sleep_mae[21], addr + 0x005C);+ au_writel(sleep_mae[22], addr + 0x1004);+ au_writel(sleep_mae[23], addr + 0x1008);+ DPRINTK("Restoring MAE BE regs\n");+ /* Save MAE backend registers */+ addr = 0xb4010000;+ au_writel(sleep_mae[24], addr + 0x0000);+ au_writel(sleep_mae[25], addr + 0x0004);+ au_writel(sleep_mae[26], addr + 0x0008);+ au_writel(sleep_mae[27], addr + 0x0100);+ au_writel(sleep_mae[28], addr + 0x0180);+ au_writel(sleep_mae[29], addr + 0x0200);+ au_writel(sleep_mae[30], addr + 0x0280);+ au_writel(sleep_mae[31], addr + 0x0300);+ au_writel(sleep_mae[32], addr + 0x0380);+ DPRINTK("Restoring MAE CSC regs\n");+ /* CSC registers */+ au_writel(sleep_mae[33], addr + 0x0400);+ au_writel(sleep_mae[34], addr + 0x0404);+ au_writel(sleep_mae[35], addr + 0x0408);+ au_writel(sleep_mae[36], addr + 0x040C);+ au_writel(sleep_mae[37], addr + 0x0410);+ au_writel(sleep_mae[38], addr + 0x0414);+ au_writel(sleep_mae[39], addr + 0x0418);+ au_writel(sleep_mae[40], addr + 0x041C);+ au_writel(sleep_mae[41], addr + 0x0420);+ au_writel(sleep_mae[42], addr + 0x0424);+ au_writel(sleep_mae[43], addr + 0x0428);+ au_writel(sleep_mae[44], addr + 0x042C);+ au_writel(sleep_mae[45], addr + 0x0430);+ DPRINTK("Restoring MAE SRC regs\n");+ /* SRC registers */+ au_writel(sleep_mae[46], addr + 0x0500);+ au_writel(sleep_mae[47], addr + 0x0504);+ au_writel(sleep_mae[48], addr + 0x0508);+ au_writel(sleep_mae[49], addr + 0x050C);+ au_writel(sleep_mae[50], addr + 0x0510);+ au_writel(sleep_mae[51], addr + 0x0514);+ au_writel(sleep_mae[52], addr + 0x0518);+ au_writel(sleep_mae[53], addr + 0x051C);+ DPRINTK("Restoring MAE DST regs\n");+ /* DST registers */+ au_writel(sleep_mae[54], addr + 0x0600);+ au_writel(sleep_mae[55], addr + 0x0604);+ au_writel(sleep_mae[56], addr + 0x0608);+ au_writel(sleep_mae[57], addr + 0x060C);+ DPRINTK("Restoring MAE CTL regs\n");+ /* CTL registers */+ au_writel(sleep_mae[58], addr + 0x0700);+ au_writel(sleep_mae[59], addr + 0x070C);+ au_writel(sleep_mae[60], addr + 0x0710);++#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200)+ /* restore board register */+ bcsr->intclr = 0xffff; au_sync();+ bcsr->intset = sleep_bcsr_int; au_sync();+ bcsr->intclr_mask = 0xffff; au_sync();+ bcsr->intset_mask = sleep_bcsr_mask; au_sync();+ bcsr->resets = 0xffff; au_sync();+ bcsr->resets = sleep_bcsr_resets;+ bcsr->pcmcia = 0xffff; au_sync();+ bcsr->pcmcia = sleep_bcsr_pcmcia;+ bcsr->board = 0xffff; au_sync();+ bcsr->board = sleep_bcsr_boards;+#endif+ restore_au1xxx_intctl(); wakeup_kernel_timer(); }--unsigned long suspend_mode;--void wakeup_from_suspend(void)-{- suspend_mode = 0;-}--int au_sleep(void)-{+ +int au_sleep(void) { unsigned long wakeup, flags;- extern void save_and_sleep(void);+ extern unsigned int save_and_sleep(void); - spin_lock_irqsave(&pm_lock,flags);-- save_core_regs();-- flush_cache_all();-- /** The code below is all system dependent and we should probably- ** have a function call out of here to set this up. You need- ** to configure the GPIO or timer interrupts that will bring- ** you out of sleep.+ spin_lock_irqsave(&au1xxx_pm_lock,flags);+ + save_core_regs();+ + /** The code in the if-else statements below is all system dependent + ** and we should probably have a function call out of here to set + ** this up. You need to configure the GPIO or timer interrupts that + ** will bring you out of sleep. ** For testing, the TOY counter wakeup is useful. **/--#if 0- au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);-- /* gpio 6 can cause a wake up event */- wakeup = au_readl(SYS_WAKEMSK);- wakeup &= ~(1 << 8); /* turn off match20 wakeup */- wakeup |= 1 << 6; /* turn on gpio 6 wakeup */-#else- /* For testing, allow match20 to wake us up.- */-#ifdef SLEEP_TEST_TIMEOUT- wakeup_toym2_set(sleep_ticks);-#endif- wakeup = 1 << 8; /* turn on match20 wakeup */- wakeup = 0;-#endif- au_writel(1, SYS_WAKESRC); /* clear cause */- au_sync();+ + if (au1xxx_pm_setup->wakeup_mode == GPIO_WAKEUP) {+ DPRINTK("Attempting GPIO based sleep\n");+ DPRINTK("sleep_ticks: %d\n", au1xxx_pm_setup->sleep_time);+ au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);++ /* gpio 5 can cause a wake up event */+ wakeup = au_readl(SYS_WAKEMSK);+ wakeup &= ~(1 << 8); /* turn off match20 wakeup */+ wakeup = 1 << 5; /* turn on gpio 5 wakeup */+ } else if (au1xxx_pm_setup->wakeup_mode == TIMER_WAKEUP) {+ DPRINTK("Attempting TOY based sleep\n");+ /* For testing, allow match20 to wake us up. */+ wakeup_toym2_set(au1xxx_pm_setup->sleep_time);+ wakeup = 1 << 8; /* turn on match20 wakeup */+ wakeup |= 1 << 5; /* turn on gpio 5 wakeup */+ } else {+ printk(KERN_ERR "Unable to sleep: power management settings are invalid.\n");+ return -EFAULT;+ }+ DPRINTK("wakeup: \t0x%08X\n", (unsigned int) wakeup);+ au_writel(0, SYS_WAKESRC); /* clear cause */ au_writel(wakeup, SYS_WAKEMSK);- au_sync();-+ DPRINTK("Entering sleep!\n"); save_and_sleep(); /* after a wakeup, the cpu vectors back to 0x1fc00000 so * it's up to the boot code to get us back here. */ restore_core_regs();- spin_unlock_irqrestore(&pm_lock, flags);+ spin_unlock_irqrestore(&au1xxx_pm_lock, flags);+ DPRINTK("Leaving sleep!\n"); return 0; } -static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,- void *buffer, size_t * len)++/***********************************************************************+ * CALLBACK FUNCTIONS+ ***********************************************************************/+static int system_power_callback(au1xxx_power_dev_t *device, + au1xxx_request_t request, void *data) { int retval = 0;-#ifdef SLEEP_TEST_TIMEOUT-#define TMPBUFLEN2 16- char buf[TMPBUFLEN2], *p;-#endif+ int i = 0;+ int power_level; - if (!write) {- *len = 0;- } else {-#ifdef SLEEP_TEST_TIMEOUT- if (*len > TMPBUFLEN2 - 1) {- return -EFAULT;+ DPRINTK("Inside the system_power_callback function: %lu\n", jiffies);+ if (request == AU1XXX_PM_GETSTATUS) {+ /* system device is always awake when processing this function */+ retval = AWAKE_STATE;+ } else if (request == AU1XXX_PM_SLEEP) {+ power_level = *((int *)data);++ /* loop to put all the other devices that are awake to sleep */+ for (i = 1; i < MAX_SUPPORTED_DEVICES; i++) {+ if ((sys_power_pointers[i]->valid) && + (sys_power_pointers[i]->cur_state != SLEEP_STATE))+ {+ DPRINTK("Suspending Device: %s\n", device->name);+ sys_power_pointers[i]->prev_state = sys_power_pointers[i]->cur_state;+ sys_power_pointers[i]->prev_state_timestamp = sys_power_pointers[i]->cur_state_timestamp;+ sys_power_pointers[i]->cur_state = SLEEP_STATE;+ do_gettimeofday(&(sys_power_pointers[i]->cur_state_timestamp));+ sys_power_pointers[i]->callback(sys_power_pointers[i],+ AU1XXX_PM_SLEEP, &power_level);+ } }- if (copy_from_user(buf, buffer, *len)) {- return -EFAULT;+ /* put the system device to sleep */+ device->prev_state = device->cur_state;+ device->prev_state_timestamp = device->cur_state_timestamp;+ do_gettimeofday(&(device->cur_state_timestamp));+ device->cur_state = SLEEP_STATE;++ if (!au1xxx_pm_setup->valid) {+ printk(KERN_ERR "Unable to sleep: power management settings are invalid.\n");+ retval = -EFAULT; }- buf[*len] = 0;- p = buf;- sleep_ticks = simple_strtoul(p, &p, 0);-#endif- retval = pm_send_all(PM_SUSPEND, (void *) 2);-+ DPRINTK("retval: %d (must be zero to continue into sleep)\n", retval); if (retval) return retval;- au_sleep();- retval = pm_send_all(PM_RESUME, (void *) 0);++ DPRINTK("resume pc0: \t0x%08X\n", au_readl(SYS_TOYREAD));+ DPRINTK("resume toymatch2: \t0x%08X\n", au_readl(SYS_TOYMATCH2));+ DPRINTK("resume wakesrc: \t0x%08X\n", au_readl(SYS_WAKESRC));+ DPRINTK("resume wakemask: \t0x%08X\n", au_readl(SYS_WAKEMSK));+ /* set the system device as awake now that we're back from sleep */+ power_level = AWAKE_STATE;+ device->callback(device, AU1XXX_PM_WAKEUP, &power_level);+ } else if (request == AU1XXX_PM_WAKEUP) {+ power_level = *((int*)data);+ /* send all valid devices a wakeup call */+ for (i = 1; i < MAX_SUPPORTED_DEVICES; i++) {+ if (sys_power_pointers[i]->cur_state == AWAKE_STATE) {+ DPRINTK("Error: Device: %s is already awake!\n", device->name);+ } else if (sys_power_pointers[i]->valid) { + DPRINTK("Awakening Device: %s\n", sys_power_pointers[i]->name);+ sys_power_pointers[i]->prev_state = sys_power_pointers[i]->cur_state;+ sys_power_pointers[i]->prev_state_timestamp = sys_power_pointers[i]->cur_state_timestamp;+ sys_power_pointers[i]->cur_state = AWAKE_STATE;+ do_gettimeofday(&(sys_power_pointers[i]->cur_state_timestamp));+ sys_power_pointers[i]->callback(sys_power_pointers[i],+ AU1XXX_PM_WAKEUP, &power_level);+ }+ }+ device->prev_state = device->cur_state;+ device->prev_state_timestamp = device->cur_state_timestamp;+ do_gettimeofday(&(device->cur_state_timestamp));+ device->cur_state = AWAKE_STATE;+ } else {+ DPRINTK("Error: Invalid request - %d\n", (int) request); }+ DPRINTK("Leaving system_power_callback\n"); return retval; } -static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,- void *buffer, size_t * len)+int test_callback(au1xxx_power_dev_t *device, au1xxx_request_t request,+ void *data) {- int retval = 0;- void au1k_wait(void);+ static int my_power_level; - if (!write) {- *len = 0;- } else {- retval = pm_send_all(PM_SUSPEND, (void *) 2);- if (retval)- return retval;- suspend_mode = 1;- au1k_wait();- retval = pm_send_all(PM_RESUME, (void *) 0);+ DPRINTK("Inside the test_callback function.\n");+ if (request == AU1XXX_PM_WAKEUP) {+ DPRINTK("%s has been told to wake up.\n", device->name);+ my_power_level = *((int *)data);+ } else if (request == AU1XXX_PM_GETSTATUS) {+ return my_power_level;+ } else if (request == AU1XXX_PM_SLEEP) {+ my_power_level = SLEEP_STATE; }- return retval;++ return 0; } -static int pm_do_freq(ctl_table * ctl, int write, struct file *file,- void *buffer, size_t * len)+/* + This function was heavily leveraged from kmod.c.+*/+int pm_catchall_callback( au1xxx_power_dev_t *dev, au1xxx_request_t request, void *power_level ) {- int retval = 0, i;- unsigned long val, pll;-#define TMPBUFLEN 64-#define MAX_CPU_FREQ 396- char buf[TMPBUFLEN], *p;- unsigned long flags, intc0_mask, intc1_mask;- unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,- old_refresh;- unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;+ pm_module *pm = dev->data; + int ret=0; - spin_lock_irqsave(&pm_lock, flags);- if (!write) {- *len = 0;- } else {- /* Parse the new frequency */- if (*len > TMPBUFLEN - 1) {- spin_unlock_irqrestore(&pm_lock, flags);- return -EFAULT;+ char *argv[] = { modprobe_path_pm, "-q", "add_remove", "empty_name", NULL };+ static char *remove="-r";+ static char *add="-a";+ static char *envp[] = { "HOME=/",+ "TERM=linux",+ "PATH=/sbin:/usr/sbin:/bin:/usr/bin",+ NULL };++ /* Make sure our argv module name is our current module's name */+ argv[3] = pm->modname;+ switch ( request )+ {+ case AU1XXX_PM_SLEEP:+ argv[2] = remove;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -