1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2022 Richtek Technology Corp. 4 * 5 * Author: ChiYuan Huang <cy_huang@richtek.com> 6 */ 7 8 #include <linux/bits.h> 9 #include <linux/bitfield.h> 10 #include <linux/i2c.h> 11 #include <linux/interrupt.h> 12 #include <linux/kernel.h> 13 #include <linux/mfd/core.h> 14 #include <linux/module.h> 15 #include <linux/regmap.h> 16 17 #include "mt6370.h" 18 19 #define MT6370_REG_DEV_INFO 0x100 20 #define MT6370_REG_CHG_IRQ1 0x1C0 21 #define MT6370_REG_CHG_MASK1 0x1E0 22 #define MT6370_REG_MAXADDR 0x1FF 23 24 #define MT6370_VENID_MASK GENMASK(7, 4) 25 26 #define MT6370_NUM_IRQREGS 16 27 #define MT6370_USBC_I2CADDR 0x4E 28 #define MT6370_MAX_ADDRLEN 2 29 30 #define MT6370_VENID_RT5081 0x8 31 #define MT6370_VENID_RT5081A 0xA 32 #define MT6370_VENID_MT6370 0xE 33 #define MT6370_VENID_MT6371 0xF 34 #define MT6370_VENID_MT6372P 0x9 35 #define MT6370_VENID_MT6372CP 0xB 36 37 static const struct regmap_irq mt6370_irqs[] = { 38 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8), 39 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8), 40 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8), 41 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8), 42 REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8), 43 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8), 44 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8), 45 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8), 46 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8), 47 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8), 48 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8), 49 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8), 50 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8), 51 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8), 52 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8), 53 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8), 54 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8), 55 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8), 56 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8), 57 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8), 58 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8), 59 REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8), 60 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8), 61 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8), 62 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8), 63 REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8), 64 REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8), 65 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8), 66 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8), 67 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8), 68 REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8), 69 REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8), 70 REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8), 71 REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8), 72 REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8), 73 REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8), 74 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8), 75 REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8), 76 REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8), 77 REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8), 78 REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET, 8), 79 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DCDT, 8), 80 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_VGOK, 8), 81 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_WDTMR, 8), 82 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_UC, 8), 83 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OC, 8), 84 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OV, 8), 85 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_SWON, 8), 86 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP_D, 8), 87 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP, 8), 88 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP_D, 8), 89 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP, 8), 90 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_STRBPIN, 8), 91 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TORPIN, 8), 92 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TX, 8), 93 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_LVF, 8), 94 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_SHORT, 8), 95 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_SHORT, 8), 96 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_STRB, 8), 97 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB, 8), 98 REGMAP_IRQ_REG_LINE(mT6370_IRQ_FLED2_STRB_TO, 8), 99 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB_TO, 8), 100 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_TOR, 8), 101 REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_TOR, 8), 102 REGMAP_IRQ_REG_LINE(MT6370_IRQ_OTP, 8), 103 REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_OVP, 8), 104 REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_UV, 8), 105 REGMAP_IRQ_REG_LINE(MT6370_IRQ_LDO_OC, 8), 106 REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OCP, 8), 107 REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OVP, 8), 108 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_OCP, 8), 109 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_OCP, 8), 110 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_BST_OCP, 8), 111 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_SCP, 8), 112 REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_SCP, 8), 113 }; 114 115 static const struct regmap_irq_chip mt6370_irq_chip = { 116 .name = "mt6370-irqs", 117 .status_base = MT6370_REG_CHG_IRQ1, 118 .mask_base = MT6370_REG_CHG_MASK1, 119 .num_regs = MT6370_NUM_IRQREGS, 120 .irqs = mt6370_irqs, 121 .num_irqs = ARRAY_SIZE(mt6370_irqs), 122 }; 123 124 static const struct resource mt6370_regulator_irqs[] = { 125 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_SCP, "db_vpos_scp"), 126 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_SCP, "db_vneg_scp"), 127 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_BST_OCP, "db_vbst_ocp"), 128 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_OCP, "db_vpos_ocp"), 129 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_OCP, "db_vneg_ocp"), 130 DEFINE_RES_IRQ_NAMED(MT6370_IRQ_LDO_OC, "ldo_oc"), 131 }; 132 133 static const struct mfd_cell mt6370_devices[] = { 134 MFD_CELL_OF("mt6370-adc", 135 NULL, NULL, 0, 0, "mediatek,mt6370-adc"), 136 MFD_CELL_OF("mt6370-charger", 137 NULL, NULL, 0, 0, "mediatek,mt6370-charger"), 138 MFD_CELL_OF("mt6370-flashlight", 139 NULL, NULL, 0, 0, "mediatek,mt6370-flashlight"), 140 MFD_CELL_OF("mt6370-indicator", 141 NULL, NULL, 0, 0, "mediatek,mt6370-indicator"), 142 MFD_CELL_OF("mt6370-tcpc", 143 NULL, NULL, 0, 0, "mediatek,mt6370-tcpc"), 144 MFD_CELL_RES("mt6370-regulator", mt6370_regulator_irqs), 145 }; 146 147 static const struct mfd_cell mt6370_exclusive_devices[] = { 148 MFD_CELL_OF("mt6370-backlight", 149 NULL, NULL, 0, 0, "mediatek,mt6370-backlight"), 150 }; 151 152 static const struct mfd_cell mt6372_exclusive_devices[] = { 153 MFD_CELL_OF("mt6370-backlight", 154 NULL, NULL, 0, 0, "mediatek,mt6372-backlight"), 155 }; 156 157 static int mt6370_check_vendor_info(struct device *dev, struct regmap *rmap, 158 int *vid) 159 { 160 unsigned int devinfo; 161 int ret; 162 163 ret = regmap_read(rmap, MT6370_REG_DEV_INFO, &devinfo); 164 if (ret) 165 return ret; 166 167 *vid = FIELD_GET(MT6370_VENID_MASK, devinfo); 168 switch (*vid) { 169 case MT6370_VENID_RT5081: 170 case MT6370_VENID_RT5081A: 171 case MT6370_VENID_MT6370: 172 case MT6370_VENID_MT6371: 173 case MT6370_VENID_MT6372P: 174 case MT6370_VENID_MT6372CP: 175 return 0; 176 default: 177 dev_err(dev, "Unknown Vendor ID 0x%02x\n", devinfo); 178 return -ENODEV; 179 } 180 } 181 182 static int mt6370_regmap_read(void *context, const void *reg_buf, 183 size_t reg_size, void *val_buf, size_t val_size) 184 { 185 struct mt6370_info *info = context; 186 const u8 *u8_buf = reg_buf; 187 u8 bank_idx, bank_addr; 188 int ret; 189 190 bank_idx = u8_buf[0]; 191 bank_addr = u8_buf[1]; 192 193 ret = i2c_smbus_read_i2c_block_data(info->i2c[bank_idx], bank_addr, 194 val_size, val_buf); 195 if (ret < 0) 196 return ret; 197 198 if (ret != val_size) 199 return -EIO; 200 201 return 0; 202 } 203 204 static int mt6370_regmap_write(void *context, const void *data, size_t count) 205 { 206 struct mt6370_info *info = context; 207 const u8 *u8_buf = data; 208 u8 bank_idx, bank_addr; 209 int len = count - MT6370_MAX_ADDRLEN; 210 211 bank_idx = u8_buf[0]; 212 bank_addr = u8_buf[1]; 213 214 return i2c_smbus_write_i2c_block_data(info->i2c[bank_idx], bank_addr, 215 len, data + MT6370_MAX_ADDRLEN); 216 } 217 218 static const struct regmap_bus mt6370_regmap_bus = { 219 .read = mt6370_regmap_read, 220 .write = mt6370_regmap_write, 221 }; 222 223 static const struct regmap_config mt6370_regmap_config = { 224 .reg_bits = 16, 225 .val_bits = 8, 226 .reg_format_endian = REGMAP_ENDIAN_BIG, 227 .max_register = MT6370_REG_MAXADDR, 228 }; 229 230 static int mt6370_probe(struct i2c_client *i2c) 231 { 232 struct mt6370_info *info; 233 struct i2c_client *usbc_i2c; 234 struct regmap *regmap; 235 struct device *dev = &i2c->dev; 236 int ret, vid; 237 238 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 239 if (!info) 240 return -ENOMEM; 241 242 usbc_i2c = devm_i2c_new_dummy_device(dev, i2c->adapter, 243 MT6370_USBC_I2CADDR); 244 if (IS_ERR(usbc_i2c)) 245 return dev_err_probe(dev, PTR_ERR(usbc_i2c), 246 "Failed to register USBC I2C client\n"); 247 248 /* Assign I2C client for PMU and TypeC */ 249 info->i2c[MT6370_PMU_I2C] = i2c; 250 info->i2c[MT6370_USBC_I2C] = usbc_i2c; 251 252 regmap = devm_regmap_init(dev, &mt6370_regmap_bus, 253 info, &mt6370_regmap_config); 254 if (IS_ERR(regmap)) 255 return dev_err_probe(dev, PTR_ERR(regmap), 256 "Failed to init regmap\n"); 257 258 ret = mt6370_check_vendor_info(dev, regmap, &vid); 259 if (ret) 260 return dev_err_probe(dev, ret, "Failed to check vendor info\n"); 261 262 ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq, 263 IRQF_ONESHOT, -1, &mt6370_irq_chip, 264 &info->irq_data); 265 if (ret) 266 return dev_err_probe(dev, ret, "Failed to add irq chip\n"); 267 268 switch (vid) { 269 case MT6370_VENID_MT6372P: 270 case MT6370_VENID_MT6372CP: 271 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 272 mt6372_exclusive_devices, 273 ARRAY_SIZE(mt6372_exclusive_devices), 274 NULL, 0, 275 regmap_irq_get_domain(info->irq_data)); 276 break; 277 default: 278 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 279 mt6370_exclusive_devices, 280 ARRAY_SIZE(mt6370_exclusive_devices), 281 NULL, 0, 282 regmap_irq_get_domain(info->irq_data)); 283 break; 284 } 285 286 if (ret) 287 return dev_err_probe(dev, ret, "Failed to add the exclusive devices\n"); 288 289 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 290 mt6370_devices, ARRAY_SIZE(mt6370_devices), 291 NULL, 0, 292 regmap_irq_get_domain(info->irq_data)); 293 } 294 295 static const struct of_device_id mt6370_match_table[] = { 296 { .compatible = "mediatek,mt6370" }, 297 {} 298 }; 299 MODULE_DEVICE_TABLE(of, mt6370_match_table); 300 301 static struct i2c_driver mt6370_driver = { 302 .driver = { 303 .name = "mt6370", 304 .of_match_table = mt6370_match_table, 305 }, 306 .probe = mt6370_probe, 307 }; 308 module_i2c_driver(mt6370_driver); 309 310 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 311 MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver"); 312 MODULE_LICENSE("GPL v2"); 313