Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += clk-pxa.o
obj-$(CONFIG_PXA25x) += clk-pxa25x.o
obj-$(CONFIG_PXA27x) += clk-pxa27x.o
obj-$(CONFIG_PXA3xx) += clk-pxa3xx.o
+251
View File
@@ -0,0 +1,251 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell PXA family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Common clock code for PXA clocks ("CKEN" type clocks + DT)
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/soc/pxa/smemc.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
#define KHz 1000
#define MHz (1000 * 1000)
#define MDREFR_K0DB4 (1 << 29) /* SDCLK0 Divide by 4 Control/Status */
#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */
#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */
#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */
#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */
#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */
#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */
#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */
#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */
#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */
#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */
#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */
#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */
#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */
#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2)
#define MDREFR_DRI_MASK 0xFFF
static DEFINE_SPINLOCK(pxa_clk_lock);
static struct clk *pxa_clocks[CLK_MAX];
static struct clk_onecell_data onecell_data = {
.clks = pxa_clocks,
.clk_num = CLK_MAX,
};
struct pxa_clk {
struct clk_hw hw;
struct clk_fixed_factor lp;
struct clk_fixed_factor hp;
struct clk_gate gate;
bool (*is_in_low_power)(void);
};
#define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, hw)
static unsigned long cken_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pxa_clk *pclk = to_pxa_clk(hw);
struct clk_fixed_factor *fix;
if (!pclk->is_in_low_power || pclk->is_in_low_power())
fix = &pclk->lp;
else
fix = &pclk->hp;
__clk_hw_set_clk(&fix->hw, hw);
return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
}
static const struct clk_ops cken_rate_ops = {
.recalc_rate = cken_recalc_rate,
};
static u8 cken_get_parent(struct clk_hw *hw)
{
struct pxa_clk *pclk = to_pxa_clk(hw);
if (!pclk->is_in_low_power)
return 0;
return pclk->is_in_low_power() ? 0 : 1;
}
static const struct clk_ops cken_mux_ops = {
.determine_rate = clk_hw_determine_rate_no_reparent,
.get_parent = cken_get_parent,
.set_parent = dummy_clk_set_parent,
};
void __init clkdev_pxa_register(int ckid, const char *con_id,
const char *dev_id, struct clk *clk)
{
if (!IS_ERR(clk) && (ckid != CLK_NONE))
pxa_clocks[ckid] = clk;
if (!IS_ERR(clk))
clk_register_clkdev(clk, con_id, dev_id);
}
int __init clk_pxa_cken_init(const struct desc_clk_cken *clks,
int nb_clks, void __iomem *clk_regs)
{
int i;
struct pxa_clk *pxa_clk;
struct clk *clk;
for (i = 0; i < nb_clks; i++) {
pxa_clk = kzalloc_obj(*pxa_clk);
if (!pxa_clk)
return -ENOMEM;
pxa_clk->is_in_low_power = clks[i].is_in_low_power;
pxa_clk->lp = clks[i].lp;
pxa_clk->hp = clks[i].hp;
pxa_clk->gate = clks[i].gate;
pxa_clk->gate.reg = clk_regs + clks[i].cken_reg;
pxa_clk->gate.lock = &pxa_clk_lock;
clk = clk_register_composite(NULL, clks[i].name,
clks[i].parent_names, 2,
&pxa_clk->hw, &cken_mux_ops,
&pxa_clk->hw, &cken_rate_ops,
&pxa_clk->gate.hw, &clk_gate_ops,
clks[i].flags);
clkdev_pxa_register(clks[i].ckid, clks[i].con_id,
clks[i].dev_id, clk);
}
return 0;
}
void __init clk_pxa_dt_common_init(struct device_node *np)
{
of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
}
void pxa2xx_core_turbo_switch(bool on)
{
unsigned long flags;
unsigned int unused, clkcfg;
local_irq_save(flags);
asm("mrc p14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
clkcfg &= ~CLKCFG_TURBO & ~CLKCFG_HALFTURBO;
if (on)
clkcfg |= CLKCFG_TURBO;
clkcfg |= CLKCFG_FCS;
asm volatile(
" b 2f\n"
" .align 5\n"
"1: mcr p14, 0, %1, c6, c0, 0\n"
" b 3f\n"
"2: b 1b\n"
"3: nop\n"
: "=&r" (unused) : "r" (clkcfg));
local_irq_restore(flags);
}
void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
u32 (*mdrefr_dri)(unsigned int),
void __iomem *cccr)
{
unsigned int clkcfg = freq->clkcfg;
unsigned int unused, preset_mdrefr, postset_mdrefr;
unsigned long flags;
void __iomem *mdrefr = pxa_smemc_get_mdrefr();
local_irq_save(flags);
/* Calculate the next MDREFR. If we're slowing down the SDRAM clock
* we need to preset the smaller DRI before the change. If we're
* speeding up we need to set the larger DRI value after the change.
*/
preset_mdrefr = postset_mdrefr = readl(mdrefr);
if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(freq->membus_khz)) {
preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
preset_mdrefr |= mdrefr_dri(freq->membus_khz);
}
postset_mdrefr =
(postset_mdrefr & ~MDREFR_DRI_MASK) |
mdrefr_dri(freq->membus_khz);
/* If we're dividing the memory clock by two for the SDRAM clock, this
* must be set prior to the change. Clearing the divide must be done
* after the change.
*/
if (freq->div2) {
preset_mdrefr |= MDREFR_DB2_MASK;
postset_mdrefr |= MDREFR_DB2_MASK;
} else {
postset_mdrefr &= ~MDREFR_DB2_MASK;
}
/* Set new the CCCR and prepare CLKCFG */
writel(freq->cccr, cccr);
asm volatile(
" ldr r4, [%1]\n"
" b 2f\n"
" .align 5\n"
"1: str %3, [%1] /* preset the MDREFR */\n"
" mcr p14, 0, %2, c6, c0, 0 /* set CLKCFG[FCS] */\n"
" str %4, [%1] /* postset the MDREFR */\n"
" b 3f\n"
"2: b 1b\n"
"3: nop\n"
: "=&r" (unused)
: "r" (mdrefr), "r" (clkcfg), "r" (preset_mdrefr),
"r" (postset_mdrefr)
: "r4", "r5");
local_irq_restore(flags);
}
int pxa2xx_determine_rate(struct clk_rate_request *req,
struct pxa2xx_freq *freqs, int nb_freqs)
{
int i, closest_below = -1, closest_above = -1;
unsigned long rate;
for (i = 0; i < nb_freqs; i++) {
rate = freqs[i].cpll;
if (rate == req->rate)
break;
if (rate < req->min_rate)
continue;
if (rate > req->max_rate)
continue;
if (rate <= req->rate)
closest_below = i;
if ((rate >= req->rate) && (closest_above == -1))
closest_above = i;
}
req->best_parent_hw = NULL;
if (i < nb_freqs) {
rate = req->rate;
} else if (closest_below >= 0) {
rate = freqs[closest_below].cpll;
} else if (closest_above >= 0) {
rate = freqs[closest_above].cpll;
} else {
pr_debug("%s(rate=%lu) no match\n", __func__, req->rate);
return -EINVAL;
}
pr_debug("%s(rate=%lu) rate=%lu\n", __func__, req->rate, rate);
req->rate = rate;
return 0;
}
+162
View File
@@ -0,0 +1,162 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Marvell PXA family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Common clock code for PXA clocks ("CKEN" type clocks + DT)
*/
#ifndef _CLK_PXA_
#define _CLK_PXA_
#define CLKCFG_TURBO 0x1
#define CLKCFG_FCS 0x2
#define CLKCFG_HALFTURBO 0x4
#define CLKCFG_FASTBUS 0x8
#define PARENTS(name) \
static const char *const name ## _parents[] __initconst
#define MUX_RO_RATE_RO_OPS(name, clk_name) \
static struct clk_hw name ## _mux_hw; \
static struct clk_hw name ## _rate_hw; \
static const struct clk_ops name ## _mux_ops = { \
.get_parent = name ## _get_parent, \
.set_parent = dummy_clk_set_parent, \
}; \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
ARRAY_SIZE(name ## _parents), \
&name ## _mux_hw, &name ## _mux_ops, \
&name ## _rate_hw, &name ## _rate_ops, \
NULL, NULL, CLK_GET_RATE_NOCACHE); \
}
#define RATE_RO_OPS(name, clk_name) \
static struct clk_hw name ## _rate_hw; \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
ARRAY_SIZE(name ## _parents), \
NULL, NULL, \
&name ## _rate_hw, &name ## _rate_ops, \
NULL, NULL, CLK_GET_RATE_NOCACHE); \
}
#define RATE_OPS(name, clk_name) \
static struct clk_hw name ## _rate_hw; \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
.set_rate = name ## _set_rate, \
.determine_rate = name ## _determine_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
ARRAY_SIZE(name ## _parents), \
NULL, NULL, \
&name ## _rate_hw, &name ## _rate_ops, \
NULL, NULL, CLK_GET_RATE_NOCACHE); \
}
#define MUX_OPS(name, clk_name, flags) \
static struct clk_hw name ## _mux_hw; \
static const struct clk_ops name ## _mux_ops = { \
.get_parent = name ## _get_parent, \
.set_parent = name ## _set_parent, \
.determine_rate = name ## _determine_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
ARRAY_SIZE(name ## _parents), \
&name ## _mux_hw, &name ## _mux_ops, \
NULL, NULL, \
NULL, NULL, \
CLK_GET_RATE_NOCACHE | flags); \
}
/*
* CKEN clock type
* This clock takes it source from 2 possible parents :
* - a low power parent
* - a normal parent
*
* +------------+ +-----------+
* | Low Power | --- | x mult_lp |
* | Clock | | / div_lp |\
* +------------+ +-----------+ \+-----+ +-----------+
* | Mux |---| CKEN gate |
* +------------+ +-----------+ /+-----+ +-----------+
* | High Power | | x mult_hp |/
* | Clock | --- | / div_hp |
* +------------+ +-----------+
*/
struct desc_clk_cken {
struct clk_hw hw;
int ckid;
int cken_reg;
const char *name;
const char *dev_id;
const char *con_id;
const char * const *parent_names;
struct clk_fixed_factor lp;
struct clk_fixed_factor hp;
struct clk_gate gate;
bool (*is_in_low_power)(void);
const unsigned long flags;
};
#define PXA_CKEN(_dev_id, _con_id, _name, parents, _mult_lp, _div_lp, \
_mult_hp, _div_hp, is_lp, _cken_reg, _cken_bit, flag) \
{ .ckid = CLK_ ## _name, .name = #_name, \
.cken_reg = _cken_reg, \
.dev_id = _dev_id, .con_id = _con_id, .parent_names = parents,\
.lp = { .mult = _mult_lp, .div = _div_lp }, \
.hp = { .mult = _mult_hp, .div = _div_hp }, \
.is_in_low_power = is_lp, \
.gate = { .bit_idx = _cken_bit }, \
.flags = flag, \
}
#define PXA_CKEN_1RATE(dev_id, con_id, name, parents, cken_reg, \
cken_bit, flag) \
PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \
NULL, cken_reg, cken_bit, flag)
struct pxa2xx_freq {
unsigned long cpll;
unsigned int membus_khz;
unsigned int cccr;
unsigned int div2;
unsigned int clkcfg;
};
static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
{
return 0;
}
extern void clkdev_pxa_register(int ckid, const char *con_id,
const char *dev_id, struct clk *clk);
extern int clk_pxa_cken_init(const struct desc_clk_cken *clks,
int nb_clks, void __iomem *clk_regs);
void clk_pxa_dt_common_init(struct device_node *np);
void pxa2xx_core_turbo_switch(bool on);
void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
u32 (*mdrefr_dri)(unsigned int),
void __iomem *cccr);
int pxa2xx_determine_rate(struct clk_rate_request *req,
struct pxa2xx_freq *freqs, int nb_freqs);
#endif
+341
View File
@@ -0,0 +1,341 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell PXA25x family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Heavily inspired from former arch/arm/mach-pxa/pxa25x.c.
*
* For non-devicetree platforms. Once pxa is fully converted to devicetree, this
* should go away.
*/
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/clk/pxa.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/soc/pxa/smemc.h>
#include <linux/soc/pxa/cpu.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
#include "clk-pxa2xx.h"
#define KHz 1000
#define MHz (1000 * 1000)
enum {
PXA_CORE_RUN = 0,
PXA_CORE_TURBO,
};
#define PXA25x_CLKCFG(T) \
(CLKCFG_FCS | \
((T) ? CLKCFG_TURBO : 0))
#define PXA25x_CCCR(N2, M, L) (N2 << 7 | M << 5 | L)
/* Define the refresh period in mSec for the SDRAM and the number of rows */
#define SDRAM_TREF 64 /* standard 64ms SDRAM */
/*
* Various clock factors driven by the CCCR register.
*/
static void __iomem *clk_regs;
/* Crystal Frequency to Memory Frequency Multiplier (L) */
static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
/* Memory Frequency to Run Mode Frequency Multiplier (M) */
static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
/* Note: we store the value N * 2 here. */
static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
static const char * const get_freq_khz[] = {
"core", "run", "cpll", "memory"
};
static u32 mdrefr_dri(unsigned int freq_khz)
{
u32 interval = freq_khz * SDRAM_TREF / pxa2xx_smemc_get_sdram_rows();
return interval / 32;
}
/*
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int pxa25x_get_clk_frequency_khz(int info)
{
struct clk *clk;
unsigned long clks[5];
int i;
for (i = 0; i < ARRAY_SIZE(get_freq_khz); i++) {
clk = clk_get(NULL, get_freq_khz[i]);
if (IS_ERR(clk)) {
clks[i] = 0;
} else {
clks[i] = clk_get_rate(clk);
clk_put(clk);
}
}
if (info) {
pr_info("Run Mode clock: %ld.%02ldMHz\n",
clks[1] / 1000000, (clks[1] % 1000000) / 10000);
pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
clks[2] / 1000000, (clks[2] % 1000000) / 10000);
pr_info("Memory clock: %ld.%02ldMHz\n",
clks[3] / 1000000, (clks[3] % 1000000) / 10000);
}
return (unsigned int)clks[0] / KHz;
}
static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long cccr = readl(clk_regs + CCCR);
unsigned int m = M_clk_mult[(cccr >> 5) & 0x03];
return parent_rate / m;
}
PARENTS(clk_pxa25x_memory) = { "run" };
RATE_RO_OPS(clk_pxa25x_memory, "memory");
PARENTS(pxa25x_pbus95) = { "ppll_95_85mhz", "ppll_95_85mhz" };
PARENTS(pxa25x_pbus147) = { "ppll_147_46mhz", "ppll_147_46mhz" };
PARENTS(pxa25x_osc3) = { "osc_3_6864mhz", "osc_3_6864mhz" };
#define PXA25X_CKEN(dev_id, con_id, parents, mult, div, \
bit, is_lp, flags) \
PXA_CKEN(dev_id, con_id, bit, parents, mult, div, mult, div, \
is_lp, CKEN, CKEN_ ## bit, flags)
#define PXA25X_PBUS95_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
PXA25X_CKEN(dev_id, con_id, pxa25x_pbus95_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_PBUS147_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay)\
PXA25X_CKEN(dev_id, con_id, pxa25x_pbus147_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_OSC3_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
PXA25X_CKEN(dev_id, con_id, pxa25x_osc3_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
CKEN, CKEN_ ## bit, 0)
#define PXA25X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
static struct desc_clk_cken pxa25x_clocks[] __initdata = {
PXA25X_PBUS95_CKEN("pxa2xx-mci.0", NULL, MMC, 1, 5, 0),
PXA25X_PBUS95_CKEN("pxa2xx-i2c.0", NULL, I2C, 1, 3, 0),
PXA25X_PBUS95_CKEN("pxa2xx-ir", "FICPCLK", FICP, 1, 2, 0),
PXA25X_PBUS95_CKEN("pxa25x-udc", NULL, USB, 1, 2, 5),
PXA25X_PBUS147_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.3", NULL, HWUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-i2s", NULL, I2S, 1, 10, 0),
PXA25X_PBUS147_CKEN(NULL, "AC97CLK", AC97, 1, 12, 0),
PXA25X_OSC3_CKEN("pxa25x-ssp.0", NULL, SSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-nssp.1", NULL, NSSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-nssp.2", NULL, ASSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-pwm.0", NULL, PWM0, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-pwm.1", NULL, PWM1, 1, 1, 0),
PXA25X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, clk_pxa25x_memory_parents, 0),
PXA25X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
clk_pxa25x_memory_parents, 0),
};
/*
* In this table, PXA25x_CCCR(N2, M, L) has the following meaning, where :
* - freq_cpll = n * m * L * 3.6864 MHz
* - n = N2 / 2
* - m = 2^(M - 1), where 1 <= M <= 3
* - l = L_clk_mult[L], ie. { 0, 27, 32, 36, 40, 45, 0, }[L]
*/
static struct pxa2xx_freq pxa25x_freqs[] = {
/* CPU MEMBUS CCCR DIV2 CCLKCFG */
{ 99532800, 99500, PXA25x_CCCR(2, 1, 1), 1, PXA25x_CLKCFG(1)},
{199065600, 99500, PXA25x_CCCR(4, 1, 1), 0, PXA25x_CLKCFG(1)},
{298598400, 99500, PXA25x_CCCR(3, 2, 1), 0, PXA25x_CLKCFG(1)},
{398131200, 99500, PXA25x_CCCR(4, 2, 1), 0, PXA25x_CLKCFG(1)},
};
static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
{
unsigned long clkcfg;
unsigned int t;
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
if (t)
return PXA_CORE_TURBO;
return PXA_CORE_RUN;
}
static int clk_pxa25x_core_set_parent(struct clk_hw *hw, u8 index)
{
if (index > PXA_CORE_TURBO)
return -EINVAL;
pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
return 0;
}
static int clk_pxa25x_core_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return __clk_mux_determine_rate(hw, req);
}
PARENTS(clk_pxa25x_core) = { "run", "cpll" };
MUX_OPS(clk_pxa25x_core, "core", CLK_SET_RATE_PARENT);
static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long cccr = readl(clk_regs + CCCR);
unsigned int n2 = N2_clk_mult[(cccr >> 7) & 0x07];
return (parent_rate / n2) * 2;
}
PARENTS(clk_pxa25x_run) = { "cpll" };
RATE_RO_OPS(clk_pxa25x_run, "run");
static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long clkcfg, cccr = readl(clk_regs + CCCR);
unsigned int l, m, n2, t;
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
l = L_clk_mult[(cccr >> 0) & 0x1f];
m = M_clk_mult[(cccr >> 5) & 0x03];
n2 = N2_clk_mult[(cccr >> 7) & 0x07];
return m * l * n2 * parent_rate / 2;
}
static int clk_pxa25x_cpll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return pxa2xx_determine_rate(req, pxa25x_freqs,
ARRAY_SIZE(pxa25x_freqs));
}
static int clk_pxa25x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int i;
pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
for (i = 0; i < ARRAY_SIZE(pxa25x_freqs); i++)
if (pxa25x_freqs[i].cpll == rate)
break;
if (i >= ARRAY_SIZE(pxa25x_freqs))
return -EINVAL;
pxa2xx_cpll_change(&pxa25x_freqs[i], mdrefr_dri, clk_regs + CCCR);
return 0;
}
PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" };
RATE_OPS(clk_pxa25x_cpll, "cpll");
static void __init pxa25x_register_core(void)
{
clkdev_pxa_register(CLK_NONE, "cpll", NULL,
clk_register_clk_pxa25x_cpll());
clkdev_pxa_register(CLK_NONE, "run", NULL,
clk_register_clk_pxa25x_run());
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa25x_core());
}
static void __init pxa25x_register_plls(void)
{
clk_register_fixed_rate(NULL, "osc_3_6864mhz", NULL,
CLK_GET_RATE_NOCACHE, 3686400);
clkdev_pxa_register(CLK_OSC32k768, "osc_32_768khz", NULL,
clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
CLK_GET_RATE_NOCACHE,
32768));
clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
clk_register_fixed_factor(NULL, "ppll_95_85mhz", "osc_3_6864mhz",
0, 26, 1);
clk_register_fixed_factor(NULL, "ppll_147_46mhz", "osc_3_6864mhz",
0, 40, 1);
}
static void __init pxa25x_base_clocks_init(void)
{
pxa25x_register_plls();
pxa25x_register_core();
clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
clk_register_clk_pxa25x_memory());
}
#define DUMMY_CLK(_con_id, _dev_id, _parent) \
{ .con_id = _con_id, .dev_id = _dev_id, .parent = _parent }
struct dummy_clk {
const char *con_id;
const char *dev_id;
const char *parent;
};
static struct dummy_clk dummy_clks[] __initdata = {
DUMMY_CLK(NULL, "pxa25x-gpio", "osc_32_768khz"),
DUMMY_CLK(NULL, "pxa26x-gpio", "osc_32_768khz"),
DUMMY_CLK("GPIO11_CLK", NULL, "osc_3_6864mhz"),
DUMMY_CLK("GPIO12_CLK", NULL, "osc_32_768khz"),
DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
DUMMY_CLK("OSTIMER0", NULL, "osc_3_6864mhz"),
DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
};
static void __init pxa25x_dummy_clocks_init(void)
{
struct clk *clk;
struct dummy_clk *d;
const char *name;
int i;
/*
* All pinctrl logic has been wiped out of the clock driver, especially
* for gpio11 and gpio12 outputs. Machine code should ensure proper pin
* control (ie. pxa2xx_mfp_config() invocation).
*/
for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) {
d = &dummy_clks[i];
name = d->dev_id ? d->dev_id : d->con_id;
clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1);
clk_register_clkdev(clk, d->con_id, d->dev_id);
}
}
int __init pxa25x_clocks_init(void __iomem *regs)
{
clk_regs = regs;
pxa25x_base_clocks_init();
pxa25x_dummy_clocks_init();
return clk_pxa_cken_init(pxa25x_clocks, ARRAY_SIZE(pxa25x_clocks), clk_regs);
}
static void __init pxa25x_dt_clocks_init(struct device_node *np)
{
pxa25x_clocks_init(ioremap(0x41300000ul, 0x10));
clk_pxa_dt_common_init(np);
}
CLK_OF_DECLARE(pxa25x_clks, "marvell,pxa250-core-clocks",
pxa25x_dt_clocks_init);
+484
View File
@@ -0,0 +1,484 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell PXA27x family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Heavily inspired from former arch/arm/mach-pxa/clock.c.
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/soc/pxa/smemc.h>
#include <linux/clk/pxa.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
#include "clk-pxa2xx.h"
#define KHz 1000
#define MHz (1000 * 1000)
enum {
PXA_CORE_13Mhz = 0,
PXA_CORE_RUN,
PXA_CORE_TURBO,
};
enum {
PXA_BUS_13Mhz = 0,
PXA_BUS_RUN,
};
enum {
PXA_LCD_13Mhz = 0,
PXA_LCD_RUN,
};
enum {
PXA_MEM_13Mhz = 0,
PXA_MEM_SYSTEM_BUS,
PXA_MEM_RUN,
};
#define PXA27x_CLKCFG(B, HT, T) \
(CLKCFG_FCS | \
((B) ? CLKCFG_FASTBUS : 0) | \
((HT) ? CLKCFG_HALFTURBO : 0) | \
((T) ? CLKCFG_TURBO : 0))
#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
/* Define the refresh period in mSec for the SDRAM and the number of rows */
#define SDRAM_TREF 64 /* standard 64ms SDRAM */
static void __iomem *clk_regs;
static const char * const get_freq_khz[] = {
"core", "run", "cpll", "memory",
"system_bus"
};
static u32 mdrefr_dri(unsigned int freq_khz)
{
u32 interval = freq_khz * SDRAM_TREF / pxa2xx_smemc_get_sdram_rows();
return (interval - 31) / 32;
}
/*
* Get the clock frequency as reflected by CCSR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int pxa27x_get_clk_frequency_khz(int info)
{
struct clk *clk;
unsigned long clks[5];
int i;
for (i = 0; i < 5; i++) {
clk = clk_get(NULL, get_freq_khz[i]);
if (IS_ERR(clk)) {
clks[i] = 0;
} else {
clks[i] = clk_get_rate(clk);
clk_put(clk);
}
}
if (info) {
pr_info("Run Mode clock: %ld.%02ldMHz\n",
clks[1] / 1000000, (clks[1] % 1000000) / 10000);
pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
clks[2] / 1000000, (clks[2] % 1000000) / 10000);
pr_info("Memory clock: %ld.%02ldMHz\n",
clks[3] / 1000000, (clks[3] % 1000000) / 10000);
pr_info("System bus clock: %ld.%02ldMHz\n",
clks[4] / 1000000, (clks[4] % 1000000) / 10000);
}
return (unsigned int)clks[0] / KHz;
}
static bool pxa27x_is_ppll_disabled(void)
{
unsigned long ccsr = readl(clk_regs + CCSR);
return ccsr & (1 << CCCR_PPDIS_BIT);
}
#define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp, \
bit, is_lp, flags) \
PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp, \
is_lp, CKEN, CKEN_ ## bit, flags)
#define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp, \
div_hp, bit, pxa27x_is_ppll_disabled, 0)
PARENTS(pxa27x_pbus) = { "osc_13mhz", "ppll_312mhz" };
PARENTS(pxa27x_sbus) = { "system_bus", "system_bus" };
PARENTS(pxa27x_32Mhz_bus) = { "osc_32_768khz", "osc_32_768khz" };
PARENTS(pxa27x_lcd_bus) = { "lcd_base", "lcd_base" };
PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" };
#define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
CKEN, CKEN_ ## bit, 0)
#define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
static struct desc_clk_cken pxa27x_clocks[] __initdata = {
PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1),
PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1),
PXA27X_PBUS_CKEN("pxa2xx-i2s", NULL, I2S, 2, 51, 0),
PXA27X_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 19, 0),
PXA27X_PBUS_CKEN("pxa27x-udc", NULL, USB, 2, 13, 5),
PXA27X_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC, 2, 32, 0),
PXA27X_PBUS_CKEN("pxa2xx-ir", "FICPCLK", FICP, 2, 13, 0),
PXA27X_PBUS_CKEN("pxa27x-ohci", NULL, USBHOST, 2, 13, 0),
PXA27X_PBUS_CKEN("pxa2xx-i2c.1", NULL, PWRI2C, 1, 24, 0),
PXA27X_PBUS_CKEN("pxa27x-ssp.0", NULL, SSP1, 1, 24, 0),
PXA27X_PBUS_CKEN("pxa27x-ssp.1", NULL, SSP2, 1, 24, 0),
PXA27X_PBUS_CKEN("pxa27x-ssp.2", NULL, SSP3, 1, 24, 0),
PXA27X_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 24, 0),
PXA27X_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 24, 0),
PXA27X_PBUS_CKEN(NULL, "MSLCLK", MSL, 2, 13, 0),
PXA27X_PBUS_CKEN(NULL, "USIMCLK", USIM, 2, 13, 0),
PXA27X_PBUS_CKEN(NULL, "MSTKCLK", MEMSTK, 2, 32, 0),
PXA27X_PBUS_CKEN(NULL, "AC97CLK", AC97, 1, 1, 0),
PXA27X_PBUS_CKEN(NULL, "AC97CONFCLK", AC97CONF, 1, 1, 0),
PXA27X_PBUS_CKEN(NULL, "OSTIMER0", OSTIMER, 1, 96, 0),
PXA27X_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
pxa27x_32Mhz_bus_parents, 0),
PXA27X_CKEN_1RATE(NULL, "IMCLK", IM, pxa27x_sbus_parents, 0),
PXA27X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, pxa27x_lcd_bus_parents, 0),
PXA27X_CKEN_1RATE("pxa27x-camera.0", NULL, CAMERA,
pxa27x_lcd_bus_parents, 0),
PXA27X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
pxa27x_membus_parents, 0),
};
/*
* PXA270 definitions
*
* For the PXA27x:
* Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
*
* A = 0 => memory controller clock from table 3-7,
* A = 1 => memory controller clock = system bus clock
* Run mode frequency = 13 MHz * L
* Turbo mode frequency = 13 MHz * L * N
* System bus frequency = 13 MHz * L / (B + 1)
*
* In CCCR:
* A = 1
* L = 16 oscillator to run mode ratio
* 2N = 6 2 * (turbo mode to run mode ratio)
*
* In CCLKCFG:
* B = 1 Fast bus mode
* HT = 0 Half-Turbo mode
* T = 1 Turbo mode
*
* For now, just support some of the combinations in table 3-7 of
* PXA27x Processor Family Developer's Manual to simplify frequency
* change sequences.
*/
static struct pxa2xx_freq pxa27x_freqs[] = {
{104000000, 104000, PXA27x_CCCR(1, 8, 2), 0, PXA27x_CLKCFG(1, 0, 1) },
{156000000, 104000, PXA27x_CCCR(1, 8, 3), 0, PXA27x_CLKCFG(1, 0, 1) },
{208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) },
{312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) },
{416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) },
{520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) },
{624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) },
};
static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long clkcfg;
unsigned int t, ht;
unsigned int l, L, n2, N;
unsigned long ccsr = readl(clk_regs + CCSR);
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
ht = clkcfg & (1 << 2);
l = ccsr & CCSR_L_MASK;
n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
L = l * parent_rate;
N = (L * n2) / 2;
return N;
}
static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return pxa2xx_determine_rate(req, pxa27x_freqs,
ARRAY_SIZE(pxa27x_freqs));
}
static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int i;
pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++)
if (pxa27x_freqs[i].cpll == rate)
break;
if (i >= ARRAY_SIZE(pxa27x_freqs))
return -EINVAL;
pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, clk_regs + CCCR);
return 0;
}
PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
RATE_OPS(clk_pxa27x_cpll, "cpll");
static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned int l, osc_forced;
unsigned long ccsr = readl(clk_regs + CCSR);
unsigned long cccr = readl(clk_regs + CCCR);
l = ccsr & CCSR_L_MASK;
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
if (osc_forced) {
if (cccr & (1 << CCCR_LCD_26_BIT))
return parent_rate * 2;
else
return parent_rate;
}
if (l <= 7)
return parent_rate;
if (l <= 16)
return parent_rate / 2;
return parent_rate / 4;
}
static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw)
{
unsigned int osc_forced;
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
if (osc_forced)
return PXA_LCD_13Mhz;
else
return PXA_LCD_RUN;
}
PARENTS(clk_pxa27x_lcd_base) = { "osc_13mhz", "run" };
MUX_RO_RATE_RO_OPS(clk_pxa27x_lcd_base, "lcd_base");
static void __init pxa27x_register_plls(void)
{
clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
CLK_GET_RATE_NOCACHE,
13 * MHz);
clkdev_pxa_register(CLK_OSC32k768, "osc_32_768khz", NULL,
clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
CLK_GET_RATE_NOCACHE,
32768 * KHz));
clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
}
static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
{
unsigned long clkcfg;
unsigned int t, ht, osc_forced;
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
if (osc_forced)
return PXA_CORE_13Mhz;
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
ht = clkcfg & (1 << 2);
if (ht || t)
return PXA_CORE_TURBO;
return PXA_CORE_RUN;
}
static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index)
{
if (index > PXA_CORE_TURBO)
return -EINVAL;
pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
return 0;
}
static int clk_pxa27x_core_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return __clk_mux_determine_rate(hw, req);
}
PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT);
static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long ccsr = readl(clk_regs + CCSR);
unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
return (parent_rate / n2) * 2;
}
PARENTS(clk_pxa27x_run) = { "cpll" };
RATE_RO_OPS(clk_pxa27x_run, "run");
static void __init pxa27x_register_core(void)
{
clkdev_pxa_register(CLK_NONE, "cpll", NULL,
clk_register_clk_pxa27x_cpll());
clkdev_pxa_register(CLK_NONE, "run", NULL,
clk_register_clk_pxa27x_run());
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa27x_core());
}
static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long clkcfg;
unsigned int b, osc_forced;
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
b = clkcfg & (1 << 3);
if (osc_forced)
return parent_rate;
if (b)
return parent_rate;
else
return parent_rate / 2;
}
static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
{
unsigned int osc_forced;
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
if (osc_forced)
return PXA_BUS_13Mhz;
else
return PXA_BUS_RUN;
}
PARENTS(clk_pxa27x_system_bus) = { "osc_13mhz", "run" };
MUX_RO_RATE_RO_OPS(clk_pxa27x_system_bus, "system_bus");
static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned int a, l, osc_forced;
unsigned long cccr = readl(clk_regs + CCCR);
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
a = cccr & (1 << CCCR_A_BIT);
l = ccsr & CCSR_L_MASK;
if (osc_forced || a)
return parent_rate;
if (l <= 10)
return parent_rate;
if (l <= 20)
return parent_rate / 2;
return parent_rate / 4;
}
static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
{
unsigned int osc_forced, a;
unsigned long cccr = readl(clk_regs + CCCR);
unsigned long ccsr = readl(clk_regs + CCSR);
osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
a = cccr & (1 << CCCR_A_BIT);
if (osc_forced)
return PXA_MEM_13Mhz;
if (a)
return PXA_MEM_SYSTEM_BUS;
else
return PXA_MEM_RUN;
}
PARENTS(clk_pxa27x_memory) = { "osc_13mhz", "system_bus", "run" };
MUX_RO_RATE_RO_OPS(clk_pxa27x_memory, "memory");
#define DUMMY_CLK(_con_id, _dev_id, _parent) \
{ .con_id = _con_id, .dev_id = _dev_id, .parent = _parent }
struct dummy_clk {
const char *con_id;
const char *dev_id;
const char *parent;
};
static struct dummy_clk dummy_clks[] __initdata = {
DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"),
DUMMY_CLK(NULL, "pxa-rtc", "osc_32_768khz"),
DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
};
static void __init pxa27x_dummy_clocks_init(void)
{
struct clk *clk;
struct dummy_clk *d;
const char *name;
int i;
for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) {
d = &dummy_clks[i];
name = d->dev_id ? d->dev_id : d->con_id;
clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1);
clk_register_clkdev(clk, d->con_id, d->dev_id);
}
}
static void __init pxa27x_base_clocks_init(void)
{
pxa27x_register_plls();
pxa27x_register_core();
clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
clk_register_clk_pxa27x_system_bus());
clkdev_pxa_register(CLK_NONE, "memory", NULL,
clk_register_clk_pxa27x_memory());
clk_register_clk_pxa27x_lcd_base();
}
int __init pxa27x_clocks_init(void __iomem *regs)
{
clk_regs = regs;
pxa27x_base_clocks_init();
pxa27x_dummy_clocks_init();
return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks), regs);
}
static void __init pxa27x_dt_clocks_init(struct device_node *np)
{
pxa27x_clocks_init(ioremap(0x41300000ul, 0x10));
clk_pxa_dt_common_init(np);
}
CLK_OF_DECLARE(pxa_clks, "marvell,pxa270-clocks", pxa27x_dt_clocks_init);
+58
View File
@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __CLK_PXA2XX_H
#define __CLK_PXA2XX_H
#define CCCR (0x0000) /* Core Clock Configuration Register */
#define CCSR (0x000C) /* Core Clock Status Register */
#define CKEN (0x0004) /* Clock Enable Register */
#define OSCC (0x0008) /* Oscillator Configuration Register */
#define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */
#define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */
#define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */
#define CCCR_CPDIS_BIT (31)
#define CCCR_PPDIS_BIT (30)
#define CCCR_LCD_26_BIT (27)
#define CCCR_A_BIT (25)
#define CCSR_N2_MASK CCCR_N_MASK
#define CCSR_M_MASK CCCR_M_MASK
#define CCSR_L_MASK CCCR_L_MASK
#define CCSR_N2_SHIFT 7
#define CKEN_AC97CONF (31) /* AC97 Controller Configuration */
#define CKEN_CAMERA (24) /* Camera Interface Clock Enable */
#define CKEN_SSP1 (23) /* SSP1 Unit Clock Enable */
#define CKEN_MEMC (22) /* Memory Controller Clock Enable */
#define CKEN_MEMSTK (21) /* Memory Stick Host Controller */
#define CKEN_IM (20) /* Internal Memory Clock Enable */
#define CKEN_KEYPAD (19) /* Keypad Interface Clock Enable */
#define CKEN_USIM (18) /* USIM Unit Clock Enable */
#define CKEN_MSL (17) /* MSL Unit Clock Enable */
#define CKEN_LCD (16) /* LCD Unit Clock Enable */
#define CKEN_PWRI2C (15) /* PWR I2C Unit Clock Enable */
#define CKEN_I2C (14) /* I2C Unit Clock Enable */
#define CKEN_FICP (13) /* FICP Unit Clock Enable */
#define CKEN_MMC (12) /* MMC Unit Clock Enable */
#define CKEN_USB (11) /* USB Unit Clock Enable */
#define CKEN_ASSP (10) /* ASSP (SSP3) Clock Enable */
#define CKEN_USBHOST (10) /* USB Host Unit Clock Enable */
#define CKEN_OSTIMER (9) /* OS Timer Unit Clock Enable */
#define CKEN_NSSP (9) /* NSSP (SSP2) Clock Enable */
#define CKEN_I2S (8) /* I2S Unit Clock Enable */
#define CKEN_BTUART (7) /* BTUART Unit Clock Enable */
#define CKEN_FFUART (6) /* FFUART Unit Clock Enable */
#define CKEN_STUART (5) /* STUART Unit Clock Enable */
#define CKEN_HWUART (4) /* HWUART Unit Clock Enable */
#define CKEN_SSP3 (4) /* SSP3 Unit Clock Enable */
#define CKEN_SSP (3) /* SSP Unit Clock Enable */
#define CKEN_SSP2 (3) /* SSP2 Unit Clock Enable */
#define CKEN_AC97 (2) /* AC97 Unit Clock Enable */
#define CKEN_PWM1 (1) /* PWM1 Clock Enable */
#define CKEN_PWM0 (0) /* PWM0 Clock Enable */
#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
#endif
+463
View File
@@ -0,0 +1,463 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Marvell PXA3xxx family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Heavily inspired from former arch/arm/mach-pxa/pxa3xx.c
*
* For non-devicetree platforms. Once pxa is fully converted to devicetree, this
* should go away.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/soc/pxa/cpu.h>
#include <linux/soc/pxa/smemc.h>
#include <linux/clk/pxa.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
#define KHz 1000
#define MHz (1000 * 1000)
#define ACCR (0x0000) /* Application Subsystem Clock Configuration Register */
#define ACSR (0x0004) /* Application Subsystem Clock Status Register */
#define AICSR (0x0008) /* Application Subsystem Interrupt Control/Status Register */
#define CKENA (0x000C) /* A Clock Enable Register */
#define CKENB (0x0010) /* B Clock Enable Register */
#define CKENC (0x0024) /* C Clock Enable Register */
#define AC97_DIV (0x0014) /* AC97 clock divisor value register */
#define ACCR_XPDIS (1 << 31) /* Core PLL Output Disable */
#define ACCR_SPDIS (1 << 30) /* System PLL Output Disable */
#define ACCR_D0CS (1 << 26) /* D0 Mode Clock Select */
#define ACCR_PCCE (1 << 11) /* Power Mode Change Clock Enable */
#define ACCR_DDR_D0CS (1 << 7) /* DDR SDRAM clock frequency in D0CS (PXA31x only) */
#define ACCR_SMCFS_MASK (0x7 << 23) /* Static Memory Controller Frequency Select */
#define ACCR_SFLFS_MASK (0x3 << 18) /* Frequency Select for Internal Memory Controller */
#define ACCR_XSPCLK_MASK (0x3 << 16) /* Core Frequency during Frequency Change */
#define ACCR_HSS_MASK (0x3 << 14) /* System Bus-Clock Frequency Select */
#define ACCR_DMCFS_MASK (0x3 << 12) /* Dynamic Memory Controller Clock Frequency Select */
#define ACCR_XN_MASK (0x7 << 8) /* Core PLL Turbo-Mode-to-Run-Mode Ratio */
#define ACCR_XL_MASK (0x1f) /* Core PLL Run-Mode-to-Oscillator Ratio */
#define ACCR_SMCFS(x) (((x) & 0x7) << 23)
#define ACCR_SFLFS(x) (((x) & 0x3) << 18)
#define ACCR_XSPCLK(x) (((x) & 0x3) << 16)
#define ACCR_HSS(x) (((x) & 0x3) << 14)
#define ACCR_DMCFS(x) (((x) & 0x3) << 12)
#define ACCR_XN(x) (((x) & 0x7) << 8)
#define ACCR_XL(x) ((x) & 0x1f)
/*
* Clock Enable Bit
*/
#define CKEN_LCD 1 /* < LCD Clock Enable */
#define CKEN_USBH 2 /* < USB host clock enable */
#define CKEN_CAMERA 3 /* < Camera interface clock enable */
#define CKEN_NAND 4 /* < NAND Flash Controller Clock Enable */
#define CKEN_USB2 6 /* < USB 2.0 client clock enable. */
#define CKEN_DMC 8 /* < Dynamic Memory Controller clock enable */
#define CKEN_SMC 9 /* < Static Memory Controller clock enable */
#define CKEN_ISC 10 /* < Internal SRAM Controller clock enable */
#define CKEN_BOOT 11 /* < Boot rom clock enable */
#define CKEN_MMC1 12 /* < MMC1 Clock enable */
#define CKEN_MMC2 13 /* < MMC2 clock enable */
#define CKEN_KEYPAD 14 /* < Keypand Controller Clock Enable */
#define CKEN_CIR 15 /* < Consumer IR Clock Enable */
#define CKEN_USIM0 17 /* < USIM[0] Clock Enable */
#define CKEN_USIM1 18 /* < USIM[1] Clock Enable */
#define CKEN_TPM 19 /* < TPM clock enable */
#define CKEN_UDC 20 /* < UDC clock enable */
#define CKEN_BTUART 21 /* < BTUART clock enable */
#define CKEN_FFUART 22 /* < FFUART clock enable */
#define CKEN_STUART 23 /* < STUART clock enable */
#define CKEN_AC97 24 /* < AC97 clock enable */
#define CKEN_TOUCH 25 /* < Touch screen Interface Clock Enable */
#define CKEN_SSP1 26 /* < SSP1 clock enable */
#define CKEN_SSP2 27 /* < SSP2 clock enable */
#define CKEN_SSP3 28 /* < SSP3 clock enable */
#define CKEN_SSP4 29 /* < SSP4 clock enable */
#define CKEN_MSL0 30 /* < MSL0 clock enable */
#define CKEN_PWM0 32 /* < PWM[0] clock enable */
#define CKEN_PWM1 33 /* < PWM[1] clock enable */
#define CKEN_I2C 36 /* < I2C clock enable */
#define CKEN_INTC 38 /* < Interrupt controller clock enable */
#define CKEN_GPIO 39 /* < GPIO clock enable */
#define CKEN_1WIRE 40 /* < 1-wire clock enable */
#define CKEN_HSIO2 41 /* < HSIO2 clock enable */
#define CKEN_MINI_IM 48 /* < Mini-IM */
#define CKEN_MINI_LCD 49 /* < Mini LCD */
#define CKEN_MMC3 5 /* < MMC3 Clock Enable */
#define CKEN_MVED 43 /* < MVED clock enable */
/* Note: GCU clock enable bit differs on PXA300/PXA310 and PXA320 */
#define CKEN_PXA300_GCU 42 /* Graphics controller clock enable */
#define CKEN_PXA320_GCU 7 /* Graphics controller clock enable */
enum {
PXA_CORE_60Mhz = 0,
PXA_CORE_RUN,
PXA_CORE_TURBO,
};
enum {
PXA_BUS_60Mhz = 0,
PXA_BUS_HSS,
};
/* crystal frequency to HSIO bus frequency multiplier (HSS) */
static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
/* crystal frequency to static memory controller multiplier (SMCFS) */
static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
static const char * const get_freq_khz[] = {
"core", "ring_osc_60mhz", "run", "cpll", "system_bus"
};
static void __iomem *clk_regs;
/*
* Get the clock frequency as reflected by ACSR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
*/
unsigned int pxa3xx_get_clk_frequency_khz(int info)
{
struct clk *clk;
unsigned long clks[5];
int i;
for (i = 0; i < 5; i++) {
clk = clk_get(NULL, get_freq_khz[i]);
if (IS_ERR(clk)) {
clks[i] = 0;
} else {
clks[i] = clk_get_rate(clk);
clk_put(clk);
}
}
if (info) {
pr_info("RO Mode clock: %ld.%02ldMHz\n",
clks[1] / 1000000, (clks[0] % 1000000) / 10000);
pr_info("Run Mode clock: %ld.%02ldMHz\n",
clks[2] / 1000000, (clks[1] % 1000000) / 10000);
pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
clks[3] / 1000000, (clks[2] % 1000000) / 10000);
pr_info("System bus clock: %ld.%02ldMHz\n",
clks[4] / 1000000, (clks[4] % 1000000) / 10000);
}
return (unsigned int)clks[0] / KHz;
}
void pxa3xx_clk_update_accr(u32 disable, u32 enable, u32 xclkcfg, u32 mask)
{
u32 accr = readl(clk_regs + ACCR);
accr &= ~disable;
accr |= enable;
writel(accr, clk_regs + ACCR);
if (xclkcfg)
__asm__("mcr p14, 0, %0, c6, c0, 0\n" : : "r"(xclkcfg));
while ((readl(clk_regs + ACSR) & mask) != (accr & mask))
cpu_relax();
}
static unsigned long clk_pxa3xx_ac97_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long ac97_div, rate;
ac97_div = readl(clk_regs + AC97_DIV);
/* This may loose precision for some rates but won't for the
* standard 24.576MHz.
*/
rate = parent_rate / 2;
rate /= ((ac97_div >> 12) & 0x7fff);
rate *= (ac97_div & 0xfff);
return rate;
}
PARENTS(clk_pxa3xx_ac97) = { "spll_624mhz" };
RATE_RO_OPS(clk_pxa3xx_ac97, "ac97");
static unsigned long clk_pxa3xx_smemc_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long acsr = readl(clk_regs + ACSR);
return (parent_rate / 48) * smcfs_mult[(acsr >> 23) & 0x7] /
pxa3xx_smemc_get_memclkdiv();
}
PARENTS(clk_pxa3xx_smemc) = { "spll_624mhz" };
RATE_RO_OPS(clk_pxa3xx_smemc, "smemc");
static bool pxa3xx_is_ring_osc_forced(void)
{
unsigned long acsr = readl(clk_regs + ACSR);
return acsr & ACCR_D0CS;
}
PARENTS(pxa3xx_pbus) = { "ring_osc_60mhz", "spll_624mhz" };
PARENTS(pxa3xx_32Khz_bus) = { "osc_32_768khz", "osc_32_768khz" };
PARENTS(pxa3xx_13MHz_bus) = { "osc_13mhz", "osc_13mhz" };
PARENTS(pxa3xx_ac97_bus) = { "ring_osc_60mhz", "ac97" };
PARENTS(pxa3xx_sbus) = { "ring_osc_60mhz", "system_bus" };
PARENTS(pxa3xx_smemcbus) = { "ring_osc_60mhz", "smemc" };
#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? CKENB : CKENA)
#define PXA3XX_CKEN(dev_id, con_id, parents, mult_lp, div_lp, mult_hp, \
div_hp, bit, is_lp, flags) \
PXA_CKEN(dev_id, con_id, bit, parents, mult_lp, div_lp, \
mult_hp, div_hp, is_lp, CKEN_AB(bit), \
(CKEN_ ## bit % 32), flags)
#define PXA3XX_PBUS_CKEN(dev_id, con_id, bit, mult_lp, div_lp, \
mult_hp, div_hp, delay) \
PXA3XX_CKEN(dev_id, con_id, pxa3xx_pbus_parents, mult_lp, \
div_lp, mult_hp, div_hp, bit, pxa3xx_is_ring_osc_forced, 0)
#define PXA3XX_CKEN_1RATE(dev_id, con_id, bit, parents) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
CKEN_AB(bit), (CKEN_ ## bit % 32), 0)
static struct desc_clk_cken pxa3xx_clocks[] __initdata = {
PXA3XX_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 4, 1, 42, 1),
PXA3XX_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 4, 1, 42, 1),
PXA3XX_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 4, 1, 42, 1),
PXA3XX_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 5, 1, 19, 0),
PXA3XX_PBUS_CKEN("pxa27x-udc", NULL, UDC, 1, 4, 1, 13, 5),
PXA3XX_PBUS_CKEN("pxa27x-ohci", NULL, USBH, 1, 4, 1, 13, 0),
PXA3XX_PBUS_CKEN("pxa3xx-u2d", NULL, USB2, 1, 4, 1, 13, 0),
PXA3XX_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 6, 1, 48, 0),
PXA3XX_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 6, 1, 48, 0),
PXA3XX_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC1, 1, 4, 1, 24, 0),
PXA3XX_PBUS_CKEN("pxa2xx-mci.1", NULL, MMC2, 1, 4, 1, 24, 0),
PXA3XX_PBUS_CKEN("pxa2xx-mci.2", NULL, MMC3, 1, 4, 1, 24, 0),
PXA3XX_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
pxa3xx_32Khz_bus_parents),
PXA3XX_CKEN_1RATE("pxa3xx-ssp.0", NULL, SSP1, pxa3xx_13MHz_bus_parents),
PXA3XX_CKEN_1RATE("pxa3xx-ssp.1", NULL, SSP2, pxa3xx_13MHz_bus_parents),
PXA3XX_CKEN_1RATE("pxa3xx-ssp.2", NULL, SSP3, pxa3xx_13MHz_bus_parents),
PXA3XX_CKEN_1RATE("pxa3xx-ssp.3", NULL, SSP4, pxa3xx_13MHz_bus_parents),
PXA3XX_CKEN(NULL, "AC97CLK", pxa3xx_ac97_bus_parents, 1, 4, 1, 1, AC97,
pxa3xx_is_ring_osc_forced, 0),
PXA3XX_CKEN(NULL, "CAMCLK", pxa3xx_sbus_parents, 1, 2, 1, 1, CAMERA,
pxa3xx_is_ring_osc_forced, 0),
PXA3XX_CKEN("pxa2xx-fb", NULL, pxa3xx_sbus_parents, 1, 1, 1, 1, LCD,
pxa3xx_is_ring_osc_forced, 0),
PXA3XX_CKEN("pxa2xx-pcmcia", NULL, pxa3xx_smemcbus_parents, 1, 4,
1, 1, SMC, pxa3xx_is_ring_osc_forced, CLK_IGNORE_UNUSED),
};
static struct desc_clk_cken pxa300_310_clocks[] __initdata = {
PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA300_GCU, 1, 1, 1, 1, 0),
PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 4, 0),
PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
};
static struct desc_clk_cken pxa320_clocks[] __initdata = {
PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 6, 0),
PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA320_GCU, 1, 1, 1, 1, 0),
PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
};
static struct desc_clk_cken pxa93x_clocks[] __initdata = {
PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA300_GCU, 1, 1, 1, 1, 0),
PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 4, 0),
PXA3XX_CKEN_1RATE("pxa93x-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
};
static unsigned long clk_pxa3xx_system_bus_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long acsr = readl(clk_regs + ACSR);
unsigned int hss = (acsr >> 14) & 0x3;
if (pxa3xx_is_ring_osc_forced())
return parent_rate;
return parent_rate / 48 * hss_mult[hss];
}
static u8 clk_pxa3xx_system_bus_get_parent(struct clk_hw *hw)
{
if (pxa3xx_is_ring_osc_forced())
return PXA_BUS_60Mhz;
else
return PXA_BUS_HSS;
}
PARENTS(clk_pxa3xx_system_bus) = { "ring_osc_60mhz", "spll_624mhz" };
MUX_RO_RATE_RO_OPS(clk_pxa3xx_system_bus, "system_bus");
static unsigned long clk_pxa3xx_core_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate;
}
static u8 clk_pxa3xx_core_get_parent(struct clk_hw *hw)
{
unsigned long xclkcfg;
unsigned int t;
if (pxa3xx_is_ring_osc_forced())
return PXA_CORE_60Mhz;
/* Read XCLKCFG register turbo bit */
__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
t = xclkcfg & 0x1;
if (t)
return PXA_CORE_TURBO;
return PXA_CORE_RUN;
}
PARENTS(clk_pxa3xx_core) = { "ring_osc_60mhz", "run", "cpll" };
MUX_RO_RATE_RO_OPS(clk_pxa3xx_core, "core");
static unsigned long clk_pxa3xx_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long acsr = readl(clk_regs + ACSR);
unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
unsigned int t, xclkcfg;
/* Read XCLKCFG register turbo bit */
__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
t = xclkcfg & 0x1;
return t ? (parent_rate / xn) * 2 : parent_rate;
}
PARENTS(clk_pxa3xx_run) = { "cpll" };
RATE_RO_OPS(clk_pxa3xx_run, "run");
static unsigned long clk_pxa3xx_cpll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long acsr = readl(clk_regs + ACSR);
unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
unsigned int xl = acsr & ACCR_XL_MASK;
unsigned int t, xclkcfg;
/* Read XCLKCFG register turbo bit */
__asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
t = xclkcfg & 0x1;
pr_info("RJK: parent_rate=%lu, xl=%u, xn=%u\n", parent_rate, xl, xn);
return t ? parent_rate * xl * xn : parent_rate * xl;
}
PARENTS(clk_pxa3xx_cpll) = { "osc_13mhz" };
RATE_RO_OPS(clk_pxa3xx_cpll, "cpll");
static void __init pxa3xx_register_core(void)
{
clk_register_clk_pxa3xx_cpll();
clk_register_clk_pxa3xx_run();
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa3xx_core());
}
static void __init pxa3xx_register_plls(void)
{
clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
CLK_GET_RATE_NOCACHE,
13 * MHz);
clkdev_pxa_register(CLK_OSC32k768, "osc_32_768khz", NULL,
clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
CLK_GET_RATE_NOCACHE,
32768));
clk_register_fixed_rate(NULL, "ring_osc_120mhz", NULL,
CLK_GET_RATE_NOCACHE,
120 * MHz);
clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
clk_register_fixed_factor(NULL, "spll_624mhz", "osc_13mhz", 0, 48, 1);
clk_register_fixed_factor(NULL, "ring_osc_60mhz", "ring_osc_120mhz",
0, 1, 2);
}
#define DUMMY_CLK(_con_id, _dev_id, _parent) \
{ .con_id = _con_id, .dev_id = _dev_id, .parent = _parent }
struct dummy_clk {
const char *con_id;
const char *dev_id;
const char *parent;
};
static struct dummy_clk dummy_clks[] __initdata = {
DUMMY_CLK(NULL, "pxa93x-gpio", "osc_13mhz"),
DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
DUMMY_CLK(NULL, "pxa3xx-pwri2c.1", "osc_13mhz"),
};
static void __init pxa3xx_dummy_clocks_init(void)
{
struct clk *clk;
struct dummy_clk *d;
const char *name;
int i;
for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) {
d = &dummy_clks[i];
name = d->dev_id ? d->dev_id : d->con_id;
clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1);
clk_register_clkdev(clk, d->con_id, d->dev_id);
}
}
static void __init pxa3xx_base_clocks_init(void __iomem *oscc_reg)
{
struct clk *clk;
pxa3xx_register_plls();
pxa3xx_register_core();
clk_register_clk_pxa3xx_system_bus();
clk_register_clk_pxa3xx_ac97();
clk_register_clk_pxa3xx_smemc();
clk = clk_register_gate(NULL, "CLK_POUT",
"osc_13mhz", 0, oscc_reg, 11, 0, NULL);
clk_register_clkdev(clk, "CLK_POUT", NULL);
clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL,
clk_register_fixed_factor(NULL, "os-timer0",
"osc_13mhz", 0, 1, 4));
}
int __init pxa3xx_clocks_init(void __iomem *regs, void __iomem *oscc_reg)
{
int ret;
clk_regs = regs;
pxa3xx_base_clocks_init(oscc_reg);
pxa3xx_dummy_clocks_init();
ret = clk_pxa_cken_init(pxa3xx_clocks, ARRAY_SIZE(pxa3xx_clocks), regs);
if (ret)
return ret;
if (cpu_is_pxa320())
return clk_pxa_cken_init(pxa320_clocks,
ARRAY_SIZE(pxa320_clocks), regs);
if (cpu_is_pxa300() || cpu_is_pxa310())
return clk_pxa_cken_init(pxa300_310_clocks,
ARRAY_SIZE(pxa300_310_clocks), regs);
return clk_pxa_cken_init(pxa93x_clocks, ARRAY_SIZE(pxa93x_clocks), regs);
}
static void __init pxa3xx_dt_clocks_init(struct device_node *np)
{
pxa3xx_clocks_init(ioremap(0x41340000, 0x10), ioremap(0x41350000, 4));
clk_pxa_dt_common_init(np);
}
CLK_OF_DECLARE(pxa_clks, "marvell,pxa300-clocks", pxa3xx_dt_clocks_init);