^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* pmc - Driver implementation for power management functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * of Power Management Controller (PMC) on SPARCstation-Voyager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2002 Eric Brower (ebrower@usa.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/auxio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Debug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * #define PMC_DEBUG_LED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * #define PMC_NO_IDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PMC_OBPNAME "SUNW,pmc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PMC_DEVNAME "pmc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PMC_IDLE_REG 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PMC_IDLE_ON 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static u8 __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define pmc_readb(offs) (sbus_readb(regs+offs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * CPU idle callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * See .../arch/sparc/kernel/process.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static void pmc_swift_idle(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #ifdef PMC_DEBUG_LED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) set_auxio(0x00, AUXIO_LED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) pmc_writeb(pmc_readb(PMC_IDLE_REG) | PMC_IDLE_ON, PMC_IDLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifdef PMC_DEBUG_LED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) set_auxio(AUXIO_LED, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int pmc_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) regs = of_ioremap(&op->resource[0], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) resource_size(&op->resource[0]), PMC_OBPNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #ifndef PMC_NO_IDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Assign power management IDLE handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sparc_idle = pmc_swift_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) printk(KERN_INFO "%s: power management initialized\n", PMC_DEVNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct of_device_id pmc_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .name = PMC_OBPNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) MODULE_DEVICE_TABLE(of, pmc_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static struct platform_driver pmc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .name = "pmc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .of_match_table = pmc_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .probe = pmc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int __init pmc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return platform_driver_register(&pmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* This driver is not critical to the boot process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * and is easiest to ioremap when SBus is already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * initialized, so we install ourselves thusly:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) __initcall(pmc_init);