1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2022 Richtek Technology Corp.
5 * Author: ChiYuan Huang <cy_huang@richtek.com>
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>
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
24 #define MT6370_VENID_MASK GENMASK(7, 4)
26 #define MT6370_NUM_IRQREGS 16
27 #define MT6370_USBC_I2CADDR 0x4E
28 #define MT6370_MAX_ADDRLEN 2
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
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),
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
,
121 .num_irqs
= ARRAY_SIZE(mt6370_irqs
),
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"),
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
),
147 static const struct mfd_cell mt6370_exclusive_devices
[] = {
148 MFD_CELL_OF("mt6370-backlight",
149 NULL
, NULL
, 0, 0, "mediatek,mt6370-backlight"),
152 static const struct mfd_cell mt6372_exclusive_devices
[] = {
153 MFD_CELL_OF("mt6370-backlight",
154 NULL
, NULL
, 0, 0, "mediatek,mt6372-backlight"),
157 static int mt6370_check_vendor_info(struct device
*dev
, struct regmap
*rmap
,
160 unsigned int devinfo
;
163 ret
= regmap_read(rmap
, MT6370_REG_DEV_INFO
, &devinfo
);
167 *vid
= FIELD_GET(MT6370_VENID_MASK
, devinfo
);
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
:
177 dev_err(dev
, "Unknown Vendor ID 0x%02x\n", devinfo
);
182 static int mt6370_regmap_read(void *context
, const void *reg_buf
,
183 size_t reg_size
, void *val_buf
, size_t val_size
)
185 struct mt6370_info
*info
= context
;
186 const u8
*u8_buf
= reg_buf
;
187 u8 bank_idx
, bank_addr
;
190 bank_idx
= u8_buf
[0];
191 bank_addr
= u8_buf
[1];
193 ret
= i2c_smbus_read_i2c_block_data(info
->i2c
[bank_idx
], bank_addr
,
204 static int mt6370_regmap_write(void *context
, const void *data
, size_t count
)
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
;
211 bank_idx
= u8_buf
[0];
212 bank_addr
= u8_buf
[1];
214 return i2c_smbus_write_i2c_block_data(info
->i2c
[bank_idx
], bank_addr
,
215 len
, data
+ MT6370_MAX_ADDRLEN
);
218 static const struct regmap_bus mt6370_regmap_bus
= {
219 .read
= mt6370_regmap_read
,
220 .write
= mt6370_regmap_write
,
223 static const struct regmap_config mt6370_regmap_config
= {
226 .reg_format_endian
= REGMAP_ENDIAN_BIG
,
227 .max_register
= MT6370_REG_MAXADDR
,
230 static int mt6370_probe(struct i2c_client
*i2c
)
232 struct mt6370_info
*info
;
233 struct i2c_client
*usbc_i2c
;
234 struct regmap
*regmap
;
235 struct device
*dev
= &i2c
->dev
;
238 info
= devm_kzalloc(dev
, sizeof(*info
), GFP_KERNEL
);
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");
248 /* Assign I2C client for PMU and TypeC */
249 info
->i2c
[MT6370_PMU_I2C
] = i2c
;
250 info
->i2c
[MT6370_USBC_I2C
] = usbc_i2c
;
252 regmap
= devm_regmap_init(dev
, &mt6370_regmap_bus
,
253 info
, &mt6370_regmap_config
);
255 return dev_err_probe(dev
, PTR_ERR(regmap
),
256 "Failed to init regmap\n");
258 ret
= mt6370_check_vendor_info(dev
, regmap
, &vid
);
260 return dev_err_probe(dev
, ret
, "Failed to check vendor info\n");
262 ret
= devm_regmap_add_irq_chip(dev
, regmap
, i2c
->irq
,
263 IRQF_ONESHOT
, -1, &mt6370_irq_chip
,
266 return dev_err_probe(dev
, ret
, "Failed to add irq chip\n");
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
),
275 regmap_irq_get_domain(info
->irq_data
));
278 ret
= devm_mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
,
279 mt6370_exclusive_devices
,
280 ARRAY_SIZE(mt6370_exclusive_devices
),
282 regmap_irq_get_domain(info
->irq_data
));
287 return dev_err_probe(dev
, ret
, "Failed to add the exclusive devices\n");
289 return devm_mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
,
290 mt6370_devices
, ARRAY_SIZE(mt6370_devices
),
292 regmap_irq_get_domain(info
->irq_data
));
295 static const struct of_device_id mt6370_match_table
[] = {
296 { .compatible
= "mediatek,mt6370" },
299 MODULE_DEVICE_TABLE(of
, mt6370_match_table
);
301 static struct i2c_driver mt6370_driver
= {
304 .of_match_table
= mt6370_match_table
,
306 .probe
= mt6370_probe
,
308 module_i2c_driver(mt6370_driver
);
310 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
311 MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver");
312 MODULE_LICENSE("GPL v2");