Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2020 MediaTek Inc.
0004  *
0005  * Author: Gene Chen <gene_chen@richtek.com>
0006  */
0007 
0008 #include <linux/crc8.h>
0009 #include <linux/i2c.h>
0010 #include <linux/init.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mfd/core.h>
0014 #include <linux/module.h>
0015 #include <linux/regmap.h>
0016 #include <linux/slab.h>
0017 
0018 enum {
0019     MT6360_SLAVE_TCPC = 0,
0020     MT6360_SLAVE_PMIC,
0021     MT6360_SLAVE_LDO,
0022     MT6360_SLAVE_PMU,
0023     MT6360_SLAVE_MAX,
0024 };
0025 
0026 struct mt6360_ddata {
0027     struct i2c_client *i2c[MT6360_SLAVE_MAX];
0028     struct device *dev;
0029     struct regmap *regmap;
0030     struct regmap_irq_chip_data *irq_data;
0031     unsigned int chip_rev;
0032     u8 crc8_tbl[CRC8_TABLE_SIZE];
0033 };
0034 
0035 #define MT6360_TCPC_SLAVEID     0x4E
0036 #define MT6360_PMIC_SLAVEID     0x1A
0037 #define MT6360_LDO_SLAVEID      0x64
0038 #define MT6360_PMU_SLAVEID      0x34
0039 
0040 #define MT6360_REG_TCPCSTART        0x00
0041 #define MT6360_REG_TCPCEND      0xFF
0042 #define MT6360_REG_PMICSTART        0x100
0043 #define MT6360_REG_PMICEND      0x13B
0044 #define MT6360_REG_LDOSTART     0x200
0045 #define MT6360_REG_LDOEND       0x21C
0046 #define MT6360_REG_PMUSTART     0x300
0047 #define MT6360_PMU_DEV_INFO     0x300
0048 #define MT6360_PMU_CHG_IRQ1     0x3D0
0049 #define MT6360_PMU_CHG_MASK1        0x3F0
0050 #define MT6360_REG_PMUEND       0x3FF
0051 
0052 #define MT6360_PMU_IRQ_REGNUM       16
0053 
0054 #define CHIP_VEN_MASK           0xF0
0055 #define CHIP_VEN_MT6360         0x50
0056 #define CHIP_REV_MASK           0x0F
0057 
0058 #define MT6360_ADDRESS_MASK     0x3F
0059 #define MT6360_DATA_SIZE_1_BYTE     0x00
0060 #define MT6360_DATA_SIZE_2_BYTES    0x40
0061 #define MT6360_DATA_SIZE_3_BYTES    0x80
0062 #define MT6360_DATA_SIZE_4_BYTES    0xC0
0063 
0064 #define MT6360_CRC8_POLYNOMIAL      0x7
0065 
0066 #define MT6360_CRC_I2C_ADDR_SIZE    1
0067 #define MT6360_CRC_REG_ADDR_SIZE    1
0068 /* prealloca read size = i2c device addr + i2c reg addr + val ... + crc8 */
0069 #define MT6360_ALLOC_READ_SIZE(_size)   (_size + 3)
0070 /* prealloca write size = i2c device addr + i2c reg addr + val ... + crc8 + dummy byte */
0071 #define MT6360_ALLOC_WRITE_SIZE(_size)  (_size + 4)
0072 #define MT6360_CRC_PREDATA_OFFSET   (MT6360_CRC_I2C_ADDR_SIZE + MT6360_CRC_REG_ADDR_SIZE)
0073 #define MT6360_CRC_CRC8_SIZE        1
0074 #define MT6360_CRC_DUMMY_BYTE_SIZE  1
0075 #define MT6360_REGMAP_REG_BYTE_SIZE 2
0076 #define I2C_ADDR_XLATE_8BIT(_addr, _rw) (((_addr & 0x7F) << 1) + _rw)
0077 
0078 /* reg 0 -> 0 ~ 7 */
0079 #define MT6360_CHG_TREG_EVT     4
0080 #define MT6360_CHG_AICR_EVT     5
0081 #define MT6360_CHG_MIVR_EVT     6
0082 #define MT6360_PWR_RDY_EVT      7
0083 /* REG 1 -> 8 ~ 15 */
0084 #define MT6360_CHG_BATSYSUV_EVT     9
0085 #define MT6360_FLED_CHG_VINOVP_EVT  11
0086 #define MT6360_CHG_VSYSUV_EVT       12
0087 #define MT6360_CHG_VSYSOV_EVT       13
0088 #define MT6360_CHG_VBATOV_EVT       14
0089 #define MT6360_CHG_VBUSOV_EVT       15
0090 /* REG 2 -> 16 ~ 23 */
0091 /* REG 3 -> 24 ~ 31 */
0092 #define MT6360_WD_PMU_DET       25
0093 #define MT6360_WD_PMU_DONE      26
0094 #define MT6360_CHG_TMRI         27
0095 #define MT6360_CHG_ADPBADI      29
0096 #define MT6360_CHG_RVPI         30
0097 #define MT6360_OTPI         31
0098 /* REG 4 -> 32 ~ 39 */
0099 #define MT6360_CHG_AICCMEASL        32
0100 #define MT6360_CHGDET_DONEI     34
0101 #define MT6360_WDTMRI           35
0102 #define MT6360_SSFINISHI        36
0103 #define MT6360_CHG_RECHGI       37
0104 #define MT6360_CHG_TERMI        38
0105 #define MT6360_CHG_IEOCI        39
0106 /* REG 5 -> 40 ~ 47 */
0107 #define MT6360_PUMPX_DONEI      40
0108 #define MT6360_BAT_OVP_ADC_EVT      41
0109 #define MT6360_TYPEC_OTP_EVT        42
0110 #define MT6360_ADC_WAKEUP_EVT       43
0111 #define MT6360_ADC_DONEI        44
0112 #define MT6360_BST_BATUVI       45
0113 #define MT6360_BST_VBUSOVI      46
0114 #define MT6360_BST_OLPI         47
0115 /* REG 6 -> 48 ~ 55 */
0116 #define MT6360_ATTACH_I         48
0117 #define MT6360_DETACH_I         49
0118 #define MT6360_QC30_STPDONE     51
0119 #define MT6360_QC_VBUSDET_DONE      52
0120 #define MT6360_HVDCP_DET        53
0121 #define MT6360_CHGDETI          54
0122 #define MT6360_DCDTI            55
0123 /* REG 7 -> 56 ~ 63 */
0124 #define MT6360_FOD_DONE_EVT     56
0125 #define MT6360_FOD_OV_EVT       57
0126 #define MT6360_CHRDET_UVP_EVT       58
0127 #define MT6360_CHRDET_OVP_EVT       59
0128 #define MT6360_CHRDET_EXT_EVT       60
0129 #define MT6360_FOD_LR_EVT       61
0130 #define MT6360_FOD_HR_EVT       62
0131 #define MT6360_FOD_DISCHG_FAIL_EVT  63
0132 /* REG 8 -> 64 ~ 71 */
0133 #define MT6360_USBID_EVT        64
0134 #define MT6360_APWDTRST_EVT     65
0135 #define MT6360_EN_EVT           66
0136 #define MT6360_QONB_RST_EVT     67
0137 #define MT6360_MRSTB_EVT        68
0138 #define MT6360_OTP_EVT          69
0139 #define MT6360_VDDAOV_EVT       70
0140 #define MT6360_SYSUV_EVT        71
0141 /* REG 9 -> 72 ~ 79 */
0142 #define MT6360_FLED_STRBPIN_EVT     72
0143 #define MT6360_FLED_TORPIN_EVT      73
0144 #define MT6360_FLED_TX_EVT      74
0145 #define MT6360_FLED_LVF_EVT     75
0146 #define MT6360_FLED2_SHORT_EVT      78
0147 #define MT6360_FLED1_SHORT_EVT      79
0148 /* REG 10 -> 80 ~ 87 */
0149 #define MT6360_FLED2_STRB_EVT       80
0150 #define MT6360_FLED1_STRB_EVT       81
0151 #define MT6360_FLED2_STRB_TO_EVT    82
0152 #define MT6360_FLED1_STRB_TO_EVT    83
0153 #define MT6360_FLED2_TOR_EVT        84
0154 #define MT6360_FLED1_TOR_EVT        85
0155 /* REG 11 -> 88 ~ 95 */
0156 /* REG 12 -> 96 ~ 103 */
0157 #define MT6360_BUCK1_PGB_EVT        96
0158 #define MT6360_BUCK1_OC_EVT     100
0159 #define MT6360_BUCK1_OV_EVT     101
0160 #define MT6360_BUCK1_UV_EVT     102
0161 /* REG 13 -> 104 ~ 111 */
0162 #define MT6360_BUCK2_PGB_EVT        104
0163 #define MT6360_BUCK2_OC_EVT     108
0164 #define MT6360_BUCK2_OV_EVT     109
0165 #define MT6360_BUCK2_UV_EVT     110
0166 /* REG 14 -> 112 ~ 119 */
0167 #define MT6360_LDO1_OC_EVT      113
0168 #define MT6360_LDO2_OC_EVT      114
0169 #define MT6360_LDO3_OC_EVT      115
0170 #define MT6360_LDO5_OC_EVT      117
0171 #define MT6360_LDO6_OC_EVT      118
0172 #define MT6360_LDO7_OC_EVT      119
0173 /* REG 15 -> 120 ~ 127 */
0174 #define MT6360_LDO1_PGB_EVT     121
0175 #define MT6360_LDO2_PGB_EVT     122
0176 #define MT6360_LDO3_PGB_EVT     123
0177 #define MT6360_LDO5_PGB_EVT     125
0178 #define MT6360_LDO6_PGB_EVT     126
0179 #define MT6360_LDO7_PGB_EVT     127
0180 
0181 static const struct regmap_irq mt6360_irqs[] =  {
0182     REGMAP_IRQ_REG_LINE(MT6360_CHG_TREG_EVT, 8),
0183     REGMAP_IRQ_REG_LINE(MT6360_CHG_AICR_EVT, 8),
0184     REGMAP_IRQ_REG_LINE(MT6360_CHG_MIVR_EVT, 8),
0185     REGMAP_IRQ_REG_LINE(MT6360_PWR_RDY_EVT, 8),
0186     REGMAP_IRQ_REG_LINE(MT6360_CHG_BATSYSUV_EVT, 8),
0187     REGMAP_IRQ_REG_LINE(MT6360_FLED_CHG_VINOVP_EVT, 8),
0188     REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSUV_EVT, 8),
0189     REGMAP_IRQ_REG_LINE(MT6360_CHG_VSYSOV_EVT, 8),
0190     REGMAP_IRQ_REG_LINE(MT6360_CHG_VBATOV_EVT, 8),
0191     REGMAP_IRQ_REG_LINE(MT6360_CHG_VBUSOV_EVT, 8),
0192     REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DET, 8),
0193     REGMAP_IRQ_REG_LINE(MT6360_WD_PMU_DONE, 8),
0194     REGMAP_IRQ_REG_LINE(MT6360_CHG_TMRI, 8),
0195     REGMAP_IRQ_REG_LINE(MT6360_CHG_ADPBADI, 8),
0196     REGMAP_IRQ_REG_LINE(MT6360_CHG_RVPI, 8),
0197     REGMAP_IRQ_REG_LINE(MT6360_OTPI, 8),
0198     REGMAP_IRQ_REG_LINE(MT6360_CHG_AICCMEASL, 8),
0199     REGMAP_IRQ_REG_LINE(MT6360_CHGDET_DONEI, 8),
0200     REGMAP_IRQ_REG_LINE(MT6360_WDTMRI, 8),
0201     REGMAP_IRQ_REG_LINE(MT6360_SSFINISHI, 8),
0202     REGMAP_IRQ_REG_LINE(MT6360_CHG_RECHGI, 8),
0203     REGMAP_IRQ_REG_LINE(MT6360_CHG_TERMI, 8),
0204     REGMAP_IRQ_REG_LINE(MT6360_CHG_IEOCI, 8),
0205     REGMAP_IRQ_REG_LINE(MT6360_PUMPX_DONEI, 8),
0206     REGMAP_IRQ_REG_LINE(MT6360_BAT_OVP_ADC_EVT, 8),
0207     REGMAP_IRQ_REG_LINE(MT6360_TYPEC_OTP_EVT, 8),
0208     REGMAP_IRQ_REG_LINE(MT6360_ADC_WAKEUP_EVT, 8),
0209     REGMAP_IRQ_REG_LINE(MT6360_ADC_DONEI, 8),
0210     REGMAP_IRQ_REG_LINE(MT6360_BST_BATUVI, 8),
0211     REGMAP_IRQ_REG_LINE(MT6360_BST_VBUSOVI, 8),
0212     REGMAP_IRQ_REG_LINE(MT6360_BST_OLPI, 8),
0213     REGMAP_IRQ_REG_LINE(MT6360_ATTACH_I, 8),
0214     REGMAP_IRQ_REG_LINE(MT6360_DETACH_I, 8),
0215     REGMAP_IRQ_REG_LINE(MT6360_QC30_STPDONE, 8),
0216     REGMAP_IRQ_REG_LINE(MT6360_QC_VBUSDET_DONE, 8),
0217     REGMAP_IRQ_REG_LINE(MT6360_HVDCP_DET, 8),
0218     REGMAP_IRQ_REG_LINE(MT6360_CHGDETI, 8),
0219     REGMAP_IRQ_REG_LINE(MT6360_DCDTI, 8),
0220     REGMAP_IRQ_REG_LINE(MT6360_FOD_DONE_EVT, 8),
0221     REGMAP_IRQ_REG_LINE(MT6360_FOD_OV_EVT, 8),
0222     REGMAP_IRQ_REG_LINE(MT6360_CHRDET_UVP_EVT, 8),
0223     REGMAP_IRQ_REG_LINE(MT6360_CHRDET_OVP_EVT, 8),
0224     REGMAP_IRQ_REG_LINE(MT6360_CHRDET_EXT_EVT, 8),
0225     REGMAP_IRQ_REG_LINE(MT6360_FOD_LR_EVT, 8),
0226     REGMAP_IRQ_REG_LINE(MT6360_FOD_HR_EVT, 8),
0227     REGMAP_IRQ_REG_LINE(MT6360_FOD_DISCHG_FAIL_EVT, 8),
0228     REGMAP_IRQ_REG_LINE(MT6360_USBID_EVT, 8),
0229     REGMAP_IRQ_REG_LINE(MT6360_APWDTRST_EVT, 8),
0230     REGMAP_IRQ_REG_LINE(MT6360_EN_EVT, 8),
0231     REGMAP_IRQ_REG_LINE(MT6360_QONB_RST_EVT, 8),
0232     REGMAP_IRQ_REG_LINE(MT6360_MRSTB_EVT, 8),
0233     REGMAP_IRQ_REG_LINE(MT6360_OTP_EVT, 8),
0234     REGMAP_IRQ_REG_LINE(MT6360_VDDAOV_EVT, 8),
0235     REGMAP_IRQ_REG_LINE(MT6360_SYSUV_EVT, 8),
0236     REGMAP_IRQ_REG_LINE(MT6360_FLED_STRBPIN_EVT, 8),
0237     REGMAP_IRQ_REG_LINE(MT6360_FLED_TORPIN_EVT, 8),
0238     REGMAP_IRQ_REG_LINE(MT6360_FLED_TX_EVT, 8),
0239     REGMAP_IRQ_REG_LINE(MT6360_FLED_LVF_EVT, 8),
0240     REGMAP_IRQ_REG_LINE(MT6360_FLED2_SHORT_EVT, 8),
0241     REGMAP_IRQ_REG_LINE(MT6360_FLED1_SHORT_EVT, 8),
0242     REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_EVT, 8),
0243     REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_EVT, 8),
0244     REGMAP_IRQ_REG_LINE(MT6360_FLED2_STRB_TO_EVT, 8),
0245     REGMAP_IRQ_REG_LINE(MT6360_FLED1_STRB_TO_EVT, 8),
0246     REGMAP_IRQ_REG_LINE(MT6360_FLED2_TOR_EVT, 8),
0247     REGMAP_IRQ_REG_LINE(MT6360_FLED1_TOR_EVT, 8),
0248     REGMAP_IRQ_REG_LINE(MT6360_BUCK1_PGB_EVT, 8),
0249     REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OC_EVT, 8),
0250     REGMAP_IRQ_REG_LINE(MT6360_BUCK1_OV_EVT, 8),
0251     REGMAP_IRQ_REG_LINE(MT6360_BUCK1_UV_EVT, 8),
0252     REGMAP_IRQ_REG_LINE(MT6360_BUCK2_PGB_EVT, 8),
0253     REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OC_EVT, 8),
0254     REGMAP_IRQ_REG_LINE(MT6360_BUCK2_OV_EVT, 8),
0255     REGMAP_IRQ_REG_LINE(MT6360_BUCK2_UV_EVT, 8),
0256     REGMAP_IRQ_REG_LINE(MT6360_LDO1_OC_EVT, 8),
0257     REGMAP_IRQ_REG_LINE(MT6360_LDO2_OC_EVT, 8),
0258     REGMAP_IRQ_REG_LINE(MT6360_LDO3_OC_EVT, 8),
0259     REGMAP_IRQ_REG_LINE(MT6360_LDO5_OC_EVT, 8),
0260     REGMAP_IRQ_REG_LINE(MT6360_LDO6_OC_EVT, 8),
0261     REGMAP_IRQ_REG_LINE(MT6360_LDO7_OC_EVT, 8),
0262     REGMAP_IRQ_REG_LINE(MT6360_LDO1_PGB_EVT, 8),
0263     REGMAP_IRQ_REG_LINE(MT6360_LDO2_PGB_EVT, 8),
0264     REGMAP_IRQ_REG_LINE(MT6360_LDO3_PGB_EVT, 8),
0265     REGMAP_IRQ_REG_LINE(MT6360_LDO5_PGB_EVT, 8),
0266     REGMAP_IRQ_REG_LINE(MT6360_LDO6_PGB_EVT, 8),
0267     REGMAP_IRQ_REG_LINE(MT6360_LDO7_PGB_EVT, 8),
0268 };
0269 
0270 static const struct regmap_irq_chip mt6360_irq_chip = {
0271     .name = "mt6360_irqs",
0272     .irqs = mt6360_irqs,
0273     .num_irqs = ARRAY_SIZE(mt6360_irqs),
0274     .num_regs = MT6360_PMU_IRQ_REGNUM,
0275     .mask_base = MT6360_PMU_CHG_MASK1,
0276     .status_base = MT6360_PMU_CHG_IRQ1,
0277     .ack_base = MT6360_PMU_CHG_IRQ1,
0278     .init_ack_masked = true,
0279     .use_ack = true,
0280 };
0281 
0282 static const struct resource mt6360_adc_resources[] = {
0283     DEFINE_RES_IRQ_NAMED(MT6360_ADC_DONEI, "adc_donei"),
0284 };
0285 
0286 static const struct resource mt6360_chg_resources[] = {
0287     DEFINE_RES_IRQ_NAMED(MT6360_CHG_TREG_EVT, "chg_treg_evt"),
0288     DEFINE_RES_IRQ_NAMED(MT6360_PWR_RDY_EVT, "pwr_rdy_evt"),
0289     DEFINE_RES_IRQ_NAMED(MT6360_CHG_BATSYSUV_EVT, "chg_batsysuv_evt"),
0290     DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSUV_EVT, "chg_vsysuv_evt"),
0291     DEFINE_RES_IRQ_NAMED(MT6360_CHG_VSYSOV_EVT, "chg_vsysov_evt"),
0292     DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBATOV_EVT, "chg_vbatov_evt"),
0293     DEFINE_RES_IRQ_NAMED(MT6360_CHG_VBUSOV_EVT, "chg_vbusov_evt"),
0294     DEFINE_RES_IRQ_NAMED(MT6360_CHG_AICCMEASL, "chg_aiccmeasl"),
0295     DEFINE_RES_IRQ_NAMED(MT6360_WDTMRI, "wdtmri"),
0296     DEFINE_RES_IRQ_NAMED(MT6360_CHG_RECHGI, "chg_rechgi"),
0297     DEFINE_RES_IRQ_NAMED(MT6360_CHG_TERMI, "chg_termi"),
0298     DEFINE_RES_IRQ_NAMED(MT6360_CHG_IEOCI, "chg_ieoci"),
0299     DEFINE_RES_IRQ_NAMED(MT6360_PUMPX_DONEI, "pumpx_donei"),
0300     DEFINE_RES_IRQ_NAMED(MT6360_ATTACH_I, "attach_i"),
0301     DEFINE_RES_IRQ_NAMED(MT6360_CHRDET_EXT_EVT, "chrdet_ext_evt"),
0302 };
0303 
0304 static const struct resource mt6360_led_resources[] = {
0305     DEFINE_RES_IRQ_NAMED(MT6360_FLED_CHG_VINOVP_EVT, "fled_chg_vinovp_evt"),
0306     DEFINE_RES_IRQ_NAMED(MT6360_FLED_LVF_EVT, "fled_lvf_evt"),
0307     DEFINE_RES_IRQ_NAMED(MT6360_FLED2_SHORT_EVT, "fled2_short_evt"),
0308     DEFINE_RES_IRQ_NAMED(MT6360_FLED1_SHORT_EVT, "fled1_short_evt"),
0309     DEFINE_RES_IRQ_NAMED(MT6360_FLED2_STRB_TO_EVT, "fled2_strb_to_evt"),
0310     DEFINE_RES_IRQ_NAMED(MT6360_FLED1_STRB_TO_EVT, "fled1_strb_to_evt"),
0311 };
0312 
0313 static const struct resource mt6360_regulator_resources[] = {
0314     DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_PGB_EVT, "buck1_pgb_evt"),
0315     DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OC_EVT, "buck1_oc_evt"),
0316     DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_OV_EVT, "buck1_ov_evt"),
0317     DEFINE_RES_IRQ_NAMED(MT6360_BUCK1_UV_EVT, "buck1_uv_evt"),
0318     DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_PGB_EVT, "buck2_pgb_evt"),
0319     DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OC_EVT, "buck2_oc_evt"),
0320     DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_OV_EVT, "buck2_ov_evt"),
0321     DEFINE_RES_IRQ_NAMED(MT6360_BUCK2_UV_EVT, "buck2_uv_evt"),
0322     DEFINE_RES_IRQ_NAMED(MT6360_LDO1_OC_EVT, "ldo1_oc_evt"),
0323     DEFINE_RES_IRQ_NAMED(MT6360_LDO2_OC_EVT, "ldo2_oc_evt"),
0324     DEFINE_RES_IRQ_NAMED(MT6360_LDO3_OC_EVT, "ldo3_oc_evt"),
0325     DEFINE_RES_IRQ_NAMED(MT6360_LDO5_OC_EVT, "ldo5_oc_evt"),
0326     DEFINE_RES_IRQ_NAMED(MT6360_LDO6_OC_EVT, "ldo6_oc_evt"),
0327     DEFINE_RES_IRQ_NAMED(MT6360_LDO7_OC_EVT, "ldo7_oc_evt"),
0328     DEFINE_RES_IRQ_NAMED(MT6360_LDO1_PGB_EVT, "ldo1_pgb_evt"),
0329     DEFINE_RES_IRQ_NAMED(MT6360_LDO2_PGB_EVT, "ldo2_pgb_evt"),
0330     DEFINE_RES_IRQ_NAMED(MT6360_LDO3_PGB_EVT, "ldo3_pgb_evt"),
0331     DEFINE_RES_IRQ_NAMED(MT6360_LDO5_PGB_EVT, "ldo5_pgb_evt"),
0332     DEFINE_RES_IRQ_NAMED(MT6360_LDO6_PGB_EVT, "ldo6_pgb_evt"),
0333     DEFINE_RES_IRQ_NAMED(MT6360_LDO7_PGB_EVT, "ldo7_pgb_evt"),
0334 };
0335 
0336 static const struct mfd_cell mt6360_devs[] = {
0337     MFD_CELL_OF("mt6360-adc", mt6360_adc_resources,
0338             NULL, 0, 0, "mediatek,mt6360-adc"),
0339     MFD_CELL_OF("mt6360-chg", mt6360_chg_resources,
0340             NULL, 0, 0, "mediatek,mt6360-chg"),
0341     MFD_CELL_OF("mt6360-led", mt6360_led_resources,
0342             NULL, 0, 0, "mediatek,mt6360-led"),
0343     MFD_CELL_RES("mt6360-regulator", mt6360_regulator_resources),
0344     MFD_CELL_OF("mt6360-tcpc", NULL,
0345             NULL, 0, 0, "mediatek,mt6360-tcpc"),
0346 };
0347 
0348 static int mt6360_check_vendor_info(struct mt6360_ddata *ddata)
0349 {
0350     u32 info;
0351     int ret;
0352 
0353     ret = regmap_read(ddata->regmap, MT6360_PMU_DEV_INFO, &info);
0354     if (ret < 0)
0355         return ret;
0356 
0357     if ((info & CHIP_VEN_MASK) != CHIP_VEN_MT6360) {
0358         dev_err(ddata->dev, "Device not supported\n");
0359         return -ENODEV;
0360     }
0361 
0362     ddata->chip_rev = info & CHIP_REV_MASK;
0363 
0364     return 0;
0365 }
0366 
0367 static const unsigned short mt6360_slave_addr[MT6360_SLAVE_MAX] = {
0368     MT6360_TCPC_SLAVEID,
0369     MT6360_PMIC_SLAVEID,
0370     MT6360_LDO_SLAVEID,
0371     MT6360_PMU_SLAVEID,
0372 };
0373 
0374 static int mt6360_xlate_pmicldo_addr(u8 *addr, int rw_size)
0375 {
0376     /* Address is already in encoded [5:0] */
0377     *addr &= MT6360_ADDRESS_MASK;
0378 
0379     switch (rw_size) {
0380     case 1:
0381         *addr |= MT6360_DATA_SIZE_1_BYTE;
0382         break;
0383     case 2:
0384         *addr |= MT6360_DATA_SIZE_2_BYTES;
0385         break;
0386     case 3:
0387         *addr |= MT6360_DATA_SIZE_3_BYTES;
0388         break;
0389     case 4:
0390         *addr |= MT6360_DATA_SIZE_4_BYTES;
0391         break;
0392     default:
0393         return -EINVAL;
0394     }
0395 
0396     return 0;
0397 }
0398 
0399 static int mt6360_regmap_read(void *context, const void *reg, size_t reg_size,
0400                   void *val, size_t val_size)
0401 {
0402     struct mt6360_ddata *ddata = context;
0403     u8 bank = *(u8 *)reg;
0404     u8 reg_addr = *(u8 *)(reg + 1);
0405     struct i2c_client *i2c = ddata->i2c[bank];
0406     bool crc_needed = false;
0407     u8 *buf;
0408     int buf_len = MT6360_ALLOC_READ_SIZE(val_size);
0409     int read_size = val_size;
0410     u8 crc;
0411     int ret;
0412 
0413     if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
0414         crc_needed = true;
0415         ret = mt6360_xlate_pmicldo_addr(&reg_addr, val_size);
0416         if (ret < 0)
0417             return ret;
0418         read_size += MT6360_CRC_CRC8_SIZE;
0419     }
0420 
0421     buf = kzalloc(buf_len, GFP_KERNEL);
0422     if (!buf)
0423         return -ENOMEM;
0424 
0425     buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_READ);
0426     buf[1] = reg_addr;
0427 
0428     ret = i2c_smbus_read_i2c_block_data(i2c, reg_addr, read_size,
0429                         buf + MT6360_CRC_PREDATA_OFFSET);
0430     if (ret < 0)
0431         goto out;
0432     else if (ret != read_size) {
0433         ret = -EIO;
0434         goto out;
0435     }
0436 
0437     if (crc_needed) {
0438         crc = crc8(ddata->crc8_tbl, buf, val_size + MT6360_CRC_PREDATA_OFFSET, 0);
0439         if (crc != buf[val_size + MT6360_CRC_PREDATA_OFFSET]) {
0440             ret = -EIO;
0441             goto out;
0442         }
0443     }
0444 
0445     memcpy(val, buf + MT6360_CRC_PREDATA_OFFSET, val_size);
0446 out:
0447     kfree(buf);
0448     return (ret < 0) ? ret : 0;
0449 }
0450 
0451 static int mt6360_regmap_write(void *context, const void *val, size_t val_size)
0452 {
0453     struct mt6360_ddata *ddata = context;
0454     u8 bank = *(u8 *)val;
0455     u8 reg_addr = *(u8 *)(val + 1);
0456     struct i2c_client *i2c = ddata->i2c[bank];
0457     bool crc_needed = false;
0458     u8 *buf;
0459     int buf_len = MT6360_ALLOC_WRITE_SIZE(val_size);
0460     int write_size = val_size - MT6360_REGMAP_REG_BYTE_SIZE;
0461     int ret;
0462 
0463     if (bank == MT6360_SLAVE_PMIC || bank == MT6360_SLAVE_LDO) {
0464         crc_needed = true;
0465         ret = mt6360_xlate_pmicldo_addr(&reg_addr, val_size - MT6360_REGMAP_REG_BYTE_SIZE);
0466         if (ret < 0)
0467             return ret;
0468     }
0469 
0470     buf = kzalloc(buf_len, GFP_KERNEL);
0471     if (!buf)
0472         return -ENOMEM;
0473 
0474     buf[0] = I2C_ADDR_XLATE_8BIT(i2c->addr, I2C_SMBUS_WRITE);
0475     buf[1] = reg_addr;
0476     memcpy(buf + MT6360_CRC_PREDATA_OFFSET, val + MT6360_REGMAP_REG_BYTE_SIZE, write_size);
0477 
0478     if (crc_needed) {
0479         buf[val_size] = crc8(ddata->crc8_tbl, buf, val_size, 0);
0480         write_size += (MT6360_CRC_CRC8_SIZE + MT6360_CRC_DUMMY_BYTE_SIZE);
0481     }
0482 
0483     ret = i2c_smbus_write_i2c_block_data(i2c, reg_addr, write_size,
0484                          buf + MT6360_CRC_PREDATA_OFFSET);
0485 
0486     kfree(buf);
0487     return ret;
0488 }
0489 
0490 static const struct regmap_bus mt6360_regmap_bus = {
0491     .read       = mt6360_regmap_read,
0492     .write      = mt6360_regmap_write,
0493 
0494     /* Due to PMIC and LDO CRC access size limit */
0495     .max_raw_read   = 4,
0496     .max_raw_write  = 4,
0497 };
0498 
0499 static bool mt6360_is_readwrite_reg(struct device *dev, unsigned int reg)
0500 {
0501     switch (reg) {
0502     case MT6360_REG_TCPCSTART ... MT6360_REG_TCPCEND:
0503         fallthrough;
0504     case MT6360_REG_PMICSTART ... MT6360_REG_PMICEND:
0505         fallthrough;
0506     case MT6360_REG_LDOSTART ... MT6360_REG_LDOEND:
0507         fallthrough;
0508     case MT6360_REG_PMUSTART ... MT6360_REG_PMUEND:
0509         return true;
0510     }
0511 
0512     return false;
0513 }
0514 
0515 static const struct regmap_config mt6360_regmap_config = {
0516     .reg_bits       = 16,
0517     .val_bits       = 8,
0518     .reg_format_endian  = REGMAP_ENDIAN_BIG,
0519     .max_register       = MT6360_REG_PMUEND,
0520     .writeable_reg      = mt6360_is_readwrite_reg,
0521     .readable_reg       = mt6360_is_readwrite_reg,
0522 };
0523 
0524 static int mt6360_probe(struct i2c_client *client)
0525 {
0526     struct mt6360_ddata *ddata;
0527     int i, ret;
0528 
0529     ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
0530     if (!ddata)
0531         return -ENOMEM;
0532 
0533     ddata->dev = &client->dev;
0534     i2c_set_clientdata(client, ddata);
0535 
0536     for (i = 0; i < MT6360_SLAVE_MAX - 1; i++) {
0537         ddata->i2c[i] = devm_i2c_new_dummy_device(&client->dev,
0538                               client->adapter,
0539                               mt6360_slave_addr[i]);
0540         if (IS_ERR(ddata->i2c[i])) {
0541             dev_err(&client->dev,
0542                 "Failed to get new dummy I2C device for address 0x%x",
0543                 mt6360_slave_addr[i]);
0544             return PTR_ERR(ddata->i2c[i]);
0545         }
0546     }
0547     ddata->i2c[MT6360_SLAVE_MAX - 1] = client;
0548 
0549     crc8_populate_msb(ddata->crc8_tbl, MT6360_CRC8_POLYNOMIAL);
0550     ddata->regmap = devm_regmap_init(ddata->dev, &mt6360_regmap_bus, ddata,
0551                      &mt6360_regmap_config);
0552     if (IS_ERR(ddata->regmap)) {
0553         dev_err(&client->dev, "Failed to register regmap\n");
0554         return PTR_ERR(ddata->regmap);
0555     }
0556 
0557     ret = mt6360_check_vendor_info(ddata);
0558     if (ret)
0559         return ret;
0560 
0561     ret = devm_regmap_add_irq_chip(&client->dev, ddata->regmap, client->irq,
0562                        0, 0, &mt6360_irq_chip,
0563                        &ddata->irq_data);
0564     if (ret) {
0565         dev_err(&client->dev, "Failed to add Regmap IRQ Chip\n");
0566         return ret;
0567     }
0568 
0569     ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
0570                    mt6360_devs, ARRAY_SIZE(mt6360_devs), NULL,
0571                    0, regmap_irq_get_domain(ddata->irq_data));
0572     if (ret) {
0573         dev_err(&client->dev,
0574             "Failed to register subordinate devices\n");
0575         return ret;
0576     }
0577 
0578     return 0;
0579 }
0580 
0581 static int __maybe_unused mt6360_suspend(struct device *dev)
0582 {
0583     struct i2c_client *i2c = to_i2c_client(dev);
0584 
0585     if (device_may_wakeup(dev))
0586         enable_irq_wake(i2c->irq);
0587 
0588     return 0;
0589 }
0590 
0591 static int __maybe_unused mt6360_resume(struct device *dev)
0592 {
0593 
0594     struct i2c_client *i2c = to_i2c_client(dev);
0595 
0596     if (device_may_wakeup(dev))
0597         disable_irq_wake(i2c->irq);
0598 
0599     return 0;
0600 }
0601 
0602 static SIMPLE_DEV_PM_OPS(mt6360_pm_ops, mt6360_suspend, mt6360_resume);
0603 
0604 static const struct of_device_id __maybe_unused mt6360_of_id[] = {
0605     { .compatible = "mediatek,mt6360", },
0606     {},
0607 };
0608 MODULE_DEVICE_TABLE(of, mt6360_of_id);
0609 
0610 static struct i2c_driver mt6360_driver = {
0611     .driver = {
0612         .name = "mt6360",
0613         .pm = &mt6360_pm_ops,
0614         .of_match_table = of_match_ptr(mt6360_of_id),
0615     },
0616     .probe_new = mt6360_probe,
0617 };
0618 module_i2c_driver(mt6360_driver);
0619 
0620 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
0621 MODULE_DESCRIPTION("MT6360 I2C Driver");
0622 MODULE_LICENSE("GPL v2");