18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * max8907.c - mfd driver for MAX8907
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
68c2ecf20Sopenharmony_ci * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/err.h>
108c2ecf20Sopenharmony_ci#include <linux/i2c.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
138c2ecf20Sopenharmony_ci#include <linux/irq.h>
148c2ecf20Sopenharmony_ci#include <linux/mfd/core.h>
158c2ecf20Sopenharmony_ci#include <linux/mfd/max8907.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/of.h>
188c2ecf20Sopenharmony_ci#include <linux/of_device.h>
198c2ecf20Sopenharmony_ci#include <linux/regmap.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const struct mfd_cell max8907_cells[] = {
238c2ecf20Sopenharmony_ci	{ .name = "max8907-regulator", },
248c2ecf20Sopenharmony_ci	{ .name = "max8907-rtc", },
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic bool max8907_gen_is_volatile_reg(struct device *dev, unsigned int reg)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	switch (reg) {
308c2ecf20Sopenharmony_ci	case MAX8907_REG_ON_OFF_IRQ1:
318c2ecf20Sopenharmony_ci	case MAX8907_REG_ON_OFF_STAT:
328c2ecf20Sopenharmony_ci	case MAX8907_REG_ON_OFF_IRQ2:
338c2ecf20Sopenharmony_ci	case MAX8907_REG_CHG_IRQ1:
348c2ecf20Sopenharmony_ci	case MAX8907_REG_CHG_IRQ2:
358c2ecf20Sopenharmony_ci	case MAX8907_REG_CHG_STAT:
368c2ecf20Sopenharmony_ci		return true;
378c2ecf20Sopenharmony_ci	default:
388c2ecf20Sopenharmony_ci		return false;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic bool max8907_gen_is_precious_reg(struct device *dev, unsigned int reg)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	switch (reg) {
458c2ecf20Sopenharmony_ci	case MAX8907_REG_ON_OFF_IRQ1:
468c2ecf20Sopenharmony_ci	case MAX8907_REG_ON_OFF_IRQ2:
478c2ecf20Sopenharmony_ci	case MAX8907_REG_CHG_IRQ1:
488c2ecf20Sopenharmony_ci	case MAX8907_REG_CHG_IRQ2:
498c2ecf20Sopenharmony_ci		return true;
508c2ecf20Sopenharmony_ci	default:
518c2ecf20Sopenharmony_ci		return false;
528c2ecf20Sopenharmony_ci	}
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic bool max8907_gen_is_writeable_reg(struct device *dev, unsigned int reg)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	return !max8907_gen_is_volatile_reg(dev, reg);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic const struct regmap_config max8907_regmap_gen_config = {
618c2ecf20Sopenharmony_ci	.reg_bits = 8,
628c2ecf20Sopenharmony_ci	.val_bits = 8,
638c2ecf20Sopenharmony_ci	.volatile_reg = max8907_gen_is_volatile_reg,
648c2ecf20Sopenharmony_ci	.precious_reg = max8907_gen_is_precious_reg,
658c2ecf20Sopenharmony_ci	.writeable_reg = max8907_gen_is_writeable_reg,
668c2ecf20Sopenharmony_ci	.max_register = MAX8907_REG_LDO20VOUT,
678c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic bool max8907_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	if (reg <= MAX8907_REG_RTC_YEAR2)
738c2ecf20Sopenharmony_ci		return true;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	switch (reg) {
768c2ecf20Sopenharmony_ci	case MAX8907_REG_RTC_STATUS:
778c2ecf20Sopenharmony_ci	case MAX8907_REG_RTC_IRQ:
788c2ecf20Sopenharmony_ci		return true;
798c2ecf20Sopenharmony_ci	default:
808c2ecf20Sopenharmony_ci		return false;
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic bool max8907_rtc_is_precious_reg(struct device *dev, unsigned int reg)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	switch (reg) {
878c2ecf20Sopenharmony_ci	case MAX8907_REG_RTC_IRQ:
888c2ecf20Sopenharmony_ci		return true;
898c2ecf20Sopenharmony_ci	default:
908c2ecf20Sopenharmony_ci		return false;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic bool max8907_rtc_is_writeable_reg(struct device *dev, unsigned int reg)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	switch (reg) {
978c2ecf20Sopenharmony_ci	case MAX8907_REG_RTC_STATUS:
988c2ecf20Sopenharmony_ci	case MAX8907_REG_RTC_IRQ:
998c2ecf20Sopenharmony_ci		return false;
1008c2ecf20Sopenharmony_ci	default:
1018c2ecf20Sopenharmony_ci		return true;
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic const struct regmap_config max8907_regmap_rtc_config = {
1068c2ecf20Sopenharmony_ci	.reg_bits = 8,
1078c2ecf20Sopenharmony_ci	.val_bits = 8,
1088c2ecf20Sopenharmony_ci	.volatile_reg = max8907_rtc_is_volatile_reg,
1098c2ecf20Sopenharmony_ci	.precious_reg = max8907_rtc_is_precious_reg,
1108c2ecf20Sopenharmony_ci	.writeable_reg = max8907_rtc_is_writeable_reg,
1118c2ecf20Sopenharmony_ci	.max_register = MAX8907_REG_MPL_CNTL,
1128c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic const struct regmap_irq max8907_chg_irqs[] = {
1168c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 0, },
1178c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 1, },
1188c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 2, },
1198c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 0, },
1208c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 1, },
1218c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 2, },
1228c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 3, },
1238c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 4, },
1248c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 5, },
1258c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 6, },
1268c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 7, },
1278c2ecf20Sopenharmony_ci};
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic const struct regmap_irq_chip max8907_chg_irq_chip = {
1308c2ecf20Sopenharmony_ci	.name = "max8907 chg",
1318c2ecf20Sopenharmony_ci	.status_base = MAX8907_REG_CHG_IRQ1,
1328c2ecf20Sopenharmony_ci	.mask_base = MAX8907_REG_CHG_IRQ1_MASK,
1338c2ecf20Sopenharmony_ci	.wake_base = MAX8907_REG_CHG_IRQ1_MASK,
1348c2ecf20Sopenharmony_ci	.irq_reg_stride = MAX8907_REG_CHG_IRQ2 - MAX8907_REG_CHG_IRQ1,
1358c2ecf20Sopenharmony_ci	.num_regs = 2,
1368c2ecf20Sopenharmony_ci	.irqs = max8907_chg_irqs,
1378c2ecf20Sopenharmony_ci	.num_irqs = ARRAY_SIZE(max8907_chg_irqs),
1388c2ecf20Sopenharmony_ci};
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic const struct regmap_irq max8907_on_off_irqs[] = {
1418c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 0, },
1428c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 1, },
1438c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 2, },
1448c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 3, },
1458c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 4, },
1468c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 5, },
1478c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 6, },
1488c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 7, },
1498c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 0, },
1508c2ecf20Sopenharmony_ci	{ .reg_offset = 1, .mask = 1 << 1, },
1518c2ecf20Sopenharmony_ci};
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic const struct regmap_irq_chip max8907_on_off_irq_chip = {
1548c2ecf20Sopenharmony_ci	.name = "max8907 on_off",
1558c2ecf20Sopenharmony_ci	.status_base = MAX8907_REG_ON_OFF_IRQ1,
1568c2ecf20Sopenharmony_ci	.mask_base = MAX8907_REG_ON_OFF_IRQ1_MASK,
1578c2ecf20Sopenharmony_ci	.irq_reg_stride = MAX8907_REG_ON_OFF_IRQ2 - MAX8907_REG_ON_OFF_IRQ1,
1588c2ecf20Sopenharmony_ci	.num_regs = 2,
1598c2ecf20Sopenharmony_ci	.irqs = max8907_on_off_irqs,
1608c2ecf20Sopenharmony_ci	.num_irqs = ARRAY_SIZE(max8907_on_off_irqs),
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic const struct regmap_irq max8907_rtc_irqs[] = {
1648c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 2, },
1658c2ecf20Sopenharmony_ci	{ .reg_offset = 0, .mask = 1 << 3, },
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic const struct regmap_irq_chip max8907_rtc_irq_chip = {
1698c2ecf20Sopenharmony_ci	.name = "max8907 rtc",
1708c2ecf20Sopenharmony_ci	.status_base = MAX8907_REG_RTC_IRQ,
1718c2ecf20Sopenharmony_ci	.mask_base = MAX8907_REG_RTC_IRQ_MASK,
1728c2ecf20Sopenharmony_ci	.num_regs = 1,
1738c2ecf20Sopenharmony_ci	.irqs = max8907_rtc_irqs,
1748c2ecf20Sopenharmony_ci	.num_irqs = ARRAY_SIZE(max8907_rtc_irqs),
1758c2ecf20Sopenharmony_ci};
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic struct max8907 *max8907_pm_off;
1788c2ecf20Sopenharmony_cistatic void max8907_power_off(void)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG,
1818c2ecf20Sopenharmony_ci			MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic int max8907_i2c_probe(struct i2c_client *i2c,
1858c2ecf20Sopenharmony_ci				       const struct i2c_device_id *id)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct max8907 *max8907;
1888c2ecf20Sopenharmony_ci	int ret;
1898c2ecf20Sopenharmony_ci	struct max8907_platform_data *pdata = dev_get_platdata(&i2c->dev);
1908c2ecf20Sopenharmony_ci	bool pm_off = false;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (pdata)
1938c2ecf20Sopenharmony_ci		pm_off = pdata->pm_off;
1948c2ecf20Sopenharmony_ci	else if (i2c->dev.of_node)
1958c2ecf20Sopenharmony_ci		pm_off = of_property_read_bool(i2c->dev.of_node,
1968c2ecf20Sopenharmony_ci					"maxim,system-power-controller");
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	max8907 = devm_kzalloc(&i2c->dev, sizeof(struct max8907), GFP_KERNEL);
1998c2ecf20Sopenharmony_ci	if (!max8907) {
2008c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2018c2ecf20Sopenharmony_ci		goto err_alloc_drvdata;
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	max8907->dev = &i2c->dev;
2058c2ecf20Sopenharmony_ci	dev_set_drvdata(max8907->dev, max8907);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	max8907->i2c_gen = i2c;
2088c2ecf20Sopenharmony_ci	i2c_set_clientdata(i2c, max8907);
2098c2ecf20Sopenharmony_ci	max8907->regmap_gen = devm_regmap_init_i2c(i2c,
2108c2ecf20Sopenharmony_ci						&max8907_regmap_gen_config);
2118c2ecf20Sopenharmony_ci	if (IS_ERR(max8907->regmap_gen)) {
2128c2ecf20Sopenharmony_ci		ret = PTR_ERR(max8907->regmap_gen);
2138c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "gen regmap init failed: %d\n", ret);
2148c2ecf20Sopenharmony_ci		goto err_regmap_gen;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	max8907->i2c_rtc = i2c_new_dummy_device(i2c->adapter, MAX8907_RTC_I2C_ADDR);
2188c2ecf20Sopenharmony_ci	if (IS_ERR(max8907->i2c_rtc)) {
2198c2ecf20Sopenharmony_ci		ret = PTR_ERR(max8907->i2c_rtc);
2208c2ecf20Sopenharmony_ci		goto err_dummy_rtc;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci	i2c_set_clientdata(max8907->i2c_rtc, max8907);
2238c2ecf20Sopenharmony_ci	max8907->regmap_rtc = devm_regmap_init_i2c(max8907->i2c_rtc,
2248c2ecf20Sopenharmony_ci						&max8907_regmap_rtc_config);
2258c2ecf20Sopenharmony_ci	if (IS_ERR(max8907->regmap_rtc)) {
2268c2ecf20Sopenharmony_ci		ret = PTR_ERR(max8907->regmap_rtc);
2278c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "rtc regmap init failed: %d\n", ret);
2288c2ecf20Sopenharmony_ci		goto err_regmap_rtc;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	irq_set_status_flags(max8907->i2c_gen->irq, IRQ_NOAUTOEN);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
2348c2ecf20Sopenharmony_ci				  IRQF_ONESHOT | IRQF_SHARED, -1,
2358c2ecf20Sopenharmony_ci				  &max8907_chg_irq_chip,
2368c2ecf20Sopenharmony_ci				  &max8907->irqc_chg);
2378c2ecf20Sopenharmony_ci	if (ret != 0) {
2388c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "failed to add chg irq chip: %d\n", ret);
2398c2ecf20Sopenharmony_ci		goto err_irqc_chg;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci	ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
2428c2ecf20Sopenharmony_ci				  IRQF_ONESHOT | IRQF_SHARED, -1,
2438c2ecf20Sopenharmony_ci				  &max8907_on_off_irq_chip,
2448c2ecf20Sopenharmony_ci				  &max8907->irqc_on_off);
2458c2ecf20Sopenharmony_ci	if (ret != 0) {
2468c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "failed to add on off irq chip: %d\n", ret);
2478c2ecf20Sopenharmony_ci		goto err_irqc_on_off;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci	ret = regmap_add_irq_chip(max8907->regmap_rtc, max8907->i2c_gen->irq,
2508c2ecf20Sopenharmony_ci				  IRQF_ONESHOT | IRQF_SHARED, -1,
2518c2ecf20Sopenharmony_ci				  &max8907_rtc_irq_chip,
2528c2ecf20Sopenharmony_ci				  &max8907->irqc_rtc);
2538c2ecf20Sopenharmony_ci	if (ret != 0) {
2548c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "failed to add rtc irq chip: %d\n", ret);
2558c2ecf20Sopenharmony_ci		goto err_irqc_rtc;
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	enable_irq(max8907->i2c_gen->irq);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	ret = mfd_add_devices(max8907->dev, -1, max8907_cells,
2618c2ecf20Sopenharmony_ci			      ARRAY_SIZE(max8907_cells), NULL, 0, NULL);
2628c2ecf20Sopenharmony_ci	if (ret != 0) {
2638c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "failed to add MFD devices %d\n", ret);
2648c2ecf20Sopenharmony_ci		goto err_add_devices;
2658c2ecf20Sopenharmony_ci	}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (pm_off && !pm_power_off) {
2688c2ecf20Sopenharmony_ci		max8907_pm_off = max8907;
2698c2ecf20Sopenharmony_ci		pm_power_off = max8907_power_off;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	return 0;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cierr_add_devices:
2758c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
2768c2ecf20Sopenharmony_cierr_irqc_rtc:
2778c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
2788c2ecf20Sopenharmony_cierr_irqc_on_off:
2798c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
2808c2ecf20Sopenharmony_cierr_irqc_chg:
2818c2ecf20Sopenharmony_cierr_regmap_rtc:
2828c2ecf20Sopenharmony_ci	i2c_unregister_device(max8907->i2c_rtc);
2838c2ecf20Sopenharmony_cierr_dummy_rtc:
2848c2ecf20Sopenharmony_cierr_regmap_gen:
2858c2ecf20Sopenharmony_cierr_alloc_drvdata:
2868c2ecf20Sopenharmony_ci	return ret;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic int max8907_i2c_remove(struct i2c_client *i2c)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct max8907 *max8907 = i2c_get_clientdata(i2c);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	mfd_remove_devices(max8907->dev);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
2968c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
2978c2ecf20Sopenharmony_ci	regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	i2c_unregister_device(max8907->i2c_rtc);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	return 0;
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
3058c2ecf20Sopenharmony_cistatic const struct of_device_id max8907_of_match[] = {
3068c2ecf20Sopenharmony_ci	{ .compatible = "maxim,max8907" },
3078c2ecf20Sopenharmony_ci	{ },
3088c2ecf20Sopenharmony_ci};
3098c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, max8907_of_match);
3108c2ecf20Sopenharmony_ci#endif
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic const struct i2c_device_id max8907_i2c_id[] = {
3138c2ecf20Sopenharmony_ci	{"max8907", 0},
3148c2ecf20Sopenharmony_ci	{}
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max8907_i2c_id);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistatic struct i2c_driver max8907_i2c_driver = {
3198c2ecf20Sopenharmony_ci	.driver = {
3208c2ecf20Sopenharmony_ci		.name = "max8907",
3218c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(max8907_of_match),
3228c2ecf20Sopenharmony_ci	},
3238c2ecf20Sopenharmony_ci	.probe = max8907_i2c_probe,
3248c2ecf20Sopenharmony_ci	.remove = max8907_i2c_remove,
3258c2ecf20Sopenharmony_ci	.id_table = max8907_i2c_id,
3268c2ecf20Sopenharmony_ci};
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic int __init max8907_i2c_init(void)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	int ret = -ENODEV;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	ret = i2c_add_driver(&max8907_i2c_driver);
3338c2ecf20Sopenharmony_ci	if (ret != 0)
3348c2ecf20Sopenharmony_ci		pr_err("Failed to register I2C driver: %d\n", ret);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	return ret;
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_cisubsys_initcall(max8907_i2c_init);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_cistatic void __exit max8907_i2c_exit(void)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	i2c_del_driver(&max8907_i2c_driver);
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_cimodule_exit(max8907_i2c_exit);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MAX8907 multi-function core driver");
3478c2ecf20Sopenharmony_ciMODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
3488c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
349