From patchwork Mon Sep 19 03:36:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Barry Song <21cnbao@gmail.com> X-Patchwork-Id: 4166 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 89AFA23F6E for ; Mon, 19 Sep 2011 03:37:00 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 4F176A18456 for ; Mon, 19 Sep 2011 03:37:00 +0000 (UTC) Received: by fxe23 with SMTP id 23so4966361fxe.11 for ; Sun, 18 Sep 2011 20:37:00 -0700 (PDT) Received: by 10.223.5.76 with SMTP id 12mr4311603fau.103.1316403420046; Sun, 18 Sep 2011 20:37:00 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.18.198 with SMTP id y6cs21423lad; Sun, 18 Sep 2011 20:36:59 -0700 (PDT) Received: by 10.204.141.135 with SMTP id m7mr1170032bku.42.1316403418003; Sun, 18 Sep 2011 20:36:58 -0700 (PDT) Received: from mail-bw0-f50.google.com (mail-bw0-f50.google.com [209.85.214.50]) by mx.google.com with ESMTPS id m8si8947881bke.139.2011.09.18.20.36.57 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 18 Sep 2011 20:36:57 -0700 (PDT) Received-SPF: pass (google.com: domain of 21cnbao@gmail.com designates 209.85.214.50 as permitted sender) client-ip=209.85.214.50; Authentication-Results: mx.google.com; spf=pass (google.com: domain of 21cnbao@gmail.com designates 209.85.214.50 as permitted sender) smtp.mail=21cnbao@gmail.com; dkim=pass (test mode) header.i=@gmail.com Received: by bkbzt19 with SMTP id zt19so23346763bkb.37 for ; Sun, 18 Sep 2011 20:36:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=uUkMNa+5BY/WNHX51Dm4P0O3720FdTf856XuF97xH/8=; b=pKAkdCJZnQgb8SEUHBHrbqwa3XdJnI76f2IXSErdPUsYkldOMCi13+zAXIfocVpiFZ zlpfZBD+5SpaqibfehMP1qkmz4bI88F/nFMRW9K9HGweuifu3ZJx8uUtK0z3MlLSnlaA LtoJxSZY+yM4GWd0Z33AyLj6WCgoxW8P/G8w0= Received: by 10.204.154.139 with SMTP id o11mr1176446bkw.181.1316403417129; Sun, 18 Sep 2011 20:36:57 -0700 (PDT) MIME-Version: 1.0 Received: by 10.204.36.139 with HTTP; Sun, 18 Sep 2011 20:36:37 -0700 (PDT) In-Reply-To: <20110917145614.GG16381@n2100.arm.linux.org.uk> References: <1315288107-14689-1-git-send-email-shawn.guo@linaro.org> <1315288107-14689-2-git-send-email-shawn.guo@linaro.org> <20110914084237.GC6267@n2100.arm.linux.org.uk> <20110915013937.GE1488@S2100-06.ap.freescale.net> <20110915083248.GG6267@n2100.arm.linux.org.uk> <20110917104518.GD16381@n2100.arm.linux.org.uk> <20110917145614.GG16381@n2100.arm.linux.org.uk> From: Barry Song <21cnbao@gmail.com> Date: Mon, 19 Sep 2011 11:36:37 +0800 Message-ID: Subject: Re: [PATCH v2 1/2] ARM: cache-l2x0: remove __init annotation from initialization functions To: Russell King - ARM Linux Cc: Shawn Guo , Shawn Guo , linux-arm-kernel@lists.infradead.org, patches@linaro.org 2011/9/17 Russell King - ARM Linux : > On Sat, Sep 17, 2011 at 10:41:58PM +0800, Barry Song wrote: >> for aux ctrl, it is really simple. but how about the following: >> >>  393 static void __init pl310_of_setup(const struct device_node *np, >>  394                                   __u32 *aux_val, __u32 *aux_mask) >>  395 { >>  396         u32 data[3] = { 0, 0, 0 }; >>  397         u32 tag[3] = { 0, 0, 0 }; >>  398         u32 filter[2] = { 0, 0 }; >>  399 >>  400         of_property_read_u32_array(np, "arm,tag-latency", tag, >> ARRAY_SIZE(tag)); >>  401         if (tag[0] && tag[1] && tag[2]) >>  402                 writel_relaxed( >>  403                         ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | >>  404                         ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | >>  405                         ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), >>  406                         l2x0_base + L2X0_TAG_LATENCY_CTRL); >>  407 >>  408         of_property_read_u32_array(np, "arm,data-latency", >>  409                                    data, ARRAY_SIZE(data)); >>  410         if (data[0] && data[1] && data[2]) >>  411                 writel_relaxed( >>  412                         ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | >>  413                         ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | >>  414                         ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), >>  415                         l2x0_base + L2X0_DATA_LATENCY_CTRL); >>  416 >>  417         of_property_read_u32_array(np, "arm,filter-ranges", >>  418                                    filter, ARRAY_SIZE(filter)); >>  419         if (filter[0] && filter[1]) { >>  420                 writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), >>  421                                l2x0_base + L2X0_ADDR_FILTER_END); >>  422                 writel_relaxed((filter[0] & ~(SZ_1M - 1)) | >> L2X0_ADDR_FILTER_EN, >>  423                                l2x0_base + L2X0_ADDR_FILTER_START); >>  424         } >>  425 } >> >> not all l2 have all these registers. for example, it seems only prima2 >> has L2X0_ADDR_FILTER_START/END by now. and only some platforms set >> latency too. > > Save them as normal.  If there aren't the values in DT, read them in the > above functions and save the value.  Then... > >> > and we can do a similar thing when initializing the PL310 and resuming >> > the PL310 - add a new outer_cache callback called 'resume' to be pointed >> > at the relevant resume function which knows which registers to restore. > > Do that. > >> in my last reply, i also suggested this: >> struct outer_cache_fns { >>        void (*inv_range)(unsigned long, unsigned long); >>        void (*clean_range)(unsigned long, unsigned long); >>        void (*flush_range)(unsigned long, unsigned long); >>        void (*flush_all)(void); >>        void (*inv_all)(void); >>        void (*disable)(void); >> #ifdef CONFIG_OUTER_CACHE_SYNC >>        void (*sync)(void); >> #endif >>        void (*set_debug)(unsigned long); >>  +       void (*save)(void); >>  +      void (*restore)(void); >> }; >> >> but it looks we only need resume since we can save all in init phase: > > Correct. Do you think the following is what you want? { @@ -280,7 +288,7 @@ static void l2x0_disable(void) spin_unlock_irqrestore(&l2x0_lock, flags); } -static void __init l2x0_unlock(__u32 cache_id) +static void l2x0_unlock(__u32 cache_id) { int lockregs; int i; @@ -356,6 +364,8 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) /* l2x0 controller is disabled */ writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); + l2x0_aux_ctrl = aux; + l2x0_inv_all(); /* enable L2X0 */ @@ -445,18 +455,64 @@ static void __init pl310_of_setup(const struct device_node *np, } } +static void __init pl310_save(void) +{ + l2x0_tag_latency = readl_relaxed(l2x0_base + L2X0_TAG_LATENCY_CTRL); + l2x0_data_latency = readl_relaxed(l2x0_base + L2X0_DATA_LATENCY_CTRL); + l2x0_filter_end = readl_relaxed(l2x0_base + L2X0_ADDR_FILTER_END); + l2x0_filter_start = readl_relaxed(l2x0_base + L2X0_ADDR_FILTER_START); +} + +static void l2x0_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + /* restore aux ctrl and enable l2 */ + l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); + + writel_relaxed(l2x0_aux_ctrl, l2x0_base + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + writel_relaxed(1, l2x0_base + L2X0_CTRL); + } +} + +static void pl310_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { + /* restore pl310 setup */ + writel_relaxed(l2x0_tag_latency, l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel_relaxed(l2x0_data_latency, l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(l2x0_filter_end, l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed(l2x0_filter_start, l2x0_base + L2X0_ADDR_FILTER_START); + } + + l2x0_resume(); +} + +static const struct l2x0_of_data pl310_data = { + pl310_of_setup, + pl310_save, + pl310_resume, +}; + +static const struct l2x0_of_data l2x0_data = { + l2x0_of_setup, + NULL, + l2x0_resume, +}; + static const struct of_device_id l2x0_ids[] __initconst = { - { .compatible = "arm,pl310-cache", .data = pl310_of_setup }, - { .compatible = "arm,l220-cache", .data = l2x0_of_setup }, - { .compatible = "arm,l210-cache", .data = l2x0_of_setup }, + { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, + { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, + { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data }, {} }; int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) { struct device_node *np; - void (*l2_setup)(const struct device_node *np, - __u32 *aux_val, __u32 *aux_mask); + struct l2x0_of_data *data; np = of_find_matching_node(NULL, l2x0_ids); if (!np) @@ -465,13 +521,20 @@ int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) if (!l2x0_base) return -ENOMEM; + data = of_match_node(l2x0_ids, np)->data; + /* L2 configuration can only be changed if the cache is disabled */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { - l2_setup = of_match_node(l2x0_ids, np)->data; - if (l2_setup) - l2_setup(np, &aux_val, &aux_mask); + if (data->setup) + data->setup(np, &aux_val, &aux_mask); } + + if (data->save) + data->save(); + l2x0_init(l2x0_base, aux_val, aux_mask); + + outer_cache.resume = data->resume; return 0; } #endif -barry diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index d838743..53426c6 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -34,6 +34,7 @@ struct outer_cache_fns { void (*sync)(void); #endif void (*set_debug)(unsigned long); + void (*resume)(void); }; #ifdef CONFIG_OUTER_CACHE @@ -74,6 +75,12 @@ static inline void outer_disable(void) outer_cache.disable(); } +static inline void outer_resume(void) +{ + if (outer_cache.resume) + outer_cache.resume(); +} + #else static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 0d85d22..4722707 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -32,6 +32,14 @@ static void __iomem *l2x0_base; static DEFINE_SPINLOCK(l2x0_lock); static uint32_t l2x0_way_mask; /* Bitmask of active ways */ static uint32_t l2x0_size; +static u32 l2x0_aux_ctrl; +static u32 l2x0_tag_latency, l2x0_data_latency, l2x0_filter_start, l2x0_filter_end; + +struct l2x0_of_data { + void (*setup)(const struct device_node *,__u32 *, __u32 *); + void (*save)(void); + void (*resume)(void); +}; static inline void cache_wait_way(void __iomem *reg, unsigned long mask)