clk: vc5: Add support for IDT VersaClock 5P49V5923B and 5P49V5933
Subsystems (3)
PATCH v3 1/1 clk: vc5: Add support for IDT VersaClock 5P49V5923B and 5P49V5933
Add driver for IDT VersaClock 5 5P49V5923B and 5P49V5933 chips. These chips have two clock inputs, XTAL or CLK, which are muxed into single PLL/VCO input. In case of 5P49V5923B, the XTAL in built into the chip while the 5P49V5923B requires external XTAL.
The PLL feeds two fractional dividers. Each fractional divider feeds output mux, which allows selecting between clock from the fractional divider itself or from output mux on output N-1. In case of output mux 0, the output N-1 is instead connected to the output from the mux feeding the PLL.
The driver thus far supports only the 5P49V5923B and 5P49V5933, while it should be easily extensible to the whole 5P49V59xx family of chips as they are all pretty similar.
---
V2: - Drop address-cells and size-cells from the binding
- Add clock-names to the binding
- Drop vc5_input_names
- Fix assortment of spelling mistakes
- Switch div_frc and div_int datatype to uXX
- Switch f_in to u32
- Add missing remove
- Define macros for handling XIN and CLKIN
- Rework the FOD fractional divider calculation, this was wrong and made the output clock be off considerably under certain circumstances (when the fractional part was large).
V3: - Rework the MUX frequency recalculation and divider configration
so that it fits into the clock framework
- Add support for 5P49V5933 chip to lay groundwork for adding more chips easily.
- Export the OUT0_SEL_I2CB output into the clock framework, so it can be accessed from DT as well. WARNING: This does change the bindings, clock0 is now the OUT0_SEL_I2CB, clock1 is OUT1 and clock2 is OUT2 (or OUT4 on the 5P49V5933).
- Drop unnecessary caching of pin_*_name clock name and clk_hw structures in driver data.
- Add missing MAINTAINERS entry
--- .../devicetree/bindings/clock/idt,versaclock5.txt | 43 ++ MAINTAINERS | 5 + drivers/clk/Kconfig | 10 + drivers/clk/Makefile | 1 + drivers/clk/clk-versaclock5.c | 823 +++++++++++++++++++++ 5 files changed, 882 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/idt,versaclock5.txt create mode 100644 drivers/clk/clk-versaclock5.c
Documentation/devicetree/bindings/clock/idt,versaclock5.txt new file +43 -0
@@ -0,0 +1,43 @@ +Binding for IDT VersaClock5 programmable i2c clock generator. + +The IDT VersaClock5 are programmable i2c clock generators providing +from 3 to 12 output clocks. + +==I2C device node== + +Required properties: +- compatible: shall be one of "idt,5p49v5923b" , "idt,5p49v5933". +- reg: i2c device address, shall be 0x68 or 0x6a. +- #clock-cells: from common clock binding; shall be set to 1. +- clocks: from common clock binding; list of parent clock handles, + - 5p49v5923b: (required) either or both of XTAL or CLKIN + reference clock. + - 5p49v5933: (optional) property not present (internal + Xtal used) or CLKIN reference + clock. +- clock-names: from common clock binding; clock input names, can be + - 5p49v5923b: (required) either or both of "xin", "clkin". + - 5p49v5933: (optional) property not present or "clkin". + +==Example== + +/* 25MHz reference crystal */ +ref25: ref25m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; +}; + +i2c-master-node { + + /* IDT 5P49V5923B i2c clock generator */ + vc5: clock-generator@6a { + compatible = "idt,5p49v5923b"; + reg = <0x6a>; + #clock-cells = <1>; + + /* Connect XIN input to 25MHz reference */ + clocks = <&ref25m>; + clock-names = "xin"; + }; +};
MAINTAINERS +5 -0
@@ -6113,6 +6113,11 @@ S: Maintained F: drivers/mfd/lpc_ich.c F: drivers/gpio/gpio-ich.c +IDT VersaClock 5 CLOCK DRIVER +M: Marek Vasut <[email protected]> +S: Maintained +F: drivers/clk/clk-versaclock5.c + IDE SUBSYSTEM M: "David S. Miller" <[email protected]> L: [email protected]
drivers/clk/Kconfig +10 -0
@@ -198,6 +198,16 @@ config COMMON_CLK_OXNAS ---help--- Support for the OXNAS SoC Family clocks. +config COMMON_CLK_VC5 + tristate "Clock driver for IDT VersaClock5 devices" + depends on I2C + depends on OF + select REGMAP_I2C + help + ---help--- + This driver supports the IDT VersaClock5 programmable clock + generator. + source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/mediatek/Kconfig"
drivers/clk/Makefile +1 -0
@@ -46,6 +46,7 @@ obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o +obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
drivers/clk/clk-versaclock5.c new file +823 -0
823 lines not on this page · raw message
Signature · 1 line
2.11.0
Hi Marek,
Quoted 11 lines · Marek Vasut
Add driver for IDT VersaClock 5 5P49V5923B and 5P49V5933 chips. These chips have two clock inputs, XTAL or CLK, which are muxed into single PLL/VCO input. In case of 5P49V5923B, the XTAL in built into the chip while the 5P49V5923B requires external XTAL.
The PLL feeds two fractional dividers. Each fractional divider feeds output mux, which allows selecting between clock from the fractional divider itself or from output mux on output N-1. In case of output mux 0, the output N-1 is instead connected to the output from the mux feeding the PLL.
Quoted 3 lines
The driver thus far supports only the 5P49V5923B and 5P49V5933, while it should be easily extensible to the whole 5P49V59xx family of chips as they are all pretty similar.
According to the datasheet, r8a7795/salvator-x has '5923A, while r8a7796-salvator-x has '5923B. I guess the driver is supposed to work with both, as the first version was tested on r8a7795/salvator-x? Shouldn't that be reflected in the bindings and compatible value?
Do you know what's the difference between the '5923A and '5923B variants?
Quoted 39 lines
drivers/clk/clk-versaclock5.c new file +35
-0@@ -0,0 +1,823 @@ +static int vc5_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +const struct of_device_id *of_id = +of_match_device (clk_vc5_of_match, &client->dev); +struct vc5_driver_data *vc5; +struct clk_init_data init; +const char *parent_names[2 ]; +unsigned int n, idx; +int ret; + + vc5 =devm_kzalloc (&client->dev,sizeof (*vc5),GFP_KERNEL ); +if (vc5 ==NULL ) +return -ENOMEM ; + +i2c_set_clientdata (client, vc5); + vc5->client = client; + vc5->model = (enum vc5_model )of_id->data; + + vc5->pin_xin =devm_clk_get (&client->dev,"xin" ); +if (PTR_ERR (vc5->pin_xin) == -EPROBE_DEFER ) +return -EPROBE_DEFER ; + + vc5->pin_clkin =devm_clk_get (&client->dev,"clkin" ); +if (PTR_ERR (vc5->pin_clkin) == -EPROBE_DEFER ) +return -EPROBE_DEFER ; + + vc5->regmap =devm_regmap_init_i2c (client, &vc5_regmap_config); +if (IS_ERR (vc5->regmap)) { +dev_err (&client->dev,"failed to allocate register map\n" ); +return PTR_ERR (vc5->regmap); + } + +/* Register clock input mux */ +memset (&init,0 ,sizeof (init));
drivers/clk/clk-versaclock5.c line 648
Quoted 10 lines
drivers/clk/clk-versaclock5.c new file +10
-0+ +if (!IS_ERR (vc5->pin_xin)) { +clk_prepare_enable (vc5->pin_xin); + vc5->clk_mux_ins |=VC5_MUX_IN_XIN ; + parent_names[init.num_parents++] =__clk_get_name (vc5->pin_xin); + }else if (vc5->model ==IDT_VC5_5P49V5933 ) { +/* IDT VC5 5P49V5933 has built-in oscilator. */ + vc5->pin_xin =clk_register_fixed_rate (&client->dev, +"internal-xtal" ,NULL , +0 ,25000000 );
What happens if you have two VC5 instances, each creating their own "internal-xtal" using the same clock name?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 1 line · Geert Uytterhoeven
Hi Marek,
Hi!
Quoted 16 lines · Marek Vasut
Quoted 11 lines
Add driver for IDT VersaClock 5 5P49V5923B and 5P49V5933 chips. These chips have two clock inputs, XTAL or CLK, which are muxed into single PLL/VCO input. In case of 5P49V5923B, the XTAL in built into the chip while the 5P49V5923B requires external XTAL.
The PLL feeds two fractional dividers. Each fractional divider feeds output mux, which allows selecting between clock from the fractional divider itself or from output mux on output N-1. In case of output mux 0, the output N-1 is instead connected to the output from the mux feeding the PLL.
Quoted 3 lines
The driver thus far supports only the 5P49V5923B and 5P49V5933, while it should be easily extensible to the whole 5P49V59xx family of chips as they are all pretty similar.
Quoted 7 lines
According to the datasheet, r8a7795/salvator-x has '5923A, while r8a7796-salvator-x has '5923B. I guess the driver is supposed to work with both, as the first version was tested on r8a7795/salvator-x? Shouldn't that be reflected in the bindings and compatible value?
Do you know what's the difference between the '5923A and '5923B variants?
Look at this update notice:
https://www.idt.com/document/pcn/pcn-mm1510-01-programming-configuration-change-versa-clock
TLDR the VCO monitoring bit is turned off on rev. B, which shouldn't affect the behavior of the chip.
I only tested the patch with rev B chip, but it should work with rev A too and I'd love to have a single binding for both, ie "idt,5p49v5923". I think I'll just send a V4 patch and update the compat string to drop the B at the end. Agreed ?
Quoted 44 lines
Quoted 44 lines
drivers/clk/clk-versaclock5.c new file +40
-0@@ -0,0 +1,823 @@ +static int vc5_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ +const struct of_device_id *of_id = +of_match_device (clk_vc5_of_match, &client->dev); +struct vc5_driver_data *vc5; +struct clk_init_data init; +const char *parent_names[2 ]; +unsigned int n, idx; +int ret; + + vc5 =devm_kzalloc (&client->dev,sizeof (*vc5),GFP_KERNEL ); +if (vc5 ==NULL ) +return -ENOMEM ; + +i2c_set_clientdata (client, vc5); + vc5->client = client; + vc5->model = (enum vc5_model )of_id->data; + + vc5->pin_xin =devm_clk_get (&client->dev,"xin" ); +if (PTR_ERR (vc5->pin_xin) == -EPROBE_DEFER ) +return -EPROBE_DEFER ; + + vc5->pin_clkin =devm_clk_get (&client->dev,"clkin" ); +if (PTR_ERR (vc5->pin_clkin) == -EPROBE_DEFER ) +return -EPROBE_DEFER ; + + vc5->regmap =devm_regmap_init_i2c (client, &vc5_regmap_config); +if (IS_ERR (vc5->regmap)) { +dev_err (&client->dev,"failed to allocate register map\n" ); +return PTR_ERR (vc5->regmap); + } + +/* Register clock input mux */ +memset (&init,0 ,sizeof (init)); + +if (!IS_ERR (vc5->pin_xin)) { +clk_prepare_enable (vc5->pin_xin); + vc5->clk_mux_ins |=VC5_MUX_IN_XIN ; + parent_names[init.num_parents++] =__clk_get_name (vc5->pin_xin);
Quoted 8 lines
drivers/clk/clk-versaclock5.c line 648
Quoted 5 lines
drivers/clk/clk-versaclock5.c new file +5
-0+ }else if (vc5->model ==IDT_VC5_5P49V5933 ) { +/* IDT VC5 5P49V5933 has built-in oscilator. */ + vc5->pin_xin =clk_register_fixed_rate (&client->dev, +"internal-xtal" ,NULL , +0 ,25000000 );What happens if you have two VC5 instances, each creating their own "internal-xtal" using the same clock name?
The fixed rate clock will have different device node (client->dev) associated with them, so you'll have two internal-xtal clock in the clock tree, but represented with two different kernel objects.
Signature · 2 lines
Best regards, Marek Vasut