1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PFSM (Pre-configurable Finite State Machine) driver for the following 4 * PMICs: 5 * - LP8764 6 * - TPS65224 7 * - TPS652G1 8 * - TPS6594 9 * - TPS6593 10 * 11 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 12 */ 13 14 #include <linux/errno.h> 15 #include <linux/fs.h> 16 #include <linux/interrupt.h> 17 #include <linux/ioctl.h> 18 #include <linux/miscdevice.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/regmap.h> 22 23 #include <linux/mfd/tps6594.h> 24 25 #include <linux/tps6594_pfsm.h> 26 27 #define TPS6594_STARTUP_DEST_MCU_ONLY_VAL 2 28 #define TPS6594_STARTUP_DEST_ACTIVE_VAL 3 29 #define TPS6594_STARTUP_DEST_SHIFT 5 30 #define TPS6594_STARTUP_DEST_MCU_ONLY (TPS6594_STARTUP_DEST_MCU_ONLY_VAL \ 31 << TPS6594_STARTUP_DEST_SHIFT) 32 #define TPS6594_STARTUP_DEST_ACTIVE (TPS6594_STARTUP_DEST_ACTIVE_VAL \ 33 << TPS6594_STARTUP_DEST_SHIFT) 34 35 /* 36 * To update the PMIC firmware, the user must be able to access 37 * page 0 (user registers) and page 1 (NVM control and configuration). 38 */ 39 #define TPS6594_PMIC_MAX_POS 0x200 40 41 #define TPS6594_FILE_TO_PFSM(f) container_of((f)->private_data, struct tps6594_pfsm, miscdev) 42 43 /** 44 * struct tps6594_pfsm - device private data structure 45 * 46 * @miscdev: misc device infos 47 * @regmap: regmap for accessing the device registers 48 * @chip_id: chip identifier of the device 49 */ 50 struct tps6594_pfsm { 51 struct miscdevice miscdev; 52 struct regmap *regmap; 53 unsigned long chip_id; 54 }; 55 56 static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf, 57 size_t count, loff_t *ppos) 58 { 59 struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); 60 loff_t pos = *ppos; 61 unsigned int val; 62 int ret; 63 int i; 64 65 if (pos < 0) 66 return -EINVAL; 67 if (pos >= TPS6594_PMIC_MAX_POS) 68 return 0; 69 if (count > TPS6594_PMIC_MAX_POS - pos) 70 count = TPS6594_PMIC_MAX_POS - pos; 71 72 for (i = 0 ; i < count ; i++) { 73 ret = regmap_read(pfsm->regmap, pos + i, &val); 74 if (ret) 75 return ret; 76 77 if (put_user(val, buf + i)) 78 return -EFAULT; 79 } 80 81 *ppos = pos + count; 82 83 return count; 84 } 85 86 static ssize_t tps6594_pfsm_write(struct file *f, const char __user *buf, 87 size_t count, loff_t *ppos) 88 { 89 struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); 90 loff_t pos = *ppos; 91 char val; 92 int ret; 93 int i; 94 95 if (pos < 0) 96 return -EINVAL; 97 if (pos >= TPS6594_PMIC_MAX_POS || !count) 98 return 0; 99 if (count > TPS6594_PMIC_MAX_POS - pos) 100 count = TPS6594_PMIC_MAX_POS - pos; 101 102 for (i = 0 ; i < count ; i++) { 103 if (get_user(val, buf + i)) 104 return -EFAULT; 105 106 ret = regmap_write(pfsm->regmap, pos + i, val); 107 if (ret) 108 return ret; 109 } 110 111 *ppos = pos + count; 112 113 return count; 114 } 115 116 static int tps6594_pfsm_configure_ret_trig(struct regmap *regmap, u8 gpio_ret, u8 ddr_ret) 117 { 118 int ret; 119 120 if (gpio_ret) 121 ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 122 TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6)); 123 else 124 ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 125 TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6)); 126 if (ret) 127 return ret; 128 129 if (ddr_ret) 130 ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 131 TPS6594_BIT_TRIGGER_I2C(7)); 132 else 133 ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 134 TPS6594_BIT_TRIGGER_I2C(7)); 135 136 return ret; 137 } 138 139 static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 140 { 141 struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f); 142 struct pmic_state_opt state_opt; 143 void __user *argp = (void __user *)arg; 144 unsigned int regmap_reg, mask; 145 int ret = -ENOIOCTLCMD; 146 147 switch (cmd) { 148 case PMIC_GOTO_STANDBY: 149 /* Disable LP mode on TPS6594 Family PMIC */ 150 if (pfsm->chip_id != TPS65224 && pfsm->chip_id != TPS652G1) { 151 ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, 152 TPS6594_BIT_LP_STANDBY_SEL); 153 154 if (ret) 155 return ret; 156 } 157 158 /* Force trigger */ 159 ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 160 TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); 161 break; 162 case PMIC_GOTO_LP_STANDBY: 163 /* TPS65224/TPS652G1 does not support LP STANDBY */ 164 if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 165 return ret; 166 167 /* Enable LP mode */ 168 ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, 169 TPS6594_BIT_LP_STANDBY_SEL); 170 if (ret) 171 return ret; 172 173 /* Force trigger */ 174 ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 175 TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); 176 break; 177 case PMIC_UPDATE_PGM: 178 /* Force trigger */ 179 ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS, 180 TPS6594_BIT_TRIGGER_I2C(3), TPS6594_BIT_TRIGGER_I2C(3)); 181 break; 182 case PMIC_SET_ACTIVE_STATE: 183 /* Modify NSLEEP1-2 bits */ 184 ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, 185 TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); 186 break; 187 case PMIC_SET_MCU_ONLY_STATE: 188 /* TPS65224/TPS652G1 does not support MCU_ONLY_STATE */ 189 if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 190 return ret; 191 192 if (copy_from_user(&state_opt, argp, sizeof(state_opt))) 193 return -EFAULT; 194 195 /* Configure retention triggers */ 196 ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention, 197 state_opt.ddr_retention); 198 if (ret) 199 return ret; 200 201 /* Modify NSLEEP1-2 bits */ 202 ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, 203 TPS6594_BIT_NSLEEP1B); 204 if (ret) 205 return ret; 206 207 ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, 208 TPS6594_BIT_NSLEEP2B); 209 break; 210 case PMIC_SET_RETENTION_STATE: 211 if (copy_from_user(&state_opt, argp, sizeof(state_opt))) 212 return -EFAULT; 213 214 /* Configure wake-up destination */ 215 if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) { 216 regmap_reg = TPS65224_REG_STARTUP_CTRL; 217 mask = TPS65224_MASK_STARTUP_DEST; 218 } else { 219 regmap_reg = TPS6594_REG_RTC_CTRL_2; 220 mask = TPS6594_MASK_STARTUP_DEST; 221 } 222 223 if (state_opt.mcu_only_startup_dest) 224 ret = regmap_write_bits(pfsm->regmap, regmap_reg, 225 mask, TPS6594_STARTUP_DEST_MCU_ONLY); 226 else 227 ret = regmap_write_bits(pfsm->regmap, regmap_reg, 228 mask, TPS6594_STARTUP_DEST_ACTIVE); 229 if (ret) 230 return ret; 231 232 /* Configure retention triggers */ 233 ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention, 234 state_opt.ddr_retention); 235 if (ret) 236 return ret; 237 238 /* Modify NSLEEP1-2 bits */ 239 if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 240 ret = regmap_clear_bits(pfsm->regmap, 241 TPS6594_REG_FSM_NSLEEP_TRIGGERS, 242 TPS6594_BIT_NSLEEP1B); 243 else 244 ret = regmap_clear_bits(pfsm->regmap, 245 TPS6594_REG_FSM_NSLEEP_TRIGGERS, 246 TPS6594_BIT_NSLEEP2B); 247 break; 248 } 249 250 return ret; 251 } 252 253 static const struct file_operations tps6594_pfsm_fops = { 254 .owner = THIS_MODULE, 255 .llseek = generic_file_llseek, 256 .read = tps6594_pfsm_read, 257 .write = tps6594_pfsm_write, 258 .unlocked_ioctl = tps6594_pfsm_ioctl, 259 .compat_ioctl = compat_ptr_ioctl, 260 }; 261 262 static irqreturn_t tps6594_pfsm_isr(int irq, void *dev_id) 263 { 264 struct platform_device *pdev = dev_id; 265 int i; 266 267 for (i = 0 ; i < pdev->num_resources ; i++) { 268 if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) { 269 dev_err(pdev->dev.parent, "%s event detected\n", pdev->resource[i].name); 270 return IRQ_HANDLED; 271 } 272 } 273 274 return IRQ_NONE; 275 } 276 277 static int tps6594_pfsm_probe(struct platform_device *pdev) 278 { 279 struct tps6594_pfsm *pfsm; 280 struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); 281 struct device *dev = &pdev->dev; 282 int irq; 283 int ret; 284 int i; 285 286 pfsm = devm_kzalloc(dev, sizeof(struct tps6594_pfsm), GFP_KERNEL); 287 if (!pfsm) 288 return -ENOMEM; 289 290 pfsm->regmap = tps->regmap; 291 292 pfsm->miscdev.minor = MISC_DYNAMIC_MINOR; 293 pfsm->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "pfsm-%ld-0x%02x", 294 tps->chip_id, tps->reg); 295 if (!pfsm->miscdev.name) 296 return -ENOMEM; 297 298 pfsm->miscdev.fops = &tps6594_pfsm_fops; 299 pfsm->miscdev.parent = dev->parent; 300 pfsm->chip_id = tps->chip_id; 301 302 for (i = 0 ; i < pdev->num_resources ; i++) { 303 irq = platform_get_irq_byname(pdev, pdev->resource[i].name); 304 if (irq < 0) 305 return irq; 306 307 ret = devm_request_threaded_irq(dev, irq, NULL, 308 tps6594_pfsm_isr, IRQF_ONESHOT, 309 pdev->resource[i].name, pdev); 310 if (ret) 311 return dev_err_probe(dev, ret, "Failed to request irq\n"); 312 } 313 314 platform_set_drvdata(pdev, pfsm); 315 316 return misc_register(&pfsm->miscdev); 317 } 318 319 static void tps6594_pfsm_remove(struct platform_device *pdev) 320 { 321 struct tps6594_pfsm *pfsm = platform_get_drvdata(pdev); 322 323 misc_deregister(&pfsm->miscdev); 324 } 325 326 static struct platform_driver tps6594_pfsm_driver = { 327 .driver = { 328 .name = "tps6594-pfsm", 329 }, 330 .probe = tps6594_pfsm_probe, 331 .remove = tps6594_pfsm_remove, 332 }; 333 334 module_platform_driver(tps6594_pfsm_driver); 335 336 MODULE_ALIAS("platform:tps6594-pfsm"); 337 MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>"); 338 MODULE_DESCRIPTION("TPS6594 Pre-configurable Finite State Machine Driver"); 339 MODULE_LICENSE("GPL"); 340