From patchwork Sun May 20 09:26:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Kaneko X-Patchwork-Id: 10413321 X-Patchwork-Delegate: eduardo.valentin@ti.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 910AF6053B for ; Sun, 20 May 2018 09:26:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 828332871C for ; Sun, 20 May 2018 09:26:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6CF052872C; Sun, 20 May 2018 09:26:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFE9128720 for ; Sun, 20 May 2018 09:26:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751122AbeETJ0d (ORCPT ); Sun, 20 May 2018 05:26:33 -0400 Received: from mail-pl0-f67.google.com ([209.85.160.67]:44737 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750925AbeETJ0b (ORCPT ); Sun, 20 May 2018 05:26:31 -0400 Received: by mail-pl0-f67.google.com with SMTP id e6-v6so7022317plt.11; Sun, 20 May 2018 02:26:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2c8p71Zi/uEIj9kP4d1h+1MLBMw+55mmTOLLIcpzKgU=; b=Wk1I/jNbsejiJVbM3LIixRebVSNdkiMxJX/tv8ybZEB9pTXVjzj9JukwMMQFVuYmEW YuuWHhnmxSoCTvvQwUACt4iXrmRImjsb+lPWfu5r3QyJybzKfGti1Vjl/u+fFnRkpO6i 0iZu8Fur5TKu3yY/wUdCDzTc5RFafnZEYIfv6BlkdQuqZ+91K6BeLxYmBgwHOJBpYjwu RFjgdjMHlO25pShBrTFa4W189VgpfaKTXqojcilD4dgl5Rv+pB6J5iFl5x1ZOOocOsys okN66lB/P5H1xcaLoYS6SXQqPO+P651jcJrHRhkKPhF9DLBhTnae6CpEAEvnZlxcSSWl 9WCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2c8p71Zi/uEIj9kP4d1h+1MLBMw+55mmTOLLIcpzKgU=; b=VMeTofGLcVJEC2oK27KZwiLJ68wP+4zVRpb1KXO7eljYlMLPhBGNph+lkyL/Zdj2tc zXOjps4yc2jq1zyd18ed+EtumyUyxmQPjJkHH0l3gfhZhC+z218oNPsb97KGK/ed/4lg dQ/7ODN6XbRB0rfs6AZj+KZhG2ZeaZPd5t/Cs3cRAxFAlWRlIXobtb5fRxyErGM/5GQi 57g6jHS/YJovJ0+A7iEnOZSxQFHvcMje56m89BBBTnyz6PE1ugP7BDQIN0CBYweldf/m lPV2hvoDrRwyQVYHP7iCn/2Y6aIQsP2JMBBGETK9v27lVOZxjgufv1oihxh3/+tO0Kp7 qDMA== X-Gm-Message-State: ALKqPweF+qc2FBGLXjdesa79X9k9wLfb32+tlpyhA38FD8gzwvpyagIz 0KkjzKNKMyyQygrSscQhmh7SyA== X-Google-Smtp-Source: AB8JxZpMbY9igRJt8nkE/X5oMq8GKtNB0dlwVm7yjY6l2LgtdsJWte2ky3piKhgPxYu3hV93uHTEbQ== X-Received: by 2002:a17:902:7402:: with SMTP id g2-v6mr16608363pll.246.1526808390654; Sun, 20 May 2018 02:26:30 -0700 (PDT) Received: from macc.flets-east.jp (p6016112-ipngn3302marunouchi.tokyo.ocn.ne.jp. [180.23.146.112]) by smtp.gmail.com with ESMTPSA id r90-v6sm29692182pfg.122.2018.05.20.02.26.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 20 May 2018 02:26:30 -0700 (PDT) From: Yoshihiro Kaneko To: linux-renesas-soc@vger.kernel.org Cc: Zhang Rui , Eduardo Valentin , Rob Herring , Simon Horman , Magnus Damm , linux-pm@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v4 1/3] thermal: rcar_thermal: add r8a77995 support Date: Sun, 20 May 2018 18:26:17 +0900 Message-Id: <1526808379-3850-2-git-send-email-ykaneko0929@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526808379-3850-1-git-send-email-ykaneko0929@gmail.com> References: <1526808379-3850-1-git-send-email-ykaneko0929@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add support for R-Car D3 (r8a77995) thermal sensor. Signed-off-by: Yoshihiro Kaneko Tested-by: Ulrich Hecht Reviewed-by: Simon Horman --- drivers/thermal/rcar_thermal.c | 158 ++++++++++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 32 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 73e5fee..45fb284 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -58,10 +58,47 @@ struct rcar_thermal_common { spinlock_t lock; }; +struct rcar_thermal_chip { + unsigned int use_of_thermal : 1; + unsigned int has_filonoff : 1; + unsigned int irq_per_ch : 1; + unsigned int needs_suspend_resume : 1; + unsigned int nirqs; +}; + +static const struct rcar_thermal_chip rcar_thermal = { + .use_of_thermal = 0, + .has_filonoff = 1, + .irq_per_ch = 0, + .needs_suspend_resume = 0, + .nirqs = 1, +}; + +static const struct rcar_thermal_chip rcar_gen2_thermal = { + .use_of_thermal = 1, + .has_filonoff = 1, + .irq_per_ch = 0, + .needs_suspend_resume = 0, + .nirqs = 1, +}; + +static const struct rcar_thermal_chip rcar_gen3_thermal = { + .use_of_thermal = 1, + .has_filonoff = 0, + .irq_per_ch = 1, + .needs_suspend_resume = 1, + /* + * The Gen3 chip has 3 interrupts, but this driver uses only 2 + * interrupts to detect a temperature change, rise or fall. + */ + .nirqs = 2, +}; + struct rcar_thermal_priv { void __iomem *base; struct rcar_thermal_common *common; struct thermal_zone_device *zone; + const struct rcar_thermal_chip *chip; struct delayed_work work; struct mutex lock; struct list_head list; @@ -77,13 +114,20 @@ struct rcar_thermal_priv { #define rcar_priv_to_dev(priv) ((priv)->common->dev) #define rcar_has_irq_support(priv) ((priv)->common->base) #define rcar_id_to_shift(priv) ((priv)->id * 8) -#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev)) -#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL) -#define USE_OF_THERMAL 1 static const struct of_device_id rcar_thermal_dt_ids[] = { - { .compatible = "renesas,rcar-thermal", }, - { .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL }, + { + .compatible = "renesas,rcar-thermal", + .data = &rcar_thermal, + }, + { + .compatible = "renesas,rcar-gen2-thermal", + .data = &rcar_gen2_thermal, + }, + { + .compatible = "renesas,thermal-r8a77995", + .data = &rcar_gen3_thermal, + }, {}, }; MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); @@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) * enable IRQ */ if (rcar_has_irq_support(priv)) { - rcar_thermal_write(priv, FILONOFF, 0); + if (priv->chip->has_filonoff) + rcar_thermal_write(priv, FILONOFF, 0); /* enable Rising/Falling edge interrupt */ rcar_thermal_write(priv, POSNEG, 0x1); @@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev) rcar_thermal_for_each_priv(priv, common) { rcar_thermal_irq_disable(priv); - if (rcar_use_of_thermal(dev)) + if (priv->chip->use_of_thermal) thermal_remove_hwmon_sysfs(priv->zone); else thermal_zone_device_unregister(priv->zone); @@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) struct rcar_thermal_priv *priv; struct device *dev = &pdev->dev; struct resource *res, *irq; + const struct rcar_thermal_chip *chip = of_device_get_match_data(dev); int mres = 0; int i; int ret = -ENODEV; @@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev); - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq) { - /* - * platform has IRQ support. - * Then, driver uses common registers - * rcar_has_irq_support() will be enabled - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); - common->base = devm_ioremap_resource(dev, res); - if (IS_ERR(common->base)) - return PTR_ERR(common->base); + for (i = 0; i < chip->nirqs; i++) { + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) + continue; + if (!common->base) { + /* + * platform has IRQ support. + * Then, driver uses common registers + * rcar_has_irq_support() will be enabled + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, + mres++); + common->base = devm_ioremap_resource(dev, res); + if (IS_ERR(common->base)) + return PTR_ERR(common->base); + + idle = 0; /* polling delay is not needed */ + } - idle = 0; /* polling delay is not needed */ + ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, + IRQF_SHARED, dev_name(dev), common); + if (ret) { + dev_err(dev, "irq request failed\n "); + goto error_unregister; + } + + /* update ENR bits */ + if (chip->irq_per_ch) + enr_bits |= 1 << i; } for (i = 0;; i++) { @@ -491,6 +553,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) priv->common = common; priv->id = i; + priv->chip = chip; mutex_init(&priv->lock); INIT_LIST_HEAD(&priv->list); INIT_DELAYED_WORK(&priv->work, rcar_thermal_work); @@ -498,7 +561,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) if (ret < 0) goto error_unregister; - if (rcar_use_of_thermal(dev)) + if (chip->use_of_thermal) priv->zone = devm_thermal_zone_of_sensor_register( dev, i, priv, &rcar_thermal_zone_of_ops); @@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_unregister; } - if (rcar_use_of_thermal(dev)) { + if (chip->use_of_thermal) { /* * thermal_zone doesn't enable hwmon as default, * but, enable it here to keep compatible @@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev) list_move_tail(&priv->list, &common->head); /* update ENR bits */ - enr_bits |= 3 << (i * 8); + if (!chip->irq_per_ch) + enr_bits |= 3 << (i * 8); } - /* enable temperature comparation */ - if (irq) { - ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, - dev_name(dev), common); - if (ret) { - dev_err(dev, "irq request failed\n "); - goto error_unregister; - } - + if (enr_bits) rcar_thermal_common_write(common, ENR, enr_bits); - } dev_info(dev, "%d sensor probed\n", i); @@ -556,9 +611,48 @@ static int rcar_thermal_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_PM_SLEEP +static int rcar_thermal_suspend(struct device *dev) +{ + struct rcar_thermal_common *common = dev_get_drvdata(dev); + struct rcar_thermal_priv *priv = list_first_entry(&common->head, + typeof(*priv), list); + + if (priv->chip->needs_suspend_resume) { + rcar_thermal_common_write(common, ENR, 0); + rcar_thermal_irq_disable(priv); + rcar_thermal_bset(priv, THSCR, CPCTL, 0); + } + + return 0; +} + +static int rcar_thermal_resume(struct device *dev) +{ + struct rcar_thermal_common *common = dev_get_drvdata(dev); + struct rcar_thermal_priv *priv = list_first_entry(&common->head, + typeof(*priv), list); + int ret; + + if (priv->chip->needs_suspend_resume) { + ret = rcar_thermal_update_temp(priv); + if (ret < 0) + return ret; + rcar_thermal_irq_enable(priv); + rcar_thermal_common_write(common, ENR, 0x03); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend, + rcar_thermal_resume); + static struct platform_driver rcar_thermal_driver = { .driver = { .name = "rcar_thermal", + .pm = &rcar_thermal_pm_ops, .of_match_table = rcar_thermal_dt_ids, }, .probe = rcar_thermal_probe,