|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | +/* |
| 3 | + * RZ/V2M Clock Pulse Generator / Module Standby and Software Reset |
| 4 | + * |
| 5 | + * Copyright (C) 2022 Renesas Electronics Corp. |
| 6 | + * |
| 7 | + * Based on r9a07g044-cpg.c |
| 8 | + */ |
| 9 | + |
| 10 | +#include <linux/clk-provider.h> |
| 11 | +#include <linux/device.h> |
| 12 | +#include <linux/init.h> |
| 13 | +#include <linux/kernel.h> |
| 14 | + |
| 15 | +#include <dt-bindings/clock/r9a09g011-cpg.h> |
| 16 | + |
| 17 | +#include "rzg2l-cpg.h" |
| 18 | + |
| 19 | +#define RZV2M_SAMPLL4_CLK1 0x104 |
| 20 | +#define RZV2M_SAMPLL4_CLK2 0x108 |
| 21 | + |
| 22 | +#define PLL4_CONF (RZV2M_SAMPLL4_CLK1 << 22 | RZV2M_SAMPLL4_CLK2 << 12) |
| 23 | + |
| 24 | +#define DIV_A DDIV_PACK(0x200, 0, 3) |
| 25 | +#define DIV_B DDIV_PACK(0x204, 0, 2) |
| 26 | +#define DIV_E DDIV_PACK(0x204, 8, 1) |
| 27 | +#define DIV_W DDIV_PACK(0x328, 0, 3) |
| 28 | + |
| 29 | +#define SEL_B SEL_PLL_PACK(0x214, 0, 1) |
| 30 | +#define SEL_E SEL_PLL_PACK(0x214, 2, 1) |
| 31 | +#define SEL_W0 SEL_PLL_PACK(0x32C, 0, 1) |
| 32 | + |
| 33 | +enum clk_ids { |
| 34 | + /* Core Clock Outputs exported to DT */ |
| 35 | + LAST_DT_CORE_CLK = 0, |
| 36 | + |
| 37 | + /* External Input Clocks */ |
| 38 | + CLK_EXTAL, |
| 39 | + |
| 40 | + /* Internal Core Clocks */ |
| 41 | + CLK_MAIN, |
| 42 | + CLK_MAIN_24, |
| 43 | + CLK_MAIN_2, |
| 44 | + CLK_PLL1, |
| 45 | + CLK_PLL2, |
| 46 | + CLK_PLL2_800, |
| 47 | + CLK_PLL2_400, |
| 48 | + CLK_PLL2_200, |
| 49 | + CLK_PLL2_100, |
| 50 | + CLK_PLL4, |
| 51 | + CLK_DIV_A, |
| 52 | + CLK_DIV_B, |
| 53 | + CLK_DIV_E, |
| 54 | + CLK_DIV_W, |
| 55 | + CLK_SEL_B, |
| 56 | + CLK_SEL_B_D2, |
| 57 | + CLK_SEL_E, |
| 58 | + CLK_SEL_W0, |
| 59 | + |
| 60 | + /* Module Clocks */ |
| 61 | + MOD_CLK_BASE |
| 62 | +}; |
| 63 | + |
| 64 | +/* Divider tables */ |
| 65 | +static const struct clk_div_table dtable_diva[] = { |
| 66 | + {0, 1}, |
| 67 | + {1, 2}, |
| 68 | + {2, 3}, |
| 69 | + {3, 4}, |
| 70 | + {4, 6}, |
| 71 | + {5, 12}, |
| 72 | + {6, 24}, |
| 73 | + {0, 0}, |
| 74 | +}; |
| 75 | + |
| 76 | +static const struct clk_div_table dtable_divb[] = { |
| 77 | + {0, 1}, |
| 78 | + {1, 2}, |
| 79 | + {2, 4}, |
| 80 | + {3, 8}, |
| 81 | + {0, 0}, |
| 82 | +}; |
| 83 | + |
| 84 | +static const struct clk_div_table dtable_divw[] = { |
| 85 | + {0, 6}, |
| 86 | + {1, 7}, |
| 87 | + {2, 8}, |
| 88 | + {3, 9}, |
| 89 | + {4, 10}, |
| 90 | + {5, 11}, |
| 91 | + {6, 12}, |
| 92 | + {0, 0}, |
| 93 | +}; |
| 94 | + |
| 95 | +/* Mux clock tables */ |
| 96 | +static const char * const sel_b[] = { ".main", ".divb" }; |
| 97 | +static const char * const sel_e[] = { ".main", ".dive" }; |
| 98 | +static const char * const sel_w[] = { ".main", ".divw" }; |
| 99 | + |
| 100 | +static const struct cpg_core_clk r9a09g011_core_clks[] __initconst = { |
| 101 | + /* External Clock Inputs */ |
| 102 | + DEF_INPUT("extal", CLK_EXTAL), |
| 103 | + |
| 104 | + /* Internal Core Clocks */ |
| 105 | + DEF_FIXED(".main", CLK_MAIN, CLK_EXTAL, 1, 1), |
| 106 | + DEF_FIXED(".main_24", CLK_MAIN_24, CLK_MAIN, 1, 2), |
| 107 | + DEF_FIXED(".main_2", CLK_MAIN_2, CLK_MAIN, 1, 24), |
| 108 | + DEF_FIXED(".pll1", CLK_PLL1, CLK_MAIN_2, 498, 1), |
| 109 | + DEF_FIXED(".pll2", CLK_PLL2, CLK_MAIN_2, 800, 1), |
| 110 | + DEF_FIXED(".pll2_800", CLK_PLL2_800, CLK_PLL2, 1, 2), |
| 111 | + DEF_FIXED(".pll2_400", CLK_PLL2_400, CLK_PLL2_800, 1, 2), |
| 112 | + DEF_FIXED(".pll2_200", CLK_PLL2_200, CLK_PLL2_800, 1, 4), |
| 113 | + DEF_FIXED(".pll2_100", CLK_PLL2_100, CLK_PLL2_800, 1, 8), |
| 114 | + DEF_SAMPLL(".pll4", CLK_PLL4, CLK_MAIN_2, PLL4_CONF), |
| 115 | + |
| 116 | + DEF_DIV_RO(".diva", CLK_DIV_A, CLK_PLL1, DIV_A, dtable_diva), |
| 117 | + DEF_DIV_RO(".divb", CLK_DIV_B, CLK_PLL2_400, DIV_B, dtable_divb), |
| 118 | + DEF_DIV_RO(".dive", CLK_DIV_E, CLK_PLL2_100, DIV_E, NULL), |
| 119 | + DEF_DIV_RO(".divw", CLK_DIV_W, CLK_PLL4, DIV_W, dtable_divw), |
| 120 | + |
| 121 | + DEF_MUX_RO(".selb", CLK_SEL_B, SEL_B, sel_b), |
| 122 | + DEF_MUX_RO(".sele", CLK_SEL_E, SEL_E, sel_e), |
| 123 | + DEF_MUX(".selw0", CLK_SEL_W0, SEL_W0, sel_w), |
| 124 | + |
| 125 | + DEF_FIXED(".selb_d2", CLK_SEL_B_D2, CLK_SEL_B, 1, 2), |
| 126 | +}; |
| 127 | + |
| 128 | +static const struct rzg2l_mod_clk r9a09g011_mod_clks[] __initconst = { |
| 129 | + DEF_MOD("gic", R9A09G011_GIC_CLK, CLK_SEL_B_D2, 0x400, 5), |
| 130 | + DEF_MOD("syc_cnt_clk", R9A09G011_SYC_CNT_CLK, CLK_MAIN_24, 0x41c, 12), |
| 131 | + DEF_MOD("urt_pclk", R9A09G011_URT_PCLK, CLK_SEL_E, 0x438, 4), |
| 132 | + DEF_MOD("urt0_clk", R9A09G011_URT0_CLK, CLK_SEL_W0, 0x438, 5), |
| 133 | + DEF_MOD("ca53", R9A09G011_CA53_CLK, CLK_DIV_A, 0x448, 0), |
| 134 | +}; |
| 135 | + |
| 136 | +static const struct rzg2l_reset r9a09g011_resets[] = { |
| 137 | + DEF_RST_MON(R9A09G011_SYC_RST_N, 0x610, 9, 13), |
| 138 | +}; |
| 139 | + |
| 140 | +static const unsigned int r9a09g011_crit_mod_clks[] __initconst = { |
| 141 | + MOD_CLK_BASE + R9A09G011_CA53_CLK, |
| 142 | + MOD_CLK_BASE + R9A09G011_GIC_CLK, |
| 143 | + MOD_CLK_BASE + R9A09G011_SYC_CNT_CLK, |
| 144 | + MOD_CLK_BASE + R9A09G011_URT_PCLK, |
| 145 | +}; |
| 146 | + |
| 147 | +const struct rzg2l_cpg_info r9a09g011_cpg_info = { |
| 148 | + /* Core Clocks */ |
| 149 | + .core_clks = r9a09g011_core_clks, |
| 150 | + .num_core_clks = ARRAY_SIZE(r9a09g011_core_clks), |
| 151 | + .last_dt_core_clk = LAST_DT_CORE_CLK, |
| 152 | + .num_total_core_clks = MOD_CLK_BASE, |
| 153 | + |
| 154 | + /* Critical Module Clocks */ |
| 155 | + .crit_mod_clks = r9a09g011_crit_mod_clks, |
| 156 | + .num_crit_mod_clks = ARRAY_SIZE(r9a09g011_crit_mod_clks), |
| 157 | + |
| 158 | + /* Module Clocks */ |
| 159 | + .mod_clks = r9a09g011_mod_clks, |
| 160 | + .num_mod_clks = ARRAY_SIZE(r9a09g011_mod_clks), |
| 161 | + .num_hw_mod_clks = R9A09G011_CA53_CLK + 1, |
| 162 | + |
| 163 | + /* Resets */ |
| 164 | + .resets = r9a09g011_resets, |
| 165 | + .num_resets = ARRAY_SIZE(r9a09g011_resets), |
| 166 | + |
| 167 | + .has_clk_mon_regs = false, |
| 168 | +}; |
0 commit comments