2018-05-06 21:58:06 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2016-05-16 06:17:25 +00:00
|
|
|
/*
|
|
|
|
* clk-synthesizer.c
|
|
|
|
*
|
|
|
|
* Clock synthesizer apis
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <asm/arch/clk_synthesizer.h>
|
|
|
|
#include <i2c.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* clk_synthesizer_reg_read - Read register from synthesizer.
|
2018-12-07 13:50:49 +00:00
|
|
|
* dev: i2c bus device (not used if CONFIG_DM_I2C is not set)
|
2016-05-16 06:17:25 +00:00
|
|
|
* @addr: addr within the i2c device
|
|
|
|
* buf: Buffer to which value is to be read.
|
|
|
|
*
|
|
|
|
* For reading the register from this clock synthesizer, a command needs to
|
|
|
|
* be send along with enabling byte read more, and then read can happen.
|
|
|
|
* Returns 0 on success
|
|
|
|
*/
|
2018-12-07 13:50:49 +00:00
|
|
|
static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf)
|
2016-05-16 06:17:25 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* Enable Bye read */
|
|
|
|
addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
|
|
|
|
|
2021-02-09 11:52:45 +00:00
|
|
|
#if !CONFIG_IS_ENABLED(DM_I2C)
|
2016-05-16 06:17:25 +00:00
|
|
|
/* Send the command byte */
|
|
|
|
rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
|
|
|
|
if (rc)
|
|
|
|
printf("Failed to send command to clock synthesizer\n");
|
|
|
|
|
|
|
|
/* Read the Data */
|
|
|
|
return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
|
2018-12-07 13:50:49 +00:00
|
|
|
#else
|
|
|
|
/* Send the command byte */
|
|
|
|
rc = dm_i2c_reg_write(dev, addr, *buf);
|
|
|
|
if (rc)
|
|
|
|
printf("Failed to send command to clock synthesizer\n");
|
|
|
|
|
|
|
|
/* Read the Data */
|
|
|
|
rc = dm_i2c_reg_read(dev, addr);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
*buf = (u8)rc;
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
|
2016-05-16 06:17:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* clk_synthesizer_reg_write - Write a value to register in synthesizer.
|
2018-12-07 13:50:49 +00:00
|
|
|
* dev: i2c bus device (not used if CONFIG_DM_I2C is not set)
|
2016-05-16 06:17:25 +00:00
|
|
|
* @addr: addr within the i2c device
|
|
|
|
* val: Value to be written in the addr.
|
|
|
|
*
|
|
|
|
* Enable the byte read mode in the address and start the i2c transfer.
|
|
|
|
* Returns 0 on success
|
|
|
|
*/
|
2018-12-07 13:50:49 +00:00
|
|
|
static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val)
|
2016-05-16 06:17:25 +00:00
|
|
|
{
|
2018-12-07 13:50:49 +00:00
|
|
|
u8 cmd[2];
|
2016-05-16 06:17:25 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/* Enable byte write */
|
|
|
|
cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
|
|
|
|
cmd[1] = val;
|
|
|
|
|
2021-02-09 11:52:45 +00:00
|
|
|
#if !CONFIG_IS_ENABLED(DM_I2C)
|
2016-05-16 06:17:25 +00:00
|
|
|
rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
|
2018-12-07 13:50:49 +00:00
|
|
|
#else
|
|
|
|
rc = dm_i2c_write(dev, addr, cmd, 2);
|
|
|
|
#endif
|
2016-05-16 06:17:25 +00:00
|
|
|
if (rc)
|
|
|
|
printf("Clock synthesizer reg write failed at addr = 0x%x\n",
|
|
|
|
addr);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setup_clock_syntherizer - Program the clock synthesizer to get the desired
|
|
|
|
* frequency.
|
|
|
|
* @data: Data containing the desired output
|
|
|
|
*
|
|
|
|
* This is a PLL-based high performance synthesizer which gives 3 outputs
|
|
|
|
* as per the PLL_DIV and load capacitor programmed.
|
|
|
|
*/
|
|
|
|
int setup_clock_synthesizer(struct clk_synth *data)
|
|
|
|
{
|
|
|
|
int rc;
|
2018-12-07 13:50:49 +00:00
|
|
|
u8 val = 0;
|
|
|
|
struct udevice *dev = NULL;
|
2021-02-09 11:52:45 +00:00
|
|
|
#if !CONFIG_IS_ENABLED(DM_I2C)
|
2016-05-16 06:17:25 +00:00
|
|
|
rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
|
|
|
|
if (rc) {
|
|
|
|
printf("i2c probe failed at address 0x%x\n",
|
|
|
|
CLK_SYNTHESIZER_I2C_ADDR);
|
|
|
|
return rc;
|
|
|
|
}
|
2018-12-07 13:50:49 +00:00
|
|
|
#else
|
|
|
|
rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev);
|
|
|
|
if (rc) {
|
|
|
|
printf("failed to get device for synthesizer at address 0x%x\n",
|
|
|
|
CLK_SYNTHESIZER_I2C_ADDR);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val);
|
2016-05-16 06:17:25 +00:00
|
|
|
if (val != data->id)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
/* Crystal Load capacitor selection */
|
2018-12-07 13:50:49 +00:00
|
|
|
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL,
|
|
|
|
data->capacitor);
|
2016-05-16 06:17:25 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2018-12-07 13:50:49 +00:00
|
|
|
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG,
|
|
|
|
data->mux);
|
2016-05-16 06:17:25 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2018-12-07 13:50:49 +00:00
|
|
|
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG,
|
|
|
|
data->pdiv2);
|
2016-05-16 06:17:25 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2018-12-07 13:50:49 +00:00
|
|
|
rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG,
|
|
|
|
data->pdiv3);
|
2016-05-16 06:17:25 +00:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|