12dfef650SFabio Estevam // SPDX-License-Identifier: GPL-2.0 22dfef650SFabio Estevam // 32dfef650SFabio Estevam // Copyright 2016 Freescale Semiconductor, Inc. 443528445SJia Hongtao 551904045SAnson Huang #include <linux/clk.h> 643528445SJia Hongtao #include <linux/module.h> 743528445SJia Hongtao #include <linux/platform_device.h> 843528445SJia Hongtao #include <linux/err.h> 943528445SJia Hongtao #include <linux/io.h> 1043528445SJia Hongtao #include <linux/of.h> 1143528445SJia Hongtao #include <linux/of_address.h> 1243528445SJia Hongtao #include <linux/thermal.h> 1343528445SJia Hongtao 1443528445SJia Hongtao #include "thermal_core.h" 1543528445SJia Hongtao 1643528445SJia Hongtao #define SITES_MAX 16 179809797bSYuantian Tang #define TMR_DISABLE 0x0 189809797bSYuantian Tang #define TMR_ME 0x80000000 199809797bSYuantian Tang #define TMR_ALPF 0x0c000000 209809797bSYuantian Tang #define TMR_ALPF_V2 0x03000000 219809797bSYuantian Tang #define TMTMIR_DEFAULT 0x0000000f 229809797bSYuantian Tang #define TIER_DISABLE 0x0 239809797bSYuantian Tang #define TEUMR0_V2 0x51009c00 249809797bSYuantian Tang #define TMU_VER1 0x1 259809797bSYuantian Tang #define TMU_VER2 0x2 2643528445SJia Hongtao 2743528445SJia Hongtao /* 2843528445SJia Hongtao * QorIQ TMU Registers 2943528445SJia Hongtao */ 3043528445SJia Hongtao struct qoriq_tmu_site_regs { 3143528445SJia Hongtao u32 tritsr; /* Immediate Temperature Site Register */ 3243528445SJia Hongtao u32 tratsr; /* Average Temperature Site Register */ 3343528445SJia Hongtao u8 res0[0x8]; 3443528445SJia Hongtao }; 3543528445SJia Hongtao 369809797bSYuantian Tang struct qoriq_tmu_regs_v1 { 3743528445SJia Hongtao u32 tmr; /* Mode Register */ 3843528445SJia Hongtao u32 tsr; /* Status Register */ 3943528445SJia Hongtao u32 tmtmir; /* Temperature measurement interval Register */ 4043528445SJia Hongtao u8 res0[0x14]; 4143528445SJia Hongtao u32 tier; /* Interrupt Enable Register */ 4243528445SJia Hongtao u32 tidr; /* Interrupt Detect Register */ 4343528445SJia Hongtao u32 tiscr; /* Interrupt Site Capture Register */ 4443528445SJia Hongtao u32 ticscr; /* Interrupt Critical Site Capture Register */ 4543528445SJia Hongtao u8 res1[0x10]; 4643528445SJia Hongtao u32 tmhtcrh; /* High Temperature Capture Register */ 4743528445SJia Hongtao u32 tmhtcrl; /* Low Temperature Capture Register */ 4843528445SJia Hongtao u8 res2[0x8]; 4943528445SJia Hongtao u32 tmhtitr; /* High Temperature Immediate Threshold */ 5043528445SJia Hongtao u32 tmhtatr; /* High Temperature Average Threshold */ 5143528445SJia Hongtao u32 tmhtactr; /* High Temperature Average Crit Threshold */ 5243528445SJia Hongtao u8 res3[0x24]; 5343528445SJia Hongtao u32 ttcfgr; /* Temperature Configuration Register */ 5443528445SJia Hongtao u32 tscfgr; /* Sensor Configuration Register */ 5543528445SJia Hongtao u8 res4[0x78]; 5643528445SJia Hongtao struct qoriq_tmu_site_regs site[SITES_MAX]; 5743528445SJia Hongtao u8 res5[0x9f8]; 5843528445SJia Hongtao u32 ipbrr0; /* IP Block Revision Register 0 */ 5943528445SJia Hongtao u32 ipbrr1; /* IP Block Revision Register 1 */ 6043528445SJia Hongtao u8 res6[0x310]; 619809797bSYuantian Tang u32 ttrcr[4]; /* Temperature Range Control Register */ 629809797bSYuantian Tang }; 639809797bSYuantian Tang 649809797bSYuantian Tang struct qoriq_tmu_regs_v2 { 659809797bSYuantian Tang u32 tmr; /* Mode Register */ 669809797bSYuantian Tang u32 tsr; /* Status Register */ 679809797bSYuantian Tang u32 tmsr; /* monitor site register */ 689809797bSYuantian Tang u32 tmtmir; /* Temperature measurement interval Register */ 699809797bSYuantian Tang u8 res0[0x10]; 709809797bSYuantian Tang u32 tier; /* Interrupt Enable Register */ 719809797bSYuantian Tang u32 tidr; /* Interrupt Detect Register */ 729809797bSYuantian Tang u8 res1[0x8]; 739809797bSYuantian Tang u32 tiiscr; /* interrupt immediate site capture register */ 749809797bSYuantian Tang u32 tiascr; /* interrupt average site capture register */ 759809797bSYuantian Tang u32 ticscr; /* Interrupt Critical Site Capture Register */ 769809797bSYuantian Tang u32 res2; 779809797bSYuantian Tang u32 tmhtcr; /* monitor high temperature capture register */ 789809797bSYuantian Tang u32 tmltcr; /* monitor low temperature capture register */ 799809797bSYuantian Tang u32 tmrtrcr; /* monitor rising temperature rate capture register */ 809809797bSYuantian Tang u32 tmftrcr; /* monitor falling temperature rate capture register */ 819809797bSYuantian Tang u32 tmhtitr; /* High Temperature Immediate Threshold */ 829809797bSYuantian Tang u32 tmhtatr; /* High Temperature Average Threshold */ 839809797bSYuantian Tang u32 tmhtactr; /* High Temperature Average Crit Threshold */ 849809797bSYuantian Tang u32 res3; 859809797bSYuantian Tang u32 tmltitr; /* monitor low temperature immediate threshold */ 869809797bSYuantian Tang u32 tmltatr; /* monitor low temperature average threshold register */ 879809797bSYuantian Tang u32 tmltactr; /* monitor low temperature average critical threshold */ 889809797bSYuantian Tang u32 res4; 899809797bSYuantian Tang u32 tmrtrctr; /* monitor rising temperature rate critical threshold */ 909809797bSYuantian Tang u32 tmftrctr; /* monitor falling temperature rate critical threshold*/ 919809797bSYuantian Tang u8 res5[0x8]; 929809797bSYuantian Tang u32 ttcfgr; /* Temperature Configuration Register */ 939809797bSYuantian Tang u32 tscfgr; /* Sensor Configuration Register */ 949809797bSYuantian Tang u8 res6[0x78]; 959809797bSYuantian Tang struct qoriq_tmu_site_regs site[SITES_MAX]; 969809797bSYuantian Tang u8 res7[0x9f8]; 979809797bSYuantian Tang u32 ipbrr0; /* IP Block Revision Register 0 */ 989809797bSYuantian Tang u32 ipbrr1; /* IP Block Revision Register 1 */ 999809797bSYuantian Tang u8 res8[0x300]; 1009809797bSYuantian Tang u32 teumr0; 1019809797bSYuantian Tang u32 teumr1; 1029809797bSYuantian Tang u32 teumr2; 1039809797bSYuantian Tang u32 res9; 1049809797bSYuantian Tang u32 ttrcr[4]; /* Temperature Range Control Register */ 10543528445SJia Hongtao }; 10643528445SJia Hongtao 1077797ff42SYuantian Tang struct qoriq_tmu_data; 1087797ff42SYuantian Tang 10943528445SJia Hongtao /* 11043528445SJia Hongtao * Thermal zone data 11143528445SJia Hongtao */ 1127797ff42SYuantian Tang struct qoriq_sensor { 1137797ff42SYuantian Tang struct qoriq_tmu_data *qdata; 1147797ff42SYuantian Tang int id; 1157797ff42SYuantian Tang }; 1167797ff42SYuantian Tang 11743528445SJia Hongtao struct qoriq_tmu_data { 1189809797bSYuantian Tang int ver; 1199809797bSYuantian Tang struct qoriq_tmu_regs_v1 __iomem *regs; 1209809797bSYuantian Tang struct qoriq_tmu_regs_v2 __iomem *regs_v2; 12151904045SAnson Huang struct clk *clk; 12243528445SJia Hongtao bool little_endian; 1237797ff42SYuantian Tang struct qoriq_sensor *sensor[SITES_MAX]; 12443528445SJia Hongtao }; 12543528445SJia Hongtao 12643528445SJia Hongtao static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr) 12743528445SJia Hongtao { 12843528445SJia Hongtao if (p->little_endian) 12943528445SJia Hongtao iowrite32(val, addr); 13043528445SJia Hongtao else 13143528445SJia Hongtao iowrite32be(val, addr); 13243528445SJia Hongtao } 13343528445SJia Hongtao 13443528445SJia Hongtao static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr) 13543528445SJia Hongtao { 13643528445SJia Hongtao if (p->little_endian) 13743528445SJia Hongtao return ioread32(addr); 13843528445SJia Hongtao else 13943528445SJia Hongtao return ioread32be(addr); 14043528445SJia Hongtao } 14143528445SJia Hongtao 14243528445SJia Hongtao static int tmu_get_temp(void *p, int *temp) 14343528445SJia Hongtao { 1447797ff42SYuantian Tang struct qoriq_sensor *qsensor = p; 1457797ff42SYuantian Tang struct qoriq_tmu_data *qdata = qsensor->qdata; 14643528445SJia Hongtao u32 val; 14743528445SJia Hongtao 1487797ff42SYuantian Tang val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr); 14943528445SJia Hongtao *temp = (val & 0xff) * 1000; 15043528445SJia Hongtao 15143528445SJia Hongtao return 0; 15243528445SJia Hongtao } 15343528445SJia Hongtao 1547797ff42SYuantian Tang static const struct thermal_zone_of_device_ops tmu_tz_ops = { 1557797ff42SYuantian Tang .get_temp = tmu_get_temp, 1567797ff42SYuantian Tang }; 1577797ff42SYuantian Tang 1587797ff42SYuantian Tang static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev) 15943528445SJia Hongtao { 1607797ff42SYuantian Tang struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev); 1617797ff42SYuantian Tang int id, sites = 0; 16243528445SJia Hongtao 1637797ff42SYuantian Tang for (id = 0; id < SITES_MAX; id++) { 16411ef00f7SAndrey Smirnov struct thermal_zone_device *tzd; 165d6fb0564SAndrey Smirnov struct qoriq_sensor *sensor; 16611ef00f7SAndrey Smirnov int ret; 16711ef00f7SAndrey Smirnov 168d6fb0564SAndrey Smirnov sensor = devm_kzalloc(&pdev->dev, 169d6fb0564SAndrey Smirnov sizeof(struct qoriq_sensor), 170d6fb0564SAndrey Smirnov GFP_KERNEL); 1717797ff42SYuantian Tang if (!qdata->sensor[id]) 1727797ff42SYuantian Tang return -ENOMEM; 17343528445SJia Hongtao 174d6fb0564SAndrey Smirnov qdata->sensor[id] = sensor; 175d6fb0564SAndrey Smirnov 176d6fb0564SAndrey Smirnov sensor->id = id; 177d6fb0564SAndrey Smirnov sensor->qdata = qdata; 17811ef00f7SAndrey Smirnov 17911ef00f7SAndrey Smirnov tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id, 180d6fb0564SAndrey Smirnov sensor, 18111ef00f7SAndrey Smirnov &tmu_tz_ops); 18211ef00f7SAndrey Smirnov ret = PTR_ERR_OR_ZERO(tzd); 18311ef00f7SAndrey Smirnov if (ret) { 18411ef00f7SAndrey Smirnov if (ret == -ENODEV) 1857797ff42SYuantian Tang continue; 1867797ff42SYuantian Tang else 18711ef00f7SAndrey Smirnov return ret; 18843528445SJia Hongtao } 18943528445SJia Hongtao 1909809797bSYuantian Tang if (qdata->ver == TMU_VER1) 1917797ff42SYuantian Tang sites |= 0x1 << (15 - id); 1929809797bSYuantian Tang else 1939809797bSYuantian Tang sites |= 0x1 << id; 19443528445SJia Hongtao } 19543528445SJia Hongtao 1967797ff42SYuantian Tang /* Enable monitoring */ 1979809797bSYuantian Tang if (sites != 0) { 1989809797bSYuantian Tang if (qdata->ver == TMU_VER1) { 1999809797bSYuantian Tang tmu_write(qdata, sites | TMR_ME | TMR_ALPF, 2009809797bSYuantian Tang &qdata->regs->tmr); 2019809797bSYuantian Tang } else { 2029809797bSYuantian Tang tmu_write(qdata, sites, &qdata->regs_v2->tmsr); 2039809797bSYuantian Tang tmu_write(qdata, TMR_ME | TMR_ALPF_V2, 2049809797bSYuantian Tang &qdata->regs_v2->tmr); 2059809797bSYuantian Tang } 2069809797bSYuantian Tang } 20743528445SJia Hongtao 2087797ff42SYuantian Tang return 0; 20943528445SJia Hongtao } 21043528445SJia Hongtao 21143528445SJia Hongtao static int qoriq_tmu_calibration(struct platform_device *pdev) 21243528445SJia Hongtao { 21343528445SJia Hongtao int i, val, len; 21443528445SJia Hongtao u32 range[4]; 21543528445SJia Hongtao const u32 *calibration; 21643528445SJia Hongtao struct device_node *np = pdev->dev.of_node; 21743528445SJia Hongtao struct qoriq_tmu_data *data = platform_get_drvdata(pdev); 21843528445SJia Hongtao 2199809797bSYuantian Tang len = of_property_count_u32_elems(np, "fsl,tmu-range"); 2209809797bSYuantian Tang if (len < 0 || len > 4) { 2219809797bSYuantian Tang dev_err(&pdev->dev, "invalid range data.\n"); 2229809797bSYuantian Tang return len; 2239809797bSYuantian Tang } 2249809797bSYuantian Tang 2259809797bSYuantian Tang val = of_property_read_u32_array(np, "fsl,tmu-range", range, len); 2269809797bSYuantian Tang if (val != 0) { 2279809797bSYuantian Tang dev_err(&pdev->dev, "failed to read range data.\n"); 2289809797bSYuantian Tang return val; 22943528445SJia Hongtao } 23043528445SJia Hongtao 23143528445SJia Hongtao /* Init temperature range registers */ 2329809797bSYuantian Tang for (i = 0; i < len; i++) 2339809797bSYuantian Tang tmu_write(data, range[i], &data->regs->ttrcr[i]); 23443528445SJia Hongtao 23543528445SJia Hongtao calibration = of_get_property(np, "fsl,tmu-calibration", &len); 23643528445SJia Hongtao if (calibration == NULL || len % 8) { 23743528445SJia Hongtao dev_err(&pdev->dev, "invalid calibration data.\n"); 23843528445SJia Hongtao return -ENODEV; 23943528445SJia Hongtao } 24043528445SJia Hongtao 24143528445SJia Hongtao for (i = 0; i < len; i += 8, calibration += 2) { 24243528445SJia Hongtao val = of_read_number(calibration, 1); 24343528445SJia Hongtao tmu_write(data, val, &data->regs->ttcfgr); 24443528445SJia Hongtao val = of_read_number(calibration + 1, 1); 24543528445SJia Hongtao tmu_write(data, val, &data->regs->tscfgr); 24643528445SJia Hongtao } 24743528445SJia Hongtao 24843528445SJia Hongtao return 0; 24943528445SJia Hongtao } 25043528445SJia Hongtao 25143528445SJia Hongtao static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) 25243528445SJia Hongtao { 25343528445SJia Hongtao /* Disable interrupt, using polling instead */ 25443528445SJia Hongtao tmu_write(data, TIER_DISABLE, &data->regs->tier); 25543528445SJia Hongtao 25643528445SJia Hongtao /* Set update_interval */ 2579809797bSYuantian Tang if (data->ver == TMU_VER1) { 25843528445SJia Hongtao tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir); 2599809797bSYuantian Tang } else { 2609809797bSYuantian Tang tmu_write(data, TMTMIR_DEFAULT, &data->regs_v2->tmtmir); 2619809797bSYuantian Tang tmu_write(data, TEUMR0_V2, &data->regs_v2->teumr0); 2629809797bSYuantian Tang } 26343528445SJia Hongtao 26443528445SJia Hongtao /* Disable monitoring */ 26543528445SJia Hongtao tmu_write(data, TMR_DISABLE, &data->regs->tmr); 26643528445SJia Hongtao } 26743528445SJia Hongtao 26843528445SJia Hongtao static int qoriq_tmu_probe(struct platform_device *pdev) 26943528445SJia Hongtao { 27043528445SJia Hongtao int ret; 2719809797bSYuantian Tang u32 ver; 27243528445SJia Hongtao struct qoriq_tmu_data *data; 27343528445SJia Hongtao struct device_node *np = pdev->dev.of_node; 274e167dc43SAndrey Smirnov struct device *dev = &pdev->dev; 27543528445SJia Hongtao 276e167dc43SAndrey Smirnov data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data), 27743528445SJia Hongtao GFP_KERNEL); 27843528445SJia Hongtao if (!data) 27943528445SJia Hongtao return -ENOMEM; 28043528445SJia Hongtao 28143528445SJia Hongtao platform_set_drvdata(pdev, data); 28243528445SJia Hongtao 28343528445SJia Hongtao data->little_endian = of_property_read_bool(np, "little-endian"); 28443528445SJia Hongtao 2854d82000aSAnson Huang data->regs = devm_platform_ioremap_resource(pdev, 0); 2864d82000aSAnson Huang if (IS_ERR(data->regs)) { 287e167dc43SAndrey Smirnov dev_err(dev, "Failed to get memory region\n"); 2884d82000aSAnson Huang return PTR_ERR(data->regs); 28943528445SJia Hongtao } 29043528445SJia Hongtao 291e167dc43SAndrey Smirnov data->clk = devm_clk_get_optional(dev, NULL); 29251904045SAnson Huang if (IS_ERR(data->clk)) 29351904045SAnson Huang return PTR_ERR(data->clk); 29451904045SAnson Huang 29551904045SAnson Huang ret = clk_prepare_enable(data->clk); 29651904045SAnson Huang if (ret) { 297e167dc43SAndrey Smirnov dev_err(dev, "Failed to enable clock\n"); 29851904045SAnson Huang return ret; 29951904045SAnson Huang } 30051904045SAnson Huang 3019809797bSYuantian Tang /* version register offset at: 0xbf8 on both v1 and v2 */ 3029809797bSYuantian Tang ver = tmu_read(data, &data->regs->ipbrr0); 3039809797bSYuantian Tang data->ver = (ver >> 8) & 0xff; 3049809797bSYuantian Tang if (data->ver == TMU_VER2) 3059809797bSYuantian Tang data->regs_v2 = (void __iomem *)data->regs; 3069809797bSYuantian Tang 30743528445SJia Hongtao qoriq_tmu_init_device(data); /* TMU initialization */ 30843528445SJia Hongtao 30943528445SJia Hongtao ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ 31043528445SJia Hongtao if (ret < 0) 3114d82000aSAnson Huang goto err; 31243528445SJia Hongtao 3137797ff42SYuantian Tang ret = qoriq_tmu_register_tmu_zone(pdev); 3147797ff42SYuantian Tang if (ret < 0) { 315e167dc43SAndrey Smirnov dev_err(dev, "Failed to register sensors\n"); 3167797ff42SYuantian Tang ret = -ENODEV; 3174d82000aSAnson Huang goto err; 31843528445SJia Hongtao } 31943528445SJia Hongtao 32043528445SJia Hongtao return 0; 32143528445SJia Hongtao 3224d82000aSAnson Huang err: 32351904045SAnson Huang clk_disable_unprepare(data->clk); 32443528445SJia Hongtao platform_set_drvdata(pdev, NULL); 32543528445SJia Hongtao 32643528445SJia Hongtao return ret; 32743528445SJia Hongtao } 32843528445SJia Hongtao 32943528445SJia Hongtao static int qoriq_tmu_remove(struct platform_device *pdev) 33043528445SJia Hongtao { 33143528445SJia Hongtao struct qoriq_tmu_data *data = platform_get_drvdata(pdev); 33243528445SJia Hongtao 33343528445SJia Hongtao /* Disable monitoring */ 33443528445SJia Hongtao tmu_write(data, TMR_DISABLE, &data->regs->tmr); 33543528445SJia Hongtao 33651904045SAnson Huang clk_disable_unprepare(data->clk); 33751904045SAnson Huang 33843528445SJia Hongtao platform_set_drvdata(pdev, NULL); 33943528445SJia Hongtao 34043528445SJia Hongtao return 0; 34143528445SJia Hongtao } 34243528445SJia Hongtao 343aea59197SAnson Huang static int __maybe_unused qoriq_tmu_suspend(struct device *dev) 34443528445SJia Hongtao { 34543528445SJia Hongtao u32 tmr; 34643528445SJia Hongtao struct qoriq_tmu_data *data = dev_get_drvdata(dev); 34743528445SJia Hongtao 34843528445SJia Hongtao /* Disable monitoring */ 34943528445SJia Hongtao tmr = tmu_read(data, &data->regs->tmr); 35043528445SJia Hongtao tmr &= ~TMR_ME; 35143528445SJia Hongtao tmu_write(data, tmr, &data->regs->tmr); 35243528445SJia Hongtao 35351904045SAnson Huang clk_disable_unprepare(data->clk); 35451904045SAnson Huang 35543528445SJia Hongtao return 0; 35643528445SJia Hongtao } 35743528445SJia Hongtao 358aea59197SAnson Huang static int __maybe_unused qoriq_tmu_resume(struct device *dev) 35943528445SJia Hongtao { 36043528445SJia Hongtao u32 tmr; 36151904045SAnson Huang int ret; 36243528445SJia Hongtao struct qoriq_tmu_data *data = dev_get_drvdata(dev); 36343528445SJia Hongtao 36451904045SAnson Huang ret = clk_prepare_enable(data->clk); 36551904045SAnson Huang if (ret) 36651904045SAnson Huang return ret; 36751904045SAnson Huang 36843528445SJia Hongtao /* Enable monitoring */ 36943528445SJia Hongtao tmr = tmu_read(data, &data->regs->tmr); 37043528445SJia Hongtao tmr |= TMR_ME; 37143528445SJia Hongtao tmu_write(data, tmr, &data->regs->tmr); 37243528445SJia Hongtao 37343528445SJia Hongtao return 0; 37443528445SJia Hongtao } 37543528445SJia Hongtao 37643528445SJia Hongtao static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, 37743528445SJia Hongtao qoriq_tmu_suspend, qoriq_tmu_resume); 37843528445SJia Hongtao 37943528445SJia Hongtao static const struct of_device_id qoriq_tmu_match[] = { 38043528445SJia Hongtao { .compatible = "fsl,qoriq-tmu", }, 3816017e2a9SAnson Huang { .compatible = "fsl,imx8mq-tmu", }, 38243528445SJia Hongtao {}, 38343528445SJia Hongtao }; 38443528445SJia Hongtao MODULE_DEVICE_TABLE(of, qoriq_tmu_match); 38543528445SJia Hongtao 38643528445SJia Hongtao static struct platform_driver qoriq_tmu = { 38743528445SJia Hongtao .driver = { 38843528445SJia Hongtao .name = "qoriq_thermal", 38943528445SJia Hongtao .pm = &qoriq_tmu_pm_ops, 39043528445SJia Hongtao .of_match_table = qoriq_tmu_match, 39143528445SJia Hongtao }, 39243528445SJia Hongtao .probe = qoriq_tmu_probe, 39343528445SJia Hongtao .remove = qoriq_tmu_remove, 39443528445SJia Hongtao }; 39543528445SJia Hongtao module_platform_driver(qoriq_tmu); 39643528445SJia Hongtao 39743528445SJia Hongtao MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>"); 39843528445SJia Hongtao MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver"); 39943528445SJia Hongtao MODULE_LICENSE("GPL v2"); 400