2 * intel_bxtwc_tmu.c - Intel BXT Whiskey Cove PMIC TMU driver
4 * Copyright (C) 2016 Intel Corporation. All rights reserved.
6 * This driver adds TMU (Time Management Unit) support for Intel BXT platform.
7 * It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License version
12 * 2 as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
21 #include <linux/module.h>
22 #include <linux/mod_devicetable.h>
23 #include <linux/interrupt.h>
24 #include <linux/platform_device.h>
25 #include <linux/mfd/intel_soc_pmic.h>
27 #define BXTWC_TMUIRQ 0x4fb6
28 #define BXTWC_MIRQLVL1 0x4e0e
29 #define BXTWC_MTMUIRQ_REG 0x4fb7
30 #define BXTWC_MIRQLVL1_MTMU BIT(1)
31 #define BXTWC_TMU_WK_ALRM BIT(1)
32 #define BXTWC_TMU_SYS_ALRM BIT(2)
33 #define BXTWC_TMU_ALRM_MASK (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
34 #define BXTWC_TMU_ALRM_IRQ (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
39 struct regmap
*regmap
;
42 static irqreturn_t
bxt_wcove_tmu_irq_handler(int irq
, void *data
)
44 struct wcove_tmu
*wctmu
= data
;
47 /* Read TMU interrupt reg */
48 regmap_read(wctmu
->regmap
, BXTWC_TMUIRQ
, &tmu_irq
);
49 if (tmu_irq
& BXTWC_TMU_ALRM_IRQ
) {
51 regmap_write(wctmu
->regmap
, BXTWC_TMUIRQ
, tmu_irq
);
57 static int bxt_wcove_tmu_probe(struct platform_device
*pdev
)
59 struct intel_soc_pmic
*pmic
= dev_get_drvdata(pdev
->dev
.parent
);
60 struct regmap_irq_chip_data
*regmap_irq_chip
;
61 struct wcove_tmu
*wctmu
;
64 wctmu
= devm_kzalloc(&pdev
->dev
, sizeof(*wctmu
), GFP_KERNEL
);
68 wctmu
->dev
= &pdev
->dev
;
69 wctmu
->regmap
= pmic
->regmap
;
71 irq
= platform_get_irq(pdev
, 0);
74 dev_err(&pdev
->dev
, "invalid irq %d\n", irq
);
78 regmap_irq_chip
= pmic
->irq_chip_data_tmu
;
79 virq
= regmap_irq_get_virq(regmap_irq_chip
, irq
);
82 "failed to get virtual interrupt=%d\n", irq
);
86 ret
= devm_request_threaded_irq(&pdev
->dev
, virq
,
87 NULL
, bxt_wcove_tmu_irq_handler
,
88 IRQF_ONESHOT
, "bxt_wcove_tmu", wctmu
);
90 dev_err(&pdev
->dev
, "request irq failed: %d,virq: %d\n",
96 /* Unmask TMU second level Wake & System alarm */
97 regmap_update_bits(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
,
98 BXTWC_TMU_ALRM_MASK
, 0);
100 platform_set_drvdata(pdev
, wctmu
);
104 static int bxt_wcove_tmu_remove(struct platform_device
*pdev
)
106 struct wcove_tmu
*wctmu
= platform_get_drvdata(pdev
);
109 /* Mask TMU interrupts */
110 regmap_read(wctmu
->regmap
, BXTWC_MIRQLVL1
, &val
);
111 regmap_write(wctmu
->regmap
, BXTWC_MIRQLVL1
,
112 val
| BXTWC_MIRQLVL1_MTMU
);
113 regmap_read(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
, &val
);
114 regmap_write(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
,
115 val
| BXTWC_TMU_ALRM_MASK
);
119 #ifdef CONFIG_PM_SLEEP
120 static int bxtwc_tmu_suspend(struct device
*dev
)
122 struct wcove_tmu
*wctmu
= dev_get_drvdata(dev
);
124 enable_irq_wake(wctmu
->irq
);
128 static int bxtwc_tmu_resume(struct device
*dev
)
130 struct wcove_tmu
*wctmu
= dev_get_drvdata(dev
);
132 disable_irq_wake(wctmu
->irq
);
137 static SIMPLE_DEV_PM_OPS(bxtwc_tmu_pm_ops
, bxtwc_tmu_suspend
, bxtwc_tmu_resume
);
139 static const struct platform_device_id bxt_wcove_tmu_id_table
[] = {
140 { .name
= "bxt_wcove_tmu" },
143 MODULE_DEVICE_TABLE(platform
, bxt_wcove_tmu_id_table
);
145 static struct platform_driver bxt_wcove_tmu_driver
= {
146 .probe
= bxt_wcove_tmu_probe
,
147 .remove
= bxt_wcove_tmu_remove
,
149 .name
= "bxt_wcove_tmu",
150 .pm
= &bxtwc_tmu_pm_ops
,
152 .id_table
= bxt_wcove_tmu_id_table
,
155 module_platform_driver(bxt_wcove_tmu_driver
);
157 MODULE_LICENSE("GPL v2");
158 MODULE_AUTHOR("Nilesh Bacchewar <nilesh.bacchewar@intel.com>");
159 MODULE_DESCRIPTION("BXT Whiskey Cove TMU Driver");