mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.7 KiB
147 lines
3.7 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* |
|
* Intel BXT Whiskey Cove PMIC TMU driver |
|
* |
|
* Copyright (C) 2016 Intel Corporation. All rights reserved. |
|
* |
|
* This driver adds TMU (Time Management Unit) support for Intel BXT platform. |
|
* It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove |
|
* PMIC. |
|
*/ |
|
|
|
#include <linux/module.h> |
|
#include <linux/mod_devicetable.h> |
|
#include <linux/interrupt.h> |
|
#include <linux/platform_device.h> |
|
#include <linux/mfd/intel_soc_pmic.h> |
|
|
|
#define BXTWC_TMUIRQ 0x4fb6 |
|
#define BXTWC_MIRQLVL1 0x4e0e |
|
#define BXTWC_MTMUIRQ_REG 0x4fb7 |
|
#define BXTWC_MIRQLVL1_MTMU BIT(1) |
|
#define BXTWC_TMU_WK_ALRM BIT(1) |
|
#define BXTWC_TMU_SYS_ALRM BIT(2) |
|
#define BXTWC_TMU_ALRM_MASK (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM) |
|
#define BXTWC_TMU_ALRM_IRQ (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM) |
|
|
|
struct wcove_tmu { |
|
int irq; |
|
struct device *dev; |
|
struct regmap *regmap; |
|
}; |
|
|
|
static irqreturn_t bxt_wcove_tmu_irq_handler(int irq, void *data) |
|
{ |
|
struct wcove_tmu *wctmu = data; |
|
unsigned int tmu_irq; |
|
|
|
/* Read TMU interrupt reg */ |
|
regmap_read(wctmu->regmap, BXTWC_TMUIRQ, &tmu_irq); |
|
if (tmu_irq & BXTWC_TMU_ALRM_IRQ) { |
|
/* clear TMU irq */ |
|
regmap_write(wctmu->regmap, BXTWC_TMUIRQ, tmu_irq); |
|
return IRQ_HANDLED; |
|
} |
|
return IRQ_NONE; |
|
} |
|
|
|
static int bxt_wcove_tmu_probe(struct platform_device *pdev) |
|
{ |
|
struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); |
|
struct regmap_irq_chip_data *regmap_irq_chip; |
|
struct wcove_tmu *wctmu; |
|
int ret, virq, irq; |
|
|
|
wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL); |
|
if (!wctmu) |
|
return -ENOMEM; |
|
|
|
wctmu->dev = &pdev->dev; |
|
wctmu->regmap = pmic->regmap; |
|
|
|
irq = platform_get_irq(pdev, 0); |
|
if (irq < 0) |
|
return irq; |
|
|
|
regmap_irq_chip = pmic->irq_chip_data_tmu; |
|
virq = regmap_irq_get_virq(regmap_irq_chip, irq); |
|
if (virq < 0) { |
|
dev_err(&pdev->dev, |
|
"failed to get virtual interrupt=%d\n", irq); |
|
return virq; |
|
} |
|
|
|
ret = devm_request_threaded_irq(&pdev->dev, virq, |
|
NULL, bxt_wcove_tmu_irq_handler, |
|
IRQF_ONESHOT, "bxt_wcove_tmu", wctmu); |
|
if (ret) { |
|
dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n", |
|
ret, virq); |
|
return ret; |
|
} |
|
wctmu->irq = virq; |
|
|
|
/* Unmask TMU second level Wake & System alarm */ |
|
regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG, |
|
BXTWC_TMU_ALRM_MASK, 0); |
|
|
|
platform_set_drvdata(pdev, wctmu); |
|
return 0; |
|
} |
|
|
|
static int bxt_wcove_tmu_remove(struct platform_device *pdev) |
|
{ |
|
struct wcove_tmu *wctmu = platform_get_drvdata(pdev); |
|
unsigned int val; |
|
|
|
/* Mask TMU interrupts */ |
|
regmap_read(wctmu->regmap, BXTWC_MIRQLVL1, &val); |
|
regmap_write(wctmu->regmap, BXTWC_MIRQLVL1, |
|
val | BXTWC_MIRQLVL1_MTMU); |
|
regmap_read(wctmu->regmap, BXTWC_MTMUIRQ_REG, &val); |
|
regmap_write(wctmu->regmap, BXTWC_MTMUIRQ_REG, |
|
val | BXTWC_TMU_ALRM_MASK); |
|
return 0; |
|
} |
|
|
|
#ifdef CONFIG_PM_SLEEP |
|
static int bxtwc_tmu_suspend(struct device *dev) |
|
{ |
|
struct wcove_tmu *wctmu = dev_get_drvdata(dev); |
|
|
|
enable_irq_wake(wctmu->irq); |
|
return 0; |
|
} |
|
|
|
static int bxtwc_tmu_resume(struct device *dev) |
|
{ |
|
struct wcove_tmu *wctmu = dev_get_drvdata(dev); |
|
|
|
disable_irq_wake(wctmu->irq); |
|
return 0; |
|
} |
|
#endif |
|
|
|
static SIMPLE_DEV_PM_OPS(bxtwc_tmu_pm_ops, bxtwc_tmu_suspend, bxtwc_tmu_resume); |
|
|
|
static const struct platform_device_id bxt_wcove_tmu_id_table[] = { |
|
{ .name = "bxt_wcove_tmu" }, |
|
{}, |
|
}; |
|
MODULE_DEVICE_TABLE(platform, bxt_wcove_tmu_id_table); |
|
|
|
static struct platform_driver bxt_wcove_tmu_driver = { |
|
.probe = bxt_wcove_tmu_probe, |
|
.remove = bxt_wcove_tmu_remove, |
|
.driver = { |
|
.name = "bxt_wcove_tmu", |
|
.pm = &bxtwc_tmu_pm_ops, |
|
}, |
|
.id_table = bxt_wcove_tmu_id_table, |
|
}; |
|
|
|
module_platform_driver(bxt_wcove_tmu_driver); |
|
|
|
MODULE_LICENSE("GPL v2"); |
|
MODULE_AUTHOR("Nilesh Bacchewar <[email protected]>"); |
|
MODULE_DESCRIPTION("BXT Whiskey Cove TMU Driver");
|
|
|