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