1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright ASPEED Technology Inc.
4  */
5 
6 #include <common.h>
7 #include <clk.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <fdtdec.h>
11 #include <asm/io.h>
12 #include <reset.h>
13 #include "ast2600_i2c_global.h"
14 
15 enum global_version {
16 	ASPEED_I2C_GLOBAL = 0,
17 	AST2600_I2C_GLOBAL,
18 };
19 
20 struct ast2600_i2c_global_priv {
21 	void __iomem *regs;
22 	struct reset_ctl reset;
23 	int version;
24 };
25 
26 /*
27  * APB clk : 100Mhz
28  * div  : scl       : baseclk [APB/((div/2) + 1)] : tBuf [1/bclk * 16]
29  * I2CG10[31:24] base clk4 for i2c auto recovery timeout counter (0xC6)
30  * I2CG10[23:16] base clk3 for Standard-mode (100Khz) min tBuf 4.7us
31  * 0x3c : 100.8Khz  : 3.225Mhz                    : 4.96us
32  * 0x3d : 99.2Khz   : 3.174Mhz                    : 5.04us
33  * 0x3e : 97.65Khz  : 3.125Mhz                    : 5.12us
34  * 0x40 : 97.75Khz  : 3.03Mhz                     : 5.28us
35  * 0x41 : 99.5Khz   : 2.98Mhz                     : 5.36us (default)
36  * I2CG10[15:8] base clk2 for Fast-mode (400Khz) min tBuf 1.3us
37  * 0x12 : 400Khz    : 10Mhz                       : 1.6us
38  * I2CG10[7:0] base clk1 for Fast-mode Plus (1Mhz) min tBuf 0.5us
39  * 0x08 : 1Mhz      : 20Mhz                       : 0.8us
40  */
41 
aspeed_i2c_global_probe(struct udevice * dev)42 static int aspeed_i2c_global_probe(struct udevice *dev)
43 {
44 	struct ast2600_i2c_global_priv *i2c_global = dev_get_priv(dev);
45 	int ret = 0;
46 
47 	i2c_global->regs = devfdt_get_addr_ptr(dev);
48 	if (IS_ERR(i2c_global->regs))
49 		return PTR_ERR(i2c_global->regs);
50 
51 	debug("%s(dev=%p)\n", __func__, dev);
52 
53 	ret = reset_get_by_index(dev, 0, &i2c_global->reset);
54 	if (ret) {
55 		printf("%s(): Failed to get reset signal\n", __func__);
56 		return ret;
57 	}
58 
59 	i2c_global->version = dev_get_driver_data(dev);
60 
61 	reset_deassert(&i2c_global->reset);
62 
63 	if (IS_ENABLED(SYS_I2C_AST2600) &&
64 	    i2c_global->version == AST2600_I2C_GLOBAL) {
65 		writel(AST2600_GLOBAL_INIT, i2c_global->regs +
66 			AST2600_I2CG_CTRL);
67 		writel(I2CCG_DIV_CTRL, i2c_global->regs +
68 			AST2600_I2CG_CLK_DIV_CTRL);
69 	}
70 
71 	return 0;
72 }
73 
74 static const struct udevice_id aspeed_i2c_global_ids[] = {
75 	{
76 		.compatible = "aspeed,ast2500-i2c-ic",
77 		.data = ASPEED_I2C_GLOBAL
78 	},
79 	{
80 		.compatible = "aspeed,ast2600-i2c-global",
81 		.data = AST2600_I2C_GLOBAL
82 	},
83 	{ }
84 };
85 
86 U_BOOT_DRIVER(aspeed_i2c_global) = {
87 	.name		= "aspeed_i2c_global",
88 	.id			= UCLASS_MISC,
89 	.of_match	= aspeed_i2c_global_ids,
90 	.probe		= aspeed_i2c_global_probe,
91 	.priv_auto_alloc_size = sizeof(struct ast2600_i2c_global_priv),
92 };
93