Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
4ffd6952 AV |
2 | /* |
3 | * Suspend/resume support | |
4 | * | |
5 | * Copyright 2009 MontaVista Software, Inc. | |
6 | * | |
7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | |
4ffd6952 AV |
8 | */ |
9 | ||
10 | #include <linux/init.h> | |
11 | #include <linux/types.h> | |
12 | #include <linux/errno.h> | |
66b15db6 | 13 | #include <linux/export.h> |
4ffd6952 AV |
14 | #include <linux/suspend.h> |
15 | #include <linux/delay.h> | |
81d7cac4 | 16 | #include <linux/mod_devicetable.h> |
26a2056e | 17 | #include <linux/of_address.h> |
81d7cac4 | 18 | #include <linux/platform_device.h> |
4ffd6952 AV |
19 | |
20 | struct pmc_regs { | |
21 | __be32 devdisr; | |
22 | __be32 devdisr2; | |
23 | __be32 :32; | |
24 | __be32 :32; | |
25 | __be32 pmcsr; | |
26 | #define PMCSR_SLP (1 << 17) | |
27 | }; | |
28 | ||
29 | static struct device *pmc_dev; | |
30 | static struct pmc_regs __iomem *pmc_regs; | |
31 | ||
32 | static int pmc_suspend_enter(suspend_state_t state) | |
33 | { | |
34 | int ret; | |
35 | ||
36 | setbits32(&pmc_regs->pmcsr, PMCSR_SLP); | |
37 | /* At this point, the CPU is asleep. */ | |
38 | ||
39 | /* Upon resume, wait for SLP bit to be clear. */ | |
40 | ret = spin_event_timeout((in_be32(&pmc_regs->pmcsr) & PMCSR_SLP) == 0, | |
41 | 10000, 10) ? 0 : -ETIMEDOUT; | |
42 | if (ret) | |
43 | dev_err(pmc_dev, "tired waiting for SLP bit to clear\n"); | |
44 | return ret; | |
45 | } | |
46 | ||
47 | static int pmc_suspend_valid(suspend_state_t state) | |
48 | { | |
49 | if (state != PM_SUSPEND_STANDBY) | |
50 | return 0; | |
51 | return 1; | |
52 | } | |
53 | ||
2f55ac07 | 54 | static const struct platform_suspend_ops pmc_suspend_ops = { |
4ffd6952 AV |
55 | .valid = pmc_suspend_valid, |
56 | .enter = pmc_suspend_enter, | |
57 | }; | |
58 | ||
00006124 | 59 | static int pmc_probe(struct platform_device *ofdev) |
4ffd6952 | 60 | { |
61c7a080 | 61 | pmc_regs = of_iomap(ofdev->dev.of_node, 0); |
4ffd6952 AV |
62 | if (!pmc_regs) |
63 | return -ENOMEM; | |
64 | ||
65 | pmc_dev = &ofdev->dev; | |
66 | suspend_set_ops(&pmc_suspend_ops); | |
67 | return 0; | |
68 | } | |
69 | ||
70 | static const struct of_device_id pmc_ids[] = { | |
71 | { .compatible = "fsl,mpc8548-pmc", }, | |
72 | { .compatible = "fsl,mpc8641d-pmc", }, | |
73 | { }, | |
74 | }; | |
75 | ||
00006124 | 76 | static struct platform_driver pmc_driver = { |
4018294b GL |
77 | .driver = { |
78 | .name = "fsl-pmc", | |
4018294b GL |
79 | .of_match_table = pmc_ids, |
80 | }, | |
4ffd6952 AV |
81 | .probe = pmc_probe, |
82 | }; | |
83 | ||
16c6cb46 | 84 | builtin_platform_driver(pmc_driver); |