Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Board-level suspend/resume support.
0004  *
0005  * Copyright (C) 2014-2015 Marvell
0006  *
0007  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
0008  */
0009 
0010 #include <linux/delay.h>
0011 #include <linux/gpio.h>
0012 #include <linux/init.h>
0013 #include <linux/io.h>
0014 #include <linux/of.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of_gpio.h>
0017 #include <linux/slab.h>
0018 #include "common.h"
0019 
0020 #define ARMADA_PIC_NR_GPIOS 3
0021 
0022 static void __iomem *gpio_ctrl;
0023 static int pic_gpios[ARMADA_PIC_NR_GPIOS];
0024 static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS];
0025 
0026 static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd)
0027 {
0028     u32 reg, ackcmd;
0029     int i;
0030 
0031     /* Put 001 as value on the GPIOs */
0032     reg = readl(gpio_ctrl);
0033     for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
0034         reg &= ~BIT(pic_raw_gpios[i]);
0035     reg |= BIT(pic_raw_gpios[0]);
0036     writel(reg, gpio_ctrl);
0037 
0038     /* Prepare writing 111 to the GPIOs */
0039     ackcmd = readl(gpio_ctrl);
0040     for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++)
0041         ackcmd |= BIT(pic_raw_gpios[i]);
0042 
0043     srcmd = cpu_to_le32(srcmd);
0044     ackcmd = cpu_to_le32(ackcmd);
0045 
0046     /*
0047      * Wait a while, the PIC needs quite a bit of time between the
0048      * two GPIO commands.
0049      */
0050     mdelay(3000);
0051 
0052     asm volatile (
0053         /* Align to a cache line */
0054         ".balign 32\n\t"
0055 
0056         /* Enter self refresh */
0057         "str %[srcmd], [%[sdram_reg]]\n\t"
0058 
0059         /*
0060          * Wait 100 cycles for DDR to enter self refresh, by
0061          * doing 50 times two instructions.
0062          */
0063         "mov r1, #50\n\t"
0064         "1: subs r1, r1, #1\n\t"
0065         "bne 1b\n\t"
0066 
0067         /* Issue the command ACK */
0068         "str %[ackcmd], [%[gpio_ctrl]]\n\t"
0069 
0070         /* Trap the processor */
0071         "b .\n\t"
0072         : : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
0073           [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
0074 }
0075 
0076 static int __init mvebu_armada_pm_init(void)
0077 {
0078     struct device_node *np;
0079     struct device_node *gpio_ctrl_np = NULL;
0080     int ret = 0, i;
0081 
0082     if (!of_machine_is_compatible("marvell,axp-gp"))
0083         return -ENODEV;
0084 
0085     np = of_find_node_by_name(NULL, "pm_pic");
0086     if (!np)
0087         return -ENODEV;
0088 
0089     for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) {
0090         char *name;
0091         struct of_phandle_args args;
0092 
0093         pic_gpios[i] = of_get_named_gpio(np, "ctrl-gpios", i);
0094         if (pic_gpios[i] < 0) {
0095             ret = -ENODEV;
0096             goto out;
0097         }
0098 
0099         name = kasprintf(GFP_KERNEL, "pic-pin%d", i);
0100         if (!name) {
0101             ret = -ENOMEM;
0102             goto out;
0103         }
0104 
0105         ret = gpio_request(pic_gpios[i], name);
0106         if (ret < 0) {
0107             kfree(name);
0108             goto out;
0109         }
0110 
0111         ret = gpio_direction_output(pic_gpios[i], 0);
0112         if (ret < 0) {
0113             gpio_free(pic_gpios[i]);
0114             kfree(name);
0115             goto out;
0116         }
0117 
0118         ret = of_parse_phandle_with_fixed_args(np, "ctrl-gpios", 2,
0119                                i, &args);
0120         if (ret < 0) {
0121             gpio_free(pic_gpios[i]);
0122             kfree(name);
0123             goto out;
0124         }
0125 
0126         if (gpio_ctrl_np)
0127             of_node_put(gpio_ctrl_np);
0128         gpio_ctrl_np = args.np;
0129         pic_raw_gpios[i] = args.args[0];
0130     }
0131 
0132     gpio_ctrl = of_iomap(gpio_ctrl_np, 0);
0133     if (!gpio_ctrl) {
0134         ret = -ENOMEM;
0135         goto out;
0136     }
0137 
0138     mvebu_pm_suspend_init(mvebu_armada_pm_enter);
0139 
0140 out:
0141     of_node_put(np);
0142     of_node_put(gpio_ctrl_np);
0143     return ret;
0144 }
0145 
0146 /*
0147  * Registering the mvebu_board_pm_enter callback must be done before
0148  * the platform_suspend_ops will be registered. In the same time we
0149  * also need to have the gpio devices registered. That's why we use a
0150  * device_initcall_sync which is called after all the device_initcall
0151  * (used by the gpio device) but before the late_initcall (used to
0152  * register the platform_suspend_ops)
0153  */
0154 device_initcall_sync(mvebu_armada_pm_init);