Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Jul 2019 17:07:48 +0000 (10:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Jul 2019 17:07:48 +0000 (10:07 -0700)
Pull clk updates from Stephen Boyd:
 "This round of clk driver and framework updates is heavy on the driver
  update side. The two main highlights in the core framework are the
  addition of an bulk clk_get API that handles optional clks and an
  extra debugfs file that tells the developer about the current parent
  of a clk.

  The driver updates are dominated by i.MX in the diffstat, but that is
  mostly because that SoC has started converting to the clk_hw style of
  clk registration. The next big update is in the Amlogic meson clk
  driver that gained some support for audio, cpu, and temperature clks
  while fixing some PLL issues. Finally, the biggest thing that stands
  out is the conversion of a large part of the Allwinner sunxi-ng driver
  to the new clk parent scheme that uses less strings and more pointer
  comparisons to match clk parents and children up.

  In general, it looks like we have a lot of little fixes and tweaks
  here and there to clk data along with the normal addition of a handful
  of new drivers and a couple new core framework features.

  Core:
   - Add a 'clk_parent' file in clk debugfs
   - Add a clk_bulk_get_optional() API (with devm too)

  New Drivers:
   - Support gated clk controller on MIPS based BCM63XX SoCs
   - Support SiLabs Si5341 and Si5340 chips
   - Support for CPU clks on Raspberry Pi devices
   - Audsys clock driver for MediaTek MT8516 SoCs

  Updates:
   - Convert a large portion of the Allwinner sunxi-ng driver to new clk parent scheme
   - Small frequency support for SiLabs Si544 chips
   - Slow clk support for AT91 SAM9X60 SoCs
   - Remove dead code in various clk drivers (-Wunused)
   - Support for Marvell 98DX1135 SoCs
   - Get duty cycle of generic pwm clks
   - Improvement in mmc phase calculation and cleanup of some rate defintions
   - Switch i.MX6 and i.MX7 clock drivers to clk_hw based APIs
   - Add GPIO, SNVS and GIC clocks for i.MX8 drivers
   - Mark imx6sx/ul/ull/sll MMDC_P1_IPG and imx8mm DRAM_APB as critical clock
   - Correct imx7ulp nic1_bus_clk and imx8mm audio_pll2_clk clock setting
   - Add clks for new Exynos5422 Dynamic Memory Controller driver
   - Clock definition for Exynos4412 Mali
   - Add CMM (Color Management Module) clocks on Renesas R-Car H3, M3-N, E3, and D3
   - Add TPU (Timer Pulse Unit / PWM) clocks on Renesas RZ/G2M
   - Support for 32 bit clock IDs in TI's sci-clks for J721e SoCs
   - TI clock probing done from DT by default instead of firmware
   - Fix Amlogic Meson mpll fractional part and spread sprectrum issues
   - Add Amlogic meson8 audio clocks
   - Add Amlogic g12a temperature sensors clocks
   - Add Amlogic g12a and g12b cpu clocks
   - Add TPU (Timer Pulse Unit / PWM) clocks on Renesas R-Car H3, M3-W, and M3-N
   - Add CMM (Color Management Module) clocks on Renesas R-Car M3-W
   - Add Clock Domain support on Renesas RZ/N1"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (190 commits)
  clk: consoldiate the __clk_get_hw() declarations
  clk: sprd: Add check for return value of sprd_clk_regmap_init()
  clk: lochnagar: Update DT binding doc to include the primary SPDIF MCLK
  clk: Add Si5341/Si5340 driver
  dt-bindings: clock: Add silabs,si5341
  clk: clk-si544: Implement small frequency change support
  clk: add BCM63XX gated clock controller driver
  devicetree: document the BCM63XX gated clock bindings
  clk: at91: sckc: use dedicated functions to unregister clock
  clk: at91: sckc: improve error path for sama5d4 sck registration
  clk: at91: sckc: remove unnecessary line
  clk: at91: sckc: improve error path for sam9x5 sck register
  clk: at91: sckc: add support to free slow clock osclillator
  clk: at91: sckc: add support to free slow rc oscillator
  clk: at91: sckc: add support to free slow oscillator
  clk: rockchip: export HDMIPHY clock on rk3228
  clk: rockchip: add watchdog pclk on rk3328
  clk: rockchip: add clock id for hdmi_phy special clock on rk3228
  clk: rockchip: add clock id for watchdog pclk on rk3328
  clk: at91: sckc: add support for SAM9X60
  ...

65 files changed:
1  2 
Documentation/driver-api/driver-model/devres.rst
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/pm.c
arch/mips/jz4740/time.c
drivers/clk/Kconfig
drivers/clk/at91/sckc.c
drivers/clk/bcm/Kconfig
drivers/clk/clk-cdce706.c
drivers/clk/clk-pwm.c
drivers/clk/clk-qoriq.c
drivers/clk/clk.c
drivers/clk/imx/clk-busy.c
drivers/clk/imx/clk-cpu.c
drivers/clk/imx/clk-fixup-div.c
drivers/clk/imx/clk-fixup-mux.c
drivers/clk/imx/clk-gate-exclusive.c
drivers/clk/imx/clk-gate2.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6sl.c
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/imx/clk-imx8mm.c
drivers/clk/imx/clk-pfd.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/ingenic/Makefile
drivers/clk/ingenic/cgu.c
drivers/clk/ingenic/cgu.h
drivers/clk/ingenic/jz4740-cgu.c
drivers/clk/ingenic/jz4780-cgu.c
drivers/clk/keystone/Kconfig
drivers/clk/mediatek/Kconfig
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/qcom/gdsc.c
drivers/clk/rockchip/clk-mmc-phase.c
drivers/clk/rockchip/clk-px30.c
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/sunxi-ng/ccu-sun4i-a10.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun5i.c
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-r.c
drivers/clk/sunxi-ng/ccu-sun8i-r40.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
drivers/clk/sunxi-ng/ccu_common.c
drivers/clk/sunxi-ng/ccu_gate.h
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/tegra/clk-tegra210.c
drivers/firmware/ti_sci.h
include/dt-bindings/clock/rk3228-cru.h
include/dt-bindings/clock/rk3328-cru.h
include/linux/clk.h

index 4ac99122b5f1b891c363eec16db76f57e26cc67a,0000000000000000000000000000000000000000..a100bef5495284d93ee487a7b2ad44985869497d
mode 100644,000000..100644
--- /dev/null
@@@ -1,414 -1,0 +1,418 @@@
 +================================
 +Devres - Managed Device Resource
 +================================
 +
 +Tejun Heo     <teheo@suse.de>
 +
 +First draft   10 January 2007
 +
 +.. contents
 +
 +   1. Intro                   : Huh? Devres?
 +   2. Devres                  : Devres in a nutshell
 +   3. Devres Group            : Group devres'es and release them together
 +   4. Details                 : Life time rules, calling context, ...
 +   5. Overhead                        : How much do we have to pay for this?
 +   6. List of managed interfaces: Currently implemented managed interfaces
 +
 +
 +1. Intro
 +--------
 +
 +devres came up while trying to convert libata to use iomap.  Each
 +iomapped address should be kept and unmapped on driver detach.  For
 +example, a plain SFF ATA controller (that is, good old PCI IDE) in
 +native mode makes use of 5 PCI BARs and all of them should be
 +maintained.
 +
 +As with many other device drivers, libata low level drivers have
 +sufficient bugs in ->remove and ->probe failure path.  Well, yes,
 +that's probably because libata low level driver developers are lazy
 +bunch, but aren't all low level driver developers?  After spending a
 +day fiddling with braindamaged hardware with no document or
 +braindamaged document, if it's finally working, well, it's working.
 +
 +For one reason or another, low level drivers don't receive as much
 +attention or testing as core code, and bugs on driver detach or
 +initialization failure don't happen often enough to be noticeable.
 +Init failure path is worse because it's much less travelled while
 +needs to handle multiple entry points.
 +
 +So, many low level drivers end up leaking resources on driver detach
 +and having half broken failure path implementation in ->probe() which
 +would leak resources or even cause oops when failure occurs.  iomap
 +adds more to this mix.  So do msi and msix.
 +
 +
 +2. Devres
 +---------
 +
 +devres is basically linked list of arbitrarily sized memory areas
 +associated with a struct device.  Each devres entry is associated with
 +a release function.  A devres can be released in several ways.  No
 +matter what, all devres entries are released on driver detach.  On
 +release, the associated release function is invoked and then the
 +devres entry is freed.
 +
 +Managed interface is created for resources commonly used by device
 +drivers using devres.  For example, coherent DMA memory is acquired
 +using dma_alloc_coherent().  The managed version is called
 +dmam_alloc_coherent().  It is identical to dma_alloc_coherent() except
 +for the DMA memory allocated using it is managed and will be
 +automatically released on driver detach.  Implementation looks like
 +the following::
 +
 +  struct dma_devres {
 +      size_t          size;
 +      void            *vaddr;
 +      dma_addr_t      dma_handle;
 +  };
 +
 +  static void dmam_coherent_release(struct device *dev, void *res)
 +  {
 +      struct dma_devres *this = res;
 +
 +      dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
 +  }
 +
 +  dmam_alloc_coherent(dev, size, dma_handle, gfp)
 +  {
 +      struct dma_devres *dr;
 +      void *vaddr;
 +
 +      dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
 +      ...
 +
 +      /* alloc DMA memory as usual */
 +      vaddr = dma_alloc_coherent(...);
 +      ...
 +
 +      /* record size, vaddr, dma_handle in dr */
 +      dr->vaddr = vaddr;
 +      ...
 +
 +      devres_add(dev, dr);
 +
 +      return vaddr;
 +  }
 +
 +If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
 +freed whether initialization fails half-way or the device gets
 +detached.  If most resources are acquired using managed interface, a
 +driver can have much simpler init and exit code.  Init path basically
 +looks like the following::
 +
 +  my_init_one()
 +  {
 +      struct mydev *d;
 +
 +      d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
 +      if (!d)
 +              return -ENOMEM;
 +
 +      d->ring = dmam_alloc_coherent(...);
 +      if (!d->ring)
 +              return -ENOMEM;
 +
 +      if (check something)
 +              return -EINVAL;
 +      ...
 +
 +      return register_to_upper_layer(d);
 +  }
 +
 +And exit path::
 +
 +  my_remove_one()
 +  {
 +      unregister_from_upper_layer(d);
 +      shutdown_my_hardware();
 +  }
 +
 +As shown above, low level drivers can be simplified a lot by using
 +devres.  Complexity is shifted from less maintained low level drivers
 +to better maintained higher layer.  Also, as init failure path is
 +shared with exit path, both can get more testing.
 +
 +Note though that when converting current calls or assignments to
 +managed devm_* versions it is up to you to check if internal operations
 +like allocating memory, have failed. Managed resources pertains to the
 +freeing of these resources *only* - all other checks needed are still
 +on you. In some cases this may mean introducing checks that were not
 +necessary before moving to the managed devm_* calls.
 +
 +
 +3. Devres group
 +---------------
 +
 +Devres entries can be grouped using devres group.  When a group is
 +released, all contained normal devres entries and properly nested
 +groups are released.  One usage is to rollback series of acquired
 +resources on failure.  For example::
 +
 +  if (!devres_open_group(dev, NULL, GFP_KERNEL))
 +      return -ENOMEM;
 +
 +  acquire A;
 +  if (failed)
 +      goto err;
 +
 +  acquire B;
 +  if (failed)
 +      goto err;
 +  ...
 +
 +  devres_remove_group(dev, NULL);
 +  return 0;
 +
 + err:
 +  devres_release_group(dev, NULL);
 +  return err_code;
 +
 +As resource acquisition failure usually means probe failure, constructs
 +like above are usually useful in midlayer driver (e.g. libata core
 +layer) where interface function shouldn't have side effect on failure.
 +For LLDs, just returning error code suffices in most cases.
 +
 +Each group is identified by `void *id`.  It can either be explicitly
 +specified by @id argument to devres_open_group() or automatically
 +created by passing NULL as @id as in the above example.  In both
 +cases, devres_open_group() returns the group's id.  The returned id
 +can be passed to other devres functions to select the target group.
 +If NULL is given to those functions, the latest open group is
 +selected.
 +
 +For example, you can do something like the following::
 +
 +  int my_midlayer_create_something()
 +  {
 +      if (!devres_open_group(dev, my_midlayer_create_something, GFP_KERNEL))
 +              return -ENOMEM;
 +
 +      ...
 +
 +      devres_close_group(dev, my_midlayer_create_something);
 +      return 0;
 +  }
 +
 +  void my_midlayer_destroy_something()
 +  {
 +      devres_release_group(dev, my_midlayer_create_something);
 +  }
 +
 +
 +4. Details
 +----------
 +
 +Lifetime of a devres entry begins on devres allocation and finishes
 +when it is released or destroyed (removed and freed) - no reference
 +counting.
 +
 +devres core guarantees atomicity to all basic devres operations and
 +has support for single-instance devres types (atomic
 +lookup-and-add-if-not-found).  Other than that, synchronizing
 +concurrent accesses to allocated devres data is caller's
 +responsibility.  This is usually non-issue because bus ops and
 +resource allocations already do the job.
 +
 +For an example of single-instance devres type, read pcim_iomap_table()
 +in lib/devres.c.
 +
 +All devres interface functions can be called without context if the
 +right gfp mask is given.
 +
 +
 +5. Overhead
 +-----------
 +
 +Each devres bookkeeping info is allocated together with requested data
 +area.  With debug option turned off, bookkeeping info occupies 16
 +bytes on 32bit machines and 24 bytes on 64bit (three pointers rounded
 +up to ull alignment).  If singly linked list is used, it can be
 +reduced to two pointers (8 bytes on 32bit, 16 bytes on 64bit).
 +
 +Each devres group occupies 8 pointers.  It can be reduced to 6 if
 +singly linked list is used.
 +
 +Memory space overhead on ahci controller with two ports is between 300
 +and 400 bytes on 32bit machine after naive conversion (we can
 +certainly invest a bit more effort into libata core layer).
 +
 +
 +6. List of managed interfaces
 +-----------------------------
 +
 +CLOCK
 +  devm_clk_get()
 +  devm_clk_get_optional()
 +  devm_clk_put()
++  devm_clk_bulk_get()
++  devm_clk_bulk_get_all()
++  devm_clk_bulk_get_optional()
++  devm_get_clk_from_childl()
 +  devm_clk_hw_register()
 +  devm_of_clk_add_hw_provider()
 +  devm_clk_hw_register_clkdev()
 +
 +DMA
 +  dmaenginem_async_device_register()
 +  dmam_alloc_coherent()
 +  dmam_alloc_attrs()
 +  dmam_free_coherent()
 +  dmam_pool_create()
 +  dmam_pool_destroy()
 +
 +DRM
 +  devm_drm_dev_init()
 +
 +GPIO
 +  devm_gpiod_get()
 +  devm_gpiod_get_index()
 +  devm_gpiod_get_index_optional()
 +  devm_gpiod_get_optional()
 +  devm_gpiod_put()
 +  devm_gpiod_unhinge()
 +  devm_gpiochip_add_data()
 +  devm_gpio_request()
 +  devm_gpio_request_one()
 +  devm_gpio_free()
 +
 +I2C
 +  devm_i2c_new_dummy_device()
 +
 +IIO
 +  devm_iio_device_alloc()
 +  devm_iio_device_free()
 +  devm_iio_device_register()
 +  devm_iio_device_unregister()
 +  devm_iio_kfifo_allocate()
 +  devm_iio_kfifo_free()
 +  devm_iio_triggered_buffer_setup()
 +  devm_iio_triggered_buffer_cleanup()
 +  devm_iio_trigger_alloc()
 +  devm_iio_trigger_free()
 +  devm_iio_trigger_register()
 +  devm_iio_trigger_unregister()
 +  devm_iio_channel_get()
 +  devm_iio_channel_release()
 +  devm_iio_channel_get_all()
 +  devm_iio_channel_release_all()
 +
 +INPUT
 +  devm_input_allocate_device()
 +
 +IO region
 +  devm_release_mem_region()
 +  devm_release_region()
 +  devm_release_resource()
 +  devm_request_mem_region()
 +  devm_request_region()
 +  devm_request_resource()
 +
 +IOMAP
 +  devm_ioport_map()
 +  devm_ioport_unmap()
 +  devm_ioremap()
 +  devm_ioremap_nocache()
 +  devm_ioremap_wc()
 +  devm_ioremap_resource() : checks resource, requests memory region, ioremaps
 +  devm_iounmap()
 +  pcim_iomap()
 +  pcim_iomap_regions()        : do request_region() and iomap() on multiple BARs
 +  pcim_iomap_table()  : array of mapped addresses indexed by BAR
 +  pcim_iounmap()
 +
 +IRQ
 +  devm_free_irq()
 +  devm_request_any_context_irq()
 +  devm_request_irq()
 +  devm_request_threaded_irq()
 +  devm_irq_alloc_descs()
 +  devm_irq_alloc_desc()
 +  devm_irq_alloc_desc_at()
 +  devm_irq_alloc_desc_from()
 +  devm_irq_alloc_descs_from()
 +  devm_irq_alloc_generic_chip()
 +  devm_irq_setup_generic_chip()
 +  devm_irq_sim_init()
 +
 +LED
 +  devm_led_classdev_register()
 +  devm_led_classdev_unregister()
 +
 +MDIO
 +  devm_mdiobus_alloc()
 +  devm_mdiobus_alloc_size()
 +  devm_mdiobus_free()
 +
 +MEM
 +  devm_free_pages()
 +  devm_get_free_pages()
 +  devm_kasprintf()
 +  devm_kcalloc()
 +  devm_kfree()
 +  devm_kmalloc()
 +  devm_kmalloc_array()
 +  devm_kmemdup()
 +  devm_kstrdup()
 +  devm_kvasprintf()
 +  devm_kzalloc()
 +
 +MFD
 +  devm_mfd_add_devices()
 +
 +MUX
 +  devm_mux_chip_alloc()
 +  devm_mux_chip_register()
 +  devm_mux_control_get()
 +
 +PER-CPU MEM
 +  devm_alloc_percpu()
 +  devm_free_percpu()
 +
 +PCI
 +  devm_pci_alloc_host_bridge()  : managed PCI host bridge allocation
 +  devm_pci_remap_cfgspace()   : ioremap PCI configuration space
 +  devm_pci_remap_cfg_resource()       : ioremap PCI configuration space resource
 +  pcim_enable_device()                : after success, all PCI ops become managed
 +  pcim_pin_device()           : keep PCI device enabled after release
 +
 +PHY
 +  devm_usb_get_phy()
 +  devm_usb_put_phy()
 +
 +PINCTRL
 +  devm_pinctrl_get()
 +  devm_pinctrl_put()
 +  devm_pinctrl_register()
 +  devm_pinctrl_unregister()
 +
 +POWER
 +  devm_reboot_mode_register()
 +  devm_reboot_mode_unregister()
 +
 +PWM
 +  devm_pwm_get()
 +  devm_pwm_put()
 +
 +REGULATOR
 +  devm_regulator_bulk_get()
 +  devm_regulator_get()
 +  devm_regulator_put()
 +  devm_regulator_register()
 +
 +RESET
 +  devm_reset_control_get()
 +  devm_reset_controller_register()
 +
 +SERDEV
 +  devm_serdev_device_open()
 +
 +SLAVE DMA ENGINE
 +  devm_acpi_dma_controller_register()
 +
 +SPI
 +  devm_spi_register_master()
 +
 +WATCHDOG
 +  devm_watchdog_register_device()
index daed44ee116df507269864170aa9e16d61255b79,b418b23ff1d1bcd1fbf9eeaad80588aabd6a7c9c..4a7a80c358c75d673f3a6479483cf3d4ee8583a1
@@@ -1,4 -1,3 +1,4 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * linux/arch/mips/jz4740/board-qi_lb60.c
   *
@@@ -7,6 -6,10 +7,6 @@@
   * Copyright (c) 2009 Qi Hardware inc.,
   * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
   * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 or later
 - * as published by the Free Software Foundation.
   */
  
  #include <linux/kernel.h>
@@@ -37,8 -40,6 +37,6 @@@
  
  #include <asm/mach-jz4740/platform.h>
  
- #include "clock.h"
  /* GPIOs */
  #define QI_LB60_GPIO_KEYOUT(x)                (JZ_GPIO_PORTC(10) + (x))
  #define QI_LB60_GPIO_KEYIN(x)         (JZ_GPIO_PORTD(18) + (x))
@@@ -466,27 -467,27 +464,27 @@@ static unsigned long pin_cfg_bias_disab
  static struct pinctrl_map pin_map[] __initdata = {
        /* NAND pin configuration */
        PIN_MAP_MUX_GROUP_DEFAULT("jz4740-nand",
 -                      "10010000.jz4740-pinctrl", "nand", "nand-cs1"),
 +                      "10010000.pin-controller", "nand-cs1", "nand"),
  
        /* fbdev pin configuration */
        PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_DEFAULT,
 -                      "10010000.jz4740-pinctrl", "lcd", "lcd-8bit"),
 +                      "10010000.pin-controller", "lcd-8bit", "lcd"),
        PIN_MAP_MUX_GROUP("jz4740-fb", PINCTRL_STATE_SLEEP,
 -                      "10010000.jz4740-pinctrl", "lcd", "lcd-no-pins"),
 +                      "10010000.pin-controller", "lcd-no-pins", "lcd"),
  
        /* MMC pin configuration */
        PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
 -                      "10010000.jz4740-pinctrl", "mmc", "mmc-1bit"),
 +                      "10010000.pin-controller", "mmc-1bit", "mmc"),
        PIN_MAP_MUX_GROUP_DEFAULT("jz4740-mmc.0",
 -                      "10010000.jz4740-pinctrl", "mmc", "mmc-4bit"),
 +                      "10010000.pin-controller", "mmc-4bit", "mmc"),
        PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
 -                      "10010000.jz4740-pinctrl", "PD0", pin_cfg_bias_disable),
 +                      "10010000.pin-controller", "PD0", pin_cfg_bias_disable),
        PIN_MAP_CONFIGS_PIN_DEFAULT("jz4740-mmc.0",
 -                      "10010000.jz4740-pinctrl", "PD2", pin_cfg_bias_disable),
 +                      "10010000.pin-controller", "PD2", pin_cfg_bias_disable),
  
        /* PWM pin configuration */
        PIN_MAP_MUX_GROUP_DEFAULT("jz4740-pwm",
 -                      "10010000.jz4740-pinctrl", "pwm4", "pwm4"),
 +                      "10010000.pin-controller", "pwm4", "pwm4"),
  };
  
  
index 4b89abb1795009b44fdce3192c89b0c66576b2a8,cf9c660311996e743369cb7a758aee29eb59ec0f..c74c99f5951d801df2d614b0aac16acb0e972d63
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
   *  JZ4740 platform devices
 - *
 - *  This program is free software; you can redistribute it and/or modify it
 - *  under  the terms of the GNU General        Public License as published by the
 - *  Free Software Foundation;  either version 2 of the License, or (at your
 - *  option) any later version.
 - *
 - *  You should have received a copy of the GNU General Public License along
 - *  with this program; if not, write to the Free Software Foundation, Inc.,
 - *  675 Mass Ave, Cambridge, MA 02139, USA.
 - *
   */
  
  #include <linux/clk.h>
@@@ -21,8 -30,6 +21,6 @@@
  #include <linux/serial_core.h>
  #include <linux/serial_8250.h>
  
- #include "clock.h"
  /* USB Device Controller */
  struct platform_device jz4740_udc_xceiv_device = {
        .name = "usb_phy_generic",
diff --combined arch/mips/jz4740/pm.c
index bbdd2b801e6e11cf741bad6c474fe1275f6dfacd,9e6c7a2b955fd5492e8511a63978202036878b0c..f9b551f01f420c73e9a259fef7d985b18ecacab2
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
   *    JZ4740 SoC power management support
 - *
 - *  This program is free software; you can redistribute it and/or modify it
 - *  under  the terms of the GNU General        Public License as published by the
 - *  Free Software Foundation;  either version 2 of the License, or (at your
 - *  option) any later version.
 - *
 - *  You should have received a copy of the GNU General Public License along
 - *  with this program; if not, write to the Free Software Foundation, Inc.,
 - *  675 Mass Ave, Cambridge, MA 02139, USA.
 - *
   */
  
  #include <linux/init.h>
  #include <linux/delay.h>
  #include <linux/suspend.h>
  
- #include <asm/mach-jz4740/clock.h>
  static int jz4740_pm_enter(suspend_state_t state)
  {
-       jz4740_clock_suspend();
-       jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP);
        __asm__(".set\tmips3\n\t"
                "wait\n\t"
                ".set\tmips0");
  
-       jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE);
  
-       jz4740_clock_resume();
  
        return 0;
  }
diff --combined arch/mips/jz4740/time.c
index a3260c754e65b06da8c9816dd3811c42dd701df9,32cdde0cad010f95427a348a78aaa9c76dd59d30..cb768e560d8b0d0a7a658e6f775ff195310e9999
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
   *  JZ4740 platform time support
 - *
 - *  This program is free software; you can redistribute it and/or modify it
 - *  under  the terms of the GNU General        Public License as published by the
 - *  Free Software Foundation;  either version 2 of the License, or (at your
 - *  option) any later version.
 - *
 - *  You should have received a copy of the GNU General Public License along
 - *  with this program; if not, write to the Free Software Foundation, Inc.,
 - *  675 Mass Ave, Cambridge, MA 02139, USA.
 - *
   */
  
  #include <linux/clk.h>
  #include <linux/clockchips.h>
  #include <linux/sched_clock.h>
  
- #include <asm/mach-jz4740/clock.h>
  #include <asm/mach-jz4740/irq.h>
  #include <asm/mach-jz4740/timer.h>
  #include <asm/time.h>
  
- #include "clock.h"
  #define TIMER_CLOCKEVENT 0
  #define TIMER_CLOCKSOURCE 1
  
diff --combined drivers/clk/Kconfig
index 7376af25f947f0882c3bdc160099e446f25eed91,cb8f91a1d54fe653031b5d6482e979ebf7054d1b..801fa1cd03217cb54853fcfddcb49ab7c21a1478
@@@ -53,12 -53,13 +53,12 @@@ config COMMON_CLK_MAX948
          This driver supports Maxim 9485 Programmable Audio Clock Generator
  
  config COMMON_CLK_RK808
 -      tristate "Clock driver for RK805/RK808/RK818"
 +      tristate "Clock driver for RK805/RK808/RK809/RK817/RK818"
        depends on MFD_RK808
        ---help---
 -        This driver supports RK805, RK808 and RK818 crystal oscillator clock. These
 -        multi-function devices have two fixed-rate oscillators,
 -        clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
 -        by control register.
 +        This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock.
 +        These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
 +        Clkout1 is always on, Clkout2 can off by control register.
  
  config COMMON_CLK_HI655X
        tristate "Clock driver for Hi655x" if EXPERT
@@@ -90,6 -91,17 +90,17 @@@ config COMMON_CLK_SCP
          This driver uses SCPI Message Protocol to interact with the
          firmware providing all the clock controls.
  
+ config COMMON_CLK_SI5341
+       tristate "Clock driver for SiLabs 5341 and 5340 A/B/C/D devices"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         This driver supports Silicon Labs Si5341 and Si5340 programmable clock
+         generators. Not all features of these chips are currently supported
+         by the driver, in particular it only supports XTAL input. The chip can
+         be pre-programmed to support other configurations and features not yet
+         implemented in the driver.
  config COMMON_CLK_SI5351
        tristate "Clock driver for SiLabs 5351A/B/C"
        depends on I2C
@@@ -214,7 -226,7 +225,7 @@@ config CLK_QORI
  
  config COMMON_CLK_XGENE
        bool "Clock driver for APM XGene SoC"
-       default y
+       default ARCH_XGENE
        depends on ARM64 || COMPILE_TEST
        ---help---
          Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
@@@ -292,10 -304,10 +303,10 @@@ config COMMON_CLK_STM32H
  
  config COMMON_CLK_BD718XX
        tristate "Clock driver for ROHM BD718x7 PMIC"
 -      depends on MFD_ROHM_BD718XX
 +      depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528
        help
 -        This driver supports ROHM BD71837 and ROHM BD71847
 -        PMICs clock gates.
 +        This driver supports ROHM BD71837, ROHM BD71847 and
 +        ROHM BD70528 PMICs clock gates.
  
  config COMMON_CLK_FIXED_MMIO
        bool "Clock driver for Memory Mapped Fixed values"
diff --combined drivers/clk/at91/sckc.c
index 45526f56f1bab91302ee88265dbc1b19576820ef,c0451c9cf33413e797ee8bb915160bff60079936..9bfe9a28294a7ec7f5acbb38f7e21f477355839e
@@@ -1,8 -1,13 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * drivers/clk/at91/sckc.c
   *
   *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
   */
  
  #include <linux/clk-provider.h>
                                 SLOW_CLOCK_FREQ)
  
  #define       AT91_SCKC_CR                    0x00
- #define               AT91_SCKC_RCEN          (1 << 0)
- #define               AT91_SCKC_OSC32EN       (1 << 1)
- #define               AT91_SCKC_OSC32BYP      (1 << 2)
- #define               AT91_SCKC_OSCSEL        (1 << 3)
+ struct clk_slow_bits {
+       u32 cr_rcen;
+       u32 cr_osc32en;
+       u32 cr_osc32byp;
+       u32 cr_oscsel;
+ };
  
  struct clk_slow_osc {
        struct clk_hw hw;
        void __iomem *sckcr;
+       const struct clk_slow_bits *bits;
        unsigned long startup_usec;
  };
  
@@@ -34,6 -43,7 +38,7 @@@
  struct clk_sama5d4_slow_osc {
        struct clk_hw hw;
        void __iomem *sckcr;
+       const struct clk_slow_bits *bits;
        unsigned long startup_usec;
        bool prepared;
  };
@@@ -43,6 -53,7 +48,7 @@@
  struct clk_slow_rc_osc {
        struct clk_hw hw;
        void __iomem *sckcr;
+       const struct clk_slow_bits *bits;
        unsigned long frequency;
        unsigned long accuracy;
        unsigned long startup_usec;
@@@ -53,6 -64,7 +59,7 @@@
  struct clk_sam9x5_slow {
        struct clk_hw hw;
        void __iomem *sckcr;
+       const struct clk_slow_bits *bits;
        u8 parent;
  };
  
@@@ -64,10 -76,10 +71,10 @@@ static int clk_slow_osc_prepare(struct 
        void __iomem *sckcr = osc->sckcr;
        u32 tmp = readl(sckcr);
  
-       if (tmp & (AT91_SCKC_OSC32BYP | AT91_SCKC_OSC32EN))
+       if (tmp & (osc->bits->cr_osc32byp | osc->bits->cr_osc32en))
                return 0;
  
-       writel(tmp | AT91_SCKC_OSC32EN, sckcr);
+       writel(tmp | osc->bits->cr_osc32en, sckcr);
  
        usleep_range(osc->startup_usec, osc->startup_usec + 1);
  
@@@ -80,10 -92,10 +87,10 @@@ static void clk_slow_osc_unprepare(stru
        void __iomem *sckcr = osc->sckcr;
        u32 tmp = readl(sckcr);
  
-       if (tmp & AT91_SCKC_OSC32BYP)
+       if (tmp & osc->bits->cr_osc32byp)
                return;
  
-       writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
+       writel(tmp & ~osc->bits->cr_osc32en, sckcr);
  }
  
  static int clk_slow_osc_is_prepared(struct clk_hw *hw)
        void __iomem *sckcr = osc->sckcr;
        u32 tmp = readl(sckcr);
  
-       if (tmp & AT91_SCKC_OSC32BYP)
+       if (tmp & osc->bits->cr_osc32byp)
                return 1;
  
-       return !!(tmp & AT91_SCKC_OSC32EN);
+       return !!(tmp & osc->bits->cr_osc32en);
  }
  
  static const struct clk_ops slow_osc_ops = {
@@@ -109,7 -121,8 +116,8 @@@ at91_clk_register_slow_osc(void __iome
                           const char *name,
                           const char *parent_name,
                           unsigned long startup,
-                          bool bypass)
+                          bool bypass,
+                          const struct clk_slow_bits *bits)
  {
        struct clk_slow_osc *osc;
        struct clk_hw *hw;
        osc->hw.init = &init;
        osc->sckcr = sckcr;
        osc->startup_usec = startup;
+       osc->bits = bits;
  
        if (bypass)
-               writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
-                      sckcr);
+               writel((readl(sckcr) & ~osc->bits->cr_osc32en) |
+                                       osc->bits->cr_osc32byp, sckcr);
  
        hw = &osc->hw;
        ret = clk_hw_register(NULL, &osc->hw);
        return hw;
  }
  
+ static void at91_clk_unregister_slow_osc(struct clk_hw *hw)
+ {
+       struct clk_slow_osc *osc = to_clk_slow_osc(hw);
+       clk_hw_unregister(hw);
+       kfree(osc);
+ }
  static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
                                                 unsigned long parent_rate)
  {
@@@ -168,7 -190,7 +185,7 @@@ static int clk_slow_rc_osc_prepare(stru
        struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
        void __iomem *sckcr = osc->sckcr;
  
-       writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
+       writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
  
        usleep_range(osc->startup_usec, osc->startup_usec + 1);
  
@@@ -180,14 -202,14 +197,14 @@@ static void clk_slow_rc_osc_unprepare(s
        struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
        void __iomem *sckcr = osc->sckcr;
  
-       writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
+       writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr);
  }
  
  static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
  {
        struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  
-       return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
+       return !!(readl(osc->sckcr) & osc->bits->cr_rcen);
  }
  
  static const struct clk_ops slow_rc_osc_ops = {
@@@ -203,7 -225,8 +220,8 @@@ at91_clk_register_slow_rc_osc(void __io
                              const char *name,
                              unsigned long frequency,
                              unsigned long accuracy,
-                             unsigned long startup)
+                             unsigned long startup,
+                             const struct clk_slow_bits *bits)
  {
        struct clk_slow_rc_osc *osc;
        struct clk_hw *hw;
  
        osc->hw.init = &init;
        osc->sckcr = sckcr;
+       osc->bits = bits;
        osc->frequency = frequency;
        osc->accuracy = accuracy;
        osc->startup_usec = startup;
        return hw;
  }
  
+ static void at91_clk_unregister_slow_rc_osc(struct clk_hw *hw)
+ {
+       struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
+       clk_hw_unregister(hw);
+       kfree(osc);
+ }
  static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
  {
        struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
  
        tmp = readl(sckcr);
  
-       if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
-           (index && (tmp & AT91_SCKC_OSCSEL)))
+       if ((!index && !(tmp & slowck->bits->cr_oscsel)) ||
+           (index && (tmp & slowck->bits->cr_oscsel)))
                return 0;
  
        if (index)
-               tmp |= AT91_SCKC_OSCSEL;
+               tmp |= slowck->bits->cr_oscsel;
        else
-               tmp &= ~AT91_SCKC_OSCSEL;
+               tmp &= ~slowck->bits->cr_oscsel;
  
        writel(tmp, sckcr);
  
@@@ -270,7 -302,7 +297,7 @@@ static u8 clk_sam9x5_slow_get_parent(st
  {
        struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
  
-       return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
+       return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel);
  }
  
  static const struct clk_ops sam9x5_slow_ops = {
@@@ -282,7 -314,8 +309,8 @@@ static struct clk_hw * __ini
  at91_clk_register_sam9x5_slow(void __iomem *sckcr,
                              const char *name,
                              const char **parent_names,
-                             int num_parents)
+                             int num_parents,
+                             const struct clk_slow_bits *bits)
  {
        struct clk_sam9x5_slow *slowck;
        struct clk_hw *hw;
  
        slowck->hw.init = &init;
        slowck->sckcr = sckcr;
-       slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
+       slowck->bits = bits;
+       slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel);
  
        hw = &slowck->hw;
        ret = clk_hw_register(NULL, &slowck->hw);
        return hw;
  }
  
+ static void at91_clk_unregister_sam9x5_slow(struct clk_hw *hw)
+ {
+       struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
+       clk_hw_unregister(hw);
+       kfree(slowck);
+ }
  static void __init at91sam9x5_sckc_register(struct device_node *np,
-                                           unsigned int rc_osc_startup_us)
+                                           unsigned int rc_osc_startup_us,
+                                           const struct clk_slow_bits *bits)
  {
        const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
        void __iomem *regbase = of_iomap(np, 0);
        struct device_node *child = NULL;
        const char *xtal_name;
-       struct clk_hw *hw;
+       struct clk_hw *slow_rc, *slow_osc, *slowck;
        bool bypass;
+       int ret;
  
        if (!regbase)
                return;
  
-       hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768,
-                                          50000000, rc_osc_startup_us);
-       if (IS_ERR(hw))
+       slow_rc = at91_clk_register_slow_rc_osc(regbase, parent_names[0],
+                                               32768, 50000000,
+                                               rc_osc_startup_us, bits);
+       if (IS_ERR(slow_rc))
                return;
  
        xtal_name = of_clk_get_parent_name(np, 0);
                /* DT backward compatibility */
                child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
                if (!child)
-                       return;
+                       goto unregister_slow_rc;
  
                xtal_name = of_clk_get_parent_name(child, 0);
                bypass = of_property_read_bool(child, "atmel,osc-bypass");
        }
  
        if (!xtal_name)
-               return;
-       hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name,
-                                       1200000, bypass);
-       if (IS_ERR(hw))
-               return;
+               goto unregister_slow_rc;
  
-       hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2);
-       if (IS_ERR(hw))
-               return;
+       slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
+                                             xtal_name, 1200000, bypass, bits);
+       if (IS_ERR(slow_osc))
+               goto unregister_slow_rc;
  
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+       slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names,
+                                              2, bits);
+       if (IS_ERR(slowck))
+               goto unregister_slow_osc;
  
        /* DT backward compatibility */
        if (child)
-               of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw);
+               ret = of_clk_add_hw_provider(child, of_clk_hw_simple_get,
+                                            slowck);
+       else
+               ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
+       if (WARN_ON(ret))
+               goto unregister_slowck;
+       return;
+ unregister_slowck:
+       at91_clk_unregister_sam9x5_slow(slowck);
+ unregister_slow_osc:
+       at91_clk_unregister_slow_osc(slow_osc);
+ unregister_slow_rc:
+       at91_clk_unregister_slow_rc_osc(slow_rc);
  }
  
+ static const struct clk_slow_bits at91sam9x5_bits = {
+       .cr_rcen = BIT(0),
+       .cr_osc32en = BIT(1),
+       .cr_osc32byp = BIT(2),
+       .cr_oscsel = BIT(3),
+ };
  static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
  {
-       at91sam9x5_sckc_register(np, 75);
+       at91sam9x5_sckc_register(np, 75, &at91sam9x5_bits);
  }
  CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
               of_at91sam9x5_sckc_setup);
  
  static void __init of_sama5d3_sckc_setup(struct device_node *np)
  {
-       at91sam9x5_sckc_register(np, 500);
+       at91sam9x5_sckc_register(np, 500, &at91sam9x5_bits);
  }
  CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
               of_sama5d3_sckc_setup);
  
+ static const struct clk_slow_bits at91sam9x60_bits = {
+       .cr_osc32en = BIT(1),
+       .cr_osc32byp = BIT(2),
+       .cr_oscsel = BIT(24),
+ };
+ static void __init of_sam9x60_sckc_setup(struct device_node *np)
+ {
+       void __iomem *regbase = of_iomap(np, 0);
+       struct clk_hw_onecell_data *clk_data;
+       struct clk_hw *slow_rc, *slow_osc;
+       const char *xtal_name;
+       const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
+       bool bypass;
+       int ret;
+       if (!regbase)
+               return;
+       slow_rc = clk_hw_register_fixed_rate(NULL, parent_names[0], NULL, 0,
+                                            32768);
+       if (IS_ERR(slow_rc))
+               return;
+       xtal_name = of_clk_get_parent_name(np, 0);
+       if (!xtal_name)
+               goto unregister_slow_rc;
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+       slow_osc = at91_clk_register_slow_osc(regbase, parent_names[1],
+                                             xtal_name, 5000000, bypass,
+                                             &at91sam9x60_bits);
+       if (IS_ERR(slow_osc))
+               goto unregister_slow_rc;
+       clk_data = kzalloc(sizeof(*clk_data) + (2 * sizeof(struct clk_hw *)),
+                          GFP_KERNEL);
+       if (!clk_data)
+               goto unregister_slow_osc;
+       /* MD_SLCK and TD_SLCK. */
+       clk_data->num = 2;
+       clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck",
+                                                     parent_names[0],
+                                                     0, 32768);
+       if (IS_ERR(clk_data->hws[0]))
+               goto clk_data_free;
+       clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
+                                                        parent_names, 2,
+                                                        &at91sam9x60_bits);
+       if (IS_ERR(clk_data->hws[1]))
+               goto unregister_md_slck;
+       ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+       if (WARN_ON(ret))
+               goto unregister_td_slck;
+       return;
+ unregister_td_slck:
+       at91_clk_unregister_sam9x5_slow(clk_data->hws[1]);
+ unregister_md_slck:
+       clk_hw_unregister(clk_data->hws[0]);
+ clk_data_free:
+       kfree(clk_data);
+ unregister_slow_osc:
+       at91_clk_unregister_slow_osc(slow_osc);
+ unregister_slow_rc:
+       clk_hw_unregister(slow_rc);
+ }
+ CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc",
+              of_sam9x60_sckc_setup);
  static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
  {
        struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
         * Assume that if it has already been selected (for example by the
         * bootloader), enough time has aready passed.
         */
-       if ((readl(osc->sckcr) & AT91_SCKC_OSCSEL)) {
+       if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) {
                osc->prepared = true;
                return 0;
        }
@@@ -416,33 -556,35 +551,35 @@@ static const struct clk_ops sama5d4_slo
        .is_prepared = clk_sama5d4_slow_osc_is_prepared,
  };
  
+ static const struct clk_slow_bits at91sama5d4_bits = {
+       .cr_oscsel = BIT(3),
+ };
  static void __init of_sama5d4_sckc_setup(struct device_node *np)
  {
        void __iomem *regbase = of_iomap(np, 0);
-       struct clk_hw *hw;
+       struct clk_hw *slow_rc, *slowck;
        struct clk_sama5d4_slow_osc *osc;
        struct clk_init_data init;
        const char *xtal_name;
        const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
-       bool bypass;
        int ret;
  
        if (!regbase)
                return;
  
-       hw = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
-                                                     NULL, 0, 32768,
-                                                     250000000);
-       if (IS_ERR(hw))
+       slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL,
+                                                          parent_names[0],
+                                                          NULL, 0, 32768,
+                                                          250000000);
+       if (IS_ERR(slow_rc))
                return;
  
        xtal_name = of_clk_get_parent_name(np, 0);
  
-       bypass = of_property_read_bool(np, "atmel,osc-bypass");
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
        if (!osc)
-               return;
+               goto unregister_slow_rc;
  
        init.name = parent_names[1];
        init.ops = &sama5d4_slow_osc_ops;
        osc->hw.init = &init;
        osc->sckcr = regbase;
        osc->startup_usec = 1200000;
+       osc->bits = &at91sama5d4_bits;
  
-       if (bypass)
-               writel((readl(regbase) | AT91_SCKC_OSC32BYP), regbase);
-       hw = &osc->hw;
        ret = clk_hw_register(NULL, &osc->hw);
-       if (ret) {
-               kfree(osc);
-               return;
-       }
-       hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2);
-       if (IS_ERR(hw))
-               return;
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+       if (ret)
+               goto free_slow_osc_data;
+       slowck = at91_clk_register_sam9x5_slow(regbase, "slowck",
+                                              parent_names, 2,
+                                              &at91sama5d4_bits);
+       if (IS_ERR(slowck))
+               goto unregister_slow_osc;
+       ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
+       if (WARN_ON(ret))
+               goto unregister_slowck;
+       return;
+ unregister_slowck:
+       at91_clk_unregister_sam9x5_slow(slowck);
+ unregister_slow_osc:
+       clk_hw_unregister(&osc->hw);
+ free_slow_osc_data:
+       kfree(osc);
+ unregister_slow_rc:
+       clk_hw_unregister(slow_rc);
  }
  CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
               of_sama5d4_sckc_setup);
diff --combined drivers/clk/bcm/Kconfig
index 29ee7b776cd463bdd7f58dbd933ac6b956249614,ccef3edfde7a5ccf5810008a6610b0ddd6db057d..8c83977a7dc425b07d2dd262c7599ee4cd23a422
@@@ -1,4 -1,12 +1,13 @@@
 +# SPDX-License-Identifier: GPL-2.0-only
+ config CLK_BCM2835
+       bool "Broadcom BCM2835 clock support"
+       depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST
+       depends on COMMON_CLK
+       default ARCH_BCM2835 || ARCH_BRCMSTB
+       help
+         Enable common clock framework support for Broadcom BCM2835
+         SoCs.
  config CLK_BCM_63XX
        bool "Broadcom BCM63xx clock support"
        depends on ARCH_BCM_63XX || COMPILE_TEST
          Enable common clock framework support for Broadcom BCM63xx DSL SoCs
          based on the ARM architecture
  
+ config CLK_BCM_63XX_GATE
+       bool "Broadcom BCM63xx gated clock support"
+       depends on BMIPS_GENERIC || COMPILE_TEST
+       default BMIPS_GENERIC
+       help
+         Enable common clock framework support for Broadcom BCM63xx DSL SoCs
+         based on the MIPS architecture
  config CLK_BCM_KONA
        bool "Broadcom Kona CCU clock support"
        depends on ARCH_BCM_MOBILE || COMPILE_TEST
@@@ -64,3 -80,10 +81,10 @@@ config CLK_BCM_S
        default ARCH_BCM_IPROC
        help
          Enable common clock framework support for the Broadcom Stingray SoC
+ config CLK_RASPBERRYPI
+       tristate "Raspberry Pi firmware based clock support"
+       depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
+       help
+         Enable common clock framework support for Raspberry Pi's firmware
+         dependent clocks
index 0443dfc827941a80cfd869f95e5cfa3af48b0e67,476d29c013e5bdcac571ad65911c65215da18e37..239102e37e2ffa3d68f726eae035275543515b69
@@@ -1,10 -1,13 +1,10 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * TI CDCE706 programmable 3-PLL clock synthesizer driver
   *
   * Copyright (c) 2014 Cadence Design Systems Inc.
   *
   * Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
   */
  
  #include <linux/clk.h>
@@@ -630,7 -633,7 +630,7 @@@ of_clk_cdce_get(struct of_phandle_args 
  static int cdce706_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
  {
-       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct i2c_adapter *adapter = client->adapter;
        struct cdce706_dev_data *cdce;
        int ret;
  
diff --combined drivers/clk/clk-pwm.c
index 5f0490b8f6cb819c72ddee9469e19d232d874afc,c0cd6a0ff7f86fea3c45fad2707802f6e70b2d2e..87fe0b0e01a3d6ef980ea32ceea02d44a90cb2f7
@@@ -1,7 -1,10 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (C) 2014 Philipp Zabel, Pengutronix
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * PWM (mis)used as clock output
   */
  #include <linux/clk-provider.h>
@@@ -44,10 -47,24 +44,24 @@@ static unsigned long clk_pwm_recalc_rat
        return clk_pwm->fixed_rate;
  }
  
+ static int clk_pwm_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty)
+ {
+       struct clk_pwm *clk_pwm = to_clk_pwm(hw);
+       struct pwm_state state;
+       pwm_get_state(clk_pwm->pwm, &state);
+       duty->num = state.duty_cycle;
+       duty->den = state.period;
+       return 0;
+ }
  static const struct clk_ops clk_pwm_ops = {
        .prepare = clk_pwm_prepare,
        .unprepare = clk_pwm_unprepare,
        .recalc_rate = clk_pwm_recalc_rate,
+       .get_duty_cycle = clk_pwm_get_duty_cycle,
  };
  
  static int clk_pwm_probe(struct platform_device *pdev)
diff --combined drivers/clk/clk-qoriq.c
index dd93d3acc67d8228df65519ff8ae15b6b0dbc9f8,0dfac393588bd78f2d5e559af55aa870b260a261..07f3b252f3e0cb3118582a184d660ea83d4b8ada
@@@ -1,7 -1,10 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright 2013 Freescale Semiconductor, Inc.
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * clock driver for Freescale QorIQ SoCs.
   */
  
@@@ -634,6 -637,17 +634,17 @@@ static const struct clockgen_chipinfo c
                .pll_mask = 0x37,
                .flags = CG_VER3 | CG_LITTLE_ENDIAN,
        },
+       {
+               .compat = "fsl,lx2160a-clockgen",
+               .cmux_groups = {
+                       &clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+               },
+               .cmux_to_group = {
+                       0, 0, 0, 0, 1, 1, 1, 1, -1
+               },
+               .pll_mask = 0x37,
+               .flags = CG_VER3 | CG_LITTLE_ENDIAN,
+       },
        {
                .compat = "fsl,p2041-clockgen",
                .guts_compat = "fsl,qoriq-device-config-1.0",
@@@ -1493,6 -1507,7 +1504,7 @@@ CLK_OF_DECLARE(qoriq_clockgen_ls1043a, 
  CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_lx2160a, "fsl,lx2160a-clockgen", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_p2041, "fsl,p2041-clockgen", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_p3041, "fsl,p3041-clockgen", clockgen_init);
  CLK_OF_DECLARE(qoriq_clockgen_p4080, "fsl,p4080-clockgen", clockgen_init);
diff --combined drivers/clk/clk.c
index 87b410d6e51def62a75417e93304f7997becfa4b,1d54e2e91879180020149a96a586bc4a93018be6..c0990703ce5403c1092bda6d982c56dffd70e6a0
@@@ -368,7 -368,7 +368,7 @@@ static struct clk_core *clk_core_get(st
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct device_node *np = core->of_node;
  
 -      if (np && index >= 0)
 +      if (np && (name || index >= 0))
                hw = of_clk_get_hw(np, index, name);
  
        /*
@@@ -1324,10 -1324,7 +1324,7 @@@ static void clk_core_init_rate_req(stru
  
  static bool clk_core_can_round(struct clk_core * const core)
  {
-       if (core->ops->determine_rate || core->ops->round_rate)
-               return true;
-       return false;
+       return core->ops->determine_rate || core->ops->round_rate;
  }
  
  static int clk_core_round_rate_nolock(struct clk_core *core,
@@@ -2194,7 -2191,7 +2191,7 @@@ int clk_set_rate(struct clk *clk, unsig
  EXPORT_SYMBOL_GPL(clk_set_rate);
  
  /**
-  * clk_set_rate_exclusive - specify a new rate get exclusive control
+  * clk_set_rate_exclusive - specify a new rate and get exclusive control
   * @clk: the clk whose rate is being changed
   * @rate: the new rate for clk
   *
   * within a critical section
   *
   * This can be used initially to ensure that at least 1 consumer is
-  * statisfied when several consumers are competing for exclusivity over the
+  * satisfied when several consumers are competing for exclusivity over the
   * same clock provider.
   *
   * The exclusivity is not applied if setting the rate failed.
@@@ -2997,20 -2994,65 +2994,65 @@@ static int clk_flags_show(struct seq_fi
  }
  DEFINE_SHOW_ATTRIBUTE(clk_flags);
  
+ static void possible_parent_show(struct seq_file *s, struct clk_core *core,
+                                unsigned int i, char terminator)
+ {
+       struct clk_core *parent;
+       /*
+        * Go through the following options to fetch a parent's name.
+        *
+        * 1. Fetch the registered parent clock and use its name
+        * 2. Use the global (fallback) name if specified
+        * 3. Use the local fw_name if provided
+        * 4. Fetch parent clock's clock-output-name if DT index was set
+        *
+        * This may still fail in some cases, such as when the parent is
+        * specified directly via a struct clk_hw pointer, but it isn't
+        * registered (yet).
+        */
+       parent = clk_core_get_parent_by_index(core, i);
+       if (parent)
+               seq_printf(s, "%s", parent->name);
+       else if (core->parents[i].name)
+               seq_printf(s, "%s", core->parents[i].name);
+       else if (core->parents[i].fw_name)
+               seq_printf(s, "<%s>(fw)", core->parents[i].fw_name);
+       else if (core->parents[i].index >= 0)
+               seq_printf(s, "%s",
+                          of_clk_get_parent_name(core->of_node,
+                                                 core->parents[i].index));
+       else
+               seq_puts(s, "(missing)");
+       seq_putc(s, terminator);
+ }
  static int possible_parents_show(struct seq_file *s, void *data)
  {
        struct clk_core *core = s->private;
        int i;
  
        for (i = 0; i < core->num_parents - 1; i++)
-               seq_printf(s, "%s ", core->parents[i].name);
+               possible_parent_show(s, core, i, ' ');
  
-       seq_printf(s, "%s\n", core->parents[i].name);
+       possible_parent_show(s, core, i, '\n');
  
        return 0;
  }
  DEFINE_SHOW_ATTRIBUTE(possible_parents);
  
+ static int current_parent_show(struct seq_file *s, void *data)
+ {
+       struct clk_core *core = s->private;
+       if (core->parent)
+               seq_printf(s, "%s\n", core->parent->name);
+       return 0;
+ }
+ DEFINE_SHOW_ATTRIBUTE(current_parent);
  static int clk_duty_cycle_show(struct seq_file *s, void *data)
  {
        struct clk_core *core = s->private;
@@@ -3043,6 -3085,10 +3085,10 @@@ static void clk_debug_create_one(struc
        debugfs_create_file("clk_duty_cycle", 0444, root, core,
                            &clk_duty_cycle_fops);
  
+       if (core->num_parents > 0)
+               debugfs_create_file("clk_parent", 0444, root, core,
+                                   &current_parent_fops);
        if (core->num_parents > 1)
                debugfs_create_file("clk_possible_parents", 0444, root, core,
                                    &possible_parents_fops);
@@@ -4038,6 -4084,7 +4084,7 @@@ struct of_clk_provider 
        void *data;
  };
  
+ extern struct of_device_id __clk_of_table;
  static const struct of_device_id __clk_of_table_sentinel
        __used __section(__clk_of_table_end);
  
index 7b35a11238ca7d8c990afd291cc24d657df7542f,51f75500ab85244d662cd45fba54b3db61119714..25c863da32c7024fff29973f990aaae99d815e68
@@@ -1,7 -1,13 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2012 Freescale Semiconductor, Inc.
   * Copyright 2012 Linaro Ltd.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk.h>
@@@ -72,13 -78,14 +72,14 @@@ static const struct clk_ops clk_busy_di
        .set_rate = clk_busy_divider_set_rate,
  };
  
- struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
+ struct clk_hw *imx_clk_hw_busy_divider(const char *name, const char *parent_name,
                                 void __iomem *reg, u8 shift, u8 width,
                                 void __iomem *busy_reg, u8 busy_shift)
  {
        struct clk_busy_divider *busy;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        busy = kzalloc(sizeof(*busy), GFP_KERNEL);
        if (!busy)
  
        busy->div.hw.init = &init;
  
-       clk = clk_register(NULL, &busy->div.hw);
-       if (IS_ERR(clk))
+       hw = &busy->div.hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(busy);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
  
  struct clk_busy_mux {
@@@ -146,13 -157,14 +151,14 @@@ static const struct clk_ops clk_busy_mu
        .set_parent = clk_busy_mux_set_parent,
  };
  
- struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
+ struct clk_hw *imx_clk_hw_busy_mux(const char *name, void __iomem *reg, u8 shift,
                             u8 width, void __iomem *busy_reg, u8 busy_shift,
                             const char * const *parent_names, int num_parents)
  {
        struct clk_busy_mux *busy;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        busy = kzalloc(sizeof(*busy), GFP_KERNEL);
        if (!busy)
  
        busy->mux.hw.init = &init;
  
-       clk = clk_register(NULL, &busy->mux.hw);
-       if (IS_ERR(clk))
+       hw = &busy->mux.hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(busy);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index 00d026eb7891d502fe43336b4584f5858c6ea950,a7b90059716edff1e31921fc6c2d9881643576c2..cb182bec79bacfc84e26d46d13ac06cce0c28da4
@@@ -1,6 -1,12 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk.h>
@@@ -69,13 -75,14 +69,14 @@@ static const struct clk_ops clk_cpu_op
        .set_rate       = clk_cpu_set_rate,
  };
  
- struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+ struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
                struct clk *div, struct clk *mux, struct clk *pll,
                struct clk *step)
  {
        struct clk_cpu *cpu;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
        if (!cpu)
        init.num_parents = 1;
  
        cpu->hw.init = &init;
+       hw = &cpu->hw;
  
-       clk = clk_register(NULL, &cpu->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(cpu);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index bab46c6fd3db53a9f8e73c1547371a57da7131a4,287539baa301348b341956651d80a6dea289a59a..4b17b91504edd591f1f2c2355d177c26e4cc83ce
@@@ -1,6 -1,12 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2013 Freescale Semiconductor, Inc.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk-provider.h>
@@@ -85,13 -91,14 +85,14 @@@ static const struct clk_ops clk_fixup_d
        .set_rate = clk_fixup_div_set_rate,
  };
  
- struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
+ struct clk_hw *imx_clk_hw_fixup_divider(const char *name, const char *parent,
                                  void __iomem *reg, u8 shift, u8 width,
                                  void (*fixup)(u32 *val))
  {
        struct clk_fixup_div *fixup_div;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        if (!fixup)
                return ERR_PTR(-EINVAL);
        fixup_div->ops = &clk_divider_ops;
        fixup_div->fixup = fixup;
  
-       clk = clk_register(NULL, &fixup_div->divider.hw);
-       if (IS_ERR(clk))
+       hw = &fixup_div->divider.hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(fixup_div);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index 1aa3e8d9abf3d1ce53540486f7f045b03a57f492,f3c4ec2c26707ce0f4b0d56c80c1df044f8aa867..b569d919c64563f4ee7dc11e3343bea9d7b7cbee
@@@ -1,6 -1,12 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2013 Freescale Semiconductor, Inc.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk-provider.h>
@@@ -63,13 -69,14 +63,14 @@@ static const struct clk_ops clk_fixup_m
        .set_parent = clk_fixup_mux_set_parent,
  };
  
- struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
+ struct clk_hw *imx_clk_hw_fixup_mux(const char *name, void __iomem *reg,
                              u8 shift, u8 width, const char * const *parents,
                              int num_parents, void (*fixup)(u32 *val))
  {
        struct clk_fixup_mux *fixup_mux;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        if (!fixup)
                return ERR_PTR(-EINVAL);
        fixup_mux->ops = &clk_mux_ops;
        fixup_mux->fixup = fixup;
  
-       clk = clk_register(NULL, &fixup_mux->mux.hw);
-       if (IS_ERR(clk))
+       hw = &fixup_mux->mux.hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(fixup_mux);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index cffa4966568d1fbed0ea156bfc157fb9b88ca41d,7bd9f140970104d97a06f608656fd398869eadbd..77342893bb719747ef1b50a40a8c5a88e554ca4d
@@@ -1,6 -1,9 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright 2014 Freescale Semiconductor, Inc.
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
   */
  
  #include <linux/clk-provider.h>
@@@ -55,13 -58,14 +55,14 @@@ static const struct clk_ops clk_gate_ex
        .is_enabled = clk_gate_exclusive_is_enabled,
  };
  
- struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
+ struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
         void __iomem *reg, u8 shift, u32 exclusive_mask)
  {
        struct clk_gate_exclusive *exgate;
        struct clk_gate *gate;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        if (exclusive_mask == 0)
                return ERR_PTR(-EINVAL);
        gate->hw.init = &init;
        exgate->exclusive_mask = exclusive_mask;
  
-       clk = clk_register(NULL, &gate->hw);
-       if (IS_ERR(clk))
-               kfree(exgate);
+       hw = &gate->hw;
  
-       return clk;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
+               kfree(gate);
+               return ERR_PTR(ret);
+       }
+       return hw;
  }
index ec08fda547a36d6d45de268b558076930abbcc6c,14551fd36ae5ecafd50a9ccfc3789f2c3d603a4a..7d44ce8148063976a0fd55710786b7b67a1b90a7
@@@ -1,8 -1,11 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
   * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * Gated clock implementation
   */
  
@@@ -122,15 -125,16 +122,16 @@@ static const struct clk_ops clk_gate2_o
        .is_enabled = clk_gate2_is_enabled,
  };
  
- struct clk *clk_register_gate2(struct device *dev, const char *name,
+ struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 bit_idx, u8 cgr_val,
                u8 clk_gate2_flags, spinlock_t *lock,
                unsigned int *share_count)
  {
        struct clk_gate2 *gate;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        gate = kzalloc(sizeof(struct clk_gate2), GFP_KERNEL);
        if (!gate)
        init.num_parents = parent_name ? 1 : 0;
  
        gate->hw.init = &init;
+       hw = &gate->hw;
  
-       clk = clk_register(dev, &gate->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(gate);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index d5de733f336ed1184cf43b8da2b9dc4fe7b03e5c,466561fb8925e97ee8ddcb1b3c08c0bafc90e261..60f2de851f39fcfe36305fbc9a90c11ffb92800a
@@@ -1,13 -1,20 +1,14 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2011-2013 Freescale Semiconductor, Inc.
   * Copyright 2011 Linaro Ltd.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/init.h>
  #include <linux/types.h>
  #include <linux/clk.h>
  #include <linux/clkdev.h>
+ #include <linux/clk-provider.h>
  #include <linux/err.h>
  #include <linux/io.h>
  #include <linux/of.h>
@@@ -87,8 -94,8 +88,8 @@@ static const char *pll5_bypass_sels[] 
  static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
  static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
  
- static struct clk *clk[IMX6QDL_CLK_END];
- static struct clk_onecell_data clk_data;
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
  
  static struct clk_div_table clk_enet_ref_table[] = {
        { .val = 0, .div = 20, },
@@@ -138,12 -145,13 +139,13 @@@ static inline int clk_on_imx6dl(void
        return of_machine_is_compatible("fsl,imx6dl");
  }
  
- static struct clk ** const uart_clks[] __initconst = {
-       &clk[IMX6QDL_CLK_UART_IPG],
-       &clk[IMX6QDL_CLK_UART_SERIAL],
-       NULL
+ static const int uart_clk_ids[] __initconst = {
+       IMX6QDL_CLK_UART_IPG,
+       IMX6QDL_CLK_UART_SERIAL,
  };
  
+ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata;
  static int ldb_di_sel_by_clock_id(int clock_id)
  {
        switch (clock_id) {
@@@ -254,25 -262,14 +256,14 @@@ static bool pll6_bypassed(struct device
        return false;
  }
  
- #define CCM_CCDR              0x04
  #define CCM_CCSR              0x0c
  #define CCM_CS2CDR            0x2c
  
- #define CCDR_MMDC_CH1_MASK            BIT(16)
  #define CCSR_PLL3_SW_CLK_SEL          BIT(0)
  
  #define CS2CDR_LDB_DI0_CLK_SEL_SHIFT  9
  #define CS2CDR_LDB_DI1_CLK_SEL_SHIFT  12
  
- static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
- {
-       unsigned int reg;
-       reg = readl_relaxed(ccm_base + CCM_CCDR);
-       reg |= CCDR_MMDC_CH1_MASK;
-       writel_relaxed(reg, ccm_base + CCM_CCDR);
- }
  /*
   * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
   * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
@@@ -282,14 -279,8 +273,8 @@@ static void mmdc_ch1_disable(void __iom
  {
        unsigned int reg;
  
-       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
-                      clk[IMX6QDL_CLK_PLL3_USB_OTG]);
-       /*
-        * Handshake with mmdc_ch1 module must be masked when changing
-        * periph2_clk_sel.
-        */
-       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+       clk_set_parent(hws[IMX6QDL_CLK_PERIPH2_CLK2_SEL]->clk,
+                      hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
  
        /* Disable pll3_sw_clk by selecting the bypass clock source */
        reg = readl_relaxed(ccm_base + CCM_CCSR);
@@@ -305,8 -296,6 +290,6 @@@ static void mmdc_ch1_reenable(void __io
        reg = readl_relaxed(ccm_base + CCM_CCSR);
        reg &= ~CCSR_PLL3_SW_CLK_SEL;
        writel_relaxed(reg, ccm_base + CCM_CCSR);
-       clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
  }
  
  /*
@@@ -365,8 -354,8 +348,8 @@@ static void init_ldb_clks(struct device
  
                /* Only switch to or from pll2_pfd2_396m if it is disabled */
                if ((sel[i][0] == 2 || sel[i][3] == 2) &&
-                   (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
-                    clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+                   (clk_get_parent(hws[IMX6QDL_CLK_PERIPH_PRE]->clk) ==
+                    hws[IMX6QDL_CLK_PLL2_PFD2_396M]->clk)) {
                        pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
                               i);
                        sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
@@@ -418,8 -407,8 +401,8 @@@ static void disable_anatop_clocks(void 
        /* Make sure PLL2 PFDs 0-2 are gated */
        reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
        /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
-       if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
-           clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+       if (clk_get_parent(hws[IMX6QDL_CLK_PERIPH_PRE]->clk) ==
+           hws[IMX6QDL_CLK_PLL2_PFD2_396M]->clk)
                reg |= PFD0_CLKGATE | PFD1_CLKGATE;
        else
                reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
        writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
  }
  
+ static struct clk_hw * __init imx6q_obtain_fixed_clk_hw(struct device_node *np,
+                                                       const char *name,
+                                                       unsigned long rate)
+ {
+       struct clk *clk = of_clk_get_by_name(np, name);
+       struct clk_hw *hw;
+       if (IS_ERR(clk))
+               hw = imx_obtain_fixed_clock_hw(name, rate);
+       else
+               hw = __clk_get_hw(clk);
+       return hw;
+ }
  static void __init imx6q_clocks_init(struct device_node *ccm_node)
  {
        struct device_node *np;
        void __iomem *anatop_base, *base;
        int ret;
+       int i;
+       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+                                         IMX6QDL_CLK_END), GFP_KERNEL);
+       if (WARN_ON(!clk_hw_data))
+               return;
  
-       clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
-       clk[IMX6QDL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
-       if (IS_ERR(clk[IMX6QDL_CLK_CKIL]))
-               clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
-       clk[IMX6QDL_CLK_CKIH] = of_clk_get_by_name(ccm_node, "ckih1");
-       if (IS_ERR(clk[IMX6QDL_CLK_CKIH]))
-               clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0);
-       clk[IMX6QDL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
-       if (IS_ERR(clk[IMX6QDL_CLK_OSC]))
-               clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
+       clk_hw_data->num = IMX6QDL_CLK_END;
+       hws = clk_hw_data->hws;
  
-       /* Clock source from external clock via CLK1/2 PADs */
-       clk[IMX6QDL_CLK_ANACLK1] = of_clk_get_by_name(ccm_node, "anaclk1");
-       if (IS_ERR(clk[IMX6QDL_CLK_ANACLK1]))
-               clk[IMX6QDL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
+       hws[IMX6QDL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
  
-       clk[IMX6QDL_CLK_ANACLK2] = of_clk_get_by_name(ccm_node, "anaclk2");
-       if (IS_ERR(clk[IMX6QDL_CLK_ANACLK2]))
-               clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
+       hws[IMX6QDL_CLK_CKIL] = imx6q_obtain_fixed_clk_hw(ccm_node, "ckil", 0);
+       hws[IMX6QDL_CLK_CKIH] = imx6q_obtain_fixed_clk_hw(ccm_node, "ckih1", 0);
+       hws[IMX6QDL_CLK_OSC] = imx6q_obtain_fixed_clk_hw(ccm_node, "osc", 0);
+       /* Clock source from external clock via CLK1/2 PADs */
+       hws[IMX6QDL_CLK_ANACLK1] = imx6q_obtain_fixed_clk_hw(ccm_node, "anaclk1", 0);
+       hws[IMX6QDL_CLK_ANACLK2] = imx6q_obtain_fixed_clk_hw(ccm_node, "anaclk2", 0);
  
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
        anatop_base = base = of_iomap(np, 0);
                video_div_table[3].div = 1;
        }
  
-       clk[IMX6QDL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clk[IMX6QDL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src", base + 0x00, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL2_BYPASS_SRC] = imx_clk_hw_mux("pll2_bypass_src", base + 0x30, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL3_BYPASS_SRC] = imx_clk_hw_mux("pll3_bypass_src", base + 0x10, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL4_BYPASS_SRC] = imx_clk_hw_mux("pll4_bypass_src", base + 0x70, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL5_BYPASS_SRC] = imx_clk_hw_mux("pll5_bypass_src", base + 0xa0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL6_BYPASS_SRC] = imx_clk_hw_mux("pll6_bypass_src", base + 0xe0, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6QDL_PLL7_BYPASS_SRC] = imx_clk_hw_mux("pll7_bypass_src", base + 0x20, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
  
        /*                                    type               name    parent_name        base         div_mask */
-       clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
-       clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
-       clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
-       clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
-       clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
-       clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
-       clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
-       clk[IMX6QDL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_CLK_PLL1] = imx_clk_hw_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       hws[IMX6QDL_CLK_PLL2] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       hws[IMX6QDL_CLK_PLL3] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       hws[IMX6QDL_CLK_PLL4] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       hws[IMX6QDL_CLK_PLL5] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       hws[IMX6QDL_CLK_PLL6] = imx_clk_hw_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       hws[IMX6QDL_CLK_PLL7] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
+       hws[IMX6QDL_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL4_BYPASS] = imx_clk_hw_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
  
        /* Do not bypass PLLs initially */
-       clk_set_parent(clk[IMX6QDL_PLL1_BYPASS], clk[IMX6QDL_CLK_PLL1]);
-       clk_set_parent(clk[IMX6QDL_PLL2_BYPASS], clk[IMX6QDL_CLK_PLL2]);
-       clk_set_parent(clk[IMX6QDL_PLL3_BYPASS], clk[IMX6QDL_CLK_PLL3]);
-       clk_set_parent(clk[IMX6QDL_PLL4_BYPASS], clk[IMX6QDL_CLK_PLL4]);
-       clk_set_parent(clk[IMX6QDL_PLL5_BYPASS], clk[IMX6QDL_CLK_PLL5]);
-       clk_set_parent(clk[IMX6QDL_PLL6_BYPASS], clk[IMX6QDL_CLK_PLL6]);
-       clk_set_parent(clk[IMX6QDL_PLL7_BYPASS], clk[IMX6QDL_CLK_PLL7]);
-       clk[IMX6QDL_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
-       clk[IMX6QDL_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
-       clk[IMX6QDL_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
-       clk[IMX6QDL_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
-       clk[IMX6QDL_CLK_PLL5_VIDEO]    = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
-       clk[IMX6QDL_CLK_PLL6_ENET]     = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
-       clk[IMX6QDL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+       clk_set_parent(hws[IMX6QDL_PLL1_BYPASS]->clk, hws[IMX6QDL_CLK_PLL1]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL2_BYPASS]->clk, hws[IMX6QDL_CLK_PLL2]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL3_BYPASS]->clk, hws[IMX6QDL_CLK_PLL3]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL4_BYPASS]->clk, hws[IMX6QDL_CLK_PLL4]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL5_BYPASS]->clk, hws[IMX6QDL_CLK_PLL5]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL6_BYPASS]->clk, hws[IMX6QDL_CLK_PLL6]->clk);
+       clk_set_parent(hws[IMX6QDL_PLL7_BYPASS]->clk, hws[IMX6QDL_CLK_PLL7]->clk);
+       hws[IMX6QDL_CLK_PLL1_SYS]      = imx_clk_hw_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       hws[IMX6QDL_CLK_PLL2_BUS]      = imx_clk_hw_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
+       hws[IMX6QDL_CLK_PLL3_USB_OTG]  = imx_clk_hw_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
+       hws[IMX6QDL_CLK_PLL4_AUDIO]    = imx_clk_hw_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
+       hws[IMX6QDL_CLK_PLL5_VIDEO]    = imx_clk_hw_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
+       hws[IMX6QDL_CLK_PLL6_ENET]     = imx_clk_hw_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
+       hws[IMX6QDL_CLK_PLL7_USB_HOST] = imx_clk_hw_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
  
        /*
         * Bit 20 is the reserved and read-only bit, we do this only for:
         * - Keep refcount when do usbphy clk_enable/disable, in that case,
         * the clk framework may need to enable/disable usbphy's parent
         */
-       clk[IMX6QDL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
-       clk[IMX6QDL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+       hws[IMX6QDL_CLK_USBPHY1] = imx_clk_hw_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+       hws[IMX6QDL_CLK_USBPHY2] = imx_clk_hw_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
  
        /*
         * usbphy*_gate needs to be on after system boots up, and software
         * never needs to control it anymore.
         */
-       clk[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
-       clk[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+       hws[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_hw_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+       hws[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_hw_gate("usbphy2_gate", "dummy", base + 0x20, 6);
  
        /*
         * The ENET PLL is special in that is has multiple outputs with
         *
         */
        if (!pll6_bypassed(ccm_node)) {
-               clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
-               clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
-               clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+               hws[IMX6QDL_CLK_SATA_REF] = imx_clk_hw_fixed_factor("sata_ref", "pll6_enet", 1, 5);
+               hws[IMX6QDL_CLK_PCIE_REF] = imx_clk_hw_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+               hws[IMX6QDL_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
                                                base + 0xe0, 0, 2, 0, clk_enet_ref_table,
                                                &imx_ccm_lock);
        } else {
-               clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 1);
-               clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 1);
-               clk[IMX6QDL_CLK_ENET_REF] = imx_clk_fixed_factor("enet_ref", "pll6_enet", 1, 1);
+               hws[IMX6QDL_CLK_SATA_REF] = imx_clk_hw_fixed_factor("sata_ref", "pll6_enet", 1, 1);
+               hws[IMX6QDL_CLK_PCIE_REF] = imx_clk_hw_fixed_factor("pcie_ref", "pll6_enet", 1, 1);
+               hws[IMX6QDL_CLK_ENET_REF] = imx_clk_hw_fixed_factor("enet_ref", "pll6_enet", 1, 1);
        }
  
-       clk[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
-       clk[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
+       hws[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_hw_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
+       hws[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_hw_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
  
-       clk[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
-       clk[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+       hws[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_hw_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+       hws[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_hw_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
  
        /*
         * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
         * it.
         */
        writel(readl(base + 0x160) & ~0x3c00, base + 0x160);
-       clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
-       clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
+       hws[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_hw_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
+       hws[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_hw_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
  
-       clk[IMX6QDL_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10));
-       clk[IMX6QDL_CLK_LVDS2_IN] = imx_clk_gate_exclusive("lvds2_in", "anaclk2", base + 0x160, 13, BIT(11));
+       hws[IMX6QDL_CLK_LVDS1_IN] = imx_clk_hw_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10));
+       hws[IMX6QDL_CLK_LVDS2_IN] = imx_clk_hw_gate_exclusive("lvds2_in", "anaclk2", base + 0x160, 13, BIT(11));
  
        /*                                            name              parent_name        reg       idx */
-       clk[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
-       clk[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
-       clk[IMX6QDL_CLK_PLL2_PFD2_396M] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
-       clk[IMX6QDL_CLK_PLL3_PFD0_720M] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
-       clk[IMX6QDL_CLK_PLL3_PFD1_540M] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
-       clk[IMX6QDL_CLK_PLL3_PFD2_508M] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
-       clk[IMX6QDL_CLK_PLL3_PFD3_454M] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
+       hws[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
+       hws[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
+       hws[IMX6QDL_CLK_PLL2_PFD2_396M] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
+       hws[IMX6QDL_CLK_PLL3_PFD0_720M] = imx_clk_hw_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+       hws[IMX6QDL_CLK_PLL3_PFD1_540M] = imx_clk_hw_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+       hws[IMX6QDL_CLK_PLL3_PFD2_508M] = imx_clk_hw_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
+       hws[IMX6QDL_CLK_PLL3_PFD3_454M] = imx_clk_hw_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
  
        /*                                                name         parent_name     mult div */
-       clk[IMX6QDL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
-       clk[IMX6QDL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
-       clk[IMX6QDL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
-       clk[IMX6QDL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
-       clk[IMX6QDL_CLK_TWD]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
-       clk[IMX6QDL_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",    "osc",            1, 8);
-       clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
+       hws[IMX6QDL_CLK_PLL2_198M] = imx_clk_hw_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+       hws[IMX6QDL_CLK_PLL3_120M] = imx_clk_hw_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
+       hws[IMX6QDL_CLK_PLL3_80M]  = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
+       hws[IMX6QDL_CLK_PLL3_60M]  = imx_clk_hw_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
+       hws[IMX6QDL_CLK_TWD]       = imx_clk_hw_fixed_factor("twd",       "arm",            1, 2);
+       hws[IMX6QDL_CLK_GPT_3M]    = imx_clk_hw_fixed_factor("gpt_3m",    "osc",            1, 8);
+       hws[IMX6QDL_CLK_VIDEO_27M] = imx_clk_hw_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
        if (clk_on_imx6dl() || clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1);
-               clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
+               hws[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_hw_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1);
+               hws[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_hw_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
        }
  
-       clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
-       clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+       hws[IMX6QDL_CLK_PLL4_POST_DIV] = clk_hw_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       hws[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+       hws[IMX6QDL_CLK_PLL5_POST_DIV] = clk_hw_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       hws[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
  
        np = ccm_node;
        base = of_iomap(np, 0);
        WARN_ON(!base);
  
        /*                                              name                reg       shift width parent_names     num_parents */
-       clk[IMX6QDL_CLK_STEP]             = imx_clk_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
-       clk[IMX6QDL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
-       clk[IMX6QDL_CLK_PERIPH_PRE]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-       clk[IMX6QDL_CLK_PERIPH2_PRE]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-       clk[IMX6QDL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
-       clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
-       clk[IMX6QDL_CLK_AXI_SEL]          = imx_clk_mux("axi_sel",          base + 0x14, 6,  2, axi_sels,          ARRAY_SIZE(axi_sels));
-       clk[IMX6QDL_CLK_ESAI_SEL]         = imx_clk_mux("esai_sel",         base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
-       clk[IMX6QDL_CLK_ASRC_SEL]         = imx_clk_mux("asrc_sel",         base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
-       clk[IMX6QDL_CLK_SPDIF_SEL]        = imx_clk_mux("spdif_sel",        base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6QDL_CLK_STEP]             = imx_clk_hw_mux("step",                  base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
+       hws[IMX6QDL_CLK_PLL1_SW]          = imx_clk_hw_mux("pll1_sw",       base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
+       hws[IMX6QDL_CLK_PERIPH_PRE]       = imx_clk_hw_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
+       hws[IMX6QDL_CLK_PERIPH2_PRE]      = imx_clk_hw_mux("periph2_pre",      base + 0x18, 21, 2, periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
+       hws[IMX6QDL_CLK_PERIPH_CLK2_SEL]  = imx_clk_hw_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+       hws[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_hw_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       hws[IMX6QDL_CLK_AXI_SEL]          = imx_clk_hw_mux("axi_sel",          base + 0x14, 6,  2, axi_sels,          ARRAY_SIZE(axi_sels));
+       hws[IMX6QDL_CLK_ESAI_SEL]         = imx_clk_hw_mux("esai_sel",         base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6QDL_CLK_ASRC_SEL]         = imx_clk_hw_mux("asrc_sel",         base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6QDL_CLK_SPDIF_SEL]        = imx_clk_hw_mux("spdif_sel",        base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
        if (clk_on_imx6q()) {
-               clk[IMX6QDL_CLK_GPU2D_AXI]        = imx_clk_mux("gpu2d_axi",        base + 0x18, 0,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
-               clk[IMX6QDL_CLK_GPU3D_AXI]        = imx_clk_mux("gpu3d_axi",        base + 0x18, 1,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
+               hws[IMX6QDL_CLK_GPU2D_AXI]        = imx_clk_hw_mux("gpu2d_axi",        base + 0x18, 0,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
+               hws[IMX6QDL_CLK_GPU3D_AXI]        = imx_clk_hw_mux("gpu3d_axi",        base + 0x18, 1,  1, gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
        }
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_CAN_SEL]   = imx_clk_mux("can_sel",     base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
-               clk[IMX6QDL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel",   base + 0x38, 18, 1, ecspi_sels,  ARRAY_SIZE(ecspi_sels));
-               clk[IMX6QDL_CLK_IPG_PER_SEL] = imx_clk_mux("ipg_per_sel", base + 0x1c, 6, 1, ipg_per_sels, ARRAY_SIZE(ipg_per_sels));
-               clk[IMX6QDL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
-               clk[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels_2, ARRAY_SIZE(gpu2d_core_sels_2));
+               hws[IMX6QDL_CLK_CAN_SEL]   = imx_clk_hw_mux("can_sel",  base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
+               hws[IMX6QDL_CLK_ECSPI_SEL] = imx_clk_hw_mux("ecspi_sel",        base + 0x38, 18, 1, ecspi_sels,  ARRAY_SIZE(ecspi_sels));
+               hws[IMX6QDL_CLK_IPG_PER_SEL] = imx_clk_hw_mux("ipg_per_sel", base + 0x1c, 6, 1, ipg_per_sels, ARRAY_SIZE(ipg_per_sels));
+               hws[IMX6QDL_CLK_UART_SEL] = imx_clk_hw_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
+               hws[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_hw_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels_2, ARRAY_SIZE(gpu2d_core_sels_2));
        } else if (clk_on_imx6dl()) {
-               clk[IMX6QDL_CLK_MLB_SEL] = imx_clk_mux("mlb_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
+               hws[IMX6QDL_CLK_MLB_SEL] = imx_clk_hw_mux("mlb_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
        } else {
-               clk[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_mux("gpu2d_core_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
+               hws[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_hw_mux("gpu2d_core_sel",   base + 0x18, 16, 2, gpu2d_core_sels,   ARRAY_SIZE(gpu2d_core_sels));
        }
-       clk[IMX6QDL_CLK_GPU3D_CORE_SEL]   = imx_clk_mux("gpu3d_core_sel",   base + 0x18, 4,  2, gpu3d_core_sels,   ARRAY_SIZE(gpu3d_core_sels));
+       hws[IMX6QDL_CLK_GPU3D_CORE_SEL]   = imx_clk_hw_mux("gpu3d_core_sel",   base + 0x18, 4,  2, gpu3d_core_sels,   ARRAY_SIZE(gpu3d_core_sels));
        if (clk_on_imx6dl())
-               clk[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
+               hws[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_hw_mux("gpu2d_core_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
        else
-               clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
-       clk[IMX6QDL_CLK_IPU1_SEL]         = imx_clk_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-       clk[IMX6QDL_CLK_IPU2_SEL]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
+               hws[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_hw_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
+       hws[IMX6QDL_CLK_IPU1_SEL]         = imx_clk_hw_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
+       hws[IMX6QDL_CLK_IPU2_SEL]         = imx_clk_hw_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
  
        disable_anatop_clocks(anatop_base);
  
-       imx6q_mmdc_ch1_mask_handshake(base);
+       imx_mmdc_mask_handshake(base, 1);
  
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_hw_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_hw_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
        } else {
                /*
                 * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
                 */
                init_ldb_clks(np, base);
  
-               clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
-               clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
+               hws[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_hw_mux_ldb("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
+               hws[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_hw_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
        }
-       clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
-       clk[IMX6QDL_CLK_HSI_TX_SEL]       = imx_clk_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
-       clk[IMX6QDL_CLK_PCIE_AXI_SEL]     = imx_clk_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
+       hws[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_hw_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_hw_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_hw_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_CLK_IPU2_DI1_PRE_SEL] = imx_clk_hw_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6QDL_CLK_HSI_TX_SEL]       = imx_clk_hw_mux("hsi_tx_sel",       base + 0x30, 28, 1, hsi_tx_sels,       ARRAY_SIZE(hsi_tx_sels));
+       hws[IMX6QDL_CLK_PCIE_AXI_SEL]     = imx_clk_hw_mux("pcie_axi_sel",     base + 0x18, 10, 1, pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_IPU1_DI0_SEL]     = imx_clk_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels_2,     ARRAY_SIZE(ipu1_di0_sels_2), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU1_DI1_SEL]     = imx_clk_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels_2,     ARRAY_SIZE(ipu1_di1_sels_2), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU2_DI0_SEL]     = imx_clk_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels_2,     ARRAY_SIZE(ipu2_di0_sels_2), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU2_DI1_SEL]     = imx_clk_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels_2,     ARRAY_SIZE(ipu2_di1_sels_2), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_SSI1_SEL]         = imx_clk_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-               clk[IMX6QDL_CLK_SSI2_SEL]         = imx_clk_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-               clk[IMX6QDL_CLK_SSI3_SEL]         = imx_clk_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
-               clk[IMX6QDL_CLK_USDHC1_SEL]       = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-               clk[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-               clk[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-               clk[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-               clk[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 15, 3, enfc_sels_2,         ARRAY_SIZE(enfc_sels_2));
-               clk[IMX6QDL_CLK_EIM_SEL]          = imx_clk_mux("eim_sel",      base + 0x1c, 27, 2, eim_sels,        ARRAY_SIZE(eim_sels));
-               clk[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels,   ARRAY_SIZE(eim_slow_sels));
-               clk[IMX6QDL_CLK_PRE_AXI]          = imx_clk_mux("pre_axi",      base + 0x18, 1,  1, pre_axi_sels,    ARRAY_SIZE(pre_axi_sels));
+               hws[IMX6QDL_CLK_IPU1_DI0_SEL]     = imx_clk_hw_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels_2,     ARRAY_SIZE(ipu1_di0_sels_2), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU1_DI1_SEL]     = imx_clk_hw_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels_2,     ARRAY_SIZE(ipu1_di1_sels_2), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU2_DI0_SEL]     = imx_clk_hw_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels_2,     ARRAY_SIZE(ipu2_di0_sels_2), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU2_DI1_SEL]     = imx_clk_hw_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels_2,     ARRAY_SIZE(ipu2_di1_sels_2), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_SSI1_SEL]         = imx_clk_hw_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
+               hws[IMX6QDL_CLK_SSI2_SEL]         = imx_clk_hw_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
+               hws[IMX6QDL_CLK_SSI3_SEL]         = imx_clk_hw_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels));
+               hws[IMX6QDL_CLK_USDHC1_SEL]       = imx_clk_hw_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+               hws[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_hw_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+               hws[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_hw_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+               hws[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_hw_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+               hws[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_hw_mux("enfc_sel",         base + 0x2c, 15, 3, enfc_sels_2,         ARRAY_SIZE(enfc_sels_2));
+               hws[IMX6QDL_CLK_EIM_SEL]          = imx_clk_hw_mux("eim_sel",      base + 0x1c, 27, 2, eim_sels,        ARRAY_SIZE(eim_sels));
+               hws[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_hw_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels,   ARRAY_SIZE(eim_slow_sels));
+               hws[IMX6QDL_CLK_PRE_AXI]          = imx_clk_hw_mux("pre_axi",   base + 0x18, 1,  1, pre_axi_sels,    ARRAY_SIZE(pre_axi_sels));
        } else {
-               clk[IMX6QDL_CLK_IPU1_DI0_SEL]     = imx_clk_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU1_DI1_SEL]     = imx_clk_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU2_DI0_SEL]     = imx_clk_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_IPU2_DI1_SEL]     = imx_clk_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
-               clk[IMX6QDL_CLK_SSI1_SEL]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_SSI2_SEL]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_SSI3_SEL]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_USDHC1_SEL]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
-               clk[IMX6QDL_CLK_EIM_SEL]          = imx_clk_fixup_mux("eim_sel",      base + 0x1c, 27, 2, eim_sels,        ARRAY_SIZE(eim_sels), imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_fixup_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels,   ARRAY_SIZE(eim_slow_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_IPU1_DI0_SEL]     = imx_clk_hw_mux_flags("ipu1_di0_sel",     base + 0x34, 0,  3, ipu1_di0_sels,     ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU1_DI1_SEL]     = imx_clk_hw_mux_flags("ipu1_di1_sel",     base + 0x34, 9,  3, ipu1_di1_sels,     ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU2_DI0_SEL]     = imx_clk_hw_mux_flags("ipu2_di0_sel",     base + 0x38, 0,  3, ipu2_di0_sels,     ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_IPU2_DI1_SEL]     = imx_clk_hw_mux_flags("ipu2_di1_sel",     base + 0x38, 9,  3, ipu2_di1_sels,     ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
+               hws[IMX6QDL_CLK_SSI1_SEL]         = imx_clk_hw_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_SSI2_SEL]         = imx_clk_hw_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_SSI3_SEL]         = imx_clk_hw_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_USDHC1_SEL]       = imx_clk_hw_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_USDHC2_SEL]       = imx_clk_hw_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_hw_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_hw_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_hw_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
+               hws[IMX6QDL_CLK_EIM_SEL]          = imx_clk_hw_fixup_mux("eim_sel",      base + 0x1c, 27, 2, eim_sels,        ARRAY_SIZE(eim_sels), imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_hw_fixup_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels,   ARRAY_SIZE(eim_slow_sels), imx_cscmr1_fixup);
        }
-       clk[IMX6QDL_CLK_VDO_AXI_SEL]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
-       clk[IMX6QDL_CLK_VPU_AXI_SEL]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
-       clk[IMX6QDL_CLK_CKO1_SEL]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
-       clk[IMX6QDL_CLK_CKO2_SEL]         = imx_clk_mux("cko2_sel",         base + 0x60, 16, 5, cko2_sels,         ARRAY_SIZE(cko2_sels));
-       clk[IMX6QDL_CLK_CKO]              = imx_clk_mux("cko",              base + 0x60, 8, 1,  cko_sels,          ARRAY_SIZE(cko_sels));
+       hws[IMX6QDL_CLK_VDO_AXI_SEL]      = imx_clk_hw_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
+       hws[IMX6QDL_CLK_VPU_AXI_SEL]      = imx_clk_hw_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
+       hws[IMX6QDL_CLK_CKO1_SEL]         = imx_clk_hw_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
+       hws[IMX6QDL_CLK_CKO2_SEL]         = imx_clk_hw_mux("cko2_sel",         base + 0x60, 16, 5, cko2_sels,         ARRAY_SIZE(cko2_sels));
+       hws[IMX6QDL_CLK_CKO]              = imx_clk_hw_mux("cko",              base + 0x60, 8, 1,  cko_sels,          ARRAY_SIZE(cko_sels));
  
        /*                                          name         reg      shift width busy: reg, shift parent_names  num_parents */
-       clk[IMX6QDL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
-       clk[IMX6QDL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
+       hws[IMX6QDL_CLK_PERIPH]  = imx_clk_hw_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
+       hws[IMX6QDL_CLK_PERIPH2] = imx_clk_hw_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
  
        /*                                                  name                parent_name          reg       shift width */
-       clk[IMX6QDL_CLK_PERIPH_CLK2]      = imx_clk_divider("periph_clk2",      "periph_clk2_sel",   base + 0x14, 27, 3);
-       clk[IMX6QDL_CLK_PERIPH2_CLK2]     = imx_clk_divider("periph2_clk2",     "periph2_clk2_sel",  base + 0x14, 0,  3);
-       clk[IMX6QDL_CLK_IPG]              = imx_clk_divider("ipg",              "ahb",               base + 0x14, 8,  2);
-       clk[IMX6QDL_CLK_ESAI_PRED]        = imx_clk_divider("esai_pred",        "esai_sel",          base + 0x28, 9,  3);
-       clk[IMX6QDL_CLK_ESAI_PODF]        = imx_clk_divider("esai_podf",        "esai_pred",         base + 0x28, 25, 3);
-       clk[IMX6QDL_CLK_ASRC_PRED]        = imx_clk_divider("asrc_pred",        "asrc_sel",          base + 0x30, 12, 3);
-       clk[IMX6QDL_CLK_ASRC_PODF]        = imx_clk_divider("asrc_podf",        "asrc_pred",         base + 0x30, 9,  3);
-       clk[IMX6QDL_CLK_SPDIF_PRED]       = imx_clk_divider("spdif_pred",       "spdif_sel",         base + 0x30, 25, 3);
-       clk[IMX6QDL_CLK_SPDIF_PODF]       = imx_clk_divider("spdif_podf",       "spdif_pred",        base + 0x30, 22, 3);
+       hws[IMX6QDL_CLK_PERIPH_CLK2]      = imx_clk_hw_divider("periph_clk2",      "periph_clk2_sel",   base + 0x14, 27, 3);
+       hws[IMX6QDL_CLK_PERIPH2_CLK2]     = imx_clk_hw_divider("periph2_clk2",     "periph2_clk2_sel",  base + 0x14, 0,  3);
+       hws[IMX6QDL_CLK_IPG]              = imx_clk_hw_divider("ipg",              "ahb",               base + 0x14, 8,  2);
+       hws[IMX6QDL_CLK_ESAI_PRED]        = imx_clk_hw_divider("esai_pred",        "esai_sel",          base + 0x28, 9,  3);
+       hws[IMX6QDL_CLK_ESAI_PODF]        = imx_clk_hw_divider("esai_podf",        "esai_pred",         base + 0x28, 25, 3);
+       hws[IMX6QDL_CLK_ASRC_PRED]        = imx_clk_hw_divider("asrc_pred",        "asrc_sel",          base + 0x30, 12, 3);
+       hws[IMX6QDL_CLK_ASRC_PODF]        = imx_clk_hw_divider("asrc_podf",        "asrc_pred",         base + 0x30, 9,  3);
+       hws[IMX6QDL_CLK_SPDIF_PRED]       = imx_clk_hw_divider("spdif_pred",       "spdif_sel",         base + 0x30, 25, 3);
+       hws[IMX6QDL_CLK_SPDIF_PODF]       = imx_clk_hw_divider("spdif_podf",       "spdif_pred",        base + 0x30, 22, 3);
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_IPG_PER] = imx_clk_divider("ipg_per", "ipg_per_sel", base + 0x1c, 0, 6);
-               clk[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6);
-               clk[IMX6QDL_CLK_CAN_ROOT] = imx_clk_divider("can_root", "can_sel", base + 0x20, 2, 6);
-               clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "uart_sel", base + 0x24, 0, 6);
-               clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0", 2, 7);
-               clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1", 2, 7);
+               hws[IMX6QDL_CLK_IPG_PER] = imx_clk_hw_divider("ipg_per", "ipg_per_sel", base + 0x1c, 0, 6);
+               hws[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_hw_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6);
+               hws[IMX6QDL_CLK_CAN_ROOT] = imx_clk_hw_divider("can_root", "can_sel", base + 0x20, 2, 6);
+               hws[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_hw_divider("uart_serial_podf", "uart_sel", base + 0x24, 0, 6);
+               hws[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di0_div_3_5", "ldb_di0", 2, 7);
+               hws[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di1_div_3_5", "ldb_di1", 2, 7);
        } else {
-               clk[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
-               clk[IMX6QDL_CLK_CAN_ROOT] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
-               clk[IMX6QDL_CLK_IPG_PER] = imx_clk_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "pll3_80m",          base + 0x24, 0,  6);
-               clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-               clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+               hws[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_hw_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
+               hws[IMX6QDL_CLK_CAN_ROOT] = imx_clk_hw_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
+               hws[IMX6QDL_CLK_IPG_PER] = imx_clk_hw_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_hw_divider("uart_serial_podf", "pll3_80m",          base + 0x24, 0,  6);
+               hws[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+               hws[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
        }
        if (clk_on_imx6dl())
-               clk[IMX6QDL_CLK_MLB_PODF]  = imx_clk_divider("mlb_podf",  "mlb_sel",    base + 0x18, 23, 3);
+               hws[IMX6QDL_CLK_MLB_PODF]  = imx_clk_hw_divider("mlb_podf",  "mlb_sel",    base + 0x18, 23, 3);
        else
-               clk[IMX6QDL_CLK_GPU2D_CORE_PODF]  = imx_clk_divider("gpu2d_core_podf",  "gpu2d_core_sel",    base + 0x18, 23, 3);
-       clk[IMX6QDL_CLK_GPU3D_CORE_PODF]  = imx_clk_divider("gpu3d_core_podf",  "gpu3d_core_sel",    base + 0x18, 26, 3);
+               hws[IMX6QDL_CLK_GPU2D_CORE_PODF]  = imx_clk_hw_divider("gpu2d_core_podf",  "gpu2d_core_sel",    base + 0x18, 23, 3);
+       hws[IMX6QDL_CLK_GPU3D_CORE_PODF]  = imx_clk_hw_divider("gpu3d_core_podf",  "gpu3d_core_sel",    base + 0x18, 26, 3);
        if (clk_on_imx6dl())
-               clk[IMX6QDL_CLK_GPU2D_CORE_PODF]  = imx_clk_divider("gpu2d_core_podf",     "gpu2d_core_sel",  base + 0x18, 29, 3);
+               hws[IMX6QDL_CLK_GPU2D_CORE_PODF]  = imx_clk_hw_divider("gpu2d_core_podf",     "gpu2d_core_sel",  base + 0x18, 29, 3);
        else
-               clk[IMX6QDL_CLK_GPU3D_SHADER]     = imx_clk_divider("gpu3d_shader",     "gpu3d_shader_sel",  base + 0x18, 29, 3);
-       clk[IMX6QDL_CLK_IPU1_PODF]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
-       clk[IMX6QDL_CLK_IPU2_PODF]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
-       clk[IMX6QDL_CLK_LDB_DI0_PODF]     = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
-       clk[IMX6QDL_CLK_LDB_DI1_PODF]     = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
-       clk[IMX6QDL_CLK_IPU1_DI0_PRE]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
-       clk[IMX6QDL_CLK_IPU1_DI1_PRE]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
-       clk[IMX6QDL_CLK_IPU2_DI0_PRE]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
-       clk[IMX6QDL_CLK_IPU2_DI1_PRE]     = imx_clk_divider("ipu2_di1_pre",     "ipu2_di1_pre_sel",  base + 0x38, 12, 3);
-       clk[IMX6QDL_CLK_HSI_TX_PODF]      = imx_clk_divider("hsi_tx_podf",      "hsi_tx_sel",        base + 0x30, 29, 3);
-       clk[IMX6QDL_CLK_SSI1_PRED]        = imx_clk_divider("ssi1_pred",        "ssi1_sel",          base + 0x28, 6,  3);
-       clk[IMX6QDL_CLK_SSI1_PODF]        = imx_clk_divider("ssi1_podf",        "ssi1_pred",         base + 0x28, 0,  6);
-       clk[IMX6QDL_CLK_SSI2_PRED]        = imx_clk_divider("ssi2_pred",        "ssi2_sel",          base + 0x2c, 6,  3);
-       clk[IMX6QDL_CLK_SSI2_PODF]        = imx_clk_divider("ssi2_podf",        "ssi2_pred",         base + 0x2c, 0,  6);
-       clk[IMX6QDL_CLK_SSI3_PRED]        = imx_clk_divider("ssi3_pred",        "ssi3_sel",          base + 0x28, 22, 3);
-       clk[IMX6QDL_CLK_SSI3_PODF]        = imx_clk_divider("ssi3_podf",        "ssi3_pred",         base + 0x28, 16, 6);
-       clk[IMX6QDL_CLK_USDHC1_PODF]      = imx_clk_divider("usdhc1_podf",      "usdhc1_sel",        base + 0x24, 11, 3);
-       clk[IMX6QDL_CLK_USDHC2_PODF]      = imx_clk_divider("usdhc2_podf",      "usdhc2_sel",        base + 0x24, 16, 3);
-       clk[IMX6QDL_CLK_USDHC3_PODF]      = imx_clk_divider("usdhc3_podf",      "usdhc3_sel",        base + 0x24, 19, 3);
-       clk[IMX6QDL_CLK_USDHC4_PODF]      = imx_clk_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
-       clk[IMX6QDL_CLK_ENFC_PRED]        = imx_clk_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
-       clk[IMX6QDL_CLK_ENFC_PODF]        = imx_clk_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
+               hws[IMX6QDL_CLK_GPU3D_SHADER]     = imx_clk_hw_divider("gpu3d_shader",     "gpu3d_shader_sel",  base + 0x18, 29, 3);
+       hws[IMX6QDL_CLK_IPU1_PODF]        = imx_clk_hw_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
+       hws[IMX6QDL_CLK_IPU2_PODF]        = imx_clk_hw_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
+       hws[IMX6QDL_CLK_LDB_DI0_PODF]     = imx_clk_hw_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
+       hws[IMX6QDL_CLK_LDB_DI1_PODF]     = imx_clk_hw_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
+       hws[IMX6QDL_CLK_IPU1_DI0_PRE]     = imx_clk_hw_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
+       hws[IMX6QDL_CLK_IPU1_DI1_PRE]     = imx_clk_hw_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
+       hws[IMX6QDL_CLK_IPU2_DI0_PRE]     = imx_clk_hw_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
+       hws[IMX6QDL_CLK_IPU2_DI1_PRE]     = imx_clk_hw_divider("ipu2_di1_pre",     "ipu2_di1_pre_sel",  base + 0x38, 12, 3);
+       hws[IMX6QDL_CLK_HSI_TX_PODF]      = imx_clk_hw_divider("hsi_tx_podf",      "hsi_tx_sel",        base + 0x30, 29, 3);
+       hws[IMX6QDL_CLK_SSI1_PRED]        = imx_clk_hw_divider("ssi1_pred",        "ssi1_sel",          base + 0x28, 6,  3);
+       hws[IMX6QDL_CLK_SSI1_PODF]        = imx_clk_hw_divider("ssi1_podf",        "ssi1_pred",         base + 0x28, 0,  6);
+       hws[IMX6QDL_CLK_SSI2_PRED]        = imx_clk_hw_divider("ssi2_pred",        "ssi2_sel",          base + 0x2c, 6,  3);
+       hws[IMX6QDL_CLK_SSI2_PODF]        = imx_clk_hw_divider("ssi2_podf",        "ssi2_pred",         base + 0x2c, 0,  6);
+       hws[IMX6QDL_CLK_SSI3_PRED]        = imx_clk_hw_divider("ssi3_pred",        "ssi3_sel",          base + 0x28, 22, 3);
+       hws[IMX6QDL_CLK_SSI3_PODF]        = imx_clk_hw_divider("ssi3_podf",        "ssi3_pred",         base + 0x28, 16, 6);
+       hws[IMX6QDL_CLK_USDHC1_PODF]      = imx_clk_hw_divider("usdhc1_podf",      "usdhc1_sel",        base + 0x24, 11, 3);
+       hws[IMX6QDL_CLK_USDHC2_PODF]      = imx_clk_hw_divider("usdhc2_podf",      "usdhc2_sel",        base + 0x24, 16, 3);
+       hws[IMX6QDL_CLK_USDHC3_PODF]      = imx_clk_hw_divider("usdhc3_podf",      "usdhc3_sel",        base + 0x24, 19, 3);
+       hws[IMX6QDL_CLK_USDHC4_PODF]      = imx_clk_hw_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
+       hws[IMX6QDL_CLK_ENFC_PRED]        = imx_clk_hw_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
+       hws[IMX6QDL_CLK_ENFC_PODF]        = imx_clk_hw_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_EIM_PODF]         = imx_clk_divider("eim_podf",   "eim_sel",           base + 0x1c, 20, 3);
-               clk[IMX6QDL_CLK_EIM_SLOW_PODF]    = imx_clk_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3);
+               hws[IMX6QDL_CLK_EIM_PODF]         = imx_clk_hw_divider("eim_podf",   "eim_sel",           base + 0x1c, 20, 3);
+               hws[IMX6QDL_CLK_EIM_SLOW_PODF]    = imx_clk_hw_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3);
        } else {
-               clk[IMX6QDL_CLK_EIM_PODF]         = imx_clk_fixup_divider("eim_podf",   "eim_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
-               clk[IMX6QDL_CLK_EIM_SLOW_PODF]    = imx_clk_fixup_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_EIM_PODF]         = imx_clk_hw_fixup_divider("eim_podf",   "eim_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
+               hws[IMX6QDL_CLK_EIM_SLOW_PODF]    = imx_clk_hw_fixup_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
        }
-       clk[IMX6QDL_CLK_VPU_AXI_PODF]     = imx_clk_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
-       clk[IMX6QDL_CLK_CKO1_PODF]        = imx_clk_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
-       clk[IMX6QDL_CLK_CKO2_PODF]        = imx_clk_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
+       hws[IMX6QDL_CLK_VPU_AXI_PODF]     = imx_clk_hw_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
+       hws[IMX6QDL_CLK_CKO1_PODF]        = imx_clk_hw_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
+       hws[IMX6QDL_CLK_CKO2_PODF]        = imx_clk_hw_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
  
        /*                                                        name                 parent_name    reg        shift width busy: reg, shift */
-       clk[IMX6QDL_CLK_AXI]               = imx_clk_busy_divider("axi",               "axi_sel",     base + 0x14, 16,  3,   base + 0x48, 0);
-       clk[IMX6QDL_CLK_MMDC_CH0_AXI_PODF] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph",      base + 0x14, 19,  3,   base + 0x48, 4);
+       hws[IMX6QDL_CLK_AXI]               = imx_clk_hw_busy_divider("axi",               "axi_sel",     base + 0x14, 16,  3,   base + 0x48, 0);
+       hws[IMX6QDL_CLK_MMDC_CH0_AXI_PODF] = imx_clk_hw_busy_divider("mmdc_ch0_axi_podf", "periph",      base + 0x14, 19,  3,   base + 0x48, 4);
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_MMDC_CH1_AXI_CG] = imx_clk_gate("mmdc_ch1_axi_cg", "periph2", base + 0x4, 18);
-               clk[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "mmdc_ch1_axi_cg", base + 0x14, 3, 3, base + 0x48, 2);
+               hws[IMX6QDL_CLK_MMDC_CH1_AXI_CG] = imx_clk_hw_gate("mmdc_ch1_axi_cg", "periph2", base + 0x4, 18);
+               hws[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_hw_busy_divider("mmdc_ch1_axi_podf", "mmdc_ch1_axi_cg", base + 0x14, 3, 3, base + 0x48, 2);
        } else {
-               clk[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2",     base + 0x14, 3,   3,   base + 0x48, 2);
+               hws[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_hw_busy_divider("mmdc_ch1_axi_podf", "periph2",     base + 0x14, 3,   3,   base + 0x48, 2);
        }
-       clk[IMX6QDL_CLK_ARM]               = imx_clk_busy_divider("arm",               "pll1_sw",     base + 0x10, 0,   3,   base + 0x48, 16);
-       clk[IMX6QDL_CLK_AHB]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
+       hws[IMX6QDL_CLK_ARM]               = imx_clk_hw_busy_divider("arm",               "pll1_sw",     base + 0x10, 0,   3,   base + 0x48, 16);
+       hws[IMX6QDL_CLK_AHB]               = imx_clk_hw_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
  
        /*                                            name             parent_name          reg         shift */
-       clk[IMX6QDL_CLK_APBH_DMA]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
-       clk[IMX6QDL_CLK_ASRC]         = imx_clk_gate2_shared("asrc",         "asrc_podf",   base + 0x68, 6, &share_count_asrc);
-       clk[IMX6QDL_CLK_ASRC_IPG]     = imx_clk_gate2_shared("asrc_ipg",     "ahb",         base + 0x68, 6, &share_count_asrc);
-       clk[IMX6QDL_CLK_ASRC_MEM]     = imx_clk_gate2_shared("asrc_mem",     "ahb",         base + 0x68, 6, &share_count_asrc);
-       clk[IMX6QDL_CLK_CAAM_MEM]     = imx_clk_gate2("caam_mem",      "ahb",               base + 0x68, 8);
-       clk[IMX6QDL_CLK_CAAM_ACLK]    = imx_clk_gate2("caam_aclk",     "ahb",               base + 0x68, 10);
-       clk[IMX6QDL_CLK_CAAM_IPG]     = imx_clk_gate2("caam_ipg",      "ipg",               base + 0x68, 12);
-       clk[IMX6QDL_CLK_CAN1_IPG]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
-       clk[IMX6QDL_CLK_CAN1_SERIAL]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
-       clk[IMX6QDL_CLK_CAN2_IPG]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
-       clk[IMX6QDL_CLK_CAN2_SERIAL]  = imx_clk_gate2("can2_serial",   "can_root",          base + 0x68, 20);
-       clk[IMX6QDL_CLK_DCIC1]        = imx_clk_gate2("dcic1",         "ipu1_podf",         base + 0x68, 24);
-       clk[IMX6QDL_CLK_DCIC2]        = imx_clk_gate2("dcic2",         "ipu2_podf",         base + 0x68, 26);
-       clk[IMX6QDL_CLK_ECSPI1]       = imx_clk_gate2("ecspi1",        "ecspi_root",        base + 0x6c, 0);
-       clk[IMX6QDL_CLK_ECSPI2]       = imx_clk_gate2("ecspi2",        "ecspi_root",        base + 0x6c, 2);
-       clk[IMX6QDL_CLK_ECSPI3]       = imx_clk_gate2("ecspi3",        "ecspi_root",        base + 0x6c, 4);
-       clk[IMX6QDL_CLK_ECSPI4]       = imx_clk_gate2("ecspi4",        "ecspi_root",        base + 0x6c, 6);
+       hws[IMX6QDL_CLK_APBH_DMA]     = imx_clk_hw_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
+       hws[IMX6QDL_CLK_ASRC]         = imx_clk_hw_gate2_shared("asrc",         "asrc_podf",   base + 0x68, 6, &share_count_asrc);
+       hws[IMX6QDL_CLK_ASRC_IPG]     = imx_clk_hw_gate2_shared("asrc_ipg",     "ahb",         base + 0x68, 6, &share_count_asrc);
+       hws[IMX6QDL_CLK_ASRC_MEM]     = imx_clk_hw_gate2_shared("asrc_mem",     "ahb",         base + 0x68, 6, &share_count_asrc);
+       hws[IMX6QDL_CLK_CAAM_MEM]     = imx_clk_hw_gate2("caam_mem",      "ahb",               base + 0x68, 8);
+       hws[IMX6QDL_CLK_CAAM_ACLK]    = imx_clk_hw_gate2("caam_aclk",     "ahb",               base + 0x68, 10);
+       hws[IMX6QDL_CLK_CAAM_IPG]     = imx_clk_hw_gate2("caam_ipg",      "ipg",               base + 0x68, 12);
+       hws[IMX6QDL_CLK_CAN1_IPG]     = imx_clk_hw_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
+       hws[IMX6QDL_CLK_CAN1_SERIAL]  = imx_clk_hw_gate2("can1_serial",   "can_root",          base + 0x68, 16);
+       hws[IMX6QDL_CLK_CAN2_IPG]     = imx_clk_hw_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
+       hws[IMX6QDL_CLK_CAN2_SERIAL]  = imx_clk_hw_gate2("can2_serial",   "can_root",          base + 0x68, 20);
+       hws[IMX6QDL_CLK_DCIC1]        = imx_clk_hw_gate2("dcic1",         "ipu1_podf",         base + 0x68, 24);
+       hws[IMX6QDL_CLK_DCIC2]        = imx_clk_hw_gate2("dcic2",         "ipu2_podf",         base + 0x68, 26);
+       hws[IMX6QDL_CLK_ECSPI1]       = imx_clk_hw_gate2("ecspi1",        "ecspi_root",        base + 0x6c, 0);
+       hws[IMX6QDL_CLK_ECSPI2]       = imx_clk_hw_gate2("ecspi2",        "ecspi_root",        base + 0x6c, 2);
+       hws[IMX6QDL_CLK_ECSPI3]       = imx_clk_hw_gate2("ecspi3",        "ecspi_root",        base + 0x6c, 4);
+       hws[IMX6QDL_CLK_ECSPI4]       = imx_clk_hw_gate2("ecspi4",        "ecspi_root",        base + 0x6c, 6);
        if (clk_on_imx6dl())
-               clk[IMX6DL_CLK_I2C4]  = imx_clk_gate2("i2c4",          "ipg_per",           base + 0x6c, 8);
+               hws[IMX6DL_CLK_I2C4]  = imx_clk_hw_gate2("i2c4",          "ipg_per",           base + 0x6c, 8);
        else
-               clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5",        "ecspi_root",        base + 0x6c, 8);
-       clk[IMX6QDL_CLK_ENET]         = imx_clk_gate2("enet",          "ipg",               base + 0x6c, 10);
-       clk[IMX6QDL_CLK_EPIT1]        = imx_clk_gate2("epit1",         "ipg",               base + 0x6c, 12);
-       clk[IMX6QDL_CLK_EPIT2]        = imx_clk_gate2("epit2",         "ipg",               base + 0x6c, 14);
-       clk[IMX6QDL_CLK_ESAI_EXTAL]   = imx_clk_gate2_shared("esai_extal",   "esai_podf",   base + 0x6c, 16, &share_count_esai);
-       clk[IMX6QDL_CLK_ESAI_IPG]     = imx_clk_gate2_shared("esai_ipg",   "ahb",           base + 0x6c, 16, &share_count_esai);
-       clk[IMX6QDL_CLK_ESAI_MEM]     = imx_clk_gate2_shared("esai_mem", "ahb",             base + 0x6c, 16, &share_count_esai);
-       clk[IMX6QDL_CLK_GPT_IPG]      = imx_clk_gate2("gpt_ipg",       "ipg",               base + 0x6c, 20);
-       clk[IMX6QDL_CLK_GPT_IPG_PER]  = imx_clk_gate2("gpt_ipg_per",   "ipg_per",           base + 0x6c, 22);
-       clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
-       clk[IMX6QDL_CLK_GPU3D_CORE]   = imx_clk_gate2("gpu3d_core",    "gpu3d_core_podf",   base + 0x6c, 26);
-       clk[IMX6QDL_CLK_HDMI_IAHB]    = imx_clk_gate2("hdmi_iahb",     "ahb",               base + 0x70, 0);
-       clk[IMX6QDL_CLK_HDMI_ISFR]    = imx_clk_gate2("hdmi_isfr",     "mipi_core_cfg",     base + 0x70, 4);
-       clk[IMX6QDL_CLK_I2C1]         = imx_clk_gate2("i2c1",          "ipg_per",           base + 0x70, 6);
-       clk[IMX6QDL_CLK_I2C2]         = imx_clk_gate2("i2c2",          "ipg_per",           base + 0x70, 8);
-       clk[IMX6QDL_CLK_I2C3]         = imx_clk_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
-       clk[IMX6QDL_CLK_IIM]          = imx_clk_gate2("iim",           "ipg",               base + 0x70, 12);
-       clk[IMX6QDL_CLK_ENFC]         = imx_clk_gate2("enfc",          "enfc_podf",         base + 0x70, 14);
-       clk[IMX6QDL_CLK_VDOA]         = imx_clk_gate2("vdoa",          "vdo_axi",           base + 0x70, 26);
-       clk[IMX6QDL_CLK_IPU1]         = imx_clk_gate2("ipu1",          "ipu1_podf",         base + 0x74, 0);
-       clk[IMX6QDL_CLK_IPU1_DI0]     = imx_clk_gate2("ipu1_di0",      "ipu1_di0_sel",      base + 0x74, 2);
-       clk[IMX6QDL_CLK_IPU1_DI1]     = imx_clk_gate2("ipu1_di1",      "ipu1_di1_sel",      base + 0x74, 4);
-       clk[IMX6QDL_CLK_IPU2]         = imx_clk_gate2("ipu2",          "ipu2_podf",         base + 0x74, 6);
-       clk[IMX6QDL_CLK_IPU2_DI0]     = imx_clk_gate2("ipu2_di0",      "ipu2_di0_sel",      base + 0x74, 8);
+               hws[IMX6Q_CLK_ECSPI5] = imx_clk_hw_gate2("ecspi5",        "ecspi_root",        base + 0x6c, 8);
+       hws[IMX6QDL_CLK_ENET]         = imx_clk_hw_gate2("enet",          "ipg",               base + 0x6c, 10);
+       hws[IMX6QDL_CLK_EPIT1]        = imx_clk_hw_gate2("epit1",         "ipg",               base + 0x6c, 12);
+       hws[IMX6QDL_CLK_EPIT2]        = imx_clk_hw_gate2("epit2",         "ipg",               base + 0x6c, 14);
+       hws[IMX6QDL_CLK_ESAI_EXTAL]   = imx_clk_hw_gate2_shared("esai_extal",   "esai_podf",   base + 0x6c, 16, &share_count_esai);
+       hws[IMX6QDL_CLK_ESAI_IPG]     = imx_clk_hw_gate2_shared("esai_ipg",   "ahb",           base + 0x6c, 16, &share_count_esai);
+       hws[IMX6QDL_CLK_ESAI_MEM]     = imx_clk_hw_gate2_shared("esai_mem", "ahb",             base + 0x6c, 16, &share_count_esai);
+       hws[IMX6QDL_CLK_GPT_IPG]      = imx_clk_hw_gate2("gpt_ipg",       "ipg",               base + 0x6c, 20);
+       hws[IMX6QDL_CLK_GPT_IPG_PER]  = imx_clk_hw_gate2("gpt_ipg_per",   "ipg_per",           base + 0x6c, 22);
+       hws[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_hw_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
+       hws[IMX6QDL_CLK_GPU3D_CORE]   = imx_clk_hw_gate2("gpu3d_core",    "gpu3d_core_podf",   base + 0x6c, 26);
+       hws[IMX6QDL_CLK_HDMI_IAHB]    = imx_clk_hw_gate2("hdmi_iahb",     "ahb",               base + 0x70, 0);
+       hws[IMX6QDL_CLK_HDMI_ISFR]    = imx_clk_hw_gate2("hdmi_isfr",     "mipi_core_cfg",     base + 0x70, 4);
+       hws[IMX6QDL_CLK_I2C1]         = imx_clk_hw_gate2("i2c1",          "ipg_per",           base + 0x70, 6);
+       hws[IMX6QDL_CLK_I2C2]         = imx_clk_hw_gate2("i2c2",          "ipg_per",           base + 0x70, 8);
+       hws[IMX6QDL_CLK_I2C3]         = imx_clk_hw_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
+       hws[IMX6QDL_CLK_IIM]          = imx_clk_hw_gate2("iim",           "ipg",               base + 0x70, 12);
+       hws[IMX6QDL_CLK_ENFC]         = imx_clk_hw_gate2("enfc",          "enfc_podf",         base + 0x70, 14);
+       hws[IMX6QDL_CLK_VDOA]         = imx_clk_hw_gate2("vdoa",          "vdo_axi",           base + 0x70, 26);
+       hws[IMX6QDL_CLK_IPU1]         = imx_clk_hw_gate2("ipu1",          "ipu1_podf",         base + 0x74, 0);
+       hws[IMX6QDL_CLK_IPU1_DI0]     = imx_clk_hw_gate2("ipu1_di0",      "ipu1_di0_sel",      base + 0x74, 2);
+       hws[IMX6QDL_CLK_IPU1_DI1]     = imx_clk_hw_gate2("ipu1_di1",      "ipu1_di1_sel",      base + 0x74, 4);
+       hws[IMX6QDL_CLK_IPU2]         = imx_clk_hw_gate2("ipu2",          "ipu2_podf",         base + 0x74, 6);
+       hws[IMX6QDL_CLK_IPU2_DI0]     = imx_clk_hw_gate2("ipu2_di0",      "ipu2_di0_sel",      base + 0x74, 8);
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_LDB_DI0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_sel",      base + 0x74, 12);
-               clk[IMX6QDL_CLK_LDB_DI1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_sel",      base + 0x74, 14);
+               hws[IMX6QDL_CLK_LDB_DI0]      = imx_clk_hw_gate2("ldb_di0",       "ldb_di0_sel",      base + 0x74, 12);
+               hws[IMX6QDL_CLK_LDB_DI1]      = imx_clk_hw_gate2("ldb_di1",       "ldb_di1_sel",      base + 0x74, 14);
        } else {
-               clk[IMX6QDL_CLK_LDB_DI0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_podf",      base + 0x74, 12);
-               clk[IMX6QDL_CLK_LDB_DI1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
+               hws[IMX6QDL_CLK_LDB_DI0]      = imx_clk_hw_gate2("ldb_di0",       "ldb_di0_podf",      base + 0x74, 12);
+               hws[IMX6QDL_CLK_LDB_DI1]      = imx_clk_hw_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
        }
-       clk[IMX6QDL_CLK_IPU2_DI1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
-       clk[IMX6QDL_CLK_HSI_TX]       = imx_clk_gate2_shared("hsi_tx", "hsi_tx_podf",       base + 0x74, 16, &share_count_mipi_core_cfg);
-       clk[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg);
-       clk[IMX6QDL_CLK_MIPI_IPG]     = imx_clk_gate2_shared("mipi_ipg", "ipg",             base + 0x74, 16, &share_count_mipi_core_cfg);
+       hws[IMX6QDL_CLK_IPU2_DI1]     = imx_clk_hw_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
+       hws[IMX6QDL_CLK_HSI_TX]       = imx_clk_hw_gate2_shared("hsi_tx", "hsi_tx_podf",       base + 0x74, 16, &share_count_mipi_core_cfg);
+       hws[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_hw_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg);
+       hws[IMX6QDL_CLK_MIPI_IPG]     = imx_clk_hw_gate2_shared("mipi_ipg", "ipg",             base + 0x74, 16, &share_count_mipi_core_cfg);
        if (clk_on_imx6dl())
                /*
                 * The multiplexer and divider of the imx6q clock gpu2d get
                 * redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl.
                 */
-               clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb",            "mlb_podf",   base + 0x74, 18);
+               hws[IMX6QDL_CLK_MLB] = imx_clk_hw_gate2("mlb",            "mlb_podf",   base + 0x74, 18);
        else
-               clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb",            "axi",               base + 0x74, 18);
-       clk[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_gate2_flags("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20, CLK_IS_CRITICAL);
-       clk[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
-       clk[IMX6QDL_CLK_MMDC_P0_IPG]  = imx_clk_gate2_flags("mmdc_p0_ipg",   "ipg",         base + 0x74, 24, CLK_IS_CRITICAL);
-       clk[IMX6QDL_CLK_OCRAM]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
-       clk[IMX6QDL_CLK_OPENVG_AXI]   = imx_clk_gate2("openvg_axi",    "axi",               base + 0x74, 30);
-       clk[IMX6QDL_CLK_PCIE_AXI]     = imx_clk_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
-       clk[IMX6QDL_CLK_PER1_BCH]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
-       clk[IMX6QDL_CLK_PWM1]         = imx_clk_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
-       clk[IMX6QDL_CLK_PWM2]         = imx_clk_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
-       clk[IMX6QDL_CLK_PWM3]         = imx_clk_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
-       clk[IMX6QDL_CLK_PWM4]         = imx_clk_gate2("pwm4",          "ipg_per",           base + 0x78, 22);
-       clk[IMX6QDL_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
-       clk[IMX6QDL_CLK_GPMI_BCH]     = imx_clk_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
-       clk[IMX6QDL_CLK_GPMI_IO]      = imx_clk_gate2("gpmi_io",       "enfc",              base + 0x78, 28);
-       clk[IMX6QDL_CLK_GPMI_APB]     = imx_clk_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
-       clk[IMX6QDL_CLK_ROM]          = imx_clk_gate2_flags("rom",     "ahb",               base + 0x7c, 0, CLK_IS_CRITICAL);
-       clk[IMX6QDL_CLK_SATA]         = imx_clk_gate2("sata",          "ahb",               base + 0x7c, 4);
-       clk[IMX6QDL_CLK_SDMA]         = imx_clk_gate2("sdma",          "ahb",               base + 0x7c, 6);
-       clk[IMX6QDL_CLK_SPBA]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
-       clk[IMX6QDL_CLK_SPDIF]        = imx_clk_gate2_shared("spdif",     "spdif_podf",     base + 0x7c, 14, &share_count_spdif);
-       clk[IMX6QDL_CLK_SPDIF_GCLK]   = imx_clk_gate2_shared("spdif_gclk", "ipg",           base + 0x7c, 14, &share_count_spdif);
-       clk[IMX6QDL_CLK_SSI1_IPG]     = imx_clk_gate2_shared("ssi1_ipg",      "ipg",        base + 0x7c, 18, &share_count_ssi1);
-       clk[IMX6QDL_CLK_SSI2_IPG]     = imx_clk_gate2_shared("ssi2_ipg",      "ipg",        base + 0x7c, 20, &share_count_ssi2);
-       clk[IMX6QDL_CLK_SSI3_IPG]     = imx_clk_gate2_shared("ssi3_ipg",      "ipg",        base + 0x7c, 22, &share_count_ssi3);
-       clk[IMX6QDL_CLK_SSI1]         = imx_clk_gate2_shared("ssi1",          "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
-       clk[IMX6QDL_CLK_SSI2]         = imx_clk_gate2_shared("ssi2",          "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
-       clk[IMX6QDL_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
-       clk[IMX6QDL_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
-       clk[IMX6QDL_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_serial_podf",  base + 0x7c, 26);
-       clk[IMX6QDL_CLK_USBOH3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
-       clk[IMX6QDL_CLK_USDHC1]       = imx_clk_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
-       clk[IMX6QDL_CLK_USDHC2]       = imx_clk_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
-       clk[IMX6QDL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
-       clk[IMX6QDL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
-       clk[IMX6QDL_CLK_EIM_SLOW]     = imx_clk_gate2("eim_slow",      "eim_slow_podf",     base + 0x80, 10);
-       clk[IMX6QDL_CLK_VDO_AXI]      = imx_clk_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
-       clk[IMX6QDL_CLK_VPU_AXI]      = imx_clk_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
+               hws[IMX6QDL_CLK_MLB] = imx_clk_hw_gate2("mlb",            "axi",               base + 0x74, 18);
+       hws[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_hw_gate2_flags("mmdc_ch0_axi",  "mmdc_ch0_axi_podf", base + 0x74, 20, CLK_IS_CRITICAL);
+       hws[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_hw_gate2("mmdc_ch1_axi",  "mmdc_ch1_axi_podf", base + 0x74, 22);
+       hws[IMX6QDL_CLK_MMDC_P0_IPG]  = imx_clk_hw_gate2_flags("mmdc_p0_ipg",   "ipg",         base + 0x74, 24, CLK_IS_CRITICAL);
+       hws[IMX6QDL_CLK_OCRAM]        = imx_clk_hw_gate2("ocram",         "ahb",               base + 0x74, 28);
+       hws[IMX6QDL_CLK_OPENVG_AXI]   = imx_clk_hw_gate2("openvg_axi",    "axi",               base + 0x74, 30);
+       hws[IMX6QDL_CLK_PCIE_AXI]     = imx_clk_hw_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
+       hws[IMX6QDL_CLK_PER1_BCH]     = imx_clk_hw_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
+       hws[IMX6QDL_CLK_PWM1]         = imx_clk_hw_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
+       hws[IMX6QDL_CLK_PWM2]         = imx_clk_hw_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
+       hws[IMX6QDL_CLK_PWM3]         = imx_clk_hw_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
+       hws[IMX6QDL_CLK_PWM4]         = imx_clk_hw_gate2("pwm4",          "ipg_per",           base + 0x78, 22);
+       hws[IMX6QDL_CLK_GPMI_BCH_APB] = imx_clk_hw_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
+       hws[IMX6QDL_CLK_GPMI_BCH]     = imx_clk_hw_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
+       hws[IMX6QDL_CLK_GPMI_IO]      = imx_clk_hw_gate2("gpmi_io",       "enfc",              base + 0x78, 28);
+       hws[IMX6QDL_CLK_GPMI_APB]     = imx_clk_hw_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
+       hws[IMX6QDL_CLK_ROM]          = imx_clk_hw_gate2_flags("rom",     "ahb",               base + 0x7c, 0, CLK_IS_CRITICAL);
+       hws[IMX6QDL_CLK_SATA]         = imx_clk_hw_gate2("sata",          "ahb",               base + 0x7c, 4);
+       hws[IMX6QDL_CLK_SDMA]         = imx_clk_hw_gate2("sdma",          "ahb",               base + 0x7c, 6);
+       hws[IMX6QDL_CLK_SPBA]         = imx_clk_hw_gate2("spba",          "ipg",               base + 0x7c, 12);
+       hws[IMX6QDL_CLK_SPDIF]        = imx_clk_hw_gate2_shared("spdif",     "spdif_podf",     base + 0x7c, 14, &share_count_spdif);
+       hws[IMX6QDL_CLK_SPDIF_GCLK]   = imx_clk_hw_gate2_shared("spdif_gclk", "ipg",           base + 0x7c, 14, &share_count_spdif);
+       hws[IMX6QDL_CLK_SSI1_IPG]     = imx_clk_hw_gate2_shared("ssi1_ipg",      "ipg",        base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6QDL_CLK_SSI2_IPG]     = imx_clk_hw_gate2_shared("ssi2_ipg",      "ipg",        base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6QDL_CLK_SSI3_IPG]     = imx_clk_hw_gate2_shared("ssi3_ipg",      "ipg",        base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6QDL_CLK_SSI1]         = imx_clk_hw_gate2_shared("ssi1",          "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6QDL_CLK_SSI2]         = imx_clk_hw_gate2_shared("ssi2",          "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6QDL_CLK_SSI3]         = imx_clk_hw_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6QDL_CLK_UART_IPG]     = imx_clk_hw_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
+       hws[IMX6QDL_CLK_UART_SERIAL]  = imx_clk_hw_gate2("uart_serial",   "uart_serial_podf",  base + 0x7c, 26);
+       hws[IMX6QDL_CLK_USBOH3]       = imx_clk_hw_gate2("usboh3",        "ipg",               base + 0x80, 0);
+       hws[IMX6QDL_CLK_USDHC1]       = imx_clk_hw_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
+       hws[IMX6QDL_CLK_USDHC2]       = imx_clk_hw_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
+       hws[IMX6QDL_CLK_USDHC3]       = imx_clk_hw_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
+       hws[IMX6QDL_CLK_USDHC4]       = imx_clk_hw_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
+       hws[IMX6QDL_CLK_EIM_SLOW]     = imx_clk_hw_gate2("eim_slow",      "eim_slow_podf",     base + 0x80, 10);
+       hws[IMX6QDL_CLK_VDO_AXI]      = imx_clk_hw_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
+       hws[IMX6QDL_CLK_VPU_AXI]      = imx_clk_hw_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
        if (clk_on_imx6qp()) {
-               clk[IMX6QDL_CLK_PRE0] = imx_clk_gate2("pre0",          "pre_axi",           base + 0x80, 16);
-               clk[IMX6QDL_CLK_PRE1] = imx_clk_gate2("pre1",          "pre_axi",           base + 0x80, 18);
-               clk[IMX6QDL_CLK_PRE2] = imx_clk_gate2("pre2",          "pre_axi",         base + 0x80, 20);
-               clk[IMX6QDL_CLK_PRE3] = imx_clk_gate2("pre3",          "pre_axi",           base + 0x80, 22);
-               clk[IMX6QDL_CLK_PRG0_AXI] = imx_clk_gate2_shared("prg0_axi",  "ipu1_podf",  base + 0x80, 24, &share_count_prg0);
-               clk[IMX6QDL_CLK_PRG1_AXI] = imx_clk_gate2_shared("prg1_axi",  "ipu2_podf",  base + 0x80, 26, &share_count_prg1);
-               clk[IMX6QDL_CLK_PRG0_APB] = imx_clk_gate2_shared("prg0_apb",  "ipg",        base + 0x80, 24, &share_count_prg0);
-               clk[IMX6QDL_CLK_PRG1_APB] = imx_clk_gate2_shared("prg1_apb",  "ipg",        base + 0x80, 26, &share_count_prg1);
+               hws[IMX6QDL_CLK_PRE0] = imx_clk_hw_gate2("pre0",               "pre_axi",           base + 0x80, 16);
+               hws[IMX6QDL_CLK_PRE1] = imx_clk_hw_gate2("pre1",               "pre_axi",           base + 0x80, 18);
+               hws[IMX6QDL_CLK_PRE2] = imx_clk_hw_gate2("pre2",               "pre_axi",         base + 0x80, 20);
+               hws[IMX6QDL_CLK_PRE3] = imx_clk_hw_gate2("pre3",               "pre_axi",           base + 0x80, 22);
+               hws[IMX6QDL_CLK_PRG0_AXI] = imx_clk_hw_gate2_shared("prg0_axi",  "ipu1_podf",  base + 0x80, 24, &share_count_prg0);
+               hws[IMX6QDL_CLK_PRG1_AXI] = imx_clk_hw_gate2_shared("prg1_axi",  "ipu2_podf",  base + 0x80, 26, &share_count_prg1);
+               hws[IMX6QDL_CLK_PRG0_APB] = imx_clk_hw_gate2_shared("prg0_apb",  "ipg",     base + 0x80, 24, &share_count_prg0);
+               hws[IMX6QDL_CLK_PRG1_APB] = imx_clk_hw_gate2_shared("prg1_apb",  "ipg",     base + 0x80, 26, &share_count_prg1);
        }
-       clk[IMX6QDL_CLK_CKO1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
-       clk[IMX6QDL_CLK_CKO2]         = imx_clk_gate("cko2",           "cko2_podf",         base + 0x60, 24);
+       hws[IMX6QDL_CLK_CKO1]         = imx_clk_hw_gate("cko1",           "cko1_podf",         base + 0x60, 7);
+       hws[IMX6QDL_CLK_CKO2]         = imx_clk_hw_gate("cko2",           "cko2_podf",         base + 0x60, 24);
  
        /*
         * The gpt_3m clock is not available on i.MX6Q TO1.0.  Let's point it
         * to clock gpt_ipg_per to ease the gpt driver code.
         */
        if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
-               clk[IMX6QDL_CLK_GPT_3M] = clk[IMX6QDL_CLK_GPT_IPG_PER];
+               hws[IMX6QDL_CLK_GPT_3M] = hws[IMX6QDL_CLK_GPT_IPG_PER];
  
-       imx_check_clocks(clk, ARRAY_SIZE(clk));
+       imx_check_clk_hws(hws, IMX6QDL_CLK_END);
  
-       clk_data.clks = clk;
-       clk_data.clk_num = ARRAY_SIZE(clk);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
  
-       clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
+       clk_hw_register_clkdev(hws[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
  
-       clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
+       clk_set_rate(hws[IMX6QDL_CLK_PLL3_PFD1_540M]->clk, 540000000);
        if (clk_on_imx6dl())
-               clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
+               clk_set_parent(hws[IMX6QDL_CLK_IPU1_SEL]->clk, hws[IMX6QDL_CLK_PLL3_PFD1_540M]->clk);
  
-       clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_SEL], clk[IMX6QDL_CLK_IPU1_DI0_PRE]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_SEL], clk[IMX6QDL_CLK_IPU1_DI1_PRE]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]);
-       clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU1_DI0_PRE_SEL]->clk, hws[IMX6QDL_CLK_PLL5_VIDEO_DIV]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU1_DI1_PRE_SEL]->clk, hws[IMX6QDL_CLK_PLL5_VIDEO_DIV]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU2_DI0_PRE_SEL]->clk, hws[IMX6QDL_CLK_PLL5_VIDEO_DIV]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU2_DI1_PRE_SEL]->clk, hws[IMX6QDL_CLK_PLL5_VIDEO_DIV]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU1_DI0_SEL]->clk, hws[IMX6QDL_CLK_IPU1_DI0_PRE]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU1_DI1_SEL]->clk, hws[IMX6QDL_CLK_IPU1_DI1_PRE]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU2_DI0_SEL]->clk, hws[IMX6QDL_CLK_IPU2_DI0_PRE]->clk);
+       clk_set_parent(hws[IMX6QDL_CLK_IPU2_DI1_SEL]->clk, hws[IMX6QDL_CLK_IPU2_DI1_PRE]->clk);
  
        /*
         * The gpmi needs 100MHz frequency in the EDO/Sync mode,
         * We can not get the 100MHz from the pll2_pfd0_352m.
         * So choose pll2_pfd2_396m as enfc_sel's parent.
         */
-       clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
+       clk_set_parent(hws[IMX6QDL_CLK_ENFC_SEL]->clk, hws[IMX6QDL_CLK_PLL2_PFD2_396M]->clk);
  
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
-               clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]);
-               clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]);
+               clk_prepare_enable(hws[IMX6QDL_CLK_USBPHY1_GATE]->clk);
+               clk_prepare_enable(hws[IMX6QDL_CLK_USBPHY2_GATE]->clk);
        }
  
        /*
         * Let's initially set up CLKO with OSC24M, since this configuration
         * is widely used by imx6q board designs to clock audio codec.
         */
-       ret = clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]);
+       ret = clk_set_parent(hws[IMX6QDL_CLK_CKO2_SEL]->clk, hws[IMX6QDL_CLK_OSC]->clk);
        if (!ret)
-               ret = clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]);
+               ret = clk_set_parent(hws[IMX6QDL_CLK_CKO]->clk, hws[IMX6QDL_CLK_CKO2]->clk);
        if (ret)
                pr_warn("failed to set up CLKO: %d\n", ret);
  
        /* Audio-related clocks configuration */
-       clk_set_parent(clk[IMX6QDL_CLK_SPDIF_SEL], clk[IMX6QDL_CLK_PLL3_PFD3_454M]);
+       clk_set_parent(hws[IMX6QDL_CLK_SPDIF_SEL]->clk, hws[IMX6QDL_CLK_PLL3_PFD3_454M]->clk);
  
        /* All existing boards with PCIe use LVDS1 */
        if (IS_ENABLED(CONFIG_PCI_IMX6))
-               clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
+               clk_set_parent(hws[IMX6QDL_CLK_LVDS1_SEL]->clk, hws[IMX6QDL_CLK_SATA_REF_100M]->clk);
  
        /*
         * Initialize the GPU clock muxes, so that the maximum specified clock
         * rates for the respective SoC are not exceeded.
         */
        if (clk_on_imx6dl()) {
-               clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL],
-                              clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
-               clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL],
-                              clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
+               clk_set_parent(hws[IMX6QDL_CLK_GPU3D_CORE_SEL]->clk,
+                              hws[IMX6QDL_CLK_PLL2_PFD1_594M]->clk);
+               clk_set_parent(hws[IMX6QDL_CLK_GPU2D_CORE_SEL]->clk,
+                              hws[IMX6QDL_CLK_PLL2_PFD1_594M]->clk);
        } else if (clk_on_imx6q()) {
-               clk_set_parent(clk[IMX6QDL_CLK_GPU3D_CORE_SEL],
-                              clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
-               clk_set_parent(clk[IMX6QDL_CLK_GPU3D_SHADER_SEL],
-                              clk[IMX6QDL_CLK_PLL2_PFD1_594M]);
-               clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL],
-                              clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+               clk_set_parent(hws[IMX6QDL_CLK_GPU3D_CORE_SEL]->clk,
+                              hws[IMX6QDL_CLK_MMDC_CH0_AXI]->clk);
+               clk_set_parent(hws[IMX6QDL_CLK_GPU3D_SHADER_SEL]->clk,
+                              hws[IMX6QDL_CLK_PLL2_PFD1_594M]->clk);
+               clk_set_parent(hws[IMX6QDL_CLK_GPU2D_CORE_SEL]->clk,
+                              hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
+       }
+       for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) {
+               int index = uart_clk_ids[i];
+               uart_clks[i] = &hws[index]->clk;
        }
  
        imx_register_uart_clocks(uart_clks);
index f9f1f8a95d9296a824e3f05617681bb59d03bf1b,68293b0f0c534a5de8ac663839b300f3f49131ea..4bd44d89eaaa8b0ffc5798210f638cb4d1b2839c
@@@ -1,6 -1,10 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright 2013-2014 Freescale Semiconductor, Inc.
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   */
  
  #include <linux/clk.h>
@@@ -13,8 -17,6 +13,6 @@@
  
  #include "clk.h"
  
- #define CCDR                          0x4
- #define BM_CCM_CCDR_MMDC_CH0_MASK     (1 << 17)
  #define CCSR                  0xc
  #define BM_CCSR_PLL1_SW_CLK_SEL       (1 << 2)
  #define CACRR                 0x10
@@@ -97,8 -99,8 +95,8 @@@ static unsigned int share_count_ssi2
  static unsigned int share_count_ssi3;
  static unsigned int share_count_spdif;
  
- static struct clk *clks[IMX6SL_CLK_END];
- static struct clk_onecell_data clk_data;
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
  static void __iomem *ccm_base;
  static void __iomem *anatop_base;
  
@@@ -179,74 -181,84 +177,84 @@@ void imx6sl_set_wait_clk(bool enter
                imx6sl_enable_pll_arm(false);
  }
  
- static struct clk ** const uart_clks[] __initconst = {
-       &clks[IMX6SL_CLK_UART],
-       &clks[IMX6SL_CLK_UART_SERIAL],
-       NULL
+ static const int uart_clk_ids[] __initconst = {
+       IMX6SL_CLK_UART,
+       IMX6SL_CLK_UART_SERIAL,
  };
  
+ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata;
  static void __init imx6sl_clocks_init(struct device_node *ccm_node)
  {
        struct device_node *np;
        void __iomem *base;
        int ret;
+       int i;
+       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+                                         IMX6SL_CLK_END), GFP_KERNEL);
+       if (WARN_ON(!clk_hw_data))
+               return;
+       clk_hw_data->num = IMX6SL_CLK_END;
+       hws = clk_hw_data->hws;
  
-       clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
-       clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
-       clks[IMX6SL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
+       hws[IMX6SL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
+       hws[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock_hw("ckil", 0);
+       hws[IMX6SL_CLK_OSC] = imx_obtain_fixed_clock_hw("osc", 0);
        /* Clock source from external clock via CLK1 PAD */
-       clks[IMX6SL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
+       hws[IMX6SL_CLK_ANACLK1] = imx_obtain_fixed_clock_hw("anaclk1", 0);
  
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop");
        base = of_iomap(np, 0);
        WARN_ON(!base);
        anatop_base = base;
  
-       clks[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL2_BYPASS_SRC] = imx_clk_hw_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL3_BYPASS_SRC] = imx_clk_hw_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL4_BYPASS_SRC] = imx_clk_hw_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL5_BYPASS_SRC] = imx_clk_hw_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL6_BYPASS_SRC] = imx_clk_hw_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_hw_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
  
        /*                                    type               name    parent_name        base         div_mask */
-       clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
-       clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
-       clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
-       clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
-       clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
-       clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
-       clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
-       clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_CLK_PLL1] = imx_clk_hw_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       hws[IMX6SL_CLK_PLL2] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       hws[IMX6SL_CLK_PLL3] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       hws[IMX6SL_CLK_PLL4] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       hws[IMX6SL_CLK_PLL5] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       hws[IMX6SL_CLK_PLL6] = imx_clk_hw_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       hws[IMX6SL_CLK_PLL7] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
+       hws[IMX6SL_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL4_BYPASS] = imx_clk_hw_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
  
        /* Do not bypass PLLs initially */
-       clk_set_parent(clks[IMX6SL_PLL1_BYPASS], clks[IMX6SL_CLK_PLL1]);
-       clk_set_parent(clks[IMX6SL_PLL2_BYPASS], clks[IMX6SL_CLK_PLL2]);
-       clk_set_parent(clks[IMX6SL_PLL3_BYPASS], clks[IMX6SL_CLK_PLL3]);
-       clk_set_parent(clks[IMX6SL_PLL4_BYPASS], clks[IMX6SL_CLK_PLL4]);
-       clk_set_parent(clks[IMX6SL_PLL5_BYPASS], clks[IMX6SL_CLK_PLL5]);
-       clk_set_parent(clks[IMX6SL_PLL6_BYPASS], clks[IMX6SL_CLK_PLL6]);
-       clk_set_parent(clks[IMX6SL_PLL7_BYPASS], clks[IMX6SL_CLK_PLL7]);
-       clks[IMX6SL_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
-       clks[IMX6SL_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
-       clks[IMX6SL_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
-       clks[IMX6SL_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
-       clks[IMX6SL_CLK_PLL5_VIDEO]    = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
-       clks[IMX6SL_CLK_PLL6_ENET]     = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
-       clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
-       clks[IMX6SL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
-       clks[IMX6SL_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12));
-       clks[IMX6SL_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10));
+       clk_set_parent(hws[IMX6SL_PLL1_BYPASS]->clk, hws[IMX6SL_CLK_PLL1]->clk);
+       clk_set_parent(hws[IMX6SL_PLL2_BYPASS]->clk, hws[IMX6SL_CLK_PLL2]->clk);
+       clk_set_parent(hws[IMX6SL_PLL3_BYPASS]->clk, hws[IMX6SL_CLK_PLL3]->clk);
+       clk_set_parent(hws[IMX6SL_PLL4_BYPASS]->clk, hws[IMX6SL_CLK_PLL4]->clk);
+       clk_set_parent(hws[IMX6SL_PLL5_BYPASS]->clk, hws[IMX6SL_CLK_PLL5]->clk);
+       clk_set_parent(hws[IMX6SL_PLL6_BYPASS]->clk, hws[IMX6SL_CLK_PLL6]->clk);
+       clk_set_parent(hws[IMX6SL_PLL7_BYPASS]->clk, hws[IMX6SL_CLK_PLL7]->clk);
+       hws[IMX6SL_CLK_PLL1_SYS]      = imx_clk_hw_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       hws[IMX6SL_CLK_PLL2_BUS]      = imx_clk_hw_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
+       hws[IMX6SL_CLK_PLL3_USB_OTG]  = imx_clk_hw_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
+       hws[IMX6SL_CLK_PLL4_AUDIO]    = imx_clk_hw_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
+       hws[IMX6SL_CLK_PLL5_VIDEO]    = imx_clk_hw_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
+       hws[IMX6SL_CLK_PLL6_ENET]     = imx_clk_hw_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
+       hws[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_hw_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+       hws[IMX6SL_CLK_LVDS1_SEL] = imx_clk_hw_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+       hws[IMX6SL_CLK_LVDS1_OUT] = imx_clk_hw_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12));
+       hws[IMX6SL_CLK_LVDS1_IN] = imx_clk_hw_gate_exclusive("lvds1_in", "anaclk1", base + 0x160, 12, BIT(10));
  
        /*
         * usbphy1 and usbphy2 are implemented as dummy gates using reserve
         * turned on during boot, and software will not need to control it
         * anymore after that.
         */
-       clks[IMX6SL_CLK_USBPHY1]      = imx_clk_gate("usbphy1",      "pll3_usb_otg",  base + 0x10, 20);
-       clks[IMX6SL_CLK_USBPHY2]      = imx_clk_gate("usbphy2",      "pll7_usb_host", base + 0x20, 20);
-       clks[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy",         base + 0x10, 6);
-       clks[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy",         base + 0x20, 6);
+       hws[IMX6SL_CLK_USBPHY1]      = imx_clk_hw_gate("usbphy1",      "pll3_usb_otg",  base + 0x10, 20);
+       hws[IMX6SL_CLK_USBPHY2]      = imx_clk_hw_gate("usbphy2",      "pll7_usb_host", base + 0x20, 20);
+       hws[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_hw_gate("usbphy1_gate", "dummy",         base + 0x10, 6);
+       hws[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_hw_gate("usbphy2_gate", "dummy",         base + 0x20, 6);
  
        /*                                                           dev   name              parent_name      flags                reg        shift width div: flags, div_table lock */
-       clks[IMX6SL_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div",  "pll4_audio",    CLK_SET_RATE_PARENT, base + 0x70,  19, 2,   0, post_div_table, &imx_ccm_lock);
-       clks[IMX6SL_CLK_PLL4_AUDIO_DIV] =       clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1,   0, &imx_ccm_lock);
-       clks[IMX6SL_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div",  "pll5_video",    CLK_SET_RATE_PARENT, base + 0xa0,  19, 2,   0, post_div_table, &imx_ccm_lock);
-       clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2,   0, video_div_table, &imx_ccm_lock);
-       clks[IMX6SL_CLK_ENET_REF]       = clk_register_divider_table(NULL, "enet_ref",       "pll6_enet",     0,                   base + 0xe0,  0,  2,   0, clk_enet_ref_table, &imx_ccm_lock);
+       hws[IMX6SL_CLK_PLL4_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll4_post_div",  "pll4_audio",    CLK_SET_RATE_PARENT, base + 0x70,  19, 2,   0, post_div_table, &imx_ccm_lock);
+       hws[IMX6SL_CLK_PLL4_AUDIO_DIV] =       clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1,   0, &imx_ccm_lock);
+       hws[IMX6SL_CLK_PLL5_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll5_post_div",  "pll5_video",    CLK_SET_RATE_PARENT, base + 0xa0,  19, 2,   0, post_div_table, &imx_ccm_lock);
+       hws[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2,   0, video_div_table, &imx_ccm_lock);
+       hws[IMX6SL_CLK_ENET_REF]       = clk_hw_register_divider_table(NULL, "enet_ref",       "pll6_enet",     0,                   base + 0xe0,  0,  2,   0, clk_enet_ref_table, &imx_ccm_lock);
  
        /*                                       name         parent_name     reg           idx */
-       clks[IMX6SL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0", "pll2_bus",     base + 0x100, 0);
-       clks[IMX6SL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus",     base + 0x100, 1);
-       clks[IMX6SL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus",     base + 0x100, 2);
-       clks[IMX6SL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0", "pll3_usb_otg", base + 0xf0,  0);
-       clks[IMX6SL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", base + 0xf0,  1);
-       clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0,  2);
-       clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0,  3);
+       hws[IMX6SL_CLK_PLL2_PFD0] = imx_clk_hw_pfd("pll2_pfd0", "pll2_bus",     base + 0x100, 0);
+       hws[IMX6SL_CLK_PLL2_PFD1] = imx_clk_hw_pfd("pll2_pfd1", "pll2_bus",     base + 0x100, 1);
+       hws[IMX6SL_CLK_PLL2_PFD2] = imx_clk_hw_pfd("pll2_pfd2", "pll2_bus",     base + 0x100, 2);
+       hws[IMX6SL_CLK_PLL3_PFD0] = imx_clk_hw_pfd("pll3_pfd0", "pll3_usb_otg", base + 0xf0,  0);
+       hws[IMX6SL_CLK_PLL3_PFD1] = imx_clk_hw_pfd("pll3_pfd1", "pll3_usb_otg", base + 0xf0,  1);
+       hws[IMX6SL_CLK_PLL3_PFD2] = imx_clk_hw_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0,  2);
+       hws[IMX6SL_CLK_PLL3_PFD3] = imx_clk_hw_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0,  3);
  
        /*                                                name         parent_name     mult div */
-       clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2",      1, 2);
-       clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
-       clks[IMX6SL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
-       clks[IMX6SL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
+       hws[IMX6SL_CLK_PLL2_198M] = imx_clk_hw_fixed_factor("pll2_198m", "pll2_pfd2",      1, 2);
+       hws[IMX6SL_CLK_PLL3_120M] = imx_clk_hw_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
+       hws[IMX6SL_CLK_PLL3_80M]  = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
+       hws[IMX6SL_CLK_PLL3_60M]  = imx_clk_hw_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
  
        np = ccm_node;
        base = of_iomap(np, 0);
        ccm_base = base;
  
        /*                                              name                reg       shift width parent_names     num_parents */
-       clks[IMX6SL_CLK_STEP]             = imx_clk_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
-       clks[IMX6SL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
-       clks[IMX6SL_CLK_OCRAM_ALT_SEL]    = imx_clk_mux("ocram_alt_sel",    base + 0x14, 7,  1, ocram_alt_sels,    ARRAY_SIZE(ocram_alt_sels));
-       clks[IMX6SL_CLK_OCRAM_SEL]        = imx_clk_mux("ocram_sel",        base + 0x14, 6,  1, ocram_sels,        ARRAY_SIZE(ocram_sels));
-       clks[IMX6SL_CLK_PRE_PERIPH2_SEL]  = imx_clk_mux("pre_periph2_sel",  base + 0x18, 21, 2, pre_periph_sels,   ARRAY_SIZE(pre_periph_sels));
-       clks[IMX6SL_CLK_PRE_PERIPH_SEL]   = imx_clk_mux("pre_periph_sel",   base + 0x18, 18, 2, pre_periph_sels,   ARRAY_SIZE(pre_periph_sels));
-       clks[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
-       clks[IMX6SL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
-       clks[IMX6SL_CLK_CSI_SEL]          = imx_clk_mux("csi_sel",          base + 0x3c, 9,  2, csi_sels,          ARRAY_SIZE(csi_sels));
-       clks[IMX6SL_CLK_LCDIF_AXI_SEL]    = imx_clk_mux("lcdif_axi_sel",    base + 0x3c, 14, 2, lcdif_axi_sels,    ARRAY_SIZE(lcdif_axi_sels));
-       clks[IMX6SL_CLK_USDHC1_SEL]       = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_USDHC2_SEL]       = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_USDHC3_SEL]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_USDHC4_SEL]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_SSI1_SEL]         = imx_clk_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_SSI2_SEL]         = imx_clk_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_SSI3_SEL]         = imx_clk_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_PERCLK_SEL]       = imx_clk_fixup_mux("perclk_sel", base + 0x1c, 6,  1, perclk_sels,       ARRAY_SIZE(perclk_sels), imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_PXP_AXI_SEL]      = imx_clk_mux("pxp_axi_sel",      base + 0x34, 6,  3, pxp_axi_sels,      ARRAY_SIZE(pxp_axi_sels));
-       clks[IMX6SL_CLK_EPDC_AXI_SEL]     = imx_clk_mux("epdc_axi_sel",     base + 0x34, 15, 3, epdc_axi_sels,     ARRAY_SIZE(epdc_axi_sels));
-       clks[IMX6SL_CLK_GPU2D_OVG_SEL]    = imx_clk_mux("gpu2d_ovg_sel",    base + 0x18, 4,  2, gpu2d_ovg_sels,    ARRAY_SIZE(gpu2d_ovg_sels));
-       clks[IMX6SL_CLK_GPU2D_SEL]        = imx_clk_mux("gpu2d_sel",        base + 0x18, 8,  2, gpu2d_sels,        ARRAY_SIZE(gpu2d_sels));
-       clks[IMX6SL_CLK_LCDIF_PIX_SEL]    = imx_clk_mux("lcdif_pix_sel",    base + 0x38, 6,  3, lcdif_pix_sels,    ARRAY_SIZE(lcdif_pix_sels));
-       clks[IMX6SL_CLK_EPDC_PIX_SEL]     = imx_clk_mux("epdc_pix_sel",     base + 0x38, 15, 3, epdc_pix_sels,     ARRAY_SIZE(epdc_pix_sels));
-       clks[IMX6SL_CLK_SPDIF0_SEL]       = imx_clk_mux("spdif0_sel",       base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SL_CLK_SPDIF1_SEL]       = imx_clk_mux("spdif1_sel",       base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SL_CLK_ECSPI_SEL]        = imx_clk_mux("ecspi_sel",        base + 0x38, 18, 1, ecspi_sels,        ARRAY_SIZE(ecspi_sels));
-       clks[IMX6SL_CLK_UART_SEL]         = imx_clk_mux("uart_sel",         base + 0x24, 6,  1, uart_sels,         ARRAY_SIZE(uart_sels));
+       hws[IMX6SL_CLK_STEP]             = imx_clk_hw_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
+       hws[IMX6SL_CLK_PLL1_SW]          = imx_clk_hw_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
+       hws[IMX6SL_CLK_OCRAM_ALT_SEL]    = imx_clk_hw_mux("ocram_alt_sel",    base + 0x14, 7,  1, ocram_alt_sels,    ARRAY_SIZE(ocram_alt_sels));
+       hws[IMX6SL_CLK_OCRAM_SEL]        = imx_clk_hw_mux("ocram_sel",        base + 0x14, 6,  1, ocram_sels,        ARRAY_SIZE(ocram_sels));
+       hws[IMX6SL_CLK_PRE_PERIPH2_SEL]  = imx_clk_hw_mux("pre_periph2_sel",  base + 0x18, 21, 2, pre_periph_sels,   ARRAY_SIZE(pre_periph_sels));
+       hws[IMX6SL_CLK_PRE_PERIPH_SEL]   = imx_clk_hw_mux("pre_periph_sel",   base + 0x18, 18, 2, pre_periph_sels,   ARRAY_SIZE(pre_periph_sels));
+       hws[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_hw_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       hws[IMX6SL_CLK_PERIPH_CLK2_SEL]  = imx_clk_hw_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+       hws[IMX6SL_CLK_CSI_SEL]          = imx_clk_hw_mux("csi_sel",          base + 0x3c, 9,  2, csi_sels,          ARRAY_SIZE(csi_sels));
+       hws[IMX6SL_CLK_LCDIF_AXI_SEL]    = imx_clk_hw_mux("lcdif_axi_sel",    base + 0x3c, 14, 2, lcdif_axi_sels,    ARRAY_SIZE(lcdif_axi_sels));
+       hws[IMX6SL_CLK_USDHC1_SEL]       = imx_clk_hw_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_USDHC2_SEL]       = imx_clk_hw_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_USDHC3_SEL]       = imx_clk_hw_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_USDHC4_SEL]       = imx_clk_hw_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels),  imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_SSI1_SEL]         = imx_clk_hw_fixup_mux("ssi1_sel",   base + 0x1c, 10, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_SSI2_SEL]         = imx_clk_hw_fixup_mux("ssi2_sel",   base + 0x1c, 12, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_SSI3_SEL]         = imx_clk_hw_fixup_mux("ssi3_sel",   base + 0x1c, 14, 2, ssi_sels,          ARRAY_SIZE(ssi_sels),    imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_PERCLK_SEL]       = imx_clk_hw_fixup_mux("perclk_sel", base + 0x1c, 6,  1, perclk_sels,       ARRAY_SIZE(perclk_sels), imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_PXP_AXI_SEL]      = imx_clk_hw_mux("pxp_axi_sel",      base + 0x34, 6,  3, pxp_axi_sels,      ARRAY_SIZE(pxp_axi_sels));
+       hws[IMX6SL_CLK_EPDC_AXI_SEL]     = imx_clk_hw_mux("epdc_axi_sel",     base + 0x34, 15, 3, epdc_axi_sels,     ARRAY_SIZE(epdc_axi_sels));
+       hws[IMX6SL_CLK_GPU2D_OVG_SEL]    = imx_clk_hw_mux("gpu2d_ovg_sel",    base + 0x18, 4,  2, gpu2d_ovg_sels,    ARRAY_SIZE(gpu2d_ovg_sels));
+       hws[IMX6SL_CLK_GPU2D_SEL]        = imx_clk_hw_mux("gpu2d_sel",        base + 0x18, 8,  2, gpu2d_sels,        ARRAY_SIZE(gpu2d_sels));
+       hws[IMX6SL_CLK_LCDIF_PIX_SEL]    = imx_clk_hw_mux("lcdif_pix_sel",    base + 0x38, 6,  3, lcdif_pix_sels,    ARRAY_SIZE(lcdif_pix_sels));
+       hws[IMX6SL_CLK_EPDC_PIX_SEL]     = imx_clk_hw_mux("epdc_pix_sel",     base + 0x38, 15, 3, epdc_pix_sels,     ARRAY_SIZE(epdc_pix_sels));
+       hws[IMX6SL_CLK_SPDIF0_SEL]       = imx_clk_hw_mux("spdif0_sel",       base + 0x30, 20, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SL_CLK_SPDIF1_SEL]       = imx_clk_hw_mux("spdif1_sel",       base + 0x30, 7,  2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_hw_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SL_CLK_ECSPI_SEL]        = imx_clk_hw_mux("ecspi_sel",        base + 0x38, 18, 1, ecspi_sels,        ARRAY_SIZE(ecspi_sels));
+       hws[IMX6SL_CLK_UART_SEL]         = imx_clk_hw_mux("uart_sel",         base + 0x24, 6,  1, uart_sels,         ARRAY_SIZE(uart_sels));
  
        /*                                          name       reg        shift width busy: reg, shift parent_names  num_parents */
-       clks[IMX6SL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
-       clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
+       hws[IMX6SL_CLK_PERIPH]  = imx_clk_hw_busy_mux("periph",  base + 0x14, 25,  1,   base + 0x48, 5,  periph_sels,  ARRAY_SIZE(periph_sels));
+       hws[IMX6SL_CLK_PERIPH2] = imx_clk_hw_busy_mux("periph2", base + 0x14, 26,  1,   base + 0x48, 3,  periph2_sels, ARRAY_SIZE(periph2_sels));
  
        /*                                                   name                 parent_name          reg       shift width */
-       clks[IMX6SL_CLK_OCRAM_PODF]        = imx_clk_busy_divider("ocram_podf",   "ocram_sel",         base + 0x14, 16, 3, base + 0x48, 0);
-       clks[IMX6SL_CLK_PERIPH_CLK2_PODF]  = imx_clk_divider("periph_clk2_podf",  "periph_clk2_sel",   base + 0x14, 27, 3);
-       clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel",  base + 0x14, 0,  3);
-       clks[IMX6SL_CLK_IPG]               = imx_clk_divider("ipg",               "ahb",               base + 0x14, 8,  2);
-       clks[IMX6SL_CLK_CSI_PODF]          = imx_clk_divider("csi_podf",          "csi_sel",           base + 0x3c, 11, 3);
-       clks[IMX6SL_CLK_LCDIF_AXI_PODF]    = imx_clk_divider("lcdif_axi_podf",    "lcdif_axi_sel",     base + 0x3c, 16, 3);
-       clks[IMX6SL_CLK_USDHC1_PODF]       = imx_clk_divider("usdhc1_podf",       "usdhc1_sel",        base + 0x24, 11, 3);
-       clks[IMX6SL_CLK_USDHC2_PODF]       = imx_clk_divider("usdhc2_podf",       "usdhc2_sel",        base + 0x24, 16, 3);
-       clks[IMX6SL_CLK_USDHC3_PODF]       = imx_clk_divider("usdhc3_podf",       "usdhc3_sel",        base + 0x24, 19, 3);
-       clks[IMX6SL_CLK_USDHC4_PODF]       = imx_clk_divider("usdhc4_podf",       "usdhc4_sel",        base + 0x24, 22, 3);
-       clks[IMX6SL_CLK_SSI1_PRED]         = imx_clk_divider("ssi1_pred",         "ssi1_sel",          base + 0x28, 6,  3);
-       clks[IMX6SL_CLK_SSI1_PODF]         = imx_clk_divider("ssi1_podf",         "ssi1_pred",         base + 0x28, 0,  6);
-       clks[IMX6SL_CLK_SSI2_PRED]         = imx_clk_divider("ssi2_pred",         "ssi2_sel",          base + 0x2c, 6,  3);
-       clks[IMX6SL_CLK_SSI2_PODF]         = imx_clk_divider("ssi2_podf",         "ssi2_pred",         base + 0x2c, 0,  6);
-       clks[IMX6SL_CLK_SSI3_PRED]         = imx_clk_divider("ssi3_pred",         "ssi3_sel",          base + 0x28, 22, 3);
-       clks[IMX6SL_CLK_SSI3_PODF]         = imx_clk_divider("ssi3_podf",         "ssi3_pred",         base + 0x28, 16, 6);
-       clks[IMX6SL_CLK_PERCLK]            = imx_clk_fixup_divider("perclk",      "perclk_sel",        base + 0x1c, 0,  6, imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_PXP_AXI_PODF]      = imx_clk_divider("pxp_axi_podf",      "pxp_axi_sel",       base + 0x34, 3,  3);
-       clks[IMX6SL_CLK_EPDC_AXI_PODF]     = imx_clk_divider("epdc_axi_podf",     "epdc_axi_sel",      base + 0x34, 12, 3);
-       clks[IMX6SL_CLK_GPU2D_OVG_PODF]    = imx_clk_divider("gpu2d_ovg_podf",    "gpu2d_ovg_sel",     base + 0x18, 26, 3);
-       clks[IMX6SL_CLK_GPU2D_PODF]        = imx_clk_divider("gpu2d_podf",        "gpu2d_sel",         base + 0x18, 29, 3);
-       clks[IMX6SL_CLK_LCDIF_PIX_PRED]    = imx_clk_divider("lcdif_pix_pred",    "lcdif_pix_sel",     base + 0x38, 3,  3);
-       clks[IMX6SL_CLK_EPDC_PIX_PRED]     = imx_clk_divider("epdc_pix_pred",     "epdc_pix_sel",      base + 0x38, 12, 3);
-       clks[IMX6SL_CLK_LCDIF_PIX_PODF]    = imx_clk_fixup_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3, imx_cscmr1_fixup);
-       clks[IMX6SL_CLK_EPDC_PIX_PODF]     = imx_clk_divider("epdc_pix_podf",     "epdc_pix_pred",     base + 0x18, 23, 3);
-       clks[IMX6SL_CLK_SPDIF0_PRED]       = imx_clk_divider("spdif0_pred",       "spdif0_sel",        base + 0x30, 25, 3);
-       clks[IMX6SL_CLK_SPDIF0_PODF]       = imx_clk_divider("spdif0_podf",       "spdif0_pred",       base + 0x30, 22, 3);
-       clks[IMX6SL_CLK_SPDIF1_PRED]       = imx_clk_divider("spdif1_pred",       "spdif1_sel",        base + 0x30, 12, 3);
-       clks[IMX6SL_CLK_SPDIF1_PODF]       = imx_clk_divider("spdif1_podf",       "spdif1_pred",       base + 0x30, 9,  3);
-       clks[IMX6SL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel",  base + 0x28, 9,  3);
-       clks[IMX6SL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x28, 25, 3);
-       clks[IMX6SL_CLK_ECSPI_ROOT]        = imx_clk_divider("ecspi_root",        "ecspi_sel",         base + 0x38, 19, 6);
-       clks[IMX6SL_CLK_UART_ROOT]         = imx_clk_divider("uart_root",         "uart_sel",          base + 0x24, 0,  6);
+       hws[IMX6SL_CLK_OCRAM_PODF]        = imx_clk_hw_busy_divider("ocram_podf",   "ocram_sel",         base + 0x14, 16, 3, base + 0x48, 0);
+       hws[IMX6SL_CLK_PERIPH_CLK2_PODF]  = imx_clk_hw_divider("periph_clk2_podf",  "periph_clk2_sel",   base + 0x14, 27, 3);
+       hws[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_hw_divider("periph2_clk2_podf", "periph2_clk2_sel",  base + 0x14, 0,  3);
+       hws[IMX6SL_CLK_IPG]               = imx_clk_hw_divider("ipg",               "ahb",               base + 0x14, 8,  2);
+       hws[IMX6SL_CLK_CSI_PODF]          = imx_clk_hw_divider("csi_podf",          "csi_sel",           base + 0x3c, 11, 3);
+       hws[IMX6SL_CLK_LCDIF_AXI_PODF]    = imx_clk_hw_divider("lcdif_axi_podf",    "lcdif_axi_sel",     base + 0x3c, 16, 3);
+       hws[IMX6SL_CLK_USDHC1_PODF]       = imx_clk_hw_divider("usdhc1_podf",       "usdhc1_sel",        base + 0x24, 11, 3);
+       hws[IMX6SL_CLK_USDHC2_PODF]       = imx_clk_hw_divider("usdhc2_podf",       "usdhc2_sel",        base + 0x24, 16, 3);
+       hws[IMX6SL_CLK_USDHC3_PODF]       = imx_clk_hw_divider("usdhc3_podf",       "usdhc3_sel",        base + 0x24, 19, 3);
+       hws[IMX6SL_CLK_USDHC4_PODF]       = imx_clk_hw_divider("usdhc4_podf",       "usdhc4_sel",        base + 0x24, 22, 3);
+       hws[IMX6SL_CLK_SSI1_PRED]         = imx_clk_hw_divider("ssi1_pred",         "ssi1_sel",          base + 0x28, 6,  3);
+       hws[IMX6SL_CLK_SSI1_PODF]         = imx_clk_hw_divider("ssi1_podf",         "ssi1_pred",         base + 0x28, 0,  6);
+       hws[IMX6SL_CLK_SSI2_PRED]         = imx_clk_hw_divider("ssi2_pred",         "ssi2_sel",          base + 0x2c, 6,  3);
+       hws[IMX6SL_CLK_SSI2_PODF]         = imx_clk_hw_divider("ssi2_podf",         "ssi2_pred",         base + 0x2c, 0,  6);
+       hws[IMX6SL_CLK_SSI3_PRED]         = imx_clk_hw_divider("ssi3_pred",         "ssi3_sel",          base + 0x28, 22, 3);
+       hws[IMX6SL_CLK_SSI3_PODF]         = imx_clk_hw_divider("ssi3_podf",         "ssi3_pred",         base + 0x28, 16, 6);
+       hws[IMX6SL_CLK_PERCLK]            = imx_clk_hw_fixup_divider("perclk",      "perclk_sel",        base + 0x1c, 0,  6, imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_PXP_AXI_PODF]      = imx_clk_hw_divider("pxp_axi_podf",      "pxp_axi_sel",       base + 0x34, 3,  3);
+       hws[IMX6SL_CLK_EPDC_AXI_PODF]     = imx_clk_hw_divider("epdc_axi_podf",     "epdc_axi_sel",      base + 0x34, 12, 3);
+       hws[IMX6SL_CLK_GPU2D_OVG_PODF]    = imx_clk_hw_divider("gpu2d_ovg_podf",    "gpu2d_ovg_sel",     base + 0x18, 26, 3);
+       hws[IMX6SL_CLK_GPU2D_PODF]        = imx_clk_hw_divider("gpu2d_podf",        "gpu2d_sel",         base + 0x18, 29, 3);
+       hws[IMX6SL_CLK_LCDIF_PIX_PRED]    = imx_clk_hw_divider("lcdif_pix_pred",    "lcdif_pix_sel",     base + 0x38, 3,  3);
+       hws[IMX6SL_CLK_EPDC_PIX_PRED]     = imx_clk_hw_divider("epdc_pix_pred",     "epdc_pix_sel",      base + 0x38, 12, 3);
+       hws[IMX6SL_CLK_LCDIF_PIX_PODF]    = imx_clk_hw_fixup_divider("lcdif_pix_podf", "lcdif_pix_pred", base + 0x1c, 20, 3, imx_cscmr1_fixup);
+       hws[IMX6SL_CLK_EPDC_PIX_PODF]     = imx_clk_hw_divider("epdc_pix_podf",     "epdc_pix_pred",     base + 0x18, 23, 3);
+       hws[IMX6SL_CLK_SPDIF0_PRED]       = imx_clk_hw_divider("spdif0_pred",       "spdif0_sel",        base + 0x30, 25, 3);
+       hws[IMX6SL_CLK_SPDIF0_PODF]       = imx_clk_hw_divider("spdif0_podf",       "spdif0_pred",       base + 0x30, 22, 3);
+       hws[IMX6SL_CLK_SPDIF1_PRED]       = imx_clk_hw_divider("spdif1_pred",       "spdif1_sel",        base + 0x30, 12, 3);
+       hws[IMX6SL_CLK_SPDIF1_PODF]       = imx_clk_hw_divider("spdif1_podf",       "spdif1_pred",       base + 0x30, 9,  3);
+       hws[IMX6SL_CLK_EXTERN_AUDIO_PRED] = imx_clk_hw_divider("extern_audio_pred", "extern_audio_sel",  base + 0x28, 9,  3);
+       hws[IMX6SL_CLK_EXTERN_AUDIO_PODF] = imx_clk_hw_divider("extern_audio_podf", "extern_audio_pred", base + 0x28, 25, 3);
+       hws[IMX6SL_CLK_ECSPI_ROOT]        = imx_clk_hw_divider("ecspi_root",        "ecspi_sel",         base + 0x38, 19, 6);
+       hws[IMX6SL_CLK_UART_ROOT]         = imx_clk_hw_divider("uart_root",         "uart_sel",          base + 0x24, 0,  6);
  
        /*                                                name         parent_name reg       shift width busy: reg, shift */
-       clks[IMX6SL_CLK_AHB]       = imx_clk_busy_divider("ahb",       "periph",  base + 0x14, 10, 3,    base + 0x48, 1);
-       clks[IMX6SL_CLK_MMDC_ROOT] = imx_clk_busy_divider("mmdc",      "periph2", base + 0x14, 3,  3,    base + 0x48, 2);
-       clks[IMX6SL_CLK_ARM]       = imx_clk_busy_divider("arm",       "pll1_sw", base + 0x10, 0,  3,    base + 0x48, 16);
+       hws[IMX6SL_CLK_AHB]       = imx_clk_hw_busy_divider("ahb",       "periph",  base + 0x14, 10, 3,    base + 0x48, 1);
+       hws[IMX6SL_CLK_MMDC_ROOT] = imx_clk_hw_busy_divider("mmdc",      "periph2", base + 0x14, 3,  3,    base + 0x48, 2);
+       hws[IMX6SL_CLK_ARM]       = imx_clk_hw_busy_divider("arm",       "pll1_sw", base + 0x10, 0,  3,    base + 0x48, 16);
  
        /*                                            name            parent_name          reg         shift */
-       clks[IMX6SL_CLK_ECSPI1]       = imx_clk_gate2("ecspi1",       "ecspi_root",        base + 0x6c, 0);
-       clks[IMX6SL_CLK_ECSPI2]       = imx_clk_gate2("ecspi2",       "ecspi_root",        base + 0x6c, 2);
-       clks[IMX6SL_CLK_ECSPI3]       = imx_clk_gate2("ecspi3",       "ecspi_root",        base + 0x6c, 4);
-       clks[IMX6SL_CLK_ECSPI4]       = imx_clk_gate2("ecspi4",       "ecspi_root",        base + 0x6c, 6);
-       clks[IMX6SL_CLK_ENET]         = imx_clk_gate2("enet",         "ipg",               base + 0x6c, 10);
-       clks[IMX6SL_CLK_EPIT1]        = imx_clk_gate2("epit1",        "perclk",            base + 0x6c, 12);
-       clks[IMX6SL_CLK_EPIT2]        = imx_clk_gate2("epit2",        "perclk",            base + 0x6c, 14);
-       clks[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_gate2("extern_audio", "extern_audio_podf", base + 0x6c, 16);
-       clks[IMX6SL_CLK_GPT]          = imx_clk_gate2("gpt",          "perclk",            base + 0x6c, 20);
-       clks[IMX6SL_CLK_GPT_SERIAL]   = imx_clk_gate2("gpt_serial",   "perclk",            base + 0x6c, 22);
-       clks[IMX6SL_CLK_GPU2D_OVG]    = imx_clk_gate2("gpu2d_ovg",    "gpu2d_ovg_podf",    base + 0x6c, 26);
-       clks[IMX6SL_CLK_I2C1]         = imx_clk_gate2("i2c1",         "perclk",            base + 0x70, 6);
-       clks[IMX6SL_CLK_I2C2]         = imx_clk_gate2("i2c2",         "perclk",            base + 0x70, 8);
-       clks[IMX6SL_CLK_I2C3]         = imx_clk_gate2("i2c3",         "perclk",            base + 0x70, 10);
-       clks[IMX6SL_CLK_OCOTP]        = imx_clk_gate2("ocotp",        "ipg",               base + 0x70, 12);
-       clks[IMX6SL_CLK_CSI]          = imx_clk_gate2("csi",          "csi_podf",          base + 0x74, 0);
-       clks[IMX6SL_CLK_PXP_AXI]      = imx_clk_gate2("pxp_axi",      "pxp_axi_podf",      base + 0x74, 2);
-       clks[IMX6SL_CLK_EPDC_AXI]     = imx_clk_gate2("epdc_axi",     "epdc_axi_podf",     base + 0x74, 4);
-       clks[IMX6SL_CLK_LCDIF_AXI]    = imx_clk_gate2("lcdif_axi",    "lcdif_axi_podf",    base + 0x74, 6);
-       clks[IMX6SL_CLK_LCDIF_PIX]    = imx_clk_gate2("lcdif_pix",    "lcdif_pix_podf",    base + 0x74, 8);
-       clks[IMX6SL_CLK_EPDC_PIX]     = imx_clk_gate2("epdc_pix",     "epdc_pix_podf",     base + 0x74, 10);
-       clks[IMX6SL_CLK_MMDC_P0_IPG]  = imx_clk_gate2_flags("mmdc_p0_ipg",  "ipg",         base + 0x74, 24, CLK_IS_CRITICAL);
-       clks[IMX6SL_CLK_MMDC_P1_IPG]  = imx_clk_gate2("mmdc_p1_ipg",  "ipg",               base + 0x74, 26);
-       clks[IMX6SL_CLK_OCRAM]        = imx_clk_gate2("ocram",        "ocram_podf",        base + 0x74, 28);
-       clks[IMX6SL_CLK_PWM1]         = imx_clk_gate2("pwm1",         "perclk",            base + 0x78, 16);
-       clks[IMX6SL_CLK_PWM2]         = imx_clk_gate2("pwm2",         "perclk",            base + 0x78, 18);
-       clks[IMX6SL_CLK_PWM3]         = imx_clk_gate2("pwm3",         "perclk",            base + 0x78, 20);
-       clks[IMX6SL_CLK_PWM4]         = imx_clk_gate2("pwm4",         "perclk",            base + 0x78, 22);
-       clks[IMX6SL_CLK_SDMA]         = imx_clk_gate2("sdma",         "ipg",               base + 0x7c, 6);
-       clks[IMX6SL_CLK_SPBA]         = imx_clk_gate2("spba",         "ipg",               base + 0x7c, 12);
-       clks[IMX6SL_CLK_SPDIF]        = imx_clk_gate2_shared("spdif",     "spdif0_podf",   base + 0x7c, 14, &share_count_spdif);
-       clks[IMX6SL_CLK_SPDIF_GCLK]   = imx_clk_gate2_shared("spdif_gclk",  "ipg",         base + 0x7c, 14, &share_count_spdif);
-       clks[IMX6SL_CLK_SSI1_IPG]     = imx_clk_gate2_shared("ssi1_ipg",     "ipg",        base + 0x7c, 18, &share_count_ssi1);
-       clks[IMX6SL_CLK_SSI2_IPG]     = imx_clk_gate2_shared("ssi2_ipg",     "ipg",        base + 0x7c, 20, &share_count_ssi2);
-       clks[IMX6SL_CLK_SSI3_IPG]     = imx_clk_gate2_shared("ssi3_ipg",     "ipg",        base + 0x7c, 22, &share_count_ssi3);
-       clks[IMX6SL_CLK_SSI1]         = imx_clk_gate2_shared("ssi1",         "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
-       clks[IMX6SL_CLK_SSI2]         = imx_clk_gate2_shared("ssi2",         "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
-       clks[IMX6SL_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",         "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
-       clks[IMX6SL_CLK_UART]         = imx_clk_gate2("uart",         "ipg",               base + 0x7c, 24);
-       clks[IMX6SL_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",  "uart_root",         base + 0x7c, 26);
-       clks[IMX6SL_CLK_USBOH3]       = imx_clk_gate2("usboh3",       "ipg",               base + 0x80, 0);
-       clks[IMX6SL_CLK_USDHC1]       = imx_clk_gate2("usdhc1",       "usdhc1_podf",       base + 0x80, 2);
-       clks[IMX6SL_CLK_USDHC2]       = imx_clk_gate2("usdhc2",       "usdhc2_podf",       base + 0x80, 4);
-       clks[IMX6SL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",       "usdhc3_podf",       base + 0x80, 6);
-       clks[IMX6SL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",       "usdhc4_podf",       base + 0x80, 8);
+       hws[IMX6SL_CLK_ECSPI1]       = imx_clk_hw_gate2("ecspi1",       "ecspi_root",        base + 0x6c, 0);
+       hws[IMX6SL_CLK_ECSPI2]       = imx_clk_hw_gate2("ecspi2",       "ecspi_root",        base + 0x6c, 2);
+       hws[IMX6SL_CLK_ECSPI3]       = imx_clk_hw_gate2("ecspi3",       "ecspi_root",        base + 0x6c, 4);
+       hws[IMX6SL_CLK_ECSPI4]       = imx_clk_hw_gate2("ecspi4",       "ecspi_root",        base + 0x6c, 6);
+       hws[IMX6SL_CLK_ENET]         = imx_clk_hw_gate2("enet",         "ipg",               base + 0x6c, 10);
+       hws[IMX6SL_CLK_EPIT1]        = imx_clk_hw_gate2("epit1",        "perclk",            base + 0x6c, 12);
+       hws[IMX6SL_CLK_EPIT2]        = imx_clk_hw_gate2("epit2",        "perclk",            base + 0x6c, 14);
+       hws[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_hw_gate2("extern_audio", "extern_audio_podf", base + 0x6c, 16);
+       hws[IMX6SL_CLK_GPT]          = imx_clk_hw_gate2("gpt",          "perclk",            base + 0x6c, 20);
+       hws[IMX6SL_CLK_GPT_SERIAL]   = imx_clk_hw_gate2("gpt_serial",   "perclk",            base + 0x6c, 22);
+       hws[IMX6SL_CLK_GPU2D_OVG]    = imx_clk_hw_gate2("gpu2d_ovg",    "gpu2d_ovg_podf",    base + 0x6c, 26);
+       hws[IMX6SL_CLK_I2C1]         = imx_clk_hw_gate2("i2c1",         "perclk",            base + 0x70, 6);
+       hws[IMX6SL_CLK_I2C2]         = imx_clk_hw_gate2("i2c2",         "perclk",            base + 0x70, 8);
+       hws[IMX6SL_CLK_I2C3]         = imx_clk_hw_gate2("i2c3",         "perclk",            base + 0x70, 10);
+       hws[IMX6SL_CLK_OCOTP]        = imx_clk_hw_gate2("ocotp",        "ipg",               base + 0x70, 12);
+       hws[IMX6SL_CLK_CSI]          = imx_clk_hw_gate2("csi",          "csi_podf",          base + 0x74, 0);
+       hws[IMX6SL_CLK_PXP_AXI]      = imx_clk_hw_gate2("pxp_axi",      "pxp_axi_podf",      base + 0x74, 2);
+       hws[IMX6SL_CLK_EPDC_AXI]     = imx_clk_hw_gate2("epdc_axi",     "epdc_axi_podf",     base + 0x74, 4);
+       hws[IMX6SL_CLK_LCDIF_AXI]    = imx_clk_hw_gate2("lcdif_axi",    "lcdif_axi_podf",    base + 0x74, 6);
+       hws[IMX6SL_CLK_LCDIF_PIX]    = imx_clk_hw_gate2("lcdif_pix",    "lcdif_pix_podf",    base + 0x74, 8);
+       hws[IMX6SL_CLK_EPDC_PIX]     = imx_clk_hw_gate2("epdc_pix",     "epdc_pix_podf",     base + 0x74, 10);
+       hws[IMX6SL_CLK_MMDC_P0_IPG]  = imx_clk_hw_gate2_flags("mmdc_p0_ipg",  "ipg",         base + 0x74, 24, CLK_IS_CRITICAL);
+       hws[IMX6SL_CLK_MMDC_P1_IPG]  = imx_clk_hw_gate2("mmdc_p1_ipg",  "ipg",               base + 0x74, 26);
+       hws[IMX6SL_CLK_OCRAM]        = imx_clk_hw_gate2("ocram",        "ocram_podf",        base + 0x74, 28);
+       hws[IMX6SL_CLK_PWM1]         = imx_clk_hw_gate2("pwm1",         "perclk",            base + 0x78, 16);
+       hws[IMX6SL_CLK_PWM2]         = imx_clk_hw_gate2("pwm2",         "perclk",            base + 0x78, 18);
+       hws[IMX6SL_CLK_PWM3]         = imx_clk_hw_gate2("pwm3",         "perclk",            base + 0x78, 20);
+       hws[IMX6SL_CLK_PWM4]         = imx_clk_hw_gate2("pwm4",         "perclk",            base + 0x78, 22);
+       hws[IMX6SL_CLK_SDMA]         = imx_clk_hw_gate2("sdma",         "ipg",               base + 0x7c, 6);
+       hws[IMX6SL_CLK_SPBA]         = imx_clk_hw_gate2("spba",         "ipg",               base + 0x7c, 12);
+       hws[IMX6SL_CLK_SPDIF]        = imx_clk_hw_gate2_shared("spdif",     "spdif0_podf",   base + 0x7c, 14, &share_count_spdif);
+       hws[IMX6SL_CLK_SPDIF_GCLK]   = imx_clk_hw_gate2_shared("spdif_gclk",  "ipg",         base + 0x7c, 14, &share_count_spdif);
+       hws[IMX6SL_CLK_SSI1_IPG]     = imx_clk_hw_gate2_shared("ssi1_ipg",     "ipg",        base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6SL_CLK_SSI2_IPG]     = imx_clk_hw_gate2_shared("ssi2_ipg",     "ipg",        base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6SL_CLK_SSI3_IPG]     = imx_clk_hw_gate2_shared("ssi3_ipg",     "ipg",        base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6SL_CLK_SSI1]         = imx_clk_hw_gate2_shared("ssi1",         "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6SL_CLK_SSI2]         = imx_clk_hw_gate2_shared("ssi2",         "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6SL_CLK_SSI3]         = imx_clk_hw_gate2_shared("ssi3",         "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6SL_CLK_UART]         = imx_clk_hw_gate2("uart",         "ipg",               base + 0x7c, 24);
+       hws[IMX6SL_CLK_UART_SERIAL]  = imx_clk_hw_gate2("uart_serial",  "uart_root",         base + 0x7c, 26);
+       hws[IMX6SL_CLK_USBOH3]       = imx_clk_hw_gate2("usboh3",       "ipg",               base + 0x80, 0);
+       hws[IMX6SL_CLK_USDHC1]       = imx_clk_hw_gate2("usdhc1",       "usdhc1_podf",       base + 0x80, 2);
+       hws[IMX6SL_CLK_USDHC2]       = imx_clk_hw_gate2("usdhc2",       "usdhc2_podf",       base + 0x80, 4);
+       hws[IMX6SL_CLK_USDHC3]       = imx_clk_hw_gate2("usdhc3",       "usdhc3_podf",       base + 0x80, 6);
+       hws[IMX6SL_CLK_USDHC4]       = imx_clk_hw_gate2("usdhc4",       "usdhc4_podf",       base + 0x80, 8);
  
        /* Ensure the MMDC CH0 handshake is bypassed */
-       writel_relaxed(readl_relaxed(base + CCDR) |
-               BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+       imx_mmdc_mask_handshake(base, 0);
  
-       imx_check_clocks(clks, ARRAY_SIZE(clks));
+       imx_check_clk_hws(hws, IMX6SL_CLK_END);
  
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
  
        /* Ensure the AHB clk is at 132MHz. */
-       ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
+       ret = clk_set_rate(hws[IMX6SL_CLK_AHB]->clk, 132000000);
        if (ret)
                pr_warn("%s: failed to set AHB clock rate %d!\n",
                        __func__, ret);
  
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
-               clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]);
-               clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]);
+               clk_prepare_enable(hws[IMX6SL_CLK_USBPHY1_GATE]->clk);
+               clk_prepare_enable(hws[IMX6SL_CLK_USBPHY2_GATE]->clk);
        }
  
        /* Audio-related clocks configuration */
-       clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]);
+       clk_set_parent(hws[IMX6SL_CLK_SPDIF0_SEL]->clk, hws[IMX6SL_CLK_PLL3_PFD3]->clk);
  
        /* set PLL5 video as lcdif pix parent clock */
-       clk_set_parent(clks[IMX6SL_CLK_LCDIF_PIX_SEL],
-                       clks[IMX6SL_CLK_PLL5_VIDEO_DIV]);
+       clk_set_parent(hws[IMX6SL_CLK_LCDIF_PIX_SEL]->clk,
+                       hws[IMX6SL_CLK_PLL5_VIDEO_DIV]->clk);
  
-       clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
-                      clks[IMX6SL_CLK_PLL2_PFD2]);
+       clk_set_parent(hws[IMX6SL_CLK_LCDIF_AXI_SEL]->clk,
+                      hws[IMX6SL_CLK_PLL2_PFD2]->clk);
+       for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) {
+               int index = uart_clk_ids[i];
+               uart_clks[i] = &hws[index]->clk;
+       }
  
        imx_register_uart_clocks(uart_clks);
  }
index d243e3483e24e9dc0847e47e997cc5dba94ccad2,2ada63e6ba16cb4ac8ee72b9ba9d0bf86a05c5e4..c4685c01929a4a4b5bb39f26af59fe0fae0a0725
@@@ -1,11 -1,18 +1,12 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2014 Freescale Semiconductor, Inc.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <dt-bindings/clock/imx6sx-clock.h>
  #include <linux/clk.h>
  #include <linux/clkdev.h>
+ #include <linux/clk-provider.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/io.h>
@@@ -16,9 -23,6 +17,6 @@@
  
  #include "clk.h"
  
- #define CCDR    0x4
- #define BM_CCM_CCDR_MMDC_CH0_MASK       (0x2 << 16)
  static const char *step_sels[]                = { "osc", "pll2_pfd2_396m", };
  static const char *pll1_sw_sels[]     = { "pll1_sys", "step", };
  static const char *periph_pre_sels[]  = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
@@@ -83,8 -87,8 +81,8 @@@ static const char *pll5_bypass_sels[] 
  static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
  static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
  
- static struct clk *clks[IMX6SX_CLK_CLK_END];
- static struct clk_onecell_data clk_data;
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
  
  static const struct clk_div_table clk_enet_ref_table[] = {
        { .val = 0, .div = 20, },
@@@ -118,76 -122,86 +116,86 @@@ static u32 share_count_ssi3
  static u32 share_count_sai1;
  static u32 share_count_sai2;
  
- static struct clk ** const uart_clks[] __initconst = {
-       &clks[IMX6SX_CLK_UART_IPG],
-       &clks[IMX6SX_CLK_UART_SERIAL],
-       NULL
+ static const int uart_clk_ids[] __initconst = {
+       IMX6SX_CLK_UART_IPG,
+       IMX6SX_CLK_UART_SERIAL,
  };
  
+ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata;
  static void __init imx6sx_clocks_init(struct device_node *ccm_node)
  {
        struct device_node *np;
        void __iomem *base;
+       int i;
+       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+                                         IMX6SX_CLK_CLK_END), GFP_KERNEL);
+       if (WARN_ON(!clk_hw_data))
+               return;
+       clk_hw_data->num = IMX6SX_CLK_CLK_END;
+       hws = clk_hw_data->hws;
  
-       clks[IMX6SX_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+       hws[IMX6SX_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
  
-       clks[IMX6SX_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
-       clks[IMX6SX_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+       hws[IMX6SX_CLK_CKIL] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ckil"));
+       hws[IMX6SX_CLK_OSC] = __clk_get_hw(of_clk_get_by_name(ccm_node, "osc"));
  
        /* ipp_di clock is external input */
-       clks[IMX6SX_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
-       clks[IMX6SX_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+       hws[IMX6SX_CLK_IPP_DI0] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ipp_di0"));
+       hws[IMX6SX_CLK_IPP_DI1] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ipp_di1"));
  
        /* Clock source from external clock via CLK1/2 PAD */
-       clks[IMX6SX_CLK_ANACLK1] = of_clk_get_by_name(ccm_node, "anaclk1");
-       clks[IMX6SX_CLK_ANACLK2] = of_clk_get_by_name(ccm_node, "anaclk2");
+       hws[IMX6SX_CLK_ANACLK1] = __clk_get_hw(of_clk_get_by_name(ccm_node, "anaclk1"));
+       hws[IMX6SX_CLK_ANACLK2] = __clk_get_hw(of_clk_get_by_name(ccm_node, "anaclk2"));
  
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop");
        base = of_iomap(np, 0);
        WARN_ON(!base);
        of_node_put(np);
  
-       clks[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6SX_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_hw_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL3_BYPASS_SRC] = imx_clk_hw_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL4_BYPASS_SRC] = imx_clk_hw_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL5_BYPASS_SRC] = imx_clk_hw_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL6_BYPASS_SRC] = imx_clk_hw_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6SX_PLL7_BYPASS_SRC] = imx_clk_hw_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
  
        /*                                    type               name    parent_name        base         div_mask */
-       clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
-       clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
-       clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
-       clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
-       clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
-       clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
-       clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
-       clks[IMX6SX_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_PLL1] = imx_clk_hw_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
+       hws[IMX6SX_CLK_PLL2] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       hws[IMX6SX_CLK_PLL3] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
+       hws[IMX6SX_CLK_PLL4] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
+       hws[IMX6SX_CLK_PLL5] = imx_clk_hw_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
+       hws[IMX6SX_CLK_PLL6] = imx_clk_hw_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
+       hws[IMX6SX_CLK_PLL7] = imx_clk_hw_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
+       hws[IMX6SX_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL4_BYPASS] = imx_clk_hw_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
  
        /* Do not bypass PLLs initially */
-       clk_set_parent(clks[IMX6SX_PLL1_BYPASS], clks[IMX6SX_CLK_PLL1]);
-       clk_set_parent(clks[IMX6SX_PLL2_BYPASS], clks[IMX6SX_CLK_PLL2]);
-       clk_set_parent(clks[IMX6SX_PLL3_BYPASS], clks[IMX6SX_CLK_PLL3]);
-       clk_set_parent(clks[IMX6SX_PLL4_BYPASS], clks[IMX6SX_CLK_PLL4]);
-       clk_set_parent(clks[IMX6SX_PLL5_BYPASS], clks[IMX6SX_CLK_PLL5]);
-       clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]);
-       clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]);
-       clks[IMX6SX_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
-       clks[IMX6SX_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
-       clks[IMX6SX_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
-       clks[IMX6SX_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
-       clks[IMX6SX_CLK_PLL5_VIDEO]    = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
-       clks[IMX6SX_CLK_PLL6_ENET]     = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
-       clks[IMX6SX_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+       clk_set_parent(hws[IMX6SX_PLL1_BYPASS]->clk, hws[IMX6SX_CLK_PLL1]->clk);
+       clk_set_parent(hws[IMX6SX_PLL2_BYPASS]->clk, hws[IMX6SX_CLK_PLL2]->clk);
+       clk_set_parent(hws[IMX6SX_PLL3_BYPASS]->clk, hws[IMX6SX_CLK_PLL3]->clk);
+       clk_set_parent(hws[IMX6SX_PLL4_BYPASS]->clk, hws[IMX6SX_CLK_PLL4]->clk);
+       clk_set_parent(hws[IMX6SX_PLL5_BYPASS]->clk, hws[IMX6SX_CLK_PLL5]->clk);
+       clk_set_parent(hws[IMX6SX_PLL6_BYPASS]->clk, hws[IMX6SX_CLK_PLL6]->clk);
+       clk_set_parent(hws[IMX6SX_PLL7_BYPASS]->clk, hws[IMX6SX_CLK_PLL7]->clk);
+       hws[IMX6SX_CLK_PLL1_SYS]      = imx_clk_hw_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       hws[IMX6SX_CLK_PLL2_BUS]      = imx_clk_hw_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
+       hws[IMX6SX_CLK_PLL3_USB_OTG]  = imx_clk_hw_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
+       hws[IMX6SX_CLK_PLL4_AUDIO]    = imx_clk_hw_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
+       hws[IMX6SX_CLK_PLL5_VIDEO]    = imx_clk_hw_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
+       hws[IMX6SX_CLK_PLL6_ENET]     = imx_clk_hw_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
+       hws[IMX6SX_CLK_PLL7_USB_HOST] = imx_clk_hw_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
  
        /*
         * Bit 20 is the reserved and read-only bit, we do this only for:
         * - Keep refcount when do usbphy clk_enable/disable, in that case,
         * the clk framework may need to enable/disable usbphy's parent
         */
-       clks[IMX6SX_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
-       clks[IMX6SX_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+       hws[IMX6SX_CLK_USBPHY1] = imx_clk_hw_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
+       hws[IMX6SX_CLK_USBPHY2] = imx_clk_hw_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
  
        /*
         * usbphy*_gate needs to be on after system boots up, and software
         * never needs to control it anymore.
         */
-       clks[IMX6SX_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
-       clks[IMX6SX_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+       hws[IMX6SX_CLK_USBPHY1_GATE] = imx_clk_hw_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+       hws[IMX6SX_CLK_USBPHY2_GATE] = imx_clk_hw_gate("usbphy2_gate", "dummy", base + 0x20, 6);
  
        /* FIXME 100MHz is used for pcie ref for all imx6 pcie, excepted imx6q */
-       clks[IMX6SX_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 5);
-       clks[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
+       hws[IMX6SX_CLK_PCIE_REF] = imx_clk_hw_fixed_factor("pcie_ref", "pll6_enet", 1, 5);
+       hws[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_hw_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
  
-       clks[IMX6SX_CLK_LVDS1_OUT] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12));
-       clks[IMX6SX_CLK_LVDS2_OUT] = imx_clk_gate_exclusive("lvds2_out", "lvds2_sel", base + 0x160, 11, BIT(13));
-       clks[IMX6SX_CLK_LVDS1_IN]  = imx_clk_gate_exclusive("lvds1_in",  "anaclk1",   base + 0x160, 12, BIT(10));
-       clks[IMX6SX_CLK_LVDS2_IN]  = imx_clk_gate_exclusive("lvds2_in",  "anaclk2",   base + 0x160, 13, BIT(11));
+       hws[IMX6SX_CLK_LVDS1_OUT] = imx_clk_hw_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x160, 10, BIT(12));
+       hws[IMX6SX_CLK_LVDS2_OUT] = imx_clk_hw_gate_exclusive("lvds2_out", "lvds2_sel", base + 0x160, 11, BIT(13));
+       hws[IMX6SX_CLK_LVDS1_IN]  = imx_clk_hw_gate_exclusive("lvds1_in",  "anaclk1",   base + 0x160, 12, BIT(10));
+       hws[IMX6SX_CLK_LVDS2_IN]  = imx_clk_hw_gate_exclusive("lvds2_in",  "anaclk2",   base + 0x160, 13, BIT(11));
  
-       clks[IMX6SX_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+       hws[IMX6SX_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
                        base + 0xe0, 0, 2, 0, clk_enet_ref_table,
                        &imx_ccm_lock);
-       clks[IMX6SX_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
+       hws[IMX6SX_CLK_ENET2_REF] = clk_hw_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
                        base + 0xe0, 2, 2, 0, clk_enet_ref_table,
                        &imx_ccm_lock);
-       clks[IMX6SX_CLK_ENET2_REF_125M] = imx_clk_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20);
+       hws[IMX6SX_CLK_ENET2_REF_125M] = imx_clk_hw_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20);
  
-       clks[IMX6SX_CLK_ENET_PTP_REF] = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
-       clks[IMX6SX_CLK_ENET_PTP] = imx_clk_gate("enet_ptp_25m", "enet_ptp_ref", base + 0xe0, 21);
+       hws[IMX6SX_CLK_ENET_PTP_REF] = imx_clk_hw_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
+       hws[IMX6SX_CLK_ENET_PTP] = imx_clk_hw_gate("enet_ptp_25m", "enet_ptp_ref", base + 0xe0, 21);
  
        /*                                       name              parent_name     reg           idx */
-       clks[IMX6SX_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
-       clks[IMX6SX_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
-       clks[IMX6SX_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
-       clks[IMX6SX_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus",     base + 0x100, 3);
-       clks[IMX6SX_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
-       clks[IMX6SX_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
-       clks[IMX6SX_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
-       clks[IMX6SX_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
+       hws[IMX6SX_CLK_PLL2_PFD0] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
+       hws[IMX6SX_CLK_PLL2_PFD1] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
+       hws[IMX6SX_CLK_PLL2_PFD2] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
+       hws[IMX6SX_CLK_PLL2_PFD3] = imx_clk_hw_pfd("pll2_pfd3_594m", "pll2_bus",     base + 0x100, 3);
+       hws[IMX6SX_CLK_PLL3_PFD0] = imx_clk_hw_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+       hws[IMX6SX_CLK_PLL3_PFD1] = imx_clk_hw_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+       hws[IMX6SX_CLK_PLL3_PFD2] = imx_clk_hw_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
+       hws[IMX6SX_CLK_PLL3_PFD3] = imx_clk_hw_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
  
        /*                                                name         parent_name       mult div */
-       clks[IMX6SX_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,   2);
-       clks[IMX6SX_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1,   4);
-       clks[IMX6SX_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,   6);
-       clks[IMX6SX_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,   8);
-       clks[IMX6SX_CLK_TWD]       = imx_clk_fixed_factor("twd",       "arm",            1,   2);
-       clks[IMX6SX_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",    "osc",            1,   8);
-       clks[IMX6SX_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+       hws[IMX6SX_CLK_PLL2_198M] = imx_clk_hw_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,   2);
+       hws[IMX6SX_CLK_PLL3_120M] = imx_clk_hw_fixed_factor("pll3_120m", "pll3_usb_otg",   1,   4);
+       hws[IMX6SX_CLK_PLL3_80M]  = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,   6);
+       hws[IMX6SX_CLK_PLL3_60M]  = imx_clk_hw_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,   8);
+       hws[IMX6SX_CLK_TWD]       = imx_clk_hw_fixed_factor("twd",       "arm",            1,   2);
+       hws[IMX6SX_CLK_GPT_3M]    = imx_clk_hw_fixed_factor("gpt_3m",    "osc",            1,   8);
+       hws[IMX6SX_CLK_PLL4_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
                                CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clks[IMX6SX_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+       hws[IMX6SX_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
                                CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
-       clks[IMX6SX_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+       hws[IMX6SX_CLK_PLL5_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll5_post_div", "pll5_video",
                                CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clks[IMX6SX_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+       hws[IMX6SX_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
                                CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
  
        /*                                                name                reg           shift   width   parent_names       num_parents */
-       clks[IMX6SX_CLK_LVDS1_SEL]          = imx_clk_mux("lvds1_sel",        base + 0x160, 0,      5,      lvds_sels,         ARRAY_SIZE(lvds_sels));
-       clks[IMX6SX_CLK_LVDS2_SEL]          = imx_clk_mux("lvds2_sel",        base + 0x160, 5,      5,      lvds_sels,         ARRAY_SIZE(lvds_sels));
+       hws[IMX6SX_CLK_LVDS1_SEL]          = imx_clk_hw_mux("lvds1_sel",        base + 0x160, 0,      5,      lvds_sels,         ARRAY_SIZE(lvds_sels));
+       hws[IMX6SX_CLK_LVDS2_SEL]          = imx_clk_hw_mux("lvds2_sel",        base + 0x160, 5,      5,      lvds_sels,         ARRAY_SIZE(lvds_sels));
  
        np = ccm_node;
        base = of_iomap(np, 0);
        WARN_ON(!base);
  
        /*                                                name                reg           shift   width   parent_names       num_parents */
-       clks[IMX6SX_CLK_STEP]               = imx_clk_mux("step",             base + 0xc,   8,      1,      step_sels,         ARRAY_SIZE(step_sels));
-       clks[IMX6SX_CLK_PLL1_SW]            = imx_clk_mux("pll1_sw",          base + 0xc,   2,      1,      pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
-       clks[IMX6SX_CLK_OCRAM_SEL]          = imx_clk_mux("ocram_sel",        base + 0x14,  6,      2,      ocram_sels,        ARRAY_SIZE(ocram_sels));
-       clks[IMX6SX_CLK_PERIPH_PRE]         = imx_clk_mux("periph_pre",       base + 0x18,  18,     2,      periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
-       clks[IMX6SX_CLK_PERIPH2_PRE]        = imx_clk_mux("periph2_pre",      base + 0x18,  21,     2,      periph2_pre_sels,   ARRAY_SIZE(periph2_pre_sels));
-       clks[IMX6SX_CLK_PERIPH_CLK2_SEL]    = imx_clk_mux("periph_clk2_sel",  base + 0x18,  12,     2,      periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
-       clks[IMX6SX_CLK_PERIPH2_CLK2_SEL]   = imx_clk_mux("periph2_clk2_sel", base + 0x18,  20,     1,      periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
-       clks[IMX6SX_CLK_PCIE_AXI_SEL]       = imx_clk_mux("pcie_axi_sel",     base + 0x18,  10,     1,      pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
-       clks[IMX6SX_CLK_GPU_AXI_SEL]        = imx_clk_mux("gpu_axi_sel",      base + 0x18,  8,      2,      gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
-       clks[IMX6SX_CLK_GPU_CORE_SEL]       = imx_clk_mux("gpu_core_sel",     base + 0x18,  4,      2,      gpu_core_sels,     ARRAY_SIZE(gpu_core_sels));
-       clks[IMX6SX_CLK_EIM_SLOW_SEL]       = imx_clk_mux("eim_slow_sel",     base + 0x1c,  29,     2,      eim_slow_sels,     ARRAY_SIZE(eim_slow_sels));
-       clks[IMX6SX_CLK_USDHC1_SEL]         = imx_clk_mux("usdhc1_sel",       base + 0x1c,  16,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-       clks[IMX6SX_CLK_USDHC2_SEL]         = imx_clk_mux("usdhc2_sel",       base + 0x1c,  17,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-       clks[IMX6SX_CLK_USDHC3_SEL]         = imx_clk_mux("usdhc3_sel",       base + 0x1c,  18,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-       clks[IMX6SX_CLK_USDHC4_SEL]         = imx_clk_mux("usdhc4_sel",       base + 0x1c,  19,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
-       clks[IMX6SX_CLK_SSI3_SEL]           = imx_clk_mux("ssi3_sel",         base + 0x1c,  14,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-       clks[IMX6SX_CLK_SSI2_SEL]           = imx_clk_mux("ssi2_sel",         base + 0x1c,  12,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-       clks[IMX6SX_CLK_SSI1_SEL]           = imx_clk_mux("ssi1_sel",         base + 0x1c,  10,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-       clks[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_mux_flags("qspi1_sel", base + 0x1c,  7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_PERCLK_SEL]         = imx_clk_mux("perclk_sel",       base + 0x1c,  6,      1,      perclk_sels,       ARRAY_SIZE(perclk_sels));
-       clks[IMX6SX_CLK_VID_SEL]            = imx_clk_mux("vid_sel",          base + 0x20,  21,     3,      vid_sels,          ARRAY_SIZE(vid_sels));
-       clks[IMX6SX_CLK_ESAI_SEL]           = imx_clk_mux("esai_sel",         base + 0x20,  19,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SX_CLK_CAN_SEL]            = imx_clk_mux("can_sel",          base + 0x20,  8,      2,      can_sels,          ARRAY_SIZE(can_sels));
-       clks[IMX6SX_CLK_UART_SEL]           = imx_clk_mux("uart_sel",         base + 0x24,  6,      1,      uart_sels,         ARRAY_SIZE(uart_sels));
-       clks[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_SPDIF_SEL]          = imx_clk_mux("spdif_sel",        base + 0x30,  20,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SX_CLK_AUDIO_SEL]          = imx_clk_mux("audio_sel",        base + 0x30,  7,      2,      audio_sels,        ARRAY_SIZE(audio_sels));
-       clks[IMX6SX_CLK_ENET_PRE_SEL]       = imx_clk_mux("enet_pre_sel",     base + 0x34,  15,     3,      enet_pre_sels,     ARRAY_SIZE(enet_pre_sels));
-       clks[IMX6SX_CLK_ENET_SEL]           = imx_clk_mux("enet_sel",         base + 0x34,  9,      3,      enet_sels,         ARRAY_SIZE(enet_sels));
-       clks[IMX6SX_CLK_M4_PRE_SEL]         = imx_clk_mux("m4_pre_sel",       base + 0x34,  6,      3,      m4_pre_sels,       ARRAY_SIZE(m4_pre_sels));
-       clks[IMX6SX_CLK_M4_SEL]             = imx_clk_mux("m4_sel",           base + 0x34,  0,      3,      m4_sels,           ARRAY_SIZE(m4_sels));
-       clks[IMX6SX_CLK_ECSPI_SEL]          = imx_clk_mux("ecspi_sel",        base + 0x38,  18,     1,      ecspi_sels,        ARRAY_SIZE(ecspi_sels));
-       clks[IMX6SX_CLK_LCDIF2_PRE_SEL]     = imx_clk_mux("lcdif2_pre_sel",   base + 0x38,  6,      3,      lcdif2_pre_sels,   ARRAY_SIZE(lcdif2_pre_sels));
-       clks[IMX6SX_CLK_LCDIF2_SEL]         = imx_clk_mux("lcdif2_sel",       base + 0x38,  0,      3,      lcdif2_sels,       ARRAY_SIZE(lcdif2_sels));
-       clks[IMX6SX_CLK_DISPLAY_SEL]        = imx_clk_mux("display_sel",      base + 0x3c,  14,     2,      display_sels,      ARRAY_SIZE(display_sels));
-       clks[IMX6SX_CLK_CSI_SEL]            = imx_clk_mux("csi_sel",          base + 0x3c,  9,      2,      csi_sels,          ARRAY_SIZE(csi_sels));
-       clks[IMX6SX_CLK_CKO1_SEL]           = imx_clk_mux("cko1_sel",         base + 0x60,  0,      4,      cko1_sels,         ARRAY_SIZE(cko1_sels));
-       clks[IMX6SX_CLK_CKO2_SEL]           = imx_clk_mux("cko2_sel",         base + 0x60,  16,     5,      cko2_sels,         ARRAY_SIZE(cko2_sels));
-       clks[IMX6SX_CLK_CKO]                = imx_clk_mux("cko",              base + 0x60,  8,      1,      cko_sels,          ARRAY_SIZE(cko_sels));
-       clks[IMX6SX_CLK_LDB_DI1_DIV_SEL]    = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_LDB_DI0_DIV_SEL]    = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_LDB_DI1_SEL]        = imx_clk_mux_flags("ldb_di1_sel",     base + 0x2c, 12, 3, ldb_di1_sels,      ARRAY_SIZE(ldb_di1_sels),    CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_LDB_DI0_SEL]        = imx_clk_mux_flags("ldb_di0_sel",     base + 0x2c, 9,  3, ldb_di0_sels,      ARRAY_SIZE(ldb_di0_sels),    CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_LCDIF1_PRE_SEL]     = imx_clk_mux_flags("lcdif1_pre_sel",  base + 0x38, 15, 3, lcdif1_pre_sels,   ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6SX_CLK_LCDIF1_SEL]         = imx_clk_mux_flags("lcdif1_sel",      base + 0x38, 9,  3, lcdif1_sels,       ARRAY_SIZE(lcdif1_sels),     CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_STEP]               = imx_clk_hw_mux("step",             base + 0xc,   8,      1,      step_sels,         ARRAY_SIZE(step_sels));
+       hws[IMX6SX_CLK_PLL1_SW]            = imx_clk_hw_mux("pll1_sw",          base + 0xc,   2,      1,      pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
+       hws[IMX6SX_CLK_OCRAM_SEL]          = imx_clk_hw_mux("ocram_sel",        base + 0x14,  6,      2,      ocram_sels,        ARRAY_SIZE(ocram_sels));
+       hws[IMX6SX_CLK_PERIPH_PRE]         = imx_clk_hw_mux("periph_pre",       base + 0x18,  18,     2,      periph_pre_sels,   ARRAY_SIZE(periph_pre_sels));
+       hws[IMX6SX_CLK_PERIPH2_PRE]        = imx_clk_hw_mux("periph2_pre",      base + 0x18,  21,     2,      periph2_pre_sels,   ARRAY_SIZE(periph2_pre_sels));
+       hws[IMX6SX_CLK_PERIPH_CLK2_SEL]    = imx_clk_hw_mux("periph_clk2_sel",  base + 0x18,  12,     2,      periph_clk2_sels,  ARRAY_SIZE(periph_clk2_sels));
+       hws[IMX6SX_CLK_PERIPH2_CLK2_SEL]   = imx_clk_hw_mux("periph2_clk2_sel", base + 0x18,  20,     1,      periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       hws[IMX6SX_CLK_PCIE_AXI_SEL]       = imx_clk_hw_mux("pcie_axi_sel",     base + 0x18,  10,     1,      pcie_axi_sels,     ARRAY_SIZE(pcie_axi_sels));
+       hws[IMX6SX_CLK_GPU_AXI_SEL]        = imx_clk_hw_mux("gpu_axi_sel",      base + 0x18,  8,      2,      gpu_axi_sels,      ARRAY_SIZE(gpu_axi_sels));
+       hws[IMX6SX_CLK_GPU_CORE_SEL]       = imx_clk_hw_mux("gpu_core_sel",     base + 0x18,  4,      2,      gpu_core_sels,     ARRAY_SIZE(gpu_core_sels));
+       hws[IMX6SX_CLK_EIM_SLOW_SEL]       = imx_clk_hw_mux("eim_slow_sel",     base + 0x1c,  29,     2,      eim_slow_sels,     ARRAY_SIZE(eim_slow_sels));
+       hws[IMX6SX_CLK_USDHC1_SEL]         = imx_clk_hw_mux("usdhc1_sel",       base + 0x1c,  16,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+       hws[IMX6SX_CLK_USDHC2_SEL]         = imx_clk_hw_mux("usdhc2_sel",       base + 0x1c,  17,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+       hws[IMX6SX_CLK_USDHC3_SEL]         = imx_clk_hw_mux("usdhc3_sel",       base + 0x1c,  18,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+       hws[IMX6SX_CLK_USDHC4_SEL]         = imx_clk_hw_mux("usdhc4_sel",       base + 0x1c,  19,     1,      usdhc_sels,        ARRAY_SIZE(usdhc_sels));
+       hws[IMX6SX_CLK_SSI3_SEL]           = imx_clk_hw_mux("ssi3_sel",         base + 0x1c,  14,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
+       hws[IMX6SX_CLK_SSI2_SEL]           = imx_clk_hw_mux("ssi2_sel",         base + 0x1c,  12,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
+       hws[IMX6SX_CLK_SSI1_SEL]           = imx_clk_hw_mux("ssi1_sel",         base + 0x1c,  10,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
+       hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux_flags("qspi1_sel", base + 0x1c,  7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_PERCLK_SEL]         = imx_clk_hw_mux("perclk_sel",       base + 0x1c,  6,      1,      perclk_sels,       ARRAY_SIZE(perclk_sels));
+       hws[IMX6SX_CLK_VID_SEL]            = imx_clk_hw_mux("vid_sel",          base + 0x20,  21,     3,      vid_sels,          ARRAY_SIZE(vid_sels));
+       hws[IMX6SX_CLK_ESAI_SEL]           = imx_clk_hw_mux("esai_sel",         base + 0x20,  19,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SX_CLK_CAN_SEL]            = imx_clk_hw_mux("can_sel",          base + 0x20,  8,      2,      can_sels,          ARRAY_SIZE(can_sels));
+       hws[IMX6SX_CLK_UART_SEL]           = imx_clk_hw_mux("uart_sel",         base + 0x24,  6,      1,      uart_sels,         ARRAY_SIZE(uart_sels));
+       hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_SPDIF_SEL]          = imx_clk_hw_mux("spdif_sel",        base + 0x30,  20,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SX_CLK_AUDIO_SEL]          = imx_clk_hw_mux("audio_sel",        base + 0x30,  7,      2,      audio_sels,        ARRAY_SIZE(audio_sels));
+       hws[IMX6SX_CLK_ENET_PRE_SEL]       = imx_clk_hw_mux("enet_pre_sel",     base + 0x34,  15,     3,      enet_pre_sels,     ARRAY_SIZE(enet_pre_sels));
+       hws[IMX6SX_CLK_ENET_SEL]           = imx_clk_hw_mux("enet_sel",         base + 0x34,  9,      3,      enet_sels,         ARRAY_SIZE(enet_sels));
+       hws[IMX6SX_CLK_M4_PRE_SEL]         = imx_clk_hw_mux("m4_pre_sel",       base + 0x34,  6,      3,      m4_pre_sels,       ARRAY_SIZE(m4_pre_sels));
+       hws[IMX6SX_CLK_M4_SEL]             = imx_clk_hw_mux("m4_sel",           base + 0x34,  0,      3,      m4_sels,           ARRAY_SIZE(m4_sels));
+       hws[IMX6SX_CLK_ECSPI_SEL]          = imx_clk_hw_mux("ecspi_sel",        base + 0x38,  18,     1,      ecspi_sels,        ARRAY_SIZE(ecspi_sels));
+       hws[IMX6SX_CLK_LCDIF2_PRE_SEL]     = imx_clk_hw_mux("lcdif2_pre_sel",   base + 0x38,  6,      3,      lcdif2_pre_sels,   ARRAY_SIZE(lcdif2_pre_sels));
+       hws[IMX6SX_CLK_LCDIF2_SEL]         = imx_clk_hw_mux("lcdif2_sel",       base + 0x38,  0,      3,      lcdif2_sels,       ARRAY_SIZE(lcdif2_sels));
+       hws[IMX6SX_CLK_DISPLAY_SEL]        = imx_clk_hw_mux("display_sel",      base + 0x3c,  14,     2,      display_sels,      ARRAY_SIZE(display_sels));
+       hws[IMX6SX_CLK_CSI_SEL]            = imx_clk_hw_mux("csi_sel",          base + 0x3c,  9,      2,      csi_sels,          ARRAY_SIZE(csi_sels));
+       hws[IMX6SX_CLK_CKO1_SEL]           = imx_clk_hw_mux("cko1_sel",         base + 0x60,  0,      4,      cko1_sels,         ARRAY_SIZE(cko1_sels));
+       hws[IMX6SX_CLK_CKO2_SEL]           = imx_clk_hw_mux("cko2_sel",         base + 0x60,  16,     5,      cko2_sels,         ARRAY_SIZE(cko2_sels));
+       hws[IMX6SX_CLK_CKO]                = imx_clk_hw_mux("cko",              base + 0x60,  8,      1,      cko_sels,          ARRAY_SIZE(cko_sels));
+       hws[IMX6SX_CLK_LDB_DI1_DIV_SEL]    = imx_clk_hw_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_LDB_DI0_DIV_SEL]    = imx_clk_hw_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_LDB_DI1_SEL]        = imx_clk_hw_mux_flags("ldb_di1_sel",     base + 0x2c, 12, 3, ldb_di1_sels,      ARRAY_SIZE(ldb_di1_sels),    CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_LDB_DI0_SEL]        = imx_clk_hw_mux_flags("ldb_di0_sel",     base + 0x2c, 9,  3, ldb_di0_sels,      ARRAY_SIZE(ldb_di0_sels),    CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_LCDIF1_PRE_SEL]     = imx_clk_hw_mux_flags("lcdif1_pre_sel",  base + 0x38, 15, 3, lcdif1_pre_sels,   ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_LCDIF1_SEL]         = imx_clk_hw_mux_flags("lcdif1_sel",      base + 0x38, 9,  3, lcdif1_sels,       ARRAY_SIZE(lcdif1_sels),     CLK_SET_RATE_PARENT);
  
        /*                                                    name              parent_name          reg          shift width */
-       clks[IMX6SX_CLK_PERIPH_CLK2]        = imx_clk_divider("periph_clk2",    "periph_clk2_sel",   base + 0x14, 27,   3);
-       clks[IMX6SX_CLK_PERIPH2_CLK2]       = imx_clk_divider("periph2_clk2",   "periph2_clk2_sel",  base + 0x14, 0,    3);
-       clks[IMX6SX_CLK_IPG]                = imx_clk_divider("ipg",            "ahb",               base + 0x14, 8,    2);
-       clks[IMX6SX_CLK_GPU_CORE_PODF]      = imx_clk_divider("gpu_core_podf",  "gpu_core_sel",      base + 0x18, 29,   3);
-       clks[IMX6SX_CLK_GPU_AXI_PODF]       = imx_clk_divider("gpu_axi_podf",   "gpu_axi_sel",       base + 0x18, 26,   3);
-       clks[IMX6SX_CLK_LCDIF1_PODF]        = imx_clk_divider("lcdif1_podf",    "lcdif1_pred",       base + 0x18, 23,   3);
-       clks[IMX6SX_CLK_QSPI1_PODF]         = imx_clk_divider("qspi1_podf",     "qspi1_sel",         base + 0x1c, 26,   3);
-       clks[IMX6SX_CLK_EIM_SLOW_PODF]      = imx_clk_divider("eim_slow_podf",  "eim_slow_sel",      base + 0x1c, 23,   3);
-       clks[IMX6SX_CLK_LCDIF2_PODF]        = imx_clk_divider("lcdif2_podf",    "lcdif2_pred",       base + 0x1c, 20,   3);
-       clks[IMX6SX_CLK_PERCLK]             = imx_clk_divider_flags("perclk", "perclk_sel", base + 0x1c, 0, 6, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_VID_PODF]           = imx_clk_divider("vid_podf",       "vid_sel",           base + 0x20, 24,   2);
-       clks[IMX6SX_CLK_CAN_PODF]           = imx_clk_divider("can_podf",       "can_sel",           base + 0x20, 2,    6);
-       clks[IMX6SX_CLK_USDHC4_PODF]        = imx_clk_divider("usdhc4_podf",    "usdhc4_sel",        base + 0x24, 22,   3);
-       clks[IMX6SX_CLK_USDHC3_PODF]        = imx_clk_divider("usdhc3_podf",    "usdhc3_sel",        base + 0x24, 19,   3);
-       clks[IMX6SX_CLK_USDHC2_PODF]        = imx_clk_divider("usdhc2_podf",    "usdhc2_sel",        base + 0x24, 16,   3);
-       clks[IMX6SX_CLK_USDHC1_PODF]        = imx_clk_divider("usdhc1_podf",    "usdhc1_sel",        base + 0x24, 11,   3);
-       clks[IMX6SX_CLK_UART_PODF]          = imx_clk_divider("uart_podf",      "uart_sel",          base + 0x24, 0,    6);
-       clks[IMX6SX_CLK_ESAI_PRED]          = imx_clk_divider("esai_pred",      "esai_sel",          base + 0x28, 9,    3);
-       clks[IMX6SX_CLK_ESAI_PODF]          = imx_clk_divider("esai_podf",      "esai_pred",         base + 0x28, 25,   3);
-       clks[IMX6SX_CLK_SSI3_PRED]          = imx_clk_divider("ssi3_pred",      "ssi3_sel",          base + 0x28, 22,   3);
-       clks[IMX6SX_CLK_SSI3_PODF]          = imx_clk_divider("ssi3_podf",      "ssi3_pred",         base + 0x28, 16,   6);
-       clks[IMX6SX_CLK_SSI1_PRED]          = imx_clk_divider("ssi1_pred",      "ssi1_sel",          base + 0x28, 6,    3);
-       clks[IMX6SX_CLK_SSI1_PODF]          = imx_clk_divider("ssi1_podf",      "ssi1_pred",         base + 0x28, 0,    6);
-       clks[IMX6SX_CLK_QSPI2_PRED]         = imx_clk_divider("qspi2_pred",     "qspi2_sel",         base + 0x2c, 18,   3);
-       clks[IMX6SX_CLK_QSPI2_PODF]         = imx_clk_divider("qspi2_podf",     "qspi2_pred",        base + 0x2c, 21,   6);
-       clks[IMX6SX_CLK_SSI2_PRED]          = imx_clk_divider("ssi2_pred",      "ssi2_sel",          base + 0x2c, 6,    3);
-       clks[IMX6SX_CLK_SSI2_PODF]          = imx_clk_divider("ssi2_podf",      "ssi2_pred",         base + 0x2c, 0,    6);
-       clks[IMX6SX_CLK_SPDIF_PRED]         = imx_clk_divider("spdif_pred",     "spdif_sel",         base + 0x30, 25,   3);
-       clks[IMX6SX_CLK_SPDIF_PODF]         = imx_clk_divider("spdif_podf",     "spdif_pred",        base + 0x30, 22,   3);
-       clks[IMX6SX_CLK_AUDIO_PRED]         = imx_clk_divider("audio_pred",     "audio_sel",         base + 0x30, 12,   3);
-       clks[IMX6SX_CLK_AUDIO_PODF]         = imx_clk_divider("audio_podf",     "audio_pred",        base + 0x30, 9,    3);
-       clks[IMX6SX_CLK_ENET_PODF]          = imx_clk_divider("enet_podf",      "enet_pre_sel",      base + 0x34, 12,   3);
-       clks[IMX6SX_CLK_M4_PODF]            = imx_clk_divider("m4_podf",        "m4_sel",            base + 0x34, 3,    3);
-       clks[IMX6SX_CLK_ECSPI_PODF]         = imx_clk_divider("ecspi_podf",     "ecspi_sel",         base + 0x38, 19,   6);
-       clks[IMX6SX_CLK_LCDIF1_PRED]        = imx_clk_divider("lcdif1_pred",    "lcdif1_pre_sel",    base + 0x38, 12,   3);
-       clks[IMX6SX_CLK_LCDIF2_PRED]        = imx_clk_divider("lcdif2_pred",    "lcdif2_pre_sel",    base + 0x38, 3,    3);
-       clks[IMX6SX_CLK_DISPLAY_PODF]       = imx_clk_divider("display_podf",   "display_sel",       base + 0x3c, 16,   3);
-       clks[IMX6SX_CLK_CSI_PODF]           = imx_clk_divider("csi_podf",       "csi_sel",           base + 0x3c, 11,   3);
-       clks[IMX6SX_CLK_CKO1_PODF]          = imx_clk_divider("cko1_podf",      "cko1_sel",          base + 0x60, 4,    3);
-       clks[IMX6SX_CLK_CKO2_PODF]          = imx_clk_divider("cko2_podf",      "cko2_sel",          base + 0x60, 21,   3);
-       clks[IMX6SX_CLK_LDB_DI0_DIV_3_5]    = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-       clks[IMX6SX_CLK_LDB_DI0_DIV_7]      = imx_clk_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
-       clks[IMX6SX_CLK_LDB_DI1_DIV_3_5]    = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
-       clks[IMX6SX_CLK_LDB_DI1_DIV_7]      = imx_clk_fixed_factor("ldb_di1_div_7",   "ldb_di1_sel", 1, 7);
+       hws[IMX6SX_CLK_PERIPH_CLK2]        = imx_clk_hw_divider("periph_clk2",    "periph_clk2_sel",   base + 0x14, 27,   3);
+       hws[IMX6SX_CLK_PERIPH2_CLK2]       = imx_clk_hw_divider("periph2_clk2",   "periph2_clk2_sel",  base + 0x14, 0,    3);
+       hws[IMX6SX_CLK_IPG]                = imx_clk_hw_divider("ipg",            "ahb",               base + 0x14, 8,    2);
+       hws[IMX6SX_CLK_GPU_CORE_PODF]      = imx_clk_hw_divider("gpu_core_podf",  "gpu_core_sel",      base + 0x18, 29,   3);
+       hws[IMX6SX_CLK_GPU_AXI_PODF]       = imx_clk_hw_divider("gpu_axi_podf",   "gpu_axi_sel",       base + 0x18, 26,   3);
+       hws[IMX6SX_CLK_LCDIF1_PODF]        = imx_clk_hw_divider("lcdif1_podf",    "lcdif1_pred",       base + 0x18, 23,   3);
+       hws[IMX6SX_CLK_QSPI1_PODF]         = imx_clk_hw_divider("qspi1_podf",     "qspi1_sel",         base + 0x1c, 26,   3);
+       hws[IMX6SX_CLK_EIM_SLOW_PODF]      = imx_clk_hw_divider("eim_slow_podf",  "eim_slow_sel",      base + 0x1c, 23,   3);
+       hws[IMX6SX_CLK_LCDIF2_PODF]        = imx_clk_hw_divider("lcdif2_podf",    "lcdif2_pred",       base + 0x1c, 20,   3);
+       hws[IMX6SX_CLK_PERCLK]             = imx_clk_hw_divider_flags("perclk", "perclk_sel", base + 0x1c, 0, 6, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_VID_PODF]           = imx_clk_hw_divider("vid_podf",       "vid_sel",           base + 0x20, 24,   2);
+       hws[IMX6SX_CLK_CAN_PODF]           = imx_clk_hw_divider("can_podf",       "can_sel",           base + 0x20, 2,    6);
+       hws[IMX6SX_CLK_USDHC4_PODF]        = imx_clk_hw_divider("usdhc4_podf",    "usdhc4_sel",        base + 0x24, 22,   3);
+       hws[IMX6SX_CLK_USDHC3_PODF]        = imx_clk_hw_divider("usdhc3_podf",    "usdhc3_sel",        base + 0x24, 19,   3);
+       hws[IMX6SX_CLK_USDHC2_PODF]        = imx_clk_hw_divider("usdhc2_podf",    "usdhc2_sel",        base + 0x24, 16,   3);
+       hws[IMX6SX_CLK_USDHC1_PODF]        = imx_clk_hw_divider("usdhc1_podf",    "usdhc1_sel",        base + 0x24, 11,   3);
+       hws[IMX6SX_CLK_UART_PODF]          = imx_clk_hw_divider("uart_podf",      "uart_sel",          base + 0x24, 0,    6);
+       hws[IMX6SX_CLK_ESAI_PRED]          = imx_clk_hw_divider("esai_pred",      "esai_sel",          base + 0x28, 9,    3);
+       hws[IMX6SX_CLK_ESAI_PODF]          = imx_clk_hw_divider("esai_podf",      "esai_pred",         base + 0x28, 25,   3);
+       hws[IMX6SX_CLK_SSI3_PRED]          = imx_clk_hw_divider("ssi3_pred",      "ssi3_sel",          base + 0x28, 22,   3);
+       hws[IMX6SX_CLK_SSI3_PODF]          = imx_clk_hw_divider("ssi3_podf",      "ssi3_pred",         base + 0x28, 16,   6);
+       hws[IMX6SX_CLK_SSI1_PRED]          = imx_clk_hw_divider("ssi1_pred",      "ssi1_sel",          base + 0x28, 6,    3);
+       hws[IMX6SX_CLK_SSI1_PODF]          = imx_clk_hw_divider("ssi1_podf",      "ssi1_pred",         base + 0x28, 0,    6);
+       hws[IMX6SX_CLK_QSPI2_PRED]         = imx_clk_hw_divider("qspi2_pred",     "qspi2_sel",         base + 0x2c, 18,   3);
+       hws[IMX6SX_CLK_QSPI2_PODF]         = imx_clk_hw_divider("qspi2_podf",     "qspi2_pred",        base + 0x2c, 21,   6);
+       hws[IMX6SX_CLK_SSI2_PRED]          = imx_clk_hw_divider("ssi2_pred",      "ssi2_sel",          base + 0x2c, 6,    3);
+       hws[IMX6SX_CLK_SSI2_PODF]          = imx_clk_hw_divider("ssi2_podf",      "ssi2_pred",         base + 0x2c, 0,    6);
+       hws[IMX6SX_CLK_SPDIF_PRED]         = imx_clk_hw_divider("spdif_pred",     "spdif_sel",         base + 0x30, 25,   3);
+       hws[IMX6SX_CLK_SPDIF_PODF]         = imx_clk_hw_divider("spdif_podf",     "spdif_pred",        base + 0x30, 22,   3);
+       hws[IMX6SX_CLK_AUDIO_PRED]         = imx_clk_hw_divider("audio_pred",     "audio_sel",         base + 0x30, 12,   3);
+       hws[IMX6SX_CLK_AUDIO_PODF]         = imx_clk_hw_divider("audio_podf",     "audio_pred",        base + 0x30, 9,    3);
+       hws[IMX6SX_CLK_ENET_PODF]          = imx_clk_hw_divider("enet_podf",      "enet_pre_sel",      base + 0x34, 12,   3);
+       hws[IMX6SX_CLK_M4_PODF]            = imx_clk_hw_divider("m4_podf",        "m4_sel",            base + 0x34, 3,    3);
+       hws[IMX6SX_CLK_ECSPI_PODF]         = imx_clk_hw_divider("ecspi_podf",     "ecspi_sel",         base + 0x38, 19,   6);
+       hws[IMX6SX_CLK_LCDIF1_PRED]        = imx_clk_hw_divider("lcdif1_pred",    "lcdif1_pre_sel",    base + 0x38, 12,   3);
+       hws[IMX6SX_CLK_LCDIF2_PRED]        = imx_clk_hw_divider("lcdif2_pred",    "lcdif2_pre_sel",    base + 0x38, 3,    3);
+       hws[IMX6SX_CLK_DISPLAY_PODF]       = imx_clk_hw_divider("display_podf",   "display_sel",       base + 0x3c, 16,   3);
+       hws[IMX6SX_CLK_CSI_PODF]           = imx_clk_hw_divider("csi_podf",       "csi_sel",           base + 0x3c, 11,   3);
+       hws[IMX6SX_CLK_CKO1_PODF]          = imx_clk_hw_divider("cko1_podf",      "cko1_sel",          base + 0x60, 4,    3);
+       hws[IMX6SX_CLK_CKO2_PODF]          = imx_clk_hw_divider("cko2_podf",      "cko2_sel",          base + 0x60, 21,   3);
+       hws[IMX6SX_CLK_LDB_DI0_DIV_3_5]    = imx_clk_hw_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       hws[IMX6SX_CLK_LDB_DI0_DIV_7]      = imx_clk_hw_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
+       hws[IMX6SX_CLK_LDB_DI1_DIV_3_5]    = imx_clk_hw_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+       hws[IMX6SX_CLK_LDB_DI1_DIV_7]      = imx_clk_hw_fixed_factor("ldb_di1_div_7",   "ldb_di1_sel", 1, 7);
  
        /*                                               name        reg          shift width busy: reg,   shift parent_names       num_parents */
-       clks[IMX6SX_CLK_PERIPH]       = imx_clk_busy_mux("periph",   base + 0x14, 25,   1,    base + 0x48, 5,    periph_sels,       ARRAY_SIZE(periph_sels));
-       clks[IMX6SX_CLK_PERIPH2]      = imx_clk_busy_mux("periph2",  base + 0x14, 26,   1,    base + 0x48, 3,    periph2_sels,      ARRAY_SIZE(periph2_sels));
+       hws[IMX6SX_CLK_PERIPH]       = imx_clk_hw_busy_mux("periph",   base + 0x14, 25,   1,    base + 0x48, 5,    periph_sels,       ARRAY_SIZE(periph_sels));
+       hws[IMX6SX_CLK_PERIPH2]      = imx_clk_hw_busy_mux("periph2",  base + 0x14, 26,   1,    base + 0x48, 3,    periph2_sels,      ARRAY_SIZE(periph2_sels));
        /*                                                   name             parent_name    reg          shift width busy: reg,   shift */
-       clks[IMX6SX_CLK_OCRAM_PODF]   = imx_clk_busy_divider("ocram_podf",    "ocram_sel",   base + 0x14, 16,   3,    base + 0x48, 0);
-       clks[IMX6SX_CLK_AHB]          = imx_clk_busy_divider("ahb",           "periph",      base + 0x14, 10,   3,    base + 0x48, 1);
-       clks[IMX6SX_CLK_MMDC_PODF]    = imx_clk_busy_divider("mmdc_podf",     "periph2",     base + 0x14, 3,    3,    base + 0x48, 2);
-       clks[IMX6SX_CLK_ARM]          = imx_clk_busy_divider("arm",           "pll1_sw",     base + 0x10, 0,    3,    base + 0x48, 16);
+       hws[IMX6SX_CLK_OCRAM_PODF]   = imx_clk_hw_busy_divider("ocram_podf",    "ocram_sel",   base + 0x14, 16,   3,    base + 0x48, 0);
+       hws[IMX6SX_CLK_AHB]          = imx_clk_hw_busy_divider("ahb",           "periph",      base + 0x14, 10,   3,    base + 0x48, 1);
+       hws[IMX6SX_CLK_MMDC_PODF]    = imx_clk_hw_busy_divider("mmdc_podf",     "periph2",     base + 0x14, 3,    3,    base + 0x48, 2);
+       hws[IMX6SX_CLK_ARM]          = imx_clk_hw_busy_divider("arm",           "pll1_sw",     base + 0x10, 0,    3,    base + 0x48, 16);
  
        /*                                            name             parent_name          reg         shift */
        /* CCGR0 */
-       clks[IMX6SX_CLK_AIPS_TZ1]     = imx_clk_gate2_flags("aips_tz1", "ahb", base + 0x68, 0, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_AIPS_TZ2]     = imx_clk_gate2_flags("aips_tz2", "ahb", base + 0x68, 2, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_APBH_DMA]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
-       clks[IMX6SX_CLK_ASRC_MEM]     = imx_clk_gate2_shared("asrc_mem", "ahb",             base + 0x68, 6, &share_count_asrc);
-       clks[IMX6SX_CLK_ASRC_IPG]     = imx_clk_gate2_shared("asrc_ipg", "ahb",             base + 0x68, 6, &share_count_asrc);
-       clks[IMX6SX_CLK_CAAM_MEM]     = imx_clk_gate2("caam_mem",      "ahb",               base + 0x68, 8);
-       clks[IMX6SX_CLK_CAAM_ACLK]    = imx_clk_gate2("caam_aclk",     "ahb",               base + 0x68, 10);
-       clks[IMX6SX_CLK_CAAM_IPG]     = imx_clk_gate2("caam_ipg",      "ipg",               base + 0x68, 12);
-       clks[IMX6SX_CLK_CAN1_IPG]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
-       clks[IMX6SX_CLK_CAN1_SERIAL]  = imx_clk_gate2("can1_serial",   "can_podf",          base + 0x68, 16);
-       clks[IMX6SX_CLK_CAN2_IPG]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
-       clks[IMX6SX_CLK_CAN2_SERIAL]  = imx_clk_gate2("can2_serial",   "can_podf",          base + 0x68, 20);
-       clks[IMX6SX_CLK_DCIC1]        = imx_clk_gate2("dcic1",         "display_podf",      base + 0x68, 24);
-       clks[IMX6SX_CLK_DCIC2]        = imx_clk_gate2("dcic2",         "display_podf",      base + 0x68, 26);
-       clks[IMX6SX_CLK_AIPS_TZ3]     = imx_clk_gate2_flags("aips_tz3", "ahb", base + 0x68, 30, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_AIPS_TZ1]     = imx_clk_hw_gate2_flags("aips_tz1", "ahb", base + 0x68, 0, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_AIPS_TZ2]     = imx_clk_hw_gate2_flags("aips_tz2", "ahb", base + 0x68, 2, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_APBH_DMA]     = imx_clk_hw_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
+       hws[IMX6SX_CLK_ASRC_MEM]     = imx_clk_hw_gate2_shared("asrc_mem", "ahb",             base + 0x68, 6, &share_count_asrc);
+       hws[IMX6SX_CLK_ASRC_IPG]     = imx_clk_hw_gate2_shared("asrc_ipg", "ahb",             base + 0x68, 6, &share_count_asrc);
+       hws[IMX6SX_CLK_CAAM_MEM]     = imx_clk_hw_gate2("caam_mem",      "ahb",               base + 0x68, 8);
+       hws[IMX6SX_CLK_CAAM_ACLK]    = imx_clk_hw_gate2("caam_aclk",     "ahb",               base + 0x68, 10);
+       hws[IMX6SX_CLK_CAAM_IPG]     = imx_clk_hw_gate2("caam_ipg",      "ipg",               base + 0x68, 12);
+       hws[IMX6SX_CLK_CAN1_IPG]     = imx_clk_hw_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
+       hws[IMX6SX_CLK_CAN1_SERIAL]  = imx_clk_hw_gate2("can1_serial",   "can_podf",          base + 0x68, 16);
+       hws[IMX6SX_CLK_CAN2_IPG]     = imx_clk_hw_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
+       hws[IMX6SX_CLK_CAN2_SERIAL]  = imx_clk_hw_gate2("can2_serial",   "can_podf",          base + 0x68, 20);
+       hws[IMX6SX_CLK_DCIC1]        = imx_clk_hw_gate2("dcic1",         "display_podf",      base + 0x68, 24);
+       hws[IMX6SX_CLK_DCIC2]        = imx_clk_hw_gate2("dcic2",         "display_podf",      base + 0x68, 26);
+       hws[IMX6SX_CLK_AIPS_TZ3]     = imx_clk_hw_gate2_flags("aips_tz3", "ahb", base + 0x68, 30, CLK_IS_CRITICAL);
  
        /* CCGR1 */
-       clks[IMX6SX_CLK_ECSPI1]       = imx_clk_gate2("ecspi1",        "ecspi_podf",        base + 0x6c, 0);
-       clks[IMX6SX_CLK_ECSPI2]       = imx_clk_gate2("ecspi2",        "ecspi_podf",        base + 0x6c, 2);
-       clks[IMX6SX_CLK_ECSPI3]       = imx_clk_gate2("ecspi3",        "ecspi_podf",        base + 0x6c, 4);
-       clks[IMX6SX_CLK_ECSPI4]       = imx_clk_gate2("ecspi4",        "ecspi_podf",        base + 0x6c, 6);
-       clks[IMX6SX_CLK_ECSPI5]       = imx_clk_gate2("ecspi5",        "ecspi_podf",        base + 0x6c, 8);
-       clks[IMX6SX_CLK_EPIT1]        = imx_clk_gate2("epit1",         "perclk",            base + 0x6c, 12);
-       clks[IMX6SX_CLK_EPIT2]        = imx_clk_gate2("epit2",         "perclk",            base + 0x6c, 14);
-       clks[IMX6SX_CLK_ESAI_EXTAL]   = imx_clk_gate2_shared("esai_extal", "esai_podf",     base + 0x6c, 16, &share_count_esai);
-       clks[IMX6SX_CLK_ESAI_IPG]     = imx_clk_gate2_shared("esai_ipg",   "ahb",           base + 0x6c, 16, &share_count_esai);
-       clks[IMX6SX_CLK_ESAI_MEM]     = imx_clk_gate2_shared("esai_mem",   "ahb",           base + 0x6c, 16, &share_count_esai);
-       clks[IMX6SX_CLK_WAKEUP]       = imx_clk_gate2_flags("wakeup", "ipg", base + 0x6c, 18, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_GPT_BUS]      = imx_clk_gate2("gpt_bus",       "perclk",            base + 0x6c, 20);
-       clks[IMX6SX_CLK_GPT_SERIAL]   = imx_clk_gate2("gpt_serial",    "perclk",            base + 0x6c, 22);
-       clks[IMX6SX_CLK_GPU]          = imx_clk_gate2("gpu",           "gpu_core_podf",     base + 0x6c, 26);
-       clks[IMX6SX_CLK_OCRAM_S]      = imx_clk_gate2("ocram_s",       "ahb",               base + 0x6c, 28);
-       clks[IMX6SX_CLK_CANFD]        = imx_clk_gate2("canfd",         "can_podf",          base + 0x6c, 30);
+       hws[IMX6SX_CLK_ECSPI1]       = imx_clk_hw_gate2("ecspi1",        "ecspi_podf",        base + 0x6c, 0);
+       hws[IMX6SX_CLK_ECSPI2]       = imx_clk_hw_gate2("ecspi2",        "ecspi_podf",        base + 0x6c, 2);
+       hws[IMX6SX_CLK_ECSPI3]       = imx_clk_hw_gate2("ecspi3",        "ecspi_podf",        base + 0x6c, 4);
+       hws[IMX6SX_CLK_ECSPI4]       = imx_clk_hw_gate2("ecspi4",        "ecspi_podf",        base + 0x6c, 6);
+       hws[IMX6SX_CLK_ECSPI5]       = imx_clk_hw_gate2("ecspi5",        "ecspi_podf",        base + 0x6c, 8);
+       hws[IMX6SX_CLK_EPIT1]        = imx_clk_hw_gate2("epit1",         "perclk",            base + 0x6c, 12);
+       hws[IMX6SX_CLK_EPIT2]        = imx_clk_hw_gate2("epit2",         "perclk",            base + 0x6c, 14);
+       hws[IMX6SX_CLK_ESAI_EXTAL]   = imx_clk_hw_gate2_shared("esai_extal", "esai_podf",     base + 0x6c, 16, &share_count_esai);
+       hws[IMX6SX_CLK_ESAI_IPG]     = imx_clk_hw_gate2_shared("esai_ipg",   "ahb",           base + 0x6c, 16, &share_count_esai);
+       hws[IMX6SX_CLK_ESAI_MEM]     = imx_clk_hw_gate2_shared("esai_mem",   "ahb",           base + 0x6c, 16, &share_count_esai);
+       hws[IMX6SX_CLK_WAKEUP]       = imx_clk_hw_gate2_flags("wakeup", "ipg", base + 0x6c, 18, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_GPT_BUS]      = imx_clk_hw_gate2("gpt_bus",       "perclk",            base + 0x6c, 20);
+       hws[IMX6SX_CLK_GPT_SERIAL]   = imx_clk_hw_gate2("gpt_serial",    "perclk",            base + 0x6c, 22);
+       hws[IMX6SX_CLK_GPU]          = imx_clk_hw_gate2("gpu",           "gpu_core_podf",     base + 0x6c, 26);
+       hws[IMX6SX_CLK_OCRAM_S]      = imx_clk_hw_gate2("ocram_s",       "ahb",               base + 0x6c, 28);
+       hws[IMX6SX_CLK_CANFD]        = imx_clk_hw_gate2("canfd",         "can_podf",          base + 0x6c, 30);
  
        /* CCGR2 */
-       clks[IMX6SX_CLK_CSI]          = imx_clk_gate2("csi",           "csi_podf",          base + 0x70, 2);
-       clks[IMX6SX_CLK_I2C1]         = imx_clk_gate2("i2c1",          "perclk",            base + 0x70, 6);
-       clks[IMX6SX_CLK_I2C2]         = imx_clk_gate2("i2c2",          "perclk",            base + 0x70, 8);
-       clks[IMX6SX_CLK_I2C3]         = imx_clk_gate2("i2c3",          "perclk",            base + 0x70, 10);
-       clks[IMX6SX_CLK_OCOTP]        = imx_clk_gate2("ocotp",         "ipg",               base + 0x70, 12);
-       clks[IMX6SX_CLK_IOMUXC]       = imx_clk_gate2("iomuxc",        "lcdif1_podf",       base + 0x70, 14);
-       clks[IMX6SX_CLK_IPMUX1]       = imx_clk_gate2_flags("ipmux1", "ahb", base + 0x70, 16, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_IPMUX2]       = imx_clk_gate2_flags("ipmux2", "ahb", base + 0x70, 18, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_IPMUX3]       = imx_clk_gate2_flags("ipmux3", "ahb", base + 0x70, 20, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_TZASC1]       = imx_clk_gate2_flags("tzasc1", "mmdc_podf", base + 0x70, 22, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_LCDIF_APB]    = imx_clk_gate2("lcdif_apb",     "display_podf",      base + 0x70, 28);
-       clks[IMX6SX_CLK_PXP_AXI]      = imx_clk_gate2("pxp_axi",       "display_podf",      base + 0x70, 30);
+       hws[IMX6SX_CLK_CSI]          = imx_clk_hw_gate2("csi",           "csi_podf",          base + 0x70, 2);
+       hws[IMX6SX_CLK_I2C1]         = imx_clk_hw_gate2("i2c1",          "perclk",            base + 0x70, 6);
+       hws[IMX6SX_CLK_I2C2]         = imx_clk_hw_gate2("i2c2",          "perclk",            base + 0x70, 8);
+       hws[IMX6SX_CLK_I2C3]         = imx_clk_hw_gate2("i2c3",          "perclk",            base + 0x70, 10);
+       hws[IMX6SX_CLK_OCOTP]        = imx_clk_hw_gate2("ocotp",         "ipg",               base + 0x70, 12);
+       hws[IMX6SX_CLK_IOMUXC]       = imx_clk_hw_gate2("iomuxc",        "lcdif1_podf",       base + 0x70, 14);
+       hws[IMX6SX_CLK_IPMUX1]       = imx_clk_hw_gate2_flags("ipmux1", "ahb", base + 0x70, 16, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_IPMUX2]       = imx_clk_hw_gate2_flags("ipmux2", "ahb", base + 0x70, 18, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_IPMUX3]       = imx_clk_hw_gate2_flags("ipmux3", "ahb", base + 0x70, 20, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_TZASC1]       = imx_clk_hw_gate2_flags("tzasc1", "mmdc_podf", base + 0x70, 22, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_LCDIF_APB]    = imx_clk_hw_gate2("lcdif_apb",     "display_podf",      base + 0x70, 28);
+       hws[IMX6SX_CLK_PXP_AXI]      = imx_clk_hw_gate2("pxp_axi",       "display_podf",      base + 0x70, 30);
  
        /* CCGR3 */
-       clks[IMX6SX_CLK_M4]           = imx_clk_gate2("m4",            "m4_podf",           base + 0x74, 2);
-       clks[IMX6SX_CLK_ENET]         = imx_clk_gate2("enet",          "ipg",               base + 0x74, 4);
-       clks[IMX6SX_CLK_ENET_AHB]     = imx_clk_gate2("enet_ahb",      "enet_sel",          base + 0x74, 4);
-       clks[IMX6SX_CLK_DISPLAY_AXI]  = imx_clk_gate2("display_axi",   "display_podf",      base + 0x74, 6);
-       clks[IMX6SX_CLK_LCDIF2_PIX]   = imx_clk_gate2("lcdif2_pix",    "lcdif2_sel",        base + 0x74, 8);
-       clks[IMX6SX_CLK_LCDIF1_PIX]   = imx_clk_gate2("lcdif1_pix",    "lcdif1_sel",        base + 0x74, 10);
-       clks[IMX6SX_CLK_LDB_DI0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_div_sel",   base + 0x74, 12);
-       clks[IMX6SX_CLK_QSPI1]        = imx_clk_gate2("qspi1",         "qspi1_podf",        base + 0x74, 14);
-       clks[IMX6SX_CLK_MLB]          = imx_clk_gate2("mlb",           "ahb",               base + 0x74, 18);
-       clks[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_gate2_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_MMDC_P0_IPG]  = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_MMDC_P1_IPG]  = imx_clk_gate2("mmdc_p1_ipg", "ipg", base + 0x74, 26);
-       clks[IMX6SX_CLK_OCRAM]        = imx_clk_gate2_flags("ocram", "ocram_podf", base + 0x74, 28, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_M4]           = imx_clk_hw_gate2("m4",            "m4_podf",           base + 0x74, 2);
+       hws[IMX6SX_CLK_ENET]         = imx_clk_hw_gate2("enet",          "ipg",               base + 0x74, 4);
+       hws[IMX6SX_CLK_ENET_AHB]     = imx_clk_hw_gate2("enet_ahb",      "enet_sel",          base + 0x74, 4);
+       hws[IMX6SX_CLK_DISPLAY_AXI]  = imx_clk_hw_gate2("display_axi",   "display_podf",      base + 0x74, 6);
+       hws[IMX6SX_CLK_LCDIF2_PIX]   = imx_clk_hw_gate2("lcdif2_pix",    "lcdif2_sel",        base + 0x74, 8);
+       hws[IMX6SX_CLK_LCDIF1_PIX]   = imx_clk_hw_gate2("lcdif1_pix",    "lcdif1_sel",        base + 0x74, 10);
+       hws[IMX6SX_CLK_LDB_DI0]      = imx_clk_hw_gate2("ldb_di0",       "ldb_di0_div_sel",   base + 0x74, 12);
+       hws[IMX6SX_CLK_QSPI1]        = imx_clk_hw_gate2("qspi1",         "qspi1_podf",        base + 0x74, 14);
+       hws[IMX6SX_CLK_MLB]          = imx_clk_hw_gate2("mlb",           "ahb",               base + 0x74, 18);
+       hws[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_hw_gate2_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_MMDC_P0_IPG]  = imx_clk_hw_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_MMDC_P1_IPG]  = imx_clk_hw_gate2_flags("mmdc_p1_ipg", "ipg", base + 0x74, 26, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_OCRAM]        = imx_clk_hw_gate2_flags("ocram", "ocram_podf", base + 0x74, 28, CLK_IS_CRITICAL);
  
        /* CCGR4 */
-       clks[IMX6SX_CLK_PCIE_AXI]     = imx_clk_gate2("pcie_axi",      "display_podf",      base + 0x78, 0);
-       clks[IMX6SX_CLK_QSPI2]        = imx_clk_gate2("qspi2",         "qspi2_podf",        base + 0x78, 10);
-       clks[IMX6SX_CLK_PER1_BCH]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
-       clks[IMX6SX_CLK_PER2_MAIN]    = imx_clk_gate2_flags("per2_main", "ahb", base + 0x78, 14, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_PWM1]         = imx_clk_gate2("pwm1",          "perclk",            base + 0x78, 16);
-       clks[IMX6SX_CLK_PWM2]         = imx_clk_gate2("pwm2",          "perclk",            base + 0x78, 18);
-       clks[IMX6SX_CLK_PWM3]         = imx_clk_gate2("pwm3",          "perclk",            base + 0x78, 20);
-       clks[IMX6SX_CLK_PWM4]         = imx_clk_gate2("pwm4",          "perclk",            base + 0x78, 22);
-       clks[IMX6SX_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
-       clks[IMX6SX_CLK_GPMI_BCH]     = imx_clk_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
-       clks[IMX6SX_CLK_GPMI_IO]      = imx_clk_gate2("gpmi_io",       "qspi2_podf",        base + 0x78, 28);
-       clks[IMX6SX_CLK_GPMI_APB]     = imx_clk_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
+       hws[IMX6SX_CLK_PCIE_AXI]     = imx_clk_hw_gate2("pcie_axi",      "display_podf",      base + 0x78, 0);
+       hws[IMX6SX_CLK_QSPI2]        = imx_clk_hw_gate2("qspi2",         "qspi2_podf",        base + 0x78, 10);
+       hws[IMX6SX_CLK_PER1_BCH]     = imx_clk_hw_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
+       hws[IMX6SX_CLK_PER2_MAIN]    = imx_clk_hw_gate2_flags("per2_main", "ahb", base + 0x78, 14, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_PWM1]         = imx_clk_hw_gate2("pwm1",          "perclk",            base + 0x78, 16);
+       hws[IMX6SX_CLK_PWM2]         = imx_clk_hw_gate2("pwm2",          "perclk",            base + 0x78, 18);
+       hws[IMX6SX_CLK_PWM3]         = imx_clk_hw_gate2("pwm3",          "perclk",            base + 0x78, 20);
+       hws[IMX6SX_CLK_PWM4]         = imx_clk_hw_gate2("pwm4",          "perclk",            base + 0x78, 22);
+       hws[IMX6SX_CLK_GPMI_BCH_APB] = imx_clk_hw_gate2("gpmi_bch_apb",  "usdhc3",            base + 0x78, 24);
+       hws[IMX6SX_CLK_GPMI_BCH]     = imx_clk_hw_gate2("gpmi_bch",      "usdhc4",            base + 0x78, 26);
+       hws[IMX6SX_CLK_GPMI_IO]      = imx_clk_hw_gate2("gpmi_io",       "qspi2_podf",        base + 0x78, 28);
+       hws[IMX6SX_CLK_GPMI_APB]     = imx_clk_hw_gate2("gpmi_apb",      "usdhc3",            base + 0x78, 30);
  
        /* CCGR5 */
-       clks[IMX6SX_CLK_ROM]          = imx_clk_gate2_flags("rom", "ahb", base + 0x7c, 0, CLK_IS_CRITICAL);
-       clks[IMX6SX_CLK_SDMA]         = imx_clk_gate2("sdma",          "ahb",               base + 0x7c, 6);
-       clks[IMX6SX_CLK_SPBA]         = imx_clk_gate2("spba",          "ipg",               base + 0x7c, 12);
-       clks[IMX6SX_CLK_AUDIO]        = imx_clk_gate2_shared("audio",  "audio_podf",        base + 0x7c, 14, &share_count_audio);
-       clks[IMX6SX_CLK_SPDIF]        = imx_clk_gate2_shared("spdif",  "spdif_podf",        base + 0x7c, 14, &share_count_audio);
-       clks[IMX6SX_CLK_SPDIF_GCLK]   = imx_clk_gate2_shared("spdif_gclk",    "ipg",        base + 0x7c, 14, &share_count_audio);
-       clks[IMX6SX_CLK_SSI1_IPG]     = imx_clk_gate2_shared("ssi1_ipg",      "ipg",        base + 0x7c, 18, &share_count_ssi1);
-       clks[IMX6SX_CLK_SSI2_IPG]     = imx_clk_gate2_shared("ssi2_ipg",      "ipg",        base + 0x7c, 20, &share_count_ssi2);
-       clks[IMX6SX_CLK_SSI3_IPG]     = imx_clk_gate2_shared("ssi3_ipg",      "ipg",        base + 0x7c, 22, &share_count_ssi3);
-       clks[IMX6SX_CLK_SSI1]         = imx_clk_gate2_shared("ssi1",          "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
-       clks[IMX6SX_CLK_SSI2]         = imx_clk_gate2_shared("ssi2",          "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
-       clks[IMX6SX_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
-       clks[IMX6SX_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
-       clks[IMX6SX_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_podf",         base + 0x7c, 26);
-       clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2_shared("sai1_ipg", "ipg",             base + 0x7c, 28, &share_count_sai1);
-       clks[IMX6SX_CLK_SAI2_IPG]     = imx_clk_gate2_shared("sai2_ipg", "ipg",             base + 0x7c, 30, &share_count_sai2);
-       clks[IMX6SX_CLK_SAI1]         = imx_clk_gate2_shared("sai1",    "ssi1_podf",        base + 0x7c, 28, &share_count_sai1);
-       clks[IMX6SX_CLK_SAI2]         = imx_clk_gate2_shared("sai2",    "ssi2_podf",        base + 0x7c, 30, &share_count_sai2);
+       hws[IMX6SX_CLK_ROM]          = imx_clk_hw_gate2_flags("rom", "ahb", base + 0x7c, 0, CLK_IS_CRITICAL);
+       hws[IMX6SX_CLK_SDMA]         = imx_clk_hw_gate2("sdma",          "ahb",               base + 0x7c, 6);
+       hws[IMX6SX_CLK_SPBA]         = imx_clk_hw_gate2("spba",          "ipg",               base + 0x7c, 12);
+       hws[IMX6SX_CLK_AUDIO]        = imx_clk_hw_gate2_shared("audio",  "audio_podf",        base + 0x7c, 14, &share_count_audio);
+       hws[IMX6SX_CLK_SPDIF]        = imx_clk_hw_gate2_shared("spdif",  "spdif_podf",        base + 0x7c, 14, &share_count_audio);
+       hws[IMX6SX_CLK_SPDIF_GCLK]   = imx_clk_hw_gate2_shared("spdif_gclk",    "ipg",        base + 0x7c, 14, &share_count_audio);
+       hws[IMX6SX_CLK_SSI1_IPG]     = imx_clk_hw_gate2_shared("ssi1_ipg",      "ipg",        base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6SX_CLK_SSI2_IPG]     = imx_clk_hw_gate2_shared("ssi2_ipg",      "ipg",        base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6SX_CLK_SSI3_IPG]     = imx_clk_hw_gate2_shared("ssi3_ipg",      "ipg",        base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6SX_CLK_SSI1]         = imx_clk_hw_gate2_shared("ssi1",          "ssi1_podf",  base + 0x7c, 18, &share_count_ssi1);
+       hws[IMX6SX_CLK_SSI2]         = imx_clk_hw_gate2_shared("ssi2",          "ssi2_podf",  base + 0x7c, 20, &share_count_ssi2);
+       hws[IMX6SX_CLK_SSI3]         = imx_clk_hw_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
+       hws[IMX6SX_CLK_UART_IPG]     = imx_clk_hw_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
+       hws[IMX6SX_CLK_UART_SERIAL]  = imx_clk_hw_gate2("uart_serial",   "uart_podf",         base + 0x7c, 26);
+       hws[IMX6SX_CLK_SAI1_IPG]     = imx_clk_hw_gate2_shared("sai1_ipg", "ipg",             base + 0x7c, 28, &share_count_sai1);
+       hws[IMX6SX_CLK_SAI2_IPG]     = imx_clk_hw_gate2_shared("sai2_ipg", "ipg",             base + 0x7c, 30, &share_count_sai2);
+       hws[IMX6SX_CLK_SAI1]         = imx_clk_hw_gate2_shared("sai1",  "ssi1_podf",        base + 0x7c, 28, &share_count_sai1);
+       hws[IMX6SX_CLK_SAI2]         = imx_clk_hw_gate2_shared("sai2",  "ssi2_podf",        base + 0x7c, 30, &share_count_sai2);
  
        /* CCGR6 */
-       clks[IMX6SX_CLK_USBOH3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
-       clks[IMX6SX_CLK_USDHC1]       = imx_clk_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
-       clks[IMX6SX_CLK_USDHC2]       = imx_clk_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
-       clks[IMX6SX_CLK_USDHC3]       = imx_clk_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
-       clks[IMX6SX_CLK_USDHC4]       = imx_clk_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
-       clks[IMX6SX_CLK_EIM_SLOW]     = imx_clk_gate2("eim_slow",      "eim_slow_podf",     base + 0x80, 10);
-       clks[IMX6SX_CLK_PWM8]         = imx_clk_gate2("pwm8",          "perclk",            base + 0x80, 16);
-       clks[IMX6SX_CLK_VADC]         = imx_clk_gate2("vadc",          "vid_podf",          base + 0x80, 20);
-       clks[IMX6SX_CLK_GIS]          = imx_clk_gate2("gis",           "display_podf",      base + 0x80, 22);
-       clks[IMX6SX_CLK_I2C4]         = imx_clk_gate2("i2c4",          "perclk",            base + 0x80, 24);
-       clks[IMX6SX_CLK_PWM5]         = imx_clk_gate2("pwm5",          "perclk",            base + 0x80, 26);
-       clks[IMX6SX_CLK_PWM6]         = imx_clk_gate2("pwm6",          "perclk",            base + 0x80, 28);
-       clks[IMX6SX_CLK_PWM7]         = imx_clk_gate2("pwm7",          "perclk",            base + 0x80, 30);
-       clks[IMX6SX_CLK_CKO1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
-       clks[IMX6SX_CLK_CKO2]         = imx_clk_gate("cko2",           "cko2_podf",         base + 0x60, 24);
+       hws[IMX6SX_CLK_USBOH3]       = imx_clk_hw_gate2("usboh3",        "ipg",               base + 0x80, 0);
+       hws[IMX6SX_CLK_USDHC1]       = imx_clk_hw_gate2("usdhc1",        "usdhc1_podf",       base + 0x80, 2);
+       hws[IMX6SX_CLK_USDHC2]       = imx_clk_hw_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
+       hws[IMX6SX_CLK_USDHC3]       = imx_clk_hw_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
+       hws[IMX6SX_CLK_USDHC4]       = imx_clk_hw_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
+       hws[IMX6SX_CLK_EIM_SLOW]     = imx_clk_hw_gate2("eim_slow",      "eim_slow_podf",     base + 0x80, 10);
+       hws[IMX6SX_CLK_PWM8]         = imx_clk_hw_gate2("pwm8",          "perclk",            base + 0x80, 16);
+       hws[IMX6SX_CLK_VADC]         = imx_clk_hw_gate2("vadc",          "vid_podf",          base + 0x80, 20);
+       hws[IMX6SX_CLK_GIS]          = imx_clk_hw_gate2("gis",           "display_podf",      base + 0x80, 22);
+       hws[IMX6SX_CLK_I2C4]         = imx_clk_hw_gate2("i2c4",          "perclk",            base + 0x80, 24);
+       hws[IMX6SX_CLK_PWM5]         = imx_clk_hw_gate2("pwm5",          "perclk",            base + 0x80, 26);
+       hws[IMX6SX_CLK_PWM6]         = imx_clk_hw_gate2("pwm6",          "perclk",            base + 0x80, 28);
+       hws[IMX6SX_CLK_PWM7]         = imx_clk_hw_gate2("pwm7",          "perclk",            base + 0x80, 30);
+       hws[IMX6SX_CLK_CKO1]         = imx_clk_hw_gate("cko1",           "cko1_podf",         base + 0x60, 7);
+       hws[IMX6SX_CLK_CKO2]         = imx_clk_hw_gate("cko2",           "cko2_podf",         base + 0x60, 24);
  
        /* mask handshake of mmdc */
-       writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+       imx_mmdc_mask_handshake(base, 0);
  
-       imx_check_clocks(clks, ARRAY_SIZE(clks));
+       imx_check_clk_hws(hws, IMX6SX_CLK_CLK_END);
  
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
  
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
-               clk_prepare_enable(clks[IMX6SX_CLK_USBPHY1_GATE]);
-               clk_prepare_enable(clks[IMX6SX_CLK_USBPHY2_GATE]);
+               clk_prepare_enable(hws[IMX6SX_CLK_USBPHY1_GATE]->clk);
+               clk_prepare_enable(hws[IMX6SX_CLK_USBPHY2_GATE]->clk);
        }
  
        /* Set the default 132MHz for EIM module */
-       clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
-       clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000);
+       clk_set_parent(hws[IMX6SX_CLK_EIM_SLOW_SEL]->clk, hws[IMX6SX_CLK_PLL2_PFD2]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_EIM_SLOW]->clk, 132000000);
  
        /* set parent clock for LCDIF1 pixel clock */
-       clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]);
-       clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]);
+       clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk, hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk, hws[IMX6SX_CLK_LCDIF1_PODF]->clk);
  
        /* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */
-       if (clk_set_parent(clks[IMX6SX_CLK_LVDS1_SEL], clks[IMX6SX_CLK_PCIE_REF_125M]))
+       if (clk_set_parent(hws[IMX6SX_CLK_LVDS1_SEL]->clk, hws[IMX6SX_CLK_PCIE_REF_125M]->clk))
                pr_err("Failed to set pcie bus parent clk.\n");
-       if (clk_set_parent(clks[IMX6SX_CLK_PCIE_AXI_SEL], clks[IMX6SX_CLK_AXI]))
-               pr_err("Failed to set pcie parent clk.\n");
  
        /*
         * Init enet system AHB clock, set to 200MHz
         * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB
         */
-       clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]);
-       clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]);
-       clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000);
-       clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000);
-       clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000);
+       clk_set_parent(hws[IMX6SX_CLK_ENET_PRE_SEL]->clk, hws[IMX6SX_CLK_PLL2_PFD2]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_ENET_SEL]->clk, hws[IMX6SX_CLK_ENET_PODF]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_ENET_PODF]->clk, 200000000);
+       clk_set_rate(hws[IMX6SX_CLK_ENET_REF]->clk, 125000000);
+       clk_set_rate(hws[IMX6SX_CLK_ENET2_REF]->clk, 125000000);
  
        /* Audio clocks */
-       clk_set_rate(clks[IMX6SX_CLK_PLL4_AUDIO_DIV], 393216000);
+       clk_set_rate(hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk, 393216000);
  
-       clk_set_parent(clks[IMX6SX_CLK_SPDIF_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
-       clk_set_rate(clks[IMX6SX_CLK_SPDIF_PODF], 98304000);
+       clk_set_parent(hws[IMX6SX_CLK_SPDIF_SEL]->clk, hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_SPDIF_PODF]->clk, 98304000);
  
-       clk_set_parent(clks[IMX6SX_CLK_AUDIO_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
-       clk_set_rate(clks[IMX6SX_CLK_AUDIO_PODF], 24000000);
+       clk_set_parent(hws[IMX6SX_CLK_AUDIO_SEL]->clk, hws[IMX6SX_CLK_PLL3_USB_OTG]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_AUDIO_PODF]->clk, 24000000);
  
-       clk_set_parent(clks[IMX6SX_CLK_SSI1_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
-       clk_set_parent(clks[IMX6SX_CLK_SSI2_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
-       clk_set_parent(clks[IMX6SX_CLK_SSI3_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
-       clk_set_rate(clks[IMX6SX_CLK_SSI1_PODF], 24576000);
-       clk_set_rate(clks[IMX6SX_CLK_SSI2_PODF], 24576000);
-       clk_set_rate(clks[IMX6SX_CLK_SSI3_PODF], 24576000);
+       clk_set_parent(hws[IMX6SX_CLK_SSI1_SEL]->clk, hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_SSI2_SEL]->clk, hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_SSI3_SEL]->clk, hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_SSI1_PODF]->clk, 24576000);
+       clk_set_rate(hws[IMX6SX_CLK_SSI2_PODF]->clk, 24576000);
+       clk_set_rate(hws[IMX6SX_CLK_SSI3_PODF]->clk, 24576000);
  
-       clk_set_parent(clks[IMX6SX_CLK_ESAI_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]);
-       clk_set_rate(clks[IMX6SX_CLK_ESAI_PODF], 24576000);
+       clk_set_parent(hws[IMX6SX_CLK_ESAI_SEL]->clk, hws[IMX6SX_CLK_PLL4_AUDIO_DIV]->clk);
+       clk_set_rate(hws[IMX6SX_CLK_ESAI_PODF]->clk, 24576000);
  
        /* Set parent clock for vadc */
-       clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]);
+       clk_set_parent(hws[IMX6SX_CLK_VID_SEL]->clk, hws[IMX6SX_CLK_PLL3_USB_OTG]->clk);
  
        /* default parent of can_sel clock is invalid, manually set it here */
-       clk_set_parent(clks[IMX6SX_CLK_CAN_SEL], clks[IMX6SX_CLK_PLL3_60M]);
+       clk_set_parent(hws[IMX6SX_CLK_CAN_SEL]->clk, hws[IMX6SX_CLK_PLL3_60M]->clk);
  
        /* Update gpu clock from default 528M to 720M */
-       clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
-       clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]);
+       clk_set_parent(hws[IMX6SX_CLK_GPU_CORE_SEL]->clk, hws[IMX6SX_CLK_PLL3_PFD0]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_GPU_AXI_SEL]->clk, hws[IMX6SX_CLK_PLL3_PFD0]->clk);
  
-       clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
-       clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
+       clk_set_parent(hws[IMX6SX_CLK_QSPI1_SEL]->clk, hws[IMX6SX_CLK_PLL2_BUS]->clk);
+       clk_set_parent(hws[IMX6SX_CLK_QSPI2_SEL]->clk, hws[IMX6SX_CLK_PLL2_BUS]->clk);
+       for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) {
+               int index = uart_clk_ids[i];
+               uart_clks[i] = &hws[index]->clk;
+       }
  
        imx_register_uart_clocks(uart_clks);
  }
index 8fd52e103cc299443ef0b012293018171abc2b51,d860a244363a9da049d139ae0ec3a2179db52e1f..bc931988fe7b245ada0c460ed182ecfcdaa19689
@@@ -1,11 -1,18 +1,12 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2015 Freescale Semiconductor, Inc.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <dt-bindings/clock/imx6ul-clock.h>
  #include <linux/clk.h>
  #include <linux/clkdev.h>
+ #include <linux/clk-provider.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/io.h>
@@@ -16,9 -23,6 +17,6 @@@
  
  #include "clk.h"
  
- #define BM_CCM_CCDR_MMDC_CH0_MASK     (0x2 << 16)
- #define CCDR  0x4
  static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
  static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
  static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
@@@ -70,8 -74,8 +68,8 @@@ static const char *cko2_sels[] = { "dum
                                   "dummy", "dummy", "dummy", "dummy", "uart_serial", "spdif", "dummy", "dummy", };
  static const char *cko_sels[] = { "cko1", "cko2", };
  
- static struct clk *clks[IMX6UL_CLK_END];
- static struct clk_onecell_data clk_data;
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
  
  static const struct clk_div_table clk_enet_ref_table[] = {
        { .val = 0, .div = 20, },
@@@ -118,61 -122,69 +116,69 @@@ static void __init imx6ul_clocks_init(s
        struct device_node *np;
        void __iomem *base;
  
-       clks[IMX6UL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+                                         IMX6UL_CLK_END), GFP_KERNEL);
+       if (WARN_ON(!clk_hw_data))
+               return;
+       clk_hw_data->num = IMX6UL_CLK_END;
+       hws = clk_hw_data->hws;
+       hws[IMX6UL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
  
-       clks[IMX6UL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
-       clks[IMX6UL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+       hws[IMX6UL_CLK_CKIL] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ckil"));
+       hws[IMX6UL_CLK_OSC] = __clk_get_hw(of_clk_get_by_name(ccm_node, "osc"));
  
        /* ipp_di clock is external input */
-       clks[IMX6UL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
-       clks[IMX6UL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+       hws[IMX6UL_CLK_IPP_DI0] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ipp_di0"));
+       hws[IMX6UL_CLK_IPP_DI1] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ipp_di1"));
  
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
        base = of_iomap(np, 0);
        of_node_put(np);
        WARN_ON(!base);
  
-       clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
-       clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "osc", base + 0x00, 0x7f);
-       clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
-       clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "osc", base + 0x10, 0x3);
-       clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "osc", base + 0x70, 0x7f);
-       clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "osc", base + 0xa0, 0x7f);
-       clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "osc", base + 0xe0, 0x3);
-       clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "osc", base + 0x20, 0x3);
-       clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL2_BYPASS_SRC] = imx_clk_hw_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL3_BYPASS_SRC] = imx_clk_hw_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL4_BYPASS_SRC] = imx_clk_hw_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL5_BYPASS_SRC] = imx_clk_hw_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_hw_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_hw_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       hws[IMX6UL_CLK_PLL1] = imx_clk_hw_pllv3(IMX_PLLV3_SYS,   "pll1", "osc", base + 0x00, 0x7f);
+       hws[IMX6UL_CLK_PLL2] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+       hws[IMX6UL_CLK_PLL3] = imx_clk_hw_pllv3(IMX_PLLV3_USB,   "pll3", "osc", base + 0x10, 0x3);
+       hws[IMX6UL_CLK_PLL4] = imx_clk_hw_pllv3(IMX_PLLV3_AV,    "pll4", "osc", base + 0x70, 0x7f);
+       hws[IMX6UL_CLK_PLL5] = imx_clk_hw_pllv3(IMX_PLLV3_AV,    "pll5", "osc", base + 0xa0, 0x7f);
+       hws[IMX6UL_CLK_PLL6] = imx_clk_hw_pllv3(IMX_PLLV3_ENET,  "pll6", "osc", base + 0xe0, 0x3);
+       hws[IMX6UL_CLK_PLL7] = imx_clk_hw_pllv3(IMX_PLLV3_USB,   "pll7", "osc", base + 0x20, 0x3);
+       hws[IMX6UL_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL4_BYPASS] = imx_clk_hw_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
  
        /* Do not bypass PLLs initially */
-       clk_set_parent(clks[IMX6UL_PLL1_BYPASS], clks[IMX6UL_CLK_PLL1]);
-       clk_set_parent(clks[IMX6UL_PLL2_BYPASS], clks[IMX6UL_CLK_PLL2]);
-       clk_set_parent(clks[IMX6UL_PLL3_BYPASS], clks[IMX6UL_CLK_PLL3]);
-       clk_set_parent(clks[IMX6UL_PLL4_BYPASS], clks[IMX6UL_CLK_PLL4]);
-       clk_set_parent(clks[IMX6UL_PLL5_BYPASS], clks[IMX6UL_CLK_PLL5]);
-       clk_set_parent(clks[IMX6UL_PLL6_BYPASS], clks[IMX6UL_CLK_PLL6]);
-       clk_set_parent(clks[IMX6UL_PLL7_BYPASS], clks[IMX6UL_CLK_PLL7]);
-       clks[IMX6UL_CLK_PLL1_SYS]       = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
-       clks[IMX6UL_CLK_PLL2_BUS]       = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
-       clks[IMX6UL_CLK_PLL3_USB_OTG]   = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
-       clks[IMX6UL_CLK_PLL4_AUDIO]     = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
-       clks[IMX6UL_CLK_PLL5_VIDEO]     = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
-       clks[IMX6UL_CLK_PLL6_ENET]      = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
-       clks[IMX6UL_CLK_PLL7_USB_HOST]  = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+       clk_set_parent(hws[IMX6UL_PLL1_BYPASS]->clk, hws[IMX6UL_CLK_PLL1]->clk);
+       clk_set_parent(hws[IMX6UL_PLL2_BYPASS]->clk, hws[IMX6UL_CLK_PLL2]->clk);
+       clk_set_parent(hws[IMX6UL_PLL3_BYPASS]->clk, hws[IMX6UL_CLK_PLL3]->clk);
+       clk_set_parent(hws[IMX6UL_PLL4_BYPASS]->clk, hws[IMX6UL_CLK_PLL4]->clk);
+       clk_set_parent(hws[IMX6UL_PLL5_BYPASS]->clk, hws[IMX6UL_CLK_PLL5]->clk);
+       clk_set_parent(hws[IMX6UL_PLL6_BYPASS]->clk, hws[IMX6UL_CLK_PLL6]->clk);
+       clk_set_parent(hws[IMX6UL_PLL7_BYPASS]->clk, hws[IMX6UL_CLK_PLL7]->clk);
+       hws[IMX6UL_CLK_PLL1_SYS]        = imx_clk_hw_fixed_factor("pll1_sys",   "pll1_bypass", 1, 1);
+       hws[IMX6UL_CLK_PLL2_BUS]        = imx_clk_hw_gate("pll2_bus",   "pll2_bypass", base + 0x30, 13);
+       hws[IMX6UL_CLK_PLL3_USB_OTG]    = imx_clk_hw_gate("pll3_usb_otg",       "pll3_bypass", base + 0x10, 13);
+       hws[IMX6UL_CLK_PLL4_AUDIO]      = imx_clk_hw_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
+       hws[IMX6UL_CLK_PLL5_VIDEO]      = imx_clk_hw_gate("pll5_video", "pll5_bypass", base + 0xa0, 13);
+       hws[IMX6UL_CLK_PLL6_ENET]       = imx_clk_hw_gate("pll6_enet",  "pll6_bypass", base + 0xe0, 13);
+       hws[IMX6UL_CLK_PLL7_USB_HOST]   = imx_clk_hw_gate("pll7_usb_host",      "pll7_bypass", base + 0x20, 13);
  
        /*
         * Bit 20 is the reserved and read-only bit, we do this only for:
         * - Keep refcount when do usbphy clk_enable/disable, in that case,
         * the clk framework many need to enable/disable usbphy's parent
         */
-       clks[IMX6UL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
-       clks[IMX6UL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+       hws[IMX6UL_CLK_USBPHY1] = imx_clk_hw_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
+       hws[IMX6UL_CLK_USBPHY2] = imx_clk_hw_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
  
        /*
         * usbphy*_gate needs to be on after system boots up, and software
         * never needs to control it anymore.
         */
-       clks[IMX6UL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
-       clks[IMX6UL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+       hws[IMX6UL_CLK_USBPHY1_GATE] = imx_clk_hw_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+       hws[IMX6UL_CLK_USBPHY2_GATE] = imx_clk_hw_gate("usbphy2_gate", "dummy", base + 0x20, 6);
  
        /*                                      name               parent_name     reg          idx */
-       clks[IMX6UL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
-       clks[IMX6UL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
-       clks[IMX6UL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
-       clks[IMX6UL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus",     base + 0x100, 3);
-       clks[IMX6UL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
-       clks[IMX6UL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
-       clks[IMX6UL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
-       clks[IMX6UL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
-       clks[IMX6UL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+       hws[IMX6UL_CLK_PLL2_PFD0] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_bus",           base + 0x100, 0);
+       hws[IMX6UL_CLK_PLL2_PFD1] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_bus",           base + 0x100, 1);
+       hws[IMX6UL_CLK_PLL2_PFD2] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_bus",           base + 0x100, 2);
+       hws[IMX6UL_CLK_PLL2_PFD3] = imx_clk_hw_pfd("pll2_pfd3_594m", "pll2_bus",           base + 0x100, 3);
+       hws[IMX6UL_CLK_PLL3_PFD0] = imx_clk_hw_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+       hws[IMX6UL_CLK_PLL3_PFD1] = imx_clk_hw_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+       hws[IMX6UL_CLK_PLL3_PFD2] = imx_clk_hw_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,        2);
+       hws[IMX6UL_CLK_PLL3_PFD3] = imx_clk_hw_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,        3);
+       hws[IMX6UL_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
                        base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
-       clks[IMX6UL_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
+       hws[IMX6UL_CLK_ENET2_REF] = clk_hw_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
                        base + 0xe0, 2, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
  
-       clks[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
-       clks[IMX6UL_CLK_ENET_PTP_REF]   = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
-       clks[IMX6UL_CLK_ENET_PTP]       = imx_clk_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
+       hws[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_hw_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
+       hws[IMX6UL_CLK_ENET_PTP_REF]    = imx_clk_hw_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
+       hws[IMX6UL_CLK_ENET_PTP]        = imx_clk_hw_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
  
-       clks[IMX6UL_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+       hws[IMX6UL_CLK_PLL4_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
                 CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clks[IMX6UL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+       hws[IMX6UL_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
                 CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
-       clks[IMX6UL_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+       hws[IMX6UL_CLK_PLL5_POST_DIV]  = clk_hw_register_divider_table(NULL, "pll5_post_div", "pll5_video",
                 CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
-       clks[IMX6UL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+       hws[IMX6UL_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
                 CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
  
        /*                                                 name         parent_name      mult  div */
-       clks[IMX6UL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,     2);
-       clks[IMX6UL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,     6);
-       clks[IMX6UL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,     8);
-       clks[IMX6UL_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",     "osc",           1,     8);
+       hws[IMX6UL_CLK_PLL2_198M] = imx_clk_hw_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,   2);
+       hws[IMX6UL_CLK_PLL3_80M]  = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,   6);
+       hws[IMX6UL_CLK_PLL3_60M]  = imx_clk_hw_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,   8);
+       hws[IMX6UL_CLK_GPT_3M]     = imx_clk_hw_fixed_factor("gpt_3m",  "osc",           1,     8);
  
        np = ccm_node;
        base = of_iomap(np, 0);
        WARN_ON(!base);
  
-       clks[IMX6UL_CA7_SECONDARY_SEL]    = imx_clk_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
-       clks[IMX6UL_CLK_STEP]             = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
-       clks[IMX6UL_CLK_PLL1_SW]          = imx_clk_mux_flags("pll1_sw",   base + 0x0c, 2,  1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
-       clks[IMX6UL_CLK_AXI_ALT_SEL]      = imx_clk_mux("axi_alt_sel",          base + 0x14, 7,  1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
-       clks[IMX6UL_CLK_AXI_SEL]          = imx_clk_mux_flags("axi_sel",        base + 0x14, 6,  1, axi_sels, ARRAY_SIZE(axi_sels), 0);
-       clks[IMX6UL_CLK_PERIPH_PRE]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
-       clks[IMX6UL_CLK_PERIPH2_PRE]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
-       clks[IMX6UL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
-       clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
-       clks[IMX6UL_CLK_EIM_SLOW_SEL]     = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
-       clks[IMX6UL_CLK_GPMI_SEL]         = imx_clk_mux("gpmi_sel",     base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
-       clks[IMX6UL_CLK_BCH_SEL]          = imx_clk_mux("bch_sel",      base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
-       clks[IMX6UL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",   base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
-       clks[IMX6UL_CLK_USDHC1_SEL]       = imx_clk_mux("usdhc1_sel",   base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
-       clks[IMX6UL_CLK_SAI3_SEL]         = imx_clk_mux("sai3_sel",     base + 0x1c, 14, 2, sai_sels, ARRAY_SIZE(sai_sels));
-       clks[IMX6UL_CLK_SAI2_SEL]         = imx_clk_mux("sai2_sel",     base + 0x1c, 12, 2, sai_sels, ARRAY_SIZE(sai_sels));
-       clks[IMX6UL_CLK_SAI1_SEL]         = imx_clk_mux("sai1_sel",     base + 0x1c, 10, 2, sai_sels, ARRAY_SIZE(sai_sels));
-       clks[IMX6UL_CLK_QSPI1_SEL]        = imx_clk_mux("qspi1_sel",    base + 0x1c, 7,  3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
-       clks[IMX6UL_CLK_PERCLK_SEL]       = imx_clk_mux("perclk_sel",   base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
-       clks[IMX6UL_CLK_CAN_SEL]          = imx_clk_mux("can_sel",      base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
+       hws[IMX6UL_CA7_SECONDARY_SEL]     = imx_clk_hw_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
+       hws[IMX6UL_CLK_STEP]              = imx_clk_hw_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+       hws[IMX6UL_CLK_PLL1_SW]   = imx_clk_hw_mux_flags("pll1_sw",   base + 0x0c, 2,  1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+       hws[IMX6UL_CLK_AXI_ALT_SEL]       = imx_clk_hw_mux("axi_alt_sel",               base + 0x14, 7,  1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+       hws[IMX6UL_CLK_AXI_SEL]   = imx_clk_hw_mux_flags("axi_sel",     base + 0x14, 6,  1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+       hws[IMX6UL_CLK_PERIPH_PRE]        = imx_clk_hw_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+       hws[IMX6UL_CLK_PERIPH2_PRE]       = imx_clk_hw_mux("periph2_pre",      base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+       hws[IMX6UL_CLK_PERIPH_CLK2_SEL]  = imx_clk_hw_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+       hws[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_hw_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       hws[IMX6UL_CLK_EIM_SLOW_SEL]      = imx_clk_hw_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
+       hws[IMX6UL_CLK_GPMI_SEL]          = imx_clk_hw_mux("gpmi_sel",     base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
+       hws[IMX6UL_CLK_BCH_SEL]   = imx_clk_hw_mux("bch_sel",   base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
+       hws[IMX6UL_CLK_USDHC2_SEL]        = imx_clk_hw_mux("usdhc2_sel",   base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       hws[IMX6UL_CLK_USDHC1_SEL]        = imx_clk_hw_mux("usdhc1_sel",   base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       hws[IMX6UL_CLK_SAI3_SEL]          = imx_clk_hw_mux("sai3_sel",     base + 0x1c, 14, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       hws[IMX6UL_CLK_SAI2_SEL]         = imx_clk_hw_mux("sai2_sel",     base + 0x1c, 12, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       hws[IMX6UL_CLK_SAI1_SEL]          = imx_clk_hw_mux("sai1_sel",     base + 0x1c, 10, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       hws[IMX6UL_CLK_QSPI1_SEL]         = imx_clk_hw_mux("qspi1_sel",    base + 0x1c, 7,  3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
+       hws[IMX6UL_CLK_PERCLK_SEL]        = imx_clk_hw_mux("perclk_sel",        base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
+       hws[IMX6UL_CLK_CAN_SEL]   = imx_clk_hw_mux("can_sel",   base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
        if (clk_on_imx6ull())
-               clks[IMX6ULL_CLK_ESAI_SEL]        = imx_clk_mux("esai_sel",     base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
-       clks[IMX6UL_CLK_UART_SEL]         = imx_clk_mux("uart_sel",     base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
-       clks[IMX6UL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",     base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
-       clks[IMX6UL_CLK_LDB_DI0_SEL]      = imx_clk_mux("ldb_di0_sel",  base + 0x2c, 9,  3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
-       clks[IMX6UL_CLK_SPDIF_SEL]        = imx_clk_mux("spdif_sel",    base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+               hws[IMX6ULL_CLK_ESAI_SEL]         = imx_clk_hw_mux("esai_sel",  base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
+       hws[IMX6UL_CLK_UART_SEL]          = imx_clk_hw_mux("uart_sel",  base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
+       hws[IMX6UL_CLK_ENFC_SEL]          = imx_clk_hw_mux("enfc_sel",  base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
+       hws[IMX6UL_CLK_LDB_DI0_SEL]       = imx_clk_hw_mux("ldb_di0_sel",       base + 0x2c, 9,  3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+       hws[IMX6UL_CLK_SPDIF_SEL]         = imx_clk_hw_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
        if (clk_on_imx6ul()) {
-               clks[IMX6UL_CLK_SIM_PRE_SEL]      = imx_clk_mux("sim_pre_sel",  base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
-               clks[IMX6UL_CLK_SIM_SEL]          = imx_clk_mux("sim_sel",      base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+               hws[IMX6UL_CLK_SIM_PRE_SEL]     = imx_clk_hw_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+               hws[IMX6UL_CLK_SIM_SEL]         = imx_clk_hw_mux("sim_sel",     base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
        } else if (clk_on_imx6ull()) {
-               clks[IMX6ULL_CLK_EPDC_PRE_SEL]    = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
-               clks[IMX6ULL_CLK_EPDC_SEL]        = imx_clk_mux("epdc_sel",     base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+               hws[IMX6ULL_CLK_EPDC_PRE_SEL]   = imx_clk_hw_mux("epdc_pre_sel",        base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+               hws[IMX6ULL_CLK_EPDC_SEL]       = imx_clk_hw_mux("epdc_sel",    base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
        }
-       clks[IMX6UL_CLK_ECSPI_SEL]        = imx_clk_mux("ecspi_sel",    base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
-       clks[IMX6UL_CLK_LCDIF_PRE_SEL]    = imx_clk_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT);
-       clks[IMX6UL_CLK_LCDIF_SEL]        = imx_clk_mux("lcdif_sel",    base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
-       clks[IMX6UL_CLK_LDB_DI0_DIV_SEL]  = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
-       clks[IMX6UL_CLK_LDB_DI1_DIV_SEL]  = imx_clk_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
-       clks[IMX6UL_CLK_CKO1_SEL]         = imx_clk_mux("cko1_sel", base + 0x60, 0,  4, cko1_sels, ARRAY_SIZE(cko1_sels));
-       clks[IMX6UL_CLK_CKO2_SEL]         = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
-       clks[IMX6UL_CLK_CKO]              = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
-       clks[IMX6UL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-       clks[IMX6UL_CLK_LDB_DI0_DIV_7]   = imx_clk_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
-       clks[IMX6UL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "qspi1_sel", 2, 7);
-       clks[IMX6UL_CLK_LDB_DI1_DIV_7]   = imx_clk_fixed_factor("ldb_di1_div_7",   "qspi1_sel", 1, 7);
-       clks[IMX6UL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
-       clks[IMX6UL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
-       clks[IMX6UL_CLK_PERIPH_CLK2]    = imx_clk_divider("periph_clk2",   "periph_clk2_sel",   base + 0x14, 27, 3);
-       clks[IMX6UL_CLK_PERIPH2_CLK2]   = imx_clk_divider("periph2_clk2",  "periph2_clk2_sel",  base + 0x14, 0,  3);
-       clks[IMX6UL_CLK_IPG]            = imx_clk_divider("ipg",           "ahb",               base + 0x14, 8,  2);
-       clks[IMX6UL_CLK_LCDIF_PODF]     = imx_clk_divider("lcdif_podf",    "lcdif_pred",        base + 0x18, 23, 3);
-       clks[IMX6UL_CLK_QSPI1_PDOF]     = imx_clk_divider("qspi1_podf",    "qspi1_sel",         base + 0x1c, 26, 3);
-       clks[IMX6UL_CLK_EIM_SLOW_PODF]  = imx_clk_divider("eim_slow_podf", "eim_slow_sel",      base + 0x1c, 23, 3);
-       clks[IMX6UL_CLK_PERCLK]         = imx_clk_divider("perclk",        "perclk_sel",        base + 0x1c, 0,  6);
-       clks[IMX6UL_CLK_CAN_PODF]       = imx_clk_divider("can_podf",      "can_sel",           base + 0x20, 2,  6);
-       clks[IMX6UL_CLK_GPMI_PODF]      = imx_clk_divider("gpmi_podf",     "gpmi_sel",          base + 0x24, 22, 3);
-       clks[IMX6UL_CLK_BCH_PODF]       = imx_clk_divider("bch_podf",      "bch_sel",           base + 0x24, 19, 3);
-       clks[IMX6UL_CLK_USDHC2_PODF]    = imx_clk_divider("usdhc2_podf",   "usdhc2_sel",        base + 0x24, 16, 3);
-       clks[IMX6UL_CLK_USDHC1_PODF]    = imx_clk_divider("usdhc1_podf",   "usdhc1_sel",        base + 0x24, 11, 3);
-       clks[IMX6UL_CLK_UART_PODF]      = imx_clk_divider("uart_podf",     "uart_sel",          base + 0x24, 0,  6);
-       clks[IMX6UL_CLK_SAI3_PRED]      = imx_clk_divider("sai3_pred",     "sai3_sel",          base + 0x28, 22, 3);
-       clks[IMX6UL_CLK_SAI3_PODF]      = imx_clk_divider("sai3_podf",     "sai3_pred",         base + 0x28, 16, 6);
-       clks[IMX6UL_CLK_SAI1_PRED]      = imx_clk_divider("sai1_pred",     "sai1_sel",          base + 0x28, 6,  3);
-       clks[IMX6UL_CLK_SAI1_PODF]      = imx_clk_divider("sai1_podf",     "sai1_pred",         base + 0x28, 0,  6);
+       hws[IMX6UL_CLK_ECSPI_SEL]         = imx_clk_hw_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+       hws[IMX6UL_CLK_LCDIF_PRE_SEL]     = imx_clk_hw_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6UL_CLK_LCDIF_SEL]         = imx_clk_hw_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+       hws[IMX6UL_CLK_LDB_DI0_DIV_SEL]  = imx_clk_hw_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+       hws[IMX6UL_CLK_LDB_DI1_DIV_SEL]  = imx_clk_hw_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+       hws[IMX6UL_CLK_CKO1_SEL]          = imx_clk_hw_mux("cko1_sel", base + 0x60, 0,  4, cko1_sels, ARRAY_SIZE(cko1_sels));
+       hws[IMX6UL_CLK_CKO2_SEL]          = imx_clk_hw_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
+       hws[IMX6UL_CLK_CKO]               = imx_clk_hw_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
+       hws[IMX6UL_CLK_LDB_DI0_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       hws[IMX6UL_CLK_LDB_DI0_DIV_7]    = imx_clk_hw_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
+       hws[IMX6UL_CLK_LDB_DI1_DIV_3_5] = imx_clk_hw_fixed_factor("ldb_di1_div_3_5", "qspi1_sel", 2, 7);
+       hws[IMX6UL_CLK_LDB_DI1_DIV_7]    = imx_clk_hw_fixed_factor("ldb_di1_div_7",   "qspi1_sel", 1, 7);
+       hws[IMX6UL_CLK_PERIPH]  = imx_clk_hw_busy_mux("periph",  base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+       hws[IMX6UL_CLK_PERIPH2] = imx_clk_hw_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+       hws[IMX6UL_CLK_PERIPH_CLK2]     = imx_clk_hw_divider("periph_clk2",   "periph_clk2_sel",        base + 0x14, 27, 3);
+       hws[IMX6UL_CLK_PERIPH2_CLK2]    = imx_clk_hw_divider("periph2_clk2",  "periph2_clk2_sel",       base + 0x14, 0,  3);
+       hws[IMX6UL_CLK_IPG]             = imx_clk_hw_divider("ipg",        "ahb",               base + 0x14, 8,  2);
+       hws[IMX6UL_CLK_LCDIF_PODF]      = imx_clk_hw_divider("lcdif_podf",         "lcdif_pred",        base + 0x18, 23, 3);
+       hws[IMX6UL_CLK_QSPI1_PDOF]      = imx_clk_hw_divider("qspi1_podf",         "qspi1_sel",         base + 0x1c, 26, 3);
+       hws[IMX6UL_CLK_EIM_SLOW_PODF]   = imx_clk_hw_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3);
+       hws[IMX6UL_CLK_PERCLK]          = imx_clk_hw_divider("perclk",     "perclk_sel",        base + 0x1c, 0,  6);
+       hws[IMX6UL_CLK_CAN_PODF]        = imx_clk_hw_divider("can_podf",           "can_sel",           base + 0x20, 2,  6);
+       hws[IMX6UL_CLK_GPMI_PODF]       = imx_clk_hw_divider("gpmi_podf",          "gpmi_sel",          base + 0x24, 22, 3);
+       hws[IMX6UL_CLK_BCH_PODF]        = imx_clk_hw_divider("bch_podf",           "bch_sel",           base + 0x24, 19, 3);
+       hws[IMX6UL_CLK_USDHC2_PODF]     = imx_clk_hw_divider("usdhc2_podf",   "usdhc2_sel",     base + 0x24, 16, 3);
+       hws[IMX6UL_CLK_USDHC1_PODF]     = imx_clk_hw_divider("usdhc1_podf",   "usdhc1_sel",     base + 0x24, 11, 3);
+       hws[IMX6UL_CLK_UART_PODF]       = imx_clk_hw_divider("uart_podf",          "uart_sel",          base + 0x24, 0,  6);
+       hws[IMX6UL_CLK_SAI3_PRED]       = imx_clk_hw_divider("sai3_pred",          "sai3_sel",          base + 0x28, 22, 3);
+       hws[IMX6UL_CLK_SAI3_PODF]       = imx_clk_hw_divider("sai3_podf",          "sai3_pred",         base + 0x28, 16, 6);
+       hws[IMX6UL_CLK_SAI1_PRED]       = imx_clk_hw_divider("sai1_pred",          "sai1_sel",          base + 0x28, 6,  3);
+       hws[IMX6UL_CLK_SAI1_PODF]       = imx_clk_hw_divider("sai1_podf",          "sai1_pred",         base + 0x28, 0,  6);
        if (clk_on_imx6ull()) {
-               clks[IMX6ULL_CLK_ESAI_PRED]     = imx_clk_divider("esai_pred",     "esai_sel",          base + 0x28, 9,  3);
-               clks[IMX6ULL_CLK_ESAI_PODF]     = imx_clk_divider("esai_podf",     "esai_pred",         base + 0x28, 25, 3);
+               hws[IMX6ULL_CLK_ESAI_PRED]      = imx_clk_hw_divider("esai_pred",     "esai_sel",               base + 0x28, 9,  3);
+               hws[IMX6ULL_CLK_ESAI_PODF]      = imx_clk_hw_divider("esai_podf",     "esai_pred",              base + 0x28, 25, 3);
        }
-       clks[IMX6UL_CLK_ENFC_PRED]      = imx_clk_divider("enfc_pred",     "enfc_sel",          base + 0x2c, 18, 3);
-       clks[IMX6UL_CLK_ENFC_PODF]      = imx_clk_divider("enfc_podf",     "enfc_pred",         base + 0x2c, 21, 6);
-       clks[IMX6UL_CLK_SAI2_PRED]      = imx_clk_divider("sai2_pred",     "sai2_sel",          base + 0x2c, 6,  3);
-       clks[IMX6UL_CLK_SAI2_PODF]      = imx_clk_divider("sai2_podf",     "sai2_pred",         base + 0x2c, 0,  6);
-       clks[IMX6UL_CLK_SPDIF_PRED]     = imx_clk_divider("spdif_pred",    "spdif_sel",         base + 0x30, 25, 3);
-       clks[IMX6UL_CLK_SPDIF_PODF]     = imx_clk_divider("spdif_podf",    "spdif_pred",        base + 0x30, 22, 3);
+       hws[IMX6UL_CLK_ENFC_PRED]       = imx_clk_hw_divider("enfc_pred",          "enfc_sel",          base + 0x2c, 18, 3);
+       hws[IMX6UL_CLK_ENFC_PODF]       = imx_clk_hw_divider("enfc_podf",          "enfc_pred",         base + 0x2c, 21, 6);
+       hws[IMX6UL_CLK_SAI2_PRED]       = imx_clk_hw_divider("sai2_pred",          "sai2_sel",          base + 0x2c, 6,  3);
+       hws[IMX6UL_CLK_SAI2_PODF]       = imx_clk_hw_divider("sai2_podf",          "sai2_pred",         base + 0x2c, 0,  6);
+       hws[IMX6UL_CLK_SPDIF_PRED]      = imx_clk_hw_divider("spdif_pred",         "spdif_sel",         base + 0x30, 25, 3);
+       hws[IMX6UL_CLK_SPDIF_PODF]      = imx_clk_hw_divider("spdif_podf",         "spdif_pred",        base + 0x30, 22, 3);
        if (clk_on_imx6ul())
-               clks[IMX6UL_CLK_SIM_PODF]       = imx_clk_divider("sim_podf",      "sim_pre_sel",       base + 0x34, 12, 3);
+               hws[IMX6UL_CLK_SIM_PODF]        = imx_clk_hw_divider("sim_podf",           "sim_pre_sel",       base + 0x34, 12, 3);
        else if (clk_on_imx6ull())
-               clks[IMX6ULL_CLK_EPDC_PODF]     = imx_clk_divider("epdc_podf",     "epdc_pre_sel",      base + 0x34, 12, 3);
-       clks[IMX6UL_CLK_ECSPI_PODF]     = imx_clk_divider("ecspi_podf",    "ecspi_sel",         base + 0x38, 19, 6);
-       clks[IMX6UL_CLK_LCDIF_PRED]     = imx_clk_divider("lcdif_pred",    "lcdif_pre_sel",     base + 0x38, 12, 3);
-       clks[IMX6UL_CLK_CSI_PODF]       = imx_clk_divider("csi_podf",      "csi_sel",           base + 0x3c, 11, 3);
+               hws[IMX6ULL_CLK_EPDC_PODF]      = imx_clk_hw_divider("epdc_podf",          "epdc_pre_sel",      base + 0x34, 12, 3);
+       hws[IMX6UL_CLK_ECSPI_PODF]      = imx_clk_hw_divider("ecspi_podf",         "ecspi_sel",         base + 0x38, 19, 6);
+       hws[IMX6UL_CLK_LCDIF_PRED]      = imx_clk_hw_divider("lcdif_pred",         "lcdif_pre_sel",     base + 0x38, 12, 3);
+       hws[IMX6UL_CLK_CSI_PODF]       = imx_clk_hw_divider("csi_podf",      "csi_sel",           base + 0x3c, 11, 3);
  
-       clks[IMX6UL_CLK_CKO1_PODF]      = imx_clk_divider("cko1_podf",     "cko1_sel",          base + 0x60, 4,  3);
-       clks[IMX6UL_CLK_CKO2_PODF]      = imx_clk_divider("cko2_podf",     "cko2_sel",          base + 0x60, 21, 3);
+       hws[IMX6UL_CLK_CKO1_PODF]       = imx_clk_hw_divider("cko1_podf",     "cko1_sel",          base + 0x60, 4,  3);
+       hws[IMX6UL_CLK_CKO2_PODF]       = imx_clk_hw_divider("cko2_podf",     "cko2_sel",          base + 0x60, 21, 3);
  
-       clks[IMX6UL_CLK_ARM]            = imx_clk_busy_divider("arm",       "pll1_sw",  base +  0x10, 0,  3,  base + 0x48, 16);
-       clks[IMX6UL_CLK_MMDC_PODF]      = imx_clk_busy_divider("mmdc_podf", "periph2",  base +  0x14, 3,  3,  base + 0x48, 2);
-       clks[IMX6UL_CLK_AXI_PODF]       = imx_clk_busy_divider("axi_podf",  "axi_sel",  base +  0x14, 16, 3,  base + 0x48, 0);
-       clks[IMX6UL_CLK_AHB]            = imx_clk_busy_divider("ahb",       "periph",   base +  0x14, 10, 3,  base + 0x48, 1);
+       hws[IMX6UL_CLK_ARM]             = imx_clk_hw_busy_divider("arm",            "pll1_sw",  base +  0x10, 0,  3,  base + 0x48, 16);
+       hws[IMX6UL_CLK_MMDC_PODF]       = imx_clk_hw_busy_divider("mmdc_podf", "periph2",       base +  0x14, 3,  3,  base + 0x48, 2);
+       hws[IMX6UL_CLK_AXI_PODF]        = imx_clk_hw_busy_divider("axi_podf",  "axi_sel",       base +  0x14, 16, 3,  base + 0x48, 0);
+       hws[IMX6UL_CLK_AHB]             = imx_clk_hw_busy_divider("ahb",            "periph",   base +  0x14, 10, 3,  base + 0x48, 1);
  
        /* CCGR0 */
-       clks[IMX6UL_CLK_AIPSTZ1]        = imx_clk_gate2_flags("aips_tz1", "ahb", base + 0x68, 0, CLK_IS_CRITICAL);
-       clks[IMX6UL_CLK_AIPSTZ2]        = imx_clk_gate2_flags("aips_tz2", "ahb", base + 0x68, 2, CLK_IS_CRITICAL);
-       clks[IMX6UL_CLK_APBHDMA]        = imx_clk_gate2("apbh_dma",     "bch_podf",     base + 0x68,    4);
-       clks[IMX6UL_CLK_ASRC_IPG]       = imx_clk_gate2_shared("asrc_ipg",      "ahb",  base + 0x68,    6, &share_count_asrc);
-       clks[IMX6UL_CLK_ASRC_MEM]       = imx_clk_gate2_shared("asrc_mem",      "ahb",  base + 0x68,    6, &share_count_asrc);
+       hws[IMX6UL_CLK_AIPSTZ1] = imx_clk_hw_gate2_flags("aips_tz1", "ahb", base + 0x68, 0, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_AIPSTZ2] = imx_clk_hw_gate2_flags("aips_tz2", "ahb", base + 0x68, 2, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_APBHDMA] = imx_clk_hw_gate2("apbh_dma",  "bch_podf",     base + 0x68,    4);
+       hws[IMX6UL_CLK_ASRC_IPG]        = imx_clk_hw_gate2_shared("asrc_ipg",   "ahb",  base + 0x68,    6, &share_count_asrc);
+       hws[IMX6UL_CLK_ASRC_MEM]        = imx_clk_hw_gate2_shared("asrc_mem",   "ahb",  base + 0x68,    6, &share_count_asrc);
        if (clk_on_imx6ul()) {
-               clks[IMX6UL_CLK_CAAM_MEM]       = imx_clk_gate2("caam_mem",     "ahb",          base + 0x68,    8);
-               clks[IMX6UL_CLK_CAAM_ACLK]      = imx_clk_gate2("caam_aclk",    "ahb",          base + 0x68,    10);
-               clks[IMX6UL_CLK_CAAM_IPG]       = imx_clk_gate2("caam_ipg",     "ipg",          base + 0x68,    12);
+               hws[IMX6UL_CLK_CAAM_MEM]        = imx_clk_hw_gate2("caam_mem",  "ahb",          base + 0x68,    8);
+               hws[IMX6UL_CLK_CAAM_ACLK]       = imx_clk_hw_gate2("caam_aclk", "ahb",          base + 0x68,    10);
+               hws[IMX6UL_CLK_CAAM_IPG]        = imx_clk_hw_gate2("caam_ipg",  "ipg",          base + 0x68,    12);
        } else if (clk_on_imx6ull()) {
-               clks[IMX6ULL_CLK_DCP_CLK]       = imx_clk_gate2("dcp",          "ahb",          base + 0x68,    10);
-               clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x68,    12);
-               clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x68,    12);
+               hws[IMX6ULL_CLK_DCP_CLK]        = imx_clk_hw_gate2("dcp",               "ahb",          base + 0x68,    10);
+               hws[IMX6UL_CLK_ENET]            = imx_clk_hw_gate2("enet",              "ipg",          base + 0x68,    12);
+               hws[IMX6UL_CLK_ENET_AHB]        = imx_clk_hw_gate2("enet_ahb",  "ahb",          base + 0x68,    12);
        }
-       clks[IMX6UL_CLK_CAN1_IPG]       = imx_clk_gate2("can1_ipg",     "ipg",          base + 0x68,    14);
-       clks[IMX6UL_CLK_CAN1_SERIAL]    = imx_clk_gate2("can1_serial",  "can_podf",     base + 0x68,    16);
-       clks[IMX6UL_CLK_CAN2_IPG]       = imx_clk_gate2("can2_ipg",     "ipg",          base + 0x68,    18);
-       clks[IMX6UL_CLK_CAN2_SERIAL]    = imx_clk_gate2("can2_serial",  "can_podf",     base + 0x68,    20);
-       clks[IMX6UL_CLK_GPT2_BUS]       = imx_clk_gate2("gpt2_bus",     "perclk",       base + 0x68,    24);
-       clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt2_serial",  "perclk",       base + 0x68,    26);
-       clks[IMX6UL_CLK_UART2_IPG]      = imx_clk_gate2("uart2_ipg",    "ipg",          base + 0x68,    28);
-       clks[IMX6UL_CLK_UART2_SERIAL]   = imx_clk_gate2("uart2_serial", "uart_podf",    base + 0x68,    28);
+       hws[IMX6UL_CLK_CAN1_IPG]        = imx_clk_hw_gate2("can1_ipg",  "ipg",          base + 0x68,    14);
+       hws[IMX6UL_CLK_CAN1_SERIAL]     = imx_clk_hw_gate2("can1_serial",       "can_podf",     base + 0x68,    16);
+       hws[IMX6UL_CLK_CAN2_IPG]        = imx_clk_hw_gate2("can2_ipg",  "ipg",          base + 0x68,    18);
+       hws[IMX6UL_CLK_CAN2_SERIAL]     = imx_clk_hw_gate2("can2_serial",       "can_podf",     base + 0x68,    20);
+       hws[IMX6UL_CLK_GPT2_BUS]        = imx_clk_hw_gate2("gpt2_bus",  "perclk",       base + 0x68,    24);
+       hws[IMX6UL_CLK_GPT2_SERIAL]     = imx_clk_hw_gate2("gpt2_serial",       "perclk",       base + 0x68,    26);
+       hws[IMX6UL_CLK_UART2_IPG]       = imx_clk_hw_gate2("uart2_ipg", "ipg",          base + 0x68,    28);
+       hws[IMX6UL_CLK_UART2_SERIAL]    = imx_clk_hw_gate2("uart2_serial",      "uart_podf",    base + 0x68,    28);
        if (clk_on_imx6ull())
-               clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",           base + 0x80,   18);
-       clks[IMX6UL_CLK_GPIO2]          = imx_clk_gate2("gpio2",        "ipg",          base + 0x68,    30);
+               hws[IMX6UL_CLK_AIPSTZ3] = imx_clk_hw_gate2("aips_tz3",  "ahb",           base + 0x80,   18);
+       hws[IMX6UL_CLK_GPIO2]           = imx_clk_hw_gate2("gpio2",     "ipg",          base + 0x68,    30);
  
        /* CCGR1 */
-       clks[IMX6UL_CLK_ECSPI1]         = imx_clk_gate2("ecspi1",       "ecspi_podf",   base + 0x6c,    0);
-       clks[IMX6UL_CLK_ECSPI2]         = imx_clk_gate2("ecspi2",       "ecspi_podf",   base + 0x6c,    2);
-       clks[IMX6UL_CLK_ECSPI3]         = imx_clk_gate2("ecspi3",       "ecspi_podf",   base + 0x6c,    4);
-       clks[IMX6UL_CLK_ECSPI4]         = imx_clk_gate2("ecspi4",       "ecspi_podf",   base + 0x6c,    6);
-       clks[IMX6UL_CLK_ADC2]           = imx_clk_gate2("adc2",         "ipg",          base + 0x6c,    8);
-       clks[IMX6UL_CLK_UART3_IPG]      = imx_clk_gate2("uart3_ipg",    "ipg",          base + 0x6c,    10);
-       clks[IMX6UL_CLK_UART3_SERIAL]   = imx_clk_gate2("uart3_serial", "uart_podf",    base + 0x6c,    10);
-       clks[IMX6UL_CLK_EPIT1]          = imx_clk_gate2("epit1",        "perclk",       base + 0x6c,    12);
-       clks[IMX6UL_CLK_EPIT2]          = imx_clk_gate2("epit2",        "perclk",       base + 0x6c,    14);
-       clks[IMX6UL_CLK_ADC1]           = imx_clk_gate2("adc1",         "ipg",          base + 0x6c,    16);
-       clks[IMX6UL_CLK_GPT1_BUS]       = imx_clk_gate2("gpt1_bus",     "perclk",       base + 0x6c,    20);
-       clks[IMX6UL_CLK_GPT1_SERIAL]    = imx_clk_gate2("gpt1_serial",  "perclk",       base + 0x6c,    22);
-       clks[IMX6UL_CLK_UART4_IPG]      = imx_clk_gate2("uart4_ipg",    "ipg",          base + 0x6c,    24);
-       clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serial", "uart_podf",    base + 0x6c,    24);
-       clks[IMX6UL_CLK_GPIO1]          = imx_clk_gate2("gpio1",        "ipg",          base + 0x6c,    26);
-       clks[IMX6UL_CLK_GPIO5]          = imx_clk_gate2("gpio5",        "ipg",          base + 0x6c,    30);
+       hws[IMX6UL_CLK_ECSPI1]          = imx_clk_hw_gate2("ecspi1",    "ecspi_podf",   base + 0x6c,    0);
+       hws[IMX6UL_CLK_ECSPI2]          = imx_clk_hw_gate2("ecspi2",    "ecspi_podf",   base + 0x6c,    2);
+       hws[IMX6UL_CLK_ECSPI3]          = imx_clk_hw_gate2("ecspi3",    "ecspi_podf",   base + 0x6c,    4);
+       hws[IMX6UL_CLK_ECSPI4]          = imx_clk_hw_gate2("ecspi4",    "ecspi_podf",   base + 0x6c,    6);
+       hws[IMX6UL_CLK_ADC2]            = imx_clk_hw_gate2("adc2",              "ipg",          base + 0x6c,    8);
+       hws[IMX6UL_CLK_UART3_IPG]       = imx_clk_hw_gate2("uart3_ipg", "ipg",          base + 0x6c,    10);
+       hws[IMX6UL_CLK_UART3_SERIAL]    = imx_clk_hw_gate2("uart3_serial",      "uart_podf",    base + 0x6c,    10);
+       hws[IMX6UL_CLK_EPIT1]           = imx_clk_hw_gate2("epit1",     "perclk",       base + 0x6c,    12);
+       hws[IMX6UL_CLK_EPIT2]           = imx_clk_hw_gate2("epit2",     "perclk",       base + 0x6c,    14);
+       hws[IMX6UL_CLK_ADC1]            = imx_clk_hw_gate2("adc1",              "ipg",          base + 0x6c,    16);
+       hws[IMX6UL_CLK_GPT1_BUS]        = imx_clk_hw_gate2("gpt1_bus",  "perclk",       base + 0x6c,    20);
+       hws[IMX6UL_CLK_GPT1_SERIAL]     = imx_clk_hw_gate2("gpt1_serial",       "perclk",       base + 0x6c,    22);
+       hws[IMX6UL_CLK_UART4_IPG]       = imx_clk_hw_gate2("uart4_ipg", "ipg",          base + 0x6c,    24);
+       hws[IMX6UL_CLK_UART4_SERIAL]    = imx_clk_hw_gate2("uart4_serial",      "uart_podf",    base + 0x6c,    24);
+       hws[IMX6UL_CLK_GPIO1]           = imx_clk_hw_gate2("gpio1",     "ipg",          base + 0x6c,    26);
+       hws[IMX6UL_CLK_GPIO5]           = imx_clk_hw_gate2("gpio5",     "ipg",          base + 0x6c,    30);
  
        /* CCGR2 */
        if (clk_on_imx6ull()) {
-               clks[IMX6ULL_CLK_ESAI_EXTAL]    = imx_clk_gate2_shared("esai_extal",    "esai_podf",    base + 0x70,    0, &share_count_esai);
-               clks[IMX6ULL_CLK_ESAI_IPG]      = imx_clk_gate2_shared("esai_ipg",      "ahb",          base + 0x70,    0, &share_count_esai);
-               clks[IMX6ULL_CLK_ESAI_MEM]      = imx_clk_gate2_shared("esai_mem",      "ahb",          base + 0x70,    0, &share_count_esai);
+               hws[IMX6ULL_CLK_ESAI_EXTAL]     = imx_clk_hw_gate2_shared("esai_extal", "esai_podf",    base + 0x70,    0, &share_count_esai);
+               hws[IMX6ULL_CLK_ESAI_IPG]       = imx_clk_hw_gate2_shared("esai_ipg",   "ahb",          base + 0x70,    0, &share_count_esai);
+               hws[IMX6ULL_CLK_ESAI_MEM]       = imx_clk_hw_gate2_shared("esai_mem",   "ahb",          base + 0x70,    0, &share_count_esai);
        }
-       clks[IMX6UL_CLK_CSI]            = imx_clk_gate2("csi",          "csi_podf",             base + 0x70,    2);
-       clks[IMX6UL_CLK_I2C1]           = imx_clk_gate2("i2c1",         "perclk",       base + 0x70,    6);
-       clks[IMX6UL_CLK_I2C2]           = imx_clk_gate2("i2c2",         "perclk",       base + 0x70,    8);
-       clks[IMX6UL_CLK_I2C3]           = imx_clk_gate2("i2c3",         "perclk",       base + 0x70,    10);
-       clks[IMX6UL_CLK_OCOTP]          = imx_clk_gate2("ocotp",        "ipg",          base + 0x70,    12);
-       clks[IMX6UL_CLK_IOMUXC]         = imx_clk_gate2("iomuxc",       "lcdif_podf",   base + 0x70,    14);
-       clks[IMX6UL_CLK_GPIO3]          = imx_clk_gate2("gpio3",        "ipg",          base + 0x70,    26);
-       clks[IMX6UL_CLK_LCDIF_APB]      = imx_clk_gate2("lcdif_apb",    "axi",          base + 0x70,    28);
-       clks[IMX6UL_CLK_PXP]            = imx_clk_gate2("pxp",          "axi",          base + 0x70,    30);
+       hws[IMX6UL_CLK_CSI]             = imx_clk_hw_gate2("csi",               "csi_podf",             base + 0x70,    2);
+       hws[IMX6UL_CLK_I2C1]            = imx_clk_hw_gate2("i2c1",              "perclk",       base + 0x70,    6);
+       hws[IMX6UL_CLK_I2C2]            = imx_clk_hw_gate2("i2c2",              "perclk",       base + 0x70,    8);
+       hws[IMX6UL_CLK_I2C3]            = imx_clk_hw_gate2("i2c3",              "perclk",       base + 0x70,    10);
+       hws[IMX6UL_CLK_OCOTP]           = imx_clk_hw_gate2("ocotp",     "ipg",          base + 0x70,    12);
+       hws[IMX6UL_CLK_IOMUXC]          = imx_clk_hw_gate2("iomuxc",    "lcdif_podf",   base + 0x70,    14);
+       hws[IMX6UL_CLK_GPIO3]           = imx_clk_hw_gate2("gpio3",     "ipg",          base + 0x70,    26);
+       hws[IMX6UL_CLK_LCDIF_APB]       = imx_clk_hw_gate2("lcdif_apb", "axi",          base + 0x70,    28);
+       hws[IMX6UL_CLK_PXP]             = imx_clk_hw_gate2("pxp",               "axi",          base + 0x70,    30);
  
        /* CCGR3 */
-       clks[IMX6UL_CLK_UART5_IPG]      = imx_clk_gate2("uart5_ipg",    "ipg",          base + 0x74,    2);
-       clks[IMX6UL_CLK_UART5_SERIAL]   = imx_clk_gate2("uart5_serial", "uart_podf",    base + 0x74,    2);
+       hws[IMX6UL_CLK_UART5_IPG]       = imx_clk_hw_gate2("uart5_ipg", "ipg",          base + 0x74,    2);
+       hws[IMX6UL_CLK_UART5_SERIAL]    = imx_clk_hw_gate2("uart5_serial",      "uart_podf",    base + 0x74,    2);
        if (clk_on_imx6ul()) {
-               clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x74,    4);
-               clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x74,    4);
+               hws[IMX6UL_CLK_ENET]            = imx_clk_hw_gate2("enet",              "ipg",          base + 0x74,    4);
+               hws[IMX6UL_CLK_ENET_AHB]        = imx_clk_hw_gate2("enet_ahb",  "ahb",          base + 0x74,    4);
        } else if (clk_on_imx6ull()) {
-               clks[IMX6ULL_CLK_EPDC_ACLK]     = imx_clk_gate2("epdc_aclk",    "axi",          base + 0x74,    4);
-               clks[IMX6ULL_CLK_EPDC_PIX]      = imx_clk_gate2("epdc_pix",     "epdc_podf",    base + 0x74,    4);
+               hws[IMX6ULL_CLK_EPDC_ACLK]      = imx_clk_hw_gate2("epdc_aclk", "axi",          base + 0x74,    4);
+               hws[IMX6ULL_CLK_EPDC_PIX]       = imx_clk_hw_gate2("epdc_pix",  "epdc_podf",    base + 0x74,    4);
        }
-       clks[IMX6UL_CLK_UART6_IPG]      = imx_clk_gate2("uart6_ipg",    "ipg",          base + 0x74,    6);
-       clks[IMX6UL_CLK_UART6_SERIAL]   = imx_clk_gate2("uart6_serial", "uart_podf",    base + 0x74,    6);
-       clks[IMX6UL_CLK_LCDIF_PIX]      = imx_clk_gate2("lcdif_pix",    "lcdif_podf",   base + 0x74,    10);
-       clks[IMX6UL_CLK_GPIO4]          = imx_clk_gate2("gpio4",        "ipg",          base + 0x74,    12);
-       clks[IMX6UL_CLK_QSPI]           = imx_clk_gate2("qspi1",        "qspi1_podf",   base + 0x74,    14);
-       clks[IMX6UL_CLK_WDOG1]          = imx_clk_gate2("wdog1",        "ipg",          base + 0x74,    16);
-       clks[IMX6UL_CLK_MMDC_P0_FAST]   = imx_clk_gate_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74,  20, CLK_IS_CRITICAL);
-       clks[IMX6UL_CLK_MMDC_P0_IPG]    = imx_clk_gate2_flags("mmdc_p0_ipg",    "ipg",          base + 0x74,    24, CLK_IS_CRITICAL);
-       clks[IMX6UL_CLK_MMDC_P1_IPG]    = imx_clk_gate2("mmdc_p1_ipg",  "ipg",          base + 0x74,    26);
-       clks[IMX6UL_CLK_AXI]            = imx_clk_gate_flags("axi",     "axi_podf",     base + 0x74,    28, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_UART6_IPG]       = imx_clk_hw_gate2("uart6_ipg", "ipg",          base + 0x74,    6);
+       hws[IMX6UL_CLK_UART6_SERIAL]    = imx_clk_hw_gate2("uart6_serial",      "uart_podf",    base + 0x74,    6);
+       hws[IMX6UL_CLK_LCDIF_PIX]       = imx_clk_hw_gate2("lcdif_pix", "lcdif_podf",   base + 0x74,    10);
+       hws[IMX6UL_CLK_GPIO4]           = imx_clk_hw_gate2("gpio4",     "ipg",          base + 0x74,    12);
+       hws[IMX6UL_CLK_QSPI]            = imx_clk_hw_gate2("qspi1",     "qspi1_podf",   base + 0x74,    14);
+       hws[IMX6UL_CLK_WDOG1]           = imx_clk_hw_gate2("wdog1",     "ipg",          base + 0x74,    16);
+       hws[IMX6UL_CLK_MMDC_P0_FAST]    = imx_clk_hw_gate_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74,       20, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_MMDC_P0_IPG]     = imx_clk_hw_gate2_flags("mmdc_p0_ipg", "ipg",          base + 0x74,    24, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_MMDC_P1_IPG]     = imx_clk_hw_gate2_flags("mmdc_p1_ipg", "ipg",          base + 0x74,    26, CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_AXI]             = imx_clk_hw_gate_flags("axi",  "axi_podf",     base + 0x74,    28, CLK_IS_CRITICAL);
  
        /* CCGR4 */
-       clks[IMX6UL_CLK_PER_BCH]        = imx_clk_gate2("per_bch",      "bch_podf",     base + 0x78,    12);
-       clks[IMX6UL_CLK_PWM1]           = imx_clk_gate2("pwm1",         "perclk",       base + 0x78,    16);
-       clks[IMX6UL_CLK_PWM2]           = imx_clk_gate2("pwm2",         "perclk",       base + 0x78,    18);
-       clks[IMX6UL_CLK_PWM3]           = imx_clk_gate2("pwm3",         "perclk",       base + 0x78,    20);
-       clks[IMX6UL_CLK_PWM4]           = imx_clk_gate2("pwm4",         "perclk",       base + 0x78,    22);
-       clks[IMX6UL_CLK_GPMI_BCH_APB]   = imx_clk_gate2("gpmi_bch_apb", "bch_podf",     base + 0x78,    24);
-       clks[IMX6UL_CLK_GPMI_BCH]       = imx_clk_gate2("gpmi_bch",     "gpmi_podf",    base + 0x78,    26);
-       clks[IMX6UL_CLK_GPMI_IO]        = imx_clk_gate2("gpmi_io",      "enfc_podf",    base + 0x78,    28);
-       clks[IMX6UL_CLK_GPMI_APB]       = imx_clk_gate2("gpmi_apb",     "bch_podf",     base + 0x78,    30);
+       hws[IMX6UL_CLK_PER_BCH] = imx_clk_hw_gate2("per_bch",   "bch_podf",     base + 0x78,    12);
+       hws[IMX6UL_CLK_PWM1]            = imx_clk_hw_gate2("pwm1",              "perclk",       base + 0x78,    16);
+       hws[IMX6UL_CLK_PWM2]            = imx_clk_hw_gate2("pwm2",              "perclk",       base + 0x78,    18);
+       hws[IMX6UL_CLK_PWM3]            = imx_clk_hw_gate2("pwm3",              "perclk",       base + 0x78,    20);
+       hws[IMX6UL_CLK_PWM4]            = imx_clk_hw_gate2("pwm4",              "perclk",       base + 0x78,    22);
+       hws[IMX6UL_CLK_GPMI_BCH_APB]    = imx_clk_hw_gate2("gpmi_bch_apb",      "bch_podf",     base + 0x78,    24);
+       hws[IMX6UL_CLK_GPMI_BCH]        = imx_clk_hw_gate2("gpmi_bch",  "gpmi_podf",    base + 0x78,    26);
+       hws[IMX6UL_CLK_GPMI_IO] = imx_clk_hw_gate2("gpmi_io",   "enfc_podf",    base + 0x78,    28);
+       hws[IMX6UL_CLK_GPMI_APB]        = imx_clk_hw_gate2("gpmi_apb",  "bch_podf",     base + 0x78,    30);
  
        /* CCGR5 */
-       clks[IMX6UL_CLK_ROM]            = imx_clk_gate2_flags("rom",    "ahb",          base + 0x7c,    0,      CLK_IS_CRITICAL);
-       clks[IMX6UL_CLK_SDMA]           = imx_clk_gate2("sdma",         "ahb",          base + 0x7c,    6);
-       clks[IMX6UL_CLK_KPP]            = imx_clk_gate2("kpp",          "ipg",          base + 0x7c,    8);
-       clks[IMX6UL_CLK_WDOG2]          = imx_clk_gate2("wdog2",        "ipg",          base + 0x7c,    10);
-       clks[IMX6UL_CLK_SPBA]           = imx_clk_gate2("spba",         "ipg",          base + 0x7c,    12);
-       clks[IMX6UL_CLK_SPDIF]          = imx_clk_gate2_shared("spdif",         "spdif_podf",   base + 0x7c,    14, &share_count_audio);
-       clks[IMX6UL_CLK_SPDIF_GCLK]     = imx_clk_gate2_shared("spdif_gclk",    "ipg",          base + 0x7c,    14, &share_count_audio);
-       clks[IMX6UL_CLK_SAI3]           = imx_clk_gate2_shared("sai3",          "sai3_podf",    base + 0x7c,    22, &share_count_sai3);
-       clks[IMX6UL_CLK_SAI3_IPG]       = imx_clk_gate2_shared("sai3_ipg",      "ipg",          base + 0x7c,    22, &share_count_sai3);
-       clks[IMX6UL_CLK_UART1_IPG]      = imx_clk_gate2("uart1_ipg",    "ipg",          base + 0x7c,    24);
-       clks[IMX6UL_CLK_UART1_SERIAL]   = imx_clk_gate2("uart1_serial", "uart_podf",    base + 0x7c,    24);
-       clks[IMX6UL_CLK_UART7_IPG]      = imx_clk_gate2("uart7_ipg",    "ipg",          base + 0x7c,    26);
-       clks[IMX6UL_CLK_UART7_SERIAL]   = imx_clk_gate2("uart7_serial", "uart_podf",    base + 0x7c,    26);
-       clks[IMX6UL_CLK_SAI1]           = imx_clk_gate2_shared("sai1",          "sai1_podf",    base + 0x7c,    28, &share_count_sai1);
-       clks[IMX6UL_CLK_SAI1_IPG]       = imx_clk_gate2_shared("sai1_ipg",      "ipg",          base + 0x7c,    28, &share_count_sai1);
-       clks[IMX6UL_CLK_SAI2]           = imx_clk_gate2_shared("sai2",          "sai2_podf",    base + 0x7c,    30, &share_count_sai2);
-       clks[IMX6UL_CLK_SAI2_IPG]       = imx_clk_gate2_shared("sai2_ipg",      "ipg",          base + 0x7c,    30, &share_count_sai2);
+       hws[IMX6UL_CLK_ROM]             = imx_clk_hw_gate2_flags("rom", "ahb",          base + 0x7c,    0,      CLK_IS_CRITICAL);
+       hws[IMX6UL_CLK_SDMA]            = imx_clk_hw_gate2("sdma",              "ahb",          base + 0x7c,    6);
+       hws[IMX6UL_CLK_KPP]             = imx_clk_hw_gate2("kpp",               "ipg",          base + 0x7c,    8);
+       hws[IMX6UL_CLK_WDOG2]           = imx_clk_hw_gate2("wdog2",     "ipg",          base + 0x7c,    10);
+       hws[IMX6UL_CLK_SPBA]            = imx_clk_hw_gate2("spba",              "ipg",          base + 0x7c,    12);
+       hws[IMX6UL_CLK_SPDIF]           = imx_clk_hw_gate2_shared("spdif",              "spdif_podf",   base + 0x7c,    14, &share_count_audio);
+       hws[IMX6UL_CLK_SPDIF_GCLK]      = imx_clk_hw_gate2_shared("spdif_gclk", "ipg",          base + 0x7c,    14, &share_count_audio);
+       hws[IMX6UL_CLK_SAI3]            = imx_clk_hw_gate2_shared("sai3",               "sai3_podf",    base + 0x7c,    22, &share_count_sai3);
+       hws[IMX6UL_CLK_SAI3_IPG]        = imx_clk_hw_gate2_shared("sai3_ipg",   "ipg",          base + 0x7c,    22, &share_count_sai3);
+       hws[IMX6UL_CLK_UART1_IPG]       = imx_clk_hw_gate2("uart1_ipg", "ipg",          base + 0x7c,    24);
+       hws[IMX6UL_CLK_UART1_SERIAL]    = imx_clk_hw_gate2("uart1_serial",      "uart_podf",    base + 0x7c,    24);
+       hws[IMX6UL_CLK_UART7_IPG]       = imx_clk_hw_gate2("uart7_ipg", "ipg",          base + 0x7c,    26);
+       hws[IMX6UL_CLK_UART7_SERIAL]    = imx_clk_hw_gate2("uart7_serial",      "uart_podf",    base + 0x7c,    26);
+       hws[IMX6UL_CLK_SAI1]            = imx_clk_hw_gate2_shared("sai1",               "sai1_podf",    base + 0x7c,    28, &share_count_sai1);
+       hws[IMX6UL_CLK_SAI1_IPG]        = imx_clk_hw_gate2_shared("sai1_ipg",   "ipg",          base + 0x7c,    28, &share_count_sai1);
+       hws[IMX6UL_CLK_SAI2]            = imx_clk_hw_gate2_shared("sai2",               "sai2_podf",    base + 0x7c,    30, &share_count_sai2);
+       hws[IMX6UL_CLK_SAI2_IPG]        = imx_clk_hw_gate2_shared("sai2_ipg",   "ipg",          base + 0x7c,    30, &share_count_sai2);
  
        /* CCGR6 */
-       clks[IMX6UL_CLK_USBOH3]         = imx_clk_gate2("usboh3",       "ipg",           base + 0x80,   0);
-       clks[IMX6UL_CLK_USDHC1]         = imx_clk_gate2("usdhc1",       "usdhc1_podf",   base + 0x80,   2);
-       clks[IMX6UL_CLK_USDHC2]         = imx_clk_gate2("usdhc2",       "usdhc2_podf",   base + 0x80,   4);
+       hws[IMX6UL_CLK_USBOH3]          = imx_clk_hw_gate2("usboh3",    "ipg",           base + 0x80,   0);
+       hws[IMX6UL_CLK_USDHC1]          = imx_clk_hw_gate2("usdhc1",    "usdhc1_podf",   base + 0x80,   2);
+       hws[IMX6UL_CLK_USDHC2]          = imx_clk_hw_gate2("usdhc2",    "usdhc2_podf",   base + 0x80,   4);
        if (clk_on_imx6ul()) {
-               clks[IMX6UL_CLK_SIM1]           = imx_clk_gate2("sim1",         "sim_sel",       base + 0x80,   6);
-               clks[IMX6UL_CLK_SIM2]           = imx_clk_gate2("sim2",         "sim_sel",       base + 0x80,   8);
+               hws[IMX6UL_CLK_SIM1]            = imx_clk_hw_gate2("sim1",              "sim_sel",       base + 0x80,   6);
+               hws[IMX6UL_CLK_SIM2]            = imx_clk_hw_gate2("sim2",              "sim_sel",       base + 0x80,   8);
        }
-       clks[IMX6UL_CLK_EIM]            = imx_clk_gate2("eim",          "eim_slow_podf", base + 0x80,   10);
-       clks[IMX6UL_CLK_PWM8]           = imx_clk_gate2("pwm8",         "perclk",        base + 0x80,   16);
-       clks[IMX6UL_CLK_UART8_IPG]      = imx_clk_gate2("uart8_ipg",    "ipg",           base + 0x80,   14);
-       clks[IMX6UL_CLK_UART8_SERIAL]   = imx_clk_gate2("uart8_serial", "uart_podf",     base + 0x80,   14);
-       clks[IMX6UL_CLK_WDOG3]          = imx_clk_gate2("wdog3",        "ipg",           base + 0x80,   20);
-       clks[IMX6UL_CLK_I2C4]           = imx_clk_gate2("i2c4",         "perclk",        base + 0x80,   24);
-       clks[IMX6UL_CLK_PWM5]           = imx_clk_gate2("pwm5",         "perclk",        base + 0x80,   26);
-       clks[IMX6UL_CLK_PWM6]           = imx_clk_gate2("pwm6",         "perclk",        base + 0x80,   28);
-       clks[IMX6UL_CLK_PWM7]           = imx_clk_gate2("pwm7",         "perclk",        base + 0x80,   30);
+       hws[IMX6UL_CLK_EIM]             = imx_clk_hw_gate2("eim",               "eim_slow_podf", base + 0x80,   10);
+       hws[IMX6UL_CLK_PWM8]            = imx_clk_hw_gate2("pwm8",              "perclk",        base + 0x80,   16);
+       hws[IMX6UL_CLK_UART8_IPG]       = imx_clk_hw_gate2("uart8_ipg", "ipg",           base + 0x80,   14);
+       hws[IMX6UL_CLK_UART8_SERIAL]    = imx_clk_hw_gate2("uart8_serial", "uart_podf",  base + 0x80,   14);
+       hws[IMX6UL_CLK_WDOG3]           = imx_clk_hw_gate2("wdog3",     "ipg",           base + 0x80,   20);
+       hws[IMX6UL_CLK_I2C4]            = imx_clk_hw_gate2("i2c4",              "perclk",        base + 0x80,   24);
+       hws[IMX6UL_CLK_PWM5]            = imx_clk_hw_gate2("pwm5",              "perclk",        base + 0x80,   26);
+       hws[IMX6UL_CLK_PWM6]            = imx_clk_hw_gate2("pwm6",              "perclk",        base + 0x80,   28);
+       hws[IMX6UL_CLK_PWM7]            = imx_clk_hw_gate2("pwm7",              "perclk",        base + 0x80,   30);
  
        /* CCOSR */
-       clks[IMX6UL_CLK_CKO1]           = imx_clk_gate("cko1",          "cko1_podf",     base + 0x60,   7);
-       clks[IMX6UL_CLK_CKO2]           = imx_clk_gate("cko2",          "cko2_podf",     base + 0x60,   24);
+       hws[IMX6UL_CLK_CKO1]            = imx_clk_hw_gate("cko1",               "cko1_podf",     base + 0x60,   7);
+       hws[IMX6UL_CLK_CKO2]            = imx_clk_hw_gate("cko2",               "cko2_podf",     base + 0x60,   24);
  
        /* mask handshake of mmdc */
-       writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+       imx_mmdc_mask_handshake(base, 0);
  
-       imx_check_clocks(clks, ARRAY_SIZE(clks));
+       imx_check_clk_hws(hws, IMX6UL_CLK_END);
  
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
  
        /*
         * Lower the AHB clock rate before changing the parent clock source,
         * AXI clock rate, so we need to lower AHB rate first to make sure at
         * any time, AHB rate is <= 133MHz.
         */
-       clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
+       clk_set_rate(hws[IMX6UL_CLK_AHB]->clk, 99000000);
  
        /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
-       clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_OSC]);
-       clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
-       clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
-       clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
+       clk_set_parent(hws[IMX6UL_CLK_PERIPH_CLK2_SEL]->clk, hws[IMX6UL_CLK_OSC]->clk);
+       clk_set_parent(hws[IMX6UL_CLK_PERIPH]->clk, hws[IMX6UL_CLK_PERIPH_CLK2]->clk);
+       clk_set_parent(hws[IMX6UL_CLK_PERIPH_PRE]->clk, hws[IMX6UL_CLK_PLL2_BUS]->clk);
+       clk_set_parent(hws[IMX6UL_CLK_PERIPH]->clk, hws[IMX6UL_CLK_PERIPH_PRE]->clk);
  
        /* Make sure AHB rate is 132MHz  */
-       clk_set_rate(clks[IMX6UL_CLK_AHB], 132000000);
+       clk_set_rate(hws[IMX6UL_CLK_AHB]->clk, 132000000);
  
        /* set perclk to from OSC */
-       clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
+       clk_set_parent(hws[IMX6UL_CLK_PERCLK_SEL]->clk, hws[IMX6UL_CLK_OSC]->clk);
  
-       clk_set_rate(clks[IMX6UL_CLK_ENET_REF], 50000000);
-       clk_set_rate(clks[IMX6UL_CLK_ENET2_REF], 50000000);
-       clk_set_rate(clks[IMX6UL_CLK_CSI], 24000000);
+       clk_set_rate(hws[IMX6UL_CLK_ENET_REF]->clk, 50000000);
+       clk_set_rate(hws[IMX6UL_CLK_ENET2_REF]->clk, 50000000);
+       clk_set_rate(hws[IMX6UL_CLK_CSI]->clk, 24000000);
  
        if (clk_on_imx6ull())
-               clk_prepare_enable(clks[IMX6UL_CLK_AIPSTZ3]);
+               clk_prepare_enable(hws[IMX6UL_CLK_AIPSTZ3]->clk);
  
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
-               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
-               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
+               clk_prepare_enable(hws[IMX6UL_CLK_USBPHY1_GATE]->clk);
+               clk_prepare_enable(hws[IMX6UL_CLK_USBPHY2_GATE]->clk);
        }
  
-       clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
+       clk_set_parent(hws[IMX6UL_CLK_CAN_SEL]->clk, hws[IMX6UL_CLK_PLL3_60M]->clk);
        if (clk_on_imx6ul())
-               clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+               clk_set_parent(hws[IMX6UL_CLK_SIM_PRE_SEL]->clk, hws[IMX6UL_CLK_PLL3_USB_OTG]->clk);
        else if (clk_on_imx6ull())
-               clk_set_parent(clks[IMX6ULL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]);
+               clk_set_parent(hws[IMX6ULL_CLK_EPDC_PRE_SEL]->clk, hws[IMX6UL_CLK_PLL3_PFD2]->clk);
  
-       clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
+       clk_set_parent(hws[IMX6UL_CLK_ENFC_SEL]->clk, hws[IMX6UL_CLK_PLL2_PFD2]->clk);
  }
  
  CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
index 8f3aa994c8f7b07aa68a69742fc22621bfb41068,c1efb061d237e5e3663b43b0d8f23c556adf6be0..fbea774ef6877b27d9ceb94917c4562e50cefa74
@@@ -1,11 -1,18 +1,12 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <dt-bindings/clock/imx7d-clock.h>
  #include <linux/clk.h>
  #include <linux/clkdev.h>
+ #include <linux/clk-provider.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/io.h>
@@@ -39,7 -46,6 +40,6 @@@ static const struct clk_div_table post_
        { }
  };
  
- static struct clk *clks[IMX7D_CLK_END];
  static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk",
        "pll_enet_500m_clk", "pll_dram_main_clk",
        "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_audio_post_div",
@@@ -373,517 -379,533 +373,533 @@@ static const char *pll_enet_bypass_sel[
  static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", };
  static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", };
  
- static struct clk_onecell_data clk_data;
- static struct clk ** const uart_clks[] __initconst = {
-       &clks[IMX7D_UART1_ROOT_CLK],
-       &clks[IMX7D_UART2_ROOT_CLK],
-       &clks[IMX7D_UART3_ROOT_CLK],
-       &clks[IMX7D_UART4_ROOT_CLK],
-       &clks[IMX7D_UART5_ROOT_CLK],
-       &clks[IMX7D_UART6_ROOT_CLK],
-       &clks[IMX7D_UART7_ROOT_CLK],
-       NULL
+ static struct clk_hw **hws;
+ static struct clk_hw_onecell_data *clk_hw_data;
+ static const int uart_clk_ids[] __initconst = {
+       IMX7D_UART1_ROOT_CLK,
+       IMX7D_UART2_ROOT_CLK,
+       IMX7D_UART3_ROOT_CLK,
+       IMX7D_UART4_ROOT_CLK,
+       IMX7D_UART5_ROOT_CLK,
+       IMX7D_UART6_ROOT_CLK,
+       IMX7D_UART7_ROOT_CLK,
  };
  
+ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata;
  static void __init imx7d_clocks_init(struct device_node *ccm_node)
  {
        struct device_node *np;
        void __iomem *base;
+       int i;
+       clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+                                         IMX7D_CLK_END), GFP_KERNEL);
+       if (WARN_ON(!clk_hw_data))
+               return;
+       clk_hw_data->num = IMX7D_CLK_END;
+       hws = clk_hw_data->hws;
  
-       clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
-       clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
-       clks[IMX7D_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+       hws[IMX7D_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
+       hws[IMX7D_OSC_24M_CLK] = __clk_get_hw(of_clk_get_by_name(ccm_node, "osc"));
+       hws[IMX7D_CKIL] = __clk_get_hw(of_clk_get_by_name(ccm_node, "ckil"));
  
        np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
        base = of_iomap(np, 0);
        WARN_ON(!base);
        of_node_put(np);
  
-       clks[IMX7D_PLL_ARM_MAIN_SRC]  = imx_clk_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_SYS_MAIN_SRC]  = imx_clk_mux("pll_sys_main_src", base + 0xb0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_ENET_MAIN_SRC] = imx_clk_mux("pll_enet_main_src", base + 0xe0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
-       clks[IMX7D_PLL_ARM_MAIN]  = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f);
-       clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_DDR_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f);
-       clks[IMX7D_PLL_SYS_MAIN]  = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
-       clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
-       clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_audio_main", "osc", base + 0xf0, 0x7f);
-       clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_video_main", "osc", base + 0x130, 0x7f);
-       clks[IMX7D_PLL_ARM_MAIN_BYPASS]  = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_SYS_MAIN_BYPASS]  = imx_clk_mux_flags("pll_sys_main_bypass", base + 0xb0, 16, 1, pll_sys_bypass_sel, ARRAY_SIZE(pll_sys_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_ENET_MAIN_BYPASS] = imx_clk_mux_flags("pll_enet_main_bypass", base + 0xe0, 16, 1, pll_enet_bypass_sel, ARRAY_SIZE(pll_enet_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
-       clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13);
-       clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_test_div", base + 0x70, 13);
-       clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13);
-       clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13);
-       clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13);
-       clks[IMX7D_PLL_DRAM_TEST_DIV]  = clk_register_divider_table(NULL, "pll_dram_test_div", "pll_dram_main_bypass",
+       hws[IMX7D_PLL_ARM_MAIN_SRC]  = imx_clk_hw_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_hw_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_SYS_MAIN_SRC]  = imx_clk_hw_mux("pll_sys_main_src", base + 0xb0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_ENET_MAIN_SRC] = imx_clk_hw_mux("pll_enet_main_src", base + 0xe0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_hw_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_hw_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
+       hws[IMX7D_PLL_ARM_MAIN]  = imx_clk_hw_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f);
+       hws[IMX7D_PLL_DRAM_MAIN] = imx_clk_hw_pllv3(IMX_PLLV3_DDR_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f);
+       hws[IMX7D_PLL_SYS_MAIN]  = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
+       hws[IMX7D_PLL_ENET_MAIN] = imx_clk_hw_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
+       hws[IMX7D_PLL_AUDIO_MAIN] = imx_clk_hw_pllv3(IMX_PLLV3_AV_IMX7, "pll_audio_main", "osc", base + 0xf0, 0x7f);
+       hws[IMX7D_PLL_VIDEO_MAIN] = imx_clk_hw_pllv3(IMX_PLLV3_AV_IMX7, "pll_video_main", "osc", base + 0x130, 0x7f);
+       hws[IMX7D_PLL_ARM_MAIN_BYPASS]  = imx_clk_hw_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_hw_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_SYS_MAIN_BYPASS]  = imx_clk_hw_mux_flags("pll_sys_main_bypass", base + 0xb0, 16, 1, pll_sys_bypass_sel, ARRAY_SIZE(pll_sys_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_ENET_MAIN_BYPASS] = imx_clk_hw_mux_flags("pll_enet_main_bypass", base + 0xe0, 16, 1, pll_enet_bypass_sel, ARRAY_SIZE(pll_enet_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_hw_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_hw_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
+       hws[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_hw_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13);
+       hws[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_hw_gate("pll_dram_main_clk", "pll_dram_test_div", base + 0x70, 13);
+       hws[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_hw_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13);
+       hws[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_hw_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13);
+       hws[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_hw_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13);
+       hws[IMX7D_PLL_DRAM_TEST_DIV]  = clk_hw_register_divider_table(NULL, "pll_dram_test_div", "pll_dram_main_bypass",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 21, 2, 0, test_div_table, &imx_ccm_lock);
-       clks[IMX7D_PLL_AUDIO_TEST_DIV]  = clk_register_divider_table(NULL, "pll_audio_test_div", "pll_audio_main_clk",
+       hws[IMX7D_PLL_AUDIO_TEST_DIV]  = clk_hw_register_divider_table(NULL, "pll_audio_test_div", "pll_audio_main_clk",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 19, 2, 0, test_div_table, &imx_ccm_lock);
-       clks[IMX7D_PLL_AUDIO_POST_DIV] = clk_register_divider_table(NULL, "pll_audio_post_div", "pll_audio_test_div",
+       hws[IMX7D_PLL_AUDIO_POST_DIV] = clk_hw_register_divider_table(NULL, "pll_audio_post_div", "pll_audio_test_div",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 22, 2, 0, post_div_table, &imx_ccm_lock);
-       clks[IMX7D_PLL_VIDEO_TEST_DIV]  = clk_register_divider_table(NULL, "pll_video_test_div", "pll_video_main_clk",
+       hws[IMX7D_PLL_VIDEO_TEST_DIV]  = clk_hw_register_divider_table(NULL, "pll_video_test_div", "pll_video_main_clk",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 19, 2, 0, test_div_table, &imx_ccm_lock);
-       clks[IMX7D_PLL_VIDEO_POST_DIV] = clk_register_divider_table(NULL, "pll_video_post_div", "pll_video_test_div",
+       hws[IMX7D_PLL_VIDEO_POST_DIV] = clk_hw_register_divider_table(NULL, "pll_video_post_div", "pll_video_test_div",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 22, 2, 0, post_div_table, &imx_ccm_lock);
  
-       clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0);
-       clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1);
-       clks[IMX7D_PLL_SYS_PFD2_270M_CLK] = imx_clk_pfd("pll_sys_pfd2_270m_clk", "pll_sys_main_clk", base + 0xc0, 2);
-       clks[IMX7D_PLL_SYS_PFD3_CLK] = imx_clk_pfd("pll_sys_pfd3_clk", "pll_sys_main_clk", base + 0xc0, 3);
-       clks[IMX7D_PLL_SYS_PFD4_CLK] = imx_clk_pfd("pll_sys_pfd4_clk", "pll_sys_main_clk", base + 0xd0, 0);
-       clks[IMX7D_PLL_SYS_PFD5_CLK] = imx_clk_pfd("pll_sys_pfd5_clk", "pll_sys_main_clk", base + 0xd0, 1);
-       clks[IMX7D_PLL_SYS_PFD6_CLK] = imx_clk_pfd("pll_sys_pfd6_clk", "pll_sys_main_clk", base + 0xd0, 2);
-       clks[IMX7D_PLL_SYS_PFD7_CLK] = imx_clk_pfd("pll_sys_pfd7_clk", "pll_sys_main_clk", base + 0xd0, 3);
-       clks[IMX7D_PLL_SYS_MAIN_480M] = imx_clk_fixed_factor("pll_sys_main_480m", "pll_sys_main_clk", 1, 1);
-       clks[IMX7D_PLL_SYS_MAIN_240M] = imx_clk_fixed_factor("pll_sys_main_240m", "pll_sys_main_clk", 1, 2);
-       clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4);
-       clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2);
-       clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis_flags("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4, CLK_IS_CRITICAL);
-       clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5);
-       clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6);
-       clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12);
-       clks[IMX7D_PLL_SYS_PFD0_196M] = imx_clk_fixed_factor("pll_sys_pfd0_196m", "pll_sys_pfd0_392m_clk", 1, 2);
-       clks[IMX7D_PLL_SYS_PFD1_166M] = imx_clk_fixed_factor("pll_sys_pfd1_166m", "pll_sys_pfd1_332m_clk", 1, 2);
-       clks[IMX7D_PLL_SYS_PFD2_135M] = imx_clk_fixed_factor("pll_sys_pfd2_135m", "pll_sys_pfd2_270m_clk", 1, 2);
-       clks[IMX7D_PLL_SYS_PFD0_196M_CLK] = imx_clk_gate_dis("pll_sys_pfd0_196m_clk", "pll_sys_pfd0_196m", base + 0xb0, 26);
-       clks[IMX7D_PLL_SYS_PFD1_166M_CLK] = imx_clk_gate_dis("pll_sys_pfd1_166m_clk", "pll_sys_pfd1_166m", base + 0xb0, 27);
-       clks[IMX7D_PLL_SYS_PFD2_135M_CLK] = imx_clk_gate_dis("pll_sys_pfd2_135m_clk", "pll_sys_pfd2_135m", base + 0xb0, 28);
-       clks[IMX7D_PLL_ENET_MAIN_CLK] = imx_clk_fixed_factor("pll_enet_main_clk", "pll_enet_main_bypass", 1, 1);
-       clks[IMX7D_PLL_ENET_MAIN_500M] = imx_clk_fixed_factor("pll_enet_500m", "pll_enet_main_clk", 1, 2);
-       clks[IMX7D_PLL_ENET_MAIN_250M] = imx_clk_fixed_factor("pll_enet_250m", "pll_enet_main_clk", 1, 4);
-       clks[IMX7D_PLL_ENET_MAIN_125M] = imx_clk_fixed_factor("pll_enet_125m", "pll_enet_main_clk", 1, 8);
-       clks[IMX7D_PLL_ENET_MAIN_100M] = imx_clk_fixed_factor("pll_enet_100m", "pll_enet_main_clk", 1, 10);
-       clks[IMX7D_PLL_ENET_MAIN_50M] = imx_clk_fixed_factor("pll_enet_50m", "pll_enet_main_clk", 1, 20);
-       clks[IMX7D_PLL_ENET_MAIN_40M] = imx_clk_fixed_factor("pll_enet_40m", "pll_enet_main_clk", 1, 25);
-       clks[IMX7D_PLL_ENET_MAIN_25M] = imx_clk_fixed_factor("pll_enet_25m", "pll_enet_main_clk", 1, 40);
-       clks[IMX7D_PLL_ENET_MAIN_500M_CLK] = imx_clk_gate("pll_enet_500m_clk", "pll_enet_500m", base + 0xe0, 12);
-       clks[IMX7D_PLL_ENET_MAIN_250M_CLK] = imx_clk_gate("pll_enet_250m_clk", "pll_enet_250m", base + 0xe0, 11);
-       clks[IMX7D_PLL_ENET_MAIN_125M_CLK] = imx_clk_gate("pll_enet_125m_clk", "pll_enet_125m", base + 0xe0, 10);
-       clks[IMX7D_PLL_ENET_MAIN_100M_CLK] = imx_clk_gate("pll_enet_100m_clk", "pll_enet_100m", base + 0xe0, 9);
-       clks[IMX7D_PLL_ENET_MAIN_50M_CLK]  = imx_clk_gate("pll_enet_50m_clk", "pll_enet_50m", base + 0xe0, 8);
-       clks[IMX7D_PLL_ENET_MAIN_40M_CLK]  = imx_clk_gate("pll_enet_40m_clk", "pll_enet_40m", base + 0xe0, 7);
-       clks[IMX7D_PLL_ENET_MAIN_25M_CLK]  = imx_clk_gate("pll_enet_25m_clk", "pll_enet_25m", base + 0xe0, 6);
-       clks[IMX7D_LVDS1_OUT_SEL] = imx_clk_mux("lvds1_sel", base + 0x170, 0, 5, lvds1_sel, ARRAY_SIZE(lvds1_sel));
-       clks[IMX7D_LVDS1_OUT_CLK] = imx_clk_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x170, 5, BIT(6));
+       hws[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_hw_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0);
+       hws[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_hw_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1);
+       hws[IMX7D_PLL_SYS_PFD2_270M_CLK] = imx_clk_hw_pfd("pll_sys_pfd2_270m_clk", "pll_sys_main_clk", base + 0xc0, 2);
+       hws[IMX7D_PLL_SYS_PFD3_CLK] = imx_clk_hw_pfd("pll_sys_pfd3_clk", "pll_sys_main_clk", base + 0xc0, 3);
+       hws[IMX7D_PLL_SYS_PFD4_CLK] = imx_clk_hw_pfd("pll_sys_pfd4_clk", "pll_sys_main_clk", base + 0xd0, 0);
+       hws[IMX7D_PLL_SYS_PFD5_CLK] = imx_clk_hw_pfd("pll_sys_pfd5_clk", "pll_sys_main_clk", base + 0xd0, 1);
+       hws[IMX7D_PLL_SYS_PFD6_CLK] = imx_clk_hw_pfd("pll_sys_pfd6_clk", "pll_sys_main_clk", base + 0xd0, 2);
+       hws[IMX7D_PLL_SYS_PFD7_CLK] = imx_clk_hw_pfd("pll_sys_pfd7_clk", "pll_sys_main_clk", base + 0xd0, 3);
+       hws[IMX7D_PLL_SYS_MAIN_480M] = imx_clk_hw_fixed_factor("pll_sys_main_480m", "pll_sys_main_clk", 1, 1);
+       hws[IMX7D_PLL_SYS_MAIN_240M] = imx_clk_hw_fixed_factor("pll_sys_main_240m", "pll_sys_main_clk", 1, 2);
+       hws[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_hw_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4);
+       hws[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_hw_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2);
+       hws[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_hw_gate_dis_flags("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4, CLK_IS_CRITICAL);
+       hws[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_hw_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5);
+       hws[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_hw_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6);
+       hws[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_hw_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12);
+       hws[IMX7D_PLL_SYS_PFD0_196M] = imx_clk_hw_fixed_factor("pll_sys_pfd0_196m", "pll_sys_pfd0_392m_clk", 1, 2);
+       hws[IMX7D_PLL_SYS_PFD1_166M] = imx_clk_hw_fixed_factor("pll_sys_pfd1_166m", "pll_sys_pfd1_332m_clk", 1, 2);
+       hws[IMX7D_PLL_SYS_PFD2_135M] = imx_clk_hw_fixed_factor("pll_sys_pfd2_135m", "pll_sys_pfd2_270m_clk", 1, 2);
+       hws[IMX7D_PLL_SYS_PFD0_196M_CLK] = imx_clk_hw_gate_dis("pll_sys_pfd0_196m_clk", "pll_sys_pfd0_196m", base + 0xb0, 26);
+       hws[IMX7D_PLL_SYS_PFD1_166M_CLK] = imx_clk_hw_gate_dis("pll_sys_pfd1_166m_clk", "pll_sys_pfd1_166m", base + 0xb0, 27);
+       hws[IMX7D_PLL_SYS_PFD2_135M_CLK] = imx_clk_hw_gate_dis("pll_sys_pfd2_135m_clk", "pll_sys_pfd2_135m", base + 0xb0, 28);
+       hws[IMX7D_PLL_ENET_MAIN_CLK] = imx_clk_hw_fixed_factor("pll_enet_main_clk", "pll_enet_main_bypass", 1, 1);
+       hws[IMX7D_PLL_ENET_MAIN_500M] = imx_clk_hw_fixed_factor("pll_enet_500m", "pll_enet_main_clk", 1, 2);
+       hws[IMX7D_PLL_ENET_MAIN_250M] = imx_clk_hw_fixed_factor("pll_enet_250m", "pll_enet_main_clk", 1, 4);
+       hws[IMX7D_PLL_ENET_MAIN_125M] = imx_clk_hw_fixed_factor("pll_enet_125m", "pll_enet_main_clk", 1, 8);
+       hws[IMX7D_PLL_ENET_MAIN_100M] = imx_clk_hw_fixed_factor("pll_enet_100m", "pll_enet_main_clk", 1, 10);
+       hws[IMX7D_PLL_ENET_MAIN_50M] = imx_clk_hw_fixed_factor("pll_enet_50m", "pll_enet_main_clk", 1, 20);
+       hws[IMX7D_PLL_ENET_MAIN_40M] = imx_clk_hw_fixed_factor("pll_enet_40m", "pll_enet_main_clk", 1, 25);
+       hws[IMX7D_PLL_ENET_MAIN_25M] = imx_clk_hw_fixed_factor("pll_enet_25m", "pll_enet_main_clk", 1, 40);
+       hws[IMX7D_PLL_ENET_MAIN_500M_CLK] = imx_clk_hw_gate("pll_enet_500m_clk", "pll_enet_500m", base + 0xe0, 12);
+       hws[IMX7D_PLL_ENET_MAIN_250M_CLK] = imx_clk_hw_gate("pll_enet_250m_clk", "pll_enet_250m", base + 0xe0, 11);
+       hws[IMX7D_PLL_ENET_MAIN_125M_CLK] = imx_clk_hw_gate("pll_enet_125m_clk", "pll_enet_125m", base + 0xe0, 10);
+       hws[IMX7D_PLL_ENET_MAIN_100M_CLK] = imx_clk_hw_gate("pll_enet_100m_clk", "pll_enet_100m", base + 0xe0, 9);
+       hws[IMX7D_PLL_ENET_MAIN_50M_CLK]  = imx_clk_hw_gate("pll_enet_50m_clk", "pll_enet_50m", base + 0xe0, 8);
+       hws[IMX7D_PLL_ENET_MAIN_40M_CLK]  = imx_clk_hw_gate("pll_enet_40m_clk", "pll_enet_40m", base + 0xe0, 7);
+       hws[IMX7D_PLL_ENET_MAIN_25M_CLK]  = imx_clk_hw_gate("pll_enet_25m_clk", "pll_enet_25m", base + 0xe0, 6);
+       hws[IMX7D_LVDS1_OUT_SEL] = imx_clk_hw_mux("lvds1_sel", base + 0x170, 0, 5, lvds1_sel, ARRAY_SIZE(lvds1_sel));
+       hws[IMX7D_LVDS1_OUT_CLK] = imx_clk_hw_gate_exclusive("lvds1_out", "lvds1_sel", base + 0x170, 5, BIT(6));
  
        np = ccm_node;
        base = of_iomap(np, 0);
        WARN_ON(!base);
  
-       clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
-       clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
-       clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
-       clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
-       clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel));
-       clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel));
-       clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel));
-       clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel));
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel));
-       clks[IMX7D_DRAM_ALT_ROOT_SRC]  = imx_clk_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel));
-       clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel));
-       clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
-       clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
-       clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
-       clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
-       clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 0xa380, 24, 3,  mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
-       clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
-       clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
-       clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel));
-       clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel));
-       clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel));
-       clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel));
-       clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel));
-       clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel));
-       clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel));
-       clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel));
-       clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel));
-       clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel));
-       clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel));
-       clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel));
-       clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel));
-       clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel));
-       clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel));
-       clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel));
-       clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel));
-       clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel));
-       clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel));
-       clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel));
-       clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel));
-       clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel));
-       clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel));
-       clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel));
-       clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel));
-       clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel));
-       clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel));
-       clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel));
-       clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel));
-       clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel));
-       clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel));
-       clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel));
-       clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel));
-       clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel));
-       clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel));
-       clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel));
-       clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel));
-       clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel));
-       clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel));
-       clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel));
-       clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel));
-       clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel));
-       clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel));
-       clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel));
-       clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel));
-       clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel));
-       clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel));
-       clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel));
-       clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel));
-       clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel));
-       clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel));
-       clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
-       clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
-       clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28);
-       clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
-       clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate3("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28);
-       clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate3("ahb_cg", "ahb_src", base + 0x9000, 28);
-       clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate3("dram_phym_cg", "dram_phym_src", base + 0x9800, 28);
-       clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate3("dram_cg", "dram_src", base + 0x9880, 28);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate3("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28);
-       clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate3("dram_alt_cg", "dram_alt_src", base + 0xa080, 28);
-       clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate3("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28);
-       clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate3("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28);
-       clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate3("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28);
-       clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate3("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate3("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28);
-       clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate3("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28);
-       clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate3("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28);
-       clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate3("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28);
-       clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate3("sai1_cg", "sai1_src", base + 0xa500, 28);
-       clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate3("sai2_cg", "sai2_src", base + 0xa580, 28);
-       clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate3("sai3_cg", "sai3_src", base + 0xa600, 28);
-       clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate3("spdif_cg", "spdif_src", base + 0xa680, 28);
-       clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate3("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28);
-       clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate3("enet1_time_cg", "enet1_time_src", base + 0xa780, 28);
-       clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate3("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28);
-       clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate3("enet2_time_cg", "enet2_time_src", base + 0xa880, 28);
-       clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate3("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28);
-       clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate3("eim_cg", "eim_src", base + 0xa980, 28);
-       clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate3("nand_cg", "nand_src", base + 0xaa00, 28);
-       clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate3("qspi_cg", "qspi_src", base + 0xaa80, 28);
-       clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate3("usdhc1_cg", "usdhc1_src", base + 0xab00, 28);
-       clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate3("usdhc2_cg", "usdhc2_src", base + 0xab80, 28);
-       clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate3("usdhc3_cg", "usdhc3_src", base + 0xac00, 28);
-       clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate3("can1_cg", "can1_src", base + 0xac80, 28);
-       clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate3("can2_cg", "can2_src", base + 0xad00, 28);
-       clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate3("i2c1_cg", "i2c1_src", base + 0xad80, 28);
-       clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate3("i2c2_cg", "i2c2_src", base + 0xae00, 28);
-       clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate3("i2c3_cg", "i2c3_src", base + 0xae80, 28);
-       clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate3("i2c4_cg", "i2c4_src", base + 0xaf00, 28);
-       clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate3("uart1_cg", "uart1_src", base + 0xaf80, 28);
-       clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate3("uart2_cg", "uart2_src", base + 0xb000, 28);
-       clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate3("uart3_cg", "uart3_src", base + 0xb080, 28);
-       clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate3("uart4_cg", "uart4_src", base + 0xb100, 28);
-       clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate3("uart5_cg", "uart5_src", base + 0xb180, 28);
-       clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate3("uart6_cg", "uart6_src", base + 0xb200, 28);
-       clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate3("uart7_cg", "uart7_src", base + 0xb280, 28);
-       clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate3("ecspi1_cg", "ecspi1_src", base + 0xb300, 28);
-       clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate3("ecspi2_cg", "ecspi2_src", base + 0xb380, 28);
-       clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate3("ecspi3_cg", "ecspi3_src", base + 0xb400, 28);
-       clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate3("ecspi4_cg", "ecspi4_src", base + 0xb480, 28);
-       clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate3("pwm1_cg", "pwm1_src", base + 0xb500, 28);
-       clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate3("pwm2_cg", "pwm2_src", base + 0xb580, 28);
-       clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate3("pwm3_cg", "pwm3_src", base + 0xb600, 28);
-       clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate3("pwm4_cg", "pwm4_src", base + 0xb680, 28);
-       clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate3("flextimer1_cg", "flextimer1_src", base + 0xb700, 28);
-       clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate3("flextimer2_cg", "flextimer2_src", base + 0xb780, 28);
-       clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate3("sim1_cg", "sim1_src", base + 0xb800, 28);
-       clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate3("sim2_cg", "sim2_src", base + 0xb880, 28);
-       clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate3("gpt1_cg", "gpt1_src", base + 0xb900, 28);
-       clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate3("gpt2_cg", "gpt2_src", base + 0xb980, 28);
-       clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate3("gpt3_cg", "gpt3_src", base + 0xbA00, 28);
-       clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate3("gpt4_cg", "gpt4_src", base + 0xbA80, 28);
-       clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate3("trace_cg", "trace_src", base + 0xbb00, 28);
-       clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate3("wdog_cg", "wdog_src", base + 0xbb80, 28);
-       clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate3("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28);
-       clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate3("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28);
-       clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate3("wrclk_cg", "wrclk_src", base + 0xbd00, 28);
-       clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate3("clko1_cg", "clko1_src", base + 0xbd80, 28);
-       clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate3("clko2_cg", "clko2_src", base + 0xbe00, 28);
-       clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider2("axi_pre_div", "axi_cg", base + 0x8800, 16, 3);
-       clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3);
-       clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider2("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3);
-       clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3);
-       clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3);
-       clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider2("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3);
-       clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider2("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3);
-       clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider2("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3);
-       clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3);
-       clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3);
-       clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3);
-       clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3);
-       clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider2("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3);
-       clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider2("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3);
-       clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider2("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3);
-       clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider2("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3);
-       clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3);
-       clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3);
-       clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3);
-       clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3);
-       clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3);
-       clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider2("eim_pre_div", "eim_cg", base + 0xa980, 16, 3);
-       clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider2("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3);
-       clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider2("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3);
-       clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3);
-       clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3);
-       clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider2("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3);
-       clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider2("can1_pre_div", "can1_cg", base + 0xac80, 16, 3);
-       clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider2("can2_pre_div", "can2_cg", base + 0xad00, 16, 3);
-       clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3);
-       clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider2("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3);
-       clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3);
-       clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider2("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3);
-       clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider2("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3);
-       clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider2("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3);
-       clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider2("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3);
-       clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider2("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3);
-       clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider2("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3);
-       clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider2("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3);
-       clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider2("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3);
-       clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3);
-       clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3);
-       clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3);
-       clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider2("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3);
-       clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3);
-       clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3);
-       clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3);
-       clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3);
-       clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider2("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3);
-       clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider2("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3);
-       clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider2("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3);
-       clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider2("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3);
-       clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3);
-       clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider2("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3);
-       clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider2("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3);
-       clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider2("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3);
-       clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider2("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3);
-       clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider2("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3);
-       clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3);
-       clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3);
-       clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider2("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3);
-       clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3);
-       clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3);
-       clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
-       clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
-       clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
-       clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
-       clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
-       clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
-       clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
-       clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
-       clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
-       clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider2("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6);
-       clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider2("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6);
-       clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider2("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6);
-       clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider2("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6);
-       clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6);
-       clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6);
-       clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_dphy_pre_div", base + 0xa480, 0, 6);
-       clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6);
-       clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6);
-       clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6);
-       clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider2("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6);
-       clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider2("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6);
-       clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider2("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6);
-       clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider2("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6);
-       clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6);
-       clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_divider2("enet_phy_ref_root_clk", "enet_phy_ref_pre_div", base + 0xa900, 0, 6);
-       clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6);
-       clks[IMX7D_NAND_ROOT_CLK] = imx_clk_divider2("nand_root_clk", "nand_pre_div", base + 0xaa00, 0, 6);
-       clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6);
-       clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6);
-       clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6);
-       clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider2("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6);
-       clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider2("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6);
-       clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider2("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6);
-       clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider2("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6);
-       clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider2("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6);
-       clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider2("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6);
-       clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider2("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6);
-       clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider2("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6);
-       clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider2("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6);
-       clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider2("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6);
-       clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider2("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6);
-       clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider2("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6);
-       clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider2("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6);
-       clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider2("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6);
-       clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider2("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6);
-       clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider2("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6);
-       clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider2("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6);
-       clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider2("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6);
-       clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider2("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6);
-       clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider2("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6);
-       clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider2("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6);
-       clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider2("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6);
-       clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider2("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6);
-       clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider2("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6);
-       clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider2("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6);
-       clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider2("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6);
-       clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider2("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6);
-       clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider2("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6);
-       clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider2("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6);
-       clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider2("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6);
-       clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider2("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6);
-       clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider2("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6);
-       clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider2("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6);
-       clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider2("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6);
-       clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider2("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6);
-       clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
-       clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
-       clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
-       clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2_flags("main_axi_root_clk", "axi_post_div", base + 0x4040, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
-       clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
-       clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
-       clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
-       clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2_flags("dram_root_clk", "dram_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
-       clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
-       clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
-       clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
-       clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
-       clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4690, 0);
-       clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0);
-       clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
-       clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
-       clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0);
-       clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate4("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0);
-       clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0);
-       clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0);
-       clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0);
-       clks[IMX7D_ENET1_IPG_ROOT_CLK] = imx_clk_gate2_shared2("enet1_ipg_root_clk", "enet_axi_post_div", base + 0x4700, 0, &share_count_enet1);
-       clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2_shared2("enet1_time_root_clk", "enet1_time_post_div", base + 0x4700, 0, &share_count_enet1);
-       clks[IMX7D_ENET2_IPG_ROOT_CLK] = imx_clk_gate2_shared2("enet2_ipg_root_clk", "enet_axi_post_div", base + 0x4710, 0, &share_count_enet2);
-       clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2_shared2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4710, 0, &share_count_enet2);
-       clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2_shared2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0, &share_count_sai1);
-       clks[IMX7D_SAI1_IPG_CLK]  = imx_clk_gate2_shared2("sai1_ipg_clk",  "ipg_root_clk",  base + 0x48c0, 0, &share_count_sai1);
-       clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2_shared2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0, &share_count_sai2);
-       clks[IMX7D_SAI2_IPG_CLK]  = imx_clk_gate2_shared2("sai2_ipg_clk",  "ipg_root_clk",  base + 0x48d0, 0, &share_count_sai2);
-       clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2_shared2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0, &share_count_sai3);
-       clks[IMX7D_SAI3_IPG_CLK]  = imx_clk_gate2_shared2("sai3_ipg_clk",  "ipg_root_clk",  base + 0x48e0, 0, &share_count_sai3);
-       clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0);
-       clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0);
-       clks[IMX7D_NAND_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_rawnand_clk", "nand_root_clk", base + 0x4140, 0, &share_count_nand);
-       clks[IMX7D_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_root_clk", base + 0x4140, 0, &share_count_nand);
-       clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
-       clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
-       clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
-       clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate4("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0);
-       clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate4("can1_root_clk", "can1_post_div", base + 0x4740, 0);
-       clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate4("can2_root_clk", "can2_post_div", base + 0x4750, 0);
-       clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate4("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0);
-       clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate4("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0);
-       clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate4("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0);
-       clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate4("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0);
-       clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate4("uart1_root_clk", "uart1_post_div", base + 0x4940, 0);
-       clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate4("uart2_root_clk", "uart2_post_div", base + 0x4950, 0);
-       clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate4("uart3_root_clk", "uart3_post_div", base + 0x4960, 0);
-       clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate4("uart4_root_clk", "uart4_post_div", base + 0x4970, 0);
-       clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate4("uart5_root_clk", "uart5_post_div", base + 0x4980, 0);
-       clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate4("uart6_root_clk", "uart6_post_div", base + 0x4990, 0);
-       clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate4("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0);
-       clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate4("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0);
-       clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate4("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0);
-       clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate4("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0);
-       clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate4("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0);
-       clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate4("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0);
-       clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate4("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0);
-       clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate4("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0);
-       clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate4("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0);
-       clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate4("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0);
-       clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate4("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0);
-       clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate4("sim1_root_clk", "sim1_post_div", base + 0x4900, 0);
-       clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate4("sim2_root_clk", "sim2_post_div", base + 0x4910, 0);
-       clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate4("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0);
-       clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate4("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0);
-       clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate4("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0);
-       clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate4("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0);
-       clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate4("trace_root_clk", "trace_post_div", base + 0x4300, 0);
-       clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate4("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0);
-       clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate4("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0);
-       clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate4("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0);
-       clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
-       clks[IMX7D_KPP_ROOT_CLK] = imx_clk_gate4("kpp_root_clk", "ipg_root_clk", base + 0x4aa0, 0);
-       clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
-       clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
-       clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
-       clks[IMX7D_USB_CTRL_CLK] = imx_clk_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
-       clks[IMX7D_USB_PHY1_CLK] = imx_clk_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
-       clks[IMX7D_USB_PHY2_CLK] = imx_clk_gate4("usb_phy2_clk", "pll_usb_main_clk", base + 0x46b0, 0);
-       clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
-       clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
-       clks[IMX7D_CLK_ARM] = imx_clk_cpu("arm", "arm_a7_root_clk",
-                                        clks[IMX7D_ARM_A7_ROOT_CLK],
-                                        clks[IMX7D_ARM_A7_ROOT_SRC],
-                                        clks[IMX7D_PLL_ARM_MAIN_CLK],
-                                        clks[IMX7D_PLL_SYS_MAIN_CLK]);
-       imx_check_clocks(clks, ARRAY_SIZE(clks));
-       clk_data.clks = clks;
-       clk_data.clk_num = ARRAY_SIZE(clks);
-       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-       clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]);
-       clk_set_parent(clks[IMX7D_MIPI_CSI_ROOT_SRC], clks[IMX7D_PLL_SYS_PFD3_CLK]);
+       hws[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_hw_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
+       hws[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_hw_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
+       hws[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_hw_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
+       hws[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_hw_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
+       hws[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_hw_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
+       hws[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_hw_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel));
+       hws[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_hw_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel));
+       hws[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_hw_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel));
+       hws[IMX7D_DRAM_ROOT_SRC] = imx_clk_hw_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel));
+       hws[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_hw_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel));
+       hws[IMX7D_DRAM_ALT_ROOT_SRC]  = imx_clk_hw_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel));
+       hws[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_hw_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel));
+       hws[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_hw_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
+       hws[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_hw_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
+       hws[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_hw_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
+       hws[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_hw_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
+       hws[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_hw_mux2("mipi_dsi_src", base + 0xa380, 24, 3,  mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
+       hws[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_hw_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
+       hws[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_hw_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
+       hws[IMX7D_SAI1_ROOT_SRC] = imx_clk_hw_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel));
+       hws[IMX7D_SAI2_ROOT_SRC] = imx_clk_hw_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel));
+       hws[IMX7D_SAI3_ROOT_SRC] = imx_clk_hw_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel));
+       hws[IMX7D_SPDIF_ROOT_SRC] = imx_clk_hw_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel));
+       hws[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_hw_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel));
+       hws[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_hw_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel));
+       hws[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_hw_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel));
+       hws[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_hw_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel));
+       hws[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_hw_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel));
+       hws[IMX7D_EIM_ROOT_SRC] = imx_clk_hw_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel));
+       hws[IMX7D_NAND_ROOT_SRC] = imx_clk_hw_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel));
+       hws[IMX7D_QSPI_ROOT_SRC] = imx_clk_hw_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel));
+       hws[IMX7D_USDHC1_ROOT_SRC] = imx_clk_hw_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel));
+       hws[IMX7D_USDHC2_ROOT_SRC] = imx_clk_hw_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel));
+       hws[IMX7D_USDHC3_ROOT_SRC] = imx_clk_hw_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel));
+       hws[IMX7D_CAN1_ROOT_SRC] = imx_clk_hw_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel));
+       hws[IMX7D_CAN2_ROOT_SRC] = imx_clk_hw_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel));
+       hws[IMX7D_I2C1_ROOT_SRC] = imx_clk_hw_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel));
+       hws[IMX7D_I2C2_ROOT_SRC] = imx_clk_hw_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel));
+       hws[IMX7D_I2C3_ROOT_SRC] = imx_clk_hw_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel));
+       hws[IMX7D_I2C4_ROOT_SRC] = imx_clk_hw_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel));
+       hws[IMX7D_UART1_ROOT_SRC] = imx_clk_hw_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel));
+       hws[IMX7D_UART2_ROOT_SRC] = imx_clk_hw_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel));
+       hws[IMX7D_UART3_ROOT_SRC] = imx_clk_hw_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel));
+       hws[IMX7D_UART4_ROOT_SRC] = imx_clk_hw_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel));
+       hws[IMX7D_UART5_ROOT_SRC] = imx_clk_hw_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel));
+       hws[IMX7D_UART6_ROOT_SRC] = imx_clk_hw_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel));
+       hws[IMX7D_UART7_ROOT_SRC] = imx_clk_hw_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel));
+       hws[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_hw_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel));
+       hws[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_hw_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel));
+       hws[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_hw_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel));
+       hws[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_hw_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel));
+       hws[IMX7D_PWM1_ROOT_SRC] = imx_clk_hw_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel));
+       hws[IMX7D_PWM2_ROOT_SRC] = imx_clk_hw_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel));
+       hws[IMX7D_PWM3_ROOT_SRC] = imx_clk_hw_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel));
+       hws[IMX7D_PWM4_ROOT_SRC] = imx_clk_hw_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel));
+       hws[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_hw_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel));
+       hws[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_hw_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel));
+       hws[IMX7D_SIM1_ROOT_SRC] = imx_clk_hw_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel));
+       hws[IMX7D_SIM2_ROOT_SRC] = imx_clk_hw_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel));
+       hws[IMX7D_GPT1_ROOT_SRC] = imx_clk_hw_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel));
+       hws[IMX7D_GPT2_ROOT_SRC] = imx_clk_hw_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel));
+       hws[IMX7D_GPT3_ROOT_SRC] = imx_clk_hw_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel));
+       hws[IMX7D_GPT4_ROOT_SRC] = imx_clk_hw_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel));
+       hws[IMX7D_TRACE_ROOT_SRC] = imx_clk_hw_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel));
+       hws[IMX7D_WDOG_ROOT_SRC] = imx_clk_hw_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel));
+       hws[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_hw_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel));
+       hws[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_hw_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel));
+       hws[IMX7D_WRCLK_ROOT_SRC] = imx_clk_hw_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel));
+       hws[IMX7D_CLKO1_ROOT_SRC] = imx_clk_hw_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel));
+       hws[IMX7D_CLKO2_ROOT_SRC] = imx_clk_hw_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel));
+       hws[IMX7D_ARM_A7_ROOT_CG] = imx_clk_hw_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
+       hws[IMX7D_ARM_M4_ROOT_CG] = imx_clk_hw_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
+       hws[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_hw_gate3("axi_cg", "axi_src", base + 0x8800, 28);
+       hws[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_hw_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
+       hws[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_hw_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
+       hws[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_hw_gate3("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28);
+       hws[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_hw_gate3("ahb_cg", "ahb_src", base + 0x9000, 28);
+       hws[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_hw_gate3("dram_phym_cg", "dram_phym_src", base + 0x9800, 28);
+       hws[IMX7D_DRAM_ROOT_CG] = imx_clk_hw_gate3("dram_cg", "dram_src", base + 0x9880, 28);
+       hws[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_hw_gate3("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28);
+       hws[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_hw_gate3("dram_alt_cg", "dram_alt_src", base + 0xa080, 28);
+       hws[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_hw_gate3("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28);
+       hws[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_hw_gate3("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28);
+       hws[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_hw_gate3("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28);
+       hws[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_hw_gate3("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28);
+       hws[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_hw_gate3("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28);
+       hws[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_hw_gate3("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28);
+       hws[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_hw_gate3("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28);
+       hws[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_hw_gate3("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28);
+       hws[IMX7D_SAI1_ROOT_CG] = imx_clk_hw_gate3("sai1_cg", "sai1_src", base + 0xa500, 28);
+       hws[IMX7D_SAI2_ROOT_CG] = imx_clk_hw_gate3("sai2_cg", "sai2_src", base + 0xa580, 28);
+       hws[IMX7D_SAI3_ROOT_CG] = imx_clk_hw_gate3("sai3_cg", "sai3_src", base + 0xa600, 28);
+       hws[IMX7D_SPDIF_ROOT_CG] = imx_clk_hw_gate3("spdif_cg", "spdif_src", base + 0xa680, 28);
+       hws[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_hw_gate3("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28);
+       hws[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_hw_gate3("enet1_time_cg", "enet1_time_src", base + 0xa780, 28);
+       hws[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_hw_gate3("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28);
+       hws[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_hw_gate3("enet2_time_cg", "enet2_time_src", base + 0xa880, 28);
+       hws[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_hw_gate3("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28);
+       hws[IMX7D_EIM_ROOT_CG] = imx_clk_hw_gate3("eim_cg", "eim_src", base + 0xa980, 28);
+       hws[IMX7D_NAND_ROOT_CG] = imx_clk_hw_gate3("nand_cg", "nand_src", base + 0xaa00, 28);
+       hws[IMX7D_QSPI_ROOT_CG] = imx_clk_hw_gate3("qspi_cg", "qspi_src", base + 0xaa80, 28);
+       hws[IMX7D_USDHC1_ROOT_CG] = imx_clk_hw_gate3("usdhc1_cg", "usdhc1_src", base + 0xab00, 28);
+       hws[IMX7D_USDHC2_ROOT_CG] = imx_clk_hw_gate3("usdhc2_cg", "usdhc2_src", base + 0xab80, 28);
+       hws[IMX7D_USDHC3_ROOT_CG] = imx_clk_hw_gate3("usdhc3_cg", "usdhc3_src", base + 0xac00, 28);
+       hws[IMX7D_CAN1_ROOT_CG] = imx_clk_hw_gate3("can1_cg", "can1_src", base + 0xac80, 28);
+       hws[IMX7D_CAN2_ROOT_CG] = imx_clk_hw_gate3("can2_cg", "can2_src", base + 0xad00, 28);
+       hws[IMX7D_I2C1_ROOT_CG] = imx_clk_hw_gate3("i2c1_cg", "i2c1_src", base + 0xad80, 28);
+       hws[IMX7D_I2C2_ROOT_CG] = imx_clk_hw_gate3("i2c2_cg", "i2c2_src", base + 0xae00, 28);
+       hws[IMX7D_I2C3_ROOT_CG] = imx_clk_hw_gate3("i2c3_cg", "i2c3_src", base + 0xae80, 28);
+       hws[IMX7D_I2C4_ROOT_CG] = imx_clk_hw_gate3("i2c4_cg", "i2c4_src", base + 0xaf00, 28);
+       hws[IMX7D_UART1_ROOT_CG] = imx_clk_hw_gate3("uart1_cg", "uart1_src", base + 0xaf80, 28);
+       hws[IMX7D_UART2_ROOT_CG] = imx_clk_hw_gate3("uart2_cg", "uart2_src", base + 0xb000, 28);
+       hws[IMX7D_UART3_ROOT_CG] = imx_clk_hw_gate3("uart3_cg", "uart3_src", base + 0xb080, 28);
+       hws[IMX7D_UART4_ROOT_CG] = imx_clk_hw_gate3("uart4_cg", "uart4_src", base + 0xb100, 28);
+       hws[IMX7D_UART5_ROOT_CG] = imx_clk_hw_gate3("uart5_cg", "uart5_src", base + 0xb180, 28);
+       hws[IMX7D_UART6_ROOT_CG] = imx_clk_hw_gate3("uart6_cg", "uart6_src", base + 0xb200, 28);
+       hws[IMX7D_UART7_ROOT_CG] = imx_clk_hw_gate3("uart7_cg", "uart7_src", base + 0xb280, 28);
+       hws[IMX7D_ECSPI1_ROOT_CG] = imx_clk_hw_gate3("ecspi1_cg", "ecspi1_src", base + 0xb300, 28);
+       hws[IMX7D_ECSPI2_ROOT_CG] = imx_clk_hw_gate3("ecspi2_cg", "ecspi2_src", base + 0xb380, 28);
+       hws[IMX7D_ECSPI3_ROOT_CG] = imx_clk_hw_gate3("ecspi3_cg", "ecspi3_src", base + 0xb400, 28);
+       hws[IMX7D_ECSPI4_ROOT_CG] = imx_clk_hw_gate3("ecspi4_cg", "ecspi4_src", base + 0xb480, 28);
+       hws[IMX7D_PWM1_ROOT_CG] = imx_clk_hw_gate3("pwm1_cg", "pwm1_src", base + 0xb500, 28);
+       hws[IMX7D_PWM2_ROOT_CG] = imx_clk_hw_gate3("pwm2_cg", "pwm2_src", base + 0xb580, 28);
+       hws[IMX7D_PWM3_ROOT_CG] = imx_clk_hw_gate3("pwm3_cg", "pwm3_src", base + 0xb600, 28);
+       hws[IMX7D_PWM4_ROOT_CG] = imx_clk_hw_gate3("pwm4_cg", "pwm4_src", base + 0xb680, 28);
+       hws[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_hw_gate3("flextimer1_cg", "flextimer1_src", base + 0xb700, 28);
+       hws[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_hw_gate3("flextimer2_cg", "flextimer2_src", base + 0xb780, 28);
+       hws[IMX7D_SIM1_ROOT_CG] = imx_clk_hw_gate3("sim1_cg", "sim1_src", base + 0xb800, 28);
+       hws[IMX7D_SIM2_ROOT_CG] = imx_clk_hw_gate3("sim2_cg", "sim2_src", base + 0xb880, 28);
+       hws[IMX7D_GPT1_ROOT_CG] = imx_clk_hw_gate3("gpt1_cg", "gpt1_src", base + 0xb900, 28);
+       hws[IMX7D_GPT2_ROOT_CG] = imx_clk_hw_gate3("gpt2_cg", "gpt2_src", base + 0xb980, 28);
+       hws[IMX7D_GPT3_ROOT_CG] = imx_clk_hw_gate3("gpt3_cg", "gpt3_src", base + 0xbA00, 28);
+       hws[IMX7D_GPT4_ROOT_CG] = imx_clk_hw_gate3("gpt4_cg", "gpt4_src", base + 0xbA80, 28);
+       hws[IMX7D_TRACE_ROOT_CG] = imx_clk_hw_gate3("trace_cg", "trace_src", base + 0xbb00, 28);
+       hws[IMX7D_WDOG_ROOT_CG] = imx_clk_hw_gate3("wdog_cg", "wdog_src", base + 0xbb80, 28);
+       hws[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_hw_gate3("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28);
+       hws[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_hw_gate3("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28);
+       hws[IMX7D_WRCLK_ROOT_CG] = imx_clk_hw_gate3("wrclk_cg", "wrclk_src", base + 0xbd00, 28);
+       hws[IMX7D_CLKO1_ROOT_CG] = imx_clk_hw_gate3("clko1_cg", "clko1_src", base + 0xbd80, 28);
+       hws[IMX7D_CLKO2_ROOT_CG] = imx_clk_hw_gate3("clko2_cg", "clko2_src", base + 0xbe00, 28);
+       hws[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_hw_divider2("axi_pre_div", "axi_cg", base + 0x8800, 16, 3);
+       hws[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_hw_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3);
+       hws[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3);
+       hws[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_hw_divider2("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3);
+       hws[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_hw_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3);
+       hws[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_hw_divider2("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3);
+       hws[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_hw_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3);
+       hws[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_hw_divider2("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3);
+       hws[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_hw_divider2("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3);
+       hws[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_hw_divider2("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3);
+       hws[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_hw_divider2("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3);
+       hws[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_hw_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3);
+       hws[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_hw_divider2("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3);
+       hws[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_hw_divider2("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3);
+       hws[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_hw_divider2("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3);
+       hws[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_hw_divider2("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3);
+       hws[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_hw_divider2("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3);
+       hws[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_hw_divider2("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3);
+       hws[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_hw_divider2("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3);
+       hws[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3);
+       hws[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3);
+       hws[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3);
+       hws[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3);
+       hws[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_hw_divider2("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3);
+       hws[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_hw_divider2("eim_pre_div", "eim_cg", base + 0xa980, 16, 3);
+       hws[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_hw_divider2("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3);
+       hws[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_hw_divider2("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3);
+       hws[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_hw_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3);
+       hws[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_hw_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3);
+       hws[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_hw_divider2("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3);
+       hws[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_hw_divider2("can1_pre_div", "can1_cg", base + 0xac80, 16, 3);
+       hws[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_hw_divider2("can2_pre_div", "can2_cg", base + 0xad00, 16, 3);
+       hws[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_hw_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3);
+       hws[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_hw_divider2("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3);
+       hws[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_hw_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3);
+       hws[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_hw_divider2("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3);
+       hws[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3);
+       hws[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3);
+       hws[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3);
+       hws[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3);
+       hws[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3);
+       hws[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3);
+       hws[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_hw_divider2("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3);
+       hws[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_hw_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3);
+       hws[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_hw_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3);
+       hws[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_hw_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3);
+       hws[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_hw_divider2("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3);
+       hws[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_hw_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3);
+       hws[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_hw_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3);
+       hws[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_hw_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3);
+       hws[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_hw_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3);
+       hws[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_hw_divider2("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3);
+       hws[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_hw_divider2("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3);
+       hws[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_hw_divider2("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3);
+       hws[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_hw_divider2("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3);
+       hws[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_hw_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3);
+       hws[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_hw_divider2("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3);
+       hws[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_hw_divider2("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3);
+       hws[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_hw_divider2("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3);
+       hws[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_hw_divider2("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3);
+       hws[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_hw_divider2("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3);
+       hws[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_hw_divider2("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3);
+       hws[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_hw_divider2("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3);
+       hws[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_hw_divider2("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3);
+       hws[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_hw_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3);
+       hws[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_hw_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3);
+       hws[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_hw_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
+       hws[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_hw_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
+       hws[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_hw_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
+       hws[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_hw_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
+       hws[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_hw_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
+       hws[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_hw_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
+       hws[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_hw_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
+       hws[IMX7D_IPG_ROOT_CLK] = imx_clk_hw_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
+       hws[IMX7D_DRAM_ROOT_DIV] = imx_clk_hw_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
+       hws[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_hw_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
+       hws[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_hw_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
+       hws[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_hw_divider2("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6);
+       hws[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_hw_divider2("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6);
+       hws[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_hw_divider2("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6);
+       hws[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_hw_divider2("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6);
+       hws[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_hw_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6);
+       hws[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_hw_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6);
+       hws[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_hw_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6);
+       hws[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_hw_divider2("mipi_dphy_post_div", "mipi_dphy_pre_div", base + 0xa480, 0, 6);
+       hws[IMX7D_SAI1_ROOT_DIV] = imx_clk_hw_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6);
+       hws[IMX7D_SAI2_ROOT_DIV] = imx_clk_hw_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6);
+       hws[IMX7D_SAI3_ROOT_DIV] = imx_clk_hw_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6);
+       hws[IMX7D_SPDIF_ROOT_DIV] = imx_clk_hw_divider2("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6);
+       hws[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_hw_divider2("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6);
+       hws[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_hw_divider2("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6);
+       hws[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_hw_divider2("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6);
+       hws[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_hw_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6);
+       hws[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_hw_divider2("enet_phy_ref_root_clk", "enet_phy_ref_pre_div", base + 0xa900, 0, 6);
+       hws[IMX7D_EIM_ROOT_DIV] = imx_clk_hw_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6);
+       hws[IMX7D_NAND_ROOT_CLK] = imx_clk_hw_divider2("nand_root_clk", "nand_pre_div", base + 0xaa00, 0, 6);
+       hws[IMX7D_QSPI_ROOT_DIV] = imx_clk_hw_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6);
+       hws[IMX7D_USDHC1_ROOT_DIV] = imx_clk_hw_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6);
+       hws[IMX7D_USDHC2_ROOT_DIV] = imx_clk_hw_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6);
+       hws[IMX7D_USDHC3_ROOT_DIV] = imx_clk_hw_divider2("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6);
+       hws[IMX7D_CAN1_ROOT_DIV] = imx_clk_hw_divider2("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6);
+       hws[IMX7D_CAN2_ROOT_DIV] = imx_clk_hw_divider2("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6);
+       hws[IMX7D_I2C1_ROOT_DIV] = imx_clk_hw_divider2("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6);
+       hws[IMX7D_I2C2_ROOT_DIV] = imx_clk_hw_divider2("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6);
+       hws[IMX7D_I2C3_ROOT_DIV] = imx_clk_hw_divider2("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6);
+       hws[IMX7D_I2C4_ROOT_DIV] = imx_clk_hw_divider2("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6);
+       hws[IMX7D_UART1_ROOT_DIV] = imx_clk_hw_divider2("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6);
+       hws[IMX7D_UART2_ROOT_DIV] = imx_clk_hw_divider2("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6);
+       hws[IMX7D_UART3_ROOT_DIV] = imx_clk_hw_divider2("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6);
+       hws[IMX7D_UART4_ROOT_DIV] = imx_clk_hw_divider2("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6);
+       hws[IMX7D_UART5_ROOT_DIV] = imx_clk_hw_divider2("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6);
+       hws[IMX7D_UART6_ROOT_DIV] = imx_clk_hw_divider2("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6);
+       hws[IMX7D_UART7_ROOT_DIV] = imx_clk_hw_divider2("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6);
+       hws[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_hw_divider2("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6);
+       hws[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_hw_divider2("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6);
+       hws[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_hw_divider2("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6);
+       hws[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_hw_divider2("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6);
+       hws[IMX7D_PWM1_ROOT_DIV] = imx_clk_hw_divider2("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6);
+       hws[IMX7D_PWM2_ROOT_DIV] = imx_clk_hw_divider2("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6);
+       hws[IMX7D_PWM3_ROOT_DIV] = imx_clk_hw_divider2("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6);
+       hws[IMX7D_PWM4_ROOT_DIV] = imx_clk_hw_divider2("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6);
+       hws[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_hw_divider2("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6);
+       hws[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_hw_divider2("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6);
+       hws[IMX7D_SIM1_ROOT_DIV] = imx_clk_hw_divider2("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6);
+       hws[IMX7D_SIM2_ROOT_DIV] = imx_clk_hw_divider2("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6);
+       hws[IMX7D_GPT1_ROOT_DIV] = imx_clk_hw_divider2("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6);
+       hws[IMX7D_GPT2_ROOT_DIV] = imx_clk_hw_divider2("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6);
+       hws[IMX7D_GPT3_ROOT_DIV] = imx_clk_hw_divider2("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6);
+       hws[IMX7D_GPT4_ROOT_DIV] = imx_clk_hw_divider2("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6);
+       hws[IMX7D_TRACE_ROOT_DIV] = imx_clk_hw_divider2("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6);
+       hws[IMX7D_WDOG_ROOT_DIV] = imx_clk_hw_divider2("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6);
+       hws[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_hw_divider2("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6);
+       hws[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_hw_divider2("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6);
+       hws[IMX7D_WRCLK_ROOT_DIV] = imx_clk_hw_divider2("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6);
+       hws[IMX7D_CLKO1_ROOT_DIV] = imx_clk_hw_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
+       hws[IMX7D_CLKO2_ROOT_DIV] = imx_clk_hw_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
+       hws[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_hw_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_hw_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
+       hws[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_hw_gate2_flags("main_axi_root_clk", "axi_post_div", base + 0x4040, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_hw_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
+       hws[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_hw_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
+       hws[IMX7D_OCRAM_CLK] = imx_clk_hw_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
+       hws[IMX7D_OCRAM_S_CLK] = imx_clk_hw_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
+       hws[IMX7D_DRAM_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_root_clk", "dram_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
+       hws[IMX7D_OCOTP_CLK] = imx_clk_hw_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
+       hws[IMX7D_SNVS_CLK] = imx_clk_hw_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
+       hws[IMX7D_MU_ROOT_CLK] = imx_clk_hw_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
+       hws[IMX7D_CAAM_CLK] = imx_clk_hw_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
+       hws[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_hw_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4690, 0);
+       hws[IMX7D_SDMA_CORE_CLK] = imx_clk_hw_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0);
+       hws[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_hw_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
+       hws[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_hw_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
+       hws[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_hw_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0);
+       hws[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_hw_gate4("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0);
+       hws[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_hw_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0);
+       hws[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_hw_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0);
+       hws[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_hw_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0);
+       hws[IMX7D_ENET1_IPG_ROOT_CLK] = imx_clk_hw_gate2_shared2("enet1_ipg_root_clk", "enet_axi_post_div", base + 0x4700, 0, &share_count_enet1);
+       hws[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_hw_gate2_shared2("enet1_time_root_clk", "enet1_time_post_div", base + 0x4700, 0, &share_count_enet1);
+       hws[IMX7D_ENET2_IPG_ROOT_CLK] = imx_clk_hw_gate2_shared2("enet2_ipg_root_clk", "enet_axi_post_div", base + 0x4710, 0, &share_count_enet2);
+       hws[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_hw_gate2_shared2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4710, 0, &share_count_enet2);
+       hws[IMX7D_SAI1_ROOT_CLK] = imx_clk_hw_gate2_shared2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0, &share_count_sai1);
+       hws[IMX7D_SAI1_IPG_CLK]  = imx_clk_hw_gate2_shared2("sai1_ipg_clk",  "ipg_root_clk",  base + 0x48c0, 0, &share_count_sai1);
+       hws[IMX7D_SAI2_ROOT_CLK] = imx_clk_hw_gate2_shared2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0, &share_count_sai2);
+       hws[IMX7D_SAI2_IPG_CLK]  = imx_clk_hw_gate2_shared2("sai2_ipg_clk",  "ipg_root_clk",  base + 0x48d0, 0, &share_count_sai2);
+       hws[IMX7D_SAI3_ROOT_CLK] = imx_clk_hw_gate2_shared2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0, &share_count_sai3);
+       hws[IMX7D_SAI3_IPG_CLK]  = imx_clk_hw_gate2_shared2("sai3_ipg_clk",  "ipg_root_clk",  base + 0x48e0, 0, &share_count_sai3);
+       hws[IMX7D_SPDIF_ROOT_CLK] = imx_clk_hw_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0);
+       hws[IMX7D_EIM_ROOT_CLK] = imx_clk_hw_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0);
+       hws[IMX7D_NAND_RAWNAND_CLK] = imx_clk_hw_gate2_shared2("nand_rawnand_clk", "nand_root_clk", base + 0x4140, 0, &share_count_nand);
+       hws[IMX7D_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_hw_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_root_clk", base + 0x4140, 0, &share_count_nand);
+       hws[IMX7D_QSPI_ROOT_CLK] = imx_clk_hw_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
+       hws[IMX7D_USDHC1_ROOT_CLK] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
+       hws[IMX7D_USDHC2_ROOT_CLK] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
+       hws[IMX7D_USDHC3_ROOT_CLK] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0);
+       hws[IMX7D_CAN1_ROOT_CLK] = imx_clk_hw_gate4("can1_root_clk", "can1_post_div", base + 0x4740, 0);
+       hws[IMX7D_CAN2_ROOT_CLK] = imx_clk_hw_gate4("can2_root_clk", "can2_post_div", base + 0x4750, 0);
+       hws[IMX7D_I2C1_ROOT_CLK] = imx_clk_hw_gate4("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0);
+       hws[IMX7D_I2C2_ROOT_CLK] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0);
+       hws[IMX7D_I2C3_ROOT_CLK] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0);
+       hws[IMX7D_I2C4_ROOT_CLK] = imx_clk_hw_gate4("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0);
+       hws[IMX7D_UART1_ROOT_CLK] = imx_clk_hw_gate4("uart1_root_clk", "uart1_post_div", base + 0x4940, 0);
+       hws[IMX7D_UART2_ROOT_CLK] = imx_clk_hw_gate4("uart2_root_clk", "uart2_post_div", base + 0x4950, 0);
+       hws[IMX7D_UART3_ROOT_CLK] = imx_clk_hw_gate4("uart3_root_clk", "uart3_post_div", base + 0x4960, 0);
+       hws[IMX7D_UART4_ROOT_CLK] = imx_clk_hw_gate4("uart4_root_clk", "uart4_post_div", base + 0x4970, 0);
+       hws[IMX7D_UART5_ROOT_CLK] = imx_clk_hw_gate4("uart5_root_clk", "uart5_post_div", base + 0x4980, 0);
+       hws[IMX7D_UART6_ROOT_CLK] = imx_clk_hw_gate4("uart6_root_clk", "uart6_post_div", base + 0x4990, 0);
+       hws[IMX7D_UART7_ROOT_CLK] = imx_clk_hw_gate4("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0);
+       hws[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_hw_gate4("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0);
+       hws[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_hw_gate4("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0);
+       hws[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_hw_gate4("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0);
+       hws[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_hw_gate4("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0);
+       hws[IMX7D_PWM1_ROOT_CLK] = imx_clk_hw_gate4("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0);
+       hws[IMX7D_PWM2_ROOT_CLK] = imx_clk_hw_gate4("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0);
+       hws[IMX7D_PWM3_ROOT_CLK] = imx_clk_hw_gate4("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0);
+       hws[IMX7D_PWM4_ROOT_CLK] = imx_clk_hw_gate4("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0);
+       hws[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_hw_gate4("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0);
+       hws[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_hw_gate4("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0);
+       hws[IMX7D_SIM1_ROOT_CLK] = imx_clk_hw_gate4("sim1_root_clk", "sim1_post_div", base + 0x4900, 0);
+       hws[IMX7D_SIM2_ROOT_CLK] = imx_clk_hw_gate4("sim2_root_clk", "sim2_post_div", base + 0x4910, 0);
+       hws[IMX7D_GPT1_ROOT_CLK] = imx_clk_hw_gate4("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0);
+       hws[IMX7D_GPT2_ROOT_CLK] = imx_clk_hw_gate4("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0);
+       hws[IMX7D_GPT3_ROOT_CLK] = imx_clk_hw_gate4("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0);
+       hws[IMX7D_GPT4_ROOT_CLK] = imx_clk_hw_gate4("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0);
+       hws[IMX7D_TRACE_ROOT_CLK] = imx_clk_hw_gate4("trace_root_clk", "trace_post_div", base + 0x4300, 0);
+       hws[IMX7D_WDOG1_ROOT_CLK] = imx_clk_hw_gate4("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0);
+       hws[IMX7D_WDOG2_ROOT_CLK] = imx_clk_hw_gate4("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0);
+       hws[IMX7D_WDOG3_ROOT_CLK] = imx_clk_hw_gate4("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0);
+       hws[IMX7D_WDOG4_ROOT_CLK] = imx_clk_hw_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
+       hws[IMX7D_KPP_ROOT_CLK] = imx_clk_hw_gate4("kpp_root_clk", "ipg_root_clk", base + 0x4aa0, 0);
+       hws[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_hw_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
+       hws[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_hw_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
+       hws[IMX7D_WRCLK_ROOT_CLK] = imx_clk_hw_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+       hws[IMX7D_USB_CTRL_CLK] = imx_clk_hw_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
+       hws[IMX7D_USB_PHY1_CLK] = imx_clk_hw_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
+       hws[IMX7D_USB_PHY2_CLK] = imx_clk_hw_gate4("usb_phy2_clk", "pll_usb_main_clk", base + 0x46b0, 0);
+       hws[IMX7D_ADC_ROOT_CLK] = imx_clk_hw_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
+       hws[IMX7D_GPT_3M_CLK] = imx_clk_hw_fixed_factor("gpt_3m", "osc", 1, 8);
+       hws[IMX7D_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a7_root_clk",
+                                        hws[IMX7D_ARM_A7_ROOT_CLK]->clk,
+                                        hws[IMX7D_ARM_A7_ROOT_SRC]->clk,
+                                        hws[IMX7D_PLL_ARM_MAIN_CLK]->clk,
+                                        hws[IMX7D_PLL_SYS_MAIN_CLK]->clk);
+       imx_check_clk_hws(hws, IMX7D_CLK_END);
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
+       clk_set_parent(hws[IMX7D_PLL_ARM_MAIN_BYPASS]->clk, hws[IMX7D_PLL_ARM_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_PLL_DRAM_MAIN_BYPASS]->clk, hws[IMX7D_PLL_DRAM_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_PLL_SYS_MAIN_BYPASS]->clk, hws[IMX7D_PLL_SYS_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_PLL_ENET_MAIN_BYPASS]->clk, hws[IMX7D_PLL_ENET_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_PLL_AUDIO_MAIN_BYPASS]->clk, hws[IMX7D_PLL_AUDIO_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_PLL_VIDEO_MAIN_BYPASS]->clk, hws[IMX7D_PLL_VIDEO_MAIN]->clk);
+       clk_set_parent(hws[IMX7D_MIPI_CSI_ROOT_SRC]->clk, hws[IMX7D_PLL_SYS_PFD3_CLK]->clk);
  
        /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */
-       clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
+       clk_set_parent(hws[IMX7D_GPT1_ROOT_SRC]->clk, hws[IMX7D_OSC_24M_CLK]->clk);
  
        /* Set clock rate for USBPHY, the USB_PLL at CCM is from USBOTG2 */
-       clks[IMX7D_USB1_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb1_main_clk", "osc", 20, 1);
-       clks[IMX7D_USB_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb_main_clk", "osc", 20, 1);
+       hws[IMX7D_USB1_MAIN_480M_CLK] = imx_clk_hw_fixed_factor("pll_usb1_main_clk", "osc", 20, 1);
+       hws[IMX7D_USB_MAIN_480M_CLK] = imx_clk_hw_fixed_factor("pll_usb_main_clk", "osc", 20, 1);
+       for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) {
+               int index = uart_clk_ids[i];
+               uart_clks[i] = &hws[index]->clk;
+       }
  
        imx_register_uart_clocks(uart_clks);
  
index 122a81ab8e48c749b50446946d9bb812e30c2ced,3a873e0e278f83852b73e7ea8c6309b5c7d236b2..6b8e75df994d387d47af89d7d19449aef72a0a16
@@@ -288,6 -288,9 +288,9 @@@ static const char *imx8mm_usb_core_sels
  static const char *imx8mm_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", "sys_pll2_100m",
                                             "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
  
+ static const char *imx8mm_gic_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll2_100m",
+                                       "sys_pll1_800m", "clk_ext2", "clk_ext4", "audio_pll2_out" };
  static const char *imx8mm_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
                                           "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
  
@@@ -325,7 -328,7 +328,7 @@@ static const char *imx8mm_dsi_dbi_sels[
                                            "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
  
  static const char *imx8mm_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
-                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
+                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
  
  static const char *imx8mm_csi1_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
                                              "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
@@@ -361,11 -364,11 +364,11 @@@ static const char *imx8mm_pdm_sels[] = 
                                        "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
  
  static const char *imx8mm_vpu_h1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
-                                          "audio_pll2_clk", "sys_pll2_125m", "sys_pll3_clk", "audio_pll1_out", };
+                                          "audio_pll2_out", "sys_pll2_125m", "sys_pll3_clk", "audio_pll1_out", };
  
  static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
  
- static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", "sys_pll1_200m", "audio_pll2_clk",
+ static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", "sys_pll1_200m", "audio_pll2_out",
                                         "vpu_pll", "sys_pll1_80m", };
  
  static struct clk *clks[IMX8MM_CLK_END];
@@@ -449,12 -452,12 +452,12 @@@ static int __init imx8mm_clocks_init(st
        clks[IMX8MM_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
        clks[IMX8MM_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
        clks[IMX8MM_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
 -      clks[IMX8MM_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13);
 -      clks[IMX8MM_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13);
 -      clks[IMX8MM_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13);
 -      clks[IMX8MM_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13);
 -      clks[IMX8MM_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13);
 -      clks[IMX8MM_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13);
 +      clks[IMX8MM_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
 +      clks[IMX8MM_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11);
 +      clks[IMX8MM_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11);
 +      clks[IMX8MM_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 11);
 +      clks[IMX8MM_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 11);
 +      clks[IMX8MM_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
  
        /* SYS PLL fixed output */
        clks[IMX8MM_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
  
        /* IP */
        clks[IMX8MM_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000);
-       clks[IMX8MM_CLK_DRAM_APB] = imx8m_clk_composite("dram_apb", imx8mm_dram_apb_sels, base + 0xa080);
+       clks[IMX8MM_CLK_DRAM_APB] = imx8m_clk_composite_critical("dram_apb", imx8mm_dram_apb_sels, base + 0xa080);
        clks[IMX8MM_CLK_VPU_G1] = imx8m_clk_composite("vpu_g1", imx8mm_vpu_g1_sels, base + 0xa100);
        clks[IMX8MM_CLK_VPU_G2] = imx8m_clk_composite("vpu_g2", imx8mm_vpu_g2_sels, base + 0xa180);
        clks[IMX8MM_CLK_DISP_DTRC] = imx8m_clk_composite("disp_dtrc", imx8mm_disp_dtrc_sels, base + 0xa200);
        clks[IMX8MM_CLK_UART4] = imx8m_clk_composite("uart4", imx8mm_uart4_sels, base + 0xb080);
        clks[IMX8MM_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mm_usb_core_sels, base + 0xb100);
        clks[IMX8MM_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mm_usb_phy_sels, base + 0xb180);
+       clks[IMX8MM_CLK_GIC] = imx8m_clk_composite_critical("gic", imx8mm_gic_sels, base + 0xb200);
        clks[IMX8MM_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mm_ecspi1_sels, base + 0xb280);
        clks[IMX8MM_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mm_ecspi2_sels, base + 0xb300);
        clks[IMX8MM_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mm_pwm1_sels, base + 0xb380);
        clks[IMX8MM_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
        clks[IMX8MM_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
        clks[IMX8MM_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+       clks[IMX8MM_CLK_GPIO1_ROOT] = imx_clk_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0);
+       clks[IMX8MM_CLK_GPIO2_ROOT] = imx_clk_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0);
+       clks[IMX8MM_CLK_GPIO3_ROOT] = imx_clk_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0);
+       clks[IMX8MM_CLK_GPIO4_ROOT] = imx_clk_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0);
+       clks[IMX8MM_CLK_GPIO5_ROOT] = imx_clk_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0);
        clks[IMX8MM_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0);
        clks[IMX8MM_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
        clks[IMX8MM_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
        clks[IMX8MM_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5);
        clks[IMX8MM_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6);
        clks[IMX8MM_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6);
+       clks[IMX8MM_CLK_SNVS_ROOT] = imx_clk_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0);
        clks[IMX8MM_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
        clks[IMX8MM_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
        clks[IMX8MM_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
index fa82ddea4996d740f4fd7bcda6255232ec1feb26,3b43d2990fe942be992a44316857a8dd901b2bbf..50b7c30296f7354009fbcc06aaa43c55771bdf00
@@@ -1,7 -1,13 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2012 Freescale Semiconductor, Inc.
   * Copyright 2012 Linaro Ltd.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk-provider.h>
@@@ -121,12 -127,13 +121,13 @@@ static const struct clk_ops clk_pfd_op
        .is_enabled     = clk_pfd_is_enabled,
  };
  
- struct clk *imx_clk_pfd(const char *name, const char *parent_name,
+ struct clk_hw *imx_clk_hw_pfd(const char *name, const char *parent_name,
                        void __iomem *reg, u8 idx)
  {
        struct clk_pfd *pfd;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        pfd = kzalloc(sizeof(*pfd), GFP_KERNEL);
        if (!pfd)
        init.num_parents = 1;
  
        pfd->hw.init = &init;
+       hw = &pfd->hw;
  
-       clk = clk_register(NULL, &pfd->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(pfd);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index 93b059608d3c64717b2121b049e1a626539ba13e,23aebca06c80a7eb26ca0b02014c06a9bd084780..df91a8244fb4d97d581bbdd470550d476b4327b6
@@@ -1,7 -1,13 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2012 Freescale Semiconductor, Inc.
   * Copyright 2012 Linaro Ltd.
 - *
 - * The code contained herein is licensed under the GNU General Public
 - * License. You may obtain a copy of the GNU General Public License
 - * Version 2 or later at the following locations:
 - *
 - * http://www.opensource.org/licenses/gpl-license.html
 - * http://www.gnu.org/copyleft/gpl.html
   */
  
  #include <linux/clk-provider.h>
@@@ -410,14 -416,15 +410,15 @@@ static const struct clk_ops clk_pllv3_e
        .recalc_rate    = clk_pllv3_enet_recalc_rate,
  };
  
- struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
+ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name,
                          const char *parent_name, void __iomem *base,
                          u32 div_mask)
  {
        struct clk_pllv3 *pll;
        const struct clk_ops *ops;
-       struct clk *clk;
+       struct clk_hw *hw;
        struct clk_init_data init;
+       int ret;
  
        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
        if (!pll)
        init.num_parents = 1;
  
        pll->hw.init = &init;
+       hw = &pll->hw;
  
-       clk = clk_register(NULL, &pll->hw);
-       if (IS_ERR(clk))
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
                kfree(pll);
+               return ERR_PTR(ret);
+       }
  
-       return clk;
+       return hw;
  }
index ab58a6a862a50b9ac4b2ced6964b38de9b4231cc,589a2b772b0d5fb9940b98a4d9a232931f61a616..250570a809d3cfa4cf1362a57d04655b17e0a8ea
@@@ -1,5 -1,4 +1,5 @@@
- obj-$(CONFIG_INGENIC_CGU_COMMON)      += cgu.o
 +# SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_INGENIC_CGU_COMMON)      += cgu.o pm.o
  obj-$(CONFIG_INGENIC_CGU_JZ4740)      += jz4740-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4725B)     += jz4725b-cgu.o
  obj-$(CONFIG_INGENIC_CGU_JZ4770)      += jz4770-cgu.o
index 92c3314275136b5acca9417f64aa2ae696a6f80e,c8150cbd0894bc8903d743007a1cf4db8e2fd51f..6e963031cd8733cba159ee102a38c50789d851c1
@@@ -1,9 -1,18 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Ingenic SoC CGU driver
   *
   * Copyright (c) 2013-2015 Imagination Technologies
   * Author: Paul Burton <paul.burton@mips.com>
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU General Public License as
 - * published by the Free Software Foundation; either version 2 of
 - * the License, or (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/bitops.h>
@@@ -375,8 -384,11 +375,11 @@@ ingenic_clk_recalc_rate(struct clk_hw *
                div_reg = readl(cgu->base + clk_info->div.reg);
                div = (div_reg >> clk_info->div.shift) &
                      GENMASK(clk_info->div.bits - 1, 0);
-               div += 1;
-               div *= clk_info->div.div;
+               if (clk_info->div.div_table)
+                       div = clk_info->div.div_table[div];
+               else
+                       div = (div + 1) * clk_info->div.div;
  
                rate /= div;
        } else if (clk_info->type & CGU_CLK_FIXDIV) {
        return rate;
  }
  
+ static unsigned int
+ ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,
+                       unsigned int div)
+ {
+       unsigned int i;
+       for (i = 0; i < (1 << clk_info->div.bits)
+                               && clk_info->div.div_table[i]; i++) {
+               if (clk_info->div.div_table[i] >= div)
+                       return i;
+       }
+       return i - 1;
+ }
  static unsigned
  ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
                     unsigned long parent_rate, unsigned long req_rate)
  {
-       unsigned div;
+       unsigned int div, hw_div;
  
        /* calculate the divide */
        div = DIV_ROUND_UP(parent_rate, req_rate);
  
-       /* and impose hardware constraints */
+       if (clk_info->div.div_table) {
+               hw_div = ingenic_clk_calc_hw_div(clk_info, div);
+               return clk_info->div.div_table[hw_div];
+       }
+       /* Impose hardware constraints */
        div = min_t(unsigned, div, 1 << clk_info->div.bits);
        div = max_t(unsigned, div, 1);
  
@@@ -438,7 -471,7 +462,7 @@@ ingenic_clk_set_rate(struct clk_hw *hw
        const struct ingenic_cgu_clk_info *clk_info;
        const unsigned timeout = 100;
        unsigned long rate, flags;
-       unsigned div, i;
+       unsigned int hw_div, div, i;
        u32 reg, mask;
        int ret = 0;
  
                if (rate != req_rate)
                        return -EINVAL;
  
+               if (clk_info->div.div_table)
+                       hw_div = ingenic_clk_calc_hw_div(clk_info, div);
+               else
+                       hw_div = ((div / clk_info->div.div) - 1);
                spin_lock_irqsave(&cgu->lock, flags);
                reg = readl(cgu->base + clk_info->div.reg);
  
                /* update the divide */
                mask = GENMASK(clk_info->div.bits - 1, 0);
                reg &= ~(mask << clk_info->div.shift);
-               reg |= ((div / clk_info->div.div) - 1) << clk_info->div.shift;
+               reg |= hw_div << clk_info->div.shift;
  
                /* clear the stop bit */
                if (clk_info->div.stop_bit != -1)
index bfbcf6db437d7de0bfe1e91d61e4d7f86ad4bd88,377eb921f598904e330557e31bf705ac2dcf766b..0dc8004079ee24426cc855da459763d0c23d2693
@@@ -1,15 -1,25 +1,16 @@@
 +/* SPDX-License-Identifier: GPL-2.0-or-later */
  /*
   * Ingenic SoC CGU driver
   *
   * Copyright (c) 2013-2015 Imagination Technologies
   * Author: Paul Burton <paul.burton@mips.com>
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU General Public License as
 - * published by the Free Software Foundation; either version 2 of
 - * the License, or (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #ifndef __DRIVERS_CLK_INGENIC_CGU_H__
  #define __DRIVERS_CLK_INGENIC_CGU_H__
  
  #include <linux/bitops.h>
+ #include <linux/clk-provider.h>
  #include <linux/of.h>
  #include <linux/spinlock.h>
  
@@@ -79,6 -89,8 +80,8 @@@ struct ingenic_cgu_mux_info 
   *          isn't one
   * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one
   * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one
+  * @div_table: optional table to map the value read from the register to the
+  *             actual divider value
   */
  struct ingenic_cgu_div_info {
        unsigned reg;
        s8 ce_bit;
        s8 busy_bit;
        s8 stop_bit;
+       const u8 *div_table;
  };
  
  /**
index c77f4e1506dc07284a8f0f7d610668096494c2ff,cb22d0633b9c3e961f036e28d6528da880b0b9cf..4c0a20949c2c2785978b6b4d04f990b661c861c2
@@@ -1,9 -1,18 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Ingenic JZ4740 SoC CGU driver
   *
   * Copyright (c) 2015 Imagination Technologies
   * Author: Paul Burton <paul.burton@mips.com>
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU General Public License as
 - * published by the Free Software Foundation; either version 2 of
 - * the License, or (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -11,8 -20,8 +11,8 @@@
  #include <linux/io.h>
  #include <linux/of.h>
  #include <dt-bindings/clock/jz4740-cgu.h>
- #include <asm/mach-jz4740/clock.h>
  #include "cgu.h"
+ #include "pm.h"
  
  /* CGU register offsets */
  #define CGU_REG_CPCCR         0x00
@@@ -49,6 -58,10 +49,10 @@@ static const s8 pll_od_encoding[4] = 
        0x0, 0x1, -1, 0x3,
  };
  
+ static const u8 jz4740_cgu_cpccr_div_table[] = {
+       1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
+ };
  static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
  
        /* External clocks */
        [JZ4740_CLK_CCLK] = {
                "cclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-               .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+               .div = {
+                       CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
+                       jz4740_cgu_cpccr_div_table,
+               },
        },
  
        [JZ4740_CLK_HCLK] = {
                "hclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-               .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+               .div = {
+                       CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
+                       jz4740_cgu_cpccr_div_table,
+               },
        },
  
        [JZ4740_CLK_PCLK] = {
                "pclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-               .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
+               .div = {
+                       CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
+                       jz4740_cgu_cpccr_div_table,
+               },
        },
  
        [JZ4740_CLK_MCLK] = {
                "mclk", CGU_CLK_DIV,
                .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-               .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
+               .div = {
+                       CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
+                       jz4740_cgu_cpccr_div_table,
+               },
        },
  
        [JZ4740_CLK_LCD] = {
                "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
                .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
-               .div = { CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1 },
+               .div = {
+                       CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1,
+                       jz4740_cgu_cpccr_div_table,
+               },
                .gate = { CGU_REG_CLKGR, 10 },
        },
  
@@@ -219,77 -247,7 +238,7 @@@ static void __init jz4740_cgu_init(stru
        retval = ingenic_cgu_register_clocks(cgu);
        if (retval)
                pr_err("%s: failed to register CGU Clocks\n", __func__);
- }
- CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
- void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
- {
-       uint32_t lcr = readl(cgu->base + CGU_REG_LCR);
-       switch (mode) {
-       case JZ4740_WAIT_MODE_IDLE:
-               lcr &= ~LCR_SLEEP;
-               break;
-       case JZ4740_WAIT_MODE_SLEEP:
-               lcr |= LCR_SLEEP;
-               break;
-       }
-       writel(lcr, cgu->base + CGU_REG_LCR);
- }
  
- void jz4740_clock_udc_disable_auto_suspend(void)
- {
-       uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
-       clkgr &= ~CLKGR_UDC;
-       writel(clkgr, cgu->base + CGU_REG_CLKGR);
- }
- EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
- void jz4740_clock_udc_enable_auto_suspend(void)
- {
-       uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
-       clkgr |= CLKGR_UDC;
-       writel(clkgr, cgu->base + CGU_REG_CLKGR);
- }
- EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
- #define JZ_CLOCK_GATE_UART0   BIT(0)
- #define JZ_CLOCK_GATE_TCU     BIT(1)
- #define JZ_CLOCK_GATE_DMAC    BIT(12)
- void jz4740_clock_suspend(void)
- {
-       uint32_t clkgr, cppcr;
-       clkgr = readl(cgu->base + CGU_REG_CLKGR);
-       clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0;
-       writel(clkgr, cgu->base + CGU_REG_CLKGR);
-       cppcr = readl(cgu->base + CGU_REG_CPPCR);
-       cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
-       writel(cppcr, cgu->base + CGU_REG_CPPCR);
- }
- void jz4740_clock_resume(void)
- {
-       uint32_t clkgr, cppcr, stable;
-       cppcr = readl(cgu->base + CGU_REG_CPPCR);
-       cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
-       writel(cppcr, cgu->base + CGU_REG_CPPCR);
-       stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit);
-       do {
-               cppcr = readl(cgu->base + CGU_REG_CPPCR);
-       } while (!(cppcr & stable));
-       clkgr = readl(cgu->base + CGU_REG_CLKGR);
-       clkgr &= ~JZ_CLOCK_GATE_TCU;
-       clkgr &= ~JZ_CLOCK_GATE_DMAC;
-       clkgr &= ~JZ_CLOCK_GATE_UART0;
-       writel(clkgr, cgu->base + CGU_REG_CLKGR);
+       ingenic_cgu_register_syscore_ops(cgu);
  }
+ CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
index 2464fc4032aff80bb3e398352f8732d6c40e5bb1,4cfcef98accc8de46bb5fe6b0a6c2c54c4684ac1..8c67f89df25e54909fa5ed3443aeb804416e4022
@@@ -1,9 -1,18 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Ingenic JZ4780 SoC CGU driver
   *
   * Copyright (c) 2013-2015 Imagination Technologies
   * Author: Paul Burton <paul.burton@mips.com>
 - *
 - * This program is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU General Public License as
 - * published by the Free Software Foundation; either version 2 of
 - * the License, or (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -12,6 -21,7 +12,7 @@@
  #include <linux/of.h>
  #include <dt-bindings/clock/jz4780-cgu.h>
  #include "cgu.h"
+ #include "pm.h"
  
  /* CGU register offsets */
  #define CGU_REG_CLOCKCONTROL  0x00
@@@ -721,5 -731,7 +722,7 @@@ static void __init jz4780_cgu_init(stru
                pr_err("%s: failed to register CGU Clocks\n", __func__);
                return;
        }
+       ingenic_cgu_register_syscore_ops(cgu);
  }
  CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
index 0ca63014718a218d8cacb0598c8c436dfe77d0b3,aaaee7d1c126b1544542e000a404720c88932594..38aeefb1e80808281d3d5110cd563c8ded9f94df
@@@ -1,4 -1,3 +1,4 @@@
 +# SPDX-License-Identifier: GPL-2.0-only
  config COMMON_CLK_KEYSTONE
        tristate "Clock drivers for Keystone based SOCs"
        depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
@@@ -15,3 -14,14 +15,14 @@@ config TI_SCI_CL
          This adds the clock driver support over TI System Control Interface.
          If you wish to use clock resources from the PMMC firmware, say Y.
          Otherwise, say N.
+ config TI_SCI_CLK_PROBE_FROM_FW
+       bool "Probe available clocks from firmware"
+       depends on TI_SCI_CLK
+       default n
+       help
+         Forces the TI SCI clock driver to probe available clocks from the
+         firmware. By default, only the used clocks are probed from DT.
+         This is mostly only useful for debugging purposes, and will
+         increase the boot time of the device. If you want the clocks probed
+         from firmware, say Y. Otherwise, say N.
index f797f09c6425f99ca8bf2f9b108c32a9b8182434,77b9847fa61f68b59553f3ec58738985f33caaaa..ce3d9b300bab57d4855601972a696cd8c17e4fab
@@@ -1,4 -1,3 +1,4 @@@
 +# SPDX-License-Identifier: GPL-2.0-only
  #
  # MediaTek Clock Drivers
  #
@@@ -300,4 -299,10 +300,10 @@@ config COMMON_CLK_MT851
        help
          This driver supports MediaTek MT8516 clocks.
  
+ config COMMON_CLK_MT8516_AUDSYS
+       bool "Clock driver for MediaTek MT8516 audsys"
+       depends on COMMON_CLK_MT8516
+       help
+         This driver supports MediaTek MT8516 audsys clocks.
  endmenu
index d2f39a972cadc6d459d2fbf626419c33c63fef67,292d7214a226c418c6b267ae14059a6461f48898..d004cdaa0e39a32b8074a0d0e6af18feb23c773e
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/kernel.h>
@@@ -130,22 -138,6 +130,6 @@@ static const char * const gcc_xo_gpll0_
        "gpll0_early_div"
  };
  
- static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div_map[] = {
-       { P_XO, 0 },
-       { P_GPLL0, 1 },
-       { P_GPLL2, 2 },
-       { P_GPLL3, 3 },
-       { P_GPLL0_EARLY_DIV, 6 }
- };
- static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div[] = {
-       "xo",
-       "gpll0",
-       "gpll2",
-       "gpll3",
-       "gpll0_early_div"
- };
  static const struct parent_map gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map[] = {
        { P_XO, 0 },
        { P_GPLL0, 1 },
@@@ -184,26 -176,6 +168,6 @@@ static const char * const gcc_xo_gpll0_
        "gpll0_early_div"
  };
  
- static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div_map[] = {
-       { P_XO, 0 },
-       { P_GPLL0, 1 },
-       { P_GPLL2, 2 },
-       { P_GPLL3, 3 },
-       { P_GPLL1, 4 },
-       { P_GPLL4, 5 },
-       { P_GPLL0_EARLY_DIV, 6 }
- };
- static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div[] = {
-       "xo",
-       "gpll0",
-       "gpll2",
-       "gpll3",
-       "gpll1",
-       "gpll4",
-       "gpll0_early_div"
- };
  static struct clk_fixed_factor xo = {
        .mult = 1,
        .div = 1,
diff --combined drivers/clk/qcom/gdsc.c
index 679bc7d8950ae4a52208ba863ce81e2b5031f528,6a8a4996dde3baee5814d5223f8da0470a02ce2c..a250f59708d85fc4dcc5ce8f6fc3bbdbf3d28f49
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 and
 - * only version 2 as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/bitops.h>
@@@ -141,7 -149,9 +141,9 @@@ static int gdsc_toggle_logic(struct gds
                udelay(1);
        }
  
-       return gdsc_poll_status(sc, status);
+       ret = gdsc_poll_status(sc, status);
+       WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");
+       return ret;
  }
  
  static inline int gdsc_deassert_reset(struct gdsc *sc)
index c61f4d3e52e252535ac47d53ed31b15a0d308a79,baa73285b953da385d419ecb3649acd9a4e9ff4f..4abe7ff31f535f282127d4ead002e09c8d9751ef
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2014 Google, Inc
   * Author: Alexandru M Stan <amstan@chromium.org>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/slab.h>
@@@ -46,29 -55,27 +46,27 @@@ static unsigned long rockchip_mmc_recal
  static int rockchip_mmc_get_phase(struct clk_hw *hw)
  {
        struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
-       unsigned long rate = clk_get_rate(hw->clk);
+       unsigned long rate = clk_hw_get_rate(hw);
        u32 raw_value;
        u16 degrees;
        u32 delay_num = 0;
  
        /* See the comment for rockchip_mmc_set_phase below */
-       if (!rate) {
-               pr_err("%s: invalid clk rate\n", __func__);
+       if (!rate)
                return -EINVAL;
-       }
  
        raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
  
        degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
  
        if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
-               /* degrees/delaynum * 10000 */
+               /* degrees/delaynum * 1000000 */
                unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
-                                       36 * (rate / 1000000);
+                                       36 * (rate / 10000);
  
                delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
                delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
-               degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
+               degrees += DIV_ROUND_CLOSEST(delay_num * factor, 1000000);
        }
  
        return degrees % 360;
@@@ -77,7 -84,7 +75,7 @@@
  static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
  {
        struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
-       unsigned long rate = clk_get_rate(hw->clk);
+       unsigned long rate = clk_hw_get_rate(hw);
        u8 nineties, remainder;
        u8 delay_num;
        u32 raw_value;
index bb39a799bdb537d183262e9b601e4d624db35e79,e92b64d37fb86b1d4ef1f3bd2a1128453b87c1bb..3a501896b28033825bf629b4c91178d85dabe994
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
   * Author: Elaine Zhang<zhangqing@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -794,6 -803,9 +794,9 @@@ static struct rockchip_clk_branch px30_
        GATE(ACLK_GIC, "aclk_gic", "aclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 12, GFLAGS),
        GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_pre", 0, PX30_CLKGATE_CON(13), 15, GFLAGS),
  
+       /* aclk_dmac is controlled by sgrf_soc_con1[11]. */
+       SGRF_GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre"),
        GATE(0, "hclk_bus_niu", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 9, GFLAGS),
        GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, PX30_CLKGATE_CON(13), 14, GFLAGS),
        GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_pre", 0, PX30_CLKGATE_CON(14), 1, GFLAGS),
@@@ -957,7 -969,6 +960,6 @@@ static void __init px30_clk_init(struc
  {
        struct rockchip_clk_provider *ctx;
        void __iomem *reg_base;
-       struct clk *clk;
  
        reg_base = of_iomap(np, 0);
        if (!reg_base) {
                return;
        }
  
-       /* aclk_dmac is controlled by sgrf_soc_con1[11]. */
-       clk = clk_register_fixed_factor(NULL, "aclk_dmac", "aclk_bus_pre", 0, 1, 1);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock aclk_dmac: %ld\n",
-                       __func__, PTR_ERR(clk));
-       else
-               rockchip_clk_add_lookup(ctx, clk, ACLK_DMAC);
        rockchip_clk_register_plls(ctx, px30_pll_clks,
                                   ARRAY_SIZE(px30_pll_clks),
                                   PX30_GRF_SOC_STATUS0);
index bdb126321e564e0ba708b0479f768863acb1338b,68bf4f8fd64c7d1f74e60a6b243bfaa406768606..d17cfb7a3ff4bbee6ac134f9d83a4401b20e25ce
@@@ -1,8 -1,17 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
   * Author: Xing Zheng <zhengxing@rock-chips.com>
   *         Jeffy Chen <jeffy.chen@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -101,6 -110,7 +101,7 @@@ static struct rockchip_cpuclk_rate_tabl
        RK3228_CPUCLK_RATE(1608000000, 1, 7),
        RK3228_CPUCLK_RATE(1512000000, 1, 7),
        RK3228_CPUCLK_RATE(1488000000, 1, 5),
+       RK3228_CPUCLK_RATE(1464000000, 1, 5),
        RK3228_CPUCLK_RATE(1416000000, 1, 5),
        RK3228_CPUCLK_RATE(1392000000, 1, 5),
        RK3228_CPUCLK_RATE(1296000000, 1, 5),
@@@ -246,7 -256,7 +247,7 @@@ static struct rockchip_clk_branch rk322
                        RK2928_CLKGATE_CON(4), 0, GFLAGS),
  
        /* PD_MISC */
-       MUX(0, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
+       MUX(SCLK_HDMI_PHY, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
                        RK2928_MISC_CON, 13, 1, MFLAGS),
        MUX(0, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT,
                        RK2928_MISC_CON, 14, 1, MFLAGS),
index 057629685ea1481e95ffb22add5fc43c1fd970cc,8c7a8fa3235c882d982d39b0c7a5f349b515840b..cc2a177bbdbf44937ece153a6c0b98711baaab41
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2014 MundoReader S.L.
   * Author: Heiko Stuebner <heiko@sntech.de>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -113,7 -122,6 +113,6 @@@ static struct rockchip_pll_rate_table r
        RK3066_PLL_RATE( 160000000, 1, 80, 12),
        RK3066_PLL_RATE( 157500000, 1, 105, 16),
        RK3066_PLL_RATE( 126000000, 1, 84, 16),
-       RK3066_PLL_RATE(  48000000, 1, 64, 32),
        { /* sentinel */ },
  };
  
@@@ -767,6 -775,9 +766,9 @@@ static struct rockchip_clk_branch rk328
        GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 11, GFLAGS),
        GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS),
  
+       /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
+       SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"),
        /* pclk_pd_pmu gates */
        GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 0, GFLAGS),
        GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 1, GFLAGS),
@@@ -915,7 -926,6 +917,6 @@@ static struct syscore_ops rk3288_clk_sy
  static void __init rk3288_clk_init(struct device_node *np)
  {
        struct rockchip_clk_provider *ctx;
-       struct clk *clk;
  
        rk3288_cru_base = of_iomap(np, 0);
        if (!rk3288_cru_base) {
                return;
        }
  
-       /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
-       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
-                       __func__, PTR_ERR(clk));
-       else
-               rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
        rockchip_clk_register_plls(ctx, rk3288_pll_clks,
                                   ARRAY_SIZE(rk3288_pll_clks),
                                   RK3288_GRF_SOC_STATUS1);
index 076b9777a95571578f51afb11a19400b84396f66,cc88532662a618c7348ff2aaaa9cd7c0c05a1bdf..c186a1985bf4ebf30411e91a8e550dec4eb1ea7c
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
   * Author: Elaine <zhangqing@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -791,6 -800,9 +791,9 @@@ static struct rockchip_clk_branch rk332
        GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 0, RK3328_CLKGATE_CON(17), 15, GFLAGS),
        GATE(0, "pclk_pmu", "pclk_bus", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(28), 3, GFLAGS),
  
+       /* Watchdog pclk is controlled from the secure GRF */
+       SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_bus"),
        GATE(PCLK_USB3PHY_OTG, "pclk_usb3phy_otg", "pclk_phy_pre", 0, RK3328_CLKGATE_CON(28), 1, GFLAGS),
        GATE(PCLK_USB3PHY_PIPE, "pclk_usb3phy_pipe", "pclk_phy_pre", 0, RK3328_CLKGATE_CON(28), 2, GFLAGS),
        GATE(PCLK_USB3_GRF, "pclk_usb3_grf", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(17), 2, GFLAGS),
index 43b022d9393b7b6112d4ad9d49ef01036c021c2e,6ecc17b80ffe41336d617813cc46b116c8539b73..55443349439b414c8371a4549f3e0b187ef8c0cb
@@@ -1,6 -1,15 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -811,6 -820,9 +811,9 @@@ static struct rockchip_clk_branch rk336
        GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 2, GFLAGS),
        GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(22), 1, GFLAGS),
  
+       /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
+       SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"),
        /*
         * pclk_vio gates
         * pclk_vio comes from the exactly same source as hclk_vio
@@@ -862,7 -874,6 +865,6 @@@ static void __init rk3368_clk_init(stru
  {
        struct rockchip_clk_provider *ctx;
        void __iomem *reg_base;
-       struct clk *clk;
  
        reg_base = of_iomap(np, 0);
        if (!reg_base) {
                return;
        }
  
-       /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
-       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
-                       __func__, PTR_ERR(clk));
-       else
-               rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
        rockchip_clk_register_plls(ctx, rk3368_pll_clks,
                                   ARRAY_SIZE(rk3368_pll_clks),
                                   RK3368_GRF_SOC_STATUS0);
index a7ff71313278edb30c68b3055f7c7318cdb76d96,b01496d0e2b872c5804a6ba489c42cca6e426419..ce1d2446f142fac715549ad589037f008450d47f
@@@ -1,7 -1,16 +1,7 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
   * Author: Xing Zheng <zhengxing@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -1295,6 -1304,9 +1295,9 @@@ static struct rockchip_clk_branch rk339
        GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS),
        GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS),
  
+       /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
+       SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_alive"),
        GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS),
        GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS),
  
@@@ -1522,7 -1534,6 +1525,6 @@@ static void __init rk3399_clk_init(stru
  {
        struct rockchip_clk_provider *ctx;
        void __iomem *reg_base;
-       struct clk *clk;
  
        reg_base = of_iomap(np, 0);
        if (!reg_base) {
                return;
        }
  
-       /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
-       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_alive", 0, 1, 1);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
-                       __func__, PTR_ERR(clk));
-       else
-               rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
        rockchip_clk_register_plls(ctx, rk3399_pll_clks,
                                   ARRAY_SIZE(rk3399_pll_clks), -1);
  
index adb66cc9492901ccb377027c4fec718c05047e49,2a911923cf81a0c96da0be723292e2062db5315e..b811597a3d38ea9f577f35fbbf260ce033780435
@@@ -1,4 -1,3 +1,4 @@@
 +/* SPDX-License-Identifier: GPL-2.0-or-later */
  /*
   * Copyright (c) 2014 MundoReader S.L.
   * Author: Heiko Stuebner <heiko@sntech.de>
   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   * Copyright (c) 2013 Linaro Ltd.
   * Author: Thomas Abraham <thomas.ab@samsung.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #ifndef CLK_ROCKCHIP_CLK_H
@@@ -811,6 -820,10 +811,10 @@@ struct rockchip_clk_branch 
                .gate_offset    = -1,                           \
        }
  
+ /* SGRF clocks are only accessible from secure mode, so not controllable */
+ #define SGRF_GATE(_id, cname, pname)                          \
+               FACTOR(_id, cname, pname, 0, 1, 1)
  struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
                        void __iomem *base, unsigned long nr_clks);
  void rockchip_clk_of_add_provider(struct device_node *np,
index 982eb02bafda4b1e848d7329bf56e59fd6451ce4,ed4af7da9c4fa7c982cb2b84284a6048e97cf849..51564fc23c639898486e3579f95458aa5c3906f6
@@@ -1,9 -1,12 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   * Copyright (c) 2013 Linaro Ltd.
   * Author: Thomas Abraham <thomas.ab@samsung.com>
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * Common Clock Framework support for all Exynos4 SoCs.
  */
  
@@@ -958,6 -961,7 +958,7 @@@ static const struct samsung_gate_clock 
  
  /* list of gate clocks supported in exynos4x12 soc */
  static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
+       GATE(CLK_ASYNC_G3D, "async_g3d", "aclk200", GATE_IP_LEFTBUS, 6, 0, 0),
        GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
        GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
        GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
index 12d800fd95286e757539ee53e52e1ed4c6331a02,16ad498e3f3f0f08930ef3b64620c2682e913958..01bca5a498b2a1e330287e465401aa7f330a37ae
@@@ -1,9 -1,12 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   * Authors: Thomas Abraham <thomas.ab@samsung.com>
   *        Chander Kashyap <k.chander@samsung.com>
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * Common Clock Framework support for Exynos5420 SoC.
  */
  
  #define SRC_CDREX             0x20200
  #define DIV_CDREX0            0x20500
  #define DIV_CDREX1            0x20504
+ #define GATE_BUS_CDREX0               0x20700
+ #define GATE_BUS_CDREX1               0x20704
  #define KPLL_LOCK             0x28000
  #define KPLL_CON0             0x28100
  #define SRC_KFC                       0x28200
@@@ -245,6 -250,8 +247,8 @@@ static const unsigned long exynos5x_clk
        DIV_CDREX1,
        SRC_KFC,
        DIV_KFC0,
+       GATE_BUS_CDREX0,
+       GATE_BUS_CDREX1,
  };
  
  static const unsigned long exynos5800_clk_regs[] __initconst = {
@@@ -422,6 -429,9 +426,9 @@@ PNAME(mout_group13_5800_p) = { "dout_os
  PNAME(mout_group14_5800_p)    = { "dout_aclk550_cam", "dout_sclk_sw" };
  PNAME(mout_group15_5800_p)    = { "dout_osc_div", "mout_sw_aclk550_cam" };
  PNAME(mout_group16_5800_p)    = { "dout_osc_div", "mout_mau_epll_clk" };
+ PNAME(mout_mx_mspll_ccore_phy_p) = { "sclk_bpll", "mout_sclk_dpll",
+                                       "mout_sclk_mpll", "ff_dout_spll2",
+                                       "mout_sclk_spll", "mout_sclk_epll"};
  
  /* fixed rate clocks generated outside the soc */
  static struct samsung_fixed_rate_clock
@@@ -447,7 -457,7 +454,7 @@@ static const struct samsung_fixed_facto
  static const struct samsung_fixed_factor_clock
                exynos5800_fixed_factor_clks[] __initconst = {
        FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0),
-       FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
+       FFACTOR(CLK_FF_DOUT_SPLL2, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
  };
  
  static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
        MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2),
        MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2),
  
+       MUX(CLK_MOUT_MX_MSPLL_CCORE_PHY, "mout_mx_mspll_ccore_phy",
+               mout_mx_mspll_ccore_phy_p, SRC_TOP7, 0, 3),
        MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
-                       mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
+                       mout_mx_mspll_ccore_p, SRC_TOP7, 16, 3),
        MUX_F(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p,
                        SRC_TOP7, 20, 2, CLK_SET_RATE_PARENT, 0),
-       MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
+       MUX(CLK_SCLK_BPLL, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
        MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1),
  
        MUX(0, "mout_aclk550_cam", mout_group3_5800_p, SRC_TOP8, 16, 3),
@@@ -645,7 -658,7 +655,7 @@@ static const struct samsung_mux_clock e
  
        MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
        MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
-       MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
+       MUX(CLK_MOUT_SCLK_SPLL, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
        MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
        MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
        MUX_F(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1,
@@@ -803,8 -816,21 +813,21 @@@ static const struct samsung_div_clock e
                        "mout_aclk400_disp1", DIV_TOP2, 4, 3),
  
        /* CDREX Block */
-       DIV(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1",
-                       DIV_CDREX0, 28, 3),
+       /*
+        * The three clocks below are controlled using the same register and
+        * bits. They are put into one because there is a need of
+        * synchronization between the BUS and DREXs (two external memory
+        * interfaces).
+        * They are put here to show this HW assumption and for clock
+        * information summary completeness.
+        */
+       DIV_F(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1",
+                       DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
+       DIV_F(CLK_DOUT_PCLK_DREX0, "dout_pclk_drex0", "dout_cclk_drex0",
+                       DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
+       DIV_F(CLK_DOUT_PCLK_DREX1, "dout_pclk_drex1", "dout_cclk_drex0",
+                       DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
        DIV_F(CLK_DOUT_SCLK_CDREX, "dout_sclk_cdrex", "mout_mclk_cdrex",
                        DIV_CDREX0, 24, 3, CLK_SET_RATE_PARENT, 0),
        DIV(CLK_DOUT_ACLK_CDREX1, "dout_aclk_cdrex1", "dout_clk2x_phy0",
@@@ -1167,6 -1193,32 +1190,32 @@@ static const struct samsung_gate_clock 
                        GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
  
        GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+       /* CDREX */
+       GATE(CLK_CLKM_PHY0, "clkm_phy0", "dout_sclk_cdrex",
+                       GATE_BUS_CDREX0, 0, 0, 0),
+       GATE(CLK_CLKM_PHY1, "clkm_phy1", "dout_sclk_cdrex",
+                       GATE_BUS_CDREX0, 1, 0, 0),
+       GATE(0, "mx_mspll_ccore_phy", "mout_mx_mspll_ccore_phy",
+                       SRC_MASK_TOP7, 0, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX1_1, "aclk_ppmu_drex1_1", "dout_aclk_cdrex1",
+                       GATE_BUS_CDREX1, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX1_0, "aclk_ppmu_drex1_0", "dout_aclk_cdrex1",
+                       GATE_BUS_CDREX1, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX0_1, "aclk_ppmu_drex0_1", "dout_aclk_cdrex1",
+                       GATE_BUS_CDREX1, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX0_0, "aclk_ppmu_drex0_0", "dout_aclk_cdrex1",
+                       GATE_BUS_CDREX1, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX1_1, "pclk_ppmu_drex1_1", "dout_pclk_cdrex",
+                       GATE_BUS_CDREX1, 26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX1_0, "pclk_ppmu_drex1_0", "dout_pclk_cdrex",
+                       GATE_BUS_CDREX1, 27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX0_1, "pclk_ppmu_drex0_1", "dout_pclk_cdrex",
+                       GATE_BUS_CDREX1, 28, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX0_0, "pclk_ppmu_drex0_0", "dout_pclk_cdrex",
+                       GATE_BUS_CDREX1, 29, CLK_IGNORE_UNUSED, 0),
  };
  
  static const struct samsung_div_clock exynos5x_disp_div_clks[] __initconst = {
@@@ -1282,6 -1334,17 +1331,17 @@@ static const struct samsung_pll_rate_ta
        PLL_35XX_RATE(24 * MHZ, 200000000,  200, 3, 3),
  };
  
+ static const struct samsung_pll_rate_table exynos5422_bpll_rate_table[] = {
+       PLL_35XX_RATE(24 * MHZ, 825000000, 275, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 728000000, 182, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 633000000, 211, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 543000000, 181, 2, 2),
+       PLL_35XX_RATE(24 * MHZ, 413000000, 413, 6, 2),
+       PLL_35XX_RATE(24 * MHZ, 275000000, 275, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 206000000, 206, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 165000000, 110, 2, 3),
+ };
  static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
        PLL_36XX_RATE(24 * MHZ, 600000000U, 100, 2, 1, 0),
        PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
@@@ -1424,9 -1487,13 +1484,13 @@@ static void __init exynos5x_clk_init(st
                exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
                exynos5x_plls[epll].rate_table = exynos5420_epll_24mhz_tbl;
                exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
-               exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
        }
  
+       if (soc == EXYNOS5420)
+               exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+       else
+               exynos5x_plls[bpll].rate_table = exynos5422_bpll_rate_table;
        samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
                                        reg_base);
        samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
index 945d5f2ad733be5b4a606500738d2db7041fa6b0,14e253915ca416b0abda6aefbb5f4cd2f5676de3..7824c2ba3d8e6c29c850f67655da8b9fd0d6201d
@@@ -1,8 -1,11 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2014 Samsung Electronics Co., Ltd.
   * Author: Chanwoo Choi <cw00.choi@samsung.com>
   *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
 - *
   * Common Clock Framework support for Exynos5433 SoC.
   */
  
@@@ -5587,8 -5590,8 +5587,8 @@@ static int __init exynos5433_cmu_probe(
        data->nr_clk_save = info->nr_clk_regs;
        data->clk_suspend = info->suspend_regs;
        data->nr_clk_suspend = info->nr_suspend_regs;
-       data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
-                                                   "#clock-cells");
+       data->nr_pclks = of_clk_get_parent_count(dev->of_node);
        if (data->nr_pclks > 0) {
                data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
                                           data->nr_pclks, GFP_KERNEL);
index df43952e403e1df14a168042b79d46c4765a4525,59def849db08313f69bc673bd6111efd6d7a1129..f32366d9336e7bd020af7de00844a5ba4b22a348
@@@ -1,8 -1,16 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2017 Priit Laes <plaes@plaes.org>.
   * Copyright (c) 2017 Maxime Ripard.
   * Copyright (c) 2017 Jonathan Liu.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -160,8 -168,9 +160,9 @@@ static struct ccu_nk pll_periph_base_cl
        },
  };
  
- static CLK_FIXED_FACTOR(pll_periph_clk, "pll-periph", "pll-periph-base",
-                       2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph_clk, "pll-periph",
+                          &pll_periph_base_clk.common.hw,
+                          2, 1, CLK_SET_RATE_PARENT);
  
  /* Not documented on A10 */
  static struct ccu_div pll_periph_sata_clk = {
@@@ -1028,19 -1037,29 +1029,29 @@@ static struct ccu_common *sun4i_sun7i_c
        &out_b_clk.common
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* Post-divider for pll-audio is hardcoded to 1 */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
-                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
-                       "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
+                          &pll_video0_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_video1_2x_clk, "pll-video1-2x",
+                          &pll_video1_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
  
  
  static struct clk_hw_onecell_data sun4i_a10_hw_clks = {
index 1786ee8fe8bb75956e268e6f9590b31280167108,5cc24b56dcf30a85d062d0909ffd96d18493d6a6..49bd7a4c015c46d4763d941f8d75ea3bec178ee9
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -597,23 -605,34 +597,34 @@@ static SUNXI_CCU_M_WITH_GATE(gpu_clk, "
                             0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
  
  /* Fixed Factor clocks */
- static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
+ static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
-                       "pll-periph0", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
-                       "pll-periph1", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
-                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
+                          &pll_periph0_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x",
+                          &pll_periph1_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
+                          &pll_video0_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
  
  static struct ccu_common *sun50i_a64_ccu_clks[] = {
        &pll_cpux_clk.common,
index b71ed0f6f78512ffd2d8fab7f55f3fe951bd7bec,d27f3e4c014789af228cccfed74a4f0411c398b8..b78e9b507c1c68895db8ecaf3946e5317c0bf40d
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -603,19 -611,29 +603,29 @@@ static struct ccu_common *sun5i_a10s_cc
        &iep_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
-                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
-                       "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
+                          &pll_video0_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_video1_2x_clk, "pll-video1-2x",
+                          &pll_video1_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
  
  static struct clk_hw_onecell_data sun5i_a10s_hw_clks = {
        .hws    = {
index 2ff7b082df287e28f487a1e86dcdb933fd1ccc88,048c0d75d0b0b13fe8b1b360ce33c526a51ec2c7..9b40d53266a3f4138186404160928978c05ed880
@@@ -1,10 -1,18 +1,10 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Chen-Yu Tsai
   *
   * Chen-Yu Tsai <wens@csie.org>
   *
   * Based on ccu-sun8i-h3.c by Maxime Ripard.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -955,21 -963,32 +955,32 @@@ static struct ccu_common *sun6i_a31_ccu
        &out_c_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph_2x_clk, "pll-periph-2x",
-                       "pll-periph", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
-                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
-                       "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph_2x_clk, "pll-periph-2x",
+                          &pll_periph_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
+                          &pll_video0_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_video1_2x_clk, "pll-video1-2x",
+                          &pll_video1_clk.common.hw,
+                          1, 2, CLK_SET_RATE_PARENT);
  
  static struct clk_hw_onecell_data sun6i_a31_hw_clks = {
        .hws    = {
index 14ced502788a256d7bb0250fdf70bad56d29c5b0,de2f2962164e821c2667a9a256cf8181dab8c930..103aa504f6c8a6368094b72f531876291c90db06
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -543,19 -551,29 +543,29 @@@ static struct ccu_common *sun8i_a23_ccu
        &ats_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph_2x_clk, "pll-periph-2x",
-                       "pll-periph", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video_2x_clk, "pll-video-2x",
-                       "pll-video", 1, 2, 0);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph_2x_clk, "pll-periph-2x",
+                          &pll_periph_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video_2x_clk, "pll-video-2x",
+                          &pll_video_clk.common.hw,
+                          1, 2, 0);
  
  static struct clk_hw_onecell_data sun8i_a23_hw_clks = {
        .hws    = {
index 61fb41f4903c74e4d80a68f690b4fc39105232fe,25a14548f39bb73a53e1a9e521db0197298bfcea..91838cd110377cb4e8dab7df3238f5288e66a65c
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -580,19 -588,29 +580,29 @@@ static struct ccu_common *sun8i_a33_ccu
        &ats_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph_2x_clk, "pll-periph-2x",
-                       "pll-periph", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video_2x_clk, "pll-video-2x",
-                       "pll-video", 1, 2, 0);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph_2x_clk, "pll-periph-2x",
+                          &pll_periph_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video_2x_clk, "pll-video-2x",
+                          &pll_video_clk.common.hw,
+                          1, 2, 0);
  
  static struct clk_hw_onecell_data sun8i_a33_hw_clks = {
        .hws    = {
index 9601504905b2bd5f09ba0f7862643d04769151f9,d5b5cd558ecfd9d190df077a33b39a4530fbd9bd..6b636362379ee98604fee11f5b584b73d8384783
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -717,17 -725,26 +717,26 @@@ static struct ccu_common *sun50i_h5_ccu
        &gpu_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 1 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
-                       "pll-periph0", 1, 2, 0);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
+                          &pll_periph0_clk.common.hw,
+                          1, 2, 0);
  
  static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
        .hws    = {
index b5be11e5de0d3c747adbd911d7a87e1ff734641b,a7a21feaf1433966c693bc1bb3d36513b8809356..4646fdc61053b0c65d857a8424c71e5e517a969d
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
  
  #include "ccu-sun8i-r.h"
  
- static const char * const ar100_parents[] = { "osc32k", "osc24M",
-                                            "pll-periph0", "iosc" };
- static const char * const a83t_ar100_parents[] = { "osc16M-d512", "osc24M",
-                                                  "pll-periph0", "iosc" };
+ static const struct clk_parent_data ar100_parents[] = {
+       { .fw_name = "losc" },
+       { .fw_name = "hosc" },
+       { .fw_name = "pll-periph" },
+       { .fw_name = "iosc" },
+ };
  static const struct ccu_mux_var_prediv ar100_predivs[] = {
        { .index = 2, .shift = 8, .width = 5 },
  };
@@@ -39,64 -50,49 +42,49 @@@ static struct ccu_div ar100_clk = 
        .common         = {
                .reg            = 0x00,
                .features       = CCU_FEATURE_VARIABLE_PREDIV,
-               .hw.init        = CLK_HW_INIT_PARENTS("ar100",
-                                                     ar100_parents,
-                                                     &ccu_div_ops,
-                                                     0),
-       },
- };
- static struct ccu_div a83t_ar100_clk = {
-       .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
-       .mux            = {
-               .shift  = 16,
-               .width  = 2,
-               .var_predivs    = ar100_predivs,
-               .n_var_predivs  = ARRAY_SIZE(ar100_predivs),
-       },
-       .common         = {
-               .reg            = 0x00,
-               .features       = CCU_FEATURE_VARIABLE_PREDIV,
-               .hw.init        = CLK_HW_INIT_PARENTS("ar100",
-                                                     a83t_ar100_parents,
-                                                     &ccu_div_ops,
-                                                     0),
+               .hw.init        = CLK_HW_INIT_PARENTS_DATA("ar100",
+                                                          ar100_parents,
+                                                          &ccu_div_ops,
+                                                          0),
        },
  };
  
- static CLK_FIXED_FACTOR(ahb0_clk, "ahb0", "ar100", 1, 1, 0);
+ static CLK_FIXED_FACTOR_HW(ahb0_clk, "ahb0", &ar100_clk.common.hw, 1, 1, 0);
  
  static struct ccu_div apb0_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
  
        .common         = {
                .reg            = 0x0c,
-               .hw.init        = CLK_HW_INIT("apb0",
-                                             "ahb0",
-                                             &ccu_div_ops,
-                                             0),
+               .hw.init        = CLK_HW_INIT_HW("apb0",
+                                                &ahb0_clk.hw,
+                                                &ccu_div_ops,
+                                                0),
        },
  };
  
  static SUNXI_CCU_M(a83t_apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0);
  
- static SUNXI_CCU_GATE(apb0_pio_clk,   "apb0-pio",     "apb0",
-                     0x28, BIT(0), 0);
- static SUNXI_CCU_GATE(apb0_ir_clk,    "apb0-ir",      "apb0",
-                     0x28, BIT(1), 0);
- static SUNXI_CCU_GATE(apb0_timer_clk, "apb0-timer",   "apb0",
-                     0x28, BIT(2), 0);
- static SUNXI_CCU_GATE(apb0_rsb_clk,   "apb0-rsb",     "apb0",
-                     0x28, BIT(3), 0);
- static SUNXI_CCU_GATE(apb0_uart_clk,  "apb0-uart",    "apb0",
-                     0x28, BIT(4), 0);
- static SUNXI_CCU_GATE(apb0_i2c_clk,   "apb0-i2c",     "apb0",
-                     0x28, BIT(6), 0);
- static SUNXI_CCU_GATE(apb0_twd_clk,   "apb0-twd",     "apb0",
-                     0x28, BIT(7), 0);
+ /*
+  * Define the parent as an array that can be reused to save space
+  * instead of having compound literals for each gate. Also have it
+  * non-const so we can change it on the A83T.
+  */
+ static const struct clk_hw *apb0_gate_parent[] = { &apb0_clk.common.hw };
+ static SUNXI_CCU_GATE_HWS(apb0_pio_clk,               "apb0-pio",
+                         apb0_gate_parent, 0x28, BIT(0), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_ir_clk,                "apb0-ir",
+                         apb0_gate_parent, 0x28, BIT(1), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_timer_clk,     "apb0-timer",
+                         apb0_gate_parent, 0x28, BIT(2), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_rsb_clk,               "apb0-rsb",
+                         apb0_gate_parent, 0x28, BIT(3), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_uart_clk,      "apb0-uart",
+                         apb0_gate_parent, 0x28, BIT(4), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_i2c_clk,               "apb0-i2c",
+                         apb0_gate_parent, 0x28, BIT(6), 0);
+ static SUNXI_CCU_GATE_HWS(apb0_twd_clk,               "apb0-twd",
+                         apb0_gate_parent, 0x28, BIT(7), 0);
  
  static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" };
  static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
                                  BIT(31),      /* gate */
                                  0);
  
- static const char *const a83t_r_mod0_parents[] = { "osc16M", "osc24M" };
+ static const struct clk_parent_data a83t_r_mod0_parents[] = {
+       { .fw_name = "iosc" },
+       { .fw_name = "hosc" },
+ };
  static const struct ccu_mux_fixed_prediv a83t_ir_predivs[] = {
        { .index = 0, .div = 16 },
  };
@@@ -127,15 -126,15 +118,15 @@@ static struct ccu_mp a83t_ir_clk = 
        .common         = {
                .reg            = 0x54,
                .features       = CCU_FEATURE_VARIABLE_PREDIV,
-               .hw.init        = CLK_HW_INIT_PARENTS("ir",
-                                                     a83t_r_mod0_parents,
-                                                     &ccu_mp_ops,
-                                                     0),
+               .hw.init        = CLK_HW_INIT_PARENTS_DATA("ir",
+                                                          a83t_r_mod0_parents,
+                                                          &ccu_mp_ops,
+                                                          0),
        },
  };
  
  static struct ccu_common *sun8i_a83t_r_ccu_clks[] = {
-       &a83t_ar100_clk.common,
+       &ar100_clk.common,
        &a83t_apb0_clk.common,
        &apb0_pio_clk.common,
        &apb0_ir_clk.common,
@@@ -174,7 -173,7 +165,7 @@@ static struct ccu_common *sun50i_a64_r_
  
  static struct clk_hw_onecell_data sun8i_a83t_r_hw_clks = {
        .hws    = {
-               [CLK_AR100]             = &a83t_ar100_clk.common.hw,
+               [CLK_AR100]             = &ar100_clk.common.hw,
                [CLK_AHB0]              = &ahb0_clk.hw,
                [CLK_APB0]              = &a83t_apb0_clk.common.hw,
                [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
@@@ -291,6 -290,9 +282,9 @@@ static void __init sunxi_r_ccu_init(str
  
  static void __init sun8i_a83t_r_ccu_setup(struct device_node *node)
  {
+       /* Fix apb0 bus gate parents here */
+       apb0_gate_parent[0] = &a83t_apb0_clk.common.hw;
        sunxi_r_ccu_init(node, &sun8i_a83t_r_ccu_desc);
  }
  CLK_OF_DECLARE(sun8i_a83t_r_ccu, "allwinner,sun8i-a83t-r-ccu",
index 540f5f7454fc0105412d2421d6af365b0addca0d,5fef799740acdc5dc763bc4dcd69a65088d1e9d2..897490800102f3612b79d9c6e37efed0e74ef08e
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -944,25 -952,37 +944,37 @@@ static struct ccu_common *sun8i_r40_ccu
  };
  
  /* Fixed Factor clocks */
- static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
+ static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  
  /* We hardcode the divider to 4 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
-                       "pll-periph0", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
-                       "pll-periph1", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
-                       "pll-video0", 1, 2, 0);
- static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
-                       "pll-video1", 1, 2, 0);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           4, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
+                          &pll_periph0_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x",
+                          &pll_periph1_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
+                          &pll_video0_clk.common.hw,
+                          1, 2, 0);
+ static CLK_FIXED_FACTOR_HW(pll_video1_2x_clk, "pll-video1-2x",
+                          &pll_video1_clk.common.hw,
+                          1, 2, 0);
  
  static struct clk_hw_onecell_data sun8i_r40_hw_clks = {
        .hws    = {
index cbbf06d42c2c2e20616a5e2064c7e1fcaff973f7,60f011b1fbf6e57e664c439a1e543b1b0d2b416f..9b3939fc7faa614a87413685f597f41812c8eb76
@@@ -1,9 -1,17 +1,9 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
   *
   * Based on ccu-sun8i-h3.c, which is:
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk-provider.h>
@@@ -429,17 -437,26 +429,26 @@@ static struct ccu_common *sun8i_v3s_ccu
        &mipi_csi_clk.common,
  };
  
+ static const struct clk_hw *clk_parent_pll_audio[] = {
+       &pll_audio_base_clk.common.hw
+ };
  /* We hardcode the divider to 4 for now */
- static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
-                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
-                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
-                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
-                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
- static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
-                       "pll-periph0", 1, 2, 0);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
+                           clk_parent_pll_audio,
+                           4, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+                           clk_parent_pll_audio,
+                           2, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+                           clk_parent_pll_audio,
+                           1, 1, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
+                           clk_parent_pll_audio,
+                           1, 2, CLK_SET_RATE_PARENT);
+ static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
+                          &pll_periph0_clk.common.hw,
+                          1, 2, 0);
  
  static struct clk_hw_onecell_data sun8i_v3s_hw_clks = {
        .hws    = {
index 2f82cd855b0f1dc2f2b77798eaa1a575667b1a9c,23bc11e65539374461cf90a45bf8fcc0ba118a13..4b4a507d04edfaa5e056b32e1c868fcbf2027185
@@@ -1,6 -1,14 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk.h>
  
  #include "ccu-sun9i-a80-usb.h"
  
- static SUNXI_CCU_GATE(bus_hci0_clk, "bus-hci0", "bus-usb", 0x0, BIT(1), 0);
- static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc24M", 0x0, BIT(2), 0);
- static SUNXI_CCU_GATE(bus_hci1_clk, "bus-hci1", "bus-usb", 0x0, BIT(3), 0);
- static SUNXI_CCU_GATE(bus_hci2_clk, "bus-hci2", "bus-usb", 0x0, BIT(5), 0);
- static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc24M", 0x0, BIT(6), 0);
- static SUNXI_CCU_GATE(usb0_phy_clk, "usb0-phy", "osc24M", 0x4, BIT(1), 0);
- static SUNXI_CCU_GATE(usb1_hsic_clk, "usb1-hsic", "osc24M", 0x4, BIT(2), 0);
- static SUNXI_CCU_GATE(usb1_phy_clk, "usb1-phy", "osc24M", 0x4, BIT(3), 0);
- static SUNXI_CCU_GATE(usb2_hsic_clk, "usb2-hsic", "osc24M", 0x4, BIT(4), 0);
- static SUNXI_CCU_GATE(usb2_phy_clk, "usb2-phy", "osc24M", 0x4, BIT(5), 0);
- static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "osc24M", 0x4, BIT(10), 0);
+ static const struct clk_parent_data clk_parent_hosc[] = {
+       { .fw_name = "hosc" },
+ };
+ static const struct clk_parent_data clk_parent_bus[] = {
+       { .fw_name = "bus" },
+ };
+ static SUNXI_CCU_GATE_DATA(bus_hci0_clk, "bus-hci0", clk_parent_bus, 0x0, BIT(1), 0);
+ static SUNXI_CCU_GATE_DATA(usb_ohci0_clk, "usb-ohci0", clk_parent_hosc, 0x0, BIT(2), 0);
+ static SUNXI_CCU_GATE_DATA(bus_hci1_clk, "bus-hci1", clk_parent_bus, 0x0, BIT(3), 0);
+ static SUNXI_CCU_GATE_DATA(bus_hci2_clk, "bus-hci2", clk_parent_bus, 0x0, BIT(5), 0);
+ static SUNXI_CCU_GATE_DATA(usb_ohci2_clk, "usb-ohci2", clk_parent_hosc, 0x0, BIT(6), 0);
+ static SUNXI_CCU_GATE_DATA(usb0_phy_clk, "usb0-phy", clk_parent_hosc, 0x4, BIT(1), 0);
+ static SUNXI_CCU_GATE_DATA(usb1_hsic_clk, "usb1-hsic", clk_parent_hosc, 0x4, BIT(2), 0);
+ static SUNXI_CCU_GATE_DATA(usb1_phy_clk, "usb1-phy", clk_parent_hosc, 0x4, BIT(3), 0);
+ static SUNXI_CCU_GATE_DATA(usb2_hsic_clk, "usb2-hsic", clk_parent_hosc, 0x4, BIT(4), 0);
+ static SUNXI_CCU_GATE_DATA(usb2_phy_clk, "usb2-phy", clk_parent_hosc, 0x4, BIT(5), 0);
+ static SUNXI_CCU_GATE_DATA(usb_hsic_clk, "usb-hsic", clk_parent_hosc, 0x4, BIT(10), 0);
  
  static struct ccu_common *sun9i_a80_usb_clks[] = {
        &bus_hci0_clk.common,
index c173778c8a7810c7cc6e17e2aa5a59dbcd75eab1,f1db29854934072bf437a80e86338f9bdd95d09a..7fe3ac980e5f930e61cb4004c3bd5506205a7c14
@@@ -1,8 -1,17 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2016 Maxime Ripard
   *
   * Maxime Ripard <maxime.ripard@free-electrons.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk.h>
@@@ -101,7 -110,7 +101,7 @@@ int sunxi_ccu_probe(struct device_node 
                if (!hw)
                        continue;
  
-               ret = clk_hw_register(NULL, hw);
+               ret = of_clk_hw_register(node, hw);
                if (ret) {
                        pr_err("Couldn't register clock %d - %s\n",
                               i, clk_hw_get_name(hw));
index da8100e8846d1c3d39cec68700fb1999bc6f3515,613ddd03629e4f0c51948bf8b6e56df466d5af18..c386689a952b89304e878bfa844a099605207e69
@@@ -1,6 -1,14 +1,6 @@@
 +/* SPDX-License-Identifier: GPL-2.0-only */
  /*
   * Copyright (c) 2016 Maxime Ripard. All rights reserved.
 - *
 - * This software is licensed under the terms of the GNU General Public
 - * License version 2, as published by the Free Software Foundation, and
 - * may be copied, distributed, and modified under those terms.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #ifndef _CCU_GATE_H_
@@@ -28,6 -36,59 +28,59 @@@ struct ccu_gate 
                }                                                       \
        }
  
+ #define SUNXI_CCU_GATE_HW(_struct, _name, _parent, _reg, _gate, _flags)       \
+       struct ccu_gate _struct = {                                     \
+               .enable = _gate,                                        \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_HW(_name,         \
+                                                        _parent,       \
+                                                        &ccu_gate_ops, \
+                                                        _flags),       \
+               }                                                       \
+       }
+ #define SUNXI_CCU_GATE_FW(_struct, _name, _parent, _reg, _gate, _flags)       \
+       struct ccu_gate _struct = {                                     \
+               .enable = _gate,                                        \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_FW_NAME(_name,    \
+                                                             _parent,  \
+                                                             &ccu_gate_ops, \
+                                                             _flags),  \
+               }                                                       \
+       }
+ /*
+  * The following two macros allow the re-use of the data structure
+  * holding the parent info.
+  */
+ #define SUNXI_CCU_GATE_HWS(_struct, _name, _parent, _reg, _gate, _flags) \
+       struct ccu_gate _struct = {                                     \
+               .enable = _gate,                                        \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        = CLK_HW_INIT_HWS(_name,        \
+                                                         _parent,      \
+                                                         &ccu_gate_ops, \
+                                                         _flags),      \
+               }                                                       \
+       }
+ #define SUNXI_CCU_GATE_DATA(_struct, _name, _data, _reg, _gate, _flags)       \
+       struct ccu_gate _struct = {                                     \
+               .enable = _gate,                                        \
+               .common = {                                             \
+                       .reg            = _reg,                         \
+                       .hw.init        =                               \
+                               CLK_HW_INIT_PARENTS_DATA(_name,         \
+                                                        _data,         \
+                                                        &ccu_gate_ops, \
+                                                        _flags),       \
+               }                                                       \
+       }
  static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
  {
        struct ccu_common *common = hw_to_ccu_common(hw);
index 623fda5e911fb272cb3e4de4f50706ed320e6bfc,830bfb7f5e6bc9da7c171718024904221540b2be..d3a43381a792700a96f618e4e86924612d529aa3
@@@ -1,8 -1,17 +1,8 @@@
 +// SPDX-License-Identifier: GPL-2.0-or-later
  /*
   * Copyright 2013 Emilio López
   *
   * Emilio López <emilio@elopez.com.ar>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #include <linux/clk.h>
@@@ -980,6 -989,8 +980,8 @@@ static struct clk ** __init sunxi_divs_
                if (endp) {
                        derived_name = kstrndup(clk_name, endp - clk_name,
                                                GFP_KERNEL);
+                       if (!derived_name)
+                               return NULL;
                        factors.name = derived_name;
                } else {
                        factors.name = clk_name;
index ac1d27a8c650af75543473266c7b5a62c45edb68,b474d3d7b1b6486a1172fc1c58eee6a6c4223f2e..df172d5772d7164dffb256e052c88f1c74cb7334
@@@ -1,6 -1,17 +1,6 @@@
 +// SPDX-License-Identifier: GPL-2.0-only
  /*
   * Copyright (c) 2012-2014 NVIDIA CORPORATION.  All rights reserved.
 - *
 - * This program is free software; you can redistribute it and/or modify it
 - * under the terms and conditions of the GNU General Public License,
 - * version 2, as published by the Free Software Foundation.
 - *
 - * This program is distributed in the hope it will be useful, but WITHOUT
 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 - * more details.
 - *
 - * You should have received a copy of the GNU General Public License
 - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  #include <linux/io.h>
@@@ -984,8 -995,6 +984,6 @@@ static void tegra210_pllre_set_defaults
        pllre->params->defaults_set = true;
  
        if (val & PLL_ENABLE) {
-               pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
                /*
                 * PLL is ON: check if defaults already set, then set those
                 * that can be updated in flight.
                _pll_misc_chk_default(clk_base, pllre->params, 0, val,
                                ~mask & PLLRE_MISC0_WRITE_MASK);
  
-               /* Enable lock detect */
+               /* The PLL doesn't work if it's in IDDQ. */
                val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]);
+               if (val & PLLRE_MISC0_IDDQ)
+                       pr_warn("unexpected IDDQ bit set for enabled clock\n");
+               /* Enable lock detect */
                val &= ~mask;
                val |= PLLRE_MISC0_DEFAULT_VALUE & mask;
                writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]);
                udelay(1);
  
+               if (!pllre->params->defaults_set)
+                       pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
                return;
        }
  
@@@ -2204,9 -2220,9 +2209,9 @@@ static struct div_nmp pllu_nmp = 
  };
  
  static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-       { 12000000, 480000000, 40, 1, 0, 0 },
-       { 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */
-       { 38400000, 480000000, 25, 2, 0, 0 },
+       { 12000000, 480000000, 40, 1, 1, 0 },
+       { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */
+       { 38400000, 480000000, 25, 2, 1, 0 },
        {        0,         0,  0, 0, 0, 0 },
  };
  
@@@ -3332,7 -3348,7 +3337,7 @@@ static struct tegra_clk_init_table init
        { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 },
        { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
        { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
-       { TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 },
+       { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
        { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 },
        { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 },
        { TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 },
        { TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 },
        { TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
-       { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
        { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
        { TEGRA210_CLK_SPDIF_IN_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
        { TEGRA210_CLK_I2S0_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
        { TEGRA210_CLK_I2S3_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
        { TEGRA210_CLK_I2S4_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
        { TEGRA210_CLK_VIMCLK_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
 +      { TEGRA210_CLK_HDA, TEGRA210_CLK_PLL_P, 51000000, 0 },
 +      { TEGRA210_CLK_HDA2CODEC_2X, TEGRA210_CLK_PLL_P, 48000000, 0 },
        /* This MUST be the last entry. */
        { TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
  };
index adbeeefaca92fe93c744d31f4f46bef8e497edb3,ad0b47981b87bdcab39c0947f72416942c41b876..414e0ced5409e4ca0b34a3de27070aa5d0bbe241
@@@ -1,4 -1,4 +1,4 @@@
 -// SPDX-License-Identifier: BSD-3-Clause
 +/* SPDX-License-Identifier: BSD-3-Clause */
  /*
   * Texas Instruments System Control Interface (TISCI) Protocol
   *
@@@ -202,7 -202,8 +202,8 @@@ struct ti_sci_msg_req_set_device_reset
   * @dev_id:   Device identifier this request is for
   * @clk_id:   Clock identifier for the device for this request.
   *            Each device has it's own set of clock inputs. This indexes
-  *            which clock input to modify.
+  *            which clock input to modify. Set to 255 if clock ID is
+  *            greater than or equal to 255.
   * @request_state: Request the state for the clock to be set to.
   *            MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock,
   *            it can be disabled, regardless of the state of the device
   *            being required by the device.(default)
   *            MSG_CLOCK_SW_STATE_REQ:  Configure the clock to be enabled,
   *            regardless of the state of the device.
+  * @clk_id_32:        Clock identifier for the device for this request.
+  *            Only to be used if the clock ID is greater than or equal to
+  *            255.
   *
   * Normally, all required clocks are managed by TISCI entity, this is used
   * only for specific control *IF* required. Auto managed state is
@@@ -234,6 -238,7 +238,7 @@@ struct ti_sci_msg_req_set_clock_state 
  #define MSG_CLOCK_SW_STATE_AUTO               1
  #define MSG_CLOCK_SW_STATE_REQ                2
        u8 request_state;
+       u32 clk_id_32;
  } __packed;
  
  /**
   * @dev_id:   Device identifier this request is for
   * @clk_id:   Clock identifier for the device for this request.
   *            Each device has it's own set of clock inputs. This indexes
-  *            which clock input to get state of.
+  *            which clock input to get state of. Set to 255 if the clock
+  *            ID is greater than or equal to 255.
+  * @clk_id_32:        Clock identifier for the device for the request.
+  *            Only to be used if the clock ID is greater than or equal to
+  *            255.
   *
   * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state
   * of the clock
@@@ -251,6 -260,7 +260,7 @@@ struct ti_sci_msg_req_get_clock_state 
        struct ti_sci_msg_hdr hdr;
        u32 dev_id;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
@@@ -278,9 -288,13 +288,13 @@@ struct ti_sci_msg_resp_get_clock_state 
   * @dev_id:   Device identifier this request is for
   * @clk_id:   Clock identifier for the device for this request.
   *            Each device has it's own set of clock inputs. This indexes
-  *            which clock input to modify.
+  *            which clock input to modify. Set to 255 if clock ID is
+  *            greater than or equal to 255.
   * @parent_id:        The new clock parent is selectable by an index via this
-  *            parameter.
+  *            parameter. Set to 255 if clock ID is greater than or
+  *            equal to 255.
+  * @clk_id_32:        Clock identifier if @clk_id field is 255.
+  * @parent_id_32:     Parent identifier if @parent_id is 255.
   *
   * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic
   * ACK / NACK message.
@@@ -290,6 -304,8 +304,8 @@@ struct ti_sci_msg_req_set_clock_parent 
        u32 dev_id;
        u8 clk_id;
        u8 parent_id;
+       u32 clk_id_32;
+       u32 parent_id_32;
  } __packed;
  
  /**
   * @dev_id:   Device identifier this request is for
   * @clk_id:   Clock identifier for the device for this request.
   *            Each device has it's own set of clock inputs. This indexes
-  *            which clock input to get the parent for.
+  *            which clock input to get the parent for. If this field
+  *            contains 255, the actual clock identifier is stored in
+  *            @clk_id_32.
+  * @clk_id_32:        Clock identifier if the @clk_id field contains 255.
   *
   * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information
   */
@@@ -306,25 -325,32 +325,32 @@@ struct ti_sci_msg_req_get_clock_parent 
        struct ti_sci_msg_hdr hdr;
        u32 dev_id;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
   * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent
   * @hdr:      Generic Header
-  * @parent_id:        The current clock parent
+  * @parent_id:        The current clock parent. If set to 255, the current parent
+  *            ID can be found from the @parent_id_32 field.
+  * @parent_id_32:     Current clock parent if @parent_id field is set to
+  *                    255.
   *
   * Response to TI_SCI_MSG_GET_CLOCK_PARENT.
   */
  struct ti_sci_msg_resp_get_clock_parent {
        struct ti_sci_msg_hdr hdr;
        u8 parent_id;
+       u32 parent_id_32;
  } __packed;
  
  /**
   * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents
   * @hdr:      Generic header
   * @dev_id:   Device identifier this request is for
-  * @clk_id:   Clock identifier for the device for this request.
+  * @clk_id:   Clock identifier for the device for this request. Set to
+  *            255 if clock ID is greater than or equal to 255.
+  * @clk_id_32:        Clock identifier if the @clk_id field contains 255.
   *
   * This request provides information about how many clock parent options
   * are available for a given clock to a device. This is typically used
@@@ -337,18 -363,24 +363,24 @@@ struct ti_sci_msg_req_get_clock_num_par
        struct ti_sci_msg_hdr hdr;
        u32 dev_id;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
   * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents
   * @hdr:              Generic header
-  * @num_parents:      Number of clock parents
+  * @num_parents:      Number of clock parents. If set to 255, the actual
+  *                    number of parents is stored into @num_parents_32
+  *                    field instead.
+  * @num_parents_32:   Number of clock parents if @num_parents field is
+  *                    set to 255.
   *
   * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS
   */
  struct ti_sci_msg_resp_get_clock_num_parents {
        struct ti_sci_msg_hdr hdr;
        u8 num_parents;
+       u32 num_parents_32;
  } __packed;
  
  /**
   * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
   *            allowable programmed frequency and does not account for clock
   *            tolerances and jitter.
-  * @clk_id:   Clock identifier for the device for this request.
+  * @clk_id:   Clock identifier for the device for this request. Set to
+  *            255 if clock identifier is greater than or equal to 255.
+  * @clk_id_32:        Clock identifier if @clk_id is set to 255.
   *
   * NOTE: Normally clock frequency management is automatically done by TISCI
   * entity. In case of specific requests, TISCI evaluates capability to achieve
@@@ -380,6 -414,7 +414,7 @@@ struct ti_sci_msg_req_query_clock_freq 
        u64 target_freq_hz;
        u64 max_freq_hz;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
@@@ -407,7 -442,9 +442,9 @@@ struct ti_sci_msg_resp_query_clock_fre
   * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
   *            allowable programmed frequency and does not account for clock
   *            tolerances and jitter.
-  * @clk_id:   Clock identifier for the device for this request.
+  * @clk_id:   Clock identifier for the device for this request. Set to
+  *            255 if clock ID is greater than or equal to 255.
+  * @clk_id_32:        Clock identifier if @clk_id field is set to 255.
   *
   * NOTE: Normally clock frequency management is automatically done by TISCI
   * entity. In case of specific requests, TISCI evaluates capability to achieve
@@@ -436,13 -473,16 +473,16 @@@ struct ti_sci_msg_req_set_clock_freq 
        u64 target_freq_hz;
        u64 max_freq_hz;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
   * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency
   * @hdr:      Generic Header
   * @dev_id:   Device identifier this request is for
-  * @clk_id:   Clock identifier for the device for this request.
+  * @clk_id:   Clock identifier for the device for this request. Set to
+  *            255 if clock ID is greater than or equal to 255.
+  * @clk_id_32:        Clock identifier if @clk_id field is set to 255.
   *
   * NOTE: Normally clock frequency management is automatically done by TISCI
   * entity. In some cases, clock frequencies are configured by host.
@@@ -454,6 -494,7 +494,7 @@@ struct ti_sci_msg_req_get_clock_freq 
        struct ti_sci_msg_hdr hdr;
        u32 dev_id;
        u8 clk_id;
+       u32 clk_id_32;
  } __packed;
  
  /**
index 3b245e3df8da9d281252fc6cbd43e4a10d7b13ac,a0422f62c04090c95c62eda882188c986ec902fe..de550ea56eeb0ef32e98a8549a14d750ab4d4dfb
@@@ -1,7 -1,16 +1,7 @@@
 +/* SPDX-License-Identifier: GPL-2.0-or-later */
  /*
   * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
   * Author: Jeffy Chen <jeffy.chen@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3228_H
@@@ -64,6 -73,7 +64,7 @@@
  #define SCLK_WIFI             141
  #define SCLK_OTGPHY0          142
  #define SCLK_OTGPHY1          143
+ #define SCLK_HDMI_PHY         144
  
  /* dclk gates */
  #define DCLK_VOP              190
index afb8113403828a59fb01a63e5035c379a11aee45,6ad54c39f8da0c0925e8b95bec208d185bc374d2..555b4ff660ae6d3fa5b53bbf27d3b28a99d6a6c2
@@@ -1,7 -1,16 +1,7 @@@
 +/* SPDX-License-Identifier: GPL-2.0-or-later */
  /*
   * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
   * Author: Elaine <zhangqing@rock-chips.com>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License as published by
 - * the Free Software Foundation; either version 2 of the License, or
 - * (at your option) any later version.
 - *
 - * This program is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - * GNU General Public License for more details.
   */
  
  #ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3328_H
  #define PCLK_DCF              233
  #define PCLK_SARADC           234
  #define PCLK_ACODECPHY                235
+ #define PCLK_WDT              236
  
  /* hclk gates */
  #define HCLK_PERI             308
diff --combined include/linux/clk.h
index c8e3325868bd371eb3e174d9f95ea09f5fa9111c,5e7b2dd84965a44991a0cc3274ec1ab876406832..3c096c7a51dc6105bbc90abab34f01786e36beca
@@@ -1,10 -1,13 +1,10 @@@
 +/* SPDX-License-Identifier: GPL-2.0-only */
  /*
   *  linux/include/linux/clk.h
   *
   *  Copyright (C) 2004 ARM Limited.
   *  Written by Deep Blue Solutions Limited.
   *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
 - *
 - * This program is free software; you can redistribute it and/or modify
 - * it under the terms of the GNU General Public License version 2 as
 - * published by the Free Software Foundation.
   */
  #ifndef __LINUX_CLK_H
  #define __LINUX_CLK_H
@@@ -329,6 -332,19 +329,19 @@@ int __must_check clk_bulk_get(struct de
   */
  int __must_check clk_bulk_get_all(struct device *dev,
                                  struct clk_bulk_data **clks);
+ /**
+  * clk_bulk_get_optional - lookup and obtain a number of references to clock producer
+  * @dev: device for clock "consumer"
+  * @num_clks: the number of clk_bulk_data
+  * @clks: the clk_bulk_data table of consumer
+  *
+  * Behaves the same as clk_bulk_get() except where there is no clock producer.
+  * In this case, instead of returning -ENOENT, the function returns 0 and
+  * NULL for a clk for which a clock producer could not be determined.
+  */
+ int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
+                                      struct clk_bulk_data *clks);
  /**
   * devm_clk_bulk_get - managed get multiple clk consumers
   * @dev: device for clock "consumer"
   */
  int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
                                   struct clk_bulk_data *clks);
+ /**
+  * devm_clk_bulk_get_optional - managed get multiple optional consumer clocks
+  * @dev: device for clock "consumer"
+  * @clks: pointer to the clk_bulk_data table of consumer
+  *
+  * Behaves the same as devm_clk_bulk_get() except where there is no clock
+  * producer.  In this case, instead of returning -ENOENT, the function returns
+  * NULL for given clk. It is assumed all clocks in clk_bulk_data are optional.
+  *
+  * Returns 0 if all clocks specified in clk_bulk_data table are obtained
+  * successfully or for any clk there was no clk provider available, otherwise
+  * returns valid IS_ERR() condition containing errno.
+  * The implementation uses @dev and @clk_bulk_data.id to determine the
+  * clock consumer, and thereby the clock producer.
+  * The clock returned is stored in each @clk_bulk_data.clk field.
+  *
+  * Drivers must assume that the clock source is not enabled.
+  *
+  * clk_bulk_get should not be called from within interrupt context.
+  */
+ int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
+                                           struct clk_bulk_data *clks);
  /**
   * devm_clk_bulk_get_all - managed get multiple clk consumers
   * @dev: device for clock "consumer"
@@@ -715,6 -753,12 +750,12 @@@ static inline int __must_check clk_bulk
        return 0;
  }
  
+ static inline int __must_check clk_bulk_get_optional(struct device *dev,
+                               int num_clks, struct clk_bulk_data *clks)
+ {
+       return 0;
+ }
  static inline int __must_check clk_bulk_get_all(struct device *dev,
                                         struct clk_bulk_data **clks)
  {
@@@ -738,6 -782,12 +779,12 @@@ static inline int __must_check devm_clk
        return 0;
  }
  
+ static inline int __must_check devm_clk_bulk_get_optional(struct device *dev,
+                               int num_clks, struct clk_bulk_data *clks)
+ {
+       return 0;
+ }
  static inline int __must_check devm_clk_bulk_get_all(struct device *dev,
                                                     struct clk_bulk_data **clks)
  {