18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Core driver for TI TPS6586x PMIC family
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2010 CompuLab Ltd.
68c2ecf20Sopenharmony_ci * Mike Rapoport <mike@compulab.co.il>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Based on da903x.c.
98c2ecf20Sopenharmony_ci * Copyright (C) 2008 Compulab, Ltd.
108c2ecf20Sopenharmony_ci * Mike Rapoport <mike@compulab.co.il>
118c2ecf20Sopenharmony_ci * Copyright (C) 2006-2008 Marvell International Ltd.
128c2ecf20Sopenharmony_ci * Eric Miao <eric.miao@marvell.com>
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
168c2ecf20Sopenharmony_ci#include <linux/irq.h>
178c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
188c2ecf20Sopenharmony_ci#include <linux/kernel.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/mutex.h>
218c2ecf20Sopenharmony_ci#include <linux/slab.h>
228c2ecf20Sopenharmony_ci#include <linux/err.h>
238c2ecf20Sopenharmony_ci#include <linux/i2c.h>
248c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
258c2ecf20Sopenharmony_ci#include <linux/regmap.h>
268c2ecf20Sopenharmony_ci#include <linux/of.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <linux/mfd/core.h>
298c2ecf20Sopenharmony_ci#include <linux/mfd/tps6586x.h>
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define TPS6586X_SUPPLYENE	0x14
328c2ecf20Sopenharmony_ci#define EXITSLREQ_BIT		BIT(1)
338c2ecf20Sopenharmony_ci#define SLEEP_MODE_BIT		BIT(3)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* interrupt control registers */
368c2ecf20Sopenharmony_ci#define TPS6586X_INT_ACK1	0xb5
378c2ecf20Sopenharmony_ci#define TPS6586X_INT_ACK2	0xb6
388c2ecf20Sopenharmony_ci#define TPS6586X_INT_ACK3	0xb7
398c2ecf20Sopenharmony_ci#define TPS6586X_INT_ACK4	0xb8
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* interrupt mask registers */
428c2ecf20Sopenharmony_ci#define TPS6586X_INT_MASK1	0xb0
438c2ecf20Sopenharmony_ci#define TPS6586X_INT_MASK2	0xb1
448c2ecf20Sopenharmony_ci#define TPS6586X_INT_MASK3	0xb2
458c2ecf20Sopenharmony_ci#define TPS6586X_INT_MASK4	0xb3
468c2ecf20Sopenharmony_ci#define TPS6586X_INT_MASK5	0xb4
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* device id */
498c2ecf20Sopenharmony_ci#define TPS6586X_VERSIONCRC	0xcd
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* Maximum register */
528c2ecf20Sopenharmony_ci#define TPS6586X_MAX_REGISTER	TPS6586X_VERSIONCRC
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistruct tps6586x_irq_data {
558c2ecf20Sopenharmony_ci	u8	mask_reg;
568c2ecf20Sopenharmony_ci	u8	mask_mask;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define TPS6586X_IRQ(_reg, _mask)				\
608c2ecf20Sopenharmony_ci	{							\
618c2ecf20Sopenharmony_ci		.mask_reg = (_reg) - TPS6586X_INT_MASK1,	\
628c2ecf20Sopenharmony_ci		.mask_mask = (_mask),				\
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic const struct tps6586x_irq_data tps6586x_irqs[] = {
668c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 0),
678c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 1),
688c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 2),
698c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 3),
708c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_4]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 4),
718c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_5]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 5),
728c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_6]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 6),
738c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_7]	= TPS6586X_IRQ(TPS6586X_INT_MASK1, 1 << 7),
748c2ecf20Sopenharmony_ci	[TPS6586X_INT_COMP_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 0),
758c2ecf20Sopenharmony_ci	[TPS6586X_INT_ADC]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 1),
768c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_8]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 2),
778c2ecf20Sopenharmony_ci	[TPS6586X_INT_PLDO_9]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 3),
788c2ecf20Sopenharmony_ci	[TPS6586X_INT_PSM_0]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 4),
798c2ecf20Sopenharmony_ci	[TPS6586X_INT_PSM_1]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 5),
808c2ecf20Sopenharmony_ci	[TPS6586X_INT_PSM_2]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 6),
818c2ecf20Sopenharmony_ci	[TPS6586X_INT_PSM_3]	= TPS6586X_IRQ(TPS6586X_INT_MASK2, 1 << 7),
828c2ecf20Sopenharmony_ci	[TPS6586X_INT_RTC_ALM1]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 4),
838c2ecf20Sopenharmony_ci	[TPS6586X_INT_ACUSB_OVP] = TPS6586X_IRQ(TPS6586X_INT_MASK5, 0x03),
848c2ecf20Sopenharmony_ci	[TPS6586X_INT_USB_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 2),
858c2ecf20Sopenharmony_ci	[TPS6586X_INT_AC_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 3),
868c2ecf20Sopenharmony_ci	[TPS6586X_INT_BAT_DET]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 1 << 0),
878c2ecf20Sopenharmony_ci	[TPS6586X_INT_CHG_STAT]	= TPS6586X_IRQ(TPS6586X_INT_MASK4, 0xfc),
888c2ecf20Sopenharmony_ci	[TPS6586X_INT_CHG_TEMP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0x06),
898c2ecf20Sopenharmony_ci	[TPS6586X_INT_PP]	= TPS6586X_IRQ(TPS6586X_INT_MASK3, 0xf0),
908c2ecf20Sopenharmony_ci	[TPS6586X_INT_RESUME]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 5),
918c2ecf20Sopenharmony_ci	[TPS6586X_INT_LOW_SYS]	= TPS6586X_IRQ(TPS6586X_INT_MASK5, 1 << 6),
928c2ecf20Sopenharmony_ci	[TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic struct resource tps6586x_rtc_resources[] = {
968c2ecf20Sopenharmony_ci	{
978c2ecf20Sopenharmony_ci		.start  = TPS6586X_INT_RTC_ALM1,
988c2ecf20Sopenharmony_ci		.end	= TPS6586X_INT_RTC_ALM1,
998c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
1008c2ecf20Sopenharmony_ci	},
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic const struct mfd_cell tps6586x_cell[] = {
1048c2ecf20Sopenharmony_ci	{
1058c2ecf20Sopenharmony_ci		.name = "tps6586x-gpio",
1068c2ecf20Sopenharmony_ci	},
1078c2ecf20Sopenharmony_ci	{
1088c2ecf20Sopenharmony_ci		.name = "tps6586x-regulator",
1098c2ecf20Sopenharmony_ci	},
1108c2ecf20Sopenharmony_ci	{
1118c2ecf20Sopenharmony_ci		.name = "tps6586x-rtc",
1128c2ecf20Sopenharmony_ci		.num_resources = ARRAY_SIZE(tps6586x_rtc_resources),
1138c2ecf20Sopenharmony_ci		.resources = &tps6586x_rtc_resources[0],
1148c2ecf20Sopenharmony_ci	},
1158c2ecf20Sopenharmony_ci	{
1168c2ecf20Sopenharmony_ci		.name = "tps6586x-onkey",
1178c2ecf20Sopenharmony_ci	},
1188c2ecf20Sopenharmony_ci};
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistruct tps6586x {
1218c2ecf20Sopenharmony_ci	struct device		*dev;
1228c2ecf20Sopenharmony_ci	struct i2c_client	*client;
1238c2ecf20Sopenharmony_ci	struct regmap		*regmap;
1248c2ecf20Sopenharmony_ci	int			version;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	int			irq;
1278c2ecf20Sopenharmony_ci	struct irq_chip		irq_chip;
1288c2ecf20Sopenharmony_ci	struct mutex		irq_lock;
1298c2ecf20Sopenharmony_ci	int			irq_base;
1308c2ecf20Sopenharmony_ci	u32			irq_en;
1318c2ecf20Sopenharmony_ci	u8			mask_reg[5];
1328c2ecf20Sopenharmony_ci	struct irq_domain	*irq_domain;
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic inline struct tps6586x *dev_to_tps6586x(struct device *dev)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	return i2c_get_clientdata(to_i2c_client(dev));
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ciint tps6586x_write(struct device *dev, int reg, uint8_t val)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	return regmap_write(tps6586x->regmap, reg, val);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_write);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ciint tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return regmap_bulk_write(tps6586x->regmap, reg, val, len);
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_writes);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciint tps6586x_read(struct device *dev, int reg, uint8_t *val)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1598c2ecf20Sopenharmony_ci	unsigned int rval;
1608c2ecf20Sopenharmony_ci	int ret;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	ret = regmap_read(tps6586x->regmap, reg, &rval);
1638c2ecf20Sopenharmony_ci	if (!ret)
1648c2ecf20Sopenharmony_ci		*val = rval;
1658c2ecf20Sopenharmony_ci	return ret;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_read);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ciint tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return regmap_bulk_read(tps6586x->regmap, reg, val, len);
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_reads);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ciint tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	return regmap_update_bits(tps6586x->regmap, reg, bit_mask, bit_mask);
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_set_bits);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ciint tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	return regmap_update_bits(tps6586x->regmap, reg, bit_mask, 0);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_clr_bits);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ciint tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	return regmap_update_bits(tps6586x->regmap, reg, mask, val);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_update);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciint tps6586x_irq_get_virq(struct device *dev, int irq)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_to_tps6586x(dev);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	return irq_create_mapping(tps6586x->irq_domain, irq);
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_irq_get_virq);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ciint tps6586x_get_version(struct device *dev)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_get_drvdata(dev);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	return tps6586x->version;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tps6586x_get_version);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic int __remove_subdev(struct device *dev, void *unused)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	platform_device_unregister(to_platform_device(dev));
2208c2ecf20Sopenharmony_ci	return 0;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic void tps6586x_irq_lock(struct irq_data *data)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	mutex_lock(&tps6586x->irq_lock);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void tps6586x_irq_enable(struct irq_data *irq_data)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
2388c2ecf20Sopenharmony_ci	unsigned int __irq = irq_data->hwirq;
2398c2ecf20Sopenharmony_ci	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	tps6586x->mask_reg[data->mask_reg] &= ~data->mask_mask;
2428c2ecf20Sopenharmony_ci	tps6586x->irq_en |= (1 << __irq);
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic void tps6586x_irq_disable(struct irq_data *irq_data)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	unsigned int __irq = irq_data->hwirq;
2508c2ecf20Sopenharmony_ci	const struct tps6586x_irq_data *data = &tps6586x_irqs[__irq];
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	tps6586x->mask_reg[data->mask_reg] |= data->mask_mask;
2538c2ecf20Sopenharmony_ci	tps6586x->irq_en &= ~(1 << __irq);
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic void tps6586x_irq_sync_unlock(struct irq_data *data)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(data);
2598c2ecf20Sopenharmony_ci	int i;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
2628c2ecf20Sopenharmony_ci		int ret;
2638c2ecf20Sopenharmony_ci		ret = tps6586x_write(tps6586x->dev,
2648c2ecf20Sopenharmony_ci					    TPS6586X_INT_MASK1 + i,
2658c2ecf20Sopenharmony_ci					    tps6586x->mask_reg[i]);
2668c2ecf20Sopenharmony_ci		WARN_ON(ret);
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	mutex_unlock(&tps6586x->irq_lock);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
2738c2ecf20Sopenharmony_cistatic int tps6586x_irq_set_wake(struct irq_data *irq_data, unsigned int on)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
2768c2ecf20Sopenharmony_ci	return irq_set_irq_wake(tps6586x->irq, on);
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci#else
2798c2ecf20Sopenharmony_ci#define tps6586x_irq_set_wake NULL
2808c2ecf20Sopenharmony_ci#endif
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic struct irq_chip tps6586x_irq_chip = {
2838c2ecf20Sopenharmony_ci	.name = "tps6586x",
2848c2ecf20Sopenharmony_ci	.irq_bus_lock = tps6586x_irq_lock,
2858c2ecf20Sopenharmony_ci	.irq_bus_sync_unlock = tps6586x_irq_sync_unlock,
2868c2ecf20Sopenharmony_ci	.irq_disable = tps6586x_irq_disable,
2878c2ecf20Sopenharmony_ci	.irq_enable = tps6586x_irq_enable,
2888c2ecf20Sopenharmony_ci	.irq_set_wake = tps6586x_irq_set_wake,
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic int tps6586x_irq_map(struct irq_domain *h, unsigned int virq,
2928c2ecf20Sopenharmony_ci				irq_hw_number_t hw)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = h->host_data;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	irq_set_chip_data(virq, tps6586x);
2978c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(virq, &tps6586x_irq_chip, handle_simple_irq);
2988c2ecf20Sopenharmony_ci	irq_set_nested_thread(virq, 1);
2998c2ecf20Sopenharmony_ci	irq_set_noprobe(virq);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	return 0;
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic const struct irq_domain_ops tps6586x_domain_ops = {
3058c2ecf20Sopenharmony_ci	.map    = tps6586x_irq_map,
3068c2ecf20Sopenharmony_ci	.xlate  = irq_domain_xlate_twocell,
3078c2ecf20Sopenharmony_ci};
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic irqreturn_t tps6586x_irq(int irq, void *data)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = data;
3128c2ecf20Sopenharmony_ci	uint32_t acks;
3138c2ecf20Sopenharmony_ci	__le32 val;
3148c2ecf20Sopenharmony_ci	int ret = 0;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	ret = tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1,
3178c2ecf20Sopenharmony_ci			     sizeof(acks), (uint8_t *)&val);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	if (ret < 0) {
3208c2ecf20Sopenharmony_ci		dev_err(tps6586x->dev, "failed to read interrupt status\n");
3218c2ecf20Sopenharmony_ci		return IRQ_NONE;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	acks = le32_to_cpu(val);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	while (acks) {
3278c2ecf20Sopenharmony_ci		int i = __ffs(acks);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		if (tps6586x->irq_en & (1 << i))
3308c2ecf20Sopenharmony_ci			handle_nested_irq(
3318c2ecf20Sopenharmony_ci				irq_find_mapping(tps6586x->irq_domain, i));
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci		acks &= ~(1 << i);
3348c2ecf20Sopenharmony_ci	}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
3408c2ecf20Sopenharmony_ci				       int irq_base)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	int i, ret;
3438c2ecf20Sopenharmony_ci	u8 tmp[4];
3448c2ecf20Sopenharmony_ci	int new_irq_base;
3458c2ecf20Sopenharmony_ci	int irq_num = ARRAY_SIZE(tps6586x_irqs);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	tps6586x->irq = irq;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	mutex_init(&tps6586x->irq_lock);
3508c2ecf20Sopenharmony_ci	for (i = 0; i < 5; i++) {
3518c2ecf20Sopenharmony_ci		tps6586x->mask_reg[i] = 0xff;
3528c2ecf20Sopenharmony_ci		tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff);
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	tps6586x_reads(tps6586x->dev, TPS6586X_INT_ACK1, sizeof(tmp), tmp);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if  (irq_base > 0) {
3588c2ecf20Sopenharmony_ci		new_irq_base = irq_alloc_descs(irq_base, 0, irq_num, -1);
3598c2ecf20Sopenharmony_ci		if (new_irq_base < 0) {
3608c2ecf20Sopenharmony_ci			dev_err(tps6586x->dev,
3618c2ecf20Sopenharmony_ci				"Failed to alloc IRQs: %d\n", new_irq_base);
3628c2ecf20Sopenharmony_ci			return new_irq_base;
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci	} else {
3658c2ecf20Sopenharmony_ci		new_irq_base = 0;
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	tps6586x->irq_domain = irq_domain_add_simple(tps6586x->dev->of_node,
3698c2ecf20Sopenharmony_ci				irq_num, new_irq_base, &tps6586x_domain_ops,
3708c2ecf20Sopenharmony_ci				tps6586x);
3718c2ecf20Sopenharmony_ci	if (!tps6586x->irq_domain) {
3728c2ecf20Sopenharmony_ci		dev_err(tps6586x->dev, "Failed to create IRQ domain\n");
3738c2ecf20Sopenharmony_ci		return -ENOMEM;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci	ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT,
3768c2ecf20Sopenharmony_ci				   "tps6586x", tps6586x);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (!ret)
3798c2ecf20Sopenharmony_ci		device_init_wakeup(tps6586x->dev, 1);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	return ret;
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic int tps6586x_add_subdevs(struct tps6586x *tps6586x,
3858c2ecf20Sopenharmony_ci					  struct tps6586x_platform_data *pdata)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct tps6586x_subdev_info *subdev;
3888c2ecf20Sopenharmony_ci	struct platform_device *pdev;
3898c2ecf20Sopenharmony_ci	int i, ret = 0;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	for (i = 0; i < pdata->num_subdevs; i++) {
3928c2ecf20Sopenharmony_ci		subdev = &pdata->subdevs[i];
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		pdev = platform_device_alloc(subdev->name, subdev->id);
3958c2ecf20Sopenharmony_ci		if (!pdev) {
3968c2ecf20Sopenharmony_ci			ret = -ENOMEM;
3978c2ecf20Sopenharmony_ci			goto failed;
3988c2ecf20Sopenharmony_ci		}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci		pdev->dev.parent = tps6586x->dev;
4018c2ecf20Sopenharmony_ci		pdev->dev.platform_data = subdev->platform_data;
4028c2ecf20Sopenharmony_ci		pdev->dev.of_node = subdev->of_node;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		ret = platform_device_add(pdev);
4058c2ecf20Sopenharmony_ci		if (ret) {
4068c2ecf20Sopenharmony_ci			platform_device_put(pdev);
4078c2ecf20Sopenharmony_ci			goto failed;
4088c2ecf20Sopenharmony_ci		}
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci	return 0;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cifailed:
4138c2ecf20Sopenharmony_ci	tps6586x_remove_subdevs(tps6586x);
4148c2ecf20Sopenharmony_ci	return ret;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
4188c2ecf20Sopenharmony_cistatic struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	struct device_node *np = client->dev.of_node;
4218c2ecf20Sopenharmony_ci	struct tps6586x_platform_data *pdata;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
4248c2ecf20Sopenharmony_ci	if (!pdata)
4258c2ecf20Sopenharmony_ci		return NULL;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	pdata->num_subdevs = 0;
4288c2ecf20Sopenharmony_ci	pdata->subdevs = NULL;
4298c2ecf20Sopenharmony_ci	pdata->gpio_base = -1;
4308c2ecf20Sopenharmony_ci	pdata->irq_base = -1;
4318c2ecf20Sopenharmony_ci	pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	return pdata;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic const struct of_device_id tps6586x_of_match[] = {
4378c2ecf20Sopenharmony_ci	{ .compatible = "ti,tps6586x", },
4388c2ecf20Sopenharmony_ci	{ },
4398c2ecf20Sopenharmony_ci};
4408c2ecf20Sopenharmony_ci#else
4418c2ecf20Sopenharmony_cistatic struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
4428c2ecf20Sopenharmony_ci{
4438c2ecf20Sopenharmony_ci	return NULL;
4448c2ecf20Sopenharmony_ci}
4458c2ecf20Sopenharmony_ci#endif
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic bool is_volatile_reg(struct device *dev, unsigned int reg)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	/* Cache all interrupt mask register */
4508c2ecf20Sopenharmony_ci	if ((reg >= TPS6586X_INT_MASK1) && (reg <= TPS6586X_INT_MASK5))
4518c2ecf20Sopenharmony_ci		return false;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	return true;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic const struct regmap_config tps6586x_regmap_config = {
4578c2ecf20Sopenharmony_ci	.reg_bits = 8,
4588c2ecf20Sopenharmony_ci	.val_bits = 8,
4598c2ecf20Sopenharmony_ci	.max_register = TPS6586X_MAX_REGISTER,
4608c2ecf20Sopenharmony_ci	.volatile_reg = is_volatile_reg,
4618c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
4628c2ecf20Sopenharmony_ci};
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic struct device *tps6586x_dev;
4658c2ecf20Sopenharmony_cistatic void tps6586x_power_off(void)
4668c2ecf20Sopenharmony_ci{
4678c2ecf20Sopenharmony_ci	if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
4688c2ecf20Sopenharmony_ci		return;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_cistatic void tps6586x_print_version(struct i2c_client *client, int version)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	const char *name;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	switch (version) {
4788c2ecf20Sopenharmony_ci	case TPS658621A:
4798c2ecf20Sopenharmony_ci		name = "TPS658621A";
4808c2ecf20Sopenharmony_ci		break;
4818c2ecf20Sopenharmony_ci	case TPS658621CD:
4828c2ecf20Sopenharmony_ci		name = "TPS658621C/D";
4838c2ecf20Sopenharmony_ci		break;
4848c2ecf20Sopenharmony_ci	case TPS658623:
4858c2ecf20Sopenharmony_ci		name = "TPS658623";
4868c2ecf20Sopenharmony_ci		break;
4878c2ecf20Sopenharmony_ci	case TPS658640:
4888c2ecf20Sopenharmony_ci	case TPS658640v2:
4898c2ecf20Sopenharmony_ci		name = "TPS658640";
4908c2ecf20Sopenharmony_ci		break;
4918c2ecf20Sopenharmony_ci	case TPS658643:
4928c2ecf20Sopenharmony_ci		name = "TPS658643";
4938c2ecf20Sopenharmony_ci		break;
4948c2ecf20Sopenharmony_ci	default:
4958c2ecf20Sopenharmony_ci		name = "TPS6586X";
4968c2ecf20Sopenharmony_ci		break;
4978c2ecf20Sopenharmony_ci	}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	dev_info(&client->dev, "Found %s, VERSIONCRC is %02x\n", name, version);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic int tps6586x_i2c_probe(struct i2c_client *client,
5038c2ecf20Sopenharmony_ci					const struct i2c_device_id *id)
5048c2ecf20Sopenharmony_ci{
5058c2ecf20Sopenharmony_ci	struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
5068c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x;
5078c2ecf20Sopenharmony_ci	int ret;
5088c2ecf20Sopenharmony_ci	int version;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	if (!pdata && client->dev.of_node)
5118c2ecf20Sopenharmony_ci		pdata = tps6586x_parse_dt(client);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	if (!pdata) {
5148c2ecf20Sopenharmony_ci		dev_err(&client->dev, "tps6586x requires platform data\n");
5158c2ecf20Sopenharmony_ci		return -ENOTSUPP;
5168c2ecf20Sopenharmony_ci	}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	version = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
5198c2ecf20Sopenharmony_ci	if (version < 0) {
5208c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Chip ID read failed: %d\n", version);
5218c2ecf20Sopenharmony_ci		return -EIO;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
5258c2ecf20Sopenharmony_ci	if (!tps6586x)
5268c2ecf20Sopenharmony_ci		return -ENOMEM;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	tps6586x->version = version;
5298c2ecf20Sopenharmony_ci	tps6586x_print_version(client, tps6586x->version);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	tps6586x->client = client;
5328c2ecf20Sopenharmony_ci	tps6586x->dev = &client->dev;
5338c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, tps6586x);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	tps6586x->regmap = devm_regmap_init_i2c(client,
5368c2ecf20Sopenharmony_ci					&tps6586x_regmap_config);
5378c2ecf20Sopenharmony_ci	if (IS_ERR(tps6586x->regmap)) {
5388c2ecf20Sopenharmony_ci		ret = PTR_ERR(tps6586x->regmap);
5398c2ecf20Sopenharmony_ci		dev_err(&client->dev, "regmap init failed: %d\n", ret);
5408c2ecf20Sopenharmony_ci		return ret;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	if (client->irq) {
5458c2ecf20Sopenharmony_ci		ret = tps6586x_irq_init(tps6586x, client->irq,
5468c2ecf20Sopenharmony_ci					pdata->irq_base);
5478c2ecf20Sopenharmony_ci		if (ret) {
5488c2ecf20Sopenharmony_ci			dev_err(&client->dev, "IRQ init failed: %d\n", ret);
5498c2ecf20Sopenharmony_ci			return ret;
5508c2ecf20Sopenharmony_ci		}
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ret = mfd_add_devices(tps6586x->dev, -1,
5548c2ecf20Sopenharmony_ci			      tps6586x_cell, ARRAY_SIZE(tps6586x_cell),
5558c2ecf20Sopenharmony_ci			      NULL, 0, tps6586x->irq_domain);
5568c2ecf20Sopenharmony_ci	if (ret < 0) {
5578c2ecf20Sopenharmony_ci		dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
5588c2ecf20Sopenharmony_ci		goto err_mfd_add;
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ret = tps6586x_add_subdevs(tps6586x, pdata);
5628c2ecf20Sopenharmony_ci	if (ret) {
5638c2ecf20Sopenharmony_ci		dev_err(&client->dev, "add devices failed: %d\n", ret);
5648c2ecf20Sopenharmony_ci		goto err_add_devs;
5658c2ecf20Sopenharmony_ci	}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	if (pdata->pm_off && !pm_power_off) {
5688c2ecf20Sopenharmony_ci		tps6586x_dev = &client->dev;
5698c2ecf20Sopenharmony_ci		pm_power_off = tps6586x_power_off;
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return 0;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cierr_add_devs:
5758c2ecf20Sopenharmony_ci	mfd_remove_devices(tps6586x->dev);
5768c2ecf20Sopenharmony_cierr_mfd_add:
5778c2ecf20Sopenharmony_ci	if (client->irq)
5788c2ecf20Sopenharmony_ci		free_irq(client->irq, tps6586x);
5798c2ecf20Sopenharmony_ci	return ret;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic int tps6586x_i2c_remove(struct i2c_client *client)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = i2c_get_clientdata(client);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	tps6586x_remove_subdevs(tps6586x);
5878c2ecf20Sopenharmony_ci	mfd_remove_devices(tps6586x->dev);
5888c2ecf20Sopenharmony_ci	if (client->irq)
5898c2ecf20Sopenharmony_ci		free_irq(client->irq, tps6586x);
5908c2ecf20Sopenharmony_ci	return 0;
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cistatic int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
5948c2ecf20Sopenharmony_ci{
5958c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_get_drvdata(dev);
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	if (tps6586x->client->irq)
5988c2ecf20Sopenharmony_ci		disable_irq(tps6586x->client->irq);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	return 0;
6018c2ecf20Sopenharmony_ci}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_cistatic int __maybe_unused tps6586x_i2c_resume(struct device *dev)
6048c2ecf20Sopenharmony_ci{
6058c2ecf20Sopenharmony_ci	struct tps6586x *tps6586x = dev_get_drvdata(dev);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (tps6586x->client->irq)
6088c2ecf20Sopenharmony_ci		enable_irq(tps6586x->client->irq);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	return 0;
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
6148c2ecf20Sopenharmony_ci			 tps6586x_i2c_resume);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_cistatic const struct i2c_device_id tps6586x_id_table[] = {
6178c2ecf20Sopenharmony_ci	{ "tps6586x", 0 },
6188c2ecf20Sopenharmony_ci	{ },
6198c2ecf20Sopenharmony_ci};
6208c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic struct i2c_driver tps6586x_driver = {
6238c2ecf20Sopenharmony_ci	.driver	= {
6248c2ecf20Sopenharmony_ci		.name	= "tps6586x",
6258c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(tps6586x_of_match),
6268c2ecf20Sopenharmony_ci		.pm	= &tps6586x_pm_ops,
6278c2ecf20Sopenharmony_ci	},
6288c2ecf20Sopenharmony_ci	.probe		= tps6586x_i2c_probe,
6298c2ecf20Sopenharmony_ci	.remove		= tps6586x_i2c_remove,
6308c2ecf20Sopenharmony_ci	.id_table	= tps6586x_id_table,
6318c2ecf20Sopenharmony_ci};
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic int __init tps6586x_init(void)
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	return i2c_add_driver(&tps6586x_driver);
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_cisubsys_initcall(tps6586x_init);
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic void __exit tps6586x_exit(void)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	i2c_del_driver(&tps6586x_driver);
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_cimodule_exit(tps6586x_exit);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TPS6586X core driver");
6468c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
6478c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
648