From patchwork Fri Jul 17 14:24:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Magnus Damm X-Patchwork-Id: 36018 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6HET0qo002287 for ; Fri, 17 Jul 2009 14:29:00 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757613AbZGQO25 (ORCPT ); Fri, 17 Jul 2009 10:28:57 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S933208AbZGQO25 (ORCPT ); Fri, 17 Jul 2009 10:28:57 -0400 Received: from mail-yx0-f184.google.com ([209.85.210.184]:62633 "EHLO mail-yx0-f184.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757613AbZGQO24 (ORCPT ); Fri, 17 Jul 2009 10:28:56 -0400 Received: by yxe14 with SMTP id 14so1528445yxe.33 for ; Fri, 17 Jul 2009 07:28:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:date:message-id :subject; bh=4sosXwwSGb38mJeZsHC03b3cLixU1GUzFUwV4QYwTeY=; b=gQXBEtOl5MdTfnPQ8gx385wxkpi7qpumi+IOLqTPgutevIm8LZJg83tw1tb7t+PnPc i2qsYNUZP5x7wrh3512P85GpQbBf+3c7G9sps/ZV1F8ywtiNLaXJiMabxK/fDpPVBqOG cTBmbZTmLlvxZTaKNnL8vUfv4/SaIFVb8t4hM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:date:message-id:subject; b=tAefXdCeqm78bIOTZja3Uup8w0On4lVN5SEWqdS5iriV3E+sZOD9NmXppB+Dj2hrcq TiEmjO495AGuAFGz1X92RccM3CtsIZNh8Yzjrn7Aqp1GXjfQ+KSUkya4YQCjCNCCL7kD 0LvOtkR+xZAnMRs1Ik+lP/+gvBdnfVV2h6SE4= Received: by 10.100.154.14 with SMTP id b14mr1584259ane.142.1247840935037; Fri, 17 Jul 2009 07:28:55 -0700 (PDT) Received: from rx1.opensource.se ([66.46.77.130]) by mx.google.com with ESMTPS id c23sm377247ana.8.2009.07.17.07.28.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 17 Jul 2009 07:28:54 -0700 (PDT) From: Magnus Damm To: linux-sh@vger.kernel.org Cc: Magnus Damm , lethal@linux-sh.org Date: Fri, 17 Jul 2009 23:24:55 +0900 Message-Id: <20090717142455.14866.58859.sendpatchset@rx1.opensource.se> Subject: [PATCH] sh: Add support for multiple hwblk counters Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org From: Magnus Damm Extend the SuperH hwblk code to support more than one counter. Contains ground work for the future Runtime PM implementation. Signed-off-by: Magnus Damm --- Previously posted together with the Runtime PM prototype. arch/sh/include/asm/hwblk.h | 13 +++++- arch/sh/kernel/cpu/hwblk.c | 69 +++++++++++++++++++++----------- arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c | 4 - 3 files changed, 60 insertions(+), 26 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- 0001/arch/sh/include/asm/hwblk.h +++ work/arch/sh/include/asm/hwblk.h 2009-07-09 18:38:04.000000000 +0900 @@ -4,6 +4,9 @@ #include #include +#define HWBLK_CNT_USAGE 0 +#define HWBLK_CNT_NR 1 + #define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */ #define HWBLK_AREA(_flags, _parent) \ @@ -13,7 +16,7 @@ } struct hwblk_area { - unsigned long cnt; + int cnt[HWBLK_CNT_NR]; unsigned char parent; unsigned char flags; }; @@ -29,7 +32,7 @@ struct hwblk { void __iomem *mstp; unsigned char bit; unsigned char area; - unsigned long cnt; + int cnt[HWBLK_CNT_NR]; }; struct hwblk_info { @@ -46,6 +49,12 @@ int arch_hwblk_sleep_mode(void); int hwblk_register(struct hwblk_info *info); int hwblk_init(void); +void hwblk_enable(struct hwblk_info *info, int hwblk); +void hwblk_disable(struct hwblk_info *info, int hwblk); + +void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt); +void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt); + /* allow clocks to enable and disable hardware blocks */ #define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \ { \ --- 0001/arch/sh/kernel/cpu/hwblk.c +++ work/arch/sh/kernel/cpu/hwblk.c 2009-07-09 18:34:46.000000000 +0900 @@ -9,38 +9,64 @@ static DEFINE_SPINLOCK(hwblk_lock); -static void hwblk_area_inc(struct hwblk_info *info, int area) +static void hwblk_area_mod_cnt(struct hwblk_info *info, + int area, int counter, int value, int goal) { struct hwblk_area *hap = info->areas + area; - hap->cnt++; - if (hap->cnt == 1) - if (hap->flags & HWBLK_AREA_FLAG_PARENT) - hwblk_area_inc(info, hap->parent); + hap->cnt[counter] += value; + + if (hap->cnt[counter] != goal) + return; + + if (hap->flags & HWBLK_AREA_FLAG_PARENT) + hwblk_area_mod_cnt(info, hap->parent, counter, value, goal); } -static void hwblk_area_dec(struct hwblk_info *info, int area) + +static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk, + int counter, int value, int goal) { - struct hwblk_area *hap = info->areas + area; + struct hwblk *hp = info->hwblks + hwblk; + + hp->cnt[counter] += value; + if (hp->cnt[counter] == goal) + hwblk_area_mod_cnt(info, hp->area, counter, value, goal); - if (hap->cnt == 1) - if (hap->flags & HWBLK_AREA_FLAG_PARENT) - hwblk_area_dec(info, hap->parent); - hap->cnt--; + return hp->cnt[counter]; } -static void hwblk_enable(struct hwblk_info *info, int hwblk) +static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk, + int counter, int value, int goal) +{ + unsigned long flags; + + spin_lock_irqsave(&hwblk_lock, flags); + __hwblk_mod_cnt(info, hwblk, counter, value, goal); + spin_unlock_irqrestore(&hwblk_lock, flags); +} + +void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter) +{ + hwblk_mod_cnt(info, hwblk, counter, 1, 1); +} + +void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter) +{ + hwblk_mod_cnt(info, hwblk, counter, -1, 0); +} + +void hwblk_enable(struct hwblk_info *info, int hwblk) { struct hwblk *hp = info->hwblks + hwblk; unsigned long tmp; unsigned long flags; + int ret; spin_lock_irqsave(&hwblk_lock, flags); - hp->cnt++; - if (hp->cnt == 1) { - hwblk_area_inc(info, hp->area); - + ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1); + if (ret == 1) { tmp = __raw_readl(hp->mstp); tmp &= ~(1 << hp->bit); __raw_writel(tmp, hp->mstp); @@ -49,27 +75,26 @@ static void hwblk_enable(struct hwblk_in spin_unlock_irqrestore(&hwblk_lock, flags); } -static void hwblk_disable(struct hwblk_info *info, int hwblk) +void hwblk_disable(struct hwblk_info *info, int hwblk) { struct hwblk *hp = info->hwblks + hwblk; unsigned long tmp; unsigned long flags; + int ret; spin_lock_irqsave(&hwblk_lock, flags); - if (hp->cnt == 1) { - hwblk_area_dec(info, hp->area); - + ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0); + if (ret == 0) { tmp = __raw_readl(hp->mstp); tmp |= 1 << hp->bit; __raw_writel(tmp, hp->mstp); } - hp->cnt--; spin_unlock_irqrestore(&hwblk_lock, flags); } -static struct hwblk_info *hwblk_info; +struct hwblk_info *hwblk_info; int __init hwblk_register(struct hwblk_info *info) { --- 0001/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c +++ work/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c 2009-07-09 18:38:48.000000000 +0900 @@ -91,10 +91,10 @@ static struct hwblk_info sh7722_hwblk_in int arch_hwblk_sleep_mode(void) { - if (!sh7722_hwblk_area[CORE_AREA].cnt) + if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) return SUSP_SH_STANDBY | SUSP_SH_SF; - if (!sh7722_hwblk_area[CORE_AREA_BM].cnt) + if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) return SUSP_SH_SLEEP | SUSP_SH_SF; return SUSP_SH_SLEEP;