Nx32926 命令关机

一. poweroff关机命令

~ # poweroff
~ # baud=115200, quot=102
w-config: 8bits/char
umount: devtmpfs busy - remounted read-only
Cannot open value file.
umount: can't remount rootfs reabaud=115200, quot=102
w-config: 8bits/char
d-only
cannot run '/sbin/swapoff': No such file or dirRTL871X: rtw_cmd_thread(wlan0) _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break
ectory
The system is going down NOW!
Sent SIGTERM to all processes
videoin_close
Sensor power down
Sensor power down
I2C removed
Sent SIGKILL toPower down.
enter to w55fa92_poweroff()

二、内核代码

void w55fa92_poweroff(void)
{
    unsigned long volatile flags;
#if defined(CONFIG_RTC_DRV_W55FA92)
    int rtc_time_out;
#endif

    printk("enter to w55fa92_poweroff()
");
    msleep(10);

    // disable LVR
    __raw_writel(__raw_readl(REG_MISCR) & ~(LVR_RDY | LVR_EN), REG_MISCR);

    // turn off speaker
#if defined(CONFIG_GIANTPLUS_GPM1006D0_320X240)
    __raw_writel(__raw_readl(REG_GPIOE_OMD) | (1 << 1), REG_GPIOE_OMD);
    __raw_writel(__raw_readl(REG_GPIOE_DOUT) & ~(1 << 1), REG_GPIOE_DOUT);
#endif

    // turn off video out
    __raw_writel((__raw_readl(REG_LCM_TVCtl) & ~TVCtl_LCDSrc) | 0x800, REG_LCM_TVCtl);

    // disable system interrupts
    local_irq_save(flags);

#if defined(CONFIG_RTC_DRV_W55FA92)
    __raw_writel(__raw_readl(REG_APBCLK) | RTC_CKE, REG_APBCLK);
    while (1) {
        rtc_time_out = 0;
        // enable long time press power disable
        if ((__raw_readl(REG_RTC_AER) & 0x10000) == 0x0) {
            // set RTC register access enable password
            __raw_writel(0xA965, REG_RTC_AER);
            // make sure RTC register read/write enable
            while ((__raw_readl(REG_RTC_AER) & 0x10000) == 0x0) {
                rtc_time_out++;
                if (rtc_time_out > 0xFFFFFF) {
                    printk("RTC Access Eanble Fail
");
                    break;
                }
            }

            rtc_wait_ready();

            if ((__raw_readl(REG_RTC_AER) & 0x10000) == 0x10000)
                break;
        }
        else
            break;
    }

    // RTC will power off
    __raw_writel((__raw_readl(REG_RTC_PWRON) & ~0x5) | 0x2, REG_RTC_PWRON);
#else
    // turn off power
    __raw_writel(__raw_readl(REG_GPIOE_OMD) | (1<<9), REG_GPIOE_OMD);
    __raw_writel(__raw_readl(REG_GPIOE_DOUT) & ~(1<<9), REG_GPIOE_DOUT);
#endif

    // enable system interrupts
    local_irq_restore(flags);

    // stop CPU clock
    //__raw_writel(__raw_readl(REG_AHBCLK) & ~CPU_CKE, REG_AHBCLK);
    // fix RTC may wakeup fail issue
    __raw_writel(0x0, REG_AHBCLK);

    // wait system enter power off
    while (1) ;
}

void w55fa92_reboot(void)
{
    unsigned long volatile flags;

    local_irq_save(flags);
    printk("enter to w55fa92_reboot()
");

    // turn off speaker
#if defined(CONFIG_GIANTPLUS_GPM1006D0_320X240)
    __raw_writel(__raw_readl(REG_GPIOE_OMD) | (1 << 1), REG_GPIOE_OMD);
    __raw_writel(__raw_readl(REG_GPIOE_DOUT) & ~(1 << 1), REG_GPIOE_DOUT);
#endif

    // turn off video out
    __raw_writel((__raw_readl(REG_LCM_TVCtl) & ~TVCtl_LCDSrc) | 0x800, REG_LCM_TVCtl);

    // close NAND and SIC engine clock
    __raw_writel(__raw_readl(REG_AHBCLK) & ~(NAND_CKE|SIC_CKE), REG_AHBCLK);

    // watchdog reset
    __raw_writel((__raw_readl(REG_WTCR) & ~(3<<4|1<<10))|0x2C2, REG_WTCR);

    // wait system enter power off
    while (1) ;
    local_irq_restore(flags);
}

static ssize_t
write_clk(struct device *dev, struct device_attribute *attr,
      const char *buffer, size_t count)
{
    int i;

    // power down mode
    if (buffer[0] == 'p' && buffer[1] == 'd') {
        w55fa92_pm_suspend(1);
    }

#if 0
    // idle mode or memory idle mode
    else if ((buffer[0] == 'i' && buffer[1] == 'd') || (buffer[0] == 'm' && buffer[1] == 'i')) {
        w55fa92_pm_idle();
    }
#endif

#if defined(CONFIG_RTC_DRV_W55FA92)
    // RTC power off mode
    else if (buffer[0] == 'r' && buffer[1] == 'p' && buffer[2] == 'o') {
        w55fa92_poweroff();
    }
#else
    // power off mode
    else if (buffer[0] == 'p' && buffer[1] == 'o') {
        w55fa92_poweroff();
    }
#endif

    // power reset mode
    else if (buffer[0] == 'p' && buffer[1] == 'r') {
        w55fa92_reboot();
    }

    // CPU:PLL clock change
    else {
        u32 pll_clock, sys_clock, cpu_clock, apb_clock, vpost_clock;
        u8 vpost_div_N0, vpost_div_N1;
        char clock_buf[64];
        char *clock1, *clock2, *next;

        strncpy(clock_buf, buffer, count);
        next = &clock_buf[0];
        pll_clock = w55fa92_upll_clock;
        clock1 = strsep(&next, ":");
        //printk("clock1 = %s
", clock1);
        cpu_clock = simple_strtol(clock1, NULL, 10) * 1000;
        if (cpu_clock == 0) {
            printk("Command "%s" does not support !!
", clock1);
            return -1;
        }
        if (next) {
            clock2 = strsep(&next, ":");
            //printk("clock2 = %s
", clock2);
            pll_clock = simple_strtol(clock2, NULL, 10) * 1000;
            if (pll_clock == 0) {
                printk("Command "%s" does not support !!
", clock2);
                return -1;
            }
        }

        if (pll_clock % cpu_clock) {
            printk("UPLL clock(%d) is not a multiple of CPU clock(%d) !!
", 
                pll_clock, cpu_clock);
            return -1;
        }

#if defined(CONFIG_FB_W55FA92)
        vpost_div_N0 = (__raw_readl(REG_CLKDIV1) & VPOST_N0) + 1;
        vpost_div_N1 = ((__raw_readl(REG_CLKDIV1) & VPOST_N1) >> 8) + 1;
        vpost_clock = pll_clock / (vpost_div_N0 * vpost_div_N1);
        if (cpu_clock > vpost_clock*2) {
            sys_clock = cpu_clock;
        } else {
            for (i = 1; ; i++) {
                sys_clock = cpu_clock * i * 2;
                if ((i > 8) || (sys_clock > pll_clock)) {
                    printk("Cannot get valid System clock !!
"); 
                    return -1;
                }
                if ((sys_clock>(vpost_clock*2)) && ((pll_clock%sys_clock)==0))
                    break;
            }
        }
#else
        sys_clock = cpu_clock;
#endif
        apb_clock = (cpu_clock == sys_clock) ? cpu_clock/4 : cpu_clock/2;
#if CPU_DEBUG
        printk("vpost_clock = %d
", vpost_clock);
        printk("pll_clock = %d
", pll_clock);
        printk("sys_clock = %d
", sys_clock);
        printk("cpu_clock = %d
", cpu_clock);
        printk("apb_clock = %d
", apb_clock);
#endif

        // PLL:SYS:CPU:AHB:APB = pll_clock:sys_clock:cpu_clock:sys_clock/2:apb_clock
        set_system_clocks(pll_clock, sys_clock, cpu_clock, apb_clock);
    }

    return count;
}

/* Attach the sysfs write method */
DEVICE_ATTR(clock, 0644, read_clk, write_clk);

/* Attribute Descriptor */
static struct attribute *clk_attrs[] = {
    &dev_attr_clock.attr,
    NULL
};

/* Attribute group */
static struct attribute_group clk_attr_group = {
    .attrs = clk_attrs,
};

static int __init w55fa92_system_clock_init(void)
{
    /* Register a platform device */
    printk("register clock device
");

  ///sys/devices/w55fa92-clk sys_clk
= platform_device_register_simple("w55fa92-clk", -1, NULL, 0); if (sys_clk == NULL) printk("register failed "); sysfs_create_group(&sys_clk->dev.kobj, &clk_attr_group); sram_vaddr = ioremap(0xFF000000, 4*1024); return 0; } module_init(w55fa92_system_clock_init);
原文地址:https://www.cnblogs.com/cslunatic/p/5660663.html