Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel BXT Whiskey Cove PMIC TMU driver
0004  *
0005  * Copyright (C) 2016 Intel Corporation. All rights reserved.
0006  *
0007  * This driver adds TMU (Time Management Unit) support for Intel BXT platform.
0008  * It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove
0009  * PMIC.
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/mod_devicetable.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/mfd/intel_soc_pmic.h>
0017 
0018 #define BXTWC_TMUIRQ        0x4fb6
0019 #define BXTWC_MIRQLVL1      0x4e0e
0020 #define BXTWC_MTMUIRQ_REG   0x4fb7
0021 #define BXTWC_MIRQLVL1_MTMU BIT(1)
0022 #define BXTWC_TMU_WK_ALRM   BIT(1)
0023 #define BXTWC_TMU_SYS_ALRM  BIT(2)
0024 #define BXTWC_TMU_ALRM_MASK (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
0025 #define BXTWC_TMU_ALRM_IRQ  (BXTWC_TMU_WK_ALRM | BXTWC_TMU_SYS_ALRM)
0026 
0027 struct wcove_tmu {
0028     int irq;
0029     struct device *dev;
0030     struct regmap *regmap;
0031 };
0032 
0033 static irqreturn_t bxt_wcove_tmu_irq_handler(int irq, void *data)
0034 {
0035     struct wcove_tmu *wctmu = data;
0036     unsigned int tmu_irq;
0037 
0038     /* Read TMU interrupt reg */
0039     regmap_read(wctmu->regmap, BXTWC_TMUIRQ, &tmu_irq);
0040     if (tmu_irq & BXTWC_TMU_ALRM_IRQ) {
0041         /* clear TMU irq */
0042         regmap_write(wctmu->regmap, BXTWC_TMUIRQ, tmu_irq);
0043         return IRQ_HANDLED;
0044     }
0045     return IRQ_NONE;
0046 }
0047 
0048 static int bxt_wcove_tmu_probe(struct platform_device *pdev)
0049 {
0050     struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
0051     struct regmap_irq_chip_data *regmap_irq_chip;
0052     struct wcove_tmu *wctmu;
0053     int ret, virq, irq;
0054 
0055     wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL);
0056     if (!wctmu)
0057         return -ENOMEM;
0058 
0059     wctmu->dev = &pdev->dev;
0060     wctmu->regmap = pmic->regmap;
0061 
0062     irq = platform_get_irq(pdev, 0);
0063     if (irq < 0)
0064         return irq;
0065 
0066     regmap_irq_chip = pmic->irq_chip_data_tmu;
0067     virq = regmap_irq_get_virq(regmap_irq_chip, irq);
0068     if (virq < 0) {
0069         dev_err(&pdev->dev,
0070             "failed to get virtual interrupt=%d\n", irq);
0071         return virq;
0072     }
0073 
0074     ret = devm_request_threaded_irq(&pdev->dev, virq,
0075                     NULL, bxt_wcove_tmu_irq_handler,
0076                     IRQF_ONESHOT, "bxt_wcove_tmu", wctmu);
0077     if (ret) {
0078         dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n",
0079                             ret, virq);
0080         return ret;
0081     }
0082     wctmu->irq = virq;
0083 
0084     /* Unmask TMU second level Wake & System alarm */
0085     regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG,
0086                   BXTWC_TMU_ALRM_MASK, 0);
0087 
0088     platform_set_drvdata(pdev, wctmu);
0089     return 0;
0090 }
0091 
0092 static int bxt_wcove_tmu_remove(struct platform_device *pdev)
0093 {
0094     struct wcove_tmu *wctmu = platform_get_drvdata(pdev);
0095     unsigned int val;
0096 
0097     /* Mask TMU interrupts */
0098     regmap_read(wctmu->regmap, BXTWC_MIRQLVL1, &val);
0099     regmap_write(wctmu->regmap, BXTWC_MIRQLVL1,
0100             val | BXTWC_MIRQLVL1_MTMU);
0101     regmap_read(wctmu->regmap, BXTWC_MTMUIRQ_REG, &val);
0102     regmap_write(wctmu->regmap, BXTWC_MTMUIRQ_REG,
0103             val | BXTWC_TMU_ALRM_MASK);
0104     return 0;
0105 }
0106 
0107 #ifdef CONFIG_PM_SLEEP
0108 static int bxtwc_tmu_suspend(struct device *dev)
0109 {
0110     struct wcove_tmu *wctmu = dev_get_drvdata(dev);
0111 
0112     enable_irq_wake(wctmu->irq);
0113     return 0;
0114 }
0115 
0116 static int bxtwc_tmu_resume(struct device *dev)
0117 {
0118     struct wcove_tmu *wctmu = dev_get_drvdata(dev);
0119 
0120     disable_irq_wake(wctmu->irq);
0121     return 0;
0122 }
0123 #endif
0124 
0125 static SIMPLE_DEV_PM_OPS(bxtwc_tmu_pm_ops, bxtwc_tmu_suspend, bxtwc_tmu_resume);
0126 
0127 static const struct platform_device_id bxt_wcove_tmu_id_table[] = {
0128     { .name = "bxt_wcove_tmu" },
0129     {},
0130 };
0131 MODULE_DEVICE_TABLE(platform, bxt_wcove_tmu_id_table);
0132 
0133 static struct platform_driver bxt_wcove_tmu_driver = {
0134     .probe = bxt_wcove_tmu_probe,
0135     .remove = bxt_wcove_tmu_remove,
0136     .driver = {
0137         .name = "bxt_wcove_tmu",
0138         .pm     = &bxtwc_tmu_pm_ops,
0139     },
0140     .id_table = bxt_wcove_tmu_id_table,
0141 };
0142 
0143 module_platform_driver(bxt_wcove_tmu_driver);
0144 
0145 MODULE_LICENSE("GPL v2");
0146 MODULE_AUTHOR("Nilesh Bacchewar <nilesh.bacchewar@intel.com>");
0147 MODULE_DESCRIPTION("BXT Whiskey Cove TMU Driver");