[BACK]Return to pm.c CVS log [TXT][DIR] Up to [local] / prex-old / dev / power

Annotation of prex-old/dev/power/pm.c, Revision 1.1

1.1     ! nbrk        1: /*-
        !             2:  * Copyright (c) 2005, Kohsuke Ohtani
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. Neither the name of the author nor the names of any co-contributors
        !            14:  *    may be used to endorse or promote products derived from this software
        !            15:  *    without specific prior written permission.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * pm.c - power management driver (hardware independent)
        !            32:  */
        !            33:
        !            34: #include <sys/ioctl.h>
        !            35: #include <driver.h>
        !            36: #include <machdep.h>
        !            37: #include <event.h>
        !            38: #include <pm.h>
        !            39: #include "dvs.h"
        !            40:
        !            41: /* #define DEBUG_PM 1 */
        !            42:
        !            43: #ifdef DEBUG_PM
        !            44: #define pm_printf(fmt, args...)        printk("pm: " fmt, ## args)
        !            45: #else
        !            46: #define pm_printf(fmt...)      do {} while (0)
        !            47: #endif
        !            48:
        !            49:
        !            50: #ifdef CONFIG_PM_POWERSAVE
        !            51: #define DEFAULT_POWER_POLICY   PM_POWERSAVE
        !            52: #else
        !            53: #define DEFAULT_POWER_POLICY   PM_PERFORMANCE
        !            54: #endif
        !            55:
        !            56: static int pm_open(device_t dev, int mode);
        !            57: static int pm_ioctl(device_t dev, int cmd, u_long arg);
        !            58: static int pm_close(device_t dev);
        !            59: static int pm_init(void);
        !            60:
        !            61: /*
        !            62:  * Driver structure
        !            63:  */
        !            64: struct driver pm_drv = {
        !            65:        /* name */      "Power Management",
        !            66:        /* order */     2,
        !            67:        /* init */      pm_init,
        !            68: };
        !            69:
        !            70: static struct devio pm_io = {
        !            71:        /* open */      pm_open,
        !            72:        /* close */     pm_close,
        !            73:        /* read */      NULL,
        !            74:        /* write */     NULL,
        !            75:        /* ioctl */     pm_ioctl,
        !            76:        /* event */     NULL,
        !            77: };
        !            78:
        !            79: static device_t pm_dev;                /* Device object */
        !            80: static int nr_open;            /* Open count */
        !            81:
        !            82: /*
        !            83:  * Power mangement policy
        !            84:  */
        !            85: static int power_policy;
        !            86:
        !            87: /*
        !            88:  * Idle timer
        !            89:  */
        !            90: static struct timer idle_timer;
        !            91: static u_long idle_count;      /* Idling counter in sec */
        !            92: static u_long suspend_timeout; /* Time until auto suspend in sec */
        !            93:
        !            94: /*
        !            95:  * Set system to suspend state
        !            96:  * Call to all devices and architecture depended code.
        !            97:  */
        !            98: int
        !            99: pm_suspend(void)
        !           100: {
        !           101:        int err;
        !           102:
        !           103:        pm_printf("Suspend system\n");
        !           104:        err = device_broadcast(EVT_SUSPEND, 1);
        !           105:        if (err)
        !           106:                return err;
        !           107:        machine_suspend();
        !           108:        return 0;
        !           109: }
        !           110:
        !           111: /*
        !           112:  * Resume
        !           113:  */
        !           114: int
        !           115: pm_resume(void)
        !           116: {
        !           117:        pm_printf("Resume system\n");
        !           118:        device_broadcast(EVT_RESUME, 1);
        !           119:        return 0;
        !           120: }
        !           121:
        !           122: /*
        !           123:  * Power off system
        !           124:  * Call to all devices and architecture depended code.
        !           125:  */
        !           126: int
        !           127: pm_poweroff(void)
        !           128: {
        !           129:        int err;
        !           130:
        !           131:        pm_printf("Power off...\n");
        !           132:        err = device_broadcast(EVT_SHUTDOWN, 1);
        !           133:        if (err)
        !           134:                return err;
        !           135:        machine_poweroff();
        !           136:        return 0;
        !           137: }
        !           138:
        !           139: /*
        !           140:  * Reboot system.
        !           141:  */
        !           142: int
        !           143: pm_reboot(void)
        !           144: {
        !           145:        int err;
        !           146:
        !           147:        pm_printf("rebooting...\n");
        !           148:        err = device_broadcast(EVT_SHUTDOWN, 1);
        !           149:        if (err)
        !           150:                return err;
        !           151:
        !           152:        irq_lock();
        !           153:
        !           154:        /*
        !           155:         * Do reset.
        !           156:         */
        !           157:        machine_reset();
        !           158:        return 0;
        !           159: }
        !           160:
        !           161: /*
        !           162:  * Idle timer handler
        !           163:  */
        !           164: static void
        !           165: idle_timeout(u_long dummy)
        !           166: {
        !           167:
        !           168:        irq_lock();
        !           169:        idle_count++;
        !           170:        irq_unlock();
        !           171:        if (idle_count >= suspend_timeout)
        !           172:                pm_suspend();
        !           173:        else
        !           174:                timer_callout(&idle_timer, idle_timeout, 0, 1000);
        !           175: }
        !           176:
        !           177: /*
        !           178:  * Set suspend timer
        !           179:  */
        !           180: int
        !           181: pm_settimer(u_long sec)
        !           182: {
        !           183:
        !           184:        sched_lock();
        !           185:        if (sec)
        !           186:                timer_callout(&idle_timer, idle_timeout, 0, 1000);
        !           187:        else
        !           188:                timer_stop(&idle_timer);
        !           189:        idle_count = 0;
        !           190:        suspend_timeout = sec;
        !           191:        sched_unlock();
        !           192:        return 0;
        !           193: }
        !           194:
        !           195: /*
        !           196:  * Get power management timer
        !           197:  */
        !           198: int
        !           199: pm_gettimer(u_long *sec)
        !           200: {
        !           201:
        !           202:        *sec = suspend_timeout;
        !           203:        return 0;
        !           204: }
        !           205:
        !           206: /*
        !           207:  * Reload idle timer
        !           208:  */
        !           209: void
        !           210: pm_active(void)
        !           211: {
        !           212:
        !           213:        idle_count = 0;
        !           214: }
        !           215:
        !           216: /*
        !           217:  * Set power policy
        !           218:  */
        !           219: static int
        !           220: pm_setpolicy(int policy)
        !           221: {
        !           222:
        !           223:        if (policy != PM_POWERSAVE && policy != PM_PERFORMANCE)
        !           224:                return EINVAL;
        !           225: #ifdef CONFIG_CPUFREQ
        !           226:        cpufreq_setpolicy(policy);
        !           227: #endif
        !           228:        power_policy = policy;
        !           229:        return 0;
        !           230: }
        !           231:
        !           232: /*
        !           233:  * Get current power policy
        !           234:  */
        !           235: int
        !           236: pm_getpolicy(void)
        !           237: {
        !           238:
        !           239:        return power_policy;
        !           240: }
        !           241:
        !           242: /*
        !           243:  * Open the pm device.
        !           244:  *
        !           245:  * The open operation is allowed to only one task. This can protect
        !           246:  * the critical ioctl operation from some malicious tasks. For example,
        !           247:  * the power off should be done by the privileged task like a process
        !           248:  * server.
        !           249:  */
        !           250: static int
        !           251: pm_open(device_t dev, int mode)
        !           252: {
        !           253:
        !           254:        if (nr_open > 0)
        !           255:                return EBUSY;
        !           256:        nr_open++;
        !           257:        return 0;
        !           258: }
        !           259:
        !           260: static int
        !           261: pm_close(device_t dev)
        !           262: {
        !           263:
        !           264:        if (nr_open != 1)
        !           265:                return EINVAL;
        !           266:        nr_open--;
        !           267:        return 0;
        !           268: }
        !           269:
        !           270: static int
        !           271: pm_ioctl(device_t dev, int cmd, u_long arg)
        !           272: {
        !           273:        int err = 0;
        !           274:        int policy;
        !           275:
        !           276:        switch (cmd) {
        !           277:        case PMIOC_SET_POWER:
        !           278:                switch (arg) {
        !           279:                case POWER_SUSPEND:
        !           280:                        pm_suspend();
        !           281:                        break;
        !           282:                case POWER_OFF:
        !           283:                        pm_poweroff();
        !           284:                        break;
        !           285:                case POWER_REBOOT:
        !           286:                        pm_reboot();
        !           287:                        break;
        !           288:                default:
        !           289:                        return EINVAL;
        !           290:                }
        !           291:                break;
        !           292:        case PMIOC_SET_POLICY:
        !           293:                err = pm_setpolicy((int)arg);
        !           294:                break;
        !           295:        case PMIOC_GET_POLICY:
        !           296:                policy = pm_getpolicy();
        !           297:                if (umem_copyout(&policy, (int *)arg, sizeof(int)))
        !           298:                        return EFAULT;
        !           299:                break;
        !           300:        default:
        !           301:                return EINVAL;
        !           302:        }
        !           303:        return err;
        !           304: }
        !           305:
        !           306: /*
        !           307:  * Initialize
        !           308:  */
        !           309: static int
        !           310: pm_init(void)
        !           311: {
        !           312:
        !           313:        /* Create device object */
        !           314:        pm_dev = device_create(&pm_io, "pm", DF_CHR);
        !           315:        ASSERT(pm_dev);
        !           316:
        !           317:        nr_open = 0;
        !           318:        idle_count = 0;
        !           319:        suspend_timeout = 0;
        !           320:        power_policy = DEFAULT_POWER_POLICY;
        !           321:        timer_init(&idle_timer);
        !           322:        printk("pm: Default power policy is %s mode\n",
        !           323:               (power_policy == PM_POWERSAVE) ? "power save" : "performance");
        !           324:        return 0;
        !           325: }

CVSweb