1 // SPDX-License-Identifier: GPL-2.0+
3 * Texas Instruments CDCE913/925/937/949 clock synthesizer driver
5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6 * Tero Kristo <t-kristo@ti.com>
8 * Based on Linux kernel clk-cdce925.c.
14 #include <clk-uclass.h>
16 #include <dm/device_compat.h>
18 #define MAX_NUMBER_OF_PLLS 4
19 #define MAX_NUMER_OF_OUTPUTS 9
21 #define CDCE9XX_REG_GLOBAL1 0x01
22 #define CDCE9XX_REG_Y1SPIPDIVH 0x02
23 #define CDCE9XX_REG_PDIV1L 0x03
24 #define CDCE9XX_REG_XCSEL 0x05
26 #define CDCE9XX_PDIV1_H_MASK 0x3
28 #define CDCE9XX_REG_PDIV(clk) (0x16 + (((clk) - 1) & 1) + \
29 ((clk) - 1) / 2 * 0x10)
31 #define CDCE9XX_PDIV_MASK 0x7f
33 #define CDCE9XX_BYTE_TRANSFER BIT(7)
35 struct cdce9xx_chip_info {
40 struct cdce9xx_clk_data {
42 struct cdce9xx_chip_info *chip;
46 static const struct cdce9xx_chip_info cdce913_chip_info = {
47 .num_plls = 1, .num_outputs = 3,
50 static const struct cdce9xx_chip_info cdce925_chip_info = {
51 .num_plls = 2, .num_outputs = 5,
54 static const struct cdce9xx_chip_info cdce937_chip_info = {
55 .num_plls = 3, .num_outputs = 7,
58 static const struct cdce9xx_chip_info cdce949_chip_info = {
59 .num_plls = 4, .num_outputs = 9,
62 static int cdce9xx_reg_read(struct udevice *dev, u8 addr, u8 *buf)
64 struct cdce9xx_clk_data *data = dev_get_priv(dev);
67 ret = dm_i2c_read(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, buf, 1);
69 dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
75 static int cdce9xx_reg_write(struct udevice *dev, u8 addr, u8 val)
77 struct cdce9xx_clk_data *data = dev_get_priv(dev);
80 ret = dm_i2c_write(data->i2c, addr | CDCE9XX_BYTE_TRANSFER, &val, 1);
82 dev_err(dev, "%s: failed for addr:%x, ret:%d\n", __func__,
88 static int cdce9xx_clk_of_xlate(struct clk *clk,
89 struct ofnode_phandle_args *args)
91 struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
93 if (args->args_count != 1)
96 if (args->args[0] > data->chip->num_outputs)
99 clk->id = args->args[0];
104 static int cdce9xx_clk_probe(struct udevice *dev)
106 struct cdce9xx_clk_data *data = dev_get_priv(dev);
107 struct cdce9xx_chip_info *chip = (void *)dev_get_driver_data(dev);
112 val = (u32)dev_read_addr_ptr(dev);
114 ret = i2c_get_chip(dev->parent, val, 1, &data->i2c);
116 dev_err(dev, "I2C probe failed.\n");
122 ret = clk_get_by_index(dev, 0, &clk);
123 data->xtal_rate = clk_get_rate(&clk);
125 val = dev_read_u32_default(dev, "xtal-load-pf", -1);
127 cdce9xx_reg_write(dev, CDCE9XX_REG_XCSEL, val << 3);
132 static u16 cdce9xx_clk_get_pdiv(struct clk *clk)
139 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
143 pdiv = (val & CDCE9XX_PDIV1_H_MASK) << 8;
145 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV1L, &val);
151 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
156 pdiv = val & CDCE9XX_PDIV_MASK;
162 static u32 cdce9xx_clk_get_parent_rate(struct clk *clk)
164 struct cdce9xx_clk_data *data = dev_get_priv(clk->dev);
166 return data->xtal_rate;
169 static ulong cdce9xx_clk_get_rate(struct clk *clk)
174 parent_rate = cdce9xx_clk_get_parent_rate(clk);
176 pdiv = cdce9xx_clk_get_pdiv(clk);
178 return parent_rate / pdiv;
181 static ulong cdce9xx_clk_set_rate(struct clk *clk, ulong rate)
189 parent_rate = cdce9xx_clk_get_parent_rate(clk);
191 pdiv = parent_rate / rate;
193 diff = rate - parent_rate / pdiv;
195 if (rate - parent_rate / (pdiv + 1) < diff)
199 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, &val);
203 val &= ~CDCE9XX_PDIV1_H_MASK;
207 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_Y1SPIPDIVH, val);
211 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV1L,
216 ret = cdce9xx_reg_read(clk->dev, CDCE9XX_REG_PDIV(clk->id),
221 val &= ~CDCE9XX_PDIV_MASK;
225 ret = cdce9xx_reg_write(clk->dev, CDCE9XX_REG_PDIV(clk->id),
234 static const struct udevice_id cdce9xx_clk_of_match[] = {
235 { .compatible = "ti,cdce913", .data = (u32)&cdce913_chip_info },
236 { .compatible = "ti,cdce925", .data = (u32)&cdce925_chip_info },
237 { .compatible = "ti,cdce937", .data = (u32)&cdce937_chip_info },
238 { .compatible = "ti,cdce949", .data = (u32)&cdce949_chip_info },
242 static const struct clk_ops cdce9xx_clk_ops = {
243 .of_xlate = cdce9xx_clk_of_xlate,
244 .get_rate = cdce9xx_clk_get_rate,
245 .set_rate = cdce9xx_clk_set_rate,
248 U_BOOT_DRIVER(cdce9xx_clk) = {
249 .name = "cdce9xx-clk",
251 .of_match = cdce9xx_clk_of_match,
252 .probe = cdce9xx_clk_probe,
253 .priv_auto_alloc_size = sizeof(struct cdce9xx_clk_data),
254 .ops = &cdce9xx_clk_ops,