Merge branch 'master' of git://git.denx.de/u-boot-sh
[platform/kernel/u-boot.git] / arch / arm / mach-omap2 / am33xx / clk_synthesizer.c
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  * @addr:       addr within the i2c device
18  * buf:         Buffer to which value is to be read.
19  *
20  * For reading the register from this clock synthesizer, a command needs to
21  * be send along with enabling byte read more, and then read can happen.
22  * Returns 0 on success
23  */
24 static int clk_synthesizer_reg_read(int addr, uint8_t *buf)
25 {
26         int rc;
27
28         /* Enable Bye read */
29         addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
30
31         /* Send the command byte */
32         rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
33         if (rc)
34                 printf("Failed to send command to clock synthesizer\n");
35
36         /* Read the Data */
37         return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
38 }
39
40 /**
41  * clk_synthesizer_reg_write - Write a value to register in synthesizer.
42  * @addr:       addr within the i2c device
43  * val:         Value to be written in the addr.
44  *
45  * Enable the byte read mode in the address and start the i2c transfer.
46  * Returns 0 on success
47  */
48 static int clk_synthesizer_reg_write(int addr, uint8_t val)
49 {
50         uint8_t cmd[2];
51         int rc = 0;
52
53         /* Enable byte write */
54         cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
55         cmd[1] = val;
56
57         rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
58         if (rc)
59                 printf("Clock synthesizer reg write failed at addr = 0x%x\n",
60                        addr);
61         return rc;
62 }
63
64 /**
65  * setup_clock_syntherizer - Program the clock synthesizer to get the desired
66  *                              frequency.
67  * @data: Data containing the desired output
68  *
69  * This is a PLL-based high performance synthesizer which gives 3 outputs
70  * as per the PLL_DIV and load capacitor programmed.
71  */
72 int setup_clock_synthesizer(struct clk_synth *data)
73 {
74         int rc;
75         uint8_t val;
76
77         rc =  i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
78         if (rc) {
79                 printf("i2c probe failed at address 0x%x\n",
80                        CLK_SYNTHESIZER_I2C_ADDR);
81                 return rc;
82         }
83
84         rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val);
85         if (val != data->id)
86                 return rc;
87
88         /* Crystal Load capacitor selection */
89         rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor);
90         if (rc)
91                 return rc;
92         rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux);
93         if (rc)
94                 return rc;
95         rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2);
96         if (rc)
97                 return rc;
98         rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3);
99         if (rc)
100                 return rc;
101
102         return 0;
103 }