231 lines · 6.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0//// Copyright (C) 2018 BayLibre SAS// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>//// Core MFD driver for MAXIM 77650/77651 charger/power-supply.// Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf #include <linux/i2c.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/mfd/core.h>#include <linux/mfd/max77650.h>#include <linux/module.h>#include <linux/of.h>#include <linux/regmap.h> #define MAX77650_INT_GPI_F_MSK		BIT(0)#define MAX77650_INT_GPI_R_MSK		BIT(1)#define MAX77650_INT_GPI_MSK \			(MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK)#define MAX77650_INT_nEN_F_MSK		BIT(2)#define MAX77650_INT_nEN_R_MSK		BIT(3)#define MAX77650_INT_TJAL1_R_MSK	BIT(4)#define MAX77650_INT_TJAL2_R_MSK	BIT(5)#define MAX77650_INT_DOD_R_MSK		BIT(6) #define MAX77650_INT_THM_MSK		BIT(0)#define MAX77650_INT_CHG_MSK		BIT(1)#define MAX77650_INT_CHGIN_MSK		BIT(2)#define MAX77650_INT_TJ_REG_MSK		BIT(3)#define MAX77650_INT_CHGIN_CTRL_MSK	BIT(4)#define MAX77650_INT_SYS_CTRL_MSK	BIT(5)#define MAX77650_INT_SYS_CNFG_MSK	BIT(6) #define MAX77650_INT_GLBL_OFFSET	0#define MAX77650_INT_CHG_OFFSET		1 #define MAX77650_SBIA_LPM_MASK		BIT(5)#define MAX77650_SBIA_LPM_DISABLED	0x00 enum {	MAX77650_INT_GPI,	MAX77650_INT_nEN_F,	MAX77650_INT_nEN_R,	MAX77650_INT_TJAL1_R,	MAX77650_INT_TJAL2_R,	MAX77650_INT_DOD_R,	MAX77650_INT_THM,	MAX77650_INT_CHG,	MAX77650_INT_CHGIN,	MAX77650_INT_TJ_REG,	MAX77650_INT_CHGIN_CTRL,	MAX77650_INT_SYS_CTRL,	MAX77650_INT_SYS_CNFG,}; static const struct resource max77650_charger_resources[] = {	DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"),	DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"),}; static const struct resource max77650_gpio_resources[] = {	DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"),}; static const struct resource max77650_onkey_resources[] = {	DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"),	DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"),}; static const struct mfd_cell max77650_cells[] = {	{		.name		= "max77650-regulator",		.of_compatible	= "maxim,max77650-regulator",	}, {		.name		= "max77650-charger",		.of_compatible	= "maxim,max77650-charger",		.resources	= max77650_charger_resources,		.num_resources	= ARRAY_SIZE(max77650_charger_resources),	}, {		.name		= "max77650-gpio",		.of_compatible	= "maxim,max77650-gpio",		.resources	= max77650_gpio_resources,		.num_resources	= ARRAY_SIZE(max77650_gpio_resources),	}, {		.name		= "max77650-led",		.of_compatible	= "maxim,max77650-led",	}, {		.name		= "max77650-onkey",		.of_compatible	= "maxim,max77650-onkey",		.resources	= max77650_onkey_resources,		.num_resources	= ARRAY_SIZE(max77650_onkey_resources),	},}; static const struct regmap_irq max77650_irqs[] = {	[MAX77650_INT_GPI] = {		.reg_offset = MAX77650_INT_GLBL_OFFSET,		.mask = MAX77650_INT_GPI_MSK,		.type = {			.type_falling_val = MAX77650_INT_GPI_F_MSK,			.type_rising_val = MAX77650_INT_GPI_R_MSK,			.types_supported = IRQ_TYPE_EDGE_BOTH,		},	},	REGMAP_IRQ_REG(MAX77650_INT_nEN_F,		       MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK),	REGMAP_IRQ_REG(MAX77650_INT_nEN_R,		       MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK),	REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R,		       MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK),	REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R,		       MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK),	REGMAP_IRQ_REG(MAX77650_INT_DOD_R,		       MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK),	REGMAP_IRQ_REG(MAX77650_INT_THM,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK),	REGMAP_IRQ_REG(MAX77650_INT_CHG,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK),	REGMAP_IRQ_REG(MAX77650_INT_CHGIN,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK),	REGMAP_IRQ_REG(MAX77650_INT_TJ_REG,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK),	REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK),	REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK),	REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG,		       MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK),}; static const struct regmap_irq_chip max77650_irq_chip = {	.name			= "max77650-irq",	.irqs			= max77650_irqs,	.num_irqs		= ARRAY_SIZE(max77650_irqs),	.num_regs		= 2,	.status_base		= MAX77650_REG_INT_GLBL,	.mask_base		= MAX77650_REG_INTM_GLBL,	.type_in_mask		= true,	.init_ack_masked	= true,	.clear_on_unmask	= true,}; static const struct regmap_config max77650_regmap_config = {	.name		= "max77650",	.reg_bits	= 8,	.val_bits	= 8,}; static int max77650_i2c_probe(struct i2c_client *i2c){	struct regmap_irq_chip_data *irq_data;	struct device *dev = &i2c->dev;	struct irq_domain *domain;	struct regmap *map;	unsigned int val;	int rv, id; 	map = devm_regmap_init_i2c(i2c, &max77650_regmap_config);	if (IS_ERR(map)) {		dev_err(dev, "Unable to initialise I2C Regmap\n");		return PTR_ERR(map);	} 	rv = regmap_read(map, MAX77650_REG_CID, &val);	if (rv) {		dev_err(dev, "Unable to read Chip ID\n");		return rv;	} 	id = MAX77650_CID_BITS(val);	switch (id) {	case MAX77650_CID_77650A:	case MAX77650_CID_77650C:	case MAX77650_CID_77651A:	case MAX77650_CID_77651B:		break;	default:		dev_err(dev, "Chip not supported - ID: 0x%02x\n", id);		return -ENODEV;	} 	/*	 * This IC has a low-power mode which reduces the quiescent current	 * consumption to ~5.6uA but is only suitable for systems consuming	 * less than ~2mA. Since this is not likely the case even on	 * linux-based wearables - keep the chip in normal power mode.	 */	rv = regmap_update_bits(map,				MAX77650_REG_CNFG_GLBL,				MAX77650_SBIA_LPM_MASK,				MAX77650_SBIA_LPM_DISABLED);	if (rv) {		dev_err(dev, "Unable to change the power mode\n");		return rv;	} 	rv = devm_regmap_add_irq_chip(dev, map, i2c->irq,				      IRQF_ONESHOT | IRQF_SHARED, 0,				      &max77650_irq_chip, &irq_data);	if (rv) {		dev_err(dev, "Unable to add Regmap IRQ chip\n");		return rv;	} 	domain = regmap_irq_get_domain(irq_data); 	return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,				    max77650_cells, ARRAY_SIZE(max77650_cells),				    NULL, 0, domain);} static const struct of_device_id max77650_of_match[] = {	{ .compatible = "maxim,max77650" },	{ }};MODULE_DEVICE_TABLE(of, max77650_of_match); static struct i2c_driver max77650_i2c_driver = {	.driver = {		.name = "max77650",		.of_match_table = max77650_of_match,	},	.probe = max77650_i2c_probe,};module_i2c_driver(max77650_i2c_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver");MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");MODULE_LICENSE("GPL v2");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t