From patchwork Tue Nov 24 06:52:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongtao Jia X-Patchwork-Id: 547861 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 05A571402F0 for ; Tue, 24 Nov 2015 18:16:38 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id DED111A1D76 for ; Tue, 24 Nov 2015 18:16:37 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org X-Greylist: delayed 855 seconds by postgrey-1.35 at bilbo; Tue, 24 Nov 2015 18:14:23 AEDT Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2on0135.outbound.protection.outlook.com [207.46.100.135]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id C2F151A03F8 for ; Tue, 24 Nov 2015 18:14:23 +1100 (AEDT) Received: from BLUPR03CA005.namprd03.prod.outlook.com (10.255.124.22) by BLUPR03MB152.namprd03.prod.outlook.com (10.255.212.28) with Microsoft SMTP Server (TLS) id 15.1.325.17; Tue, 24 Nov 2015 07:00:02 +0000 Received: from BN1BFFO11FD009.protection.gbl (10.255.124.4) by BLUPR03CA005.outlook.office365.com (10.255.124.22) with Microsoft SMTP Server (TLS) id 15.1.331.20 via Frontend Transport; Tue, 24 Nov 2015 07:00:02 +0000 Authentication-Results: spf=permerror (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; freescale.mail.onmicrosoft.com; dmarc=none action=none header.from=freescale.com; Received-SPF: PermError (protection.outlook.com: domain of freescale.com used an invalid SPF mechanism) Received: from az84smr01.freescale.net (192.88.158.2) by BN1BFFO11FD009.mail.protection.outlook.com (10.58.144.72) with Microsoft SMTP Server (TLS) id 15.1.331.11 via Frontend Transport; Tue, 24 Nov 2015 07:00:02 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id tAO6xofZ022023; Mon, 23 Nov 2015 23:59:58 -0700 From: Jia Hongtao To: Subject: [PATCH V4 2/5] thermal: qoriq: Add thermal management support Date: Tue, 24 Nov 2015 14:52:45 +0800 Message-ID: <1448347968-37766-3-git-send-email-hongtao.jia@freescale.com> X-Mailer: git-send-email 2.1.0.27.g96db324 In-Reply-To: <1448347968-37766-1-git-send-email-hongtao.jia@freescale.com> References: <1448347968-37766-1-git-send-email-hongtao.jia@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BN1BFFO11FD009; 1:EBH+aig19l4reDaVavZcg/MgJY6tkkQfIXqAsk1OSPPOERYb9xmZTKd7q5I2sVrLqKscpnCixTioHpAKVS3GVCNcs9u1sYTql05TfBsCi+xLnivcGLfYVEVT1Q/pb487XL3F5Jy+8eTGiVpdJkNfydcCQx2cd1PgyhUJpS2Z+lMlFFW0yQPppsUdfpZh74VcX/TzCDMWMJUQij5jB/qgV5WDa/EeXN4LL7V7Tx/WQydw1T65IuZLmQJzHYGidydTDRVxjUTD3bUsVLpsQb3b03dmKPH1v12K199TsTtcgSABH4vhwGZ6gxY1doyXX4zjdYiAGMcyR5HpWtlpVDiPrMKZJJTNXAbq5bED9OzUvxFTFqOFkE/grSzsQEEuvXlmZTBMTugh+jQTbEz8Q7Ui+cPGKQfu2VqbX2KVfV/228A= X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(2980300002)(448002)(199003)(189002)(2950100001)(69596002)(5003940100001)(50986999)(33646002)(575784001)(19580395003)(48376002)(97736004)(2351001)(11100500001)(50226001)(77096005)(76176999)(50466002)(47776003)(86362001)(586003)(19580405001)(36756003)(92566002)(110136002)(5001960100002)(5008740100001)(81156007)(106466001)(229853001)(6806005)(5007970100001)(87936001)(104016004)(189998001)(107886002)(85326001)(4001430100002)(2004002)(473944003); DIR:OUT; SFP:1102; SCL:1; SRVR:BLUPR03MB152; H:az84smr01.freescale.net; FPR:; SPF:PermError; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB152; 2:QLUmoR3mUXrNeQU2FHzM/5iGS6zBRNiZWlYEC0QcYJiAdkqb0xmUgzA5+gkLr3D4Wc4osaAM/XlkmSFT0V4J3ZHl65Ml46N8Uqax+sLgSiC86s5L+TSJmvXbK4nLBUZR0N2HPmKQfCXuW+xYjT9O/31kGh0uEKBSWx0P/AC1WG0=; 3:PQAeAnKNCQ/31nI66mMayaQRDAhYEYVspMre+3g/DYWTdmpUuZmTBTRSrOsEPxvdDvFycLc9If4VAEINup5O0gUukaRXaS6tnyCX10okVEiVVg42UFgUtCV7/dm9hIiMJ4zmr6w3Qivwa/V+7Bpo3+3lExlmjHafZirXiTdWcIiTV6r/TRQFeLtDVAxHQ10XjoLgBAVlcckClh36yr+bWQOexZ+hovHF2Q8u5GGDs1U=; 25:iyGAkmaCb2Dg0nUBdVrXUt13GFjv4uz4nM5iNneQhkuGIVcNDaW/XQpbC3PrE5kPkx50WAkRi4zQbsfqmdK5yq4ciWzev5AIuCbAM2th9eS+zJn8BGkOF7yLYJPJCl8W0Dz3BqM2bcL0jaMgtRBjjIu7iK4w2UUyuXtb451covQ3nupOCoeLB7iRyWXEiHyaUkLuKW9me9PLbuTrUSrrDoca6Yw5CqfHfKmK5ySdtyNr9Lyc02s/vFwtZJTRohca X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB152; X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB152; 20:3KrC20K05So2MZVGirQ8H9vYk+ADxRaMXuyclt9lXadTKcdz52txhoIkD1MuVF03jhW8QWSJ2v27pzQ/+7pkahHE5oDoL29FjCoMqrTk/Jb0l7rOzn/hVySI9o2cGDK8ZeXs6aQ0wNvwRRdFhX2Xy69eGe8RwQfLk6XMKxDsmulstSCHgUVYRj7ojxUYcROCMtryacYehxiCU4E5WBIEcikhkJMr/X3bpzP890w03ZgLWvGh6TL+1Jp/qWH/dqN5eWsZu2+FpGS3gHTGo0dxXzWVOQGF+uwbvCj1ccaRNG3955nY0n6nGHGYf0xQJKSVHkF45lKGxEIVfAcM656Uop0ekPRWm6ODEpj2A0OgYlI=; 4:k1t69oIWiDTfrco1wsFbdRjbQGyY5aO1MS8HYJpOQmGbPKnoLSpW4FqzmGOjPG8ZuuKU+ytMwMnVnopb40osDay7VPjLneCKmuUx2JZZ4+1C9Us+YtBphj+EpZ2YaCSTB2suZoi3IgWXJ4UFUvOH9ZUp0tHDdXRGDEvHCXfn+3UdblX4iTkY3zOkPPNXtFdXuMIxveSFZX52wQITTdvgWhxTz5qYEub2IPY/U9B3UIlo2wrFP6M8zOP3g2TKU+euujbS/FgdWKm4R8Kzg5dj6GeCLPyExmZAf4KWbXp47rIkFb4tC3r3pZnqn9nlXgawDFxQnEvMnIz2fKIvLPKXxL0fgQYDBSmrARPeqEhsa8s9bckkUzGJVingY1YrQPT5 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(520078)(5005006)(8121501046)(10201501046)(3002001); SRVR:BLUPR03MB152; BCL:0; PCL:0; RULEID:; SRVR:BLUPR03MB152; X-Forefront-PRVS: 0770F75EA9 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR03MB152; 23:DVhuYO7IIMWWWsgxxptV6k5a5b7+35ekhJ0V43epwP?= =?us-ascii?Q?xiaFu/J697P8gw1TSmryu9C7wa3qa8FCev7aqnK3rJjFUSjp3SzA2oJlToQj?= =?us-ascii?Q?gyQmVW1ne1f1Cm3B1HnRZMp+Cwr+zCJoTM5Y5tvJAcCS7wTPU6LlHFlmPYqy?= =?us-ascii?Q?uu4PVjzqltsFiYyNhEeQ8lY8y8atwQTwAlCppOVQT0tHFCvtrDe6ohDgb167?= =?us-ascii?Q?/VlIuhNoPFD5wA9sxZIziGbIAQxCbsfg+c29Hkmtq7uQV27B0T5Z7gRISMAG?= =?us-ascii?Q?Xl8I/lI7oAexIDuO6G0xYxHgeHJAFI4E2BEcxnvRm/48cPEYkAxwC2ZYn+/w?= =?us-ascii?Q?/9g3mf/kwyde3nMrBuXhX1s9noq+zplZBfQ9Rfch42HQuP8x9LJ1L+I8q8gg?= =?us-ascii?Q?Z2yFNc38GQ+sfcIGHMkXzcIlLpmkuFZNMMpZF6/FEgBM7dH+Xc9qZ58pg6dU?= =?us-ascii?Q?Rx0duEg3UBJgv90aqeKRry/OGSofYT3bRUjgc+x7zX5j3RA5zVslRgRxTnav?= =?us-ascii?Q?iJjGegStXbHoevDg3RPqDJ8j5afJZ9OPdHI4NUiE3LkEjl8G41b9SkBt/Ozx?= =?us-ascii?Q?8xfbvjh79caqk7/bZddc0EZRAmjmH6onHEBLmbSTIV9DWi4rGviMCjuhQxly?= =?us-ascii?Q?KIiUO3nXf7kZV4V5cVeNCZAZVNSbyfWEkTaTGwI8X1Y8iR/7cFwueTeepcC9?= =?us-ascii?Q?wG9vEVgsXrAsqKhUWlBakD9+7VohqCzfEglY4SZx2wX06QVw1iZJQtxlyQQv?= =?us-ascii?Q?V46F8zzmHsRJrjUekQDraJhJwzjLkwVk8j8dHFduQ++vVg8t3F2bYhQo/Io7?= =?us-ascii?Q?6/MbEyfINGvFu1zJMGR0Dqky2mw/cIBV44TEXFLWR0Bto8D1VNe/2GQ4eEZw?= =?us-ascii?Q?i6FJOuIzlPb/q7FpqOIIht6ITN/KcPfopn8Q1sUayskLk7tDR1jeeL5fG+hn?= =?us-ascii?Q?7qp/XHdHRF02+f5UYy2lhRL1MCBMPe1RZicVMCG5y7bE112iCwFveRxIe1WC?= =?us-ascii?Q?nmcAlhWevQU14L4ySmXQIU+7g/Gvq40kJIhYIrJvJrgvObiZRjRB0qs5Cc+V?= =?us-ascii?Q?a9AcsqufobjLgLh0j3CXlqLDrgRblERDG1U4JHrxQnqnUi4d/Zbc52lPd2Yj?= =?us-ascii?Q?1lYT7J00A=3D?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB152; 5:b754H+sHJXgfqqntEbZWnxvNjmcJe/cvhq5lXiKtN9S1ydf8x5SmUNKvCiVt3qaPZUY1cW8Dg94/2p6GRZWuHpQmkmiaIvV0uiE4lPKx5dAqHTvmquBiDsxrdoI6wuyfATf5U1N/yXRu2PzIQyE3zA==; 24:yDETi4eUC4r6Q62wknq6JA7QbSUkcCLJvsGfauDc0VWzaVJbpxryWvBZsJvolwmvK5H7I75lVmzEyV0YHub89S3SjGbbu/R0DKA2qNI/ziE=; 20:kIOu/XEs4Fi08m77peoLOi7RMcGGNXTOZ+3ZQZv18pDhGKZQn419Fm2IRDqAGOD8MVBb6nsYXOwRFw8BiUgP/Q== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Nov 2015 07:00:02.6180 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR03MB152 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: scottwood@freescale.com, devicetree@vger.kernel.org, hongtao.jia@freescale.com, linuxppc-dev@lists.ozlabs.org, linux-pm@vger.kernel.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" This driver add thermal management support by enabling TMU (Thermal Monitoring Unit) on QorIQ platform. It's based on thermal of framework: - Trip points defined in device tree. - Cpufreq as cooling device registered in qoriq cpufreq driver. Signed-off-by: Jia Hongtao Reviewed-by: Scott Wood --- V4 changes: - Code cleanup: * Remove unnecessary comments. * Remove unnecessary cpufreq.h inclusion. * Remove unnecessary ENABLE mode setting in probe function. * Redefine tmu_get_temp function. V3 changes: - Using thermal of framework. drivers/thermal/Kconfig | 10 ++ drivers/thermal/Makefile | 1 + drivers/thermal/qoriq_thermal.c | 262 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+) create mode 100644 drivers/thermal/qoriq_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index c463c89..43a925c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -194,6 +194,16 @@ config IMX_THERMAL cpufreq is used as the cooling device to throttle CPUs when the passive trip is crossed. +config QORIQ_THERMAL + tristate "Freescale QorIQ Thermal Monitoring Unit" + depends on CPU_THERMAL + depends on THERMAL_OF + help + Enable thermal management based on Freescale QorIQ Thermal Monitoring + Unit (TMU). It supports one critical trip point and one passive trip + point. The cpufreq is used as the cooling device to throttle CPUs when + the passive trip is crossed. + config SPEAR_THERMAL bool "SPEAr thermal sensor driver" depends on PLAT_SPEAR || COMPILE_TEST diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index cfae6a6..e269979 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o +obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c new file mode 100644 index 0000000..2a563f9 --- /dev/null +++ b/drivers/thermal/qoriq_thermal.c @@ -0,0 +1,262 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define SITES_MAX 16 + +/* + * QorIQ TMU Registers + */ +struct qoriq_tmu_site_regs { + __be32 tritsr; /* Immediate Temperature Site Register */ + __be32 tratsr; /* Average Temperature Site Register */ + u8 res0[0x8]; +} __packed; + +struct qoriq_tmu_regs { + __be32 tmr; /* Mode Register */ +#define TMR_DISABLE 0x0 +#define TMR_ME 0x80000000 +#define TMR_ALPF 0x0c000000 +#define TMR_MSITE 0x00008000 /* Core temperature site */ +#define TMR_ALL (TMR_ME | TMR_ALPF | TMR_MSITE) + __be32 tsr; /* Status Register */ + __be32 tmtmir; /* Temperature measurement interval Register */ +#define TMTMIR_DEFAULT 0x0000000f + u8 res0[0x14]; + __be32 tier; /* Interrupt Enable Register */ +#define TIER_DISABLE 0x0 + __be32 tidr; /* Interrupt Detect Register */ + __be32 tiscr; /* Interrupt Site Capture Register */ + __be32 ticscr; /* Interrupt Critical Site Capture Register */ + u8 res1[0x10]; + __be32 tmhtcrh; /* High Temperature Capture Register */ + __be32 tmhtcrl; /* Low Temperature Capture Register */ + u8 res2[0x8]; + __be32 tmhtitr; /* High Temperature Immediate Threshold */ + __be32 tmhtatr; /* High Temperature Average Threshold */ + __be32 tmhtactr; /* High Temperature Average Crit Threshold */ + u8 res3[0x24]; + __be32 ttcfgr; /* Temperature Configuration Register */ + __be32 tscfgr; /* Sensor Configuration Register */ + u8 res4[0x78]; + struct qoriq_tmu_site_regs site[SITES_MAX]; + u8 res5[0x9f8]; + __be32 ipbrr0; /* IP Block Revision Register 0 */ + __be32 ipbrr1; /* IP Block Revision Register 1 */ + u8 res6[0x310]; + __be32 ttr0cr; /* Temperature Range 0 Control Register */ + __be32 ttr1cr; /* Temperature Range 1 Control Register */ + __be32 ttr2cr; /* Temperature Range 2 Control Register */ + __be32 ttr3cr; /* Temperature Range 3 Control Register */ +}; + +/* + * Thermal zone data + */ +struct qoriq_tmu_data { + struct thermal_zone_device *tz; + struct qoriq_tmu_regs __iomem *regs; +}; + +static int tmu_get_temp(void *p, int *temp) +{ + u32 val; + struct qoriq_tmu_data *data = p; + + val = ioread32be(&data->regs->site[0].tritsr); + *temp = (val & 0xff) * 1000; + + return 0; +} + +static int qoriq_tmu_calibration(struct platform_device *pdev) +{ + int i, val, len; + u32 range[4]; + const __be32 *calibration; + struct device_node *node = pdev->dev.of_node; + struct qoriq_tmu_data *data = platform_get_drvdata(pdev); + + /* Disable monitoring before calibration */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + + if (of_property_read_u32_array(node, "fsl,tmu-range", range, 4)) { + dev_err(&pdev->dev, "TMU: missing calibration range.\n"); + return -ENODEV; + } + + /* Init temperature range registers */ + iowrite32be(range[0], &data->regs->ttr0cr); + iowrite32be(range[1], &data->regs->ttr1cr); + iowrite32be(range[2], &data->regs->ttr2cr); + iowrite32be(range[3], &data->regs->ttr3cr); + + calibration = of_get_property(node, "fsl,tmu-calibration", &len); + if (calibration == NULL) { + dev_err(&pdev->dev, "TMU: missing calibration data.\n"); + return -ENODEV; + } + + for (i = 0; i < len; i += 8, calibration += 2) { + val = of_read_number(calibration, 1); + iowrite32be(val, &data->regs->ttcfgr); + val = of_read_number(calibration + 1, 1); + iowrite32be(val, &data->regs->tscfgr); + } + + return 0; +} + +static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) +{ + /* Disable interrupt, using polling instead */ + iowrite32be(TIER_DISABLE, &data->regs->tier); + + /* Set update_interval */ + iowrite32be(TMTMIR_DEFAULT, &data->regs->tmtmir); + + /* Enable monitoring */ + iowrite32be(TMR_ALL, &data->regs->tmr); +} + +static struct thermal_zone_of_device_ops tmu_tz_ops = { + .get_temp = tmu_get_temp, +}; + +static int qoriq_tmu_probe(struct platform_device *pdev) +{ + int ret; + const struct thermal_trip *trip; + struct qoriq_tmu_data *data; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "Device OF-Node is NULL"); + return -ENODEV; + } + + data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + platform_set_drvdata(pdev, data); + data->regs = of_iomap(pdev->dev.of_node, 0); + + if (!data->regs) { + dev_err(&pdev->dev, "Failed to get memory region\n"); + ret = -ENODEV; + goto err_iomap; + } + + ret = qoriq_tmu_calibration(pdev); /* TMU calibration */ + if (ret < 0) + goto err_tmu; + + qoriq_tmu_init_device(data); /* TMU initialization */ + + data->tz = thermal_zone_of_sensor_register(&pdev->dev, 0, + data, &tmu_tz_ops); + if (IS_ERR(data->tz)) { + ret = PTR_ERR(data->tz); + dev_err(&pdev->dev, + "Failed to register thermal zone device %d\n", ret); + goto err_tmu; + } + + trip = of_thermal_get_trip_points(data->tz); + + return 0; + +err_tmu: + iounmap(data->regs); + +err_iomap: + platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, data); + + return ret; +} + +static int qoriq_tmu_remove(struct platform_device *pdev) +{ + struct qoriq_tmu_data *data = platform_get_drvdata(pdev); + + /* Disable monitoring */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + + thermal_zone_of_sensor_unregister(&pdev->dev, data->tz); + iounmap(data->regs); + + platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, data); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int qoriq_tmu_suspend(struct device *dev) +{ + struct qoriq_tmu_data *data = dev_get_drvdata(dev); + + /* Disable monitoring */ + iowrite32be(TMR_DISABLE, &data->regs->tmr); + data->tz->ops->set_mode(data->tz, THERMAL_DEVICE_DISABLED); + + return 0; +} + +static int qoriq_tmu_resume(struct device *dev) +{ + struct qoriq_tmu_data *data = dev_get_drvdata(dev); + + /* Enable monitoring */ + iowrite32be(TMR_ALL, &data->regs->tmr); + data->tz->ops->set_mode(data->tz, THERMAL_DEVICE_ENABLED); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops, + qoriq_tmu_suspend, qoriq_tmu_resume); + +static const struct of_device_id qoriq_tmu_match[] = { + { .compatible = "fsl,qoriq-tmu", }, + {}, +}; + +static struct platform_driver qoriq_tmu = { + .driver = { + .name = "qoriq_thermal", + .pm = &qoriq_tmu_pm_ops, + .of_match_table = qoriq_tmu_match, + }, + .probe = qoriq_tmu_probe, + .remove = qoriq_tmu_remove, +}; +module_platform_driver(qoriq_tmu); + +MODULE_AUTHOR("Jia Hongtao "); +MODULE_DESCRIPTION("Freescale QorIQ Thermal Monitoring Unit driver"); +MODULE_LICENSE("GPL v2");