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> 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 #include <linux/pm.h> 11 #include <linux/signal.h> 12 #include <linux/mfd/abx500.h> 13 #include <linux/mfd/abx500/ab8500.h> 14 #include <linux/mfd/abx500/ab8500-sysctrl.h> 15 16 static struct device *sysctrl_dev; 17 18 void 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 33 static inline bool valid_bank(u8 bank) 34 { 35 return ((bank == AB8500_SYS_CTRL1_BLOCK) || 36 (bank == AB8500_SYS_CTRL2_BLOCK)); 37 } 38 39 int 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 54 int 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 69 static int ab8500_sysctrl_probe(struct platform_device *pdev) 70 { 71 struct ab8500_platform_data *plat; 72 73 sysctrl_dev = &pdev->dev; 74 plat = dev_get_platdata(pdev->dev.parent); 75 if (plat->pm_power_off) 76 pm_power_off = ab8500_power_off; 77 return 0; 78 } 79 80 static int ab8500_sysctrl_remove(struct platform_device *pdev) 81 { 82 sysctrl_dev = NULL; 83 return 0; 84 } 85 86 static struct platform_driver ab8500_sysctrl_driver = { 87 .driver = { 88 .name = "ab8500-sysctrl", 89 .owner = THIS_MODULE, 90 }, 91 .probe = ab8500_sysctrl_probe, 92 .remove = ab8500_sysctrl_remove, 93 }; 94 95 static int __init ab8500_sysctrl_init(void) 96 { 97 return platform_driver_register(&ab8500_sysctrl_driver); 98 } 99 subsys_initcall(ab8500_sysctrl_init); 100 101 MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com"); 102 MODULE_DESCRIPTION("AB8500 system control driver"); 103 MODULE_LICENSE("GPL v2"); 104