From patchwork Mon Mar 25 09:34:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 2329531 X-Patchwork-Delegate: rui.zhang@intel.com Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 6BBDB3FD8C for ; Mon, 25 Mar 2013 09:34:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757934Ab3CYJei (ORCPT ); Mon, 25 Mar 2013 05:34:38 -0400 Received: from mail.free-electrons.com ([94.23.35.102]:45550 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755522Ab3CYJeh (ORCPT ); Mon, 25 Mar 2013 05:34:37 -0400 Received: by mail.free-electrons.com (Postfix, from userid 106) id EC6F39EA; Mon, 25 Mar 2013 10:34:35 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.3.2 Received: from localhost (20.222.3.200.ros.express.com.ar [200.3.222.20]) by mail.free-electrons.com (Postfix) with ESMTPSA id 6F7307CF; Mon, 25 Mar 2013 10:34:32 +0100 (CET) Date: Mon, 25 Mar 2013 06:34:32 -0300 From: Ezequiel Garcia To: Sebastian Hesselbarth Cc: linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jason Cooper , Lior Amsalem , Zhang Rui , Nobuhiro Iwamatsu , Thomas Petazzoni , Gregory Clement , Andrew Lunn Subject: Re: [PATCH v2 11/14] thermal: mvebu: Add support for Marvell Dove SoC family Message-ID: <20130325093430.GA2502@localhost> References: <1363991114-4225-1-git-send-email-ezequiel.garcia@free-electrons.com> <1363991114-4225-12-git-send-email-ezequiel.garcia@free-electrons.com> <514D914D.3010105@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <514D914D.3010105@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Hi Sebastian, Thanks again for your testing. On Sat, Mar 23, 2013 at 12:26:05PM +0100, Sebastian Hesselbarth wrote: [...] > > maybe Dove thermal isn't that compatible with the others as you thought. > > Have a look at DOVE_THERMAL_TEMP_OFFSET above, it is 1 while MVEBU_THERMAL_TEMP_OFFSET > is 10. I've tested your patches on Dove and they break thermal. You either need > a dove_get_temp() that uses correct DOVE_THERMAL_TEMP_OFFSET or have it stored > within mvebu_thermal_ops and use it in mvebu_get_temp(). > Can you try replacing this patch (i.e. the whole Dove patch) with the one below? If you confirm this is working, I can send v3 patchset. -------------------------------------8<------------------------------------------- From 8695c7cbdb4922cf0ab7004fd185fea199db6174 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 15 Mar 2013 18:28:41 -0300 Subject: [PATCH] thermal: mvebu: Add support for Marvell Dove SoC family With the infrastructure added in mvebu-thermal to support multiple SoC families, it is now possible to add support for Dove SoC. This patch adds such support taking the implementation from the dove-thermal driver, and then removing it. Signed-off-by: Ezequiel Garcia --- .../devicetree/bindings/thermal/dove-thermal.txt | 18 -- .../devicetree/bindings/thermal/mvebu-thermal.txt | 8 + drivers/thermal/Kconfig | 8 - drivers/thermal/Makefile | 1 - drivers/thermal/dove_thermal.c | 210 -------------------- drivers/thermal/mvebu_thermal.c | 86 ++++++++ 6 files changed, 94 insertions(+), 237 deletions(-) delete mode 100644 Documentation/devicetree/bindings/thermal/dove-thermal.txt delete mode 100644 drivers/thermal/dove_thermal.c diff --git a/Documentation/devicetree/bindings/thermal/dove-thermal.txt b/Documentation/devicetree/bindings/thermal/dove-thermal.txt deleted file mode 100644 index 6f47467..0000000 --- a/Documentation/devicetree/bindings/thermal/dove-thermal.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Dove Thermal - -This driver is for Dove SoCs which contain a thermal sensor. - -Required properties: -- compatible : "marvell,dove-thermal" -- reg : Address range of the thermal registers - -The reg properties should contain two ranges. The first is for the -three Thermal Manager registers, while the second range contains the -Thermal Diode Control Registers. - -Example: - - thermal@10078 { - compatible = "marvell,dove-thermal"; - reg = <0xd001c 0x0c>, <0xd005c 0x08>; - }; diff --git a/Documentation/devicetree/bindings/thermal/mvebu-thermal.txt b/Documentation/devicetree/bindings/thermal/mvebu-thermal.txt index 49d55a9..2c5297a 100644 --- a/Documentation/devicetree/bindings/thermal/mvebu-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/mvebu-thermal.txt @@ -6,6 +6,7 @@ Required properties: marvell,kirkwood-thermal marvell,armadaxp-thermal marvell,armada370-thermal + marvell,dove-thermal - reg: Device's register space. One or two entries are expected, see the examples below. @@ -21,3 +22,10 @@ Kirkwood example: compatible = "marvell,kirkwood-thermal"; reg = <0x10078 0x4>; }; + +Dove example: + + thermal: thermal@d001c { + compatible = "marvell,dove-thermal"; + reg = <0xd001c 0x0c>, <0xd005c 0x08>; + }; diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 74f6b97..237c3e6 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -126,14 +126,6 @@ config EXYNOS_THERMAL_EMUL device directory to support emulation mode. With emulation mode sysfs node, you can manually input temperature to TMU for simulation purpose. -config DOVE_THERMAL - tristate "Temperature sensor on Marvell Dove SoCs" - depends on ARCH_DOVE - depends on OF - help - Support for the Dove thermal sensor driver in the Linux thermal - framework. - config DB8500_THERMAL bool "DB8500 thermal management" depends on ARCH_U8500 diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 40293a1..ddd77f4 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -17,7 +17,6 @@ obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o obj-$(CONFIG_MVEBU_THERMAL) += mvebu_thermal.o obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o -obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c deleted file mode 100644 index ddd73a5..0000000 --- a/drivers/thermal/dove_thermal.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Dove thermal sensor driver - * - * Copyright (C) 2013 Andrew Lunn - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that 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 - -#define DOVE_THERMAL_TEMP_OFFSET 1 -#define DOVE_THERMAL_TEMP_MASK 0x1FF - -/* Dove Thermal Manager Control and Status Register */ -#define PMU_TM_DISABLE_OFFS 0 -#define PMU_TM_DISABLE_MASK (0x1 << PMU_TM_DISABLE_OFFS) - -/* Dove Theraml Diode Control 0 Register */ -#define PMU_TDC0_SW_RST_MASK (0x1 << 1) -#define PMU_TDC0_SEL_VCAL_OFFS 5 -#define PMU_TDC0_SEL_VCAL_MASK (0x3 << PMU_TDC0_SEL_VCAL_OFFS) -#define PMU_TDC0_REF_CAL_CNT_OFFS 11 -#define PMU_TDC0_REF_CAL_CNT_MASK (0x1FF << PMU_TDC0_REF_CAL_CNT_OFFS) -#define PMU_TDC0_AVG_NUM_OFFS 25 -#define PMU_TDC0_AVG_NUM_MASK (0x7 << PMU_TDC0_AVG_NUM_OFFS) - -/* Dove Thermal Diode Control 1 Register */ -#define PMU_TEMP_DIOD_CTRL1_REG 0x04 -#define PMU_TDC1_TEMP_VALID_MASK (0x1 << 10) - -/* Dove Thermal Sensor Dev Structure */ -struct dove_thermal_priv { - void __iomem *sensor; - void __iomem *control; -}; - -static int dove_init_sensor(const struct dove_thermal_priv *priv) -{ - u32 reg; - u32 i; - - /* Configure the Diode Control Register #0 */ - reg = readl_relaxed(priv->control); - - /* Use average of 2 */ - reg &= ~PMU_TDC0_AVG_NUM_MASK; - reg |= (0x1 << PMU_TDC0_AVG_NUM_OFFS); - - /* Reference calibration value */ - reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; - reg |= (0x0F1 << PMU_TDC0_REF_CAL_CNT_OFFS); - - /* Set the high level reference for calibration */ - reg &= ~PMU_TDC0_SEL_VCAL_MASK; - reg |= (0x2 << PMU_TDC0_SEL_VCAL_OFFS); - writel(reg, priv->control); - - /* Reset the sensor */ - reg = readl_relaxed(priv->control); - writel((reg | PMU_TDC0_SW_RST_MASK), priv->control); - writel(reg, priv->control); - - /* Enable the sensor */ - reg = readl_relaxed(priv->sensor); - reg &= ~PMU_TM_DISABLE_MASK; - writel(reg, priv->sensor); - - /* Poll the sensor for the first reading */ - for (i = 0; i < 1000000; i++) { - reg = readl_relaxed(priv->sensor); - if (reg & DOVE_THERMAL_TEMP_MASK) - break; - } - - if (i == 1000000) - return -EIO; - - return 0; -} - -static int dove_get_temp(struct thermal_zone_device *thermal, - unsigned long *temp) -{ - unsigned long reg; - struct dove_thermal_priv *priv = thermal->devdata; - - /* Valid check */ - reg = readl_relaxed(priv->control + PMU_TEMP_DIOD_CTRL1_REG); - if ((reg & PMU_TDC1_TEMP_VALID_MASK) == 0x0) { - dev_err(&thermal->device, - "Temperature sensor reading not valid\n"); - return -EIO; - } - - /* - * Calculate temperature. According to Marvell internal - * documentation the formula for this is: - * Celsius = (322-reg)/1.3625 - */ - reg = readl_relaxed(priv->sensor); - reg = (reg >> DOVE_THERMAL_TEMP_OFFSET) & DOVE_THERMAL_TEMP_MASK; - *temp = ((3220000000UL - (10000000UL * reg)) / 13625); - - return 0; -} - -static struct thermal_zone_device_ops ops = { - .get_temp = dove_get_temp, -}; - -static const struct of_device_id dove_thermal_id_table[] = { - { .compatible = "marvell,dove-thermal" }, - {} -}; - -static int dove_thermal_probe(struct platform_device *pdev) -{ - struct thermal_zone_device *thermal = NULL; - struct dove_thermal_priv *priv; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->sensor = devm_request_and_ioremap(&pdev->dev, res); - if (!priv->sensor) { - dev_err(&pdev->dev, "Failed to request_ioremap memory\n"); - return -EADDRNOTAVAIL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - priv->control = devm_request_and_ioremap(&pdev->dev, res); - if (!priv->control) { - dev_err(&pdev->dev, "Failed to request_ioremap memory\n"); - return -EADDRNOTAVAIL; - } - - ret = dove_init_sensor(priv); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize sensor\n"); - return ret; - } - - thermal = thermal_zone_device_register("dove_thermal", 0, 0, - priv, &ops, NULL, 0, 0); - if (IS_ERR(thermal)) { - dev_err(&pdev->dev, - "Failed to register thermal zone device\n"); - return PTR_ERR(thermal); - } - - platform_set_drvdata(pdev, thermal); - - return 0; -} - -static int dove_thermal_exit(struct platform_device *pdev) -{ - struct thermal_zone_device *dove_thermal = - platform_get_drvdata(pdev); - - thermal_zone_device_unregister(dove_thermal); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -MODULE_DEVICE_TABLE(of, dove_thermal_id_table); - -static struct platform_driver dove_thermal_driver = { - .probe = dove_thermal_probe, - .remove = dove_thermal_exit, - .driver = { - .name = "dove_thermal", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(dove_thermal_id_table), - }, -}; - -module_platform_driver(dove_thermal_driver); - -MODULE_AUTHOR("Andrew Lunn "); -MODULE_DESCRIPTION("Dove thermal driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/thermal/mvebu_thermal.c b/drivers/thermal/mvebu_thermal.c index 60d50c7..b043da3 100644 --- a/drivers/thermal/mvebu_thermal.c +++ b/drivers/thermal/mvebu_thermal.c @@ -2,6 +2,7 @@ * Marvell EBU thermal sensor driver * * Copyright (C) 2013 Marvell + * Copyright (C) 2013 Andrew Lunn * Copyright (C) 2012 Nobuhiro Iwamatsu * * This software is licensed under the terms of the GNU General Public @@ -30,6 +31,9 @@ #define MVEBU_THERMAL_TEMP_OFFSET 10 #define MVEBU_THERMAL_TEMP_MASK 0x1FF +#define DOVE_THERMAL_TEMP_OFFSET 1 +#define DOVE_THERMAL_TEMP_MASK 0x1FF + /* Thermal Manager Control and Status Register */ #define PMU_TDC0_SW_RST_MASK (0x1 << 1) #define PMU_TM_DISABLE_OFFS 0 @@ -38,6 +42,14 @@ #define PMU_TDC0_REF_CAL_CNT_MASK (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS) #define PMU_TDC0_OTF_CAL_MASK (0x1 << 30) #define PMU_TDC0_START_CAL_MASK (0x1 << 25) +#define PMU_TDC0_AVG_NUM_OFFS 25 +#define PMU_TDC0_AVG_NUM_MASK (0x7 << PMU_TDC0_AVG_NUM_OFFS) +#define PMU_TDC0_SEL_VCAL_OFFS 5 +#define PMU_TDC0_SEL_VCAL_MASK (0x3 << PMU_TDC0_SEL_VCAL_OFFS) + +/* Dove Thermal Diode Control 1 Register */ +#define PMU_TEMP_DIOD_CTRL1_REG 0x04 +#define PMU_TDC1_TEMP_VALID_MASK (0x1 << 10) struct mvebu_thermal_ops; @@ -113,6 +125,53 @@ static void armada370_init_sensor(struct mvebu_thermal_priv *priv) mdelay(10); } +static void dove_init_sensor(struct mvebu_thermal_priv *priv) +{ + unsigned long reg; + int i; + + if (!priv->control) + return; + + /* Configure the Diode Control Register #0 */ + reg = readl_relaxed(priv->control); + + /* Use average of 2 */ + reg &= ~PMU_TDC0_AVG_NUM_MASK; + reg |= (0x1 << PMU_TDC0_AVG_NUM_OFFS); + + /* Reference calibration value */ + reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; + reg |= (0x0F1 << PMU_TDC0_REF_CAL_CNT_OFFS); + + /* Set the high level reference for calibration */ + reg &= ~PMU_TDC0_SEL_VCAL_MASK; + reg |= (0x2 << PMU_TDC0_SEL_VCAL_OFFS); + writel(reg, priv->control); + + /* Reset the sensor */ + reg = readl_relaxed(priv->control); + writel((reg | PMU_TDC0_SW_RST_MASK), priv->control); + writel(reg, priv->control); + + /* Enable the sensor */ + reg = readl_relaxed(priv->sensor); + reg &= ~PMU_TM_DISABLE_MASK; + writel(reg, priv->sensor); + + /* + * FIXME: This looks really ugly. Can't we just remove it? + * Poll the sensor for the first reading + */ + for (i = 0; i < 1000000; i++) { + reg = (readl_relaxed(priv->sensor) >> MVEBU_THERMAL_TEMP_OFFSET) + & MVEBU_THERMAL_TEMP_MASK; + if (reg) + break; + } + return; +} + static bool mvebu_is_valid(struct mvebu_thermal_priv *priv) { unsigned long reg = readl_relaxed(priv->sensor); @@ -130,6 +189,15 @@ static unsigned long kirkwood_sensor_temp(struct mvebu_thermal_priv *priv) return (3220000000UL - (10000000UL * reg)) / 13625; } +static unsigned long dove_sensor_temp(struct mvebu_thermal_priv *priv) +{ + unsigned long reg = readl_relaxed(priv->sensor); + + reg = (reg >> DOVE_THERMAL_TEMP_OFFSET) & + DOVE_THERMAL_TEMP_MASK; + return (3220000000UL - (10000000UL * reg)) / 13625; +} + static unsigned long armada_sensor_temp(struct mvebu_thermal_priv *priv) { unsigned long reg = readl_relaxed(priv->sensor); @@ -139,6 +207,13 @@ static unsigned long armada_sensor_temp(struct mvebu_thermal_priv *priv) return (3153000000UL - (10000000UL*reg)) / 13825; } +static bool dove_is_valid(struct mvebu_thermal_priv *priv) +{ + unsigned long reg = + readl_relaxed(priv->control + PMU_TEMP_DIOD_CTRL1_REG); + return reg & PMU_TDC1_TEMP_VALID_MASK; +} + static int mvebu_get_temp(struct thermal_zone_device *thermal, unsigned long *temp) { @@ -164,6 +239,12 @@ static const struct mvebu_thermal_ops kirkwood_ops = { .is_valid = mvebu_is_valid, }; +static const struct mvebu_thermal_ops dove_ops = { + .sensor_temp = dove_sensor_temp, + .is_valid = dove_is_valid, + .init_sensor = dove_init_sensor, +}; + static const struct mvebu_thermal_ops armadaxp_ops = { .sensor_temp = armada_sensor_temp, .init_sensor = armadaxp_init_sensor, @@ -189,6 +270,10 @@ static const struct of_device_id mvebu_thermal_id_table[] = { .data = &armada370_ops, }, { + .compatible = "marvell,dove-thermal", + .data = &dove_ops, + }, + { /* sentinel */ }, }; @@ -267,6 +352,7 @@ static struct platform_driver mvebu_thermal_driver = { module_platform_driver(mvebu_thermal_driver); +MODULE_AUTHOR("Andrew Lunn "); MODULE_AUTHOR("Nobuhiro Iwamatsu "); MODULE_AUTHOR("Ezequiel Garcia "); MODULE_DESCRIPTION("mvebu thermal driver");