Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/mips/alchemy/devboards/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  pm.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Alchemy Development Board example suspend userspace interface.
 *
 * (c) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
 */


#include <linux/init.h>
#include <linux/kobject.h>
#include <linux/suspend.h>
#include <linux/sysfs.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-db1x00/bcsr.h>

/*
 * Generic suspend userspace interface for Alchemy development boards.
 * This code exports a few sysfs nodes under /sys/power/db1x/ which
 * can be used by userspace to en/disable all au1x-provided wakeup
 * sources and configure the timeout after which the TOYMATCH2 irq
 * is to trigger a wakeup.
 */



static unsigned long db1x_pm_sleep_secs;
static unsigned long db1x_pm_wakemsk;
static unsigned long db1x_pm_last_wakesrc;

static int db1x_pm_enter(suspend_state_t state)
{
 unsigned short bcsrs[16];
 int i, j, hasint;

 /* save CPLD regs */
 hasint = bcsr_read(BCSR_WHOAMI);
 hasint = BCSR_WHOAMI_BOARD(hasint) >= BCSR_WHOAMI_DB1200;
 j = (hasint) ? BCSR_MASKSET : BCSR_SYSTEM;

 for (i = BCSR_STATUS; i <= j; i++)
  bcsrs[i] = bcsr_read(i);

 /* shut off hexleds */
 bcsr_write(BCSR_HEXCLEAR, 3);

 /* enable GPIO based wakeup */
 alchemy_gpio1_input_enable();

 /* clear and setup wake cause and source */
 alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
 alchemy_wrsys(0, AU1000_SYS_WAKESRC);

 alchemy_wrsys(db1x_pm_wakemsk, AU1000_SYS_WAKEMSK);

 /* setup 1Hz-timer-based wakeup: wait for reg access */
 while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
  asm volatile ("nop");

 alchemy_wrsys(alchemy_rdsys(AU1000_SYS_TOYREAD) + db1x_pm_sleep_secs,
        AU1000_SYS_TOYMATCH2);

 /* wait for value to really hit the register */
 while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
  asm volatile ("nop");

 /* ...and now the sandman can come! */
 au_sleep();


 /* restore CPLD regs */
 for (i = BCSR_STATUS; i <= BCSR_SYSTEM; i++)
  bcsr_write(i, bcsrs[i]);

 /* restore CPLD int registers */
 if (hasint) {
  bcsr_write(BCSR_INTCLR, 0xffff);
  bcsr_write(BCSR_MASKCLR, 0xffff);
  bcsr_write(BCSR_INTSTAT, 0xffff);
  bcsr_write(BCSR_INTSET, bcsrs[BCSR_INTSET]);
  bcsr_write(BCSR_MASKSET, bcsrs[BCSR_MASKSET]);
 }

 /* light up hexleds */
 bcsr_write(BCSR_HEXCLEAR, 0);

 return 0;
}

static int db1x_pm_begin(suspend_state_t state)
{
 if (!db1x_pm_wakemsk) {
  printk(KERN_ERR "db1x: no wakeup source activated!\n");
  return -EINVAL;
 }

 return 0;
}

static void db1x_pm_end(void)
{
 /* read and store wakeup source, the clear the register. To
 * be able to clear it, WAKEMSK must be cleared first.
 */

 db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);

 alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
 alchemy_wrsys(0, AU1000_SYS_WAKESRC);
}

static const struct platform_suspend_ops db1x_pm_ops = {
 .valid  = suspend_valid_only_mem,
 .begin  = db1x_pm_begin,
 .enter  = db1x_pm_enter,
 .end  = db1x_pm_end,
};

#define ATTRCMP(x) (0 == strcmp(attr->attr.name, #x))

