From patchwork Mon Apr 8 09:52:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 161934 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp3481559jan; Mon, 8 Apr 2019 02:52:52 -0700 (PDT) X-Google-Smtp-Source: APXvYqz5uzv2YjkaItTBy1EyBK4kQlfe+gSKZ+ZRc4jDdwlTQG/gpLPo4CcbNI+EZUuuYMOqx5Ja X-Received: by 2002:a63:614c:: with SMTP id v73mr27089165pgb.395.1554717172327; Mon, 08 Apr 2019 02:52:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554717172; cv=none; d=google.com; s=arc-20160816; b=mLahTazicH+3bRo8WCw7fV65RbN8fqSVGcKiHT1jHctowQ7KKwNzYpQIJG3LlT0cJR WXyE4vl+WZc6yl+slmWzZi4OiyvW255LSq6NOmH98We+20csjdNEh3E2TUSIT7SALbB7 MvVyxJoopaWS6ZkELEwRUC30F7+47UNfXmUmcIDbqoPTgmcJpa7QYAp/q6frjvUxRzjz YIay2i3MjT29xTf5lb/QLBPEF/nGd26KWqDCvkGBA+QuzDuyb+t+5Fze+gyw/c03RKgl x1wDzRx9pIZT50tdL+CtIcmtdmTG9bcqd21LwbNTni1/RSdjgQGeYi/2ynDsHHeAG3cQ PiXw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject:cc :to:from:dkim-signature; bh=FLh29FmXXYCgkrmxYwSkJoF9CjtzyPpbJugmeYCvrwI=; b=QUmbbc95tHYb/nxjkJSeppslGshgrG4mMzG95tgCtzxPyt4O28ieKMrSVq5maqsY+z EMBIGt4aig+nOv2L9Zo5ct3Vco4n0KVdfBpV84WR63K25Z2r7dsqQE2WVD55rj4i6ZN5 0bOdYbHv6Gby3Xf72nsYCC6U+lOejj7Km+/8lzsRT8g1rmgUCJOjKitTDbkj0OR7X70s 45UDgjJfEWKIBMxgH/lZ9GW+XT0mBF3ztBPbmo9I11aWVSGixrVKnmgxYz4E1DNKtvNZ QFRb7vDUE3zqHN86fWbasy9YkZpgGPloxfGvC/Hfc7Hz+tiu6IZ8D/Vwt5P1bYSfEvO9 MNsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=ceC6C+oa; spf=pass (google.com: best guess record for domain of linux-omap-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-omap-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t9si14970763pgp.273.2019.04.08.02.52.52; Mon, 08 Apr 2019 02:52:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-omap-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=ceC6C+oa; spf=pass (google.com: best guess record for domain of linux-omap-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-omap-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725881AbfDHJwv (ORCPT + 5 others); Mon, 8 Apr 2019 05:52:51 -0400 Received: from lelv0142.ext.ti.com ([198.47.23.249]:50258 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725933AbfDHJwv (ORCPT ); Mon, 8 Apr 2019 05:52:51 -0400 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id x389qjIf092225; Mon, 8 Apr 2019 04:52:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554717165; bh=FLh29FmXXYCgkrmxYwSkJoF9CjtzyPpbJugmeYCvrwI=; h=From:To:CC:Subject:Date; b=ceC6C+oal5CjYtoH3jN45qFNGHc7UkTZ/Zf596aV+lpnlPpZhtCFXQ4dRYbbGTQS9 bAbQvTTWxm+m4nEykXXC8ojSWPb4oFohrO7JRuj3M7Z0+67ksF4cPxn1NzzDrZ86tN wEhqSa4+t698NCuPgqDz20dRo6swfe8R3ETNUzB4= Received: from DLEE104.ent.ti.com (dlee104.ent.ti.com [157.170.170.34]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x389qj0u021135 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 8 Apr 2019 04:52:45 -0500 Received: from DLEE104.ent.ti.com (157.170.170.34) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Mon, 8 Apr 2019 04:52:44 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Mon, 8 Apr 2019 04:52:44 -0500 Received: from lta0400828d.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id x389qgbC016970; Mon, 8 Apr 2019 04:52:42 -0500 From: Roger Quadros To: CC: , , , , , Roger Quadros Subject: [PATCH v2] bus: ti-sysc: Add generic enable/disable functions Date: Mon, 8 Apr 2019 12:52:39 +0300 Message-ID: <20190408095239.30378-1-rogerq@ti.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org For non legacy cases, add generic sysc_enable_module() and sysc_disable_module() functions. Signed-off-by: Roger Quadros --- Boot tested on - beagle-x15 (AM5728 GP EVM) - AM571x IDK - DRA7 EVM Changelog: v2: - Add helper to get best idle mode. - Add comment about not preventing clockdomain autoidle during enable/disable. - Omit PRU-ICSS specific handling. PRU-ICSS moudle can re-use omap4-simple. The STANDBY_INIT and SUB_MWAIT bits are specific to PRUSS application usage and should be managed by the PRUSS driver. cheers, -roger drivers/bus/ti-sysc.c | 129 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 5c8796276828..c37b3be1e3e2 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -793,6 +793,127 @@ static void sysc_show_registers(struct sysc *ddata) buf); } +#define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1) + +static int sysc_enable_module(struct device *dev) +{ + struct sysc *ddata; + const struct sysc_regbits *regbits; + u32 reg, idlemodes, best_mode; + + ddata = dev_get_drvdata(dev); + if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) + return 0; + + /* + * TODO: Need to prevent clockdomain autoidle? + * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c + */ + + regbits = ddata->cap->regbits; + reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + + /* Set SIDLE mode */ + idlemodes = ddata->cfg.sidlemodes; + if (!idlemodes || regbits->sidle_shift < 0) + goto set_midle; + + best_mode = fls(ddata->cfg.sidlemodes) - 1; + if (best_mode > SYSC_IDLE_MASK) { + dev_err(dev, "%s: invalid sidlemode\n", __func__); + return -EINVAL; + } + + reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); + reg |= best_mode << regbits->sidle_shift; + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + +set_midle: + /* Set MIDLE mode */ + idlemodes = ddata->cfg.midlemodes; + if (!idlemodes || regbits->midle_shift < 0) + return 0; + + best_mode = fls(ddata->cfg.midlemodes) - 1; + if (best_mode > SYSC_IDLE_MASK) { + dev_err(dev, "%s: invalid midlemode\n", __func__); + return -EINVAL; + } + + reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift); + reg |= best_mode << regbits->midle_shift; + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + + return 0; +} + +static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode) +{ + if (idlemodes & BIT(SYSC_IDLE_SMART_WKUP)) + *best_mode = SYSC_IDLE_SMART_WKUP; + else if (idlemodes & BIT(SYSC_IDLE_SMART)) + *best_mode = SYSC_IDLE_SMART; + else if (idlemodes & SYSC_IDLE_FORCE) + *best_mode = SYSC_IDLE_FORCE; + else + return -EINVAL; + + return 0; +} + +static int sysc_disable_module(struct device *dev) +{ + struct sysc *ddata; + const struct sysc_regbits *regbits; + u32 reg, idlemodes, best_mode; + int ret; + + ddata = dev_get_drvdata(dev); + if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) + return 0; + + /* + * TODO: Need to prevent clockdomain autoidle? + * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c + */ + + regbits = ddata->cap->regbits; + reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); + + /* Set MIDLE mode */ + idlemodes = ddata->cfg.midlemodes; + if (!idlemodes || regbits->midle_shift < 0) + goto set_sidle; + + ret = sysc_best_idle_mode(idlemodes, &best_mode); + if (ret) { + dev_err(dev, "%s: invalid midlemode\n", __func__); + return ret; + } + + reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift); + reg |= best_mode << regbits->midle_shift; + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + +set_sidle: + /* Set SIDLE mode */ + idlemodes = ddata->cfg.sidlemodes; + if (!idlemodes || regbits->sidle_shift < 0) + return 0; + + ret = sysc_best_idle_mode(idlemodes, &best_mode); + if (ret) { + dev_err(dev, "%s: invalid sidlemode\n", __func__); + return ret; + } + + reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); + reg |= best_mode << regbits->sidle_shift; + sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); + + return 0; +} + static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev, struct sysc *ddata) { @@ -849,6 +970,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev) error = sysc_runtime_suspend_legacy(dev, ddata); if (error) return error; + } else { + error = sysc_disable_module(dev); + if (error) + return error; } sysc_disable_main_clocks(ddata); @@ -885,6 +1010,10 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) error = sysc_runtime_resume_legacy(dev, ddata); if (error) goto err_main_clocks; + } else { + error = sysc_enable_module(dev); + if (error) + goto err_main_clocks; } ddata->enabled = true;