1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * clk-synthesizer.c
4  *
5  * Clock synthesizer apis
6  *
7  * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/
8  */
9 
10 
11 #include <common.h>
12 #include <asm/arch/clk_synthesizer.h>
13 #include <i2c.h>
14 
15 /**
16  * clk_synthesizer_reg_read - Read register from synthesizer.
17  * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
18  * @addr:	addr within the i2c device
19  * buf:		Buffer to which value is to be read.
20  *
21  * For reading the register from this clock synthesizer, a command needs to
22  * be send along with enabling byte read more, and then read can happen.
23  * Returns 0 on success
24  */
25 static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf)
26 {
27 	int rc;
28 
29 	/* Enable Bye read */
30 	addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
31 
32 #ifndef CONFIG_DM_I2C
33 	/* Send the command byte */
34 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
35 	if (rc)
36 		printf("Failed to send command to clock synthesizer\n");
37 
38 	/* Read the Data */
39 	return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
40 #else
41 	/* Send the command byte */
42 	rc = dm_i2c_reg_write(dev, addr, *buf);
43 	if (rc)
44 		printf("Failed to send command to clock synthesizer\n");
45 
46 	/* Read the Data */
47 	rc = dm_i2c_reg_read(dev, addr);
48 	if (rc < 0)
49 		return rc;
50 
51 	*buf = (u8)rc;
52 	return 0;
53 #endif
54 
55 }
56 
57 /**
58  * clk_synthesizer_reg_write - Write a value to register in synthesizer.
59  * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
60  * @addr:	addr within the i2c device
61  * val:		Value to be written in the addr.
62  *
63  * Enable the byte read mode in the address and start the i2c transfer.
64  * Returns 0 on success
65  */
66 static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val)
67 {
68 	u8 cmd[2];
69 	int rc = 0;
70 
71 	/* Enable byte write */
72 	cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
73 	cmd[1] = val;
74 
75 #ifndef CONFIG_DM_I2C
76 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
77 #else
78 	rc = dm_i2c_write(dev, addr, cmd, 2);
79 #endif
80 	if (rc)
81 		printf("Clock synthesizer reg write failed at addr = 0x%x\n",
82 		       addr);
83 	return rc;
84 }
85 
86 /**
87  * setup_clock_syntherizer - Program the clock synthesizer to get the desired
88  *				frequency.
89  * @data: Data containing the desired output
90  *
91  * This is a PLL-based high performance synthesizer which gives 3 outputs
92  * as per the PLL_DIV and load capacitor programmed.
93  */
94 int setup_clock_synthesizer(struct clk_synth *data)
95 {
96 	int rc;
97 	u8 val = 0;
98 	struct udevice *dev = NULL;
99 #ifndef CONFIG_DM_I2C
100 	rc =  i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
101 	if (rc) {
102 		printf("i2c probe failed at address 0x%x\n",
103 		       CLK_SYNTHESIZER_I2C_ADDR);
104 		return rc;
105 	}
106 #else
107 	rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev);
108 	if (rc) {
109 		printf("failed to get device for synthesizer at address 0x%x\n",
110 		       CLK_SYNTHESIZER_I2C_ADDR);
111 		return rc;
112 	}
113 #endif
114 	rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val);
115 	if (val != data->id)
116 		return rc;
117 
118 	/* Crystal Load capacitor selection */
119 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL,
120 				       data->capacitor);
121 	if (rc)
122 		return rc;
123 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG,
124 				       data->mux);
125 	if (rc)
126 		return rc;
127 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG,
128 				       data->pdiv2);
129 	if (rc)
130 		return rc;
131 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG,
132 				       data->pdiv3);
133 	if (rc)
134 		return rc;
135 
136 	return 0;
137 }
138