linux-renesas-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/3] Add Versa3 clock generator support
@ 2023-04-13 15:26 Biju Das
  2023-04-13 15:26 ` [PATCH v5 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings Biju Das
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Biju Das @ 2023-04-13 15:26 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski
  Cc: Biju Das, Geert Uytterhoeven, linux-renesas-soc, linux-clk,
	devicetree, Prabhakar Mahadev Lad

The 5P35023 is a VersaClock programmable clock generator and
it provides 6 clk outputs {diff2, diff1, se3, se2, se1 and refin}.

It has an internal OTP memory allows the user to store the configuration
in the device. After power up, the user can change the device register
settings through the I2C interface when I2C mode is selected.

This driver is for overriding OTP default values during boot based on
a full register map from DT, and also minimal support to change the
parent of a output clock.

The motivation for developing this driver is for supporting 48KHz
playback/record with audio codec on RZ/G2L SMARC EVK.

On RZ/G2L SMARC EVK, By default audio mclk is connected to
11.2896 MHz clk which is multiple of 44.1KHz.

Please see the below default OTP configuration of Dividers connected to
output clocks.

DIV3 12.2880 MHz   DIFF2--> Audio clk2
DIV5 11.2896 MHz   SE1  --> Audio clk1
DIV5 11.2896 MHz   SE2  --> Audio mck
DIV4 12      MHz   SE3  --> This clk Not used
DIV1 25 MHz        DIFF1-->Ethernet clk
Ref1-> 24MHz

With this setup, we won't be able to do 48KHz playback/record on audio codec,
as mck is always connected to 11.2896MHz clk.

But by programming the i2c, we can make use of DIV4 to generate 12.2880 MHz
and make that as parent of SE2 and there by supporting 48KHz playback/record.

A block diagram with modification can be find here[1]
[1]https://paste.pics/a253ce7cdc8720c3b5eb6953b97b25ff

DIV3 12.2880 MHz   DIFF2--> Audio clk2
DIV5 11.2896 MHz   SE1  --> Audio clk1
DIV5 11.2896 MHz | SE2  --> Audio mck
DIV4 12.2880 MHz |
DIV2 12      MHz   SE3  --> This clk Not used
DIV1 25 MHz        DIFF1--> Ethernet clk
Ref1-> 24MHz

The driver can read a full register map from the DT, and will use that
register map to initialize the clk generator when the system
boots.
and later, based on sampling rate, it switches the parent of SE2 and
support both 44.1 and 48 KHz playback/record at run time.

v4->v5:
 * Added missing .determine_rate() for muxes
 * Fixed smatch warning: replace divide condition 'req->best_parent_rate / req->rate'
   with 'req->best_parent_rate >= req->rate'  Reported-by: kernel test robot <lkp@intel.com>
   and Reported-by: Dan Carpenter <error27@gmail.com>
v3->v4:
 * Fixed the warning reported by  kernel test robot.
 * Added error check for devm_clk_hw_register_fixed_factor_* in probe().
v2->v3:
 * Added Rb tag from Krzysztof Kozlowski
 * Removed | from Link to data sheet.
 * Dropped stray blank line from example.
 * Updated example section for assigned-clocks to mach same alignment
   with assigned-clock-rates. This is trivial change so retained the
   Rb tag.
 * Updated copy right information.
 * Removed .name from parent data and started using index or struct clk_hw.
 * Dropped vc3_clk_out_ops  and started using fixed factor clocks for
   output clk.
 * Dropped vc3_divider_type_parse_dt function.
 * Dropped struct vc3_driver_data
 * Updated the dtsi changes for RZ/G2LC and RZ/G2{UL, Five}.
RFC->v2:
 * Renamed the filename to match with compatible
 * Added maintainers entry after title
 * Removed the wrapping for the link to data sheet.
 * Removed reg description
 * Removed clock names
 * Replaced minItems->maxItems in renesas,settings property
 * Dropped assigned-clocks, assigned-clock-rates
 * Dropped renesas,clock-divider-read-only and renesas,clock-flags
 * Drooped clock handle part from example
 * Dropped reg from example.
 * Dropped consumer example
 * Dropped header file <linux/clk.h> and removed all
   consumer api's
 * struct clk_parent_data used for assigning the parent names.
 * Replaced initpointer->const init pointer in vc3_clk_register
 * Replaced of_clk_add_hw_provider with devm_clk_add_hw_provider
 * Dropped vc3_remove() callback.

Logs:
root@smarc-rzg2l:~# /audio_test.sh
                                 enable  prepare  protect                                duty  hardware
   clock                          count    count    count        rate   accuracy phase  cycle    enable
-------------------------------------------------------------------------------------------------------
 xtal                                 0        0        0    24000000          0     0  50000         Y
    ref                               0        0        0    24000000          0     0  50000         Y
    pfd1                              0        0        0    24000000          0     0  50000         Y
       pll1                           0        0        0   600000000          0     0  50000         Y
          div2                        0        0        0    12000000          0     0  50000         Y
             se3_mux                  0        0        0    12000000          0     0  50000         Y
                se3                   0        0        0    12000000          0     0  50000         Y
          div1_mux                    0        0        0   600000000          0     0  50000         Y
             div1                     0        0        0    25000000          0     0  50000         Y
                diff1_mux             0        0        0    25000000          0     0  50000         Y
                   diff1              0        0        0    25000000          0     0  50000         Y
    pfd3_mux                          0        0        0    24000000          0     0  50000         Y
       pfd3                           0        0        0      960000          0     0  50000         Y
          pll3                        0        0        0   564480000          0     0  50000         Y
             div5                     0        0        0    11289600          0     0  50000         Y
                se1_mux               0        0        0    11289600          0     0  50000         Y
                   se1                0        0        0    11289600          0     0  50000         Y
                se2_mux               0        0        0    11289600          0     0  50000         Y
                   se2                0        0        0    11289600          0     0  50000         Y
    pfd2_mux                          0        0        0    24000000          0     0  50000         Y
       pfd2                           0        0        0    24000000          0     0  50000         Y
          pll2                        0        0        0   491519897          0     0  50000         Y
             div4_mux                 0        0        0   491519897          0     0  50000         Y
                div4                  0        0        0    12287998          0     0  50000         Y
             div3_mux                 0        0        0   491519897          0     0  50000         Y
                div3                  0        0        0    12287998          0     0  50000         Y
                   diff2_mux          0        0        0    12287998          0     0  50000         Y
                      diff2           0        0        0    12287998          0     0  50000         Y
 extal-clk                            4        4        0    24000000          0     0  50000         Y
    .pll5_foutpostdiv                 0        0        0    24000000          0     0  50000         Y
       M1                             0        0        0    24000000          0     0  50000         Y
          dsi_pll_clk                 0        0        0    24000000          0     0  50000         N
       .sel_pll5_4                    0        0        0    24000000          0     0  50000         Y
          DSI_DIV                     0        0        0    24000000          0     0  50000         Y
             M3                       0        0        0    24000000          0     0  50000         Y
                lcdc_clk_d            0        0        0    24000000          0     0  50000         N
                dsi_vclk              0        0        0    24000000          0     0  50000         N
       .pll5_fout1ph0                 0        0        0    12000000          0     0  50000         Y
    .pll6                             2        2        0   500000000          0     0  50000         Y
       .sel_gpu2                      1        1        0   500000000          0     0  50000         Y
          G                           1        1        0    62500000          0     0  50000         Y
             gpu_clk                  1        2        0    62500000          0     0  50000         Y
       .pll6_250                      1        1        0   250000000          0     0  50000         Y
          HP                          2        2        0   250000000          0     0  50000         Y
    .pll5                             0        0        0  3000000000          0     0  50000         Y
       .pll5_fout3                    0        0        0   500000000          0     0  50000         Y
          .pll5_250                   0        0        0   250000000          0     0  50000         Y
    .pll3                             1        2        0  1600000000          0     0  50000         Y
       .pll3_div2                     1        1        0   800000000          0     0  50000         Y
          .pll3_div2_4                3        3        0   200000000          0     0  50000         Y
             M0                       2        2        0   200000000          0     0  50000         Y
                eth1_axi              1        1        0   200000000          0     0  50000         Y
                eth0_axi              1        1        0   200000000          0     0  50000         Y
                lcdc_a                0        0        0   200000000          0     0  50000         N
                cru_aclk              0        0        0   200000000          0     0  50000         N
             P1                      11       12        0   200000000          0     0  50000         Y
                usb_pclk              8       12        0   200000000          0     0  50000         Y
                usb0_func             1        1        0   200000000          0     0  50000         Y
                usb1_host             3        5        0   200000000          0     0  50000         Y
                usb0_host             3        5        0   200000000          0     0  50000         Y
                dsi_aclk              0        0        0   200000000          0     0  50000         N
                gpu_ace_clk           0        1        0   200000000          0     0  50000         N
                gpu_axi_clk           1        2        0   200000000          0     0  50000         Y
                sdhi1_aclk            1        1        0   200000000          0     0  50000         Y
                sdhi0_aclk            1        1        0   200000000          0     0  50000         Y
                dmac_aclk             2        2        0   200000000          0     0  50000         Y
                ia55_clk              2        2        0   200000000          0     0  50000         Y
                gic                   1        1        0   200000000          0     0  50000         Y
                P1_DIV2               1        1        0   100000000          0     0  50000         Y
                   dmac_pclk          1        1        0   100000000          0     0  50000         Y
             .pll3_div2_4_2           2        2        0   100000000          0     0  50000         Y
                ZT                    2        2        0   100000000          0     0  50000         Y
                   eth1_chi           1        1        0   100000000          0     0  50000         Y
                   eth0_chi           1        1        0   100000000          0     0  50000         Y
                   lcdc_p             0        0        0   100000000          0     0  50000         N
                   cru_pclk           0        0        0   100000000          0     0  50000         N
                P2                    1        1        0   100000000          0     0  50000         Y
                   dsi_pclk           0        0        0   100000000          0     0  50000         N
                   ia55_pclk          1        1        0   100000000          0     0  50000         Y
          .pll3_div2_2                0        0        0   400000000          0     0  50000         Y
       .pll3_533                      0        1        0   533333333          0     0  50000         Y
          M2                          0        0        0   266666666          0     0  50000         Y
             cru_vclk                 0        0        0   266666666          0     0  50000         N
             M2_DIV2                  0        0        0   133333333          0     0  50000         Y
                dsi_sys_clk           0        0        0   133333333          0     0  50000         N
                cru_sysclk            0        0        0   133333333          0     0  50000         N
          .sel_pll3_3                 0        1        0   533333333          0     0  50000         Y
             divpl3c                  0        2        0   266666667          0     0  50000         Y
                SPI1                  0        1        0    66666666          0     0  50000         Y
                   spi_clk2           0        1        0    66666666          0     0  50000         N
                SPI0                  0        1        0   133333333          0     0  50000         Y
                   spi_clk            0        1        0   133333333          0     0  50000         N
       .pll3_400                      0        0        0   400000000          0     0  50000         Y
    .pll2                             2        2        0  1600000000          0     0  50000         Y
       .clk_533                       2        2        0   533333333          0     0  50000         Y
          sd1                         2        2        0   533333333          0     0  50000         Y
             sdhi1_clk_hs             1        1        0   533333333          0     0  50000         Y
             SD1_DIV4                 2        2        0   133333333          0     0  50000         Y
                sdhi1_imclk2          2        2        0   133333333          0     0  50000         Y
                sdhi1_imclk           1        1        0   133333333          0     0  50000         Y
          sd0                         2        2        0   533333333          0     0  50000         Y
             sdhi0_clk_hs             1        1        0   533333333          0     0  50000         Y
             SD0_DIV4                 2        2        0   133333333          0     0  50000         Y
                sdhi0_imclk2          2        2        0   133333333          0     0  50000         Y
                sdhi0_imclk           1        1        0   133333333          0     0  50000         Y
          .clk_266                    0        0        0   266666666          0     0  50000         Y
       .clk_800                       0        0        0   800000000          0     0  50000         Y
          .clk_400                    0        0        0   400000000          0     0  50000         Y
       .pll2_div2                     2        2        0   800000000          0     0  50000         Y
          .pll2_div2_10               1        1        0    80000000          0     0  50000         Y
             TSU                      1        2        0    80000000          0     0  50000         Y
                tsu_pclk              1        1        0    80000000          0     0  50000         Y
                adc_adclk             0        1        0    80000000          0     0  50000         N
          .pll2_div2_8                1        1        0   100000000          0     0  50000         Y
             P0                       6       14        0   100000000          0     0  50000         Y
                adc_pclk              0        1        0   100000000          0     0  50000         N
                canfd                 1        2        0   100000000          0     0  50000         Y
                rspi2                 0        0        0   100000000          0     0  50000         N
                rspi1                 0        1        0   100000000          0     0  50000         N
                rspi0                 0        0        0   100000000          0     0  50000         N
                sci1                  0        0        0   100000000          0     0  50000         N
                sci0                  0        0        0   100000000          0     0  50000         N
                scif4                 0        0        0   100000000          0     0  50000         N
                scif3                 0        0        0   100000000          0     0  50000         N
                scif2                 0        1        0   100000000          0     0  50000         N
                scif1                 0        0        0   100000000          0     0  50000         N
                scif0                 2        2        0   100000000          0     0  50000         Y
                i2c3                  0        1        0   100000000          0     0  50000         N
                i2c2                  0        0        0   100000000          0     0  50000         N
                i2c1                  0        1        0   100000000          0     0  50000         N
                i2c0                  0        1        0   100000000          0     0  50000         N
                ssi3_sfr              0        0        0   100000000          0     0  50000         N
                ssi3_pclk             0        0        0   100000000          0     0  50000         N
                ssi2_sfr              0        0        0   100000000          0     0  50000         N
                ssi2_pclk             0        0        0   100000000          0     0  50000         N
                ssi1_sfr              0        0        0   100000000          0     0  50000         N
                ssi1_pclk             0        0        0   100000000          0     0  50000         N
                ssi0_sfr              1        1        0   100000000          0     0  50000         Y
                ssi0_pclk             1        1        0   100000000          0     0  50000         Y
                wdt1_pclk             0        1        0   100000000          0     0  50000         N
                wdt0_pclk             0        1        0   100000000          0     0  50000         N
                poeg_d_clkp           0        0        0   100000000          0     0  50000         N
                poeg_c_clkp           0        0        0   100000000          0     0  50000         N
                poeg_b_clkp           0        0        0   100000000          0     0  50000         N
                poeg_a_clkp           0        0        0   100000000          0     0  50000         N
                gpt_pclk              0        0        0   100000000          0     0  50000         N
                mtu_x_mck             0        0        0   100000000          0     0  50000         N
                ostm2_pclk            1        2        0   100000000          0     0  50000         Y
                ostm1_pclk            1        2        0   100000000          0     0  50000         Y
                ostm0_pclk            0        0        0   100000000          0     0  50000         N
                P0_DIV2               0        0        0    50000000          0     0  50000         Y
       .pll2_533                      0        0        0   533333333          0     0  50000         Y
          .pll2_533_div2              0        0        0   266666666          0     0  50000         Y
             .div_dsi_lpclk           0        0        0    16666667          0     0  50000         Y
                M4                    0        0        0    16666667          0     0  50000         Y
                   dsi_lpclk          0        0        0    16666667          0     0  50000         N
    .pll1                             0        0        0  1200000000          0     0  50000         Y
       I                              0        0        0  1200000000          0     0  50000         Y
    .osc_div1000                      0        0        0       24000          0     0  50000         Y
    .osc                              1        3        0    24000000          0     0  50000         Y
       gpio                           1        2        0    24000000          0     0  50000         Y
       wdt1_clk                       0        1        0    24000000          0     0  50000         N
       wdt0_clk                       0        1        0    24000000          0     0  50000         N
 can-clk                              0        0        0           0          0     0  50000         Y
 audio2-clk                           0        0        0    12288000          0     0  50000         Y
 audio1-clk                           0        0        0    11289600          0     0  50000         Y
playback 48000 kHz sample

speaker-test 1.2.1

Playback device is hw:0,0
Stream parameters are 48000Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 8 to 8192
Period size range from 8 to 2048
Using max buffer size 8192
Periods = 4
was set period_size = 2048
was set buffer_size = 8192
 0 - Front Left
00: 80
01: 00
02: 11
03: 19
04: 4c
05: 02
06: 23
07: 7f
08: 83
09: 19
0a: 08
0b: a9
0c: 5f
0d: 25
0e: 24
0f: bf
10: 00
11: 14
12: 7a
13: e1
14: 00
15: 00
16: 00
17: 00
18: 01
19: 55
1a: 59
1b: bb
1c: 3f
1d: 30
1e: 90
1f: f6
20: 80
21: b0
22: 45
23: c4
24: 95
Read at address  0x10049C00 (0xffff9a615c00): 0x300B4022
       pfd2                           1        1        0    24000000          0     0  50000         Y
          pll2                        1        1        0   491519897          0     0  50000         Y
             div4_mux                 1        1        0   491519897          0     0  50000         Y
                div4                  1        1        0    12287998          0     0  50000         Y
                   se2_mux            1        1        0    12287998          0     0  50000         Y
                      se2             1        1        0    12287998          0     0  50000         Y
 1 - Front Right
playback 44100 kHz sample

speaker-test 1.2.1

Playback device is hw:0,0
Stream parameters are 44100Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 44100Hz (requested 44100Hz)
Buffer size range from 8 to 8192
Period size range from 8 to 2048
Using max buffer size 8192
Periods = 4
was set period_size = 2048
was set buffer_size = 8192
 0 - Front Left
/audio_test.sh: line 2:   187 Killed                  speaker-test -D hw:0,0 -c 2 -r $1
00: 80
01: 00
02: 11
03: 19
04: 4c
05: 02
06: 23
07: 7f
08: 83
09: 19
0a: 08
0b: a9
0c: 5f
0d: 25
0e: 24
0f: bf
10: 00
11: 14
12: 7a
13: e1
14: 00
15: 00
16: 00
17: 00
18: 01
19: 55
1a: 59
1b: bb
1c: 3f
1d: 30
1e: 90
1f: b6
20: 80
21: b0
22: 45
23: c4
24: 95
Read at address  0x10049C00 (0xffffb7957c00): 0x700B4022
    pfd3_mux                          1        1        0    24000000          0     0  50000         Y
       pfd3                           1        1        0      960000          0     0  50000         Y
          pll3                        1        1        0   564480000          0     0  50000         Y
             div5                     1        1        0    11289600          0     0  50000         Y
                se2_mux               1        1        0    11289600          0     0  50000         Y
                   se2                1        1        0    11289600          0     0  50000         Y

Biju Das (3):
  dt-bindings: clock: Add Renesas versa3 clock generator bindings
  drivers: clk: Add support for versa3 clock driver
  arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk

 .../bindings/clock/renesas,5p35023.yaml       |   86 ++
 .../boot/dts/renesas/rz-smarc-common.dtsi     |   13 +-
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  |   23 +
 arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi |   23 +
 arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi |   25 +
 drivers/clk/Kconfig                           |    9 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/clk-versaclock3.c                 | 1144 +++++++++++++++++
 8 files changed, 1317 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/renesas,5p35023.yaml
 create mode 100644 drivers/clk/clk-versaclock3.c


base-commit: d5b9392d664c6db52fd66e538f1145cfa927d8cc
-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v5 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings
  2023-04-13 15:26 [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
@ 2023-04-13 15:26 ` Biju Das
  2023-04-13 15:26 ` [PATCH v5 2/3] drivers: clk: Add support for versa3 clock driver Biju Das
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Biju Das @ 2023-04-13 15:26 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski
  Cc: Biju Das, Geert Uytterhoeven, linux-renesas-soc, linux-clk,
	devicetree, Prabhakar Mahadev Lad, Krzysztof Kozlowski

Document Renesas versa3 clock generator(5P35023) bindings.

The 5P35023 is a VersaClock programmable clock generator and
is designed for low-power, consumer, and high-performance PCI
Express applications. The 5P35023 device is a three PLL
architecture design, and each PLL is individually programmable
and allowing for up to 6 unique frequency outputs.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
v4->v5:
 * No change
v3->v4:
 * No change
v2->v3:
 * Added Rb tag from Krzysztof Kozlowski
 * Removed | from Link to data sheet.
 * Dropped stray blank line from example.
 * Updated example section for assigned-clocks to mach same alignment
   with assigned-clock-rates. This is trivial change so retained the
   Rb tag.
RFC->v2:
 * Renamed the filename to match with compatible
 * Added maintainers entry after title
 * Removed the wrapping for the link to data sheet.
 * Removed reg description
 * Removed clock names
 * Replaced minItems->maxItems in renesas,settings property
 * Dropped assigned-clocks, assigned-clock-rates
 * Dropped renesas,clock-divider-read-only and renesas,clock-flags
 * Drooped clock handle part from example
 * Dropped reg from example.
 * Dropped consumer example
---
 .../bindings/clock/renesas,5p35023.yaml       | 86 +++++++++++++++++++
 1 file changed, 86 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/renesas,5p35023.yaml

diff --git a/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml b/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml
new file mode 100644
index 000000000000..839648e753d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/renesas,5p35023.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas 5p35023 VersaClock 3 programmable I2C clock generator
+
+maintainers:
+  - Biju Das <biju.das.jz@bp.renesas.com>
+
+description: |
+  The 5P35023 is a VersaClock programmable clock generator and
+  is designed for low-power, consumer, and high-performance PCI
+  express applications. The 5P35023 device is a three PLL
+  architecture design, and each PLL is individually programmable
+  and allowing for up to 6 unique frequency outputs.
+
+  An internal OTP memory allows the user to store the configuration
+  in the device. After power up, the user can change the device register
+  settings through the I2C interface when I2C mode is selected.
+
+  The driver can read a full register map from the DT, and will use that
+  register map to initialize the attached part (via I2C) when the system
+  boots. Any configuration not supported by the common clock framework
+  must be done via the full register map, including optimized settings.
+
+  Link to datasheet:
+  https://www.renesas.com/us/en/products/clocks-timing/clock-generation/programmable-clocks/5p35023-versaclock-3s-programmable-clock-generator
+
+properties:
+  compatible:
+    enum:
+      - renesas,5p35023
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+  clocks:
+    maxItems: 1
+
+  renesas,settings:
+    description: Optional, complete register map of the device.
+      Optimized settings for the device must be provided in full
+      and are written during initialization.
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    maxItems: 37
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        versa3: clock-generator@68 {
+            compatible = "renesas,5p35023";
+            reg = <0x68>;
+            #clock-cells = <1>;
+
+            clocks = <&x1_x2>;
+
+            renesas,settings = [
+                80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+                00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+                80 b0 45 c4 95
+            ];
+
+            assigned-clocks = <&versa3 0>, <&versa3 1>,
+                              <&versa3 2>, <&versa3 3>,
+                              <&versa3 4>, <&versa3 5>;
+            assigned-clock-rates = <12288000>, <25000000>,
+                                   <12000000>, <11289600>,
+                                   <11289600>, <24000000>;
+        };
+    };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 2/3] drivers: clk: Add support for versa3 clock driver
  2023-04-13 15:26 [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
  2023-04-13 15:26 ` [PATCH v5 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings Biju Das
@ 2023-04-13 15:26 ` Biju Das
  2023-04-13 15:26 ` [PATCH v5 3/3] arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk Biju Das
  2023-05-02 14:18 ` [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
  3 siblings, 0 replies; 7+ messages in thread
From: Biju Das @ 2023-04-13 15:26 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: Biju Das, linux-clk, Geert Uytterhoeven, Prabhakar Mahadev Lad,
	linux-renesas-soc

Add support for Renesas versa3 clock driver(5p35023).
The clock generator provides 6 output clocks.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v4->v5:
 * Added missing .determine_rate() for muxes
 * Fixed smatch warning: replace divide condition 'req->best_parent_rate / req->rate'
   with 'req->best_parent_rate >= req->rate'  Reported-by: kernel test robot <lkp@intel.com>
   and Reported-by: Dan Carpenter <error27@gmail.com>
v3->v4:
 * Fixed the warning reported by  kernel test robot.
 * Added error check for devm_clk_hw_register_fixed_factor_* in probe().
v2->v3:
 * Updated copy right information.
 * Removed .name from parent data and started using index or struct clk_hw.
 * Dropped vc3_clk_out_ops  and started using fixed factor clocks for
   output clk.
 * Dropped vc3_divider_type_parse_dt function.
 * Dropped struct vc3_driver_data
RFC->v2:
 * Dropped header file <linux/clk.h> and removed all
   consumer api's
 * struct clk_parent_data used for assigning the parent names.
 * Replaced initpointer->const init pointer in vc3_clk_register
 * Replaced of_clk_add_hw_provider with devm_clk_add_hw_provider
 * Dropped vc3_remove() callback.
---
 drivers/clk/Kconfig           |    9 +
 drivers/clk/Makefile          |    1 +
 drivers/clk/clk-versaclock3.c | 1144 +++++++++++++++++++++++++++++++++
 3 files changed, 1154 insertions(+)
 create mode 100644 drivers/clk/clk-versaclock3.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 016814e15536..73f2ef11ffd5 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -385,6 +385,15 @@ config COMMON_CLK_SI521XX
 	  This driver supports the SkyWorks Si521xx PCIe clock generator
 	  models Si52144/Si52146/Si52147.
 
+config COMMON_CLK_VC3
+	tristate "Clock driver for Renesas VersaClock 3 devices"
+	depends on I2C
+	depends on OF
+	select REGMAP_I2C
+	help
+	  This driver supports the Renesas VersaClock 3 programmable clock
+	  generators.
+
 config COMMON_CLK_VC5
 	tristate "Clock driver for IDT VersaClock 5,6 devices"
 	depends on I2C
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 0aebef17edc6..ce1b05e73b6f 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_RS9_PCIE)	+= clk-renesas-pcie.o
 obj-$(CONFIG_COMMON_CLK_SI521XX)	+= clk-si521xx.o
+obj-$(CONFIG_COMMON_CLK_VC3)		+= clk-versaclock3.o
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_VC7)		+= clk-versaclock7.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c
new file mode 100644
index 000000000000..e89bfe4b8fd4
--- /dev/null
+++ b/drivers/clk/clk-versaclock3.c
@@ -0,0 +1,1144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Renesas Versaclock 3
+ *
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/i2c.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define NUM_CONFIG_REGISTERS		37
+
+#define VC3_GENERAL_CTR			0x0
+#define VC3_GENERAL_CTR_DIV1_SRC_SEL	BIT(3)
+#define VC3_GENERAL_CTR_PLL3_REFIN_SEL	BIT(2)
+
+#define VC3_PLL3_M_DIVIDER		0x3
+#define VC3_PLL3_M_DIV1			BIT(7)
+#define VC3_PLL3_M_DIV2			BIT(6)
+#define VC3_PLL3_M_DIV(n)		((n) & GENMASK(5, 0))
+
+#define VC3_PLL3_N_DIVIDER		0x4
+#define VC3_PLL3_LOOP_FILTER_N_DIV_MSB	0x5
+
+#define VC3_PLL3_CHARGE_PUMP_CTRL	0x6
+#define VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL	BIT(7)
+
+#define VC3_PLL1_CTRL_OUTDIV5		0x7
+#define VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER		BIT(7)
+
+#define VC3_PLL1_M_DIVIDER		0x8
+#define VC3_PLL1_M_DIV1			BIT(7)
+#define VC3_PLL1_M_DIV2			BIT(6)
+#define VC3_PLL1_M_DIV(n)		((n) & GENMASK(5, 0))
+
+#define VC3_PLL1_VCO_N_DIVIDER		0x9
+#define VC3_PLL1_LOOP_FILTER_N_DIV_MSB	0x0a
+
+#define VC3_OUT_DIV1_DIV2_CTRL		0xf
+
+#define VC3_PLL2_FB_INT_DIV_MSB		0x10
+#define VC3_PLL2_FB_INT_DIV_LSB		0x11
+#define VC3_PLL2_FB_FRC_DIV_MSB		0x12
+#define VC3_PLL2_FB_FRC_DIV_LSB		0x13
+
+#define VC3_PLL2_M_DIVIDER		0x1a
+#define VC3_PLL2_MDIV_DOUBLER		BIT(7)
+#define VC3_PLL2_M_DIV1			BIT(6)
+#define VC3_PLL2_M_DIV2			BIT(5)
+#define VC3_PLL2_M_DIV(n)		((n) & GENMASK(4, 0))
+
+#define VC3_OUT_DIV3_DIV4_CTRL		0x1b
+
+#define VC3_PLL_OP_CTRL			0x1c
+#define VC3_PLL_OP_CTRL_PLL2_REFIN_SEL	6
+
+#define VC3_OUTPUT_CTR			0x1d
+#define VC3_OUTPUT_CTR_DIV4_SRC_SEL	BIT(3)
+
+#define VC3_SE2_CTRL_REG0		0x1f
+#define VC3_SE2_CTRL_REG0_SE2_CLK_SEL	BIT(6)
+
+#define VC3_SE3_DIFF1_CTRL_REG		0x21
+#define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL	BIT(6)
+
+#define VC3_DIFF1_CTRL_REG		0x22
+#define VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL	BIT(7)
+
+#define VC3_DIFF2_CTRL_REG		0x23
+#define VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL	BIT(7)
+
+#define VC3_SE1_DIV4_CTRL		0x24
+#define VC3_SE1_DIV4_CTRL_SE1_CLK_SEL	BIT(3)
+
+#define VC3_PLL1_VCO_MIN		300000000UL
+#define VC3_PLL1_VCO_MAX		600000000UL
+
+#define VC3_PLL2_VCO_MIN		400000000UL
+#define VC3_PLL2_VCO_MAX		1200000000UL
+
+#define VC3_PLL3_VCO_MIN		300000000UL
+#define VC3_PLL3_VCO_MAX		800000000UL
+
+#define VC3_2_POW_16			(U16_MAX + 1)
+#define VC3_DIV_MASK(width)		((1 << (width)) - 1)
+
+enum vc3_pfd_mux {
+	VC3_PFD2_MUX,
+	VC3_PFD3_MUX,
+};
+
+enum vc3_pfd {
+	VC3_PFD1,
+	VC3_PFD2,
+	VC3_PFD3,
+};
+
+enum vc3_pll {
+	VC3_PLL1,
+	VC3_PLL2,
+	VC3_PLL3,
+};
+
+enum vc3_div_mux {
+	VC3_DIV1_MUX,
+	VC3_DIV3_MUX,
+	VC3_DIV4_MUX,
+};
+
+enum vc3_div {
+	VC3_DIV1,
+	VC3_DIV2,
+	VC3_DIV3,
+	VC3_DIV4,
+	VC3_DIV5,
+};
+
+enum vc3_clk_mux {
+	VC3_DIFF2_MUX,
+	VC3_DIFF1_MUX,
+	VC3_SE3_MUX,
+	VC3_SE2_MUX,
+	VC3_SE1_MUX,
+};
+
+enum vc3_clk {
+	VC3_DIFF2,
+	VC3_DIFF1,
+	VC3_SE3,
+	VC3_SE2,
+	VC3_SE1,
+	VC3_REF,
+};
+
+struct vc3_clk_data {
+	u8 offs;
+	u8 bitmsk;
+};
+
+struct vc3_pfd_data {
+	u8 num;
+	u8 offs;
+	u8 mdiv1_bitmsk;
+	u8 mdiv2_bitmsk;
+};
+
+struct vc3_pll_data {
+	u8 num;
+	u8 int_div_msb_offs;
+	u8 int_div_lsb_offs;
+	unsigned long vco_min;
+	unsigned long vco_max;
+};
+
+struct vc3_div_data {
+	u8 offs;
+	const struct clk_div_table *table;
+	u8 shift;
+	u8 width;
+	u8 flags;
+};
+
+struct vc3_hw_data {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	const void *data;
+
+	u32 div_int;
+	u32 div_frc;
+};
+
+static const struct clk_div_table div1_divs[] = {
+	{ .val = 0, .div = 1, }, { .val = 1, .div = 4, },
+	{ .val = 2, .div = 5, }, { .val = 3, .div = 6, },
+	{ .val = 4, .div = 2, }, { .val = 5, .div = 8, },
+	{ .val = 6, .div = 10, }, { .val = 7, .div = 12, },
+	{ .val = 8, .div = 4, }, { .val = 9, .div = 16, },
+	{ .val = 10, .div = 20, }, { .val = 11, .div = 24, },
+	{ .val = 12, .div = 8, }, { .val = 13, .div = 32, },
+	{ .val = 14, .div = 40, }, { .val = 15, .div = 48, },
+	{}
+};
+
+static const struct clk_div_table div245_divs[] = {
+	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },
+	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },
+	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },
+	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },
+	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },
+	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },
+	{ .val = 12, .div = 5, }, { .val = 13, .div = 15, },
+	{ .val = 14, .div = 25, }, { .val = 15, .div = 50, },
+	{}
+};
+
+static const struct clk_div_table div3_divs[] = {
+	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },
+	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },
+	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },
+	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },
+	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },
+	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },
+	{ .val = 12, .div = 8, }, { .val = 13, .div = 24, },
+	{ .val = 14, .div = 40, }, { .val = 15, .div = 80, },
+	{}
+};
+
+static struct clk_hw *clk_out[6];
+
+static unsigned char vc3_pfd_mux_get_parent(struct clk_hw *hw)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *pfd_mux = vc3->data;
+	u32 src;
+
+	regmap_read(vc3->regmap, pfd_mux->offs, &src);
+
+	return !!(src & pfd_mux->bitmsk);
+}
+
+static int vc3_pfd_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *pfd_mux = vc3->data;
+
+	regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk,
+			   index ? pfd_mux->bitmsk : 0);
+	return 0;
+}
+
+static const struct clk_ops vc3_pfd_mux_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = vc3_pfd_mux_set_parent,
+	.get_parent = vc3_pfd_mux_get_parent,
+};
+
+static unsigned long vc3_pfd_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pfd_data *pfd = vc3->data;
+	unsigned int prediv, premul;
+	unsigned long rate;
+	u8 mdiv;
+
+	regmap_read(vc3->regmap, pfd->offs, &prediv);
+	if (pfd->num == VC3_PFD1) {
+		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
+		if (prediv & pfd->mdiv1_bitmsk) {
+			/* check doubler is set or not */
+			regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul);
+			if (premul & VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER)
+				parent_rate *= 2;
+			return parent_rate;
+		}
+		mdiv = VC3_PLL1_M_DIV(prediv);
+	} else if (pfd->num == VC3_PFD2) {
+		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
+		if (prediv & pfd->mdiv1_bitmsk) {
+			regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul);
+			/* check doubler is set or not */
+			if (premul & VC3_PLL2_MDIV_DOUBLER)
+				parent_rate *= 2;
+			return parent_rate;
+		}
+
+		mdiv = VC3_PLL2_M_DIV(prediv);
+	} else {
+		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
+		if (prediv & pfd->mdiv1_bitmsk)
+			return parent_rate;
+
+		mdiv = VC3_PLL3_M_DIV(prediv);
+	}
+
+	if (prediv & pfd->mdiv2_bitmsk)
+		rate = parent_rate / 2;
+	else
+		rate = parent_rate / mdiv;
+
+	return rate;
+}
+
+static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pfd_data *pfd = vc3->data;
+	unsigned long idiv;
+
+	/* PLL cannot operate with input clock above 50 MHz. */
+	if (rate > 50000000)
+		return -EINVAL;
+
+	/* CLKIN within range of PLL input, feed directly to PLL. */
+	if (*parent_rate <= 50000000)
+		return *parent_rate;
+
+	idiv = DIV_ROUND_UP(*parent_rate, rate);
+	if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) {
+		if (idiv > 63)
+			return -EINVAL;
+	} else {
+		if (idiv > 31)
+			return -EINVAL;
+	}
+
+	return *parent_rate / idiv;
+}
+
+static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pfd_data *pfd = vc3->data;
+	unsigned long idiv;
+	u8 div;
+
+	/* CLKIN within range of PLL input, feed directly to PLL. */
+	if (parent_rate <= 50000000) {
+		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk,
+				   pfd->mdiv1_bitmsk);
+		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0);
+		return 0;
+	}
+
+	idiv = DIV_ROUND_UP(parent_rate, rate);
+	/* We have dedicated div-2 predivider. */
+	if (idiv == 2) {
+		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk,
+				   pfd->mdiv2_bitmsk);
+		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0);
+	} else {
+		if (pfd->num == VC3_PFD1)
+			div = VC3_PLL1_M_DIV(idiv);
+		else if (pfd->num == VC3_PFD2)
+			div = VC3_PLL2_M_DIV(idiv);
+		else
+			div = VC3_PLL3_M_DIV(idiv);
+
+		regmap_write(vc3->regmap, pfd->offs, div);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops vc3_pfd_ops = {
+	.recalc_rate = vc3_pfd_recalc_rate,
+	.round_rate = vc3_pfd_round_rate,
+	.set_rate = vc3_pfd_set_rate,
+};
+
+static unsigned long vc3_pll_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pll_data *pll = vc3->data;
+	u32 div_int, div_frc, val;
+	unsigned long rate;
+
+	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);
+	div_int = (val & GENMASK(2, 0)) << 8;
+	regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val);
+	div_int |= val;
+
+	if (pll->num == VC3_PLL2) {
+		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val);
+		div_frc = val << 8;
+		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val);
+		div_frc |= val;
+		rate = (parent_rate *
+			(div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16);
+	} else {
+		rate = parent_rate * div_int;
+	}
+
+	return rate;
+}
+
+static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pll_data *pll = vc3->data;
+	u64 div_frc;
+
+	if (rate < pll->vco_min)
+		rate = pll->vco_min;
+	if (rate > pll->vco_max)
+		rate = pll->vco_max;
+
+	vc3->div_int = rate / *parent_rate;
+
+	if (pll->num == VC3_PLL2) {
+		if (vc3->div_int > 0x7ff)
+			rate = *parent_rate * 0x7ff;
+
+		/* Determine best fractional part, which is 16 bit wide */
+		div_frc = rate % *parent_rate;
+		div_frc *= BIT(16) - 1;
+		do_div(div_frc, *parent_rate);
+
+		vc3->div_frc = (u32)div_frc;
+		rate = (*parent_rate *
+			(vc3->div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16);
+	} else {
+		rate = *parent_rate * vc3->div_int;
+	}
+
+	return rate;
+}
+
+static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_pll_data *pll = vc3->data;
+	u32 val;
+
+	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);
+	val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7);
+	regmap_write(vc3->regmap, pll->int_div_msb_offs, val);
+	regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff);
+
+	if (pll->num == VC3_PLL2) {
+		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB,
+			     vc3->div_frc >> 8);
+		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB,
+			     vc3->div_frc & 0xff);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops vc3_pll_ops = {
+	.recalc_rate = vc3_pll_recalc_rate,
+	.round_rate = vc3_pll_round_rate,
+	.set_rate = vc3_pll_set_rate,
+};
+
+static unsigned char vc3_div_mux_get_parent(struct clk_hw *hw)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *div_mux = vc3->data;
+	u32 src;
+
+	regmap_read(vc3->regmap, div_mux->offs, &src);
+
+	return !!(src & div_mux->bitmsk);
+}
+
+static int vc3_div_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *div_mux = vc3->data;
+
+	regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk,
+			   index ? div_mux->bitmsk : 0);
+
+	return 0;
+}
+
+static const struct clk_ops vc3_div_mux_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = vc3_div_mux_set_parent,
+	.get_parent = vc3_div_mux_get_parent,
+};
+
+static unsigned int vc3_get_div(const struct clk_div_table *table,
+				unsigned int val, unsigned long flag)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+
+	return 0;
+}
+
+static unsigned long vc3_div_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_div_data *div_data = vc3->data;
+	unsigned int val;
+
+	regmap_read(vc3->regmap, div_data->offs, &val);
+	val >>= div_data->shift;
+	val &= VC3_DIV_MASK(div_data->width);
+
+	return divider_recalc_rate(hw, parent_rate, val, div_data->table,
+				   div_data->flags, div_data->width);
+}
+
+static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_div_data *div_data = vc3->data;
+	unsigned int bestdiv;
+
+	/* if read only, just return current value */
+	if (div_data->flags & CLK_DIVIDER_READ_ONLY) {
+		regmap_read(vc3->regmap, div_data->offs, &bestdiv);
+		bestdiv >>= div_data->shift;
+		bestdiv &= VC3_DIV_MASK(div_data->width);
+		bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags);
+		return DIV_ROUND_UP(*parent_rate, bestdiv);
+	}
+
+	return divider_round_rate(hw, rate, parent_rate, div_data->table,
+				  div_data->width, div_data->flags);
+}
+
+static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_div_data *div_data = vc3->data;
+	unsigned int value;
+
+	value = divider_get_val(rate, parent_rate, div_data->table,
+				div_data->width, div_data->flags);
+	regmap_update_bits(vc3->regmap, div_data->offs,
+			   VC3_DIV_MASK(div_data->width) << div_data->shift,
+			   value << div_data->shift);
+	return 0;
+}
+
+static const struct clk_ops vc3_div_ops = {
+	.recalc_rate = vc3_div_recalc_rate,
+	.round_rate = vc3_div_round_rate,
+	.set_rate = vc3_div_set_rate,
+};
+
+static int vc3_clk_mux_determine_rate(struct clk_hw *hw,
+				      struct clk_rate_request *req)
+{
+	int ret;
+	int frc;
+
+	ret = clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT);
+	if (ret) {
+		/* The below check is equivalent to (best_parent_rate/rate) */
+		if (req->best_parent_rate >= req->rate) {
+			frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate,
+						    req->rate);
+			req->rate *= frc;
+			return clk_mux_determine_rate_flags(hw, req,
+							    CLK_SET_RATE_PARENT);
+		}
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static unsigned char vc3_clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *clk_mux = vc3->data;
+	u32 val;
+
+	regmap_read(vc3->regmap, clk_mux->offs, &val);
+
+	return !!(val & clk_mux->bitmsk);
+}
+
+static int vc3_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
+	const struct vc3_clk_data *clk_mux = vc3->data;
+
+	regmap_update_bits(vc3->regmap, clk_mux->offs,
+			   clk_mux->bitmsk, index ? clk_mux->bitmsk : 0);
+	return 0;
+}
+
+static const struct clk_ops vc3_clk_mux_ops = {
+	.determine_rate = vc3_clk_mux_determine_rate,
+	.set_parent = vc3_clk_mux_set_parent,
+	.get_parent = vc3_clk_mux_get_parent,
+};
+
+static bool vc3_regmap_is_writeable(struct device *dev, unsigned int reg)
+{
+	return true;
+}
+
+static const struct regmap_config vc3_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 0x24,
+	.writeable_reg = vc3_regmap_is_writeable,
+};
+
+static struct vc3_hw_data clk_div[5];
+
+static const struct clk_parent_data pfd_mux_parent_data[] = {
+	{ .index = 0, },
+	{ .hw = &clk_div[VC3_DIV2].hw }
+};
+
+static struct vc3_hw_data clk_pfd_mux[] = {
+	[VC3_PFD2_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_PLL_OP_CTRL,
+			.bitmsk = BIT(VC3_PLL_OP_CTRL_PLL2_REFIN_SEL)
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pfd2_mux",
+			.ops = &vc3_pfd_mux_ops,
+			.parent_data = pfd_mux_parent_data,
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+		}
+	},
+	[VC3_PFD3_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_GENERAL_CTR,
+			.bitmsk = BIT(VC3_GENERAL_CTR_PLL3_REFIN_SEL)
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pfd3_mux",
+			.ops = &vc3_pfd_mux_ops,
+			.parent_data = pfd_mux_parent_data,
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+		}
+	}
+};
+
+static struct vc3_hw_data clk_pfd[] = {
+	[VC3_PFD1] = {
+		.data = &(struct vc3_pfd_data) {
+			.num = VC3_PFD1,
+			.offs = VC3_PLL1_M_DIVIDER,
+			.mdiv1_bitmsk = VC3_PLL1_M_DIV1,
+			.mdiv2_bitmsk = VC3_PLL1_M_DIV2
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pfd1",
+			.ops = &vc3_pfd_ops,
+			.parent_data = &(const struct clk_parent_data) {
+				.index = 0
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_PFD2] = {
+		.data = &(struct vc3_pfd_data) {
+			.num = VC3_PFD2,
+			.offs = VC3_PLL2_M_DIVIDER,
+			.mdiv1_bitmsk = VC3_PLL2_M_DIV1,
+			.mdiv2_bitmsk = VC3_PLL2_M_DIV2
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pfd2",
+			.ops = &vc3_pfd_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pfd_mux[VC3_PFD2_MUX].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_PFD3] = {
+		.data = &(struct vc3_pfd_data) {
+			.num = VC3_PFD3,
+			.offs = VC3_PLL3_M_DIVIDER,
+			.mdiv1_bitmsk = VC3_PLL3_M_DIV1,
+			.mdiv2_bitmsk = VC3_PLL3_M_DIV2
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pfd3",
+			.ops = &vc3_pfd_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pfd_mux[VC3_PFD3_MUX].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	}
+};
+
+static struct vc3_hw_data clk_pll[] = {
+	[VC3_PLL1] = {
+		.data = &(struct vc3_pll_data) {
+			.num = VC3_PLL1,
+			.int_div_msb_offs = VC3_PLL1_LOOP_FILTER_N_DIV_MSB,
+			.int_div_lsb_offs = VC3_PLL1_VCO_N_DIVIDER,
+			.vco_min = VC3_PLL1_VCO_MIN,
+			.vco_max = VC3_PLL1_VCO_MAX
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pll1",
+			.ops = &vc3_pll_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pfd[VC3_PFD1].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_PLL2] = {
+		.data = &(struct vc3_pll_data) {
+			.num = VC3_PLL2,
+			.int_div_msb_offs = VC3_PLL2_FB_INT_DIV_MSB,
+			.int_div_lsb_offs = VC3_PLL2_FB_INT_DIV_LSB,
+			.vco_min = VC3_PLL2_VCO_MIN,
+			.vco_max = VC3_PLL2_VCO_MAX
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pll2",
+			.ops = &vc3_pll_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pfd[VC3_PFD2].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_PLL3] = {
+		.data = &(struct vc3_pll_data) {
+			.num = VC3_PLL3,
+			.int_div_msb_offs = VC3_PLL3_LOOP_FILTER_N_DIV_MSB,
+			.int_div_lsb_offs = VC3_PLL3_N_DIVIDER,
+			.vco_min = VC3_PLL3_VCO_MIN,
+			.vco_max = VC3_PLL3_VCO_MAX
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "pll3",
+			.ops = &vc3_pll_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pfd[VC3_PFD3].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	}
+};
+
+static const struct clk_parent_data div_mux_parent_data[][2] = {
+	[VC3_DIV1_MUX] = {
+		{ .hw = &clk_pll[VC3_PLL1].hw },
+		{ .index = 0 }
+	},
+	[VC3_DIV3_MUX] = {
+		{ .hw = &clk_pll[VC3_PLL2].hw },
+		{ .hw = &clk_pll[VC3_PLL3].hw }
+	},
+	[VC3_DIV4_MUX] = {
+		{ .hw = &clk_pll[VC3_PLL2].hw },
+		{ .index = 0 }
+	}
+};
+
+static struct vc3_hw_data clk_div_mux[] = {
+	[VC3_DIV1_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_GENERAL_CTR,
+			.bitmsk = VC3_GENERAL_CTR_DIV1_SRC_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div1_mux",
+			.ops = &vc3_div_mux_ops,
+			.parent_data = div_mux_parent_data[VC3_DIV1_MUX],
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+		}
+	},
+	[VC3_DIV3_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_PLL3_CHARGE_PUMP_CTRL,
+			.bitmsk = VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div3_mux",
+			.ops = &vc3_div_mux_ops,
+			.parent_data = div_mux_parent_data[VC3_DIV3_MUX],
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+		}
+	},
+	[VC3_DIV4_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_OUTPUT_CTR,
+			.bitmsk = VC3_OUTPUT_CTR_DIV4_SRC_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div4_mux",
+			.ops = &vc3_div_mux_ops,
+			.parent_data = div_mux_parent_data[VC3_DIV4_MUX],
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+		}
+	}
+};
+
+static struct vc3_hw_data clk_div[] = {
+	[VC3_DIV1] = {
+		.data = &(struct vc3_div_data) {
+			.offs = VC3_OUT_DIV1_DIV2_CTRL,
+			.table = div1_divs,
+			.shift = 4,
+			.width = 4,
+			.flags = CLK_DIVIDER_READ_ONLY
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div1",
+			.ops = &vc3_div_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div_mux[VC3_DIV1_MUX].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_DIV2] = {
+		.data = &(struct vc3_div_data) {
+			.offs = VC3_OUT_DIV1_DIV2_CTRL,
+			.table = div245_divs,
+			.shift = 0,
+			.width = 4,
+			.flags = CLK_DIVIDER_READ_ONLY
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div2",
+			.ops = &vc3_div_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pll[VC3_PLL1].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_DIV3] = {
+		.data = &(struct vc3_div_data) {
+			.offs = VC3_OUT_DIV3_DIV4_CTRL,
+			.table = div3_divs,
+			.shift = 4,
+			.width = 4,
+			.flags = CLK_DIVIDER_READ_ONLY
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div3",
+			.ops = &vc3_div_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div_mux[VC3_DIV3_MUX].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_DIV4] = {
+		.data = &(struct vc3_div_data) {
+			.offs = VC3_OUT_DIV3_DIV4_CTRL,
+			.table = div245_divs,
+			.shift = 0,
+			.width = 4,
+			.flags = CLK_DIVIDER_READ_ONLY
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div4",
+			.ops = &vc3_div_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div_mux[VC3_DIV4_MUX].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_DIV5] = {
+		.data = &(struct vc3_div_data) {
+			.offs = VC3_PLL1_CTRL_OUTDIV5,
+			.table = div245_divs,
+			.shift = 0,
+			.width = 4,
+			.flags = CLK_DIVIDER_READ_ONLY
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "div5",
+			.ops = &vc3_div_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_pll[VC3_PLL3].hw
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	}
+};
+
+static struct vc3_hw_data clk_mux[] = {
+	[VC3_DIFF2_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_DIFF2_CTRL_REG,
+			.bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "diff2_mux",
+			.ops = &vc3_clk_mux_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div[VC3_DIV1].hw,
+				&clk_div[VC3_DIV3].hw
+			},
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_DIFF1_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_DIFF1_CTRL_REG,
+			.bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "diff1_mux",
+			.ops = &vc3_clk_mux_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div[VC3_DIV1].hw,
+				&clk_div[VC3_DIV3].hw
+			},
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_SE3_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_SE3_DIFF1_CTRL_REG,
+			.bitmsk = VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "se3_mux",
+			.ops = &vc3_clk_mux_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div[VC3_DIV2].hw,
+				&clk_div[VC3_DIV4].hw
+			},
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_SE2_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_SE2_CTRL_REG0,
+			.bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "se2_mux",
+			.ops = &vc3_clk_mux_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div[VC3_DIV5].hw,
+				&clk_div[VC3_DIV4].hw
+			},
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	},
+	[VC3_SE1_MUX] = {
+		.data = &(struct vc3_clk_data) {
+			.offs = VC3_SE1_DIV4_CTRL,
+			.bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL
+		},
+		.hw.init = &(struct clk_init_data){
+			.name = "se1_mux",
+			.ops = &vc3_clk_mux_ops,
+			.parent_hws = (const struct clk_hw *[]) {
+				&clk_div[VC3_DIV5].hw,
+				&clk_div[VC3_DIV4].hw
+			},
+			.num_parents = 2,
+			.flags = CLK_SET_RATE_PARENT
+		}
+	}
+};
+
+static struct clk_hw *vc3_of_clk_get(struct of_phandle_args *clkspec,
+				     void *data)
+{
+	unsigned int idx = clkspec->args[0];
+	struct clk_hw **clkout_hw = data;
+
+	if (idx >= ARRAY_SIZE(clk_out)) {
+		pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return clkout_hw[idx];
+}
+
+static int vc3_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	u8 settings[NUM_CONFIG_REGISTERS];
+	struct regmap *regmap;
+	const char *name;
+	int ret, i;
+
+	regmap = devm_regmap_init_i2c(client, &vc3_regmap_config);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "failed to allocate register map\n");
+
+	ret = of_property_read_u8_array(dev->of_node, "renesas,settings",
+					settings, ARRAY_SIZE(settings));
+	if (!ret) {
+		/*
+		 * A raw settings array was specified in the DT. Write the
+		 * settings to the device immediately.
+		 */
+		for  (i = 0; i < NUM_CONFIG_REGISTERS; i++) {
+			ret = regmap_write(regmap, i, settings[i]);
+			if (ret) {
+				dev_err(dev, "error writing to chip (%i)\n", ret);
+				return ret;
+			}
+		}
+	} else if (ret == -EOVERFLOW) {
+		dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu",
+			ARRAY_SIZE(settings));
+		return ret;
+	}
+
+	/* Register pfd muxes */
+	for (i = 0; i < ARRAY_SIZE(clk_pfd_mux); i++) {
+		clk_pfd_mux[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_pfd_mux[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_pfd_mux[i].hw.init->name);
+	}
+
+	/* Register pfd's */
+	for (i = 0; i < ARRAY_SIZE(clk_pfd); i++) {
+		clk_pfd[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_pfd[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_pfd[i].hw.init->name);
+	}
+
+	/* Register pll's */
+	for (i = 0; i < ARRAY_SIZE(clk_pll); i++) {
+		clk_pll[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_pll[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_pll[i].hw.init->name);
+	}
+
+	/* Register divider muxes */
+	for (i = 0; i < ARRAY_SIZE(clk_div_mux); i++) {
+		clk_div_mux[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_div_mux[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_div_mux[i].hw.init->name);
+	}
+
+	/* Register dividers */
+	for (i = 0; i < ARRAY_SIZE(clk_div); i++) {
+		clk_div[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_div[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_div[i].hw.init->name);
+	}
+
+	/* Register clk muxes */
+	for (i = 0; i < ARRAY_SIZE(clk_mux); i++) {
+		clk_mux[i].regmap = regmap;
+		ret = devm_clk_hw_register(dev, &clk_mux[i].hw);
+		if (ret)
+			return dev_err_probe(dev, ret, "%s failed\n",
+					     clk_mux[i].hw.init->name);
+	}
+
+	/* Register clk outputs */
+	for (i = 0; i < ARRAY_SIZE(clk_out); i++) {
+		switch (i) {
+		case VC3_DIFF2:
+			name = "diff2";
+			break;
+		case VC3_DIFF1:
+			name = "diff1";
+			break;
+		case VC3_SE3:
+			name = "se3";
+			break;
+		case VC3_SE2:
+			name = "se2";
+			break;
+		case VC3_SE1:
+			name = "se1";
+			break;
+		case VC3_REF:
+			name = "ref";
+			break;
+		default:
+			pr_err("invalid clk output %d\n", i);
+			return -EINVAL;
+		}
+
+		if (i == VC3_REF)
+			clk_out[i] = devm_clk_hw_register_fixed_factor_index(dev,
+				name, 0, CLK_SET_RATE_PARENT, 1, 1);
+		else
+			clk_out[i] = devm_clk_hw_register_fixed_factor_parent_hw(dev,
+				name, &clk_mux[i].hw, CLK_SET_RATE_PARENT, 1, 1);
+
+		if (IS_ERR(clk_out[i]))
+			return PTR_ERR(clk_out[i]);
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, vc3_of_clk_get, clk_out);
+	if (ret)
+		return dev_err_probe(dev, ret, "unable to add clk provider\n");
+
+	return ret;
+}
+
+static const struct of_device_id dev_ids[] = {
+	{ .compatible = "renesas,5p35023" },
+	{ /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dev_ids);
+
+static struct i2c_driver vc3_driver = {
+	.driver = {
+		.name = "vc3",
+		.of_match_table = of_match_ptr(dev_ids),
+	},
+	.probe_new = vc3_probe,
+};
+module_i2c_driver(vc3_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas VersaClock 3 driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v5 3/3] arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk
  2023-04-13 15:26 [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
  2023-04-13 15:26 ` [PATCH v5 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings Biju Das
  2023-04-13 15:26 ` [PATCH v5 2/3] drivers: clk: Add support for versa3 clock driver Biju Das
@ 2023-04-13 15:26 ` Biju Das
  2023-05-02 14:18 ` [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
  3 siblings, 0 replies; 7+ messages in thread
From: Biju Das @ 2023-04-13 15:26 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski
  Cc: Biju Das, Geert Uytterhoeven, Magnus Damm, linux-renesas-soc,
	devicetree, Prabhakar Mahadev Lad

Currently audio mclk uses a fixed clk 11.2896MHz(multiple of 44.1KHz).
Replace this fixed clk to programmable versa3 clk that can provide
2 rates 11.2896MHz and 12.2880(multiple of 48KHz) based on audio
sampling rate for the playback/record.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v4->v5:
 * No change.
v3->v4:
 * No change.
v2->v3:
 * Updated the changes for RZ/G2LC and RZ/G2{UL, Five}.
RFC->v2:
 * No change
RFC:
 * New patch
---
 .../boot/dts/renesas/rz-smarc-common.dtsi     | 13 +++++-----
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  | 23 +++++++++++++++++
 arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi | 23 +++++++++++++++++
 arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi | 25 +++++++++++++++++++
 4 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
index 3962d47b3e59..ca868af2db38 100644
--- a/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/rz-smarc-common.dtsi
@@ -32,12 +32,6 @@ chosen {
 		stdout-path = "serial0:115200n8";
 	};
 
-	audio_mclock: audio_mclock {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <11289600>;
-	};
-
 	snd_rzg2l: sound {
 		compatible = "simple-audio-card";
 		simple-audio-card,format = "i2s";
@@ -55,7 +49,6 @@ cpu_dai: simple-audio-card,cpu {
 		};
 
 		codec_dai: simple-audio-card,codec {
-			clocks = <&audio_mclock>;
 			sound-dai = <&wm8978>;
 		};
 	};
@@ -76,6 +69,12 @@ vccq_sdhi1: regulator-vccq-sdhi1 {
 		gpios-states = <1>;
 		states = <3300000 1>, <1800000 0>;
 	};
+
+	x1_x2: xtal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
 };
 
 &audio_clk1{
diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index e180a955b6ac..9fb3cd07faa3 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -18,6 +18,10 @@ aliases {
 	};
 };
 
+&codec_dai {
+	clocks = <&versa3 3>;
+};
+
 &cpu_dai {
 	sound-dai = <&ssi0>;
 };
@@ -29,6 +33,25 @@ &i2c3 {
 
 	status = "okay";
 
+	versa3: versa3@68 {
+		compatible = "renesas,5p35023";
+		reg = <0x68>;
+		#clock-cells = <1>;
+		clocks = <&x1_x2>;
+
+		renesas,settings = [
+			80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+			00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+			80 b0 45 c4 95
+		];
+		assigned-clocks = <&versa3 0>, <&versa3 1>,
+				  <&versa3 2>, <&versa3 3>,
+				  <&versa3 4>, <&versa3 5>;
+		assigned-clock-rates = <12288000>, <25000000>,
+				       <12000000>, <11289600>,
+				       <11289600>, <24000000>;
+	};
+
 	wm8978: codec@1a {
 		compatible = "wlf,wm8978";
 		#sound-dai-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
index b6bd27196d88..ba91b2e653bc 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
@@ -32,6 +32,10 @@ &canfd {
 };
 #endif
 
+&codec_dai {
+	clocks = <&versa3 3>;
+};
+
 &cpu_dai {
 	sound-dai = <&ssi0>;
 };
@@ -43,6 +47,25 @@ &i2c2 {
 
 	status = "okay";
 
+	versa3: versa3@68 {
+		compatible = "renesas,5p35023";
+		reg = <0x68>;
+		#clock-cells = <1>;
+		clocks = <&x1_x2>;
+
+		renesas,settings = [
+			80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+			00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+			80 b0 45 c4 95
+		];
+		assigned-clocks = <&versa3 0>, <&versa3 1>,
+				  <&versa3 2>, <&versa3 3>,
+				  <&versa3 4>, <&versa3 5>;
+		assigned-clock-rates = <12288000>, <25000000>,
+				       <12000000>, <11289600>,
+				       <11289600>, <24000000>;
+	};
+
 	wm8978: codec@1a {
 		compatible = "wlf,wm8978";
 		#sound-dai-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
index 2a1331ed1a5c..85383f86cf2e 100644
--- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi
@@ -16,10 +16,35 @@ &canfd {
 };
 #endif
 
+&codec_dai {
+	clocks = <&versa3 3>;
+};
+
 &cpu_dai {
 	sound-dai = <&ssi1>;
 };
 
+&i2c0 {
+	versa3: versa3@68 {
+		compatible = "renesas,5p35023";
+		reg = <0x68>;
+		#clock-cells = <1>;
+		clocks = <&x1_x2>;
+
+		renesas,settings = [
+			80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf
+			00 14 7a e1 00 00 00 00 01 55 59 bb 3f 30 90 b6
+			80 b0 45 c4 95
+		];
+		assigned-clocks = <&versa3 0>, <&versa3 1>,
+				  <&versa3 2>, <&versa3 3>,
+				  <&versa3 4>, <&versa3 5>;
+		assigned-clock-rates = <12288000>, <25000000>,
+				       <12000000>, <11289600>,
+				       <11289600>, <24000000>;
+	};
+};
+
 &i2c1 {
 	wm8978: codec@1a {
 		compatible = "wlf,wm8978";
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH v5 0/3] Add Versa3 clock generator support
  2023-04-13 15:26 [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
                   ` (2 preceding siblings ...)
  2023-04-13 15:26 ` [PATCH v5 3/3] arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk Biju Das
@ 2023-05-02 14:18 ` Biju Das
  2023-05-02 20:24   ` Krzysztof Kozlowski
  3 siblings, 1 reply; 7+ messages in thread
From: Biju Das @ 2023-05-02 14:18 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-clk, devicetree,
	Prabhakar Mahadev Lad

Hi All,

Gentle Ping.

Cheers,
Biju

> -----Original Message-----
> From: Biju Das <biju.das.jz@bp.renesas.com>
> Sent: Thursday, April 13, 2023 4:27 PM
> To: Michael Turquette <mturquette@baylibre.com>; Stephen Boyd
> <sboyd@kernel.org>; Rob Herring <robh+dt@kernel.org>; Krzysztof Kozlowski
> <krzysztof.kozlowski+dt@linaro.org>
> Cc: Biju Das <biju.das.jz@bp.renesas.com>; Geert Uytterhoeven
> <geert+renesas@glider.be>; linux-renesas-soc@vger.kernel.org; linux-
> clk@vger.kernel.org; devicetree@vger.kernel.org; Prabhakar Mahadev Lad
> <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Subject: [PATCH v5 0/3] Add Versa3 clock generator support
> 
> The 5P35023 is a VersaClock programmable clock generator and it provides 6
> clk outputs {diff2, diff1, se3, se2, se1 and refin}.
> 
> It has an internal OTP memory allows the user to store the configuration in
> the device. After power up, the user can change the device register settings
> through the I2C interface when I2C mode is selected.
> 
> This driver is for overriding OTP default values during boot based on a full
> register map from DT, and also minimal support to change the parent of a
> output clock.
> 
> The motivation for developing this driver is for supporting 48KHz
> playback/record with audio codec on RZ/G2L SMARC EVK.
> 
> On RZ/G2L SMARC EVK, By default audio mclk is connected to
> 11.2896 MHz clk which is multiple of 44.1KHz.
> 
> Please see the below default OTP configuration of Dividers connected to
> output clocks.
> 
> DIV3 12.2880 MHz   DIFF2--> Audio clk2
> DIV5 11.2896 MHz   SE1  --> Audio clk1
> DIV5 11.2896 MHz   SE2  --> Audio mck
> DIV4 12      MHz   SE3  --> This clk Not used
> DIV1 25 MHz        DIFF1-->Ethernet clk
> Ref1-> 24MHz
> 
> With this setup, we won't be able to do 48KHz playback/record on audio
> codec, as mck is always connected to 11.2896MHz clk.
> 
> But by programming the i2c, we can make use of DIV4 to generate 12.2880 MHz
> and make that as parent of SE2 and there by supporting 48KHz
> playback/record.
> 
> A block diagram with modification can be find here[1]
> 
> DIV3 12.2880 MHz   DIFF2--> Audio clk2
> DIV5 11.2896 MHz   SE1  --> Audio clk1
> DIV5 11.2896 MHz | SE2  --> Audio mck
> DIV4 12.2880 MHz |
> DIV2 12      MHz   SE3  --> This clk Not used
> DIV1 25 MHz        DIFF1--> Ethernet clk
> Ref1-> 24MHz
> 
> The driver can read a full register map from the DT, and will use that
> register map to initialize the clk generator when the system boots.
> and later, based on sampling rate, it switches the parent of SE2 and support
> both 44.1 and 48 KHz playback/record at run time.
> 
> v4->v5:
>  * Added missing .determine_rate() for muxes
>  * Fixed smatch warning: replace divide condition 'req->best_parent_rate /
> req->rate'
>    with 'req->best_parent_rate >= req->rate'  Reported-by: kernel test robot
> <lkp@intel.com>
>    and Reported-by: Dan Carpenter <error27@gmail.com>
> v3->v4:
>  * Fixed the warning reported by  kernel test robot.
>  * Added error check for devm_clk_hw_register_fixed_factor_* in probe().
> v2->v3:
>  * Added Rb tag from Krzysztof Kozlowski
>  * Removed | from Link to data sheet.
>  * Dropped stray blank line from example.
>  * Updated example section for assigned-clocks to mach same alignment
>    with assigned-clock-rates. This is trivial change so retained the
>    Rb tag.
>  * Updated copy right information.
>  * Removed .name from parent data and started using index or struct clk_hw.
>  * Dropped vc3_clk_out_ops  and started using fixed factor clocks for
>    output clk.
>  * Dropped vc3_divider_type_parse_dt function.
>  * Dropped struct vc3_driver_data
>  * Updated the dtsi changes for RZ/G2LC and RZ/G2{UL, Five}.
> RFC->v2:
>  * Renamed the filename to match with compatible
>  * Added maintainers entry after title
>  * Removed the wrapping for the link to data sheet.
>  * Removed reg description
>  * Removed clock names
>  * Replaced minItems->maxItems in renesas,settings property
>  * Dropped assigned-clocks, assigned-clock-rates
>  * Dropped renesas,clock-divider-read-only and renesas,clock-flags
>  * Drooped clock handle part from example
>  * Dropped reg from example.
>  * Dropped consumer example
>  * Dropped header file <linux/clk.h> and removed all
>    consumer api's
>  * struct clk_parent_data used for assigning the parent names.
>  * Replaced initpointer->const init pointer in vc3_clk_register
>  * Replaced of_clk_add_hw_provider with devm_clk_add_hw_provider
>  * Dropped vc3_remove() callback.
> 
> Logs:
> root@smarc-rzg2l:~# /audio_test.sh
>                                  enable  prepare  protect
> duty  hardware
>    clock                          count    count    count        rate
> accuracy phase  cycle    enable
> ----------------------------------------------------------------------------
> ---------------------------
>  xtal                                 0        0        0    24000000
> 0     0  50000         Y
>     ref                               0        0        0    24000000
> 0     0  50000         Y
>     pfd1                              0        0        0    24000000
> 0     0  50000         Y
>        pll1                           0        0        0   600000000
> 0     0  50000         Y
>           div2                        0        0        0    12000000
> 0     0  50000         Y
>              se3_mux                  0        0        0    12000000
> 0     0  50000         Y
>                 se3                   0        0        0    12000000
> 0     0  50000         Y
>           div1_mux                    0        0        0   600000000
> 0     0  50000         Y
>              div1                     0        0        0    25000000
> 0     0  50000         Y
>                 diff1_mux             0        0        0    25000000
> 0     0  50000         Y
>                    diff1              0        0        0    25000000
> 0     0  50000         Y
>     pfd3_mux                          0        0        0    24000000
> 0     0  50000         Y
>        pfd3                           0        0        0      960000
> 0     0  50000         Y
>           pll3                        0        0        0   564480000
> 0     0  50000         Y
>              div5                     0        0        0    11289600
> 0     0  50000         Y
>                 se1_mux               0        0        0    11289600
> 0     0  50000         Y
>                    se1                0        0        0    11289600
> 0     0  50000         Y
>                 se2_mux               0        0        0    11289600
> 0     0  50000         Y
>                    se2                0        0        0    11289600
> 0     0  50000         Y
>     pfd2_mux                          0        0        0    24000000
> 0     0  50000         Y
>        pfd2                           0        0        0    24000000
> 0     0  50000         Y
>           pll2                        0        0        0   491519897
> 0     0  50000         Y
>              div4_mux                 0        0        0   491519897
> 0     0  50000         Y
>                 div4                  0        0        0    12287998
> 0     0  50000         Y
>              div3_mux                 0        0        0   491519897
> 0     0  50000         Y
>                 div3                  0        0        0    12287998
> 0     0  50000         Y
>                    diff2_mux          0        0        0    12287998
> 0     0  50000         Y
>                       diff2           0        0        0    12287998
> 0     0  50000         Y
>  extal-clk                            4        4        0    24000000
> 0     0  50000         Y
>     .pll5_foutpostdiv                 0        0        0    24000000
> 0     0  50000         Y
>        M1                             0        0        0    24000000
> 0     0  50000         Y
>           dsi_pll_clk                 0        0        0    24000000
> 0     0  50000         N
>        .sel_pll5_4                    0        0        0    24000000
> 0     0  50000         Y
>           DSI_DIV                     0        0        0    24000000
> 0     0  50000         Y
>              M3                       0        0        0    24000000
> 0     0  50000         Y
>                 lcdc_clk_d            0        0        0    24000000
> 0     0  50000         N
>                 dsi_vclk              0        0        0    24000000
> 0     0  50000         N
>        .pll5_fout1ph0                 0        0        0    12000000
> 0     0  50000         Y
>     .pll6                             2        2        0   500000000
> 0     0  50000         Y
>        .sel_gpu2                      1        1        0   500000000
> 0     0  50000         Y
>           G                           1        1        0    62500000
> 0     0  50000         Y
>              gpu_clk                  1        2        0    62500000
> 0     0  50000         Y
>        .pll6_250                      1        1        0   250000000
> 0     0  50000         Y
>           HP                          2        2        0   250000000
> 0     0  50000         Y
>     .pll5                             0        0        0  3000000000
> 0     0  50000         Y
>        .pll5_fout3                    0        0        0   500000000
> 0     0  50000         Y
>           .pll5_250                   0        0        0   250000000
> 0     0  50000         Y
>     .pll3                             1        2        0  1600000000
> 0     0  50000         Y
>        .pll3_div2                     1        1        0   800000000
> 0     0  50000         Y
>           .pll3_div2_4                3        3        0   200000000
> 0     0  50000         Y
>              M0                       2        2        0   200000000
> 0     0  50000         Y
>                 eth1_axi              1        1        0   200000000
> 0     0  50000         Y
>                 eth0_axi              1        1        0   200000000
> 0     0  50000         Y
>                 lcdc_a                0        0        0   200000000
> 0     0  50000         N
>                 cru_aclk              0        0        0   200000000
> 0     0  50000         N
>              P1                      11       12        0   200000000
> 0     0  50000         Y
>                 usb_pclk              8       12        0   200000000
> 0     0  50000         Y
>                 usb0_func             1        1        0   200000000
> 0     0  50000         Y
>                 usb1_host             3        5        0   200000000
> 0     0  50000         Y
>                 usb0_host             3        5        0   200000000
> 0     0  50000         Y
>                 dsi_aclk              0        0        0   200000000
> 0     0  50000         N
>                 gpu_ace_clk           0        1        0   200000000
> 0     0  50000         N
>                 gpu_axi_clk           1        2        0   200000000
> 0     0  50000         Y
>                 sdhi1_aclk            1        1        0   200000000
> 0     0  50000         Y
>                 sdhi0_aclk            1        1        0   200000000
> 0     0  50000         Y
>                 dmac_aclk             2        2        0   200000000
> 0     0  50000         Y
>                 ia55_clk              2        2        0   200000000
> 0     0  50000         Y
>                 gic                   1        1        0   200000000
> 0     0  50000         Y
>                 P1_DIV2               1        1        0   100000000
> 0     0  50000         Y
>                    dmac_pclk          1        1        0   100000000
> 0     0  50000         Y
>              .pll3_div2_4_2           2        2        0   100000000
> 0     0  50000         Y
>                 ZT                    2        2        0   100000000
> 0     0  50000         Y
>                    eth1_chi           1        1        0   100000000
> 0     0  50000         Y
>                    eth0_chi           1        1        0   100000000
> 0     0  50000         Y
>                    lcdc_p             0        0        0   100000000
> 0     0  50000         N
>                    cru_pclk           0        0        0   100000000
> 0     0  50000         N
>                 P2                    1        1        0   100000000
> 0     0  50000         Y
>                    dsi_pclk           0        0        0   100000000
> 0     0  50000         N
>                    ia55_pclk          1        1        0   100000000
> 0     0  50000         Y
>           .pll3_div2_2                0        0        0   400000000
> 0     0  50000         Y
>        .pll3_533                      0        1        0   533333333
> 0     0  50000         Y
>           M2                          0        0        0   266666666
> 0     0  50000         Y
>              cru_vclk                 0        0        0   266666666
> 0     0  50000         N
>              M2_DIV2                  0        0        0   133333333
> 0     0  50000         Y
>                 dsi_sys_clk           0        0        0   133333333
> 0     0  50000         N
>                 cru_sysclk            0        0        0   133333333
> 0     0  50000         N
>           .sel_pll3_3                 0        1        0   533333333
> 0     0  50000         Y
>              divpl3c                  0        2        0   266666667
> 0     0  50000         Y
>                 SPI1                  0        1        0    66666666
> 0     0  50000         Y
>                    spi_clk2           0        1        0    66666666
> 0     0  50000         N
>                 SPI0                  0        1        0   133333333
> 0     0  50000         Y
>                    spi_clk            0        1        0   133333333
> 0     0  50000         N
>        .pll3_400                      0        0        0   400000000
> 0     0  50000         Y
>     .pll2                             2        2        0  1600000000
> 0     0  50000         Y
>        .clk_533                       2        2        0   533333333
> 0     0  50000         Y
>           sd1                         2        2        0   533333333
> 0     0  50000         Y
>              sdhi1_clk_hs             1        1        0   533333333
> 0     0  50000         Y
>              SD1_DIV4                 2        2        0   133333333
> 0     0  50000         Y
>                 sdhi1_imclk2          2        2        0   133333333
> 0     0  50000         Y
>                 sdhi1_imclk           1        1        0   133333333
> 0     0  50000         Y
>           sd0                         2        2        0   533333333
> 0     0  50000         Y
>              sdhi0_clk_hs             1        1        0   533333333
> 0     0  50000         Y
>              SD0_DIV4                 2        2        0   133333333
> 0     0  50000         Y
>                 sdhi0_imclk2          2        2        0   133333333
> 0     0  50000         Y
>                 sdhi0_imclk           1        1        0   133333333
> 0     0  50000         Y
>           .clk_266                    0        0        0   266666666
> 0     0  50000         Y
>        .clk_800                       0        0        0   800000000
> 0     0  50000         Y
>           .clk_400                    0        0        0   400000000
> 0     0  50000         Y
>        .pll2_div2                     2        2        0   800000000
> 0     0  50000         Y
>           .pll2_div2_10               1        1        0    80000000
> 0     0  50000         Y
>              TSU                      1        2        0    80000000
> 0     0  50000         Y
>                 tsu_pclk              1        1        0    80000000
> 0     0  50000         Y
>                 adc_adclk             0        1        0    80000000
> 0     0  50000         N
>           .pll2_div2_8                1        1        0   100000000
> 0     0  50000         Y
>              P0                       6       14        0   100000000
> 0     0  50000         Y
>                 adc_pclk              0        1        0   100000000
> 0     0  50000         N
>                 canfd                 1        2        0   100000000
> 0     0  50000         Y
>                 rspi2                 0        0        0   100000000
> 0     0  50000         N
>                 rspi1                 0        1        0   100000000
> 0     0  50000         N
>                 rspi0                 0        0        0   100000000
> 0     0  50000         N
>                 sci1                  0        0        0   100000000
> 0     0  50000         N
>                 sci0                  0        0        0   100000000
> 0     0  50000         N
>                 scif4                 0        0        0   100000000
> 0     0  50000         N
>                 scif3                 0        0        0   100000000
> 0     0  50000         N
>                 scif2                 0        1        0   100000000
> 0     0  50000         N
>                 scif1                 0        0        0   100000000
> 0     0  50000         N
>                 scif0                 2        2        0   100000000
> 0     0  50000         Y
>                 i2c3                  0        1        0   100000000
> 0     0  50000         N
>                 i2c2                  0        0        0   100000000
> 0     0  50000         N
>                 i2c1                  0        1        0   100000000
> 0     0  50000         N
>                 i2c0                  0        1        0   100000000
> 0     0  50000         N
>                 ssi3_sfr              0        0        0   100000000
> 0     0  50000         N
>                 ssi3_pclk             0        0        0   100000000
> 0     0  50000         N
>                 ssi2_sfr              0        0        0   100000000
> 0     0  50000         N
>                 ssi2_pclk             0        0        0   100000000
> 0     0  50000         N
>                 ssi1_sfr              0        0        0   100000000
> 0     0  50000         N
>                 ssi1_pclk             0        0        0   100000000
> 0     0  50000         N
>                 ssi0_sfr              1        1        0   100000000
> 0     0  50000         Y
>                 ssi0_pclk             1        1        0   100000000
> 0     0  50000         Y
>                 wdt1_pclk             0        1        0   100000000
> 0     0  50000         N
>                 wdt0_pclk             0        1        0   100000000
> 0     0  50000         N
>                 poeg_d_clkp           0        0        0   100000000
> 0     0  50000         N
>                 poeg_c_clkp           0        0        0   100000000
> 0     0  50000         N
>                 poeg_b_clkp           0        0        0   100000000
> 0     0  50000         N
>                 poeg_a_clkp           0        0        0   100000000
> 0     0  50000         N
>                 gpt_pclk              0        0        0   100000000
> 0     0  50000         N
>                 mtu_x_mck             0        0        0   100000000
> 0     0  50000         N
>                 ostm2_pclk            1        2        0   100000000
> 0     0  50000         Y
>                 ostm1_pclk            1        2        0   100000000
> 0     0  50000         Y
>                 ostm0_pclk            0        0        0   100000000
> 0     0  50000         N
>                 P0_DIV2               0        0        0    50000000
> 0     0  50000         Y
>        .pll2_533                      0        0        0   533333333
> 0     0  50000         Y
>           .pll2_533_div2              0        0        0   266666666
> 0     0  50000         Y
>              .div_dsi_lpclk           0        0        0    16666667
> 0     0  50000         Y
>                 M4                    0        0        0    16666667
> 0     0  50000         Y
>                    dsi_lpclk          0        0        0    16666667
> 0     0  50000         N
>     .pll1                             0        0        0  1200000000
> 0     0  50000         Y
>        I                              0        0        0  1200000000
> 0     0  50000         Y
>     .osc_div1000                      0        0        0       24000
> 0     0  50000         Y
>     .osc                              1        3        0    24000000
> 0     0  50000         Y
>        gpio                           1        2        0    24000000
> 0     0  50000         Y
>        wdt1_clk                       0        1        0    24000000
> 0     0  50000         N
>        wdt0_clk                       0        1        0    24000000
> 0     0  50000         N
>  can-clk                              0        0        0           0
> 0     0  50000         Y
>  audio2-clk                           0        0        0    12288000
> 0     0  50000         Y
>  audio1-clk                           0        0        0    11289600
> 0     0  50000         Y
> playback 48000 kHz sample
> 
> speaker-test 1.2.1
> 
> Playback device is hw:0,0
> Stream parameters are 48000Hz, S16_LE, 2 channels Using 16 octaves of pink
> noise Rate set to 48000Hz (requested 48000Hz) Buffer size range from 8 to
> 8192 Period size range from 8 to 2048 Using max buffer size 8192 Periods = 4
> was set period_size = 2048 was set buffer_size = 8192
>  0 - Front Left
> 00: 80
> 01: 00
> 02: 11
> 03: 19
> 04: 4c
> 05: 02
> 06: 23
> 07: 7f
> 08: 83
> 09: 19
> 0a: 08
> 0b: a9
> 0c: 5f
> 0d: 25
> 0e: 24
> 0f: bf
> 10: 00
> 11: 14
> 12: 7a
> 13: e1
> 14: 00
> 15: 00
> 16: 00
> 17: 00
> 18: 01
> 19: 55
> 1a: 59
> 1b: bb
> 1c: 3f
> 1d: 30
> 1e: 90
> 1f: f6
> 20: 80
> 21: b0
> 22: 45
> 23: c4
> 24: 95
> Read at address  0x10049C00 (0xffff9a615c00): 0x300B4022
>        pfd2                           1        1        0    24000000
> 0     0  50000         Y
>           pll2                        1        1        0   491519897
> 0     0  50000         Y
>              div4_mux                 1        1        0   491519897
> 0     0  50000         Y
>                 div4                  1        1        0    12287998
> 0     0  50000         Y
>                    se2_mux            1        1        0    12287998
> 0     0  50000         Y
>                       se2             1        1        0    12287998
> 0     0  50000         Y
>  1 - Front Right
> playback 44100 kHz sample
> 
> speaker-test 1.2.1
> 
> Playback device is hw:0,0
> Stream parameters are 44100Hz, S16_LE, 2 channels Using 16 octaves of pink
> noise Rate set to 44100Hz (requested 44100Hz) Buffer size range from 8 to
> 8192 Period size range from 8 to 2048 Using max buffer size 8192 Periods = 4
> was set period_size = 2048 was set buffer_size = 8192
>  0 - Front Left
> /audio_test.sh: line 2:   187 Killed                  speaker-test -D hw:0,0
> -c 2 -r $1
> 00: 80
> 01: 00
> 02: 11
> 03: 19
> 04: 4c
> 05: 02
> 06: 23
> 07: 7f
> 08: 83
> 09: 19
> 0a: 08
> 0b: a9
> 0c: 5f
> 0d: 25
> 0e: 24
> 0f: bf
> 10: 00
> 11: 14
> 12: 7a
> 13: e1
> 14: 00
> 15: 00
> 16: 00
> 17: 00
> 18: 01
> 19: 55
> 1a: 59
> 1b: bb
> 1c: 3f
> 1d: 30
> 1e: 90
> 1f: b6
> 20: 80
> 21: b0
> 22: 45
> 23: c4
> 24: 95
> Read at address  0x10049C00 (0xffffb7957c00): 0x700B4022
>     pfd3_mux                          1        1        0    24000000
> 0     0  50000         Y
>        pfd3                           1        1        0      960000
> 0     0  50000         Y
>           pll3                        1        1        0   564480000
> 0     0  50000         Y
>              div5                     1        1        0    11289600
> 0     0  50000         Y
>                 se2_mux               1        1        0    11289600
> 0     0  50000         Y
>                    se2                1        1        0    11289600
> 0     0  50000         Y
> 
> Biju Das (3):
>   dt-bindings: clock: Add Renesas versa3 clock generator bindings
>   drivers: clk: Add support for versa3 clock driver
>   arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk
> 
>  .../bindings/clock/renesas,5p35023.yaml       |   86 ++
>  .../boot/dts/renesas/rz-smarc-common.dtsi     |   13 +-
>  arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  |   23 +
>  arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi |   23 +
>  arch/arm64/boot/dts/renesas/rzg2ul-smarc.dtsi |   25 +
>  drivers/clk/Kconfig                           |    9 +
>  drivers/clk/Makefile                          |    1 +
>  drivers/clk/clk-versaclock3.c                 | 1144 +++++++++++++++++
>  8 files changed, 1317 insertions(+), 7 deletions(-)  create mode 100644
> Documentation/devicetree/bindings/clock/renesas,5p35023.yaml
>  create mode 100644 drivers/clk/clk-versaclock3.c
> 
> 
> base-commit: d5b9392d664c6db52fd66e538f1145cfa927d8cc
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v5 0/3] Add Versa3 clock generator support
  2023-05-02 14:18 ` [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
@ 2023-05-02 20:24   ` Krzysztof Kozlowski
  2023-05-03  7:59     ` Biju Das
  0 siblings, 1 reply; 7+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-02 20:24 UTC (permalink / raw)
  To: Biju Das, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-clk, devicetree,
	Prabhakar Mahadev Lad

On 02/05/2023 16:18, Biju Das wrote:
> Hi All,
> 
> Gentle Ping.

It's merge window. Ping, or better resend, after it finishes.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v5 0/3] Add Versa3 clock generator support
  2023-05-02 20:24   ` Krzysztof Kozlowski
@ 2023-05-03  7:59     ` Biju Das
  0 siblings, 0 replies; 7+ messages in thread
From: Biju Das @ 2023-05-03  7:59 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-clk, devicetree,
	Prabhakar Mahadev Lad

Hi Krzysztof Kozlowski,

> Subject: Re: [PATCH v5 0/3] Add Versa3 clock generator support
> 
> On 02/05/2023 16:18, Biju Das wrote:
> > Hi All,
> >
> > Gentle Ping.
> 
> It's merge window. Ping, or better resend, after it finishes.

Thanks for the info.

Cheers,
Biju

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-05-03  8:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-13 15:26 [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
2023-04-13 15:26 ` [PATCH v5 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings Biju Das
2023-04-13 15:26 ` [PATCH v5 2/3] drivers: clk: Add support for versa3 clock driver Biju Das
2023-04-13 15:26 ` [PATCH v5 3/3] arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk Biju Das
2023-05-02 14:18 ` [PATCH v5 0/3] Add Versa3 clock generator support Biju Das
2023-05-02 20:24   ` Krzysztof Kozlowski
2023-05-03  7:59     ` Biju Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).