0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/irq.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/mfd/max77620.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018 #include <linux/slab.h>
0019 #include <linux/thermal.h>
0020
0021 #define MAX77620_NORMAL_OPERATING_TEMP 100000
0022 #define MAX77620_TJALARM1_TEMP 120000
0023 #define MAX77620_TJALARM2_TEMP 140000
0024
0025 struct max77620_therm_info {
0026 struct device *dev;
0027 struct regmap *rmap;
0028 struct thermal_zone_device *tz_device;
0029 int irq_tjalarm1;
0030 int irq_tjalarm2;
0031 };
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 static int max77620_thermal_read_temp(void *data, int *temp)
0048 {
0049 struct max77620_therm_info *mtherm = data;
0050 unsigned int val;
0051 int ret;
0052
0053 ret = regmap_read(mtherm->rmap, MAX77620_REG_STATLBT, &val);
0054 if (ret < 0) {
0055 dev_err(mtherm->dev, "Failed to read STATLBT: %d\n", ret);
0056 return ret;
0057 }
0058
0059 if (val & MAX77620_IRQ_TJALRM2_MASK)
0060 *temp = MAX77620_TJALARM2_TEMP;
0061 else if (val & MAX77620_IRQ_TJALRM1_MASK)
0062 *temp = MAX77620_TJALARM1_TEMP;
0063 else
0064 *temp = MAX77620_NORMAL_OPERATING_TEMP;
0065
0066 return 0;
0067 }
0068
0069 static const struct thermal_zone_of_device_ops max77620_thermal_ops = {
0070 .get_temp = max77620_thermal_read_temp,
0071 };
0072
0073 static irqreturn_t max77620_thermal_irq(int irq, void *data)
0074 {
0075 struct max77620_therm_info *mtherm = data;
0076
0077 if (irq == mtherm->irq_tjalarm1)
0078 dev_warn(mtherm->dev, "Junction Temp Alarm1(120C) occurred\n");
0079 else if (irq == mtherm->irq_tjalarm2)
0080 dev_crit(mtherm->dev, "Junction Temp Alarm2(140C) occurred\n");
0081
0082 thermal_zone_device_update(mtherm->tz_device,
0083 THERMAL_EVENT_UNSPECIFIED);
0084
0085 return IRQ_HANDLED;
0086 }
0087
0088 static int max77620_thermal_probe(struct platform_device *pdev)
0089 {
0090 struct max77620_therm_info *mtherm;
0091 int ret;
0092
0093 mtherm = devm_kzalloc(&pdev->dev, sizeof(*mtherm), GFP_KERNEL);
0094 if (!mtherm)
0095 return -ENOMEM;
0096
0097 mtherm->irq_tjalarm1 = platform_get_irq(pdev, 0);
0098 mtherm->irq_tjalarm2 = platform_get_irq(pdev, 1);
0099 if ((mtherm->irq_tjalarm1 < 0) || (mtherm->irq_tjalarm2 < 0)) {
0100 dev_err(&pdev->dev, "Alarm irq number not available\n");
0101 return -EINVAL;
0102 }
0103
0104 mtherm->dev = &pdev->dev;
0105 mtherm->rmap = dev_get_regmap(pdev->dev.parent, NULL);
0106 if (!mtherm->rmap) {
0107 dev_err(&pdev->dev, "Failed to get parent regmap\n");
0108 return -ENODEV;
0109 }
0110
0111
0112
0113
0114
0115 device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
0116
0117 mtherm->tz_device = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
0118 mtherm, &max77620_thermal_ops);
0119 if (IS_ERR(mtherm->tz_device)) {
0120 ret = PTR_ERR(mtherm->tz_device);
0121 dev_err(&pdev->dev, "Failed to register thermal zone: %d\n",
0122 ret);
0123 return ret;
0124 }
0125
0126 ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL,
0127 max77620_thermal_irq,
0128 IRQF_ONESHOT | IRQF_SHARED,
0129 dev_name(&pdev->dev), mtherm);
0130 if (ret < 0) {
0131 dev_err(&pdev->dev, "Failed to request irq1: %d\n", ret);
0132 return ret;
0133 }
0134
0135 ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm2, NULL,
0136 max77620_thermal_irq,
0137 IRQF_ONESHOT | IRQF_SHARED,
0138 dev_name(&pdev->dev), mtherm);
0139 if (ret < 0) {
0140 dev_err(&pdev->dev, "Failed to request irq2: %d\n", ret);
0141 return ret;
0142 }
0143
0144 platform_set_drvdata(pdev, mtherm);
0145
0146 return 0;
0147 }
0148
0149 static struct platform_device_id max77620_thermal_devtype[] = {
0150 { .name = "max77620-thermal", },
0151 {},
0152 };
0153 MODULE_DEVICE_TABLE(platform, max77620_thermal_devtype);
0154
0155 static struct platform_driver max77620_thermal_driver = {
0156 .driver = {
0157 .name = "max77620-thermal",
0158 },
0159 .probe = max77620_thermal_probe,
0160 .id_table = max77620_thermal_devtype,
0161 };
0162
0163 module_platform_driver(max77620_thermal_driver);
0164
0165 MODULE_DESCRIPTION("Max77620 Junction temperature Thermal driver");
0166 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
0167 MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
0168 MODULE_LICENSE("GPL v2");