Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  4 */
  5
  6#define pr_fmt(fmt) "%s: " fmt, __func__
  7
  8#include <linux/kernel.h>
  9#include <linux/interrupt.h>
 10#include <linux/irqchip/chained_irq.h>
 11#include <linux/irq.h>
 12#include <linux/irqdomain.h>
 13#include <linux/module.h>
 14#include <linux/platform_device.h>
 15#include <linux/slab.h>
 16#include <linux/err.h>
 17#include <linux/ssbi.h>
 18#include <linux/regmap.h>
 19#include <linux/of_platform.h>
 20#include <linux/mfd/core.h>
 21
 22#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
 23
 24#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
 25#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
 26#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
 27#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
 28#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
 29#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
 30#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
 31#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
 32#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
 33
 34#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
 35#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
 36#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
 37#define	PM8821_SSBI_REG(m, b, offset) \
 38			((m == 0) ? \
 39			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
 40			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
 41#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
 42#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
 43#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
 44#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
 45
 46#define	PM8821_BLOCKS_PER_MASTER	7
 47
 48#define	PM_IRQF_LVL_SEL			0x01	/* level select */
 49#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
 50#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
 51#define	PM_IRQF_CLR			0x08	/* clear interrupt */
 52#define	PM_IRQF_BITS_MASK		0x70
 53#define	PM_IRQF_BITS_SHIFT		4
 54#define	PM_IRQF_WRITE			0x80
 55
 56#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
 57					PM_IRQF_MASK_RE)
 58
 59#define REG_HWREV		0x002  /* PMIC4 revision */
 60#define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 61
 62#define PM8XXX_NR_IRQS		256
 63#define PM8821_NR_IRQS		112
 64
 65struct pm_irq_data {
 66	int num_irqs;
 67	struct irq_chip *irq_chip;
 68	irq_handler_t irq_handler;
 69};
 70
 71struct pm_irq_chip {
 72	struct regmap		*regmap;
 73	spinlock_t		pm_irq_lock;
 74	struct irq_domain	*irqdomain;
 75	unsigned int		num_blocks;
 76	unsigned int		num_masters;
 77	const struct pm_irq_data *pm_irq_data;
 78	/* MUST BE AT THE END OF THIS STRUCT */
 79	u8			config[];
 80};
 81
 82static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
 83				 unsigned int *ip)
 84{
 85	int	rc;
 86
 87	spin_lock(&chip->pm_irq_lock);
 88	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
 89	if (rc) {
 90		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
 91		goto bail;
 92	}
 93
 94	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
 95	if (rc)
 96		pr_err("Failed Reading Status rc=%d\n", rc);
 97bail:
 98	spin_unlock(&chip->pm_irq_lock);
 99	return rc;
100}
101
102static int
103pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
104{
105	int	rc;
106
107	spin_lock(&chip->pm_irq_lock);
108	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
109	if (rc) {
110		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
111		goto bail;
112	}
113
114	cp |= PM_IRQF_WRITE;
115	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
116	if (rc)
117		pr_err("Failed Configuring IRQ rc=%d\n", rc);
118bail:
119	spin_unlock(&chip->pm_irq_lock);
120	return rc;
121}
122
123static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
124{
125	int pmirq, i, ret = 0;
126	unsigned int bits;
127
128	ret = pm8xxx_read_block_irq(chip, block, &bits);
129	if (ret) {
130		pr_err("Failed reading %d block ret=%d", block, ret);
131		return ret;
132	}
133	if (!bits) {
134		pr_err("block bit set in master but no irqs: %d", block);
135		return 0;
136	}
137
138	/* Check IRQ bits */
139	for (i = 0; i < 8; i++) {
140		if (bits & (1 << i)) {
141			pmirq = block * 8 + i;
142			generic_handle_domain_irq(chip->irqdomain, pmirq);
143		}
144	}
145	return 0;
146}
147
148static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
149{
150	unsigned int blockbits;
151	int block_number, i, ret = 0;
152
153	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
154			  &blockbits);
155	if (ret) {
156		pr_err("Failed to read master %d ret=%d\n", master, ret);
157		return ret;
158	}
159	if (!blockbits) {
160		pr_err("master bit set in root but no blocks: %d", master);
161		return 0;
162	}
163
164	for (i = 0; i < 8; i++)
165		if (blockbits & (1 << i)) {
166			block_number = master * 8 + i;	/* block # */
167			ret |= pm8xxx_irq_block_handler(chip, block_number);
168		}
169	return ret;
170}
171
172static irqreturn_t pm8xxx_irq_handler(int irq, void *data)
173{
174	struct pm_irq_chip *chip = data;
175	unsigned int root;
176	int	i, ret, masters = 0;
177
178	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
179	if (ret) {
180		pr_err("Can't read root status ret=%d\n", ret);
181		return IRQ_NONE;
182	}
183
184	/* on pm8xxx series masters start from bit 1 of the root */
185	masters = root >> 1;
186
187	/* Read allowed masters for blocks. */
188	for (i = 0; i < chip->num_masters; i++)
189		if (masters & (1 << i))
190			pm8xxx_irq_master_handler(chip, i);
191
192	return IRQ_HANDLED;
193}
194
195static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
196				     int master, int block)
197{
198	int pmirq, i, ret;
199	unsigned int bits;
200
201	ret = regmap_read(chip->regmap,
202			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
203	if (ret) {
204		pr_err("Reading block %d failed ret=%d", block, ret);
205		return;
206	}
207
208	/* Convert block offset to global block number */
209	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
210
211	/* Check IRQ bits */
212	for (i = 0; i < 8; i++) {
213		if (bits & BIT(i)) {
214			pmirq = block * 8 + i;
215			generic_handle_domain_irq(chip->irqdomain, pmirq);
216		}
217	}
218}
219
220static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
221					     int master, u8 master_val)
222{
223	int block;
224
225	for (block = 1; block < 8; block++)
226		if (master_val & BIT(block))
227			pm8821_irq_block_handler(chip, master, block);
228}
229
230static irqreturn_t pm8821_irq_handler(int irq, void *data)
231{
232	struct pm_irq_chip *chip = data;
233	unsigned int master;
234	int ret;
235
236	ret = regmap_read(chip->regmap,
237			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
238	if (ret) {
239		pr_err("Failed to read master 0 ret=%d\n", ret);
240		return IRQ_NONE;
241	}
242
243	/* bits 1 through 7 marks the first 7 blocks in master 0 */
244	if (master & GENMASK(7, 1))
245		pm8821_irq_master_handler(chip, 0, master);
246
247	/* bit 0 marks if master 1 contains any bits */
248	if (!(master & BIT(0)))
249		return IRQ_NONE;
250
251	ret = regmap_read(chip->regmap,
252			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
253	if (ret) {
254		pr_err("Failed to read master 1 ret=%d\n", ret);
255		return IRQ_NONE;
256	}
257
258	pm8821_irq_master_handler(chip, 1, master);
259
260	return IRQ_HANDLED;
261}
262
263static void pm8xxx_irq_mask_ack(struct irq_data *d)
264{
265	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
266	unsigned int pmirq = irqd_to_hwirq(d);
267	u8	block, config;
268
269	block = pmirq / 8;
270
271	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
272	pm8xxx_config_irq(chip, block, config);
273}
274
275static void pm8xxx_irq_unmask(struct irq_data *d)
276{
277	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
278	unsigned int pmirq = irqd_to_hwirq(d);
279	u8	block, config;
280
281	block = pmirq / 8;
282
283	config = chip->config[pmirq];
284	pm8xxx_config_irq(chip, block, config);
285}
286
287static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
288{
289	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
290	unsigned int pmirq = irqd_to_hwirq(d);
291	int irq_bit;
292	u8 block, config;
293
294	block = pmirq / 8;
295	irq_bit  = pmirq % 8;
296
297	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
298							| PM_IRQF_MASK_ALL;
299	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
300		if (flow_type & IRQF_TRIGGER_RISING)
301			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
302		if (flow_type & IRQF_TRIGGER_FALLING)
303			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
304	} else {
305		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
306
307		if (flow_type & IRQF_TRIGGER_HIGH)
308			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
309		else
310			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
311	}
312
313	config = chip->config[pmirq] | PM_IRQF_CLR;
314	return pm8xxx_config_irq(chip, block, config);
315}
316
317static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
318					enum irqchip_irq_state which,
319					bool *state)
320{
321	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
322	unsigned int pmirq = irqd_to_hwirq(d);
323	unsigned int bits;
324	int irq_bit;
325	u8 block;
326	int rc;
327
328	if (which != IRQCHIP_STATE_LINE_LEVEL)
329		return -EINVAL;
330
331	block = pmirq / 8;
332	irq_bit = pmirq % 8;
333
334	spin_lock(&chip->pm_irq_lock);
335	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
336	if (rc) {
337		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
338		goto bail;
339	}
340
341	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
342	if (rc) {
343		pr_err("Failed Reading Status rc=%d\n", rc);
344		goto bail;
345	}
346
347	*state = !!(bits & BIT(irq_bit));
348bail:
349	spin_unlock(&chip->pm_irq_lock);
350
351	return rc;
352}
353
354static struct irq_chip pm8xxx_irq_chip = {
355	.name		= "pm8xxx",
356	.irq_mask_ack	= pm8xxx_irq_mask_ack,
357	.irq_unmask	= pm8xxx_irq_unmask,
358	.irq_set_type	= pm8xxx_irq_set_type,
359	.irq_get_irqchip_state = pm8xxx_irq_get_irqchip_state,
360	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
361};
362
363static void pm8xxx_irq_domain_map(struct pm_irq_chip *chip,
364				  struct irq_domain *domain, unsigned int irq,
365				  irq_hw_number_t hwirq, unsigned int type)
366{
367	irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip,
368			    chip, handle_level_irq, NULL, NULL);
369	irq_set_noprobe(irq);
370}
371
372static int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
373				   unsigned int nr_irqs, void *data)
374{
375	struct pm_irq_chip *chip = domain->host_data;
376	struct irq_fwspec *fwspec = data;
377	irq_hw_number_t hwirq;
378	unsigned int type;
379	int ret, i;
380
381	ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type);
382	if (ret)
383		return ret;
384
385	for (i = 0; i < nr_irqs; i++)
386		pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type);
387
388	return 0;
389}
390
391static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
392	.alloc = pm8xxx_irq_domain_alloc,
393	.free = irq_domain_free_irqs_common,
394	.translate = irq_domain_translate_twocell,
395};
396
397static void pm8821_irq_mask_ack(struct irq_data *d)
398{
399	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
400	unsigned int pmirq = irqd_to_hwirq(d);
401	u8 block, master;
402	int irq_bit, rc;
403
404	block = pmirq / 8;
405	master = block / PM8821_BLOCKS_PER_MASTER;
406	irq_bit = pmirq % 8;
407	block %= PM8821_BLOCKS_PER_MASTER;
408
409	rc = regmap_update_bits(chip->regmap,
410				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
411				BIT(irq_bit), BIT(irq_bit));
412	if (rc) {
413		pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
414		return;
415	}
416
417	rc = regmap_update_bits(chip->regmap,
418				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
419				BIT(irq_bit), BIT(irq_bit));
420	if (rc)
421		pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
422}
423
424static void pm8821_irq_unmask(struct irq_data *d)
425{
426	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
427	unsigned int pmirq = irqd_to_hwirq(d);
428	int irq_bit, rc;
429	u8 block, master;
430
431	block = pmirq / 8;
432	master = block / PM8821_BLOCKS_PER_MASTER;
433	irq_bit = pmirq % 8;
434	block %= PM8821_BLOCKS_PER_MASTER;
435
436	rc = regmap_update_bits(chip->regmap,
437				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
438				BIT(irq_bit), ~BIT(irq_bit));
439	if (rc)
440		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
441
442}
443
444static int pm8821_irq_get_irqchip_state(struct irq_data *d,
445					enum irqchip_irq_state which,
446					bool *state)
447{
448	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
449	int rc, pmirq = irqd_to_hwirq(d);
450	u8 block, irq_bit, master;
451	unsigned int bits;
452
453	block = pmirq / 8;
454	master = block / PM8821_BLOCKS_PER_MASTER;
455	irq_bit = pmirq % 8;
456	block %= PM8821_BLOCKS_PER_MASTER;
457
458	rc = regmap_read(chip->regmap,
459		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
460	if (rc) {
461		pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
462		return rc;
463	}
464
465	*state = !!(bits & BIT(irq_bit));
466
467	return rc;
468}
469
470static struct irq_chip pm8821_irq_chip = {
471	.name		= "pm8821",
472	.irq_mask_ack	= pm8821_irq_mask_ack,
473	.irq_unmask	= pm8821_irq_unmask,
474	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
475	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
476};
477
478static const struct regmap_config ssbi_regmap_config = {
479	.reg_bits = 16,
480	.val_bits = 8,
481	.max_register = 0x3ff,
482	.fast_io = true,
483	.reg_read = ssbi_reg_read,
484	.reg_write = ssbi_reg_write
485};
486
487static const struct pm_irq_data pm8xxx_data = {
488	.num_irqs = PM8XXX_NR_IRQS,
489	.irq_chip = &pm8xxx_irq_chip,
490	.irq_handler = pm8xxx_irq_handler,
491};
492
493static const struct pm_irq_data pm8821_data = {
494	.num_irqs = PM8821_NR_IRQS,
495	.irq_chip = &pm8821_irq_chip,
496	.irq_handler = pm8821_irq_handler,
497};
498
499static const struct of_device_id pm8xxx_id_table[] = {
500	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
501	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
502	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
503	{ }
504};
505MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
506
507static int pm8xxx_probe(struct platform_device *pdev)
508{
509	const struct pm_irq_data *data;
510	struct regmap *regmap;
511	int irq, rc;
512	unsigned int val;
513	u32 rev;
514	struct pm_irq_chip *chip;
515
516	data = of_device_get_match_data(&pdev->dev);
517	if (!data) {
518		dev_err(&pdev->dev, "No matching driver data found\n");
519		return -EINVAL;
520	}
521
522	irq = platform_get_irq(pdev, 0);
523	if (irq < 0)
524		return irq;
525
526	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
527				  &ssbi_regmap_config);
528	if (IS_ERR(regmap))
529		return PTR_ERR(regmap);
530
531	/* Read PMIC chip revision */
532	rc = regmap_read(regmap, REG_HWREV, &val);
533	if (rc) {
534		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
535		return rc;
536	}
537	pr_info("PMIC revision 1: %02X\n", val);
538	rev = val;
539
540	/* Read PMIC chip revision 2 */
541	rc = regmap_read(regmap, REG_HWREV_2, &val);
542	if (rc) {
543		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
544			REG_HWREV_2, rc);
545		return rc;
546	}
547	pr_info("PMIC revision 2: %02X\n", val);
548	rev |= val << BITS_PER_BYTE;
549
550	chip = devm_kzalloc(&pdev->dev,
551			    struct_size(chip, config, data->num_irqs),
552			    GFP_KERNEL);
553	if (!chip)
554		return -ENOMEM;
555
556	platform_set_drvdata(pdev, chip);
557	chip->regmap = regmap;
558	chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8);
559	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
560	chip->pm_irq_data = data;
561	spin_lock_init(&chip->pm_irq_lock);
562
563	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
564						data->num_irqs,
565						&pm8xxx_irq_domain_ops,
566						chip);
567	if (!chip->irqdomain)
568		return -ENODEV;
569
570	rc = devm_request_irq(&pdev->dev, irq, data->irq_handler, 0, dev_name(&pdev->dev), chip);
571	if (rc)
572		return rc;
573
574	irq_set_irq_wake(irq, 1);
575
576	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
577	if (rc)
578		irq_domain_remove(chip->irqdomain);
579
580	return rc;
581}
582
583static int pm8xxx_remove_child(struct device *dev, void *unused)
584{
585	platform_device_unregister(to_platform_device(dev));
586	return 0;
587}
588
589static int pm8xxx_remove(struct platform_device *pdev)
590{
591	struct pm_irq_chip *chip = platform_get_drvdata(pdev);
592
593	device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
594	irq_domain_remove(chip->irqdomain);
595
596	return 0;
597}
598
599static struct platform_driver pm8xxx_driver = {
600	.probe		= pm8xxx_probe,
601	.remove		= pm8xxx_remove,
602	.driver		= {
603		.name	= "pm8xxx-core",
604		.of_match_table = pm8xxx_id_table,
605	},
606};
607
608static int __init pm8xxx_init(void)
609{
610	return platform_driver_register(&pm8xxx_driver);
611}
612subsys_initcall(pm8xxx_init);
613
614static void __exit pm8xxx_exit(void)
615{
616	platform_driver_unregister(&pm8xxx_driver);
617}
618module_exit(pm8xxx_exit);
619
620MODULE_LICENSE("GPL v2");
621MODULE_DESCRIPTION("PMIC 8xxx core driver");
622MODULE_VERSION("1.0");
623MODULE_ALIAS("platform:pm8xxx-core");