Home | History | Annotate | Download | only in renesas
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Renesas RCar Gen3 CPG MSSR driver
      4  *
      5  * Copyright (C) 2017 Marek Vasut <marek.vasut (at) gmail.com>
      6  *
      7  * Based on the following driver from Linux kernel:
      8  * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
      9  *
     10  * Copyright (C) 2016 Glider bvba
     11  */
     12 
     13 #include <common.h>
     14 #include <clk-uclass.h>
     15 #include <dm.h>
     16 #include <errno.h>
     17 #include <wait_bit.h>
     18 #include <asm/io.h>
     19 
     20 #include <dt-bindings/clock/renesas-cpg-mssr.h>
     21 
     22 #include "renesas-cpg-mssr.h"
     23 #include "rcar-gen3-cpg.h"
     24 
     25 #define CPG_RST_MODEMR		0x0060
     26 
     27 #define CPG_PLL0CR		0x00d8
     28 #define CPG_PLL2CR		0x002c
     29 #define CPG_PLL4CR		0x01f4
     30 
     31 #define CPG_RPC_PREDIV_MASK	0x3
     32 #define CPG_RPC_PREDIV_OFFSET	3
     33 #define CPG_RPC_POSTDIV_MASK	0x7
     34 #define CPG_RPC_POSTDIV_OFFSET	0
     35 
     36 /*
     37  * SDn Clock
     38  */
     39 #define CPG_SD_STP_HCK		BIT(9)
     40 #define CPG_SD_STP_CK		BIT(8)
     41 
     42 #define CPG_SD_STP_MASK		(CPG_SD_STP_HCK | CPG_SD_STP_CK)
     43 #define CPG_SD_FC_MASK		(0x7 << 2 | 0x3 << 0)
     44 
     45 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
     46 { \
     47 	.val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
     48 	       ((stp_ck) ? CPG_SD_STP_CK : 0) | \
     49 	       ((sd_srcfc) << 2) | \
     50 	       ((sd_fc) << 0), \
     51 	.div = (sd_div), \
     52 }
     53 
     54 struct sd_div_table {
     55 	u32 val;
     56 	unsigned int div;
     57 };
     58 
     59 /* SDn divider
     60  *                     sd_srcfc   sd_fc   div
     61  * stp_hck   stp_ck    (div)      (div)     = sd_srcfc x sd_fc
     62  *-------------------------------------------------------------------
     63  *  0         0         0 (1)      1 (4)      4
     64  *  0         0         1 (2)      1 (4)      8
     65  *  1         0         2 (4)      1 (4)     16
     66  *  1         0         3 (8)      1 (4)     32
     67  *  1         0         4 (16)     1 (4)     64
     68  *  0         0         0 (1)      0 (2)      2
     69  *  0         0         1 (2)      0 (2)      4
     70  *  1         0         2 (4)      0 (2)      8
     71  *  1         0         3 (8)      0 (2)     16
     72  *  1         0         4 (16)     0 (2)     32
     73  */
     74 static const struct sd_div_table cpg_sd_div_table[] = {
     75 /*	CPG_SD_DIV_TABLE_DATA(stp_hck,  stp_ck,   sd_srcfc,   sd_fc,  sd_div) */
     76 	CPG_SD_DIV_TABLE_DATA(0,        0,        0,          1,        4),
     77 	CPG_SD_DIV_TABLE_DATA(0,        0,        1,          1,        8),
     78 	CPG_SD_DIV_TABLE_DATA(1,        0,        2,          1,       16),
     79 	CPG_SD_DIV_TABLE_DATA(1,        0,        3,          1,       32),
     80 	CPG_SD_DIV_TABLE_DATA(1,        0,        4,          1,       64),
     81 	CPG_SD_DIV_TABLE_DATA(0,        0,        0,          0,        2),
     82 	CPG_SD_DIV_TABLE_DATA(0,        0,        1,          0,        4),
     83 	CPG_SD_DIV_TABLE_DATA(1,        0,        2,          0,        8),
     84 	CPG_SD_DIV_TABLE_DATA(1,        0,        3,          0,       16),
     85 	CPG_SD_DIV_TABLE_DATA(1,        0,        4,          0,       32),
     86 };
     87 
     88 static int gen3_clk_get_parent(struct gen3_clk_priv *priv, struct clk *clk,
     89 			       struct cpg_mssr_info *info, struct clk *parent)
     90 {
     91 	const struct cpg_core_clk *core;
     92 	int ret;
     93 
     94 	if (!renesas_clk_is_mod(clk)) {
     95 		ret = renesas_clk_get_core(clk, info, &core);
     96 		if (ret)
     97 			return ret;
     98 
     99 		if (core->type == CLK_TYPE_GEN3_PE) {
    100 			parent->dev = clk->dev;
    101 			parent->id = core->parent >> (priv->sscg ? 16 : 0);
    102 			parent->id &= 0xffff;
    103 			return 0;
    104 		}
    105 	}
    106 
    107 	return renesas_clk_get_parent(clk, info, parent);
    108 }
    109 
    110 static int gen3_clk_setup_sdif_div(struct clk *clk)
    111 {
    112 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
    113 	struct cpg_mssr_info *info = priv->info;
    114 	const struct cpg_core_clk *core;
    115 	struct clk parent;
    116 	int ret;
    117 
    118 	ret = gen3_clk_get_parent(priv, clk, info, &parent);
    119 	if (ret) {
    120 		printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
    121 		return ret;
    122 	}
    123 
    124 	if (renesas_clk_is_mod(&parent))
    125 		return 0;
    126 
    127 	ret = renesas_clk_get_core(&parent, info, &core);
    128 	if (ret)
    129 		return ret;
    130 
    131 	if (core->type != CLK_TYPE_GEN3_SD)
    132 		return 0;
    133 
    134 	debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
    135 
    136 	writel(1, priv->base + core->offset);
    137 
    138 	return 0;
    139 }
    140 
    141 static int gen3_clk_enable(struct clk *clk)
    142 {
    143 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
    144 	int ret = gen3_clk_setup_sdif_div(clk);
    145 
    146 	if (ret)
    147 		return ret;
    148 
    149 	return renesas_clk_endisable(clk, priv->base, true);
    150 }
    151 
    152 static int gen3_clk_disable(struct clk *clk)
    153 {
    154 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
    155 
    156 	return renesas_clk_endisable(clk, priv->base, false);
    157 }
    158 
    159 static u64 gen3_clk_get_rate64(struct clk *clk)
    160 {
    161 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
    162 	struct cpg_mssr_info *info = priv->info;
    163 	struct clk parent;
    164 	const struct cpg_core_clk *core;
    165 	const struct rcar_gen3_cpg_pll_config *pll_config =
    166 					priv->cpg_pll_config;
    167 	u32 value, mult, div, prediv, postdiv;
    168 	u64 rate = 0;
    169 	int i, ret;
    170 
    171 	debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id);
    172 
    173 	ret = gen3_clk_get_parent(priv, clk, info, &parent);
    174 	if (ret) {
    175 		printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret);
    176 		return ret;
    177 	}
    178 
    179 	if (renesas_clk_is_mod(clk)) {
    180 		rate = gen3_clk_get_rate64(&parent);
    181 		debug("%s[%i] MOD clk: parent=%lu => rate=%llu\n",
    182 		      __func__, __LINE__, parent.id, rate);
    183 		return rate;
    184 	}
    185 
    186 	ret = renesas_clk_get_core(clk, info, &core);
    187 	if (ret)
    188 		return ret;
    189 
    190 	switch (core->type) {
    191 	case CLK_TYPE_IN:
    192 		if (core->id == info->clk_extal_id) {
    193 			rate = clk_get_rate(&priv->clk_extal);
    194 			debug("%s[%i] EXTAL clk: rate=%llu\n",
    195 			      __func__, __LINE__, rate);
    196 			return rate;
    197 		}
    198 
    199 		if (core->id == info->clk_extalr_id) {
    200 			rate = clk_get_rate(&priv->clk_extalr);
    201 			debug("%s[%i] EXTALR clk: rate=%llu\n",
    202 			      __func__, __LINE__, rate);
    203 			return rate;
    204 		}
    205 
    206 		return -EINVAL;
    207 
    208 	case CLK_TYPE_GEN3_MAIN:
    209 		rate = gen3_clk_get_rate64(&parent) / pll_config->extal_div;
    210 		debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%llu\n",
    211 		      __func__, __LINE__,
    212 		      core->parent, pll_config->extal_div, rate);
    213 		return rate;
    214 
    215 	case CLK_TYPE_GEN3_PLL0:
    216 		value = readl(priv->base + CPG_PLL0CR);
    217 		mult = (((value >> 24) & 0x7f) + 1) * 2;
    218 		rate = gen3_clk_get_rate64(&parent) * mult;
    219 		debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%llu\n",
    220 		      __func__, __LINE__, core->parent, mult, rate);
    221 		return rate;
    222 
    223 	case CLK_TYPE_GEN3_PLL1:
    224 		rate = gen3_clk_get_rate64(&parent) * pll_config->pll1_mult;
    225 		rate /= pll_config->pll1_div;
    226 		debug("%s[%i] PLL1 clk: parent=%i mul=%i div=%i => rate=%llu\n",
    227 		      __func__, __LINE__,
    228 		      core->parent, pll_config->pll1_mult,
    229 		      pll_config->pll1_div, rate);
    230 		return rate;
    231 
    232 	case CLK_TYPE_GEN3_PLL2:
    233 		value = readl(priv->base + CPG_PLL2CR);
    234 		mult = (((value >> 24) & 0x7f) + 1) * 2;
    235 		rate = gen3_clk_get_rate64(&parent) * mult;
    236 		debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%llu\n",
    237 		      __func__, __LINE__, core->parent, mult, rate);
    238 		return rate;
    239 
    240 	case CLK_TYPE_GEN3_PLL3:
    241 		rate = gen3_clk_get_rate64(&parent) * pll_config->pll3_mult;
    242 		rate /= pll_config->pll3_div;
    243 		debug("%s[%i] PLL3 clk: parent=%i mul=%i div=%i => rate=%llu\n",
    244 		      __func__, __LINE__,
    245 		      core->parent, pll_config->pll3_mult,
    246 		      pll_config->pll3_div, rate);
    247 		return rate;
    248 
    249 	case CLK_TYPE_GEN3_PLL4:
    250 		value = readl(priv->base + CPG_PLL4CR);
    251 		mult = (((value >> 24) & 0x7f) + 1) * 2;
    252 		rate = gen3_clk_get_rate64(&parent) * mult;
    253 		debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%llu\n",
    254 		      __func__, __LINE__, core->parent, mult, rate);
    255 		return rate;
    256 
    257 	case CLK_TYPE_FF:
    258 		rate = (gen3_clk_get_rate64(&parent) * core->mult) / core->div;
    259 		debug("%s[%i] FIXED clk: parent=%i mul=%i div=%i => rate=%llu\n",
    260 		      __func__, __LINE__,
    261 		      core->parent, core->mult, core->div, rate);
    262 		return rate;
    263 
    264 	case CLK_TYPE_GEN3_PE:
    265 		div = (core->div >> (priv->sscg ? 16 : 0)) & 0xffff;
    266 		rate = gen3_clk_get_rate64(&parent) / div;
    267 		debug("%s[%i] PE clk: parent=%i div=%u => rate=%llu\n",
    268 		      __func__, __LINE__,
    269 		      (core->parent >> (priv->sscg ? 16 : 0)) & 0xffff,
    270 		      div, rate);
    271 		return rate;
    272 
    273 	case CLK_TYPE_GEN3_SD:		/* FIXME */
    274 		value = readl(priv->base + core->offset);
    275 		value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK;
    276 
    277 		for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) {
    278 			if (cpg_sd_div_table[i].val != value)
    279 				continue;
    280 
    281 			rate = gen3_clk_get_rate64(&parent) /
    282 			       cpg_sd_div_table[i].div;
    283 			debug("%s[%i] SD clk: parent=%i div=%i => rate=%llu\n",
    284 			      __func__, __LINE__,
    285 			      core->parent, cpg_sd_div_table[i].div, rate);
    286 
    287 			return rate;
    288 		}
    289 
    290 		return -EINVAL;
    291 
    292 	case CLK_TYPE_GEN3_RPC:
    293 		rate = gen3_clk_get_rate64(&parent);
    294 
    295 		value = readl(priv->base + core->offset);
    296 
    297 		prediv = (value >> CPG_RPC_PREDIV_OFFSET) &
    298 			 CPG_RPC_PREDIV_MASK;
    299 		if (prediv == 2)
    300 			rate /= 5;
    301 		else if (prediv == 3)
    302 			rate /= 6;
    303 		else
    304 			return -EINVAL;
    305 
    306 		postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) &
    307 			  CPG_RPC_POSTDIV_MASK;
    308 		rate /= postdiv + 1;
    309 
    310 		debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%llu\n",
    311 		      __func__, __LINE__,
    312 		      core->parent, prediv, postdiv, rate);
    313 
    314 		return -EINVAL;
    315 
    316 	}
    317 
    318 	printf("%s[%i] unknown fail\n", __func__, __LINE__);
    319 
    320 	return -ENOENT;
    321 }
    322 
    323 static ulong gen3_clk_get_rate(struct clk *clk)
    324 {
    325 	return gen3_clk_get_rate64(clk);
    326 }
    327 
    328 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
    329 {
    330 	/* Force correct SD-IF divider configuration if applicable */
    331 	gen3_clk_setup_sdif_div(clk);
    332 	return gen3_clk_get_rate64(clk);
    333 }
    334 
    335 static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
    336 {
    337 	if (args->args_count != 2) {
    338 		debug("Invaild args_count: %d\n", args->args_count);
    339 		return -EINVAL;
    340 	}
    341 
    342 	clk->id = (args->args[0] << 16) | args->args[1];
    343 
    344 	return 0;
    345 }
    346 
    347 const struct clk_ops gen3_clk_ops = {
    348 	.enable		= gen3_clk_enable,
    349 	.disable	= gen3_clk_disable,
    350 	.get_rate	= gen3_clk_get_rate,
    351 	.set_rate	= gen3_clk_set_rate,
    352 	.of_xlate	= gen3_clk_of_xlate,
    353 };
    354 
    355 int gen3_clk_probe(struct udevice *dev)
    356 {
    357 	struct gen3_clk_priv *priv = dev_get_priv(dev);
    358 	struct cpg_mssr_info *info =
    359 		(struct cpg_mssr_info *)dev_get_driver_data(dev);
    360 	fdt_addr_t rst_base;
    361 	u32 cpg_mode;
    362 	int ret;
    363 
    364 	priv->base = (struct gen3_base *)devfdt_get_addr(dev);
    365 	if (!priv->base)
    366 		return -EINVAL;
    367 
    368 	priv->info = info;
    369 	ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node);
    370 	if (ret < 0)
    371 		return ret;
    372 
    373 	rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg");
    374 	if (rst_base == FDT_ADDR_T_NONE)
    375 		return -EINVAL;
    376 
    377 	cpg_mode = readl(rst_base + CPG_RST_MODEMR);
    378 
    379 	priv->cpg_pll_config =
    380 		(struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode);
    381 	if (!priv->cpg_pll_config->extal_div)
    382 		return -EINVAL;
    383 
    384 	priv->sscg = !(cpg_mode & BIT(12));
    385 
    386 	ret = clk_get_by_name(dev, "extal", &priv->clk_extal);
    387 	if (ret < 0)
    388 		return ret;
    389 
    390 	if (info->extalr_node) {
    391 		ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr);
    392 		if (ret < 0)
    393 			return ret;
    394 	}
    395 
    396 	return 0;
    397 }
    398 
    399 int gen3_clk_remove(struct udevice *dev)
    400 {
    401 	struct gen3_clk_priv *priv = dev_get_priv(dev);
    402 
    403 	return renesas_clk_remove(priv->base, priv->info);
    404 }
    405