]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/mfd/ab8500-sysctrl.c
mfd: ab8500-sysctrl: Provide a platform specific pm_power_off() call-back
[mirror_ubuntu-jammy-kernel.git] / drivers / mfd / ab8500-sysctrl.c
CommitLineData
90550d19
MN
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson.
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#include <linux/err.h>
4e36dd33 8#include <linux/module.h>
90550d19 9#include <linux/platform_device.h>
379749c4
LJ
10#include <linux/pm.h>
11#include <linux/signal.h>
90550d19 12#include <linux/mfd/abx500.h>
ee66e653
LW
13#include <linux/mfd/abx500/ab8500.h>
14#include <linux/mfd/abx500/ab8500-sysctrl.h>
90550d19
MN
15
16static struct device *sysctrl_dev;
17
379749c4
LJ
18void ab8500_power_off(void)
19{
20 sigset_t old;
21 sigset_t all;
22
23 sigfillset(&all);
24
25 if (!sigprocmask(SIG_BLOCK, &all, &old)) {
26 (void)ab8500_sysctrl_set(AB8500_STW4500CTRL1,
27 AB8500_STW4500CTRL1_SWOFF |
28 AB8500_STW4500CTRL1_SWRESET4500N);
29 (void)sigprocmask(SIG_SETMASK, &old, NULL);
30 }
31}
32
90550d19
MN
33static inline bool valid_bank(u8 bank)
34{
35 return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
36 (bank == AB8500_SYS_CTRL2_BLOCK));
37}
38
39int ab8500_sysctrl_read(u16 reg, u8 *value)
40{
41 u8 bank;
42
43 if (sysctrl_dev == NULL)
44 return -EAGAIN;
45
46 bank = (reg >> 8);
47 if (!valid_bank(bank))
48 return -EINVAL;
49
50 return abx500_get_register_interruptible(sysctrl_dev, bank,
51 (u8)(reg & 0xFF), value);
52}
53
54int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
55{
56 u8 bank;
57
58 if (sysctrl_dev == NULL)
59 return -EAGAIN;
60
61 bank = (reg >> 8);
62 if (!valid_bank(bank))
63 return -EINVAL;
64
65 return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,
66 (u8)(reg & 0xFF), mask, value);
67}
68
f791be49 69static int ab8500_sysctrl_probe(struct platform_device *pdev)
90550d19 70{
379749c4
LJ
71 struct ab8500_platform_data *plat;
72
90550d19 73 sysctrl_dev = &pdev->dev;
379749c4
LJ
74 plat = dev_get_platdata(pdev->dev.parent);
75 if (plat->pm_power_off)
76 pm_power_off = ab8500_power_off;
90550d19
MN
77 return 0;
78}
79
4740f73f 80static int ab8500_sysctrl_remove(struct platform_device *pdev)
90550d19
MN
81{
82 sysctrl_dev = NULL;
83 return 0;
84}
85
86static struct platform_driver ab8500_sysctrl_driver = {
87 .driver = {
88 .name = "ab8500-sysctrl",
89 .owner = THIS_MODULE,
90 },
91 .probe = ab8500_sysctrl_probe,
84449216 92 .remove = ab8500_sysctrl_remove,
90550d19
MN
93};
94
95static int __init ab8500_sysctrl_init(void)
96{
97 return platform_driver_register(&ab8500_sysctrl_driver);
98}
99subsys_initcall(ab8500_sysctrl_init);
100
101MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com");
102MODULE_DESCRIPTION("AB8500 system control driver");
103MODULE_LICENSE("GPL v2");