From patchwork Thu Oct 25 16:11:50 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Murali Karicheri X-Patchwork-Id: 1645791 Return-Path: X-Original-To: patchwork-davinci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by patchwork1.kernel.org (Postfix) with ESMTP id F0FCF3FE1C for ; Thu, 25 Oct 2012 16:19:57 +0000 (UTC) Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id q9PGDMb7031829; Thu, 25 Oct 2012 11:13:22 -0500 Received: from DLEE74.ent.ti.com (dlee74.ent.ti.com [157.170.170.8]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q9PGDMhX019303; Thu, 25 Oct 2012 11:13:22 -0500 Received: from dlelxv24.itg.ti.com (172.17.1.199) by DLEE74.ent.ti.com (157.170.170.8) with Microsoft SMTP Server id 14.1.323.3; Thu, 25 Oct 2012 11:13:22 -0500 Received: from linux.omap.com (dlelxs01.itg.ti.com [157.170.227.31]) by dlelxv24.itg.ti.com (8.13.8/8.13.8) with ESMTP id q9PGDKon017520; Thu, 25 Oct 2012 11:13:22 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 5245180627; Thu, 25 Oct 2012 11:13:20 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dlelxv30.itg.ti.com (dlelxv30.itg.ti.com [172.17.2.17]) by linux.omap.com (Postfix) with ESMTP id 325AF80626 for ; Thu, 25 Oct 2012 11:12:02 -0500 (CDT) Received: from DLEE74.ent.ti.com (dlee74.ent.ti.com [157.170.170.8]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q9PGC2x1015820; Thu, 25 Oct 2012 11:12:02 -0500 Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE74.ent.ti.com (157.170.170.8) with Microsoft SMTP Server id 14.1.323.3; Thu, 25 Oct 2012 11:12:01 -0500 Received: from ares-ubuntu.am.dhcp.ti.com (ares-ubuntu.am.dhcp.ti.com [158.218.103.17]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id q9PGC0d3005695; Thu, 25 Oct 2012 11:12:01 -0500 Received: from a0868495 by ares-ubuntu.am.dhcp.ti.com with local (Exim 4.76) (envelope-from ) id 1TRQ2K-00036i-Mn; Thu, 25 Oct 2012 12:12:00 -0400 From: Murali Karicheri To: , , , , , , , , , , , , , Subject: [PATCH v3 04/11] clk: davinci - add pll divider clock driver Date: Thu, 25 Oct 2012 12:11:50 -0400 Message-ID: <1351181518-11882-5-git-send-email-m-karicheri2@ti.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1351181518-11882-1-git-send-email-m-karicheri2@ti.com> References: <1351181518-11882-1-git-send-email-m-karicheri2@ti.com> MIME-Version: 1.0 CC: X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com pll dividers are present in the pll controller of DaVinci and Other SoCs that re-uses the same hardware IP. This has a enable bit for bypass the divider or enable the driver. This is a sub class of the clk-divider clock checks the enable bit to calculare the rate and invoke the recalculate() function of the clk-divider if enabled. Signed-off-by: Murali Karicheri Acked-by: Linus Walleij --- drivers/clk/davinci/clk-div.c | 124 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/davinci/clk-div.h | 42 ++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 drivers/clk/davinci/clk-div.c create mode 100644 drivers/clk/davinci/clk-div.h diff --git a/drivers/clk/davinci/clk-div.c b/drivers/clk/davinci/clk-div.c new file mode 100644 index 0000000..8147d99 --- /dev/null +++ b/drivers/clk/davinci/clk-div.c @@ -0,0 +1,124 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2012 Texas instuments + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + */ + +#include +#include +#include +#include +#include + +#include "clk-div.h" + +/** + * struct clk_div - DaVinci integer pll divider clock + * + * @divider: the parent class + * @ops: pointer to clk_ops of parent class + * @reg: register address + * @en_id: enable bit id + * + * The DaVinci pll divider clock is a subclass of basic clk_divider with + * an additional enable bit + */ +struct clk_div { + struct clk_divider divider; + const struct clk_ops *ops; + void __iomem *reg; + u8 en_id; +}; + +static inline struct clk_div *to_clk_div(struct clk_hw *hw) +{ + struct clk_divider *divider = container_of(hw, struct clk_divider, hw); + + return container_of(divider, struct clk_div, divider); +} + +static unsigned long clk_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_div *div = to_clk_div(hw); + u32 val; + + val = readl(div->reg); + if (val & BIT(div->en_id)) + return div->ops->recalc_rate(&div->divider.hw, parent_rate); + + /* pll divider bypassed, return parent rate */ + return parent_rate; +} + +static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_div *div = to_clk_div(hw); + + return div->ops->round_rate(&div->divider.hw, rate, prate); +} + +static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_div *div = to_clk_div(hw); + + return div->ops->set_rate(&div->divider.hw, rate, parent_rate); +} + +static struct clk_ops clk_div_ops = { + .recalc_rate = clk_div_recalc_rate, + .round_rate = clk_div_round_rate, + .set_rate = clk_div_set_rate, +}; + +/** + * clk_register_davinci_plldiv - register function for DaVinci PLL divider clk + * + * @dev: device ptr + * @name: name of the clock + * @parent_name: name of parent clock + * @plldiv_data: ptr to pll divider data + * @lock: ptr to spinlock passed to divider clock + */ +struct clk *clk_register_davinci_plldiv(struct device *dev, + const char *name, const char *parent_name, + struct clk_plldiv_data *plldiv_data, + spinlock_t *lock) +{ + struct clk_div *div; + struct clk *clk; + struct clk_init_data init; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &clk_div_ops; + init.flags = plldiv_data->flags; + init.parent_names = (parent_name ? &parent_name : NULL); + init.num_parents = (parent_name ? 1 : 0); + + div->reg = plldiv_data->reg; + div->en_id = plldiv_data->en_id; + + div->divider.reg = plldiv_data->reg; + div->divider.shift = plldiv_data->shift; + div->divider.width = plldiv_data->width; + div->divider.flags = plldiv_data->divider_flags; + div->divider.lock = lock; + div->divider.hw.init = &init; + div->ops = &clk_divider_ops; + + clk = clk_register(NULL, &div->divider.hw); + if (IS_ERR(clk)) + kfree(div); + + return clk; +} diff --git a/drivers/clk/davinci/clk-div.h b/drivers/clk/davinci/clk-div.h new file mode 100644 index 0000000..0e3708c --- /dev/null +++ b/drivers/clk/davinci/clk-div.h @@ -0,0 +1,42 @@ +/* + * Header file for DaVinci pll divider clk driver + * + * Copyright (C) 2006-2012 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef __CLK_DAVINCI_PLLDIV_H +#define __CLK_DAVINCI_PLLDIV_H + + +/** + * struct clk_plldiv_data - configuration for DaVinci PLL divider driver + * + * @flags - base clk driver flags + * @divider_flags - clk-divider flags + * @phys_div_reg - clk-divider register physical address + * @reg - clk-divider register io mapped address + * @shift - shift applied to the divider bits in the register + * @width - width of the divider bits in the register + * @en_id - bypass or enable bit mask id. mask = BIT(en_id) + */ +/* configuration data for PLL divider clock */ +struct clk_plldiv_data { + u32 flags; + u8 divider_flags; + u32 phys_div_reg; + void __iomem *reg; + u8 shift; + u8 width; + u8 en_id; +}; + +struct clk *clk_register_davinci_plldiv(struct device *dev, + const char *name, const char *parent_name, + struct clk_plldiv_data *plldiv_data, + spinlock_t *lock); +#endif /* CLK_DAVINCI_PLLDIV_H */