0001
0002
0003
0004
0005
0006
0007
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
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
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
0048
0049
0050 mdelay(3000);
0051
0052 asm volatile (
0053
0054 ".balign 32\n\t"
0055
0056
0057 "str %[srcmd], [%[sdram_reg]]\n\t"
0058
0059
0060
0061
0062
0063 "mov r1, #50\n\t"
0064 "1: subs r1, r1, #1\n\t"
0065 "bne 1b\n\t"
0066
0067
0068 "str %[ackcmd], [%[gpio_ctrl]]\n\t"
0069
0070
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
0148
0149
0150
0151
0152
0153
0154 device_initcall_sync(mvebu_armada_pm_init);