root/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sunxi_r_ccu_init
  2. sun50i_h6_r_ccu_setup

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz>
   4  */
   5 
   6 #include <linux/clk-provider.h>
   7 #include <linux/of_address.h>
   8 #include <linux/platform_device.h>
   9 
  10 #include "ccu_common.h"
  11 #include "ccu_reset.h"
  12 
  13 #include "ccu_div.h"
  14 #include "ccu_gate.h"
  15 #include "ccu_mp.h"
  16 #include "ccu_nm.h"
  17 
  18 #include "ccu-sun50i-h6-r.h"
  19 
  20 /*
  21  * Information about AR100 and AHB/APB clocks in R_CCU are gathered from
  22  * clock definitions in the BSP source code.
  23  */
  24 
  25 static const char * const ar100_r_apb2_parents[] = { "osc24M", "osc32k",
  26                                                      "iosc", "pll-periph0" };
  27 static const struct ccu_mux_var_prediv ar100_r_apb2_predivs[] = {
  28         { .index = 3, .shift = 0, .width = 5 },
  29 };
  30 
  31 static struct ccu_div ar100_clk = {
  32         .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  33 
  34         .mux            = {
  35                 .shift  = 24,
  36                 .width  = 2,
  37 
  38                 .var_predivs    = ar100_r_apb2_predivs,
  39                 .n_var_predivs  = ARRAY_SIZE(ar100_r_apb2_predivs),
  40         },
  41 
  42         .common         = {
  43                 .reg            = 0x000,
  44                 .features       = CCU_FEATURE_VARIABLE_PREDIV,
  45                 .hw.init        = CLK_HW_INIT_PARENTS("ar100",
  46                                                       ar100_r_apb2_parents,
  47                                                       &ccu_div_ops,
  48                                                       0),
  49         },
  50 };
  51 
  52 static CLK_FIXED_FACTOR_HW(r_ahb_clk, "r-ahb", &ar100_clk.common.hw, 1, 1, 0);
  53 
  54 static struct ccu_div r_apb1_clk = {
  55         .div            = _SUNXI_CCU_DIV(0, 2),
  56 
  57         .common         = {
  58                 .reg            = 0x00c,
  59                 .hw.init        = CLK_HW_INIT("r-apb1",
  60                                               "r-ahb",
  61                                               &ccu_div_ops,
  62                                               0),
  63         },
  64 };
  65 
  66 static struct ccu_div r_apb2_clk = {
  67         .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
  68 
  69         .mux            = {
  70                 .shift  = 24,
  71                 .width  = 2,
  72 
  73                 .var_predivs    = ar100_r_apb2_predivs,
  74                 .n_var_predivs  = ARRAY_SIZE(ar100_r_apb2_predivs),
  75         },
  76 
  77         .common         = {
  78                 .reg            = 0x010,
  79                 .features       = CCU_FEATURE_VARIABLE_PREDIV,
  80                 .hw.init        = CLK_HW_INIT_PARENTS("r-apb2",
  81                                                       ar100_r_apb2_parents,
  82                                                       &ccu_div_ops,
  83                                                       0),
  84         },
  85 };
  86 
  87 /*
  88  * Information about the gate/resets are gathered from the clock header file
  89  * in the BSP source code, although most of them are unused. The existence
  90  * of the hardware block is verified with "3.1 Memory Mapping" chapter in
  91  * "Allwinner H6 V200 User Manual V1.1"; and the parent APB buses are verified
  92  * with "3.3.2.1 System Bus Tree" chapter inthe same document.
  93  */
  94 static SUNXI_CCU_GATE(r_apb1_timer_clk, "r-apb1-timer", "r-apb1",
  95                       0x11c, BIT(0), 0);
  96 static SUNXI_CCU_GATE(r_apb1_twd_clk,   "r-apb1-twd",   "r-apb1",
  97                       0x12c, BIT(0), 0);
  98 static SUNXI_CCU_GATE(r_apb1_pwm_clk,   "r-apb1-pwm",   "r-apb1",
  99                       0x13c, BIT(0), 0);
 100 static SUNXI_CCU_GATE(r_apb2_uart_clk,  "r-apb2-uart",  "r-apb2",
 101                       0x18c, BIT(0), 0);
 102 static SUNXI_CCU_GATE(r_apb2_i2c_clk,   "r-apb2-i2c",   "r-apb2",
 103                       0x19c, BIT(0), 0);
 104 static SUNXI_CCU_GATE(r_apb1_ir_clk,    "r-apb1-ir",    "r-apb1",
 105                       0x1cc, BIT(0), 0);
 106 static SUNXI_CCU_GATE(r_apb1_w1_clk,    "r-apb1-w1",    "r-apb1",
 107                       0x1ec, BIT(0), 0);
 108 
 109 /* Information of IR(RX) mod clock is gathered from BSP source code */
 110 static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" };
 111 static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
 112                                   r_mod0_default_parents, 0x1c0,
 113                                   0, 5,         /* M */
 114                                   8, 2,         /* P */
 115                                   24, 1,        /* mux */
 116                                   BIT(31),      /* gate */
 117                                   0);
 118 
 119 /*
 120  * BSP didn't use the 1-wire function at all now, and the information about
 121  * this mod clock is guessed from the IR mod clock above. The existence of
 122  * this mod clock is proven by BSP clock header, and the dividers are verified
 123  * by contents in the 1-wire related chapter of the User Manual.
 124  */
 125 
 126 static SUNXI_CCU_MP_WITH_MUX_GATE(w1_clk, "w1",
 127                                   r_mod0_default_parents, 0x1e0,
 128                                   0, 5,         /* M */
 129                                   8, 2,         /* P */
 130                                   24, 1,        /* mux */
 131                                   BIT(31),      /* gate */
 132                                   0);
 133 
 134 static struct ccu_common *sun50i_h6_r_ccu_clks[] = {
 135         &ar100_clk.common,
 136         &r_apb1_clk.common,
 137         &r_apb2_clk.common,
 138         &r_apb1_timer_clk.common,
 139         &r_apb1_twd_clk.common,
 140         &r_apb1_pwm_clk.common,
 141         &r_apb2_uart_clk.common,
 142         &r_apb2_i2c_clk.common,
 143         &r_apb1_ir_clk.common,
 144         &r_apb1_w1_clk.common,
 145         &ir_clk.common,
 146         &w1_clk.common,
 147 };
 148 
 149 static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
 150         .hws    = {
 151                 [CLK_AR100]             = &ar100_clk.common.hw,
 152                 [CLK_R_AHB]             = &r_ahb_clk.hw,
 153                 [CLK_R_APB1]            = &r_apb1_clk.common.hw,
 154                 [CLK_R_APB2]            = &r_apb2_clk.common.hw,
 155                 [CLK_R_APB1_TIMER]      = &r_apb1_timer_clk.common.hw,
 156                 [CLK_R_APB1_TWD]        = &r_apb1_twd_clk.common.hw,
 157                 [CLK_R_APB1_PWM]        = &r_apb1_pwm_clk.common.hw,
 158                 [CLK_R_APB2_UART]       = &r_apb2_uart_clk.common.hw,
 159                 [CLK_R_APB2_I2C]        = &r_apb2_i2c_clk.common.hw,
 160                 [CLK_R_APB1_IR]         = &r_apb1_ir_clk.common.hw,
 161                 [CLK_R_APB1_W1]         = &r_apb1_w1_clk.common.hw,
 162                 [CLK_IR]                = &ir_clk.common.hw,
 163                 [CLK_W1]                = &w1_clk.common.hw,
 164         },
 165         .num    = CLK_NUMBER,
 166 };
 167 
 168 static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
 169         [RST_R_APB1_TIMER]      =  { 0x11c, BIT(16) },
 170         [RST_R_APB1_TWD]        =  { 0x12c, BIT(16) },
 171         [RST_R_APB1_PWM]        =  { 0x13c, BIT(16) },
 172         [RST_R_APB2_UART]       =  { 0x18c, BIT(16) },
 173         [RST_R_APB2_I2C]        =  { 0x19c, BIT(16) },
 174         [RST_R_APB1_IR]         =  { 0x1cc, BIT(16) },
 175         [RST_R_APB1_W1]         =  { 0x1ec, BIT(16) },
 176 };
 177 
 178 static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
 179         .ccu_clks       = sun50i_h6_r_ccu_clks,
 180         .num_ccu_clks   = ARRAY_SIZE(sun50i_h6_r_ccu_clks),
 181 
 182         .hw_clks        = &sun50i_h6_r_hw_clks,
 183 
 184         .resets         = sun50i_h6_r_ccu_resets,
 185         .num_resets     = ARRAY_SIZE(sun50i_h6_r_ccu_resets),
 186 };
 187 
 188 static void __init sunxi_r_ccu_init(struct device_node *node,
 189                                     const struct sunxi_ccu_desc *desc)
 190 {
 191         void __iomem *reg;
 192 
 193         reg = of_io_request_and_map(node, 0, of_node_full_name(node));
 194         if (IS_ERR(reg)) {
 195                 pr_err("%pOF: Could not map the clock registers\n", node);
 196                 return;
 197         }
 198 
 199         sunxi_ccu_probe(node, reg, desc);
 200 }
 201 
 202 static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
 203 {
 204         sunxi_r_ccu_init(node, &sun50i_h6_r_ccu_desc);
 205 }
 206 CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu",
 207                sun50i_h6_r_ccu_setup);

/* [<][>][^][v][top][bottom][index][help] */