233 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) STMicroelectronics 20183// Author: Pascal Paillet <p.paillet@st.com>4 5#include <linux/i2c.h>6#include <linux/interrupt.h>7#include <linux/mfd/core.h>8#include <linux/mfd/stpmic1.h>9#include <linux/module.h>10#include <linux/reboot.h>11#include <linux/of.h>12#include <linux/of_irq.h>13#include <linux/of_platform.h>14#include <linux/pm_wakeirq.h>15#include <linux/regmap.h>16 17#include <dt-bindings/mfd/st,stpmic1.h>18 19#define STPMIC1_MAIN_IRQ 020 21static const struct regmap_range stpmic1_readable_ranges[] = {22 regmap_reg_range(TURN_ON_SR, VERSION_SR),23 regmap_reg_range(MAIN_CR, LDO6_STDBY_CR),24 regmap_reg_range(BST_SW_CR, BST_SW_CR),25 regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),26 regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),27 regmap_reg_range(INT_MASK_R1, INT_MASK_R4),28 regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),29 regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),30 regmap_reg_range(INT_SRC_R1, INT_SRC_R1),31};32 33static const struct regmap_range stpmic1_writeable_ranges[] = {34 regmap_reg_range(MAIN_CR, LDO6_STDBY_CR),35 regmap_reg_range(BST_SW_CR, BST_SW_CR),36 regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),37 regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),38 regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),39};40 41static const struct regmap_range stpmic1_volatile_ranges[] = {42 regmap_reg_range(TURN_ON_SR, VERSION_SR),43 regmap_reg_range(WCHDG_CR, WCHDG_CR),44 regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),45 regmap_reg_range(INT_SRC_R1, INT_SRC_R4),46};47 48static const struct regmap_access_table stpmic1_readable_table = {49 .yes_ranges = stpmic1_readable_ranges,50 .n_yes_ranges = ARRAY_SIZE(stpmic1_readable_ranges),51};52 53static const struct regmap_access_table stpmic1_writeable_table = {54 .yes_ranges = stpmic1_writeable_ranges,55 .n_yes_ranges = ARRAY_SIZE(stpmic1_writeable_ranges),56};57 58static const struct regmap_access_table stpmic1_volatile_table = {59 .yes_ranges = stpmic1_volatile_ranges,60 .n_yes_ranges = ARRAY_SIZE(stpmic1_volatile_ranges),61};62 63static const struct regmap_config stpmic1_regmap_config = {64 .reg_bits = 8,65 .val_bits = 8,66 .cache_type = REGCACHE_MAPLE,67 .max_register = PMIC_MAX_REGISTER_ADDRESS,68 .rd_table = &stpmic1_readable_table,69 .wr_table = &stpmic1_writeable_table,70 .volatile_table = &stpmic1_volatile_table,71};72 73static const struct regmap_irq stpmic1_irqs[] = {74 REGMAP_IRQ_REG(IT_PONKEY_F, 0, 0x01),75 REGMAP_IRQ_REG(IT_PONKEY_R, 0, 0x02),76 REGMAP_IRQ_REG(IT_WAKEUP_F, 0, 0x04),77 REGMAP_IRQ_REG(IT_WAKEUP_R, 0, 0x08),78 REGMAP_IRQ_REG(IT_VBUS_OTG_F, 0, 0x10),79 REGMAP_IRQ_REG(IT_VBUS_OTG_R, 0, 0x20),80 REGMAP_IRQ_REG(IT_SWOUT_F, 0, 0x40),81 REGMAP_IRQ_REG(IT_SWOUT_R, 0, 0x80),82 83 REGMAP_IRQ_REG(IT_CURLIM_BUCK1, 1, 0x01),84 REGMAP_IRQ_REG(IT_CURLIM_BUCK2, 1, 0x02),85 REGMAP_IRQ_REG(IT_CURLIM_BUCK3, 1, 0x04),86 REGMAP_IRQ_REG(IT_CURLIM_BUCK4, 1, 0x08),87 REGMAP_IRQ_REG(IT_OCP_OTG, 1, 0x10),88 REGMAP_IRQ_REG(IT_OCP_SWOUT, 1, 0x20),89 REGMAP_IRQ_REG(IT_OCP_BOOST, 1, 0x40),90 REGMAP_IRQ_REG(IT_OVP_BOOST, 1, 0x80),91 92 REGMAP_IRQ_REG(IT_CURLIM_LDO1, 2, 0x01),93 REGMAP_IRQ_REG(IT_CURLIM_LDO2, 2, 0x02),94 REGMAP_IRQ_REG(IT_CURLIM_LDO3, 2, 0x04),95 REGMAP_IRQ_REG(IT_CURLIM_LDO4, 2, 0x08),96 REGMAP_IRQ_REG(IT_CURLIM_LDO5, 2, 0x10),97 REGMAP_IRQ_REG(IT_CURLIM_LDO6, 2, 0x20),98 REGMAP_IRQ_REG(IT_SHORT_SWOTG, 2, 0x40),99 REGMAP_IRQ_REG(IT_SHORT_SWOUT, 2, 0x80),100 101 REGMAP_IRQ_REG(IT_TWARN_F, 3, 0x01),102 REGMAP_IRQ_REG(IT_TWARN_R, 3, 0x02),103 REGMAP_IRQ_REG(IT_VINLOW_F, 3, 0x04),104 REGMAP_IRQ_REG(IT_VINLOW_R, 3, 0x08),105 REGMAP_IRQ_REG(IT_SWIN_F, 3, 0x40),106 REGMAP_IRQ_REG(IT_SWIN_R, 3, 0x80),107};108 109static const struct regmap_irq_chip stpmic1_regmap_irq_chip = {110 .name = "pmic_irq",111 .status_base = INT_PENDING_R1,112 .mask_base = INT_SET_MASK_R1,113 .unmask_base = INT_CLEAR_MASK_R1,114 .mask_unmask_non_inverted = true,115 .ack_base = INT_CLEAR_R1,116 .num_regs = STPMIC1_PMIC_NUM_IRQ_REGS,117 .irqs = stpmic1_irqs,118 .num_irqs = ARRAY_SIZE(stpmic1_irqs),119};120 121static int stpmic1_power_off(struct sys_off_data *data)122{123 struct stpmic1 *ddata = data->cb_data;124 125 regmap_update_bits(ddata->regmap, MAIN_CR,126 SOFTWARE_SWITCH_OFF, SOFTWARE_SWITCH_OFF);127 128 return NOTIFY_DONE;129}130 131static int stpmic1_probe(struct i2c_client *i2c)132{133 struct stpmic1 *ddata;134 struct device *dev = &i2c->dev;135 int ret;136 struct device_node *np = dev->of_node;137 u32 reg;138 139 ddata = devm_kzalloc(dev, sizeof(struct stpmic1), GFP_KERNEL);140 if (!ddata)141 return -ENOMEM;142 143 i2c_set_clientdata(i2c, ddata);144 ddata->dev = dev;145 146 ddata->regmap = devm_regmap_init_i2c(i2c, &stpmic1_regmap_config);147 if (IS_ERR(ddata->regmap))148 return PTR_ERR(ddata->regmap);149 150 ddata->irq = of_irq_get(np, STPMIC1_MAIN_IRQ);151 if (ddata->irq < 0) {152 dev_err(dev, "Failed to get main IRQ: %d\n", ddata->irq);153 return ddata->irq;154 }155 156 ret = regmap_read(ddata->regmap, VERSION_SR, ®);157 if (ret) {158 dev_err(dev, "Unable to read PMIC version\n");159 return ret;160 }161 dev_info(dev, "PMIC Chip Version: 0x%x\n", reg);162 163 /* Initialize PMIC IRQ Chip & associated IRQ domains */164 ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,165 IRQF_ONESHOT | IRQF_SHARED,166 0, &stpmic1_regmap_irq_chip,167 &ddata->irq_data);168 if (ret) {169 dev_err(dev, "IRQ Chip registration failed: %d\n", ret);170 return ret;171 }172 173 ret = devm_register_sys_off_handler(ddata->dev,174 SYS_OFF_MODE_POWER_OFF,175 SYS_OFF_PRIO_DEFAULT,176 stpmic1_power_off,177 ddata);178 if (ret) {179 dev_err(ddata->dev, "failed to register sys-off handler: %d\n", ret);180 return ret;181 }182 183 return devm_of_platform_populate(dev);184}185 186static int stpmic1_suspend(struct device *dev)187{188 struct i2c_client *i2c = to_i2c_client(dev);189 struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);190 191 disable_irq(pmic_dev->irq);192 193 return 0;194}195 196static int stpmic1_resume(struct device *dev)197{198 struct i2c_client *i2c = to_i2c_client(dev);199 struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);200 int ret;201 202 ret = regcache_sync(pmic_dev->regmap);203 if (ret)204 return ret;205 206 enable_irq(pmic_dev->irq);207 208 return 0;209}210 211static DEFINE_SIMPLE_DEV_PM_OPS(stpmic1_pm, stpmic1_suspend, stpmic1_resume);212 213static const struct of_device_id stpmic1_of_match[] = {214 { .compatible = "st,stpmic1", },215 {},216};217MODULE_DEVICE_TABLE(of, stpmic1_of_match);218 219static struct i2c_driver stpmic1_driver = {220 .driver = {221 .name = "stpmic1",222 .of_match_table = stpmic1_of_match,223 .pm = pm_sleep_ptr(&stpmic1_pm),224 },225 .probe = stpmic1_probe,226};227 228module_i2c_driver(stpmic1_driver);229 230MODULE_DESCRIPTION("STPMIC1 PMIC Driver");231MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");232MODULE_LICENSE("GPL v2");233