cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mt6360-core.c (19389B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2020 MediaTek Inc.
      4 *
      5 * Author: Gene Chen <gene_chen@richtek.com>
      6 */
      7
      8#include <linux/crc8.h>
      9#include <linux/i2c.h>
     10#include <linux/init.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#include <linux/slab.h>
     17
     18enum {
     19	MT6360_SLAVE_TCPC = 0,
     20	MT6360_SLAVE_PMIC,
     21	MT6360_SLAVE_LDO,
     22	MT6360_SLAVE_PMU,
     23	MT6360_SLAVE_MAX,
     24};
     25
     26struct mt6360_ddata {
     27	struct i2c_client *i2c[MT6360_SLAVE_MAX];
     28	struct device *dev;
     29	struct regmap *regmap;
     30	struct regmap_irq_chip_data *irq_data;
     31	unsigned int chip_rev;
     32	u8 crc8_tbl[CRC8_TABLE_SIZE];
     33};
     34
     35#define MT6360_TCPC_SLAVEID		0x4E
     36#define MT6360_PMIC_SLAVEID		0x1A
     37#define MT6360_LDO_SLAVEID		0x64
     38#define MT6360_PMU_SLAVEID		0x34
     39
     40#define MT6360_REG_TCPCSTART		0x00
     41#define MT6360_REG_TCPCEND		0xFF
     42#define MT6360_REG_PMICSTART		0x100
     43#define MT6360_REG_PMICEND		0x13B
     44#define MT6360_REG_LDOSTART		0x200
     45#define MT6360_REG_LDOEND		0x21C
     46#define MT6360_REG_PMUSTART		0x300
     47#define MT6360_PMU_DEV_INFO		0x300
     48#define MT6360_PMU_CHG_IRQ1		0x3D0
     49#define MT6360_PMU_CHG_MASK1		0x3F0
     50#define MT6360_REG_PMUEND		0x3FF
     51
     52#define MT6360_PMU_IRQ_REGNUM		16
     53
     54#define CHIP_VEN_MASK			0xF0
     55#define CHIP_VEN_MT6360			0x50
     56#define CHIP_REV_MASK			0x0F
     57
     58#define MT6360_ADDRESS_MASK		0x3F
     59#define MT6360_DATA_SIZE_1_BYTE		0x00
     60#define MT6360_DATA_SIZE_2_BYTES	0x40
     61#define MT6360_DATA_SIZE_3_BYTES	0x80
     62#define MT6360_DATA_SIZE_4_BYTES	0xC0
     63
     64#define MT6360_CRC8_POLYNOMIAL		0x7
     65
     66#define MT6360_CRC_I2C_ADDR_SIZE	1
     67#define MT6360_CRC_REG_ADDR_SIZE	1
     68/* prealloca read size = i2c device addr + i2c reg addr + val ... + crc8 */
     69#define MT6360_ALLOC_READ_SIZE(_size)	(_size + 3)
     70/* prealloca write size = i2c device addr + i2c reg addr + val ... + crc8 + dummy byte */
     71#define MT6360_ALLOC_WRITE_SIZE(_size)	(_size + 4)
     72#define MT6360_CRC_PREDATA_OFFSET	(MT6360_CRC_I2C_ADDR_SIZE + MT6360_CRC_REG_ADDR_SIZE)
     73#define MT6360_CRC_CRC8_SIZE		1
     74#define MT6360_CRC_DUMMY_BYTE_SIZE	1
     75#define MT6360_REGMAP_REG_BYTE_SIZE	2
     76#define I2C_ADDR_XLATE_8BIT(_addr, _rw)	(((_addr & 0x7F) << 1) + _rw)
     77
     78/* reg 0 -> 0 ~ 7 */
     79#define MT6360_CHG_TREG_EVT		4
     80#define MT6360_CHG_AICR_EVT		5
     81#define MT6360_CHG_MIVR_EVT		6
     82#define MT6360_PWR_RDY_EVT		7
     83/* REG 1 -> 8 ~ 15 */
     84#define MT6360_CHG_BATSYSUV_EVT		9
     85#define MT6360_FLED_CHG_VINOVP_EVT	11
     86#define MT6360_CHG_VSYSUV_EVT		12
     87#define MT6360_CHG_VSYSOV_EVT		13
     88#define MT6360_CHG_VBATOV_EVT		14
     89#define MT6360_CHG_VBUSOV_EVT		15
     90/* REG 2 -> 16 ~ 23 */
     91/* REG 3 -> 24 ~ 31 */
     92#define MT6360_WD_PMU_DET		25
     93#define MT6360_WD_PMU_DONE		26
     94#define MT6360_CHG_TMRI			27
     95#define MT6360_CHG_ADPBADI		29
     96#define MT6360_CHG_RVPI			30
     97#define MT6360_OTPI			31
     98/* REG 4 -> 32 ~ 39 */
     99#define MT6360_CHG_AICCMEASL		32
    100#define MT6360_CHGDET_DONEI		34
    101#define MT6360_WDTMRI			35
    102#define MT6360_SSFINISHI		36
    103#define MT6360_CHG_RECHGI		37
    104#define MT6360_CHG_TERMI		38
    105#define MT6360_CHG_IEOCI		39
    106/* REG 5 -> 40 ~ 47 */
    107#define MT6360_PUMPX_DONEI		40
    108#define MT6360_BAT_OVP_ADC_EVT		41
    109#define MT6360_TYPEC_OTP_EVT		42
    110#define MT6360_ADC_WAKEUP_EVT		43
    111#define MT6360_ADC_DONEI		44
    112#define MT6360_BST_BATUVI		45
    113#define MT6360_BST_VBUSOVI		46
    114#define MT6360_BST_OLPI			47
    115/* REG 6 -> 48 ~ 55 */
    116#define MT6360_ATTACH_I			48
    117#define MT6360_DETACH_I			49
    118#define MT6360_QC30_STPDONE		51
    119#define MT6360_QC_VBUSDET_DONE		52
    120#define MT6360_HVDCP_DET		53
    121#define MT6360_CHGDETI			54
    122#define MT6360_DCDTI			55
    123/* REG 7 -> 56 ~ 63 */
    124#define MT6360_FOD_DONE_EVT		56
    125#define MT6360_FOD_OV_EVT		57
    126#define MT6360_CHRDET_UVP_EVT		58
    127#define MT6360_CHRDET_OVP_EVT		59
    128#define MT6360_CHRDET_EXT_EVT		60
    129#define MT6360_FOD_LR_EVT		61
    130#define MT6360_FOD_HR_EVT		62
    131#define MT6360_FOD_DISCHG_FAIL_EVT	63
    132/* REG 8 -> 64 ~ 71 */
    133#define MT6360_USBID_EVT		64
    134#define MT6360_APWDTRST_EVT		65
    135#define MT6360_EN_EVT			66
    136#define MT6360_QONB_RST_EVT		67
    137#define MT6360_MRSTB_EVT		68
    138#define MT6360_OTP_EVT			69
    139#define MT6360_VDDAOV_EVT		70
    140#define MT6360_SYSUV_EVT		71
    141/* REG 9 -> 72 ~ 79 */
    142#define MT6360_FLED_STRBPIN_EVT		72
    143#define MT6360_FLED_TORPIN_EVT		73
    144#define MT6360_FLED_TX_EVT		74
    145#define MT6360_FLED_LVF_EVT		75
    146#define MT6360_FLED2_SHORT_EVT		78
    147#define MT6360_FLED1_SHORT_EVT		79
    148/* REG 10 -> 80 ~ 87 */
    149#define MT6360_FLED2_STRB_EVT		80
    150#define MT6360_FLED1_STRB_EVT		81
    151#define MT6360_FLED2_STRB_TO_EVT	82
    152#define MT6360_FLED1_STRB_TO_EVT	83
    153#define MT6360_FLED2_TOR_EVT		84
    154#define MT6360_FLED1_TOR_EVT		85
    155/* REG 11 -> 88 ~ 95 */
    156/* REG 12 -> 96 ~ 103 */
    157#define MT6360_BUCK1_PGB_EVT		96
    158#define MT6360_BUCK1_OC_EVT		100
    159#define MT6360_BUCK1_OV_EVT		101
    160#define MT6360_BUCK1_UV_EVT		102
    161/* REG 13 -> 104 ~ 111 */
    162#define MT6360_BUCK2_PGB_EVT		104
    163#define MT6360_BUCK2_OC_EVT		108
    164#define MT6360_BUCK2_OV_EVT		109
    165#define MT6360_BUCK2_UV_EVT		110
    166/* REG 14 -> 112 ~ 119 */
    167#define MT6360_LDO1_OC_EVT		113
    168#define MT6360_LDO2_OC_EVT		114
    169#define MT6360_LDO3_OC_EVT		115
    170#define MT6360_LDO5_OC_EVT		117
    171#define MT6360_LDO6_OC_EVT		118
    172#define MT6360_LDO7_OC_EVT		119
    173/* REG 15 -> 120 ~ 127 */
    174#define MT6360_LDO1_PGB_EVT		121
    175#define MT6360_LDO2_PGB_EVT		122
    176#define MT6360_LDO3_PGB_EVT		123
    177#define MT6360_LDO5_PGB_EVT		125
    178#define MT6360_LDO6_PGB_EVT		126
    179#define MT6360_LDO7_PGB_EVT		127
    180
    181static const struct regmap_irq mt6360_irqs[] =  {
    182	REGMAP_IRQ_REG_LINE(MT6360_CHG_TREG_EVT, 8),
    183	REGMAP_IRQ_REG_LINE(MT6360_CHG_AICR_EVT, 8),
    184	REGMAP_IRQ_REG_LINE(MT6360_CHG_MIVR_EVT, 8),
    185	REGMAP_IRQ_REG_LINE(MT6360_PWR_RDY_EVT, 8),
    186	REGMAP_IRQ_REG_LINE(MT6360_CHG_BATSYSUV_EVT, 8),
    187	REGMAP_IRQ_REG_LINE(MT6360_FLED_CHG_VINOVP_EVT, 8),
    188	REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSUV_EVT, 8),
    189	REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSOV_EVT, 8),
    190	REGMAP_IRQ_REG_LINE(MT6360_CHG_VBATOV_EVT, 8),
    191	REGMAP_IRQ_REG_LINE(MT6360_CHG_VBUSOV_EVT, 8),
    192	REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DET, 8),
    193	REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DONE, 8),
    194	REGMAP_IRQ_REG_LINE(MT6360_CHG_TMRI, 8),
    195	REGMAP_IRQ_REG_LINE(MT6360_CHG_ADPBADI, 8),
    196	REGMAP_IRQ_REG_LINE(MT6360_CHG_RVPI, 8),
    197	REGMAP_IRQ_REG_LINE(MT6360_OTPI, 8),
    198	REGMAP_IRQ_REG_LINE(MT6360_CHG_AICCMEASL, 8),
    199	REGMAP_IRQ_REG_LINE(MT6360_CHGDET_DONEI, 8),
    200	REGMAP_IRQ_REG_LINE(MT6360_WDTMRI, 8),
    201	REGMAP_IRQ_REG_LINE(MT6360_SSFINISHI, 8),
    202	REGMAP_IRQ_REG_LINE(MT6360_CHG_RECHGI, 8),
    203	REGMAP_IRQ_REG_LINE(MT6360_CHG_TERMI, 8),
    204	REGMAP_IRQ_REG_LINE(MT6360_CHG_IEOCI, 8),
    205	REGMAP_IRQ_REG_LINE(MT6360_PUMPX_DONEI, 8),
    206	REGMAP_IRQ_REG_LINE(MT6360_BAT_OVP_ADC_EVT, 8),
    207	REGMAP_IRQ_REG_LINE(MT6360_TYPEC_OTP_EVT, 8),
    208	REGMAP_IRQ_REG_LINE(MT6360_ADC_WAKEUP_EVT, 8),
    209	REGMAP_IRQ_REG_LINE(MT6360_ADC_DONEI, 8),
    210	REGMAP_IRQ_REG_LINE(MT6360_BST_BATUVI, 8),
    211	REGMAP_IRQ_REG_LINE(MT6360_BST_VBUSOVI, 8),
    212	REGMAP_IRQ_REG_LINE(MT6360_BST_OLPI, 8),
    213	REGMAP_IRQ_REG_LINE(MT6360_ATTACH_I, 8),
    214	REGMAP_IRQ_REG_LINE(MT6360_DETACH_I, 8),
    215	REGMAP_IRQ_REG_LINE(MT6360_QC30_STPDONE, 8),
    216	REGMAP_IRQ_REG_LINE(MT6360_QC_VBUSDET_DONE, 8),
    217	REGMAP_IRQ_REG_LINE(MT6360_HVDCP_DET, 8),
    218	REGMAP_IRQ_REG_LINE(MT6360_CHGDETI, 8),
    219	REGMAP_IRQ_REG_LINE(MT6360_DCDTI, 8),
    220	REGMAP_IRQ_REG_LINE(MT6360_FOD_DONE_EVT, 8),
    221	REGMAP_IRQ_REG_LINE(MT6360_FOD_OV_EVT, 8),
    222	REGMAP_IRQ_REG_LINE(MT6360_CHRDET_UVP_EVT, 8),
    223	REGMAP_IRQ_REG_LINE(MT6360_CHRDET_OVP_EVT, 8),
    224	REGMAP_IRQ_REG_LINE(MT6360_CHRDET_EXT_EVT, 8),
    225	REGMAP_IRQ_REG_LINE(MT6360_FOD_LR_EVT, 8),
    226	REGMAP_IRQ_REG_LINE(MT6360_FOD_HR_EVT, 8),
    227	REGMAP_IRQ_REG_LINE(MT6360_FOD_DISCHG_FAIL_EVT, 8),
    228	REGMAP_IRQ_REG_LINE(MT6360_USBID_EVT, 8),
    229	REGMAP_IRQ_REG_LINE(MT6360_APWDTRST_EVT, 8),
    230	REGMAP_IRQ_REG_LINE(MT6360_EN_EVT, 8),
    231	REGMAP_IRQ_REG_LINE(MT6360_QONB_RST_EVT, 8),
    232	REGMAP_IRQ_REG_LINE(MT6360_MRSTB_EVT, 8),
    233	REGMAP_IRQ_REG_LINE(MT6360_OTP_EVT, 8),
    234	REGMAP_IRQ_REG_LINE(MT6360_VDDAOV_EVT, 8),
    235	REGMAP_IRQ_REG_LINE(MT6360_SYSUV_EVT, 8),
    236	REGMAP_IRQ_REG_LINE(MT6360_FLED_STRBPIN_EVT, 8),
    237	REGMAP_IRQ_REG_LINE(MT6360_FLED_TORPIN_EVT, 8),
    238	REGMAP_IRQ_REG_LINE(MT6360_FLED_TX_EVT, 8),
    239	REGMAP_IRQ_REG_LINE(MT6360_FLED_LVF_EVT, 8),
    240	REGMAP_IRQ_REG_LINE(MT6360_FLED2_SHORT_EVT, 8),
    241	REGMAP_IRQ_REG_LINE(MT6360_FLED1_SHORT_EVT, 8),
    242	REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_EVT, 8),
    243	REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_EVT, 8),
    244	REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_TO_EVT, 8),
    245	REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_TO_EVT, 8),
    246	REGMAP_IRQ_REG_LINE(MT6360_FLED2_TOR_EVT, 8),
    247	REGMAP_IRQ_REG_LINE(MT6360_FLED1_TOR_EVT, 8),
    248	REGMAP_IRQ_REG_LINE(MT6360_BUCK1_PGB_EVT, 8),
    249	REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OC_EVT, 8),
    250	REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OV_EVT, 8),
    251	REGMAP_IRQ_REG_LINE(MT6360_BUCK1_UV_EVT, 8),
    252	REGMAP_IRQ_REG_LINE(MT6360_BUCK2_PGB_EVT, 8),
    253	REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OC_EVT, 8),
    254	REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OV_EVT, 8),
    255	REGMAP_IRQ_REG_LINE(MT6360_BUCK2_UV_EVT, 8),
    256	REGMAP_IRQ_REG_LINE(MT6360_LDO1_OC_EVT, 8),
    257	REGMAP_IRQ_REG_LINE(MT6360_LDO2_OC_EVT, 8),
    258	REGMAP_IRQ_REG_LINE(MT6360_LDO3_OC_EVT, 8),
    259	REGMAP_IRQ_REG_LINE(MT6360_LDO5_OC_EVT, 8),
    260	REGMAP_IRQ_REG_LINE(MT6360_LDO6_OC_EVT, 8),
    261	REGMAP_IRQ_REG_LINE(MT6360_LDO7_OC_EVT, 8),
    262	REGMAP_IRQ_REG_LINE(MT6360_LDO1_PGB_EVT, 8),
    263	REGMAP_IRQ_REG_LINE(MT6360_LDO2_PGB_EVT, 8),
    264	REGMAP_IRQ_REG_LINE(MT6360_LDO3_PGB_EVT, 8),
    265	REGMAP_IRQ_REG_LINE(MT6360_LDO5_PGB_EVT, 8),
    266	REGMAP_IRQ_REG_LINE(MT6360_LDO6_PGB_EVT, 8),
    267	REGMAP_IRQ_REG_LINE(MT6360_LDO7_PGB_EVT, 8),
    268};
    269
    270static const struct regmap_irq_chip mt6360_irq_chip = {
    271	.name = "mt6360_irqs",
    272	.irqs = mt6360_irqs,
    273	.num_irqs = ARRAY_SIZE(mt6360_irqs),
    274	.num_regs = MT6360_PMU_IRQ_REGNUM,
    275	.mask_base = MT6360_PMU_CHG_MASK1,
    276	.status_base = MT6360_PMU_CHG_IRQ1,
    277	.ack_base = MT6360_PMU_CHG_IRQ1,
    278	.init_ack_masked = true,
    279	.use_ack = true,
    280};
    281
    282static const struct resource mt6360_adc_resources[] = {
    283	DEFINE_RES_IRQ_NAMED(MT6360_ADC_DONEI, "adc_donei"),
    284};
    285
    286static const struct resource mt6360_chg_resources[] = {
    287	DEFINE_RES_IRQ_NAMED(MT6360_CHG_TREG_EVT, "chg_treg_evt"),
    288	DEFINE_RES_IRQ_NAMED(MT6360_PWR_RDY_EVT, "pwr_rdy_evt"),
    289	DEFINE_RES_IRQ_NAMED(MT6360_CHG_BATSYSUV_EVT, "chg_batsysuv_evt"),
    290	DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSUV_EVT, "chg_vsysuv_evt"),
    291	DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSOV_EVT, "chg_vsysov_evt"),
    292	DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBATOV_EVT, "chg_vbatov_evt"),
    293	DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBUSOV_EVT, "chg_vbusov_evt"),
    294	DEFINE_RES_IRQ_NAMED(MT6360_CHG_AICCMEASL, "chg_aiccmeasl"),
    295	DEFINE_RES_IRQ_NAMED(MT6360_WDTMRI, "wdtmri"),
    296	DEFINE_RES_IRQ_NAMED(MT6360_CHG_RECHGI, "chg_rechgi"),
    297	DEFINE_RES_IRQ_NAMED(MT6360_CHG_TERMI, "chg_termi"),
    298	DEFINE_RES_IRQ_NAMED(MT6360_CHG_IEOCI, "chg_ieoci"),
    299	DEFINE_RES_IRQ_NAMED(MT6360_PUMPX_DONEI, "pumpx_donei"),
    300	DEFINE_RES_IRQ_NAMED(MT6360_ATTACH_I, "attach_i"),
    301	DEFINE_RES_IRQ_NAMED(MT6360_CHRDET_EXT_EVT, "chrdet_ext_evt"),
    302};
    303
    304static const struct resource mt6360_led_resources[] = {
    305	DEFINE_RES_IRQ_NAMED(MT6360_FLED_CHG_VINOVP_EVT, "fled_chg_vinovp_evt"),
    306	DEFINE_RES_IRQ_NAMED(MT6360_FLED_LVF_EVT, "fled_lvf_evt"),
    307	DEFINE_RES_IRQ_NAMED(MT6360_FLED2_SHORT_EVT, "fled2_short_evt"),
    308	DEFINE_RES_IRQ_NAMED(MT6360_FLED1_SHORT_EVT, "fled1_short_evt"),
    309	DEFINE_RES_IRQ_NAMED(MT6360_FLED2_STRB_TO_EVT, "fled2_strb_to_evt"),
    310	DEFINE_RES_IRQ_NAMED(MT6360_FLED1_STRB_TO_EVT, "fled1_strb_to_evt"),
    311};
    312
    313static const struct resource mt6360_regulator_resources[] = {
    314	DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_PGB_EVT, "buck1_pgb_evt"),
    315	DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OC_EVT, "buck1_oc_evt"),
    316	DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OV_EVT, "buck1_ov_evt"),
    317	DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_UV_EVT, "buck1_uv_evt"),
    318	DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_PGB_EVT, "buck2_pgb_evt"),
    319	DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OC_EVT, "buck2_oc_evt"),
    320	DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OV_EVT, "buck2_ov_evt"),
    321	DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_UV_EVT, "buck2_uv_evt"),
    322	DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"),
    323	DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"),
    324	DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"),
    325	DEFINE_RES_IRQ_NAMED(MT6360_LDO5_OC_EVT, "ldo5_oc_evt"),
    326	DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
    327	DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
    328	DEFINE_RES_IRQ_NAMED(MT6360_LDO1_PGB_EVT, "ldo1_pgb_evt"),
    329	DEFINE_RES_IRQ_NAMED(MT6360_LDO2_PGB_EVT, "ldo2_pgb_evt"),
    330	DEFINE_RES_IRQ_NAMED(MT6360_LDO3_PGB_EVT, "ldo3_pgb_evt"),
    331	DEFINE_RES_IRQ_NAMED(MT6360_LDO5_PGB_EVT, "ldo5_pgb_evt"),
    332	DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
    333	DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
    334};
    335
    336static const struct mfd_cell mt6360_devs[] = {
    337	MFD_CELL_OF("mt6360-adc", mt6360_adc_resources,
    338		    NULL, 0, 0, "mediatek,mt6360-adc"),
    339	MFD_CELL_OF("mt6360-chg", mt6360_chg_resources,
    340		    NULL, 0, 0, "mediatek,mt6360-chg"),
    341	MFD_CELL_OF("mt6360-led", mt6360_led_resources,
    342		    NULL, 0, 0, "mediatek,mt6360-led"),
    343	MFD_CELL_RES("mt6360-regulator", mt6360_regulator_resources),
    344	MFD_CELL_OF("mt6360-tcpc", NULL,
    345		    NULL, 0, 0, "mediatek,mt6360-tcpc"),
    346};
    347
    348static int mt6360_check_vendor_info(struct mt6360_ddata *ddata)
    349{
    350	u32 info;
    351	int ret;
    352
    353	ret = regmap_read(ddata->regmap, MT6360_PMU_DEV_INFO, &info);
    354	if (ret < 0)
    355		return ret;
    356
    357	if ((info & CHIP_VEN_MASK) != CHIP_VEN_MT6360) {
    358		dev_err(ddata->dev, "Device not supported\n");
    359		return -ENODEV;
    360	}
    361
    362	ddata->chip_rev = info & CHIP_REV_MASK;
    363
    364	return 0;
    365}
    366
    367static const unsigned short mt6360_slave_addr[MT6360_SLAVE_MAX] = {
    368	MT6360_TCPC_SLAVEID,
    369	MT6360_PMIC_SLAVEID,
    370	MT6360_LDO_SLAVEID,
    371	MT6360_PMU_SLAVEID,
    372};
    373
    374static int mt6360_xlate_pmicldo_addr(u8 *addr, int rw_size)
    375{
    376	/* Address is already in encoded [5:0] */
    377	*addr &= MT6360_ADDRESS_MASK;
    378
    379	switch (rw_size) {
    380	case 1:
    381		*addr |= MT6360_DATA_SIZE_1_BYTE;
    382		break;
    383	case 2:
    384		*addr |= MT6360_DATA_SIZE_2_BYTES;
    385		break;
    386	case 3:
    387		*addr |= MT6360_DATA_SIZE_3_BYTES;
    388		break;
    389	case 4:
    390		*addr |= MT6360_DATA_SIZE_4_BYTES;
    391		break;
    392	default:
    393		return -EINVAL;
    394	}
    395
    396	return 0;
    397}
    398
    399static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size,
    400			      void *val, size_t val_size)
    401{
    402	struct mt6360_ddata *ddata = context;
    403	u8 bank = *(u8 *)reg;
    404	u8 reg_addr = *(u8 *)(reg + 1);
    405	struct i2c_client *i2c = ddata->i2c[bank];
    406	bool crc_needed = false;
    407	u8 *buf;
    408	int buf_len = MT6360_ALLOC_READ_SIZE(val_size);
    409	int read_size = val_size;
    410	u8 crc;
    411	int ret;
    412
    413	if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
    414		crc_needed = true;
    415		ret = mt6360_xlate_pmicldo_addr(&reg_addr, val_size);
    416		if (ret < 0)
    417			return ret;
    418		read_size += MT6360_CRC_CRC8_SIZE;
    419	}
    420
    421	buf = kzalloc(buf_len, GFP_KERNEL);
    422	if (!buf)
    423		return -ENOMEM;
    424
    425	buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_READ);
    426	buf[1] = reg_addr;
    427
    428	ret = i2c_smbus_read_i2c_block_data(i2c, reg_addr, read_size,
    429					    buf + MT6360_CRC_PREDATA_OFFSET);
    430	if (ret < 0)
    431		goto out;
    432	else if (ret != read_size) {
    433		ret = -EIO;
    434		goto out;
    435	}
    436
    437	if (crc_needed) {
    438		crc = crc8(ddata->crc8_tbl, buf, val_size + MT6360_CRC_PREDATA_OFFSET, 0);
    439		if (crc != buf[val_size + MT6360_CRC_PREDATA_OFFSET]) {
    440			ret = -EIO;
    441			goto out;
    442		}
    443	}
    444
    445	memcpy(val, buf + MT6360_CRC_PREDATA_OFFSET, val_size);
    446out:
    447	kfree(buf);
    448	return (ret < 0) ? ret : 0;
    449}
    450
    451static int mt6360_regmap_write(void *context, const void *val, size_t val_size)
    452{
    453	struct mt6360_ddata *ddata = context;
    454	u8 bank = *(u8 *)val;
    455	u8 reg_addr = *(u8 *)(val + 1);
    456	struct i2c_client *i2c = ddata->i2c[bank];
    457	bool crc_needed = false;
    458	u8 *buf;
    459	int buf_len = MT6360_ALLOC_WRITE_SIZE(val_size);
    460	int write_size = val_size - MT6360_REGMAP_REG_BYTE_SIZE;
    461	int ret;
    462
    463	if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
    464		crc_needed = true;
    465		ret = mt6360_xlate_pmicldo_addr(&reg_addr, val_size - MT6360_REGMAP_REG_BYTE_SIZE);
    466		if (ret < 0)
    467			return ret;
    468	}
    469
    470	buf = kzalloc(buf_len, GFP_KERNEL);
    471	if (!buf)
    472		return -ENOMEM;
    473
    474	buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_WRITE);
    475	buf[1] = reg_addr;
    476	memcpy(buf + MT6360_CRC_PREDATA_OFFSET, val + MT6360_REGMAP_REG_BYTE_SIZE, write_size);
    477
    478	if (crc_needed) {
    479		buf[val_size] = crc8(ddata->crc8_tbl, buf, val_size, 0);
    480		write_size += (MT6360_CRC_CRC8_SIZE + MT6360_CRC_DUMMY_BYTE_SIZE);
    481	}
    482
    483	ret = i2c_smbus_write_i2c_block_data(i2c, reg_addr, write_size,
    484					     buf + MT6360_CRC_PREDATA_OFFSET);
    485
    486	kfree(buf);
    487	return ret;
    488}
    489
    490static const struct regmap_bus mt6360_regmap_bus = {
    491	.read		= mt6360_regmap_read,
    492	.write		= mt6360_regmap_write,
    493
    494	/* Due to PMIC and LDO CRC access size limit */
    495	.max_raw_read	= 4,
    496	.max_raw_write	= 4,
    497};
    498
    499static bool mt6360_is_readwrite_reg(struct device *dev, unsigned int reg)
    500{
    501	switch (reg) {
    502	case MT6360_REG_TCPCSTART ... MT6360_REG_TCPCEND:
    503		fallthrough;
    504	case MT6360_REG_PMICSTART ... MT6360_REG_PMICEND:
    505		fallthrough;
    506	case MT6360_REG_LDOSTART ... MT6360_REG_LDOEND:
    507		fallthrough;
    508	case MT6360_REG_PMUSTART ... MT6360_REG_PMUEND:
    509		return true;
    510	}
    511
    512	return false;
    513}
    514
    515static const struct regmap_config mt6360_regmap_config = {
    516	.reg_bits		= 16,
    517	.val_bits		= 8,
    518	.reg_format_endian	= REGMAP_ENDIAN_BIG,
    519	.max_register		= MT6360_REG_PMUEND,
    520	.writeable_reg		= mt6360_is_readwrite_reg,
    521	.readable_reg		= mt6360_is_readwrite_reg,
    522};
    523
    524static int mt6360_probe(struct i2c_client *client)
    525{
    526	struct mt6360_ddata *ddata;
    527	int i, ret;
    528
    529	ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
    530	if (!ddata)
    531		return -ENOMEM;
    532
    533	ddata->dev = &client->dev;
    534	i2c_set_clientdata(client, ddata);
    535
    536	for (i = 0; i < MT6360_SLAVE_MAX - 1; i++) {
    537		ddata->i2c[i] = devm_i2c_new_dummy_device(&client->dev,
    538							  client->adapter,
    539							  mt6360_slave_addr[i]);
    540		if (IS_ERR(ddata->i2c[i])) {
    541			dev_err(&client->dev,
    542				"Failed to get new dummy I2C device for address 0x%x",
    543				mt6360_slave_addr[i]);
    544			return PTR_ERR(ddata->i2c[i]);
    545		}
    546	}
    547	ddata->i2c[MT6360_SLAVE_MAX - 1] = client;
    548
    549	crc8_populate_msb(ddata->crc8_tbl, MT6360_CRC8_POLYNOMIAL);
    550	ddata->regmap = devm_regmap_init(ddata->dev, &mt6360_regmap_bus, ddata,
    551					 &mt6360_regmap_config);
    552	if (IS_ERR(ddata->regmap)) {
    553		dev_err(&client->dev, "Failed to register regmap\n");
    554		return PTR_ERR(ddata->regmap);
    555	}
    556
    557	ret = mt6360_check_vendor_info(ddata);
    558	if (ret)
    559		return ret;
    560
    561	ret = devm_regmap_add_irq_chip(&client->dev, ddata->regmap, client->irq,
    562				       0, 0, &mt6360_irq_chip,
    563				       &ddata->irq_data);
    564	if (ret) {
    565		dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n");
    566		return ret;
    567	}
    568
    569	ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
    570				   mt6360_devs, ARRAY_SIZE(mt6360_devs), NULL,
    571				   0, regmap_irq_get_domain(ddata->irq_data));
    572	if (ret) {
    573		dev_err(&client->dev,
    574			"Failed to register subordinate devices\n");
    575		return ret;
    576	}
    577
    578	return 0;
    579}
    580
    581static int __maybe_unused mt6360_suspend(struct device *dev)
    582{
    583	struct i2c_client *i2c = to_i2c_client(dev);
    584
    585	if (device_may_wakeup(dev))
    586		enable_irq_wake(i2c->irq);
    587
    588	return 0;
    589}
    590
    591static int __maybe_unused mt6360_resume(struct device *dev)
    592{
    593
    594	struct i2c_client *i2c = to_i2c_client(dev);
    595
    596	if (device_may_wakeup(dev))
    597		disable_irq_wake(i2c->irq);
    598
    599	return 0;
    600}
    601
    602static SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume);
    603
    604static const struct of_device_id __maybe_unused mt6360_of_id[] = {
    605	{ .compatible = "mediatek,mt6360", },
    606	{},
    607};
    608MODULE_DEVICE_TABLE(of, mt6360_of_id);
    609
    610static struct i2c_driver mt6360_driver = {
    611	.driver = {
    612		.name = "mt6360",
    613		.pm = &mt6360_pm_ops,
    614		.of_match_table = of_match_ptr(mt6360_of_id),
    615	},
    616	.probe_new = mt6360_probe,
    617};
    618module_i2c_driver(mt6360_driver);
    619
    620MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
    621MODULE_DESCRIPTION("MT6360 I2C Driver");
    622MODULE_LICENSE("GPL v2");