ARM: tegra: Fix PWM clock programming
PWM clock source registers in Tegra 2 have different clock source selection bit fields than other registers. PWM clock source bits in CLK_SOURCE_PWM_0 register are located at bit field bit[30:28] while others are at bit field bit[31:30] in their respective clock source register. This patch updates the clock programming to correctly reflect that, by adding a flag to indicate the alternate bit field format and checking for it when selecting a clock source (parent clock). Signed-off-by: Bill Huang <bilhuang@nvidia.com> Signed-off-by: Simon Que <sque@chromium.org> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> Signed-off-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
parent
72d967eda2
commit
bb1dccfc63
1 changed files with 28 additions and 4 deletions
|
@ -69,6 +69,8 @@
|
|||
|
||||
#define PERIPH_CLK_SOURCE_MASK (3<<30)
|
||||
#define PERIPH_CLK_SOURCE_SHIFT 30
|
||||
#define PERIPH_CLK_SOURCE_PWM_MASK (7<<28)
|
||||
#define PERIPH_CLK_SOURCE_PWM_SHIFT 28
|
||||
#define PERIPH_CLK_SOURCE_ENABLE (1<<28)
|
||||
#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF
|
||||
#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF
|
||||
|
@ -908,9 +910,20 @@ static void tegra2_periph_clk_init(struct clk *c)
|
|||
u32 val = clk_readl(c->reg);
|
||||
const struct clk_mux_sel *mux = NULL;
|
||||
const struct clk_mux_sel *sel;
|
||||
u32 shift;
|
||||
u32 mask;
|
||||
|
||||
if (c->flags & MUX_PWM) {
|
||||
shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
|
||||
mask = PERIPH_CLK_SOURCE_PWM_MASK;
|
||||
} else {
|
||||
shift = PERIPH_CLK_SOURCE_SHIFT;
|
||||
mask = PERIPH_CLK_SOURCE_MASK;
|
||||
}
|
||||
|
||||
if (c->flags & MUX) {
|
||||
for (sel = c->inputs; sel->input != NULL; sel++) {
|
||||
if (val >> PERIPH_CLK_SOURCE_SHIFT == sel->value)
|
||||
if ((val & mask) >> shift == sel->value)
|
||||
mux = sel;
|
||||
}
|
||||
BUG_ON(!mux);
|
||||
|
@ -1023,12 +1036,23 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
|
|||
{
|
||||
u32 val;
|
||||
const struct clk_mux_sel *sel;
|
||||
u32 mask, shift;
|
||||
|
||||
pr_debug("%s: %s %s\n", __func__, c->name, p->name);
|
||||
|
||||
if (c->flags & MUX_PWM) {
|
||||
shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
|
||||
mask = PERIPH_CLK_SOURCE_PWM_MASK;
|
||||
} else {
|
||||
shift = PERIPH_CLK_SOURCE_SHIFT;
|
||||
mask = PERIPH_CLK_SOURCE_MASK;
|
||||
}
|
||||
|
||||
for (sel = c->inputs; sel->input != NULL; sel++) {
|
||||
if (sel->input == p) {
|
||||
val = clk_readl(c->reg);
|
||||
val &= ~PERIPH_CLK_SOURCE_MASK;
|
||||
val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
|
||||
val &= ~mask;
|
||||
val |= (sel->value) << shift;
|
||||
|
||||
if (c->refcnt)
|
||||
clk_enable(p);
|
||||
|
@ -2156,7 +2180,7 @@ static struct clk tegra_list_clks[] = {
|
|||
PERIPH_CLK("i2s2", "tegra20-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71),
|
||||
PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
|
||||
PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71 | MUX_PWM),
|
||||
PERIPH_CLK("spi", "spi", NULL, 43, 0x114, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("xio", "xio", NULL, 45, 0x120, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
|
||||
PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
|
||||
|
|
Loading…
Reference in a new issue