linux/drivers/mfd/mt6360-core.c
<<
>>
Prefs
   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");
 623