mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
clk: renesas: Updates for v6.12 (take two)
- Add USB clocks, resets and power domains on RZ/G3S,
- Add Generic Timer (GTM), I2C Bus Interface (RIIC), SD/MMC Host
Interface (SDHI) and Watchdog Timer (WDT) clocks and resets on
RZ/V2H,
- Miscellaneous fixes and improvements.
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCZtce6wAKCRCKwlD9ZEnx
cHiTAP995jEtnc5CnmmWV3SY5bEPRRg4oI3/3R84r2whPmz5AgEA1CcmIXCmSzyD
UVlysuC6DIIUvnZjxnZxq41fBTAGfwM=
=OrG8
-----END PGP SIGNATURE-----
Merge tag 'renesas-clk-for-v6.12-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-renesas
Pull more Renesas clk driver updates from Geert Uytterhoeven:
- Add USB clocks, resets and power domains on RZ/G3S
- Add Generic Timer (GTM), I2C Bus Interface (RIIC), SD/MMC Host
Interface (SDHI) and Watchdog Timer (WDT) clocks and resets on
RZ/V2H
- Miscellaneous fixes and improvements
* tag 'renesas-clk-for-v6.12-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers:
clk: renesas: r9a09g057: Add clock and reset entries for GTM/RIIC/SDHI/WDT
clk: renesas: rzv2h: Add support for dynamic switching divider clocks
clk: renesas: r9a08g045: Add clocks, resets and power domains for USB
dt-bindings: clock: renesas,cpg-clocks: Add top-level constraints
This commit is contained in:
commit
f37213104a
|
|
@ -32,12 +32,16 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks: true
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
clock-output-names: true
|
||||
clock-output-names:
|
||||
minItems: 3
|
||||
maxItems: 17
|
||||
|
||||
renesas,mode:
|
||||
description: Board-specific settings of the MD_CK* bits on R-Mobile A1
|
||||
|
|
|
|||
|
|
@ -208,6 +208,10 @@ static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = {
|
|||
DEF_MOD("sdhi2_imclk2", R9A08G045_SDHI2_IMCLK2, CLK_SD2_DIV4, 0x554, 9),
|
||||
DEF_MOD("sdhi2_clk_hs", R9A08G045_SDHI2_CLK_HS, R9A08G045_CLK_SD2, 0x554, 10),
|
||||
DEF_MOD("sdhi2_aclk", R9A08G045_SDHI2_ACLK, R9A08G045_CLK_P1, 0x554, 11),
|
||||
DEF_MOD("usb0_host", R9A08G045_USB_U2H0_HCLK, R9A08G045_CLK_P1, 0x578, 0),
|
||||
DEF_MOD("usb1_host", R9A08G045_USB_U2H1_HCLK, R9A08G045_CLK_P1, 0x578, 1),
|
||||
DEF_MOD("usb0_func", R9A08G045_USB_U2P_EXR_CPUCLK, R9A08G045_CLK_P1, 0x578, 2),
|
||||
DEF_MOD("usb_pclk", R9A08G045_USB_PCLK, R9A08G045_CLK_P1, 0x578, 3),
|
||||
DEF_COUPLED("eth0_axi", R9A08G045_ETH0_CLK_AXI, R9A08G045_CLK_M0, 0x57c, 0),
|
||||
DEF_COUPLED("eth0_chi", R9A08G045_ETH0_CLK_CHI, R9A08G045_CLK_ZT, 0x57c, 0),
|
||||
DEF_MOD("eth0_refclk", R9A08G045_ETH0_REFCLK, R9A08G045_CLK_HP, 0x57c, 8),
|
||||
|
|
@ -233,6 +237,10 @@ static const struct rzg2l_reset r9a08g045_resets[] = {
|
|||
DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0),
|
||||
DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1),
|
||||
DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2),
|
||||
DEF_RST(R9A08G045_USB_U2H0_HRESETN, 0x878, 0),
|
||||
DEF_RST(R9A08G045_USB_U2H1_HRESETN, 0x878, 1),
|
||||
DEF_RST(R9A08G045_USB_U2P_EXL_SYSRST, 0x878, 2),
|
||||
DEF_RST(R9A08G045_USB_PRESETN, 0x878, 3),
|
||||
DEF_RST(R9A08G045_ETH0_RST_HW_N, 0x87c, 0),
|
||||
DEF_RST(R9A08G045_ETH1_RST_HW_N, 0x87c, 1),
|
||||
DEF_RST(R9A08G045_I2C0_MRST, 0x880, 0),
|
||||
|
|
@ -280,6 +288,15 @@ static const struct rzg2l_cpg_pm_domain_init_data r9a08g045_pm_domains[] = {
|
|||
DEF_PD("sdhi2", R9A08G045_PD_SDHI2,
|
||||
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)),
|
||||
RZG2L_PD_F_NONE),
|
||||
DEF_PD("usb0", R9A08G045_PD_USB0,
|
||||
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, GENMASK(6, 5)),
|
||||
RZG2L_PD_F_NONE),
|
||||
DEF_PD("usb1", R9A08G045_PD_USB1,
|
||||
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(7)),
|
||||
RZG2L_PD_F_NONE),
|
||||
DEF_PD("usb-phy", R9A08G045_PD_USB_PHY,
|
||||
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(4)),
|
||||
RZG2L_PD_F_NONE),
|
||||
DEF_PD("eth0", R9A08G045_PD_ETHER0,
|
||||
DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)),
|
||||
RZG2L_PD_F_NONE),
|
||||
|
|
|
|||
|
|
@ -25,16 +25,31 @@ enum clk_ids {
|
|||
|
||||
/* PLL Clocks */
|
||||
CLK_PLLCM33,
|
||||
CLK_PLLCLN,
|
||||
CLK_PLLDTY,
|
||||
CLK_PLLCA55,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_PLLCM33_DIV16,
|
||||
CLK_PLLCLN_DIV2,
|
||||
CLK_PLLCLN_DIV8,
|
||||
CLK_PLLCLN_DIV16,
|
||||
CLK_PLLDTY_ACPU,
|
||||
CLK_PLLDTY_ACPU_DIV4,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
};
|
||||
|
||||
static const struct clk_div_table dtable_2_64[] = {
|
||||
{0, 2},
|
||||
{1, 4},
|
||||
{2, 8},
|
||||
{3, 16},
|
||||
{4, 64},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL),
|
||||
|
|
@ -43,23 +58,92 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
|
|||
|
||||
/* PLL Clocks */
|
||||
DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".pllcln", CLK_PLLCLN, CLK_QEXTAL, 200, 3),
|
||||
DEF_FIXED(".plldty", CLK_PLLDTY, CLK_QEXTAL, 200, 3),
|
||||
DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLL_CONF(0x64)),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_FIXED(".pllcm33_div16", CLK_PLLCM33_DIV16, CLK_PLLCM33, 1, 16),
|
||||
|
||||
DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2),
|
||||
DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8),
|
||||
DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16),
|
||||
|
||||
DEF_DDIV(".plldty_acpu", CLK_PLLDTY_ACPU, CLK_PLLDTY, CDDIV0_DIVCTL2, dtable_2_64),
|
||||
DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4),
|
||||
|
||||
/* Core Clocks */
|
||||
DEF_FIXED("sys_0_pclk", R9A09G057_SYS_0_PCLK, CLK_QEXTAL, 1, 1),
|
||||
DEF_FIXED("iotop_0_shclk", R9A09G057_IOTOP_0_SHCLK, CLK_PLLCM33_DIV16, 1, 1),
|
||||
};
|
||||
|
||||
static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
|
||||
DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3),
|
||||
DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4),
|
||||
DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5),
|
||||
DEF_MOD("gtm_3_pclk", CLK_PLLCLN_DIV16, 4, 6, 2, 6),
|
||||
DEF_MOD("gtm_4_pclk", CLK_PLLCLN_DIV16, 4, 7, 2, 7),
|
||||
DEF_MOD("gtm_5_pclk", CLK_PLLCLN_DIV16, 4, 8, 2, 8),
|
||||
DEF_MOD("gtm_6_pclk", CLK_PLLCLN_DIV16, 4, 9, 2, 9),
|
||||
DEF_MOD("gtm_7_pclk", CLK_PLLCLN_DIV16, 4, 10, 2, 10),
|
||||
DEF_MOD("wdt_0_clkp", CLK_PLLCM33_DIV16, 4, 11, 2, 11),
|
||||
DEF_MOD("wdt_0_clk_loco", CLK_QEXTAL, 4, 12, 2, 12),
|
||||
DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13),
|
||||
DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14),
|
||||
DEF_MOD("wdt_2_clkp", CLK_PLLCLN_DIV16, 4, 15, 2, 15),
|
||||
DEF_MOD("wdt_2_clk_loco", CLK_QEXTAL, 5, 0, 2, 16),
|
||||
DEF_MOD("wdt_3_clkp", CLK_PLLCLN_DIV16, 5, 1, 2, 17),
|
||||
DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18),
|
||||
DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15),
|
||||
DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19),
|
||||
DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20),
|
||||
DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21),
|
||||
DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22),
|
||||
DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23),
|
||||
DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24),
|
||||
DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25),
|
||||
DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26),
|
||||
DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27),
|
||||
DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3),
|
||||
DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4),
|
||||
DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5),
|
||||
DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6),
|
||||
DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7),
|
||||
DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8),
|
||||
DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9),
|
||||
DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10),
|
||||
DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11),
|
||||
DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12),
|
||||
DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13),
|
||||
DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14),
|
||||
};
|
||||
|
||||
static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
|
||||
DEF_RST(6, 13, 2, 30), /* GTM_0_PRESETZ */
|
||||
DEF_RST(6, 14, 2, 31), /* GTM_1_PRESETZ */
|
||||
DEF_RST(6, 15, 3, 0), /* GTM_2_PRESETZ */
|
||||
DEF_RST(7, 0, 3, 1), /* GTM_3_PRESETZ */
|
||||
DEF_RST(7, 1, 3, 2), /* GTM_4_PRESETZ */
|
||||
DEF_RST(7, 2, 3, 3), /* GTM_5_PRESETZ */
|
||||
DEF_RST(7, 3, 3, 4), /* GTM_6_PRESETZ */
|
||||
DEF_RST(7, 4, 3, 5), /* GTM_7_PRESETZ */
|
||||
DEF_RST(7, 5, 3, 6), /* WDT_0_RESET */
|
||||
DEF_RST(7, 6, 3, 7), /* WDT_1_RESET */
|
||||
DEF_RST(7, 7, 3, 8), /* WDT_2_RESET */
|
||||
DEF_RST(7, 8, 3, 9), /* WDT_3_RESET */
|
||||
DEF_RST(9, 5, 4, 6), /* SCIF_0_RST_SYSTEM_N */
|
||||
DEF_RST(9, 8, 4, 9), /* RIIC_0_MRST */
|
||||
DEF_RST(9, 9, 4, 10), /* RIIC_1_MRST */
|
||||
DEF_RST(9, 10, 4, 11), /* RIIC_2_MRST */
|
||||
DEF_RST(9, 11, 4, 12), /* RIIC_3_MRST */
|
||||
DEF_RST(9, 12, 4, 13), /* RIIC_4_MRST */
|
||||
DEF_RST(9, 13, 4, 14), /* RIIC_5_MRST */
|
||||
DEF_RST(9, 14, 4, 15), /* RIIC_6_MRST */
|
||||
DEF_RST(9, 15, 4, 16), /* RIIC_7_MRST */
|
||||
DEF_RST(10, 0, 4, 17), /* RIIC_8_MRST */
|
||||
DEF_RST(10, 7, 4, 24), /* SDHI_0_IXRST */
|
||||
DEF_RST(10, 8, 4, 25), /* SDHI_1_IXRST */
|
||||
DEF_RST(10, 9, 4, 26), /* SDHI_2_IXRST */
|
||||
};
|
||||
|
||||
const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {
|
||||
|
|
|
|||
|
|
@ -45,14 +45,19 @@
|
|||
#define PDIV(val) FIELD_GET(GENMASK(5, 0), (val))
|
||||
#define SDIV(val) FIELD_GET(GENMASK(2, 0), (val))
|
||||
|
||||
#define DDIV_DIVCTL_WEN(shift) BIT((shift) + 16)
|
||||
|
||||
#define GET_MOD_CLK_ID(base, index, bit) \
|
||||
((base) + ((((index) * (16))) + (bit)))
|
||||
|
||||
#define CPG_CLKSTATUS0 (0x700)
|
||||
|
||||
/**
|
||||
* struct rzv2h_cpg_priv - Clock Pulse Generator Private Data
|
||||
*
|
||||
* @dev: CPG device
|
||||
* @base: CPG register block base address
|
||||
* @rmw_lock: protects register accesses
|
||||
* @clks: Array containing all Core and Module Clocks
|
||||
* @num_core_clks: Number of Core Clocks in clks[]
|
||||
* @num_mod_clks: Number of Module Clocks in clks[]
|
||||
|
|
@ -64,6 +69,7 @@
|
|||
struct rzv2h_cpg_priv {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
spinlock_t rmw_lock;
|
||||
|
||||
struct clk **clks;
|
||||
unsigned int num_core_clks;
|
||||
|
|
@ -108,6 +114,21 @@ struct mod_clock {
|
|||
|
||||
#define to_mod_clock(_hw) container_of(_hw, struct mod_clock, hw)
|
||||
|
||||
/**
|
||||
* struct ddiv_clk - DDIV clock
|
||||
*
|
||||
* @priv: CPG private data
|
||||
* @div: divider clk
|
||||
* @mon: monitor bit in CPG_CLKSTATUS0 register
|
||||
*/
|
||||
struct ddiv_clk {
|
||||
struct rzv2h_cpg_priv *priv;
|
||||
struct clk_divider div;
|
||||
u8 mon;
|
||||
};
|
||||
|
||||
#define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
|
||||
|
||||
static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
|
@ -161,7 +182,7 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
|
|||
init.num_parents = 1;
|
||||
|
||||
pll_clk->hw.init = &init;
|
||||
pll_clk->conf = core->conf;
|
||||
pll_clk->conf = core->cfg.conf;
|
||||
pll_clk->base = base;
|
||||
pll_clk->priv = priv;
|
||||
pll_clk->type = core->type;
|
||||
|
|
@ -173,6 +194,143 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
|
|||
return pll_clk->hw.clk;
|
||||
}
|
||||
|
||||
static unsigned long rzv2h_ddiv_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
unsigned int val;
|
||||
|
||||
val = readl(divider->reg) >> divider->shift;
|
||||
val &= clk_div_mask(divider->width);
|
||||
|
||||
return divider_recalc_rate(hw, parent_rate, val, divider->table,
|
||||
divider->flags, divider->width);
|
||||
}
|
||||
|
||||
static long rzv2h_ddiv_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
|
||||
return divider_round_rate(hw, rate, prate, divider->table,
|
||||
divider->width, divider->flags);
|
||||
}
|
||||
|
||||
static int rzv2h_ddiv_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
|
||||
return divider_determine_rate(hw, req, divider->table, divider->width,
|
||||
divider->flags);
|
||||
}
|
||||
|
||||
static inline int rzv2h_cpg_wait_ddiv_clk_update_done(void __iomem *base, u8 mon)
|
||||
{
|
||||
u32 bitmask = BIT(mon);
|
||||
u32 val;
|
||||
|
||||
return readl_poll_timeout_atomic(base + CPG_CLKSTATUS0, val, !(val & bitmask), 10, 200);
|
||||
}
|
||||
|
||||
static int rzv2h_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_divider *divider = to_clk_divider(hw);
|
||||
struct ddiv_clk *ddiv = to_ddiv_clock(divider);
|
||||
struct rzv2h_cpg_priv *priv = ddiv->priv;
|
||||
unsigned long flags = 0;
|
||||
int value;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
value = divider_get_val(rate, parent_rate, divider->table,
|
||||
divider->width, divider->flags);
|
||||
if (value < 0)
|
||||
return value;
|
||||
|
||||
spin_lock_irqsave(divider->lock, flags);
|
||||
|
||||
ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
|
||||
if (ret)
|
||||
goto ddiv_timeout;
|
||||
|
||||
val = readl(divider->reg) | DDIV_DIVCTL_WEN(divider->shift);
|
||||
val &= ~(clk_div_mask(divider->width) << divider->shift);
|
||||
val |= (u32)value << divider->shift;
|
||||
writel(val, divider->reg);
|
||||
|
||||
ret = rzv2h_cpg_wait_ddiv_clk_update_done(priv->base, ddiv->mon);
|
||||
if (ret)
|
||||
goto ddiv_timeout;
|
||||
|
||||
spin_unlock_irqrestore(divider->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
ddiv_timeout:
|
||||
spin_unlock_irqrestore(divider->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct clk_ops rzv2h_ddiv_clk_divider_ops = {
|
||||
.recalc_rate = rzv2h_ddiv_recalc_rate,
|
||||
.round_rate = rzv2h_ddiv_round_rate,
|
||||
.determine_rate = rzv2h_ddiv_determine_rate,
|
||||
.set_rate = rzv2h_ddiv_set_rate,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
rzv2h_cpg_ddiv_clk_register(const struct cpg_core_clk *core,
|
||||
struct rzv2h_cpg_priv *priv)
|
||||
{
|
||||
struct ddiv cfg_ddiv = core->cfg.ddiv;
|
||||
struct clk_init_data init = {};
|
||||
struct device *dev = priv->dev;
|
||||
u8 shift = cfg_ddiv.shift;
|
||||
u8 width = cfg_ddiv.width;
|
||||
const struct clk *parent;
|
||||
const char *parent_name;
|
||||
struct clk_divider *div;
|
||||
struct ddiv_clk *ddiv;
|
||||
int ret;
|
||||
|
||||
parent = priv->clks[core->parent];
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
|
||||
parent_name = __clk_get_name(parent);
|
||||
|
||||
if ((shift + width) > 16)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
ddiv = devm_kzalloc(priv->dev, sizeof(*ddiv), GFP_KERNEL);
|
||||
if (!ddiv)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = core->name;
|
||||
init.ops = &rzv2h_ddiv_clk_divider_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
ddiv->priv = priv;
|
||||
ddiv->mon = cfg_ddiv.monbit;
|
||||
div = &ddiv->div;
|
||||
div->reg = priv->base + cfg_ddiv.offset;
|
||||
div->shift = shift;
|
||||
div->width = width;
|
||||
div->flags = core->flag;
|
||||
div->lock = &priv->rmw_lock;
|
||||
div->hw.init = &init;
|
||||
div->table = core->dtable;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &div->hw);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return div->hw.clk;
|
||||
}
|
||||
|
||||
static struct clk
|
||||
*rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
|
|
@ -254,6 +412,9 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
|
|||
case CLK_TYPE_PLL:
|
||||
clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops);
|
||||
break;
|
||||
case CLK_TYPE_DDIV:
|
||||
clk = rzv2h_cpg_ddiv_clk_register(core, priv);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -612,6 +773,8 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&priv->rmw_lock);
|
||||
|
||||
priv->dev = dev;
|
||||
|
||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,33 @@
|
|||
#ifndef __RENESAS_RZV2H_CPG_H__
|
||||
#define __RENESAS_RZV2H_CPG_H__
|
||||
|
||||
/**
|
||||
* struct ddiv - Structure for dynamic switching divider
|
||||
*
|
||||
* @offset: register offset
|
||||
* @shift: position of the divider bit
|
||||
* @width: width of the divider
|
||||
* @monbit: monitor bit in CPG_CLKSTATUS0 register
|
||||
*/
|
||||
struct ddiv {
|
||||
unsigned int offset:11;
|
||||
unsigned int shift:4;
|
||||
unsigned int width:4;
|
||||
unsigned int monbit:5;
|
||||
};
|
||||
|
||||
#define DDIV_PACK(_offset, _shift, _width, _monbit) \
|
||||
((struct ddiv){ \
|
||||
.offset = _offset, \
|
||||
.shift = _shift, \
|
||||
.width = _width, \
|
||||
.monbit = _monbit \
|
||||
})
|
||||
|
||||
#define CPG_CDDIV0 (0x400)
|
||||
|
||||
#define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
|
||||
|
||||
/**
|
||||
* Definitions of CPG Core Clocks
|
||||
*
|
||||
|
|
@ -23,7 +50,12 @@ struct cpg_core_clk {
|
|||
unsigned int div;
|
||||
unsigned int mult;
|
||||
unsigned int type;
|
||||
unsigned int conf;
|
||||
union {
|
||||
unsigned int conf;
|
||||
struct ddiv ddiv;
|
||||
} cfg;
|
||||
const struct clk_div_table *dtable;
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
enum clk_types {
|
||||
|
|
@ -31,6 +63,7 @@ enum clk_types {
|
|||
CLK_TYPE_IN, /* External Clock Input */
|
||||
CLK_TYPE_FF, /* Fixed Factor Clock */
|
||||
CLK_TYPE_PLL,
|
||||
CLK_TYPE_DDIV, /* Dynamic Switching Divider */
|
||||
};
|
||||
|
||||
/* BIT(31) indicates if CLK1/2 are accessible or not */
|
||||
|
|
@ -44,11 +77,17 @@ enum clk_types {
|
|||
#define DEF_BASE(_name, _id, _type, _parent...) \
|
||||
DEF_TYPE(_name, _id, _type, .parent = _parent)
|
||||
#define DEF_PLL(_name, _id, _parent, _conf) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .conf = _conf)
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.conf = _conf)
|
||||
#define DEF_INPUT(_name, _id) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_IN)
|
||||
#define DEF_FIXED(_name, _id, _parent, _mult, _div) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
|
||||
#define DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_DDIV, \
|
||||
.cfg.ddiv = _ddiv_packed, \
|
||||
.parent = _parent, \
|
||||
.dtable = _dtable, \
|
||||
.flag = CLK_DIVIDER_HIWORD_MASK)
|
||||
|
||||
/**
|
||||
* struct rzv2h_mod_clk - Module Clocks definitions
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user