1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 MediaTek Inc.
5 * Author: Gene Chen <gene_chen@richtek.com>
8 #include <linux/cleanup.h>
9 #include <linux/crc8.h>
10 #include <linux/i2c.h>
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/mfd/core.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17 #include <linux/slab.h>
20 MT6360_SLAVE_TCPC
= 0,
28 struct i2c_client
*i2c
[MT6360_SLAVE_MAX
];
30 struct regmap
*regmap
;
31 struct regmap_irq_chip_data
*irq_data
;
32 unsigned int chip_rev
;
33 u8 crc8_tbl
[CRC8_TABLE_SIZE
];
36 #define MT6360_TCPC_SLAVEID 0x4E
37 #define MT6360_PMIC_SLAVEID 0x1A
38 #define MT6360_LDO_SLAVEID 0x64
39 #define MT6360_PMU_SLAVEID 0x34
41 #define MT6360_REG_TCPCSTART 0x00
42 #define MT6360_REG_TCPCEND 0xFF
43 #define MT6360_REG_PMICSTART 0x100
44 #define MT6360_REG_PMICEND 0x13B
45 #define MT6360_REG_LDOSTART 0x200
46 #define MT6360_REG_LDOEND 0x21C
47 #define MT6360_REG_PMUSTART 0x300
48 #define MT6360_PMU_DEV_INFO 0x300
49 #define MT6360_PMU_CHG_IRQ1 0x3D0
50 #define MT6360_PMU_CHG_MASK1 0x3F0
51 #define MT6360_REG_PMUEND 0x3FF
53 #define MT6360_PMU_IRQ_REGNUM 16
55 #define CHIP_VEN_MASK 0xF0
56 #define CHIP_VEN_MT6360 0x50
57 #define CHIP_REV_MASK 0x0F
59 #define MT6360_ADDRESS_MASK 0x3F
60 #define MT6360_DATA_SIZE_1_BYTE 0x00
61 #define MT6360_DATA_SIZE_2_BYTES 0x40
62 #define MT6360_DATA_SIZE_3_BYTES 0x80
63 #define MT6360_DATA_SIZE_4_BYTES 0xC0
65 #define MT6360_CRC8_POLYNOMIAL 0x7
67 #define MT6360_CRC_I2C_ADDR_SIZE 1
68 #define MT6360_CRC_REG_ADDR_SIZE 1
69 /* prealloca read size = i2c device addr + i2c reg addr + val ... + crc8 */
70 #define MT6360_ALLOC_READ_SIZE(_size) (_size + 3)
71 /* prealloca write size = i2c device addr + i2c reg addr + val ... + crc8 + dummy byte */
72 #define MT6360_ALLOC_WRITE_SIZE(_size) (_size + 4)
73 #define MT6360_CRC_PREDATA_OFFSET (MT6360_CRC_I2C_ADDR_SIZE + MT6360_CRC_REG_ADDR_SIZE)
74 #define MT6360_CRC_CRC8_SIZE 1
75 #define MT6360_CRC_DUMMY_BYTE_SIZE 1
76 #define MT6360_REGMAP_REG_BYTE_SIZE 2
77 #define I2C_ADDR_XLATE_8BIT(_addr, _rw) (((_addr & 0x7F) << 1) + _rw)
80 #define MT6360_CHG_TREG_EVT 4
81 #define MT6360_CHG_AICR_EVT 5
82 #define MT6360_CHG_MIVR_EVT 6
83 #define MT6360_PWR_RDY_EVT 7
85 #define MT6360_CHG_BATSYSUV_EVT 9
86 #define MT6360_FLED_CHG_VINOVP_EVT 11
87 #define MT6360_CHG_VSYSUV_EVT 12
88 #define MT6360_CHG_VSYSOV_EVT 13
89 #define MT6360_CHG_VBATOV_EVT 14
90 #define MT6360_CHG_VBUSOV_EVT 15
91 /* REG 2 -> 16 ~ 23 */
92 /* REG 3 -> 24 ~ 31 */
93 #define MT6360_WD_PMU_DET 25
94 #define MT6360_WD_PMU_DONE 26
95 #define MT6360_CHG_TMRI 27
96 #define MT6360_CHG_ADPBADI 29
97 #define MT6360_CHG_RVPI 30
98 #define MT6360_OTPI 31
99 /* REG 4 -> 32 ~ 39 */
100 #define MT6360_CHG_AICCMEASL 32
101 #define MT6360_CHGDET_DONEI 34
102 #define MT6360_WDTMRI 35
103 #define MT6360_SSFINISHI 36
104 #define MT6360_CHG_RECHGI 37
105 #define MT6360_CHG_TERMI 38
106 #define MT6360_CHG_IEOCI 39
107 /* REG 5 -> 40 ~ 47 */
108 #define MT6360_PUMPX_DONEI 40
109 #define MT6360_BAT_OVP_ADC_EVT 41
110 #define MT6360_TYPEC_OTP_EVT 42
111 #define MT6360_ADC_WAKEUP_EVT 43
112 #define MT6360_ADC_DONEI 44
113 #define MT6360_BST_BATUVI 45
114 #define MT6360_BST_VBUSOVI 46
115 #define MT6360_BST_OLPI 47
116 /* REG 6 -> 48 ~ 55 */
117 #define MT6360_ATTACH_I 48
118 #define MT6360_DETACH_I 49
119 #define MT6360_QC30_STPDONE 51
120 #define MT6360_QC_VBUSDET_DONE 52
121 #define MT6360_HVDCP_DET 53
122 #define MT6360_CHGDETI 54
123 #define MT6360_DCDTI 55
124 /* REG 7 -> 56 ~ 63 */
125 #define MT6360_FOD_DONE_EVT 56
126 #define MT6360_FOD_OV_EVT 57
127 #define MT6360_CHRDET_UVP_EVT 58
128 #define MT6360_CHRDET_OVP_EVT 59
129 #define MT6360_CHRDET_EXT_EVT 60
130 #define MT6360_FOD_LR_EVT 61
131 #define MT6360_FOD_HR_EVT 62
132 #define MT6360_FOD_DISCHG_FAIL_EVT 63
133 /* REG 8 -> 64 ~ 71 */
134 #define MT6360_USBID_EVT 64
135 #define MT6360_APWDTRST_EVT 65
136 #define MT6360_EN_EVT 66
137 #define MT6360_QONB_RST_EVT 67
138 #define MT6360_MRSTB_EVT 68
139 #define MT6360_OTP_EVT 69
140 #define MT6360_VDDAOV_EVT 70
141 #define MT6360_SYSUV_EVT 71
142 /* REG 9 -> 72 ~ 79 */
143 #define MT6360_FLED_STRBPIN_EVT 72
144 #define MT6360_FLED_TORPIN_EVT 73
145 #define MT6360_FLED_TX_EVT 74
146 #define MT6360_FLED_LVF_EVT 75
147 #define MT6360_FLED2_SHORT_EVT 78
148 #define MT6360_FLED1_SHORT_EVT 79
149 /* REG 10 -> 80 ~ 87 */
150 #define MT6360_FLED2_STRB_EVT 80
151 #define MT6360_FLED1_STRB_EVT 81
152 #define MT6360_FLED2_STRB_TO_EVT 82
153 #define MT6360_FLED1_STRB_TO_EVT 83
154 #define MT6360_FLED2_TOR_EVT 84
155 #define MT6360_FLED1_TOR_EVT 85
156 /* REG 11 -> 88 ~ 95 */
157 /* REG 12 -> 96 ~ 103 */
158 #define MT6360_BUCK1_PGB_EVT 96
159 #define MT6360_BUCK1_OC_EVT 100
160 #define MT6360_BUCK1_OV_EVT 101
161 #define MT6360_BUCK1_UV_EVT 102
162 /* REG 13 -> 104 ~ 111 */
163 #define MT6360_BUCK2_PGB_EVT 104
164 #define MT6360_BUCK2_OC_EVT 108
165 #define MT6360_BUCK2_OV_EVT 109
166 #define MT6360_BUCK2_UV_EVT 110
167 /* REG 14 -> 112 ~ 119 */
168 #define MT6360_LDO1_OC_EVT 113
169 #define MT6360_LDO2_OC_EVT 114
170 #define MT6360_LDO3_OC_EVT 115
171 #define MT6360_LDO5_OC_EVT 117
172 #define MT6360_LDO6_OC_EVT 118
173 #define MT6360_LDO7_OC_EVT 119
174 /* REG 15 -> 120 ~ 127 */
175 #define MT6360_LDO1_PGB_EVT 121
176 #define MT6360_LDO2_PGB_EVT 122
177 #define MT6360_LDO3_PGB_EVT 123
178 #define MT6360_LDO5_PGB_EVT 125
179 #define MT6360_LDO6_PGB_EVT 126
180 #define MT6360_LDO7_PGB_EVT 127
182 static const struct regmap_irq mt6360_irqs
[] = {
183 REGMAP_IRQ_REG_LINE(MT6360_CHG_TREG_EVT
, 8),
184 REGMAP_IRQ_REG_LINE(MT6360_CHG_AICR_EVT
, 8),
185 REGMAP_IRQ_REG_LINE(MT6360_CHG_MIVR_EVT
, 8),
186 REGMAP_IRQ_REG_LINE(MT6360_PWR_RDY_EVT
, 8),
187 REGMAP_IRQ_REG_LINE(MT6360_CHG_BATSYSUV_EVT
, 8),
188 REGMAP_IRQ_REG_LINE(MT6360_FLED_CHG_VINOVP_EVT
, 8),
189 REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSUV_EVT
, 8),
190 REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSOV_EVT
, 8),
191 REGMAP_IRQ_REG_LINE(MT6360_CHG_VBATOV_EVT
, 8),
192 REGMAP_IRQ_REG_LINE(MT6360_CHG_VBUSOV_EVT
, 8),
193 REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DET
, 8),
194 REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DONE
, 8),
195 REGMAP_IRQ_REG_LINE(MT6360_CHG_TMRI
, 8),
196 REGMAP_IRQ_REG_LINE(MT6360_CHG_ADPBADI
, 8),
197 REGMAP_IRQ_REG_LINE(MT6360_CHG_RVPI
, 8),
198 REGMAP_IRQ_REG_LINE(MT6360_OTPI
, 8),
199 REGMAP_IRQ_REG_LINE(MT6360_CHG_AICCMEASL
, 8),
200 REGMAP_IRQ_REG_LINE(MT6360_CHGDET_DONEI
, 8),
201 REGMAP_IRQ_REG_LINE(MT6360_WDTMRI
, 8),
202 REGMAP_IRQ_REG_LINE(MT6360_SSFINISHI
, 8),
203 REGMAP_IRQ_REG_LINE(MT6360_CHG_RECHGI
, 8),
204 REGMAP_IRQ_REG_LINE(MT6360_CHG_TERMI
, 8),
205 REGMAP_IRQ_REG_LINE(MT6360_CHG_IEOCI
, 8),
206 REGMAP_IRQ_REG_LINE(MT6360_PUMPX_DONEI
, 8),
207 REGMAP_IRQ_REG_LINE(MT6360_BAT_OVP_ADC_EVT
, 8),
208 REGMAP_IRQ_REG_LINE(MT6360_TYPEC_OTP_EVT
, 8),
209 REGMAP_IRQ_REG_LINE(MT6360_ADC_WAKEUP_EVT
, 8),
210 REGMAP_IRQ_REG_LINE(MT6360_ADC_DONEI
, 8),
211 REGMAP_IRQ_REG_LINE(MT6360_BST_BATUVI
, 8),
212 REGMAP_IRQ_REG_LINE(MT6360_BST_VBUSOVI
, 8),
213 REGMAP_IRQ_REG_LINE(MT6360_BST_OLPI
, 8),
214 REGMAP_IRQ_REG_LINE(MT6360_ATTACH_I
, 8),
215 REGMAP_IRQ_REG_LINE(MT6360_DETACH_I
, 8),
216 REGMAP_IRQ_REG_LINE(MT6360_QC30_STPDONE
, 8),
217 REGMAP_IRQ_REG_LINE(MT6360_QC_VBUSDET_DONE
, 8),
218 REGMAP_IRQ_REG_LINE(MT6360_HVDCP_DET
, 8),
219 REGMAP_IRQ_REG_LINE(MT6360_CHGDETI
, 8),
220 REGMAP_IRQ_REG_LINE(MT6360_DCDTI
, 8),
221 REGMAP_IRQ_REG_LINE(MT6360_FOD_DONE_EVT
, 8),
222 REGMAP_IRQ_REG_LINE(MT6360_FOD_OV_EVT
, 8),
223 REGMAP_IRQ_REG_LINE(MT6360_CHRDET_UVP_EVT
, 8),
224 REGMAP_IRQ_REG_LINE(MT6360_CHRDET_OVP_EVT
, 8),
225 REGMAP_IRQ_REG_LINE(MT6360_CHRDET_EXT_EVT
, 8),
226 REGMAP_IRQ_REG_LINE(MT6360_FOD_LR_EVT
, 8),
227 REGMAP_IRQ_REG_LINE(MT6360_FOD_HR_EVT
, 8),
228 REGMAP_IRQ_REG_LINE(MT6360_FOD_DISCHG_FAIL_EVT
, 8),
229 REGMAP_IRQ_REG_LINE(MT6360_USBID_EVT
, 8),
230 REGMAP_IRQ_REG_LINE(MT6360_APWDTRST_EVT
, 8),
231 REGMAP_IRQ_REG_LINE(MT6360_EN_EVT
, 8),
232 REGMAP_IRQ_REG_LINE(MT6360_QONB_RST_EVT
, 8),
233 REGMAP_IRQ_REG_LINE(MT6360_MRSTB_EVT
, 8),
234 REGMAP_IRQ_REG_LINE(MT6360_OTP_EVT
, 8),
235 REGMAP_IRQ_REG_LINE(MT6360_VDDAOV_EVT
, 8),
236 REGMAP_IRQ_REG_LINE(MT6360_SYSUV_EVT
, 8),
237 REGMAP_IRQ_REG_LINE(MT6360_FLED_STRBPIN_EVT
, 8),
238 REGMAP_IRQ_REG_LINE(MT6360_FLED_TORPIN_EVT
, 8),
239 REGMAP_IRQ_REG_LINE(MT6360_FLED_TX_EVT
, 8),
240 REGMAP_IRQ_REG_LINE(MT6360_FLED_LVF_EVT
, 8),
241 REGMAP_IRQ_REG_LINE(MT6360_FLED2_SHORT_EVT
, 8),
242 REGMAP_IRQ_REG_LINE(MT6360_FLED1_SHORT_EVT
, 8),
243 REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_EVT
, 8),
244 REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_EVT
, 8),
245 REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_TO_EVT
, 8),
246 REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_TO_EVT
, 8),
247 REGMAP_IRQ_REG_LINE(MT6360_FLED2_TOR_EVT
, 8),
248 REGMAP_IRQ_REG_LINE(MT6360_FLED1_TOR_EVT
, 8),
249 REGMAP_IRQ_REG_LINE(MT6360_BUCK1_PGB_EVT
, 8),
250 REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OC_EVT
, 8),
251 REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OV_EVT
, 8),
252 REGMAP_IRQ_REG_LINE(MT6360_BUCK1_UV_EVT
, 8),
253 REGMAP_IRQ_REG_LINE(MT6360_BUCK2_PGB_EVT
, 8),
254 REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OC_EVT
, 8),
255 REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OV_EVT
, 8),
256 REGMAP_IRQ_REG_LINE(MT6360_BUCK2_UV_EVT
, 8),
257 REGMAP_IRQ_REG_LINE(MT6360_LDO1_OC_EVT
, 8),
258 REGMAP_IRQ_REG_LINE(MT6360_LDO2_OC_EVT
, 8),
259 REGMAP_IRQ_REG_LINE(MT6360_LDO3_OC_EVT
, 8),
260 REGMAP_IRQ_REG_LINE(MT6360_LDO5_OC_EVT
, 8),
261 REGMAP_IRQ_REG_LINE(MT6360_LDO6_OC_EVT
, 8),
262 REGMAP_IRQ_REG_LINE(MT6360_LDO7_OC_EVT
, 8),
263 REGMAP_IRQ_REG_LINE(MT6360_LDO1_PGB_EVT
, 8),
264 REGMAP_IRQ_REG_LINE(MT6360_LDO2_PGB_EVT
, 8),
265 REGMAP_IRQ_REG_LINE(MT6360_LDO3_PGB_EVT
, 8),
266 REGMAP_IRQ_REG_LINE(MT6360_LDO5_PGB_EVT
, 8),
267 REGMAP_IRQ_REG_LINE(MT6360_LDO6_PGB_EVT
, 8),
268 REGMAP_IRQ_REG_LINE(MT6360_LDO7_PGB_EVT
, 8),
271 static const struct regmap_irq_chip mt6360_irq_chip
= {
272 .name
= "mt6360_irqs",
274 .num_irqs
= ARRAY_SIZE(mt6360_irqs
),
275 .num_regs
= MT6360_PMU_IRQ_REGNUM
,
276 .mask_base
= MT6360_PMU_CHG_MASK1
,
277 .status_base
= MT6360_PMU_CHG_IRQ1
,
278 .ack_base
= MT6360_PMU_CHG_IRQ1
,
279 .init_ack_masked
= true,
283 static const struct resource mt6360_adc_resources
[] = {
284 DEFINE_RES_IRQ_NAMED(MT6360_ADC_DONEI
, "adc_donei"),
287 static const struct resource mt6360_chg_resources
[] = {
288 DEFINE_RES_IRQ_NAMED(MT6360_CHG_TREG_EVT
, "chg_treg_evt"),
289 DEFINE_RES_IRQ_NAMED(MT6360_PWR_RDY_EVT
, "pwr_rdy_evt"),
290 DEFINE_RES_IRQ_NAMED(MT6360_CHG_BATSYSUV_EVT
, "chg_batsysuv_evt"),
291 DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSUV_EVT
, "chg_vsysuv_evt"),
292 DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSOV_EVT
, "chg_vsysov_evt"),
293 DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBATOV_EVT
, "chg_vbatov_evt"),
294 DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBUSOV_EVT
, "chg_vbusov_evt"),
295 DEFINE_RES_IRQ_NAMED(MT6360_CHG_AICCMEASL
, "chg_aiccmeasl"),
296 DEFINE_RES_IRQ_NAMED(MT6360_WDTMRI
, "wdtmri"),
297 DEFINE_RES_IRQ_NAMED(MT6360_CHG_RECHGI
, "chg_rechgi"),
298 DEFINE_RES_IRQ_NAMED(MT6360_CHG_TERMI
, "chg_termi"),
299 DEFINE_RES_IRQ_NAMED(MT6360_CHG_IEOCI
, "chg_ieoci"),
300 DEFINE_RES_IRQ_NAMED(MT6360_PUMPX_DONEI
, "pumpx_donei"),
301 DEFINE_RES_IRQ_NAMED(MT6360_ATTACH_I
, "attach_i"),
302 DEFINE_RES_IRQ_NAMED(MT6360_CHRDET_EXT_EVT
, "chrdet_ext_evt"),
305 static const struct resource mt6360_led_resources
[] = {
306 DEFINE_RES_IRQ_NAMED(MT6360_FLED_CHG_VINOVP_EVT
, "fled_chg_vinovp_evt"),
307 DEFINE_RES_IRQ_NAMED(MT6360_FLED_LVF_EVT
, "fled_lvf_evt"),
308 DEFINE_RES_IRQ_NAMED(MT6360_FLED2_SHORT_EVT
, "fled2_short_evt"),
309 DEFINE_RES_IRQ_NAMED(MT6360_FLED1_SHORT_EVT
, "fled1_short_evt"),
310 DEFINE_RES_IRQ_NAMED(MT6360_FLED2_STRB_TO_EVT
, "fled2_strb_to_evt"),
311 DEFINE_RES_IRQ_NAMED(MT6360_FLED1_STRB_TO_EVT
, "fled1_strb_to_evt"),
314 static const struct resource mt6360_regulator_resources
[] = {
315 DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_PGB_EVT
, "buck1_pgb_evt"),
316 DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OC_EVT
, "buck1_oc_evt"),
317 DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OV_EVT
, "buck1_ov_evt"),
318 DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_UV_EVT
, "buck1_uv_evt"),
319 DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_PGB_EVT
, "buck2_pgb_evt"),
320 DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OC_EVT
, "buck2_oc_evt"),
321 DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OV_EVT
, "buck2_ov_evt"),
322 DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_UV_EVT
, "buck2_uv_evt"),
323 DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT
, "ldo1_oc_evt"),
324 DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT
, "ldo2_oc_evt"),
325 DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT
, "ldo3_oc_evt"),
326 DEFINE_RES_IRQ_NAMED(MT6360_LDO5_OC_EVT
, "ldo5_oc_evt"),
327 DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT
, "ldo6_oc_evt"),
328 DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT
, "ldo7_oc_evt"),
329 DEFINE_RES_IRQ_NAMED(MT6360_LDO1_PGB_EVT
, "ldo1_pgb_evt"),
330 DEFINE_RES_IRQ_NAMED(MT6360_LDO2_PGB_EVT
, "ldo2_pgb_evt"),
331 DEFINE_RES_IRQ_NAMED(MT6360_LDO3_PGB_EVT
, "ldo3_pgb_evt"),
332 DEFINE_RES_IRQ_NAMED(MT6360_LDO5_PGB_EVT
, "ldo5_pgb_evt"),
333 DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT
, "ldo6_pgb_evt"),
334 DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT
, "ldo7_pgb_evt"),
337 static const struct mfd_cell mt6360_devs
[] = {
338 MFD_CELL_OF("mt6360-adc", mt6360_adc_resources
,
339 NULL
, 0, 0, "mediatek,mt6360-adc"),
340 MFD_CELL_OF("mt6360-chg", mt6360_chg_resources
,
341 NULL
, 0, 0, "mediatek,mt6360-chg"),
342 MFD_CELL_OF("mt6360-led", mt6360_led_resources
,
343 NULL
, 0, 0, "mediatek,mt6360-led"),
344 MFD_CELL_RES("mt6360-regulator", mt6360_regulator_resources
),
345 MFD_CELL_OF("mt6360-tcpc", NULL
,
346 NULL
, 0, 0, "mediatek,mt6360-tcpc"),
349 static int mt6360_check_vendor_info(struct mt6360_ddata
*ddata
)
354 ret
= regmap_read(ddata
->regmap
, MT6360_PMU_DEV_INFO
, &info
);
358 if ((info
& CHIP_VEN_MASK
) != CHIP_VEN_MT6360
) {
359 dev_err(ddata
->dev
, "Device not supported\n");
363 ddata
->chip_rev
= info
& CHIP_REV_MASK
;
368 static const unsigned short mt6360_slave_addr
[MT6360_SLAVE_MAX
] = {
375 static int mt6360_xlate_pmicldo_addr(u8
*addr
, int rw_size
)
377 /* Address is already in encoded [5:0] */
378 *addr
&= MT6360_ADDRESS_MASK
;
382 *addr
|= MT6360_DATA_SIZE_1_BYTE
;
385 *addr
|= MT6360_DATA_SIZE_2_BYTES
;
388 *addr
|= MT6360_DATA_SIZE_3_BYTES
;
391 *addr
|= MT6360_DATA_SIZE_4_BYTES
;
400 static int mt6360_regmap_read(void *context
, const void *reg
, size_t reg_size
,
401 void *val
, size_t val_size
)
403 struct mt6360_ddata
*ddata
= context
;
404 u8 bank
= *(u8
*)reg
;
405 u8 reg_addr
= *(u8
*)(reg
+ 1);
406 struct i2c_client
*i2c
;
407 bool crc_needed
= false;
408 int buf_len
= MT6360_ALLOC_READ_SIZE(val_size
);
409 int read_size
= val_size
;
413 if (bank
>= MT6360_SLAVE_MAX
)
416 i2c
= ddata
->i2c
[bank
];
418 if (bank
== MT6360_SLAVE_PMIC
|| bank
== MT6360_SLAVE_LDO
) {
420 ret
= mt6360_xlate_pmicldo_addr(®_addr
, val_size
);
423 read_size
+= MT6360_CRC_CRC8_SIZE
;
426 u8
*buf
__free(kfree
) = kzalloc(buf_len
, GFP_KERNEL
);
430 buf
[0] = I2C_ADDR_XLATE_8BIT(i2c
->addr
, I2C_SMBUS_READ
);
433 ret
= i2c_smbus_read_i2c_block_data(i2c
, reg_addr
, read_size
,
434 buf
+ MT6360_CRC_PREDATA_OFFSET
);
437 else if (ret
!= read_size
)
441 crc
= crc8(ddata
->crc8_tbl
, buf
, val_size
+ MT6360_CRC_PREDATA_OFFSET
, 0);
442 if (crc
!= buf
[val_size
+ MT6360_CRC_PREDATA_OFFSET
])
446 memcpy(val
, buf
+ MT6360_CRC_PREDATA_OFFSET
, val_size
);
451 static int mt6360_regmap_write(void *context
, const void *val
, size_t val_size
)
453 struct mt6360_ddata
*ddata
= context
;
454 u8 bank
= *(u8
*)val
;
455 u8 reg_addr
= *(u8
*)(val
+ 1);
456 struct i2c_client
*i2c
;
457 bool crc_needed
= false;
459 int buf_len
= MT6360_ALLOC_WRITE_SIZE(val_size
);
460 int write_size
= val_size
- MT6360_REGMAP_REG_BYTE_SIZE
;
463 if (bank
>= MT6360_SLAVE_MAX
)
466 i2c
= ddata
->i2c
[bank
];
468 if (bank
== MT6360_SLAVE_PMIC
|| bank
== MT6360_SLAVE_LDO
) {
470 ret
= mt6360_xlate_pmicldo_addr(®_addr
, val_size
- MT6360_REGMAP_REG_BYTE_SIZE
);
475 buf
= kzalloc(buf_len
, GFP_KERNEL
);
479 buf
[0] = I2C_ADDR_XLATE_8BIT(i2c
->addr
, I2C_SMBUS_WRITE
);
481 memcpy(buf
+ MT6360_CRC_PREDATA_OFFSET
, val
+ MT6360_REGMAP_REG_BYTE_SIZE
, write_size
);
484 buf
[val_size
] = crc8(ddata
->crc8_tbl
, buf
, val_size
, 0);
485 write_size
+= (MT6360_CRC_CRC8_SIZE
+ MT6360_CRC_DUMMY_BYTE_SIZE
);
488 ret
= i2c_smbus_write_i2c_block_data(i2c
, reg_addr
, write_size
,
489 buf
+ MT6360_CRC_PREDATA_OFFSET
);
495 static const struct regmap_bus mt6360_regmap_bus
= {
496 .read
= mt6360_regmap_read
,
497 .write
= mt6360_regmap_write
,
499 /* Due to PMIC and LDO CRC access size limit */
504 static bool mt6360_is_readwrite_reg(struct device
*dev
, unsigned int reg
)
507 case MT6360_REG_TCPCSTART
... MT6360_REG_TCPCEND
:
509 case MT6360_REG_PMICSTART
... MT6360_REG_PMICEND
:
511 case MT6360_REG_LDOSTART
... MT6360_REG_LDOEND
:
513 case MT6360_REG_PMUSTART
... MT6360_REG_PMUEND
:
520 static const struct regmap_config mt6360_regmap_config
= {
523 .reg_format_endian
= REGMAP_ENDIAN_BIG
,
524 .max_register
= MT6360_REG_PMUEND
,
525 .writeable_reg
= mt6360_is_readwrite_reg
,
526 .readable_reg
= mt6360_is_readwrite_reg
,
529 static int mt6360_probe(struct i2c_client
*client
)
531 struct mt6360_ddata
*ddata
;
534 ddata
= devm_kzalloc(&client
->dev
, sizeof(*ddata
), GFP_KERNEL
);
538 ddata
->dev
= &client
->dev
;
539 i2c_set_clientdata(client
, ddata
);
541 for (i
= 0; i
< MT6360_SLAVE_MAX
- 1; i
++) {
542 ddata
->i2c
[i
] = devm_i2c_new_dummy_device(&client
->dev
,
544 mt6360_slave_addr
[i
]);
545 if (IS_ERR(ddata
->i2c
[i
])) {
546 dev_err(&client
->dev
,
547 "Failed to get new dummy I2C device for address 0x%x",
548 mt6360_slave_addr
[i
]);
549 return PTR_ERR(ddata
->i2c
[i
]);
552 ddata
->i2c
[MT6360_SLAVE_MAX
- 1] = client
;
554 crc8_populate_msb(ddata
->crc8_tbl
, MT6360_CRC8_POLYNOMIAL
);
555 ddata
->regmap
= devm_regmap_init(ddata
->dev
, &mt6360_regmap_bus
, ddata
,
556 &mt6360_regmap_config
);
557 if (IS_ERR(ddata
->regmap
)) {
558 dev_err(&client
->dev
, "Failed to register regmap\n");
559 return PTR_ERR(ddata
->regmap
);
562 ret
= mt6360_check_vendor_info(ddata
);
566 ret
= devm_regmap_add_irq_chip(&client
->dev
, ddata
->regmap
, client
->irq
,
567 0, 0, &mt6360_irq_chip
,
570 dev_err(&client
->dev
, "Failed to add Regmap IRQ Chip\n");
574 ret
= devm_mfd_add_devices(&client
->dev
, PLATFORM_DEVID_AUTO
,
575 mt6360_devs
, ARRAY_SIZE(mt6360_devs
), NULL
,
576 0, regmap_irq_get_domain(ddata
->irq_data
));
578 dev_err(&client
->dev
,
579 "Failed to register subordinate devices\n");
586 static int __maybe_unused
mt6360_suspend(struct device
*dev
)
588 struct i2c_client
*i2c
= to_i2c_client(dev
);
590 if (device_may_wakeup(dev
))
591 enable_irq_wake(i2c
->irq
);
596 static int __maybe_unused
mt6360_resume(struct device
*dev
)
599 struct i2c_client
*i2c
= to_i2c_client(dev
);
601 if (device_may_wakeup(dev
))
602 disable_irq_wake(i2c
->irq
);
607 static SIMPLE_DEV_PM_OPS(mt6360_pm_ops
, mt6360_suspend
, mt6360_resume
);
609 static const struct of_device_id __maybe_unused mt6360_of_id
[] = {
610 { .compatible
= "mediatek,mt6360", },
613 MODULE_DEVICE_TABLE(of
, mt6360_of_id
);
615 static struct i2c_driver mt6360_driver
= {
618 .pm
= &mt6360_pm_ops
,
619 .of_match_table
= of_match_ptr(mt6360_of_id
),
621 .probe
= mt6360_probe
,
623 module_i2c_driver(mt6360_driver
);
625 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
626 MODULE_DESCRIPTION("MT6360 I2C Driver");
627 MODULE_LICENSE("GPL v2");