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/interrupt.h>
23 #include <linux/platform_device.h>
24 #include <linux/mfd/intel_soc_pmic.h>
26 #define BXTWC_TMUIRQ 0x4fb6
27 #define BXTWC_MIRQLVL1 0x4e0e
28 #define BXTWC_MTMUIRQ_REG 0x4fb7
29 #define BXTWC_MIRQLVL1_MTMU BIT(1)
30 #define BXTWC_TMU_WK_ALRM BIT(1)
31 #define BXTWC_TMU_SYS_ALRM BIT(2)
32 #define BXTWC_TMU_ALRM_MASK (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
33 #define BXTWC_TMU_ALRM_IRQ (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
38 struct regmap
*regmap
;
41 static irqreturn_t
bxt_wcove_tmu_irq_handler(int irq
, void *data
)
43 struct wcove_tmu
*wctmu
= data
;
46 /* Read TMU interrupt reg */
47 regmap_read(wctmu
->regmap
, BXTWC_TMUIRQ
, &tmu_irq
);
48 if (tmu_irq
& BXTWC_TMU_ALRM_IRQ
) {
50 regmap_write(wctmu
->regmap
, BXTWC_TMUIRQ
, tmu_irq
);
56 static int bxt_wcove_tmu_probe(struct platform_device
*pdev
)
58 struct intel_soc_pmic
*pmic
= dev_get_drvdata(pdev
->dev
.parent
);
59 struct regmap_irq_chip_data
*regmap_irq_chip
;
60 struct wcove_tmu
*wctmu
;
63 wctmu
= devm_kzalloc(&pdev
->dev
, sizeof(*wctmu
), GFP_KERNEL
);
67 wctmu
->dev
= &pdev
->dev
;
68 wctmu
->regmap
= pmic
->regmap
;
70 irq
= platform_get_irq(pdev
, 0);
73 dev_err(&pdev
->dev
, "invalid irq %d\n", irq
);
77 regmap_irq_chip
= pmic
->irq_chip_data_tmu
;
78 virq
= regmap_irq_get_virq(regmap_irq_chip
, irq
);
81 "failed to get virtual interrupt=%d\n", irq
);
85 ret
= devm_request_threaded_irq(&pdev
->dev
, virq
,
86 NULL
, bxt_wcove_tmu_irq_handler
,
87 IRQF_ONESHOT
, "bxt_wcove_tmu", wctmu
);
89 dev_err(&pdev
->dev
, "request irq failed: %d,virq: %d\n",
95 /* Enable TMU interrupts */
96 regmap_update_bits(wctmu
->regmap
, BXTWC_MIRQLVL1
,
97 BXTWC_MIRQLVL1_MTMU
, 0);
99 /* Unmask TMU second level Wake & System alarm */
100 regmap_update_bits(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
,
101 BXTWC_TMU_ALRM_MASK
, 0);
103 platform_set_drvdata(pdev
, wctmu
);
107 static int bxt_wcove_tmu_remove(struct platform_device
*pdev
)
109 struct wcove_tmu
*wctmu
= platform_get_drvdata(pdev
);
112 /* Mask TMU interrupts */
113 regmap_read(wctmu
->regmap
, BXTWC_MIRQLVL1
, &val
);
114 regmap_write(wctmu
->regmap
, BXTWC_MIRQLVL1
,
115 val
| BXTWC_MIRQLVL1_MTMU
);
116 regmap_read(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
, &val
);
117 regmap_write(wctmu
->regmap
, BXTWC_MTMUIRQ_REG
,
118 val
| BXTWC_TMU_ALRM_MASK
);
122 #ifdef CONFIG_PM_SLEEP
123 static int bxtwc_tmu_suspend(struct device
*dev
)
125 struct wcove_tmu
*wctmu
= dev_get_drvdata(dev
);
127 enable_irq_wake(wctmu
->irq
);
131 static int bxtwc_tmu_resume(struct device
*dev
)
133 struct wcove_tmu
*wctmu
= dev_get_drvdata(dev
);
135 disable_irq_wake(wctmu
->irq
);
140 static SIMPLE_DEV_PM_OPS(bxtwc_tmu_pm_ops
, bxtwc_tmu_suspend
, bxtwc_tmu_resume
);
142 static const struct platform_device_id bxt_wcove_tmu_id_table
[] = {
143 { .name
= "bxt_wcove_tmu" },
146 MODULE_DEVICE_TABLE(platform
, bxt_wcove_tmu_id_table
);
148 static struct platform_driver bxt_wcove_tmu_driver
= {
149 .probe
= bxt_wcove_tmu_probe
,
150 .remove
= bxt_wcove_tmu_remove
,
152 .name
= "bxt_wcove_tmu",
153 .pm
= &bxtwc_tmu_pm_ops
,
155 .id_table
= bxt_wcove_tmu_id_table
,
158 module_platform_driver(bxt_wcove_tmu_driver
);
160 MODULE_LICENSE("GPL v2");
161 MODULE_AUTHOR("Nilesh Bacchewar <nilesh.bacchewar@intel.com>");
162 MODULE_DESCRIPTION("BXT Whiskey Cove TMU Driver");