183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2983e3700STom Rini /*
3983e3700STom Rini  * clk-synthesizer.c
4983e3700STom Rini  *
5983e3700STom Rini  * Clock synthesizer apis
6983e3700STom Rini  *
7983e3700STom Rini  * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/
8983e3700STom Rini  */
9983e3700STom Rini 
10983e3700STom Rini 
11983e3700STom Rini #include <common.h>
12983e3700STom Rini #include <asm/arch/clk_synthesizer.h>
13983e3700STom Rini #include <i2c.h>
14983e3700STom Rini 
15983e3700STom Rini /**
16983e3700STom Rini  * clk_synthesizer_reg_read - Read register from synthesizer.
17*1514244cSJean-Jacques Hiblot  * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
18983e3700STom Rini  * @addr:	addr within the i2c device
19983e3700STom Rini  * buf:		Buffer to which value is to be read.
20983e3700STom Rini  *
21983e3700STom Rini  * For reading the register from this clock synthesizer, a command needs to
22983e3700STom Rini  * be send along with enabling byte read more, and then read can happen.
23983e3700STom Rini  * Returns 0 on success
24983e3700STom Rini  */
clk_synthesizer_reg_read(struct udevice * dev,int addr,u8 * buf)25*1514244cSJean-Jacques Hiblot static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf)
26983e3700STom Rini {
27983e3700STom Rini 	int rc;
28983e3700STom Rini 
29983e3700STom Rini 	/* Enable Bye read */
30983e3700STom Rini 	addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
31983e3700STom Rini 
32*1514244cSJean-Jacques Hiblot #ifndef CONFIG_DM_I2C
33983e3700STom Rini 	/* Send the command byte */
34983e3700STom Rini 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
35983e3700STom Rini 	if (rc)
36983e3700STom Rini 		printf("Failed to send command to clock synthesizer\n");
37983e3700STom Rini 
38983e3700STom Rini 	/* Read the Data */
39983e3700STom Rini 	return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
40*1514244cSJean-Jacques Hiblot #else
41*1514244cSJean-Jacques Hiblot 	/* Send the command byte */
42*1514244cSJean-Jacques Hiblot 	rc = dm_i2c_reg_write(dev, addr, *buf);
43*1514244cSJean-Jacques Hiblot 	if (rc)
44*1514244cSJean-Jacques Hiblot 		printf("Failed to send command to clock synthesizer\n");
45*1514244cSJean-Jacques Hiblot 
46*1514244cSJean-Jacques Hiblot 	/* Read the Data */
47*1514244cSJean-Jacques Hiblot 	rc = dm_i2c_reg_read(dev, addr);
48*1514244cSJean-Jacques Hiblot 	if (rc < 0)
49*1514244cSJean-Jacques Hiblot 		return rc;
50*1514244cSJean-Jacques Hiblot 
51*1514244cSJean-Jacques Hiblot 	*buf = (u8)rc;
52*1514244cSJean-Jacques Hiblot 	return 0;
53*1514244cSJean-Jacques Hiblot #endif
54*1514244cSJean-Jacques Hiblot 
55983e3700STom Rini }
56983e3700STom Rini 
57983e3700STom Rini /**
58983e3700STom Rini  * clk_synthesizer_reg_write - Write a value to register in synthesizer.
59*1514244cSJean-Jacques Hiblot  * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
60983e3700STom Rini  * @addr:	addr within the i2c device
61983e3700STom Rini  * val:		Value to be written in the addr.
62983e3700STom Rini  *
63983e3700STom Rini  * Enable the byte read mode in the address and start the i2c transfer.
64983e3700STom Rini  * Returns 0 on success
65983e3700STom Rini  */
clk_synthesizer_reg_write(struct udevice * dev,int addr,u8 val)66*1514244cSJean-Jacques Hiblot static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val)
67983e3700STom Rini {
68*1514244cSJean-Jacques Hiblot 	u8 cmd[2];
69983e3700STom Rini 	int rc = 0;
70983e3700STom Rini 
71983e3700STom Rini 	/* Enable byte write */
72983e3700STom Rini 	cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
73983e3700STom Rini 	cmd[1] = val;
74983e3700STom Rini 
75*1514244cSJean-Jacques Hiblot #ifndef CONFIG_DM_I2C
76983e3700STom Rini 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
77*1514244cSJean-Jacques Hiblot #else
78*1514244cSJean-Jacques Hiblot 	rc = dm_i2c_write(dev, addr, cmd, 2);
79*1514244cSJean-Jacques Hiblot #endif
80983e3700STom Rini 	if (rc)
81983e3700STom Rini 		printf("Clock synthesizer reg write failed at addr = 0x%x\n",
82983e3700STom Rini 		       addr);
83983e3700STom Rini 	return rc;
84983e3700STom Rini }
85983e3700STom Rini 
86983e3700STom Rini /**
87983e3700STom Rini  * setup_clock_syntherizer - Program the clock synthesizer to get the desired
88983e3700STom Rini  *				frequency.
89983e3700STom Rini  * @data: Data containing the desired output
90983e3700STom Rini  *
91983e3700STom Rini  * This is a PLL-based high performance synthesizer which gives 3 outputs
92983e3700STom Rini  * as per the PLL_DIV and load capacitor programmed.
93983e3700STom Rini  */
setup_clock_synthesizer(struct clk_synth * data)94983e3700STom Rini int setup_clock_synthesizer(struct clk_synth *data)
95983e3700STom Rini {
96983e3700STom Rini 	int rc;
97*1514244cSJean-Jacques Hiblot 	u8 val = 0;
98*1514244cSJean-Jacques Hiblot 	struct udevice *dev = NULL;
99*1514244cSJean-Jacques Hiblot #ifndef CONFIG_DM_I2C
100983e3700STom Rini 	rc =  i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
101983e3700STom Rini 	if (rc) {
102983e3700STom Rini 		printf("i2c probe failed at address 0x%x\n",
103983e3700STom Rini 		       CLK_SYNTHESIZER_I2C_ADDR);
104983e3700STom Rini 		return rc;
105983e3700STom Rini 	}
106*1514244cSJean-Jacques Hiblot #else
107*1514244cSJean-Jacques Hiblot 	rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev);
108*1514244cSJean-Jacques Hiblot 	if (rc) {
109*1514244cSJean-Jacques Hiblot 		printf("failed to get device for synthesizer at address 0x%x\n",
110*1514244cSJean-Jacques Hiblot 		       CLK_SYNTHESIZER_I2C_ADDR);
111*1514244cSJean-Jacques Hiblot 		return rc;
112*1514244cSJean-Jacques Hiblot 	}
113*1514244cSJean-Jacques Hiblot #endif
114*1514244cSJean-Jacques Hiblot 	rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val);
115983e3700STom Rini 	if (val != data->id)
116983e3700STom Rini 		return rc;
117983e3700STom Rini 
118983e3700STom Rini 	/* Crystal Load capacitor selection */
119*1514244cSJean-Jacques Hiblot 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL,
120*1514244cSJean-Jacques Hiblot 				       data->capacitor);
121983e3700STom Rini 	if (rc)
122983e3700STom Rini 		return rc;
123*1514244cSJean-Jacques Hiblot 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG,
124*1514244cSJean-Jacques Hiblot 				       data->mux);
125983e3700STom Rini 	if (rc)
126983e3700STom Rini 		return rc;
127*1514244cSJean-Jacques Hiblot 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG,
128*1514244cSJean-Jacques Hiblot 				       data->pdiv2);
129983e3700STom Rini 	if (rc)
130983e3700STom Rini 		return rc;
131*1514244cSJean-Jacques Hiblot 	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG,
132*1514244cSJean-Jacques Hiblot 				       data->pdiv3);
133983e3700STom Rini 	if (rc)
134983e3700STom Rini 		return rc;
135983e3700STom Rini 
136983e3700STom Rini 	return 0;
137983e3700STom Rini }
138