xref: /rk3399_rockchip-uboot/drivers/clk/clk_boston.c (revision 90aa625c9a9e1fb7a2f001fd8e50099bacaf92b8)
1dd7c7494SPaul Burton /*
2dd7c7494SPaul Burton  * Copyright (C) 2016 Imagination Technologies
3dd7c7494SPaul Burton  *
4dd7c7494SPaul Burton  * SPDX-License-Identifier:	GPL-2.0
5dd7c7494SPaul Burton  */
6dd7c7494SPaul Burton 
7dd7c7494SPaul Burton #include <common.h>
8dd7c7494SPaul Burton #include <clk-uclass.h>
9dd7c7494SPaul Burton #include <dm.h>
10dd7c7494SPaul Burton #include <dt-bindings/clock/boston-clock.h>
11dd7c7494SPaul Burton #include <regmap.h>
12dd7c7494SPaul Burton #include <syscon.h>
13dd7c7494SPaul Burton 
14dd7c7494SPaul Burton struct clk_boston {
15dd7c7494SPaul Burton 	struct regmap *regmap;
16dd7c7494SPaul Burton };
17dd7c7494SPaul Burton 
18dd7c7494SPaul Burton #define BOSTON_PLAT_MMCMDIV		0x30
19dd7c7494SPaul Burton # define BOSTON_PLAT_MMCMDIV_CLK0DIV	(0xff << 0)
20dd7c7494SPaul Burton # define BOSTON_PLAT_MMCMDIV_INPUT	(0xff << 8)
21dd7c7494SPaul Burton # define BOSTON_PLAT_MMCMDIV_MUL	(0xff << 16)
22dd7c7494SPaul Burton # define BOSTON_PLAT_MMCMDIV_CLK1DIV	(0xff << 24)
23dd7c7494SPaul Burton 
ext_field(uint32_t val,uint32_t mask)24dd7c7494SPaul Burton static uint32_t ext_field(uint32_t val, uint32_t mask)
25dd7c7494SPaul Burton {
26dd7c7494SPaul Burton 	return (val & mask) >> (ffs(mask) - 1);
27dd7c7494SPaul Burton }
28dd7c7494SPaul Burton 
clk_boston_get_rate(struct clk * clk)29dd7c7494SPaul Burton static ulong clk_boston_get_rate(struct clk *clk)
30dd7c7494SPaul Burton {
31dd7c7494SPaul Burton 	struct clk_boston *state = dev_get_platdata(clk->dev);
32dd7c7494SPaul Burton 	uint32_t in_rate, mul, div;
33dd7c7494SPaul Burton 	uint mmcmdiv;
34dd7c7494SPaul Burton 	int err;
35dd7c7494SPaul Burton 
36dd7c7494SPaul Burton 	err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
37dd7c7494SPaul Burton 	if (err)
38dd7c7494SPaul Burton 		return 0;
39dd7c7494SPaul Burton 
40dd7c7494SPaul Burton 	in_rate = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT);
41dd7c7494SPaul Burton 	mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);
42dd7c7494SPaul Burton 
43dd7c7494SPaul Burton 	switch (clk->id) {
44dd7c7494SPaul Burton 	case BOSTON_CLK_SYS:
45dd7c7494SPaul Burton 		div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
46dd7c7494SPaul Burton 		break;
47dd7c7494SPaul Burton 	case BOSTON_CLK_CPU:
48dd7c7494SPaul Burton 		div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
49dd7c7494SPaul Burton 		break;
50dd7c7494SPaul Burton 	default:
51dd7c7494SPaul Burton 		return 0;
52dd7c7494SPaul Burton 	}
53dd7c7494SPaul Burton 
54dd7c7494SPaul Burton 	return (in_rate * mul * 1000000) / div;
55dd7c7494SPaul Burton }
56dd7c7494SPaul Burton 
57dd7c7494SPaul Burton const struct clk_ops clk_boston_ops = {
58dd7c7494SPaul Burton 	.get_rate = clk_boston_get_rate,
59dd7c7494SPaul Burton };
60dd7c7494SPaul Burton 
clk_boston_ofdata_to_platdata(struct udevice * dev)61dd7c7494SPaul Burton static int clk_boston_ofdata_to_platdata(struct udevice *dev)
62dd7c7494SPaul Burton {
63dd7c7494SPaul Burton 	struct clk_boston *state = dev_get_platdata(dev);
64dd7c7494SPaul Burton 	struct udevice *syscon;
65dd7c7494SPaul Burton 	int err;
66dd7c7494SPaul Burton 
67dd7c7494SPaul Burton 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
68dd7c7494SPaul Burton 					   "regmap", &syscon);
69dd7c7494SPaul Burton 	if (err) {
70*90aa625cSMasahiro Yamada 		pr_err("unable to find syscon device\n");
71dd7c7494SPaul Burton 		return err;
72dd7c7494SPaul Burton 	}
73dd7c7494SPaul Burton 
74dd7c7494SPaul Burton 	state->regmap = syscon_get_regmap(syscon);
75dd7c7494SPaul Burton 	if (!state->regmap) {
76*90aa625cSMasahiro Yamada 		pr_err("unable to find regmap\n");
77dd7c7494SPaul Burton 		return -ENODEV;
78dd7c7494SPaul Burton 	}
79dd7c7494SPaul Burton 
80dd7c7494SPaul Burton 	return 0;
81dd7c7494SPaul Burton }
82dd7c7494SPaul Burton 
83dd7c7494SPaul Burton static const struct udevice_id clk_boston_match[] = {
84dd7c7494SPaul Burton 	{
85dd7c7494SPaul Burton 		.compatible = "img,boston-clock",
86dd7c7494SPaul Burton 	},
87dd7c7494SPaul Burton 	{ /* sentinel */ }
88dd7c7494SPaul Burton };
89dd7c7494SPaul Burton 
90dd7c7494SPaul Burton U_BOOT_DRIVER(clk_boston) = {
91dd7c7494SPaul Burton 	.name = "boston_clock",
92dd7c7494SPaul Burton 	.id = UCLASS_CLK,
93dd7c7494SPaul Burton 	.of_match = clk_boston_match,
94dd7c7494SPaul Burton 	.ofdata_to_platdata = clk_boston_ofdata_to_platdata,
95dd7c7494SPaul Burton 	.platdata_auto_alloc_size = sizeof(struct clk_boston),
96dd7c7494SPaul Burton 	.ops = &clk_boston_ops,
97dd7c7494SPaul Burton };
98