Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Device driver for irqs in HISI PMIC IC
  4 *
  5 * Copyright (c) 2013 Linaro Ltd.
  6 * Copyright (c) 2011 Hisilicon.
  7 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd.
  8 */
  9
 10#include <linux/bitops.h>
 11#include <linux/interrupt.h>
 12#include <linux/irq.h>
 13#include <linux/module.h>
 14#include <linux/platform_device.h>
 15#include <linux/slab.h>
 16#include <linux/irqdomain.h>
 17#include <linux/regmap.h>
 18
 19struct hi6421v600_irq {
 20	struct device		*dev;
 21	struct irq_domain	*domain;
 22	int			irq;
 23	unsigned int		*irqs;
 24	struct regmap		*regmap;
 25
 26	/* Protect IRQ mask changes */
 27	spinlock_t		lock;
 28};
 29
 30enum hi6421v600_irq_list {
 31	OTMP = 0,
 32	VBUS_CONNECT,
 33	VBUS_DISCONNECT,
 34	ALARMON_R,
 35	HOLD_6S,
 36	HOLD_1S,
 37	POWERKEY_UP,
 38	POWERKEY_DOWN,
 39	OCP_SCP_R,
 40	COUL_R,
 41	SIM0_HPD_R,
 42	SIM0_HPD_F,
 43	SIM1_HPD_R,
 44	SIM1_HPD_F,
 45
 46	PMIC_IRQ_LIST_MAX
 47};
 48
 49#define HISI_IRQ_BANK_SIZE		2
 50
 51/*
 52 * IRQ number for the power key button and mask for both UP and DOWN IRQs
 53 */
 54#define HISI_POWERKEY_IRQ_NUM		0
 55#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
 56
 57/*
 58 * Registers for IRQ address and IRQ mask bits
 59 *
 60 * Please notice that we need to regmap a larger region, as other
 61 * registers are used by the irqs.
 62 * See drivers/irq/hi6421-irq.c.
 63 */
 64#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
 65#define SOC_PMIC_IRQ0_ADDR		0x0212
 66
 67/*
 68 * The IRQs are mapped as:
 69 *
 70 *	======================  =============   ============	=====
 71 *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
 72 *	======================  =============   ============	=====
 73 *	OTMP			0x0202		0x212		bit 0
 74 *	VBUS_CONNECT		0x0202		0x212		bit 1
 75 *	VBUS_DISCONNECT		0x0202		0x212		bit 2
 76 *	ALARMON_R		0x0202		0x212		bit 3
 77 *	HOLD_6S			0x0202		0x212		bit 4
 78 *	HOLD_1S			0x0202		0x212		bit 5
 79 *	POWERKEY_UP		0x0202		0x212		bit 6
 80 *	POWERKEY_DOWN		0x0202		0x212		bit 7
 81 *
 82 *	OCP_SCP_R		0x0203		0x213		bit 0
 83 *	COUL_R			0x0203		0x213		bit 1
 84 *	SIM0_HPD_R		0x0203		0x213		bit 2
 85 *	SIM0_HPD_F		0x0203		0x213		bit 3
 86 *	SIM1_HPD_R		0x0203		0x213		bit 4
 87 *	SIM1_HPD_F		0x0203		0x213		bit 5
 88 *	======================  =============   ============	=====
 89 *
 90 * Each mask register contains 8 bits. The ancillary macros below
 91 * convert a number from 0 to 14 into a register address and a bit mask
 92 */
 93#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
 94					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
 95#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
 96#define HISI_8BITS_MASK			0xff
 97
 98static irqreturn_t hi6421v600_irq_handler(int irq, void *__priv)
 99{
100	struct hi6421v600_irq *priv = __priv;
101	unsigned long pending;
102	unsigned int in;
103	int i, offset;
104
105	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
106		regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
107
108		/* Mark pending IRQs as handled */
109		regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, in);
110
111		pending = in & HISI_8BITS_MASK;
112
113		if (i == HISI_POWERKEY_IRQ_NUM &&
114		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
115			/*
116			 * If both powerkey down and up IRQs are received,
117			 * handle them at the right order
118			 */
119			generic_handle_irq_safe(priv->irqs[POWERKEY_DOWN]);
120			generic_handle_irq_safe(priv->irqs[POWERKEY_UP]);
121			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
122		}
123
124		if (!pending)
125			continue;
126
127		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
128			generic_handle_irq_safe(priv->irqs[offset + i * BITS_PER_BYTE]);
129		}
130	}
131
132	return IRQ_HANDLED;
133}
134
135static void hi6421v600_irq_mask(struct irq_data *d)
136{
137	struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
138	unsigned long flags;
139	unsigned int data;
140	u32 offset;
141
142	offset = HISI_IRQ_MASK_REG(d);
143
144	spin_lock_irqsave(&priv->lock, flags);
145
146	regmap_read(priv->regmap, offset, &data);
147	data |= HISI_IRQ_MASK_BIT(d);
148	regmap_write(priv->regmap, offset, data);
149
150	spin_unlock_irqrestore(&priv->lock, flags);
151}
152
153static void hi6421v600_irq_unmask(struct irq_data *d)
154{
155	struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
156	u32 data, offset;
157	unsigned long flags;
158
159	offset = HISI_IRQ_MASK_REG(d);
160
161	spin_lock_irqsave(&priv->lock, flags);
162
163	regmap_read(priv->regmap, offset, &data);
164	data &= ~HISI_IRQ_MASK_BIT(d);
165	regmap_write(priv->regmap, offset, data);
166
167	spin_unlock_irqrestore(&priv->lock, flags);
168}
169
170static struct irq_chip hi6421v600_pmu_irqchip = {
171	.name		= "hi6421v600-irq",
172	.irq_mask	= hi6421v600_irq_mask,
173	.irq_unmask	= hi6421v600_irq_unmask,
174	.irq_disable	= hi6421v600_irq_mask,
175	.irq_enable	= hi6421v600_irq_unmask,
176};
177
178static int hi6421v600_irq_map(struct irq_domain *d, unsigned int virq,
179			      irq_hw_number_t hw)
180{
181	struct hi6421v600_irq *priv = d->host_data;
182
183	irq_set_chip_and_handler_name(virq, &hi6421v600_pmu_irqchip,
184				      handle_simple_irq, "hi6421v600");
185	irq_set_chip_data(virq, priv);
186	irq_set_irq_type(virq, IRQ_TYPE_NONE);
187
188	return 0;
189}
190
191static const struct irq_domain_ops hi6421v600_domain_ops = {
192	.map	= hi6421v600_irq_map,
193	.xlate	= irq_domain_xlate_twocell,
194};
195
196static void hi6421v600_irq_init(struct hi6421v600_irq *priv)
197{
198	int i;
199	unsigned int pending;
200
201	/* Mask all IRQs */
202	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
203		regmap_write(priv->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
204			     HISI_8BITS_MASK);
205
206	/* Mark all IRQs as handled */
207	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
208		regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
209		regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i,
210			     HISI_8BITS_MASK);
211	}
212}
213
214static int hi6421v600_irq_probe(struct platform_device *pdev)
215{
216	struct device *pmic_dev = pdev->dev.parent;
217	struct device_node *np = pmic_dev->of_node;
218	struct platform_device *pmic_pdev;
219	struct device *dev = &pdev->dev;
220	struct hi6421v600_irq *priv;
221	struct regmap *regmap;
222	unsigned int virq;
223	int i, ret;
224
225	/*
226	 * This driver is meant to be called by hi6421-spmi-core,
227	 * which should first set drvdata. If this doesn't happen, hit
228	 * a warn on and return.
229	 */
230	regmap = dev_get_drvdata(pmic_dev);
231	if (WARN_ON(!regmap))
232		return -ENODEV;
233
234	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
235	if (!priv)
236		return -ENOMEM;
237
238	priv->dev = dev;
239	priv->regmap = regmap;
240
241	spin_lock_init(&priv->lock);
242
243	pmic_pdev = container_of(pmic_dev, struct platform_device, dev);
244
245	priv->irq = platform_get_irq(pmic_pdev, 0);
246	if (priv->irq < 0)
247		return priv->irq;
248
249	platform_set_drvdata(pdev, priv);
250
251	hi6421v600_irq_init(priv);
252
253	priv->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
254	if (!priv->irqs)
255		return -ENOMEM;
256
257	priv->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
258					     &hi6421v600_domain_ops, priv);
259	if (!priv->domain) {
260		dev_err(dev, "Failed to create IRQ domain\n");
261		return -ENODEV;
262	}
263
264	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
265		virq = irq_create_mapping(priv->domain, i);
266		if (!virq) {
267			dev_err(dev, "Failed to map H/W IRQ\n");
268			return -ENODEV;
269		}
270		priv->irqs[i] = virq;
271	}
272
273	ret = devm_request_threaded_irq(dev,
274					priv->irq, hi6421v600_irq_handler,
275					NULL,
276					IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
277					"pmic", priv);
278	if (ret < 0) {
279		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
280			ret);
281		return ret;
282	}
283
284	return 0;
285}
286
287static const struct platform_device_id hi6421v600_irq_table[] = {
288	{ .name = "hi6421v600-irq" },
289	{},
290};
291MODULE_DEVICE_TABLE(platform, hi6421v600_irq_table);
292
293static struct platform_driver hi6421v600_irq_driver = {
294	.id_table = hi6421v600_irq_table,
295	.driver = {
296		.name = "hi6421v600-irq",
297	},
298	.probe	= hi6421v600_irq_probe,
299};
300module_platform_driver(hi6421v600_irq_driver);
301
302MODULE_DESCRIPTION("HiSilicon Hi6421v600 IRQ driver");
303MODULE_LICENSE("GPL v2");