static ssize_t db1x_pmattr_show(struct kobject *kobj,
    struct kobj_attribute *attr,
    char *buf)
{
 int idx;

 if (ATTRCMP(timer_timeout))
  return sprintf(buf, "%lu\n", db1x_pm_sleep_secs);

 else if (ATTRCMP(timer))
  return sprintf(buf, "%u\n",
    !!(db1x_pm_wakemsk & SYS_WAKEMSK_M2));

 else if (ATTRCMP(wakesrc))
  return sprintf(buf, "%lu\n", db1x_pm_last_wakesrc);

 else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
   ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
   ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
  idx = (attr->attr.name)[4] - '0';
  return sprintf(buf, "%d\n",
   !!(db1x_pm_wakemsk & SYS_WAKEMSK_GPIO(idx)));

 } else if (ATTRCMP(wakemsk)) {
  return sprintf(buf, "%08lx\n", db1x_pm_wakemsk);
 }

 return -ENOENT;
}

static ssize_t db1x_pmattr_store(struct kobject *kobj,
     struct kobj_attribute *attr,
     const char *instr,
     size_t bytes)
{
 unsigned long l;
 int tmp;

 if (ATTRCMP(timer_timeout)) {
  tmp = kstrtoul(instr, 0, &l);
  if (tmp)
   return tmp;

  db1x_pm_sleep_secs = l;

 } else if (ATTRCMP(timer)) {
  if (instr[0] != '0')
   db1x_pm_wakemsk |= SYS_WAKEMSK_M2;
  else
   db1x_pm_wakemsk &= ~SYS_WAKEMSK_M2;

 } else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
     ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
     ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
  tmp = (attr->attr.name)[4] - '0';
  if (instr[0] != '0') {
   db1x_pm_wakemsk |= SYS_WAKEMSK_GPIO(tmp);
  } else {
   db1x_pm_wakemsk &= ~SYS_WAKEMSK_GPIO(tmp);
  }

 } else if (ATTRCMP(wakemsk)) {
  tmp = kstrtoul(instr, 0, &l);
  if (tmp)
   return tmp;

  db1x_pm_wakemsk = l & 0x0000003f;

 } else
  bytes = -ENOENT;

 return bytes;
}

#define ATTR(x)       \
 static struct kobj_attribute x##_attribute =  \
  __ATTR(x, 0664, db1x_pmattr_show,  \
    db1x_pmattr_store);

ATTR(gpio0)  /* GPIO-based wakeup enable */
ATTR(gpio1)
ATTR(gpio2)
ATTR(gpio3)
ATTR(gpio4)
ATTR(gpio5)
ATTR(gpio6)
ATTR(gpio7)
ATTR(timer)  /* TOYMATCH2-based wakeup enable */
ATTR(timer_timeout) /* timer-based wakeup timeout value, in seconds */
ATTR(wakesrc)  /* contents of SYS_WAKESRC after last wakeup */
ATTR(wakemsk)  /* direct access to SYS_WAKEMSK */

#define ATTR_LIST(x) & x ## _attribute.attr
static struct attribute *db1x_pmattrs[] = {
 ATTR_LIST(gpio0),
 ATTR_LIST(gpio1),
 ATTR_LIST(gpio2),
 ATTR_LIST(gpio3),
 ATTR_LIST(gpio4),
 ATTR_LIST(gpio5),
 ATTR_LIST(gpio6),
 ATTR_LIST(gpio7),
 ATTR_LIST(timer),
 ATTR_LIST(timer_timeout),
 ATTR_LIST(wakesrc),
 ATTR_LIST(wakemsk),
 NULL,  /* terminator */
};

static struct attribute_group db1x_pmattr_group = {
 .name = "db1x",
 .attrs = db1x_pmattrs,
};

/*
 * Initialize suspend interface
 */

static int __init pm_init(void)
{
 /* init TOY to tick at 1Hz if not already done. No need to wait
 * for confirmation since there's plenty of time from here to
 * the next suspend cycle.
 */

 if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767)
  alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);

 db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);

 alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 alchemy_wrsys(0, AU1000_SYS_WAKEMSK);

 suspend_set_ops(&db1x_pm_ops);

 return sysfs_create_group(power_kobj, &db1x_pmattr_group);
}

late_initcall(pm_init);

Messung V0.5
C=92 H=81 G=86

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.