1 /*
2  * clk-synthesizer.c
3  *
4  * Clock synthesizer apis
5  *
6  * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 
11 
12 #include <common.h>
13 #include <asm/arch/clk_synthesizer.h>
14 #include <i2c.h>
15 
16 /**
17  * clk_synthesizer_reg_read - Read register from synthesizer.
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(int addr, uint8_t *buf)
26 {
27 	int rc;
28 
29 	/* Enable Bye read */
30 	addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
31 
32 	/* Send the command byte */
33 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
34 	if (rc)
35 		printf("Failed to send command to clock synthesizer\n");
36 
37 	/* Read the Data */
38 	return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
39 }
40 
41 /**
42  * clk_synthesizer_reg_write - Write a value to register in synthesizer.
43  * @addr:	addr within the i2c device
44  * val:		Value to be written in the addr.
45  *
46  * Enable the byte read mode in the address and start the i2c transfer.
47  * Returns 0 on success
48  */
49 static int clk_synthesizer_reg_write(int addr, uint8_t val)
50 {
51 	uint8_t cmd[2];
52 	int rc = 0;
53 
54 	/* Enable byte write */
55 	cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
56 	cmd[1] = val;
57 
58 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
59 	if (rc)
60 		printf("Clock synthesizer reg write failed at addr = 0x%x\n",
61 		       addr);
62 	return rc;
63 }
64 
65 /**
66  * setup_clock_syntherizer - Program the clock synthesizer to get the desired
67  *				frequency.
68  * @data: Data containing the desired output
69  *
70  * This is a PLL-based high performance synthesizer which gives 3 outputs
71  * as per the PLL_DIV and load capacitor programmed.
72  */
73 int setup_clock_synthesizer(struct clk_synth *data)
74 {
75 	int rc;
76 	uint8_t val;
77 
78 	rc =  i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
79 	if (rc) {
80 		printf("i2c probe failed at address 0x%x\n",
81 		       CLK_SYNTHESIZER_I2C_ADDR);
82 		return rc;
83 	}
84 
85 	rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val);
86 	if (val != data->id)
87 		return rc;
88 
89 	/* Crystal Load capacitor selection */
90 	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor);
91 	if (rc)
92 		return rc;
93 	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux);
94 	if (rc)
95 		return rc;
96 	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2);
97 	if (rc)
98 		return rc;
99 	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3);
100 	if (rc)
101 		return rc;
102 
103 	return 0;
104 }
105