brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · c126ccb Raw
313 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2022 Richtek Technology Corp.4 *5 * Author: ChiYuan Huang <cy_huang@richtek.com>6 */7 8#include <linux/bits.h>9#include <linux/bitfield.h>10#include <linux/i2c.h>11#include <linux/interrupt.h>12#include <linux/kernel.h>13#include <linux/mfd/core.h>14#include <linux/module.h>15#include <linux/regmap.h>16 17#include "mt6370.h"18 19#define MT6370_REG_DEV_INFO	0x10020#define MT6370_REG_CHG_IRQ1	0x1C021#define MT6370_REG_CHG_MASK1	0x1E022#define MT6370_REG_MAXADDR	0x1FF23 24#define MT6370_VENID_MASK	GENMASK(7, 4)25 26#define MT6370_NUM_IRQREGS	1627#define MT6370_USBC_I2CADDR	0x4E28#define MT6370_MAX_ADDRLEN	229 30#define MT6370_VENID_RT5081	0x831#define MT6370_VENID_RT5081A	0xA32#define MT6370_VENID_MT6370	0xE33#define MT6370_VENID_MT6371	0xF34#define MT6370_VENID_MT6372P	0x935#define MT6370_VENID_MT6372CP	0xB36 37static const struct regmap_irq mt6370_irqs[] = {38	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8),39	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8),40	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8),41	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8),42	REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8),43	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8),44	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8),45	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8),46	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8),47	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8),48	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8),49	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8),50	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8),51	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8),52	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8),53	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8),54	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8),55	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8),56	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8),57	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8),58	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8),59	REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8),60	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8),61	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8),62	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8),63	REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8),64	REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8),65	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8),66	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8),67	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8),68	REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8),69	REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8),70	REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8),71	REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8),72	REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8),73	REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8),74	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8),75	REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8),76	REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8),77	REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8),78	REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET, 8),79	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DCDT, 8),80	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_VGOK, 8),81	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_WDTMR, 8),82	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_UC, 8),83	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OC, 8),84	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OV, 8),85	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_SWON, 8),86	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP_D, 8),87	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP, 8),88	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP_D, 8),89	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP, 8),90	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_STRBPIN, 8),91	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TORPIN, 8),92	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TX, 8),93	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_LVF, 8),94	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_SHORT, 8),95	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_SHORT, 8),96	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_STRB, 8),97	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB, 8),98	REGMAP_IRQ_REG_LINE(mT6370_IRQ_FLED2_STRB_TO, 8),99	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB_TO, 8),100	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_TOR, 8),101	REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_TOR, 8),102	REGMAP_IRQ_REG_LINE(MT6370_IRQ_OTP, 8),103	REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_OVP, 8),104	REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_UV, 8),105	REGMAP_IRQ_REG_LINE(MT6370_IRQ_LDO_OC, 8),106	REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OCP, 8),107	REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OVP, 8),108	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_OCP, 8),109	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_OCP, 8),110	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_BST_OCP, 8),111	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_SCP, 8),112	REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_SCP, 8),113};114 115static const struct regmap_irq_chip mt6370_irq_chip = {116	.name		= "mt6370-irqs",117	.status_base	= MT6370_REG_CHG_IRQ1,118	.mask_base	= MT6370_REG_CHG_MASK1,119	.num_regs	= MT6370_NUM_IRQREGS,120	.irqs		= mt6370_irqs,121	.num_irqs	= ARRAY_SIZE(mt6370_irqs),122};123 124static const struct resource mt6370_regulator_irqs[] = {125	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_SCP, "db_vpos_scp"),126	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_SCP, "db_vneg_scp"),127	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_BST_OCP, "db_vbst_ocp"),128	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_OCP, "db_vpos_ocp"),129	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_OCP, "db_vneg_ocp"),130	DEFINE_RES_IRQ_NAMED(MT6370_IRQ_LDO_OC, "ldo_oc"),131};132 133static const struct mfd_cell mt6370_devices[] = {134	MFD_CELL_OF("mt6370-adc",135		    NULL, NULL, 0, 0, "mediatek,mt6370-adc"),136	MFD_CELL_OF("mt6370-charger",137		    NULL, NULL, 0, 0, "mediatek,mt6370-charger"),138	MFD_CELL_OF("mt6370-flashlight",139		    NULL, NULL, 0, 0, "mediatek,mt6370-flashlight"),140	MFD_CELL_OF("mt6370-indicator",141		    NULL, NULL, 0, 0, "mediatek,mt6370-indicator"),142	MFD_CELL_OF("mt6370-tcpc",143		    NULL, NULL, 0, 0, "mediatek,mt6370-tcpc"),144	MFD_CELL_RES("mt6370-regulator", mt6370_regulator_irqs),145};146 147static const struct mfd_cell mt6370_exclusive_devices[] = {148	MFD_CELL_OF("mt6370-backlight",149		    NULL, NULL, 0, 0, "mediatek,mt6370-backlight"),150};151 152static const struct mfd_cell mt6372_exclusive_devices[] = {153	MFD_CELL_OF("mt6370-backlight",154		    NULL, NULL, 0, 0, "mediatek,mt6372-backlight"),155};156 157static int mt6370_check_vendor_info(struct device *dev, struct regmap *rmap,158				    int *vid)159{160	unsigned int devinfo;161	int ret;162 163	ret = regmap_read(rmap, MT6370_REG_DEV_INFO, &devinfo);164	if (ret)165		return ret;166 167	*vid = FIELD_GET(MT6370_VENID_MASK, devinfo);168	switch (*vid) {169	case MT6370_VENID_RT5081:170	case MT6370_VENID_RT5081A:171	case MT6370_VENID_MT6370:172	case MT6370_VENID_MT6371:173	case MT6370_VENID_MT6372P:174	case MT6370_VENID_MT6372CP:175		return 0;176	default:177		dev_err(dev, "Unknown Vendor ID 0x%02x\n", devinfo);178		return -ENODEV;179	}180}181 182static int mt6370_regmap_read(void *context, const void *reg_buf,183			      size_t reg_size, void *val_buf, size_t val_size)184{185	struct mt6370_info *info = context;186	const u8 *u8_buf = reg_buf;187	u8 bank_idx, bank_addr;188	int ret;189 190	bank_idx = u8_buf[0];191	bank_addr = u8_buf[1];192 193	ret = i2c_smbus_read_i2c_block_data(info->i2c[bank_idx], bank_addr,194					    val_size, val_buf);195	if (ret < 0)196		return ret;197 198	if (ret != val_size)199		return -EIO;200 201	return 0;202}203 204static int mt6370_regmap_write(void *context, const void *data, size_t count)205{206	struct mt6370_info *info = context;207	const u8 *u8_buf = data;208	u8 bank_idx, bank_addr;209	int len = count - MT6370_MAX_ADDRLEN;210 211	bank_idx = u8_buf[0];212	bank_addr = u8_buf[1];213 214	return i2c_smbus_write_i2c_block_data(info->i2c[bank_idx], bank_addr,215					      len, data + MT6370_MAX_ADDRLEN);216}217 218static const struct regmap_bus mt6370_regmap_bus = {219	.read		= mt6370_regmap_read,220	.write		= mt6370_regmap_write,221};222 223static const struct regmap_config mt6370_regmap_config = {224	.reg_bits		= 16,225	.val_bits		= 8,226	.reg_format_endian	= REGMAP_ENDIAN_BIG,227	.max_register		= MT6370_REG_MAXADDR,228};229 230static int mt6370_probe(struct i2c_client *i2c)231{232	struct mt6370_info *info;233	struct i2c_client *usbc_i2c;234	struct regmap *regmap;235	struct device *dev = &i2c->dev;236	int ret, vid;237 238	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);239	if (!info)240		return -ENOMEM;241 242	usbc_i2c = devm_i2c_new_dummy_device(dev, i2c->adapter,243					     MT6370_USBC_I2CADDR);244	if (IS_ERR(usbc_i2c))245		return dev_err_probe(dev, PTR_ERR(usbc_i2c),246				     "Failed to register USBC I2C client\n");247 248	/* Assign I2C client for PMU and TypeC */249	info->i2c[MT6370_PMU_I2C] = i2c;250	info->i2c[MT6370_USBC_I2C] = usbc_i2c;251 252	regmap = devm_regmap_init(dev, &mt6370_regmap_bus,253				  info, &mt6370_regmap_config);254	if (IS_ERR(regmap))255		return dev_err_probe(dev, PTR_ERR(regmap),256				     "Failed to init regmap\n");257 258	ret = mt6370_check_vendor_info(dev, regmap, &vid);259	if (ret)260		return dev_err_probe(dev, ret, "Failed to check vendor info\n");261 262	ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq,263				       IRQF_ONESHOT, -1, &mt6370_irq_chip,264				       &info->irq_data);265	if (ret)266		return dev_err_probe(dev, ret, "Failed to add irq chip\n");267 268	switch (vid) {269	case MT6370_VENID_MT6372P:270	case MT6370_VENID_MT6372CP:271		ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,272					   mt6372_exclusive_devices,273					   ARRAY_SIZE(mt6372_exclusive_devices),274					   NULL, 0,275					   regmap_irq_get_domain(info->irq_data));276		break;277	default:278		ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,279					   mt6370_exclusive_devices,280					   ARRAY_SIZE(mt6370_exclusive_devices),281					   NULL, 0,282					   regmap_irq_get_domain(info->irq_data));283		break;284	}285 286	if (ret)287		return dev_err_probe(dev, ret, "Failed to add the exclusive devices\n");288 289	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,290				    mt6370_devices, ARRAY_SIZE(mt6370_devices),291				    NULL, 0,292				    regmap_irq_get_domain(info->irq_data));293}294 295static const struct of_device_id mt6370_match_table[] = {296	{ .compatible = "mediatek,mt6370" },297	{}298};299MODULE_DEVICE_TABLE(of, mt6370_match_table);300 301static struct i2c_driver mt6370_driver = {302	.driver = {303		.name = "mt6370",304		.of_match_table = mt6370_match_table,305	},306	.probe = mt6370_probe,307};308module_i2c_driver(mt6370_driver);309 310MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");311MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver");312MODULE_LICENSE("GPL v2");313