Home | History | Annotate | Download | only in am33xx
      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 }
    104