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 * dev: i2c bus device (not used if CONFIG_DM_I2C is not set) 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(struct udevice *dev, int addr, u8 *buf) 26 { 27 int rc; 28 29 /* Enable Bye read */ 30 addr = addr | CLK_SYNTHESIZER_BYTE_MODE; 31 32 #ifndef CONFIG_DM_I2C 33 /* Send the command byte */ 34 rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); 35 if (rc) 36 printf("Failed to send command to clock synthesizer\n"); 37 38 /* Read the Data */ 39 return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); 40 #else 41 /* Send the command byte */ 42 rc = dm_i2c_reg_write(dev, addr, *buf); 43 if (rc) 44 printf("Failed to send command to clock synthesizer\n"); 45 46 /* Read the Data */ 47 rc = dm_i2c_reg_read(dev, addr); 48 if (rc < 0) 49 return rc; 50 51 *buf = (u8)rc; 52 return 0; 53 #endif 54 55 } 56 57 /** 58 * clk_synthesizer_reg_write - Write a value to register in synthesizer. 59 * dev: i2c bus device (not used if CONFIG_DM_I2C is not set) 60 * @addr: addr within the i2c device 61 * val: Value to be written in the addr. 62 * 63 * Enable the byte read mode in the address and start the i2c transfer. 64 * Returns 0 on success 65 */ 66 static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val) 67 { 68 u8 cmd[2]; 69 int rc = 0; 70 71 /* Enable byte write */ 72 cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE; 73 cmd[1] = val; 74 75 #ifndef CONFIG_DM_I2C 76 rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2); 77 #else 78 rc = dm_i2c_write(dev, addr, cmd, 2); 79 #endif 80 if (rc) 81 printf("Clock synthesizer reg write failed at addr = 0x%x\n", 82 addr); 83 return rc; 84 } 85 86 /** 87 * setup_clock_syntherizer - Program the clock synthesizer to get the desired 88 * frequency. 89 * @data: Data containing the desired output 90 * 91 * This is a PLL-based high performance synthesizer which gives 3 outputs 92 * as per the PLL_DIV and load capacitor programmed. 93 */ 94 int setup_clock_synthesizer(struct clk_synth *data) 95 { 96 int rc; 97 u8 val = 0; 98 struct udevice *dev = NULL; 99 #ifndef CONFIG_DM_I2C 100 rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR); 101 if (rc) { 102 printf("i2c probe failed at address 0x%x\n", 103 CLK_SYNTHESIZER_I2C_ADDR); 104 return rc; 105 } 106 #else 107 rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev); 108 if (rc) { 109 printf("failed to get device for synthesizer at address 0x%x\n", 110 CLK_SYNTHESIZER_I2C_ADDR); 111 return rc; 112 } 113 #endif 114 rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val); 115 if (val != data->id) 116 return rc; 117 118 /* Crystal Load capacitor selection */ 119 rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL, 120 data->capacitor); 121 if (rc) 122 return rc; 123 rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG, 124 data->mux); 125 if (rc) 126 return rc; 127 rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG, 128 data->pdiv2); 129 if (rc) 130 return rc; 131 rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG, 132 data->pdiv3); 133 if (rc) 134 return rc; 135 136 return 0; 137 } 138