xref: /linux-6.15/drivers/mfd/ab8500-sysctrl.c (revision 379749c4)
190550d19SMattias Nilsson /*
290550d19SMattias Nilsson  * Copyright (C) ST-Ericsson SA 2010
390550d19SMattias Nilsson  * Author: Mattias Nilsson <[email protected]> for ST Ericsson.
490550d19SMattias Nilsson  * License terms: GNU General Public License (GPL) version 2
590550d19SMattias Nilsson  */
690550d19SMattias Nilsson 
790550d19SMattias Nilsson #include <linux/err.h>
84e36dd33SPaul Gortmaker #include <linux/module.h>
990550d19SMattias Nilsson #include <linux/platform_device.h>
10*379749c4SLee Jones #include <linux/pm.h>
11*379749c4SLee Jones #include <linux/signal.h>
1290550d19SMattias Nilsson #include <linux/mfd/abx500.h>
13ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
14ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500-sysctrl.h>
1590550d19SMattias Nilsson 
1690550d19SMattias Nilsson static struct device *sysctrl_dev;
1790550d19SMattias Nilsson 
18*379749c4SLee Jones void ab8500_power_off(void)
19*379749c4SLee Jones {
20*379749c4SLee Jones 	sigset_t old;
21*379749c4SLee Jones 	sigset_t all;
22*379749c4SLee Jones 
23*379749c4SLee Jones 	sigfillset(&all);
24*379749c4SLee Jones 
25*379749c4SLee Jones 	if (!sigprocmask(SIG_BLOCK, &all, &old)) {
26*379749c4SLee Jones 		(void)ab8500_sysctrl_set(AB8500_STW4500CTRL1,
27*379749c4SLee Jones 					 AB8500_STW4500CTRL1_SWOFF |
28*379749c4SLee Jones 					 AB8500_STW4500CTRL1_SWRESET4500N);
29*379749c4SLee Jones 		(void)sigprocmask(SIG_SETMASK, &old, NULL);
30*379749c4SLee Jones 	}
31*379749c4SLee Jones }
32*379749c4SLee Jones 
3390550d19SMattias Nilsson static inline bool valid_bank(u8 bank)
3490550d19SMattias Nilsson {
3590550d19SMattias Nilsson 	return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
3690550d19SMattias Nilsson 		(bank == AB8500_SYS_CTRL2_BLOCK));
3790550d19SMattias Nilsson }
3890550d19SMattias Nilsson 
3990550d19SMattias Nilsson int ab8500_sysctrl_read(u16 reg, u8 *value)
4090550d19SMattias Nilsson {
4190550d19SMattias Nilsson 	u8 bank;
4290550d19SMattias Nilsson 
4390550d19SMattias Nilsson 	if (sysctrl_dev == NULL)
4490550d19SMattias Nilsson 		return -EAGAIN;
4590550d19SMattias Nilsson 
4690550d19SMattias Nilsson 	bank = (reg >> 8);
4790550d19SMattias Nilsson 	if (!valid_bank(bank))
4890550d19SMattias Nilsson 		return -EINVAL;
4990550d19SMattias Nilsson 
5090550d19SMattias Nilsson 	return abx500_get_register_interruptible(sysctrl_dev, bank,
5190550d19SMattias Nilsson 		(u8)(reg & 0xFF), value);
5290550d19SMattias Nilsson }
5390550d19SMattias Nilsson 
5490550d19SMattias Nilsson int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
5590550d19SMattias Nilsson {
5690550d19SMattias Nilsson 	u8 bank;
5790550d19SMattias Nilsson 
5890550d19SMattias Nilsson 	if (sysctrl_dev == NULL)
5990550d19SMattias Nilsson 		return -EAGAIN;
6090550d19SMattias Nilsson 
6190550d19SMattias Nilsson 	bank = (reg >> 8);
6290550d19SMattias Nilsson 	if (!valid_bank(bank))
6390550d19SMattias Nilsson 		return -EINVAL;
6490550d19SMattias Nilsson 
6590550d19SMattias Nilsson 	return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,
6690550d19SMattias Nilsson 		(u8)(reg & 0xFF), mask, value);
6790550d19SMattias Nilsson }
6890550d19SMattias Nilsson 
69f791be49SBill Pemberton static int ab8500_sysctrl_probe(struct platform_device *pdev)
7090550d19SMattias Nilsson {
71*379749c4SLee Jones 	struct ab8500_platform_data *plat;
72*379749c4SLee Jones 
7390550d19SMattias Nilsson 	sysctrl_dev = &pdev->dev;
74*379749c4SLee Jones 	plat = dev_get_platdata(pdev->dev.parent);
75*379749c4SLee Jones 	if (plat->pm_power_off)
76*379749c4SLee Jones 		pm_power_off = ab8500_power_off;
7790550d19SMattias Nilsson 	return 0;
7890550d19SMattias Nilsson }
7990550d19SMattias Nilsson 
804740f73fSBill Pemberton static int ab8500_sysctrl_remove(struct platform_device *pdev)
8190550d19SMattias Nilsson {
8290550d19SMattias Nilsson 	sysctrl_dev = NULL;
8390550d19SMattias Nilsson 	return 0;
8490550d19SMattias Nilsson }
8590550d19SMattias Nilsson 
8690550d19SMattias Nilsson static struct platform_driver ab8500_sysctrl_driver = {
8790550d19SMattias Nilsson 	.driver = {
8890550d19SMattias Nilsson 		.name = "ab8500-sysctrl",
8990550d19SMattias Nilsson 		.owner = THIS_MODULE,
9090550d19SMattias Nilsson 	},
9190550d19SMattias Nilsson 	.probe = ab8500_sysctrl_probe,
9284449216SBill Pemberton 	.remove = ab8500_sysctrl_remove,
9390550d19SMattias Nilsson };
9490550d19SMattias Nilsson 
9590550d19SMattias Nilsson static int __init ab8500_sysctrl_init(void)
9690550d19SMattias Nilsson {
9790550d19SMattias Nilsson 	return platform_driver_register(&ab8500_sysctrl_driver);
9890550d19SMattias Nilsson }
9990550d19SMattias Nilsson subsys_initcall(ab8500_sysctrl_init);
10090550d19SMattias Nilsson 
10190550d19SMattias Nilsson MODULE_AUTHOR("Mattias Nilsson <[email protected]");
10290550d19SMattias Nilsson MODULE_DESCRIPTION("AB8500 system control driver");
10390550d19SMattias Nilsson MODULE_LICENSE("GPL v2");
104