brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · d0e2a3c Raw
147 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Intel BXT Whiskey Cove PMIC TMU driver4 *5 * Copyright (C) 2016 Intel Corporation. All rights reserved.6 *7 * This driver adds TMU (Time Management Unit) support for Intel BXT platform.8 * It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove9 * PMIC.10 */11 12#include <linux/module.h>13#include <linux/mod_devicetable.h>14#include <linux/interrupt.h>15#include <linux/platform_device.h>16#include <linux/mfd/intel_soc_pmic.h>17 18#define BXTWC_TMUIRQ		0x4fb619#define BXTWC_MIRQLVL1		0x4e0e20#define BXTWC_MTMUIRQ_REG	0x4fb721#define BXTWC_MIRQLVL1_MTMU	BIT(1)22#define BXTWC_TMU_WK_ALRM	BIT(1)23#define BXTWC_TMU_SYS_ALRM	BIT(2)24#define BXTWC_TMU_ALRM_MASK	(BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)25#define BXTWC_TMU_ALRM_IRQ	(BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)26 27struct wcove_tmu {28	int irq;29	struct device *dev;30	struct regmap *regmap;31};32 33static irqreturn_t bxt_wcove_tmu_irq_handler(int irq, void *data)34{35	struct wcove_tmu *wctmu = data;36	unsigned int tmu_irq;37 38	/* Read TMU interrupt reg */39	regmap_read(wctmu->regmap, BXTWC_TMUIRQ, &tmu_irq);40	if (tmu_irq & BXTWC_TMU_ALRM_IRQ) {41		/* clear TMU irq */42		regmap_write(wctmu->regmap, BXTWC_TMUIRQ, tmu_irq);43		return IRQ_HANDLED;44	}45	return IRQ_NONE;46}47 48static int bxt_wcove_tmu_probe(struct platform_device *pdev)49{50	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);51	struct regmap_irq_chip_data *regmap_irq_chip;52	struct wcove_tmu *wctmu;53	int ret, virq, irq;54 55	wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL);56	if (!wctmu)57		return -ENOMEM;58 59	wctmu->dev = &pdev->dev;60	wctmu->regmap = pmic->regmap;61 62	irq = platform_get_irq(pdev, 0);63	if (irq < 0)64		return irq;65 66	regmap_irq_chip = pmic->irq_chip_data_tmu;67	virq = regmap_irq_get_virq(regmap_irq_chip, irq);68	if (virq < 0) {69		dev_err(&pdev->dev,70			"failed to get virtual interrupt=%d\n", irq);71		return virq;72	}73 74	ret = devm_request_threaded_irq(&pdev->dev, virq,75					NULL, bxt_wcove_tmu_irq_handler,76					IRQF_ONESHOT, "bxt_wcove_tmu", wctmu);77	if (ret) {78		dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n",79							ret, virq);80		return ret;81	}82	wctmu->irq = virq;83 84	/* Unmask TMU second level Wake & System alarm */85	regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG,86				  BXTWC_TMU_ALRM_MASK, 0);87 88	platform_set_drvdata(pdev, wctmu);89	return 0;90}91 92static void bxt_wcove_tmu_remove(struct platform_device *pdev)93{94	struct wcove_tmu *wctmu = platform_get_drvdata(pdev);95	unsigned int val;96 97	/* Mask TMU interrupts */98	regmap_read(wctmu->regmap, BXTWC_MIRQLVL1, &val);99	regmap_write(wctmu->regmap, BXTWC_MIRQLVL1,100			val | BXTWC_MIRQLVL1_MTMU);101	regmap_read(wctmu->regmap, BXTWC_MTMUIRQ_REG, &val);102	regmap_write(wctmu->regmap, BXTWC_MTMUIRQ_REG,103			val | BXTWC_TMU_ALRM_MASK);104}105 106#ifdef CONFIG_PM_SLEEP107static int bxtwc_tmu_suspend(struct device *dev)108{109	struct wcove_tmu *wctmu = dev_get_drvdata(dev);110 111	enable_irq_wake(wctmu->irq);112	return 0;113}114 115static int bxtwc_tmu_resume(struct device *dev)116{117	struct wcove_tmu *wctmu = dev_get_drvdata(dev);118 119	disable_irq_wake(wctmu->irq);120	return 0;121}122#endif123 124static SIMPLE_DEV_PM_OPS(bxtwc_tmu_pm_ops, bxtwc_tmu_suspend, bxtwc_tmu_resume);125 126static const struct platform_device_id bxt_wcove_tmu_id_table[] = {127	{ .name = "bxt_wcove_tmu" },128	{},129};130MODULE_DEVICE_TABLE(platform, bxt_wcove_tmu_id_table);131 132static struct platform_driver bxt_wcove_tmu_driver = {133	.probe = bxt_wcove_tmu_probe,134	.remove_new = bxt_wcove_tmu_remove,135	.driver = {136		.name = "bxt_wcove_tmu",137		.pm     = &bxtwc_tmu_pm_ops,138	},139	.id_table = bxt_wcove_tmu_id_table,140};141 142module_platform_driver(bxt_wcove_tmu_driver);143 144MODULE_LICENSE("GPL v2");145MODULE_AUTHOR("Nilesh Bacchewar <nilesh.bacchewar@intel.com>");146MODULE_DESCRIPTION("BXT Whiskey Cove TMU Driver");147