18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "%s: " fmt, __func__
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
108c2ecf20Sopenharmony_ci#include <linux/irqchip/chained_irq.h>
118c2ecf20Sopenharmony_ci#include <linux/irq.h>
128c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci#include <linux/err.h>
178c2ecf20Sopenharmony_ci#include <linux/ssbi.h>
188c2ecf20Sopenharmony_ci#include <linux/regmap.h>
198c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
208c2ecf20Sopenharmony_ci#include <linux/mfd/core.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
258c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
268c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
278c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
288c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
298c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
308c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
318c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
328c2ecf20Sopenharmony_ci#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
358c2ecf20Sopenharmony_ci#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
368c2ecf20Sopenharmony_ci#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
378c2ecf20Sopenharmony_ci#define	PM8821_SSBI_REG(m, b, offset) \
388c2ecf20Sopenharmony_ci			((m == 0) ? \
398c2ecf20Sopenharmony_ci			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
408c2ecf20Sopenharmony_ci			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
418c2ecf20Sopenharmony_ci#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
428c2ecf20Sopenharmony_ci#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
438c2ecf20Sopenharmony_ci#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
448c2ecf20Sopenharmony_ci#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#define	PM8821_BLOCKS_PER_MASTER	7
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define	PM_IRQF_LVL_SEL			0x01	/* level select */
498c2ecf20Sopenharmony_ci#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
508c2ecf20Sopenharmony_ci#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
518c2ecf20Sopenharmony_ci#define	PM_IRQF_CLR			0x08	/* clear interrupt */
528c2ecf20Sopenharmony_ci#define	PM_IRQF_BITS_MASK		0x70
538c2ecf20Sopenharmony_ci#define	PM_IRQF_BITS_SHIFT		4
548c2ecf20Sopenharmony_ci#define	PM_IRQF_WRITE			0x80
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
578c2ecf20Sopenharmony_ci					PM_IRQF_MASK_RE)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define REG_HWREV		0x002  /* PMIC4 revision */
608c2ecf20Sopenharmony_ci#define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define PM8XXX_NR_IRQS		256
638c2ecf20Sopenharmony_ci#define PM8821_NR_IRQS		112
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct pm_irq_data {
668c2ecf20Sopenharmony_ci	int num_irqs;
678c2ecf20Sopenharmony_ci	struct irq_chip *irq_chip;
688c2ecf20Sopenharmony_ci	void (*irq_handler)(struct irq_desc *desc);
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistruct pm_irq_chip {
728c2ecf20Sopenharmony_ci	struct regmap		*regmap;
738c2ecf20Sopenharmony_ci	spinlock_t		pm_irq_lock;
748c2ecf20Sopenharmony_ci	struct irq_domain	*irqdomain;
758c2ecf20Sopenharmony_ci	unsigned int		num_blocks;
768c2ecf20Sopenharmony_ci	unsigned int		num_masters;
778c2ecf20Sopenharmony_ci	const struct pm_irq_data *pm_irq_data;
788c2ecf20Sopenharmony_ci	/* MUST BE AT THE END OF THIS STRUCT */
798c2ecf20Sopenharmony_ci	u8			config[];
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
838c2ecf20Sopenharmony_ci				 unsigned int *ip)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	int	rc;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	spin_lock(&chip->pm_irq_lock);
888c2ecf20Sopenharmony_ci	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
898c2ecf20Sopenharmony_ci	if (rc) {
908c2ecf20Sopenharmony_ci		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
918c2ecf20Sopenharmony_ci		goto bail;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
958c2ecf20Sopenharmony_ci	if (rc)
968c2ecf20Sopenharmony_ci		pr_err("Failed Reading Status rc=%d\n", rc);
978c2ecf20Sopenharmony_cibail:
988c2ecf20Sopenharmony_ci	spin_unlock(&chip->pm_irq_lock);
998c2ecf20Sopenharmony_ci	return rc;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic int
1038c2ecf20Sopenharmony_cipm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	int	rc;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	spin_lock(&chip->pm_irq_lock);
1088c2ecf20Sopenharmony_ci	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
1098c2ecf20Sopenharmony_ci	if (rc) {
1108c2ecf20Sopenharmony_ci		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
1118c2ecf20Sopenharmony_ci		goto bail;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	cp |= PM_IRQF_WRITE;
1158c2ecf20Sopenharmony_ci	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
1168c2ecf20Sopenharmony_ci	if (rc)
1178c2ecf20Sopenharmony_ci		pr_err("Failed Configuring IRQ rc=%d\n", rc);
1188c2ecf20Sopenharmony_cibail:
1198c2ecf20Sopenharmony_ci	spin_unlock(&chip->pm_irq_lock);
1208c2ecf20Sopenharmony_ci	return rc;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	int pmirq, irq, i, ret = 0;
1268c2ecf20Sopenharmony_ci	unsigned int bits;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	ret = pm8xxx_read_block_irq(chip, block, &bits);
1298c2ecf20Sopenharmony_ci	if (ret) {
1308c2ecf20Sopenharmony_ci		pr_err("Failed reading %d block ret=%d", block, ret);
1318c2ecf20Sopenharmony_ci		return ret;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci	if (!bits) {
1348c2ecf20Sopenharmony_ci		pr_err("block bit set in master but no irqs: %d", block);
1358c2ecf20Sopenharmony_ci		return 0;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	/* Check IRQ bits */
1398c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
1408c2ecf20Sopenharmony_ci		if (bits & (1 << i)) {
1418c2ecf20Sopenharmony_ci			pmirq = block * 8 + i;
1428c2ecf20Sopenharmony_ci			irq = irq_find_mapping(chip->irqdomain, pmirq);
1438c2ecf20Sopenharmony_ci			generic_handle_irq(irq);
1448c2ecf20Sopenharmony_ci		}
1458c2ecf20Sopenharmony_ci	}
1468c2ecf20Sopenharmony_ci	return 0;
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	unsigned int blockbits;
1528c2ecf20Sopenharmony_ci	int block_number, i, ret = 0;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
1558c2ecf20Sopenharmony_ci			  &blockbits);
1568c2ecf20Sopenharmony_ci	if (ret) {
1578c2ecf20Sopenharmony_ci		pr_err("Failed to read master %d ret=%d\n", master, ret);
1588c2ecf20Sopenharmony_ci		return ret;
1598c2ecf20Sopenharmony_ci	}
1608c2ecf20Sopenharmony_ci	if (!blockbits) {
1618c2ecf20Sopenharmony_ci		pr_err("master bit set in root but no blocks: %d", master);
1628c2ecf20Sopenharmony_ci		return 0;
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++)
1668c2ecf20Sopenharmony_ci		if (blockbits & (1 << i)) {
1678c2ecf20Sopenharmony_ci			block_number = master * 8 + i;	/* block # */
1688c2ecf20Sopenharmony_ci			ret |= pm8xxx_irq_block_handler(chip, block_number);
1698c2ecf20Sopenharmony_ci		}
1708c2ecf20Sopenharmony_ci	return ret;
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic void pm8xxx_irq_handler(struct irq_desc *desc)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
1768c2ecf20Sopenharmony_ci	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
1778c2ecf20Sopenharmony_ci	unsigned int root;
1788c2ecf20Sopenharmony_ci	int	i, ret, masters = 0;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	chained_irq_enter(irq_chip, desc);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
1838c2ecf20Sopenharmony_ci	if (ret) {
1848c2ecf20Sopenharmony_ci		pr_err("Can't read root status ret=%d\n", ret);
1858c2ecf20Sopenharmony_ci		return;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	/* on pm8xxx series masters start from bit 1 of the root */
1898c2ecf20Sopenharmony_ci	masters = root >> 1;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* Read allowed masters for blocks. */
1928c2ecf20Sopenharmony_ci	for (i = 0; i < chip->num_masters; i++)
1938c2ecf20Sopenharmony_ci		if (masters & (1 << i))
1948c2ecf20Sopenharmony_ci			pm8xxx_irq_master_handler(chip, i);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	chained_irq_exit(irq_chip, desc);
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic void pm8821_irq_block_handler(struct pm_irq_chip *chip,
2008c2ecf20Sopenharmony_ci				     int master, int block)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	int pmirq, irq, i, ret;
2038c2ecf20Sopenharmony_ci	unsigned int bits;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	ret = regmap_read(chip->regmap,
2068c2ecf20Sopenharmony_ci			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
2078c2ecf20Sopenharmony_ci	if (ret) {
2088c2ecf20Sopenharmony_ci		pr_err("Reading block %d failed ret=%d", block, ret);
2098c2ecf20Sopenharmony_ci		return;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	/* Convert block offset to global block number */
2138c2ecf20Sopenharmony_ci	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	/* Check IRQ bits */
2168c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
2178c2ecf20Sopenharmony_ci		if (bits & BIT(i)) {
2188c2ecf20Sopenharmony_ci			pmirq = block * 8 + i;
2198c2ecf20Sopenharmony_ci			irq = irq_find_mapping(chip->irqdomain, pmirq);
2208c2ecf20Sopenharmony_ci			generic_handle_irq(irq);
2218c2ecf20Sopenharmony_ci		}
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
2268c2ecf20Sopenharmony_ci					     int master, u8 master_val)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	int block;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	for (block = 1; block < 8; block++)
2318c2ecf20Sopenharmony_ci		if (master_val & BIT(block))
2328c2ecf20Sopenharmony_ci			pm8821_irq_block_handler(chip, master, block);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void pm8821_irq_handler(struct irq_desc *desc)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
2388c2ecf20Sopenharmony_ci	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
2398c2ecf20Sopenharmony_ci	unsigned int master;
2408c2ecf20Sopenharmony_ci	int ret;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	chained_irq_enter(irq_chip, desc);
2438c2ecf20Sopenharmony_ci	ret = regmap_read(chip->regmap,
2448c2ecf20Sopenharmony_ci			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
2458c2ecf20Sopenharmony_ci	if (ret) {
2468c2ecf20Sopenharmony_ci		pr_err("Failed to read master 0 ret=%d\n", ret);
2478c2ecf20Sopenharmony_ci		goto done;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* bits 1 through 7 marks the first 7 blocks in master 0 */
2518c2ecf20Sopenharmony_ci	if (master & GENMASK(7, 1))
2528c2ecf20Sopenharmony_ci		pm8821_irq_master_handler(chip, 0, master);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* bit 0 marks if master 1 contains any bits */
2558c2ecf20Sopenharmony_ci	if (!(master & BIT(0)))
2568c2ecf20Sopenharmony_ci		goto done;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	ret = regmap_read(chip->regmap,
2598c2ecf20Sopenharmony_ci			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
2608c2ecf20Sopenharmony_ci	if (ret) {
2618c2ecf20Sopenharmony_ci		pr_err("Failed to read master 1 ret=%d\n", ret);
2628c2ecf20Sopenharmony_ci		goto done;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	pm8821_irq_master_handler(chip, 1, master);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cidone:
2688c2ecf20Sopenharmony_ci	chained_irq_exit(irq_chip, desc);
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic void pm8xxx_irq_mask_ack(struct irq_data *d)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
2748c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
2758c2ecf20Sopenharmony_ci	u8	block, config;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	block = pmirq / 8;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
2808c2ecf20Sopenharmony_ci	pm8xxx_config_irq(chip, block, config);
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic void pm8xxx_irq_unmask(struct irq_data *d)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
2868c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
2878c2ecf20Sopenharmony_ci	u8	block, config;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	block = pmirq / 8;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	config = chip->config[pmirq];
2928c2ecf20Sopenharmony_ci	pm8xxx_config_irq(chip, block, config);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
2988c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
2998c2ecf20Sopenharmony_ci	int irq_bit;
3008c2ecf20Sopenharmony_ci	u8 block, config;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	block = pmirq / 8;
3038c2ecf20Sopenharmony_ci	irq_bit  = pmirq % 8;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
3068c2ecf20Sopenharmony_ci							| PM_IRQF_MASK_ALL;
3078c2ecf20Sopenharmony_ci	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
3088c2ecf20Sopenharmony_ci		if (flow_type & IRQF_TRIGGER_RISING)
3098c2ecf20Sopenharmony_ci			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
3108c2ecf20Sopenharmony_ci		if (flow_type & IRQF_TRIGGER_FALLING)
3118c2ecf20Sopenharmony_ci			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
3128c2ecf20Sopenharmony_ci	} else {
3138c2ecf20Sopenharmony_ci		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		if (flow_type & IRQF_TRIGGER_HIGH)
3168c2ecf20Sopenharmony_ci			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
3178c2ecf20Sopenharmony_ci		else
3188c2ecf20Sopenharmony_ci			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	config = chip->config[pmirq] | PM_IRQF_CLR;
3228c2ecf20Sopenharmony_ci	return pm8xxx_config_irq(chip, block, config);
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
3268c2ecf20Sopenharmony_ci					enum irqchip_irq_state which,
3278c2ecf20Sopenharmony_ci					bool *state)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
3308c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
3318c2ecf20Sopenharmony_ci	unsigned int bits;
3328c2ecf20Sopenharmony_ci	int irq_bit;
3338c2ecf20Sopenharmony_ci	u8 block;
3348c2ecf20Sopenharmony_ci	int rc;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (which != IRQCHIP_STATE_LINE_LEVEL)
3378c2ecf20Sopenharmony_ci		return -EINVAL;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	block = pmirq / 8;
3408c2ecf20Sopenharmony_ci	irq_bit = pmirq % 8;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	spin_lock(&chip->pm_irq_lock);
3438c2ecf20Sopenharmony_ci	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
3448c2ecf20Sopenharmony_ci	if (rc) {
3458c2ecf20Sopenharmony_ci		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
3468c2ecf20Sopenharmony_ci		goto bail;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
3508c2ecf20Sopenharmony_ci	if (rc) {
3518c2ecf20Sopenharmony_ci		pr_err("Failed Reading Status rc=%d\n", rc);
3528c2ecf20Sopenharmony_ci		goto bail;
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	*state = !!(bits & BIT(irq_bit));
3568c2ecf20Sopenharmony_cibail:
3578c2ecf20Sopenharmony_ci	spin_unlock(&chip->pm_irq_lock);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	return rc;
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_cistatic struct irq_chip pm8xxx_irq_chip = {
3638c2ecf20Sopenharmony_ci	.name		= "pm8xxx",
3648c2ecf20Sopenharmony_ci	.irq_mask_ack	= pm8xxx_irq_mask_ack,
3658c2ecf20Sopenharmony_ci	.irq_unmask	= pm8xxx_irq_unmask,
3668c2ecf20Sopenharmony_ci	.irq_set_type	= pm8xxx_irq_set_type,
3678c2ecf20Sopenharmony_ci	.irq_get_irqchip_state = pm8xxx_irq_get_irqchip_state,
3688c2ecf20Sopenharmony_ci	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
3698c2ecf20Sopenharmony_ci};
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic void pm8xxx_irq_domain_map(struct pm_irq_chip *chip,
3728c2ecf20Sopenharmony_ci				  struct irq_domain *domain, unsigned int irq,
3738c2ecf20Sopenharmony_ci				  irq_hw_number_t hwirq, unsigned int type)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip,
3768c2ecf20Sopenharmony_ci			    chip, handle_level_irq, NULL, NULL);
3778c2ecf20Sopenharmony_ci	irq_set_noprobe(irq);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
3818c2ecf20Sopenharmony_ci				   unsigned int nr_irqs, void *data)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = domain->host_data;
3848c2ecf20Sopenharmony_ci	struct irq_fwspec *fwspec = data;
3858c2ecf20Sopenharmony_ci	irq_hw_number_t hwirq;
3868c2ecf20Sopenharmony_ci	unsigned int type;
3878c2ecf20Sopenharmony_ci	int ret, i;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type);
3908c2ecf20Sopenharmony_ci	if (ret)
3918c2ecf20Sopenharmony_ci		return ret;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	for (i = 0; i < nr_irqs; i++)
3948c2ecf20Sopenharmony_ci		pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	return 0;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_cistatic const struct irq_domain_ops pm8xxx_irq_domain_ops = {
4008c2ecf20Sopenharmony_ci	.alloc = pm8xxx_irq_domain_alloc,
4018c2ecf20Sopenharmony_ci	.free = irq_domain_free_irqs_common,
4028c2ecf20Sopenharmony_ci	.translate = irq_domain_translate_twocell,
4038c2ecf20Sopenharmony_ci};
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic void pm8821_irq_mask_ack(struct irq_data *d)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
4088c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
4098c2ecf20Sopenharmony_ci	u8 block, master;
4108c2ecf20Sopenharmony_ci	int irq_bit, rc;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	block = pmirq / 8;
4138c2ecf20Sopenharmony_ci	master = block / PM8821_BLOCKS_PER_MASTER;
4148c2ecf20Sopenharmony_ci	irq_bit = pmirq % 8;
4158c2ecf20Sopenharmony_ci	block %= PM8821_BLOCKS_PER_MASTER;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	rc = regmap_update_bits(chip->regmap,
4188c2ecf20Sopenharmony_ci				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
4198c2ecf20Sopenharmony_ci				BIT(irq_bit), BIT(irq_bit));
4208c2ecf20Sopenharmony_ci	if (rc) {
4218c2ecf20Sopenharmony_ci		pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
4228c2ecf20Sopenharmony_ci		return;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	rc = regmap_update_bits(chip->regmap,
4268c2ecf20Sopenharmony_ci				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
4278c2ecf20Sopenharmony_ci				BIT(irq_bit), BIT(irq_bit));
4288c2ecf20Sopenharmony_ci	if (rc)
4298c2ecf20Sopenharmony_ci		pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic void pm8821_irq_unmask(struct irq_data *d)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
4358c2ecf20Sopenharmony_ci	unsigned int pmirq = irqd_to_hwirq(d);
4368c2ecf20Sopenharmony_ci	int irq_bit, rc;
4378c2ecf20Sopenharmony_ci	u8 block, master;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	block = pmirq / 8;
4408c2ecf20Sopenharmony_ci	master = block / PM8821_BLOCKS_PER_MASTER;
4418c2ecf20Sopenharmony_ci	irq_bit = pmirq % 8;
4428c2ecf20Sopenharmony_ci	block %= PM8821_BLOCKS_PER_MASTER;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	rc = regmap_update_bits(chip->regmap,
4458c2ecf20Sopenharmony_ci				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
4468c2ecf20Sopenharmony_ci				BIT(irq_bit), ~BIT(irq_bit));
4478c2ecf20Sopenharmony_ci	if (rc)
4488c2ecf20Sopenharmony_ci		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic int pm8821_irq_get_irqchip_state(struct irq_data *d,
4538c2ecf20Sopenharmony_ci					enum irqchip_irq_state which,
4548c2ecf20Sopenharmony_ci					bool *state)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
4578c2ecf20Sopenharmony_ci	int rc, pmirq = irqd_to_hwirq(d);
4588c2ecf20Sopenharmony_ci	u8 block, irq_bit, master;
4598c2ecf20Sopenharmony_ci	unsigned int bits;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	block = pmirq / 8;
4628c2ecf20Sopenharmony_ci	master = block / PM8821_BLOCKS_PER_MASTER;
4638c2ecf20Sopenharmony_ci	irq_bit = pmirq % 8;
4648c2ecf20Sopenharmony_ci	block %= PM8821_BLOCKS_PER_MASTER;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	rc = regmap_read(chip->regmap,
4678c2ecf20Sopenharmony_ci		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
4688c2ecf20Sopenharmony_ci	if (rc) {
4698c2ecf20Sopenharmony_ci		pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
4708c2ecf20Sopenharmony_ci		return rc;
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	*state = !!(bits & BIT(irq_bit));
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	return rc;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic struct irq_chip pm8821_irq_chip = {
4798c2ecf20Sopenharmony_ci	.name		= "pm8821",
4808c2ecf20Sopenharmony_ci	.irq_mask_ack	= pm8821_irq_mask_ack,
4818c2ecf20Sopenharmony_ci	.irq_unmask	= pm8821_irq_unmask,
4828c2ecf20Sopenharmony_ci	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
4838c2ecf20Sopenharmony_ci	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
4848c2ecf20Sopenharmony_ci};
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic const struct regmap_config ssbi_regmap_config = {
4878c2ecf20Sopenharmony_ci	.reg_bits = 16,
4888c2ecf20Sopenharmony_ci	.val_bits = 8,
4898c2ecf20Sopenharmony_ci	.max_register = 0x3ff,
4908c2ecf20Sopenharmony_ci	.fast_io = true,
4918c2ecf20Sopenharmony_ci	.reg_read = ssbi_reg_read,
4928c2ecf20Sopenharmony_ci	.reg_write = ssbi_reg_write
4938c2ecf20Sopenharmony_ci};
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistatic const struct pm_irq_data pm8xxx_data = {
4968c2ecf20Sopenharmony_ci	.num_irqs = PM8XXX_NR_IRQS,
4978c2ecf20Sopenharmony_ci	.irq_chip = &pm8xxx_irq_chip,
4988c2ecf20Sopenharmony_ci	.irq_handler = pm8xxx_irq_handler,
4998c2ecf20Sopenharmony_ci};
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic const struct pm_irq_data pm8821_data = {
5028c2ecf20Sopenharmony_ci	.num_irqs = PM8821_NR_IRQS,
5038c2ecf20Sopenharmony_ci	.irq_chip = &pm8821_irq_chip,
5048c2ecf20Sopenharmony_ci	.irq_handler = pm8821_irq_handler,
5058c2ecf20Sopenharmony_ci};
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_cistatic const struct of_device_id pm8xxx_id_table[] = {
5088c2ecf20Sopenharmony_ci	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
5098c2ecf20Sopenharmony_ci	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
5108c2ecf20Sopenharmony_ci	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
5118c2ecf20Sopenharmony_ci	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
5128c2ecf20Sopenharmony_ci	{ }
5138c2ecf20Sopenharmony_ci};
5148c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pm8xxx_id_table);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic int pm8xxx_probe(struct platform_device *pdev)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	const struct pm_irq_data *data;
5198c2ecf20Sopenharmony_ci	struct regmap *regmap;
5208c2ecf20Sopenharmony_ci	int irq, rc;
5218c2ecf20Sopenharmony_ci	unsigned int val;
5228c2ecf20Sopenharmony_ci	u32 rev;
5238c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	data = of_device_get_match_data(&pdev->dev);
5268c2ecf20Sopenharmony_ci	if (!data) {
5278c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "No matching driver data found\n");
5288c2ecf20Sopenharmony_ci		return -EINVAL;
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
5328c2ecf20Sopenharmony_ci	if (irq < 0)
5338c2ecf20Sopenharmony_ci		return irq;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
5368c2ecf20Sopenharmony_ci				  &ssbi_regmap_config);
5378c2ecf20Sopenharmony_ci	if (IS_ERR(regmap))
5388c2ecf20Sopenharmony_ci		return PTR_ERR(regmap);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	/* Read PMIC chip revision */
5418c2ecf20Sopenharmony_ci	rc = regmap_read(regmap, REG_HWREV, &val);
5428c2ecf20Sopenharmony_ci	if (rc) {
5438c2ecf20Sopenharmony_ci		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
5448c2ecf20Sopenharmony_ci		return rc;
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci	pr_info("PMIC revision 1: %02X\n", val);
5478c2ecf20Sopenharmony_ci	rev = val;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* Read PMIC chip revision 2 */
5508c2ecf20Sopenharmony_ci	rc = regmap_read(regmap, REG_HWREV_2, &val);
5518c2ecf20Sopenharmony_ci	if (rc) {
5528c2ecf20Sopenharmony_ci		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
5538c2ecf20Sopenharmony_ci			REG_HWREV_2, rc);
5548c2ecf20Sopenharmony_ci		return rc;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci	pr_info("PMIC revision 2: %02X\n", val);
5578c2ecf20Sopenharmony_ci	rev |= val << BITS_PER_BYTE;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	chip = devm_kzalloc(&pdev->dev,
5608c2ecf20Sopenharmony_ci			    struct_size(chip, config, data->num_irqs),
5618c2ecf20Sopenharmony_ci			    GFP_KERNEL);
5628c2ecf20Sopenharmony_ci	if (!chip)
5638c2ecf20Sopenharmony_ci		return -ENOMEM;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, chip);
5668c2ecf20Sopenharmony_ci	chip->regmap = regmap;
5678c2ecf20Sopenharmony_ci	chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8);
5688c2ecf20Sopenharmony_ci	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
5698c2ecf20Sopenharmony_ci	chip->pm_irq_data = data;
5708c2ecf20Sopenharmony_ci	spin_lock_init(&chip->pm_irq_lock);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
5738c2ecf20Sopenharmony_ci						data->num_irqs,
5748c2ecf20Sopenharmony_ci						&pm8xxx_irq_domain_ops,
5758c2ecf20Sopenharmony_ci						chip);
5768c2ecf20Sopenharmony_ci	if (!chip->irqdomain)
5778c2ecf20Sopenharmony_ci		return -ENODEV;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
5808c2ecf20Sopenharmony_ci	irq_set_irq_wake(irq, 1);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
5838c2ecf20Sopenharmony_ci	if (rc) {
5848c2ecf20Sopenharmony_ci		irq_set_chained_handler_and_data(irq, NULL, NULL);
5858c2ecf20Sopenharmony_ci		irq_domain_remove(chip->irqdomain);
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return rc;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic int pm8xxx_remove_child(struct device *dev, void *unused)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	platform_device_unregister(to_platform_device(dev));
5948c2ecf20Sopenharmony_ci	return 0;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic int pm8xxx_remove(struct platform_device *pdev)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	int irq = platform_get_irq(pdev, 0);
6008c2ecf20Sopenharmony_ci	struct pm_irq_chip *chip = platform_get_drvdata(pdev);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
6038c2ecf20Sopenharmony_ci	irq_set_chained_handler_and_data(irq, NULL, NULL);
6048c2ecf20Sopenharmony_ci	irq_domain_remove(chip->irqdomain);
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	return 0;
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_cistatic struct platform_driver pm8xxx_driver = {
6108c2ecf20Sopenharmony_ci	.probe		= pm8xxx_probe,
6118c2ecf20Sopenharmony_ci	.remove		= pm8xxx_remove,
6128c2ecf20Sopenharmony_ci	.driver		= {
6138c2ecf20Sopenharmony_ci		.name	= "pm8xxx-core",
6148c2ecf20Sopenharmony_ci		.of_match_table = pm8xxx_id_table,
6158c2ecf20Sopenharmony_ci	},
6168c2ecf20Sopenharmony_ci};
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_cistatic int __init pm8xxx_init(void)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	return platform_driver_register(&pm8xxx_driver);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_cisubsys_initcall(pm8xxx_init);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cistatic void __exit pm8xxx_exit(void)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	platform_driver_unregister(&pm8xxx_driver);
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_cimodule_exit(pm8xxx_exit);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
6318c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PMIC 8xxx core driver");
6328c2ecf20Sopenharmony_ciMODULE_VERSION("1.0");
6338c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:pm8xxx-core");
634