From patchwork Wed Oct 13 14:21:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Mundt X-Patchwork-Id: 250751 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9DELLDr007495 for ; Wed, 13 Oct 2010 14:21:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751896Ab0JMOVS (ORCPT ); Wed, 13 Oct 2010 10:21:18 -0400 Received: from 124x34x33x190.ap124.ftth.ucom.ne.jp ([124.34.33.190]:60100 "EHLO master.linux-sh.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751519Ab0JMOVR (ORCPT ); Wed, 13 Oct 2010 10:21:17 -0400 Received: from localhost (unknown [127.0.0.1]) by master.linux-sh.org (Postfix) with ESMTP id 031296376C; Wed, 13 Oct 2010 14:21:13 +0000 (UTC) X-Virus-Scanned: amavisd-new at linux-sh.org Received: from master.linux-sh.org ([127.0.0.1]) by localhost (master.linux-sh.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1qty0egOw2bi; Wed, 13 Oct 2010 23:21:11 +0900 (JST) Received: by master.linux-sh.org (Postfix, from userid 500) id B5D7D63778; Wed, 13 Oct 2010 23:21:11 +0900 (JST) Date: Wed, 13 Oct 2010 23:21:11 +0900 From: Paul Mundt To: Magnus Damm Cc: Guennadi Liakhovetski , Kuninori Morimoto , Linux-SH Subject: Re: [PATCH 1/2] ARM: mach-shmobile: clock-sh7372: Add FSIDIV clock support Message-ID: <20101013142111.GA13310@linux-sh.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.13 (2006-08-11) Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 13 Oct 2010 14:21:21 +0000 (UTC) diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c index 661a801..a20d309 100644 --- a/drivers/sh/clk.c +++ b/drivers/sh/clk.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -233,6 +234,14 @@ EXPORT_SYMBOL_GPL(clk_enable); static LIST_HEAD(root_clks); +static struct clk *lookup_root_clock(struct clk *clk) +{ + while (clk->parent) + clk = clk->parent; + + return clk; +} + /** * recalculate_root_clocks - recalculate and propagate all root clocks * @@ -251,8 +260,76 @@ void recalculate_root_clocks(void) } } +static struct clk_mapping dummy_mapping; + +static int clk_establish_mapping(struct clk *clk) +{ + struct clk_mapping *mapping = clk->mapping; + + /* + * Propagate mappings. + */ + if (!mapping) { + struct clk *clkp; + + /* + * dummy mapping for root clocks with no specified ranges + */ + if (!clk->parent) { + clk->mapping = &dummy_mapping; + return 0; + } + + /* + * If we're on a child clock and it provides no mapping of its + * own, inherit the mapping from its root clock. + */ + clkp = lookup_root_clock(clk); + mapping = clkp->mapping; + BUG_ON(!mapping); + } + + /* + * Establish initial mapping. + */ + if (!mapping->base && mapping->phys) { + kref_init(&mapping->ref); + mapping->base = ioremap_nocache(mapping->phys, mapping->len); + if (unlikely(!mapping->base)) + return -ENXIO; + } else + /* Existing mapping */ + kref_get(&mapping->ref); + + clk->mapping = mapping; + return 0; +} + +static void clk_destroy_mapping(struct kref *kref) +{ + struct clk_mapping *mapping; + + mapping = container_of(kref, struct clk_mapping, ref); + + iounmap(mapping->base); +} + +static void clk_teardown_mapping(struct clk *clk) +{ + struct clk_mapping *mapping = clk->mapping; + + /* Nothing to do */ + if (mapping == &dummy_mapping) + return; + + kref_put(&mapping->ref, clk_destroy_mapping); + clk->mapping = NULL; +} + int clk_register(struct clk *clk) { + int ret; + if (clk == NULL || IS_ERR(clk)) return -EINVAL; @@ -267,6 +344,10 @@ int clk_register(struct clk *clk) INIT_LIST_HEAD(&clk->children); clk->usecount = 0; + ret = clk_establish_mapping(clk); + if (unlikely(ret)) + goto out_unlock; + if (clk->parent) list_add(&clk->sibling, &clk->parent->children); else @@ -275,9 +356,11 @@ int clk_register(struct clk *clk) list_add(&clk->node, &clock_list); if (clk->ops && clk->ops->init) clk->ops->init(clk); + +out_unlock: mutex_unlock(&clock_list_sem); - return 0; + return ret; } EXPORT_SYMBOL_GPL(clk_register); @@ -286,6 +369,7 @@ void clk_unregister(struct clk *clk) mutex_lock(&clock_list_sem); list_del(&clk->sibling); list_del(&clk->node); + clk_teardown_mapping(clk); mutex_unlock(&clock_list_sem); } EXPORT_SYMBOL_GPL(clk_unregister); diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index ecdfea5..8ae3770 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -4,11 +4,20 @@ #include #include #include +#include +#include #include #include struct clk; +struct clk_mapping { + phys_addr_t phys; + void __iomem *base; + unsigned long len; + struct kref ref; +}; + struct clk_ops { void (*init)(struct clk *clk); int (*enable)(struct clk *clk); @@ -42,6 +51,7 @@ struct clk { unsigned long arch_flags; void *priv; struct dentry *dentry; + struct clk_mapping *mapping; struct cpufreq_frequency_table *freq_table; };