]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Mar 2016 13:06:45 +0000 (06:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 23 Mar 2016 13:06:45 +0000 (06:06 -0700)
Pull clk updates from Stephen Boyd:
 "The clk changes for this release cycle are mostly dominated by new
  device support in terms of LoC, but there has been some cleanup in the
  core as well as the usual minor clk additions to various drivers.

  Core:
   - parent tracking has been simplified
   - CLK_IS_ROOT is now a no-op flag, cleaning up drivers has started
   - of_clk_init() doesn't consider disabled DT nodes anymore
   - clk_unregister() had an error path bug squashed
   - of_clk_get_parent_count() has been fixed to only return unsigned ints
   - HAVE_MACH_CLKDEV is removed now that the last arch user (ARM) is gone

  New Drivers:
   - NXP LPC18xx creg
   - QCOM IPQ4019 GCC
   - TI dm814x ADPLL
   - i.MX6QP

  Updates:
   - Cyngus audio clks found on Broadcom iProc devices
   - Non-critical fixes for BCM2385 PLLs
   - Samsung exynos5433 updates for clk id errors, HDMI support,
     suspend/resume simplifications
   - USB, CAN, LVDS, and FCP clks on shmobile devices
   - sunxi got support for more clks on new SoCs and went through a
     minor refactoring/rewrite to use a simpler factor clk construct
   - rockchip added some more clk ids and added suport for fraction
     dividers
   - QCOM GDSCs in msm8996
   - A new devm helper to make adding custom actions simpler (acked by Greg)"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (197 commits)
  clk: bcm2835: fix check of error code returned by devm_ioremap_resource()
  clk: renesas: div6: use RENESAS for #define
  clk: renesas: Rename header file renesas.h
  clk: max77{686,802}: Remove CLK_IS_ROOT
  clk: versatile: Remove CLK_IS_ROOT
  clk: sunxi: Remove use of variable length array
  clk: fixed-rate: Remove CLK_IS_ROOT
  clk: qcom: Remove CLK_IS_ROOT
  doc: dt: add documentation for lpc1850-creg-clk driver
  clk: add lpc18xx creg clk driver
  clk: lpc32xx: fix compilation warning
  clk: xgene: Add missing parenthesis when clearing divider value
  clk: mb86s7x: Remove CLK_IS_ROOT
  clk: x86: Remove clkdev.h and clk.h includes
  clk: x86: Remove CLK_IS_ROOT
  clk: mvebu: Remove CLK_IS_ROOT
  clk: renesas: move drivers to renesas directory
  clk: si5{14,351,70}: Remove CLK_IS_ROOT
  clk: scpi: Remove CLK_IS_ROOT
  clk: s2mps11: Remove CLK_IS_ROOT
  ...

16 files changed:
1  2 
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-shmobile/setup-rcar-gen2.c
arch/mips/Kconfig
drivers/clk/at91/clk-generated.c
drivers/clk/at91/clk-main.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/clk-slow.c
drivers/clk/at91/clk-smd.c
drivers/clk/at91/clk-usb.c
drivers/clk/pxa/clk-pxa25x.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/pxa/clk-pxa3xx.c
drivers/clk/rockchip/clk-rk3036.c
include/linux/device.h

index 0350f79f57da075d8c58757d7224a1766edff892,cb27a8f5a8e212c7a3e32dbf5a7d376d3e05dfac..412809c60d01901087f67ed1107f2538ae3a8f1b
@@@ -64,7 -64,7 +64,7 @@@
                        gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_POWER>;
                        debounce-interval = <100>;
 -                      gpio-key,wakeup;
 +                      wakeup-source;
                };
        };
  
        i2c-scl-rising-time-ns = <1000>;
  };
  
 -&power {
 -      assigned-clocks = <&cru SCLK_EDP_24M>;
 -      assigned-clock-parents = <&xin24m>;
 -};
 -
  &pwm1 {
        status = "okay";
  };
        status = "okay";
  
        assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
-       assigned-clock-parents = <&cru SCLK_OTGPHY0>;
+       assigned-clock-parents = <&usbphy0>;
        dr_mode = "host";
  };
  
index b003e3afd693008b9023cdf58911e438ceee30ea,71e97daeae708c84f73af828582e9c6d86449181..348044ea650c6725e07b910cc810e4e1ae566774
@@@ -3,6 -3,7 +3,6 @@@ menuconfig ARCH_MVEB
        depends on ARCH_MULTI_V7 || ARCH_MULTI_V5
        select ARCH_SUPPORTS_BIG_ENDIAN
        select CLKSRC_MMIO
 -      select GENERIC_IRQ_CHIP
        select PINCTRL
        select PLAT_ORION
        select SOC_BUS
@@@ -28,10 -29,10 +28,11 @@@ config MACH_ARMADA_37
        bool "Marvell Armada 370 boards"
        depends on ARCH_MULTI_V7
        select ARMADA_370_CLK
 +      select ARMADA_370_XP_IRQ
        select CPU_PJ4B
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_370
+       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 370 SoC with device tree.
@@@ -39,7 -40,6 +40,7 @@@
  config MACH_ARMADA_375
        bool "Marvell Armada 375 boards"
        depends on ARCH_MULTI_V7
 +      select ARMADA_370_XP_IRQ
        select ARM_ERRATA_720789
        select ARM_ERRATA_753970
        select ARM_GIC
@@@ -49,6 -49,7 +50,7 @@@
        select HAVE_SMP
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_375
+       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 375 SoC with device tree.
@@@ -59,13 -60,13 +61,14 @@@ config MACH_ARMADA_38
        select ARM_ERRATA_720789
        select ARM_ERRATA_753970
        select ARM_GIC
 +      select ARMADA_370_XP_IRQ
        select ARMADA_38X_CLK
        select HAVE_ARM_SCU
        select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_38X
+       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 380/385 SoC with device tree.
@@@ -74,7 -75,6 +77,7 @@@ config MACH_ARMADA_39
        bool "Marvell Armada 39x boards"
        depends on ARCH_MULTI_V7
        select ARM_GIC
 +      select ARMADA_370_XP_IRQ
        select ARMADA_39X_CLK
        select CACHE_L2X0
        select HAVE_ARM_SCU
@@@ -89,7 -89,6 +92,7 @@@
  config MACH_ARMADA_XP
        bool "Marvell Armada XP boards"
        depends on ARCH_MULTI_V7
 +      select ARMADA_370_XP_IRQ
        select ARMADA_XP_CLK
        select CPU_PJ4B
        select MACH_MVEBU_V7
index 6d0ebdfb03a292166dfa3b0979ce810993ecf658,949b402c0f19cfc04f12b02550232396cd3c414e..1c6fd11c2f824019b4e22f657d7a5d326d38816d
@@@ -15,7 -15,7 +15,7 @@@
   * GNU General Public License for more details.
   */
  
- #include <linux/clk/shmobile.h>
+ #include <linux/clk/renesas.h>
  #include <linux/clocksource.h>
  #include <linux/device.h>
  #include <linux/dma-contiguous.h>
@@@ -182,6 -182,8 +182,6 @@@ static int __init rcar_gen2_scan_mem(un
        return 0;
  }
  
 -struct cma *rcar_gen2_dma_contiguous;
 -
  void __init rcar_gen2_reserve(void)
  {
        struct memory_reserve_config mrc;
  
        of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
  #ifdef CONFIG_DMA_CMA
 -      if (mrc.size && memblock_is_region_memory(mrc.base, mrc.size))
 +      if (mrc.size && memblock_is_region_memory(mrc.base, mrc.size)) {
 +              static struct cma *rcar_gen2_dma_contiguous;
 +
                dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
                                            &rcar_gen2_dma_contiguous, true);
 +      }
  #endif
  }
diff --combined arch/mips/Kconfig
index 7c4a4ce356033c6a2aa05fe7fe306714c44689cb,0d5d785be39fc2bcf21e87ac90be1adfa6478031..2018c2b0e078f9880bca0d2bb497e2dd271196d5
@@@ -151,7 -151,6 +151,7 @@@ config BMIPS_GENERI
        select CSRC_R4K
        select SYNC_R4K
        select COMMON_CLK
 +      select BCM6345_L1_IRQ
        select BCM7038_L1_IRQ
        select BCM7120_L2_IRQ
        select BRCMSTB_L2_IRQ
@@@ -328,7 -327,6 +328,6 @@@ config LANTI
        select ARCH_REQUIRE_GPIOLIB
        select SWAP_IO_SPACE
        select BOOT_RAW
-       select HAVE_MACH_CLKDEV
        select CLKDEV_LOOKUP
        select USE_OF
        select PINCTRL
@@@ -590,7 -588,6 +589,6 @@@ config RALIN
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_MIPS16
        select SYS_HAS_EARLY_PRINTK
-       select HAVE_MACH_CLKDEV
        select CLKDEV_LOOKUP
        select ARCH_HAS_RESET_CONTROLLER
        select RESET_CONTROLLER
@@@ -2086,7 -2083,7 +2084,7 @@@ config PAGE_SIZE_32K
  
  config PAGE_SIZE_64KB
        bool "64kB"
 -      depends on !CPU_R3000 && !CPU_TX39XX
 +      depends on !CPU_R3000 && !CPU_TX39XX && !CPU_R6000
        help
          Using 64kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available on
@@@ -2170,6 -2167,7 +2168,6 @@@ config MIPS_MT_SM
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_IRQ_EI
        select SYNC_R4K
 -      select MIPS_GIC_IPI
        select MIPS_MT
        select SMP
        select SMP_UP
@@@ -2267,6 -2265,7 +2265,6 @@@ config MIPS_VPE_APSP_API_M
  config MIPS_CMP
        bool "MIPS CMP framework support (DEPRECATED)"
        depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
 -      select MIPS_GIC_IPI
        select SMP
        select SYNC_R4K
        select SYS_SUPPORTS_SMP
@@@ -2286,6 -2285,7 +2284,6 @@@ config MIPS_CP
        select MIPS_CM
        select MIPS_CPC
        select MIPS_CPS_PM if HOTPLUG_CPU
 -      select MIPS_GIC_IPI
        select SMP
        select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
        select SYS_SUPPORTS_HOTPLUG_CPU
@@@ -2303,6 -2303,9 +2301,6 @@@ config MIPS_CPS_P
        select MIPS_CPC
        bool
  
 -config MIPS_GIC_IPI
 -      bool
 -
  config MIPS_CM
        bool
  
@@@ -2871,6 -2874,8 +2869,6 @@@ config PCI_DOMAIN
  
  source "drivers/pci/Kconfig"
  
 -source "drivers/pci/pcie/Kconfig"
 -
  #
  # ISA support is now enabled via select.  Too many systems still have the one
  # or other ISA chip on the board that users don't know about so don't expect
@@@ -2930,6 -2935,8 +2928,6 @@@ config ZONE_DMA3
  
  source "drivers/pcmcia/Kconfig"
  
 -source "drivers/pci/hotplug/Kconfig"
 -
  config RAPIDIO
        tristate "RapidIO support"
        depends on PCI
index 4ad3298eb3725f95c17fb44a45286dda6323aa12,f82b16a65dee1b09cf26a669906b579eaba1b300..e1aa210dd7aa6a6bf3ca40bb76f31f36407eb116
@@@ -15,8 -15,8 +15,8 @@@
  #include <linux/clkdev.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/io.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
@@@ -28,9 -28,8 +28,9 @@@
  
  struct clk_generated {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
        struct clk_range range;
 +      spinlock_t *lock;
        u32 id;
        u32 gckdiv;
        u8 parent_id;
  static int clk_generated_enable(struct clk_hw *hw)
  {
        struct clk_generated *gck = to_clk_generated(hw);
 -      struct at91_pmc *pmc = gck->pmc;
 -      u32 tmp;
 +      unsigned long flags;
  
        pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
                 __func__, gck->gckdiv, gck->parent_id);
  
 -      pmc_lock(pmc);
 -      pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
 -      tmp = pmc_read(pmc, AT91_PMC_PCR) &
 -                      ~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK);
 -      pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id)
 -                                       | AT91_PMC_PCR_CMD
 -                                       | AT91_PMC_PCR_GCKDIV(gck->gckdiv)
 -                                       | AT91_PMC_PCR_GCKEN);
 -      pmc_unlock(pmc);
 +      spin_lock_irqsave(gck->lock, flags);
 +      regmap_write(gck->regmap, AT91_PMC_PCR,
 +                   (gck->id & AT91_PMC_PCR_PID_MASK));
 +      regmap_update_bits(gck->regmap, AT91_PMC_PCR,
 +                         AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK |
 +                         AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
 +                         AT91_PMC_PCR_GCKCSS(gck->parent_id) |
 +                         AT91_PMC_PCR_CMD |
 +                         AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
 +                         AT91_PMC_PCR_GCKEN);
 +      spin_unlock_irqrestore(gck->lock, flags);
        return 0;
  }
  
  static void clk_generated_disable(struct clk_hw *hw)
  {
        struct clk_generated *gck = to_clk_generated(hw);
 -      struct at91_pmc *pmc = gck->pmc;
 -      u32 tmp;
 -
 -      pmc_lock(pmc);
 -      pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
 -      tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN;
 -      pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
 -      pmc_unlock(pmc);
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(gck->lock, flags);
 +      regmap_write(gck->regmap, AT91_PMC_PCR,
 +                   (gck->id & AT91_PMC_PCR_PID_MASK));
 +      regmap_update_bits(gck->regmap, AT91_PMC_PCR,
 +                         AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
 +                         AT91_PMC_PCR_CMD);
 +      spin_unlock_irqrestore(gck->lock, flags);
  }
  
  static int clk_generated_is_enabled(struct clk_hw *hw)
  {
        struct clk_generated *gck = to_clk_generated(hw);
 -      struct at91_pmc *pmc = gck->pmc;
 -      int ret;
 +      unsigned long flags;
 +      unsigned int status;
  
 -      pmc_lock(pmc);
 -      pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
 -      ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN);
 -      pmc_unlock(pmc);
 +      spin_lock_irqsave(gck->lock, flags);
 +      regmap_write(gck->regmap, AT91_PMC_PCR,
 +                   (gck->id & AT91_PMC_PCR_PID_MASK));
 +      regmap_read(gck->regmap, AT91_PMC_PCR, &status);
 +      spin_unlock_irqrestore(gck->lock, flags);
  
 -      return ret;
 +      return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
  }
  
  static unsigned long
@@@ -218,14 -214,13 +218,14 @@@ static const struct clk_ops generated_o
   */
  static void clk_generated_startup(struct clk_generated *gck)
  {
 -      struct at91_pmc *pmc = gck->pmc;
        u32 tmp;
 +      unsigned long flags;
  
 -      pmc_lock(pmc);
 -      pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
 -      tmp = pmc_read(pmc, AT91_PMC_PCR);
 -      pmc_unlock(pmc);
 +      spin_lock_irqsave(gck->lock, flags);
 +      regmap_write(gck->regmap, AT91_PMC_PCR,
 +                   (gck->id & AT91_PMC_PCR_PID_MASK));
 +      regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
 +      spin_unlock_irqrestore(gck->lock, flags);
  
        gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
                                        >> AT91_PMC_PCR_GCKCSS_OFFSET;
  }
  
  static struct clk * __init
 -at91_clk_register_generated(struct at91_pmc *pmc, const char *name,
 -                          const char **parent_names, u8 num_parents,
 +at91_clk_register_generated(struct regmap *regmap,  spinlock_t *lock, const char
 +                          *name, const char **parent_names, u8 num_parents,
                            u8 id, const struct clk_range *range)
  {
        struct clk_generated *gck;
  
        gck->id = id;
        gck->hw.init = &init;
 -      gck->pmc = pmc;
 +      gck->regmap = regmap;
 +      gck->lock = lock;
        gck->range = *range;
  
        clk = clk_register(NULL, &gck->hw);
        return clk;
  }
  
 -void __init of_sama5d2_clk_generated_setup(struct device_node *np,
 -                                         struct at91_pmc *pmc)
 +void __init of_sama5d2_clk_generated_setup(struct device_node *np)
  {
        int num;
        u32 id;
        const char *name;
        struct clk *clk;
-       int num_parents;
+       unsigned int num_parents;
        const char *parent_names[GENERATED_SOURCE_MAX];
        struct device_node *gcknp;
        struct clk_range range = CLK_RANGE(0, 0);
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > GENERATED_SOURCE_MAX)
+       if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
        if (!num || num > PERIPHERAL_MAX)
                return;
  
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
        for_each_child_of_node(np, gcknp) {
                if (of_property_read_u32(gcknp, "reg", &id))
                        continue;
                of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
                                      &range);
  
 -              clk = at91_clk_register_generated(pmc, name, parent_names,
 -                                                num_parents, id, &range);
 +              clk = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
 +                                                parent_names, num_parents,
 +                                                id, &range);
                if (IS_ERR(clk))
                        continue;
  
                of_clk_add_provider(gcknp, of_clk_src_simple_get, clk);
        }
  }
 +CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
 +             of_sama5d2_clk_generated_setup);
index 4bfc94d6c26ea3643aa87caeb359f7fc363aedf6,b9bdfd8e4e6fccd5037095842cec774fe4a7932f..58b5baca670c3416fe0fc1733088f7526349005c
  #include <linux/clk/at91_pmc.h>
  #include <linux/delay.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/of_irq.h>
 -#include <linux/io.h>
 -#include <linux/interrupt.h>
 -#include <linux/irq.h>
 -#include <linux/sched.h>
 -#include <linux/wait.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
  
  struct clk_main_osc {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 -      unsigned int irq;
 -      wait_queue_head_t wait;
 +      struct regmap *regmap;
  };
  
  #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
  
  struct clk_main_rc_osc {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 -      unsigned int irq;
 -      wait_queue_head_t wait;
 +      struct regmap *regmap;
        unsigned long frequency;
        unsigned long accuracy;
  };
  
  struct clk_rm9200_main {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
  };
  
  #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
  
  struct clk_sam9x5_main {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 -      unsigned int irq;
 -      wait_queue_head_t wait;
 +      struct regmap *regmap;
        u8 parent;
  };
  
  #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
  
 -static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id)
 +static inline bool clk_main_osc_ready(struct regmap *regmap)
  {
 -      struct clk_main_osc *osc = dev_id;
 +      unsigned int status;
  
 -      wake_up(&osc->wait);
 -      disable_irq_nosync(osc->irq);
 +      regmap_read(regmap, AT91_PMC_SR, &status);
  
 -      return IRQ_HANDLED;
 +      return status & AT91_PMC_MOSCS;
  }
  
  static int clk_main_osc_prepare(struct clk_hw *hw)
  {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 +      struct regmap *regmap = osc->regmap;
        u32 tmp;
  
 -      tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
 +      regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 +      tmp &= ~MOR_KEY_MASK;
 +
        if (tmp & AT91_PMC_OSCBYPASS)
                return 0;
  
        if (!(tmp & AT91_PMC_MOSCEN)) {
                tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
 -              pmc_write(pmc, AT91_CKGR_MOR, tmp);
 +              regmap_write(regmap, AT91_CKGR_MOR, tmp);
        }
  
 -      while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
 -              enable_irq(osc->irq);
 -              wait_event(osc->wait,
 -                         pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
 -      }
 +      while (!clk_main_osc_ready(regmap))
 +              cpu_relax();
  
        return 0;
  }
  static void clk_main_osc_unprepare(struct clk_hw *hw)
  {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 -      u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
 +      struct regmap *regmap = osc->regmap;
 +      u32 tmp;
  
 +      regmap_read(regmap, AT91_CKGR_MOR, &tmp);
        if (tmp & AT91_PMC_OSCBYPASS)
                return;
  
                return;
  
        tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
 -      pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
 +      regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
  }
  
  static int clk_main_osc_is_prepared(struct clk_hw *hw)
  {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 -      u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
 +      struct regmap *regmap = osc->regmap;
 +      u32 tmp, status;
  
 +      regmap_read(regmap, AT91_CKGR_MOR, &tmp);
        if (tmp & AT91_PMC_OSCBYPASS)
                return 1;
  
 -      return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) &&
 -                (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN));
 +      regmap_read(regmap, AT91_PMC_SR, &status);
 +
 +      return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN);
  }
  
  static const struct clk_ops main_osc_ops = {
  };
  
  static struct clk * __init
 -at91_clk_register_main_osc(struct at91_pmc *pmc,
 -                         unsigned int irq,
 +at91_clk_register_main_osc(struct regmap *regmap,
                           const char *name,
                           const char *parent_name,
                           bool bypass)
  {
 -      int ret;
        struct clk_main_osc *osc;
        struct clk *clk = NULL;
        struct clk_init_data init;
  
 -      if (!pmc || !irq || !name || !parent_name)
 +      if (!name || !parent_name)
                return ERR_PTR(-EINVAL);
  
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
        init.flags = CLK_IGNORE_UNUSED;
  
        osc->hw.init = &init;
 -      osc->pmc = pmc;
 -      osc->irq = irq;
 -
 -      init_waitqueue_head(&osc->wait);
 -      irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
 -      ret = request_irq(osc->irq, clk_main_osc_irq_handler,
 -                        IRQF_TRIGGER_HIGH, name, osc);
 -      if (ret) {
 -              kfree(osc);
 -              return ERR_PTR(ret);
 -      }
 +      osc->regmap = regmap;
  
        if (bypass)
 -              pmc_write(pmc, AT91_CKGR_MOR,
 -                        (pmc_read(pmc, AT91_CKGR_MOR) &
 -                         ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) |
 -                        AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
 +              regmap_update_bits(regmap,
 +                                 AT91_CKGR_MOR, MOR_KEY_MASK |
 +                                 AT91_PMC_MOSCEN,
 +                                 AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
  
        clk = clk_register(NULL, &osc->hw);
 -      if (IS_ERR(clk)) {
 -              free_irq(irq, osc);
 +      if (IS_ERR(clk))
                kfree(osc);
 -      }
  
        return clk;
  }
  
 -void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
 -                                           struct at91_pmc *pmc)
 +static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
  {
        struct clk *clk;
 -      unsigned int irq;
        const char *name = np->name;
        const char *parent_name;
 +      struct regmap *regmap;
        bool bypass;
  
        of_property_read_string(np, "clock-output-names", &name);
        bypass = of_property_read_bool(np, "atmel,osc-bypass");
        parent_name = of_clk_get_parent_name(np, 0);
  
 -      irq = irq_of_parse_and_map(np, 0);
 -      if (!irq)
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
                return;
  
 -      clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass);
 +      clk = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
 +             of_at91rm9200_clk_main_osc_setup);
  
 -static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id)
 +static bool clk_main_rc_osc_ready(struct regmap *regmap)
  {
 -      struct clk_main_rc_osc *osc = dev_id;
 +      unsigned int status;
  
 -      wake_up(&osc->wait);
 -      disable_irq_nosync(osc->irq);
 +      regmap_read(regmap, AT91_PMC_SR, &status);
  
 -      return IRQ_HANDLED;
 +      return status & AT91_PMC_MOSCRCS;
  }
  
  static int clk_main_rc_osc_prepare(struct clk_hw *hw)
  {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 -      u32 tmp;
 +      struct regmap *regmap = osc->regmap;
 +      unsigned int mor;
  
 -      tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
 +      regmap_read(regmap, AT91_CKGR_MOR, &mor);
  
 -      if (!(tmp & AT91_PMC_MOSCRCEN)) {
 -              tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY;
 -              pmc_write(pmc, AT91_CKGR_MOR, tmp);
 -      }
 +      if (!(mor & AT91_PMC_MOSCRCEN))
 +              regmap_update_bits(regmap, AT91_CKGR_MOR,
 +                                 MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
 +                                 AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
  
 -      while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) {
 -              enable_irq(osc->irq);
 -              wait_event(osc->wait,
 -                         pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS);
 -      }
 +      while (!clk_main_rc_osc_ready(regmap))
 +              cpu_relax();
  
        return 0;
  }
  static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
  {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 -      u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
 +      struct regmap *regmap = osc->regmap;
 +      unsigned int mor;
 +
 +      regmap_read(regmap, AT91_CKGR_MOR, &mor);
  
 -      if (!(tmp & AT91_PMC_MOSCRCEN))
 +      if (!(mor & AT91_PMC_MOSCRCEN))
                return;
  
 -      tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN);
 -      pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
 +      regmap_update_bits(regmap, AT91_CKGR_MOR,
 +                         MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
  }
  
  static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
  {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 -      struct at91_pmc *pmc = osc->pmc;
 +      struct regmap *regmap = osc->regmap;
 +      unsigned int mor, status;
  
 -      return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) &&
 -                (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN));
 +      regmap_read(regmap, AT91_CKGR_MOR, &mor);
 +      regmap_read(regmap, AT91_PMC_SR, &status);
 +
 +      return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
  }
  
  static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
@@@ -272,15 -294,17 +272,15 @@@ static const struct clk_ops main_rc_osc
  };
  
  static struct clk * __init
 -at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
 -                            unsigned int irq,
 +at91_clk_register_main_rc_osc(struct regmap *regmap,
                              const char *name,
                              u32 frequency, u32 accuracy)
  {
 -      int ret;
        struct clk_main_rc_osc *osc;
        struct clk *clk = NULL;
        struct clk_init_data init;
  
 -      if (!pmc || !irq || !name || !frequency)
 +      if (!name || !frequency)
                return ERR_PTR(-EINVAL);
  
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
        init.ops = &main_rc_osc_ops;
        init.parent_names = NULL;
        init.num_parents = 0;
-       init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
+       init.flags = CLK_IGNORE_UNUSED;
  
        osc->hw.init = &init;
 -      osc->pmc = pmc;
 -      osc->irq = irq;
 +      osc->regmap = regmap;
        osc->frequency = frequency;
        osc->accuracy = accuracy;
  
 -      init_waitqueue_head(&osc->wait);
 -      irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
 -      ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler,
 -                        IRQF_TRIGGER_HIGH, name, osc);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
        clk = clk_register(NULL, &osc->hw);
 -      if (IS_ERR(clk)) {
 -              free_irq(irq, osc);
 +      if (IS_ERR(clk))
                kfree(osc);
 -      }
  
        return clk;
  }
  
 -void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
 -                                              struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
  {
        struct clk *clk;
 -      unsigned int irq;
        u32 frequency = 0;
        u32 accuracy = 0;
        const char *name = np->name;
 +      struct regmap *regmap;
  
        of_property_read_string(np, "clock-output-names", &name);
        of_property_read_u32(np, "clock-frequency", &frequency);
        of_property_read_u32(np, "clock-accuracy", &accuracy);
  
 -      irq = irq_of_parse_and_map(np, 0);
 -      if (!irq)
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
                return;
  
 -      clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency,
 -                                          accuracy);
 +      clk = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
 +             of_at91sam9x5_clk_main_rc_osc_setup);
  
  
 -static int clk_main_probe_frequency(struct at91_pmc *pmc)
 +static int clk_main_probe_frequency(struct regmap *regmap)
  {
        unsigned long prep_time, timeout;
 -      u32 tmp;
 +      unsigned int mcfr;
  
        timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
        do {
                prep_time = jiffies;
 -              tmp = pmc_read(pmc, AT91_CKGR_MCFR);
 -              if (tmp & AT91_PMC_MAINRDY)
 +              regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
 +              if (mcfr & AT91_PMC_MAINRDY)
                        return 0;
                usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
        } while (time_before(prep_time, timeout));
        return -ETIMEDOUT;
  }
  
 -static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
 +static unsigned long clk_main_recalc_rate(struct regmap *regmap,
                                          unsigned long parent_rate)
  {
 -      u32 tmp;
 +      unsigned int mcfr;
  
        if (parent_rate)
                return parent_rate;
  
        pr_warn("Main crystal frequency not set, using approximate value\n");
 -      tmp = pmc_read(pmc, AT91_CKGR_MCFR);
 -      if (!(tmp & AT91_PMC_MAINRDY))
 +      regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
 +      if (!(mcfr & AT91_PMC_MAINRDY))
                return 0;
  
 -      return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
 +      return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
  }
  
  static int clk_rm9200_main_prepare(struct clk_hw *hw)
  {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
  
 -      return clk_main_probe_frequency(clkmain->pmc);
 +      return clk_main_probe_frequency(clkmain->regmap);
  }
  
  static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
  {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 +      unsigned int status;
 +
 +      regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
  
 -      return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY);
 +      return status & AT91_PMC_MAINRDY ? 1 : 0;
  }
  
  static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
  {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
  
 -      return clk_main_recalc_rate(clkmain->pmc, parent_rate);
 +      return clk_main_recalc_rate(clkmain->regmap, parent_rate);
  }
  
  static const struct clk_ops rm9200_main_ops = {
  };
  
  static struct clk * __init
 -at91_clk_register_rm9200_main(struct at91_pmc *pmc,
 +at91_clk_register_rm9200_main(struct regmap *regmap,
                              const char *name,
                              const char *parent_name)
  {
        struct clk *clk = NULL;
        struct clk_init_data init;
  
 -      if (!pmc || !name)
 +      if (!name)
                return ERR_PTR(-EINVAL);
  
        if (!parent_name)
        init.flags = 0;
  
        clkmain->hw.init = &init;
 -      clkmain->pmc = pmc;
 +      clkmain->regmap = regmap;
  
        clk = clk_register(NULL, &clkmain->hw);
        if (IS_ERR(clk))
        return clk;
  }
  
 -void __init of_at91rm9200_clk_main_setup(struct device_node *np,
 -                                       struct at91_pmc *pmc)
 +static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
  {
        struct clk *clk;
        const char *parent_name;
        const char *name = np->name;
 +      struct regmap *regmap;
  
        parent_name = of_clk_get_parent_name(np, 0);
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91_clk_register_rm9200_main(pmc, name, parent_name);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
 +      clk = at91_clk_register_rm9200_main(regmap, name, parent_name);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
 +             of_at91rm9200_clk_main_setup);
  
 -static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id)
 +static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
  {
 -      struct clk_sam9x5_main *clkmain = dev_id;
 +      unsigned int status;
  
 -      wake_up(&clkmain->wait);
 -      disable_irq_nosync(clkmain->irq);
 +      regmap_read(regmap, AT91_PMC_SR, &status);
  
 -      return IRQ_HANDLED;
 +      return status & AT91_PMC_MOSCSELS ? 1 : 0;
  }
  
  static int clk_sam9x5_main_prepare(struct clk_hw *hw)
  {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 -      struct at91_pmc *pmc = clkmain->pmc;
 +      struct regmap *regmap = clkmain->regmap;
  
 -      while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
 -              enable_irq(clkmain->irq);
 -              wait_event(clkmain->wait,
 -                         pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
 -      }
 +      while (!clk_sam9x5_main_ready(regmap))
 +              cpu_relax();
  
 -      return clk_main_probe_frequency(pmc);
 +      return clk_main_probe_frequency(regmap);
  }
  
  static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
  {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
  
 -      return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
 +      return clk_sam9x5_main_ready(clkmain->regmap);
  }
  
  static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
  {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
  
 -      return clk_main_recalc_rate(clkmain->pmc, parent_rate);
 +      return clk_main_recalc_rate(clkmain->regmap, parent_rate);
  }
  
  static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
  {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 -      struct at91_pmc *pmc = clkmain->pmc;
 -      u32 tmp;
 +      struct regmap *regmap = clkmain->regmap;
 +      unsigned int tmp;
  
        if (index > 1)
                return -EINVAL;
  
 -      tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
 +      regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 +      tmp &= ~MOR_KEY_MASK;
  
        if (index && !(tmp & AT91_PMC_MOSCSEL))
 -              pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
 +              regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
        else if (!index && (tmp & AT91_PMC_MOSCSEL))
 -              pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
 +              regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
  
 -      while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
 -              enable_irq(clkmain->irq);
 -              wait_event(clkmain->wait,
 -                         pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
 -      }
 +      while (!clk_sam9x5_main_ready(regmap))
 +              cpu_relax();
  
        return 0;
  }
  static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
  {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 +      unsigned int status;
 +
 +      regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
  
 -      return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN);
 +      return status & AT91_PMC_MOSCEN ? 1 : 0;
  }
  
  static const struct clk_ops sam9x5_main_ops = {
  };
  
  static struct clk * __init
 -at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
 -                            unsigned int irq,
 +at91_clk_register_sam9x5_main(struct regmap *regmap,
                              const char *name,
                              const char **parent_names,
                              int num_parents)
  {
 -      int ret;
        struct clk_sam9x5_main *clkmain;
        struct clk *clk = NULL;
        struct clk_init_data init;
 +      unsigned int status;
  
 -      if (!pmc || !irq || !name)
 +      if (!name)
                return ERR_PTR(-EINVAL);
  
        if (!parent_names || !num_parents)
        init.flags = CLK_SET_PARENT_GATE;
  
        clkmain->hw.init = &init;
 -      clkmain->pmc = pmc;
 -      clkmain->irq = irq;
 -      clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) &
 -                           AT91_PMC_MOSCEN);
 -      init_waitqueue_head(&clkmain->wait);
 -      irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
 -      ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler,
 -                        IRQF_TRIGGER_HIGH, name, clkmain);
 -      if (ret)
 -              return ERR_PTR(ret);
 +      clkmain->regmap = regmap;
 +      regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
 +      clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0;
  
        clk = clk_register(NULL, &clkmain->hw);
 -      if (IS_ERR(clk)) {
 -              free_irq(clkmain->irq, clkmain);
 +      if (IS_ERR(clk))
                kfree(clkmain);
 -      }
  
        return clk;
  }
  
 -void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
 -                                       struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
  {
        struct clk *clk;
        const char *parent_names[2];
-       int num_parents;
+       unsigned int num_parents;
 -      unsigned int irq;
        const char *name = np->name;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > 2)
+       if (num_parents == 0 || num_parents > 2)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      irq = irq_of_parse_and_map(np, 0);
 -      if (!irq)
 -              return;
 -
 -      clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names,
 +      clk = at91_clk_register_sam9x5_main(regmap, name, parent_names,
                                            num_parents);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
 +             of_at91sam9x5_clk_main_setup);
index 7d4a1864ea7c1b10fbbaf07e9acc33147f623ba4,016fe110b5baf3995e5f4a4100e246b1dec5ad40..d1021e106191d844876ed829f847e72c833c86cf
  #include <linux/clkdev.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/of_irq.h>
 -#include <linux/io.h>
 -#include <linux/wait.h>
 -#include <linux/sched.h>
 -#include <linux/interrupt.h>
 -#include <linux/irq.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
@@@ -39,26 -44,32 +39,26 @@@ struct clk_master_layout 
  
  struct clk_master {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 -      unsigned int irq;
 -      wait_queue_head_t wait;
 +      struct regmap *regmap;
        const struct clk_master_layout *layout;
        const struct clk_master_characteristics *characteristics;
  };
  
 -static irqreturn_t clk_master_irq_handler(int irq, void *dev_id)
 +static inline bool clk_master_ready(struct regmap *regmap)
  {
 -      struct clk_master *master = (struct clk_master *)dev_id;
 +      unsigned int status;
  
 -      wake_up(&master->wait);
 -      disable_irq_nosync(master->irq);
 +      regmap_read(regmap, AT91_PMC_SR, &status);
  
 -      return IRQ_HANDLED;
 +      return status & AT91_PMC_MCKRDY ? 1 : 0;
  }
 +
  static int clk_master_prepare(struct clk_hw *hw)
  {
        struct clk_master *master = to_clk_master(hw);
 -      struct at91_pmc *pmc = master->pmc;
  
 -      while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) {
 -              enable_irq(master->irq);
 -              wait_event(master->wait,
 -                         pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
 -      }
 +      while (!clk_master_ready(master->regmap))
 +              cpu_relax();
  
        return 0;
  }
@@@ -67,7 -78,7 +67,7 @@@ static int clk_master_is_prepared(struc
  {
        struct clk_master *master = to_clk_master(hw);
  
 -      return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
 +      return clk_master_ready(master->regmap);
  }
  
  static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
        u8 div;
        unsigned long rate = parent_rate;
        struct clk_master *master = to_clk_master(hw);
 -      struct at91_pmc *pmc = master->pmc;
        const struct clk_master_layout *layout = master->layout;
        const struct clk_master_characteristics *characteristics =
                                                master->characteristics;
 -      u32 tmp;
 +      unsigned int mckr;
  
 -      pmc_lock(pmc);
 -      tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask;
 -      pmc_unlock(pmc);
 +      regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
 +      mckr &= layout->mask;
  
 -      pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK;
 -      div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
 +      pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
 +      div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
  
        if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
                rate /= 3;
  static u8 clk_master_get_parent(struct clk_hw *hw)
  {
        struct clk_master *master = to_clk_master(hw);
 -      struct at91_pmc *pmc = master->pmc;
 +      unsigned int mckr;
  
 -      return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS;
 +      regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
 +
 +      return mckr & AT91_PMC_CSS;
  }
  
  static const struct clk_ops master_ops = {
  };
  
  static struct clk * __init
 -at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq,
 +at91_clk_register_master(struct regmap *regmap,
                const char *name, int num_parents,
                const char **parent_names,
                const struct clk_master_layout *layout,
                const struct clk_master_characteristics *characteristics)
  {
 -      int ret;
        struct clk_master *master;
        struct clk *clk = NULL;
        struct clk_init_data init;
  
 -      if (!pmc || !irq || !name || !num_parents || !parent_names)
 +      if (!name || !num_parents || !parent_names)
                return ERR_PTR(-EINVAL);
  
        master = kzalloc(sizeof(*master), GFP_KERNEL);
        master->hw.init = &init;
        master->layout = layout;
        master->characteristics = characteristics;
 -      master->pmc = pmc;
 -      master->irq = irq;
 -      init_waitqueue_head(&master->wait);
 -      irq_set_status_flags(master->irq, IRQ_NOAUTOEN);
 -      ret = request_irq(master->irq, clk_master_irq_handler,
 -                        IRQF_TRIGGER_HIGH, "clk-master", master);
 -      if (ret) {
 -              kfree(master);
 -              return ERR_PTR(ret);
 -      }
 +      master->regmap = regmap;
  
        clk = clk_register(NULL, &master->hw);
        if (IS_ERR(clk)) {
 -              free_irq(master->irq, master);
                kfree(master);
        }
  
@@@ -195,18 -217,18 +195,18 @@@ out_free_characteristics
  }
  
  static void __init
 -of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 +of_at91_clk_master_setup(struct device_node *np,
                         const struct clk_master_layout *layout)
  {
        struct clk *clk;
-       int num_parents;
+       unsigned int num_parents;
 -      unsigned int irq;
        const char *parent_names[MASTER_SOURCE_MAX];
        const char *name = np->name;
        struct clk_master_characteristics *characteristics;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
+       if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
        if (!characteristics)
                return;
  
 -      irq = irq_of_parse_and_map(np, 0);
 -      if (!irq)
 -              goto out_free_characteristics;
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
  
 -      clk = at91_clk_register_master(pmc, irq, name, num_parents,
 +      clk = at91_clk_register_master(regmap, name, num_parents,
                                       parent_names, layout,
                                       characteristics);
        if (IS_ERR(clk))
@@@ -234,16 -256,14 +234,16 @@@ out_free_characteristics
        kfree(characteristics);
  }
  
 -void __init of_at91rm9200_clk_master_setup(struct device_node *np,
 -                                         struct at91_pmc *pmc)
 +static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
  {
 -      of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout);
 +      of_at91_clk_master_setup(np, &at91rm9200_master_layout);
  }
 +CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
 +             of_at91rm9200_clk_master_setup);
  
 -void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
 -                                         struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
  {
 -      of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout);
 +      of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
 +             of_at91sam9x5_clk_master_setup);
index bc0be629671ba2fcc928f97efb136cd47f38f198,b955fb81876f8a31e739d48fe97b8ea13fe3d5b3..10f846cc8db172c5491ddc2508f7084ac5ef5e71
  #include <linux/clkdev.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/io.h>
 -#include <linux/wait.h>
 -#include <linux/sched.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
@@@ -22,7 -24,6 +22,7 @@@
  
  #define PROG_STATUS_MASK(id)  (1 << ((id) + 8))
  #define PROG_PRES_MASK                0x7
 +#define PROG_PRES(layout, pckr)       ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
  #define PROG_MAX_RM9200_CSS   3
  
  struct clk_programmable_layout {
@@@ -33,7 -34,7 +33,7 @@@
  
  struct clk_programmable {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
        u8 id;
        const struct clk_programmable_layout *layout;
  };
  static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
                                                  unsigned long parent_rate)
  {
 -      u32 pres;
        struct clk_programmable *prog = to_clk_programmable(hw);
 -      struct at91_pmc *pmc = prog->pmc;
 -      const struct clk_programmable_layout *layout = prog->layout;
 +      unsigned int pckr;
 +
 +      regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
  
 -      pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) &
 -             PROG_PRES_MASK;
 -      return parent_rate >> pres;
 +      return parent_rate >> PROG_PRES(prog->layout, pckr);
  }
  
  static int clk_programmable_determine_rate(struct clk_hw *hw,
@@@ -98,36 -101,36 +98,36 @@@ static int clk_programmable_set_parent(
  {
        struct clk_programmable *prog = to_clk_programmable(hw);
        const struct clk_programmable_layout *layout = prog->layout;
 -      struct at91_pmc *pmc = prog->pmc;
 -      u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask;
 +      unsigned int mask = layout->css_mask;
 +      unsigned int pckr = 0;
  
        if (layout->have_slck_mck)
 -              tmp &= AT91_PMC_CSSMCK_MCK;
 +              mask |= AT91_PMC_CSSMCK_MCK;
  
        if (index > layout->css_mask) {
 -              if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) {
 -                      tmp |= AT91_PMC_CSSMCK_MCK;
 -                      return 0;
 -              } else {
 +              if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck)
                        return -EINVAL;
 -              }
 +
 +              pckr |= AT91_PMC_CSSMCK_MCK;
        }
  
 -      pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index);
 +      regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr);
 +
        return 0;
  }
  
  static u8 clk_programmable_get_parent(struct clk_hw *hw)
  {
 -      u32 tmp;
 -      u8 ret;
        struct clk_programmable *prog = to_clk_programmable(hw);
 -      struct at91_pmc *pmc = prog->pmc;
        const struct clk_programmable_layout *layout = prog->layout;
 +      unsigned int pckr;
 +      u8 ret;
 +
 +      regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
 +
 +      ret = pckr & layout->css_mask;
  
 -      tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id));
 -      ret = tmp & layout->css_mask;
 -      if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret)
 +      if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret)
                ret = PROG_MAX_RM9200_CSS + 1;
  
        return ret;
@@@ -137,27 -140,26 +137,27 @@@ static int clk_programmable_set_rate(st
                                     unsigned long parent_rate)
  {
        struct clk_programmable *prog = to_clk_programmable(hw);
 -      struct at91_pmc *pmc = prog->pmc;
        const struct clk_programmable_layout *layout = prog->layout;
        unsigned long div = parent_rate / rate;
 +      unsigned int pckr;
        int shift = 0;
 -      u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) &
 -                ~(PROG_PRES_MASK << layout->pres_shift);
 +
 +      regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
  
        if (!div)
                return -EINVAL;
  
        shift = fls(div) - 1;
  
 -      if (div != (1<<shift))
 +      if (div != (1 << shift))
                return -EINVAL;
  
        if (shift >= PROG_PRES_MASK)
                return -EINVAL;
  
 -      pmc_write(pmc, AT91_PMC_PCKR(prog->id),
 -                tmp | (shift << layout->pres_shift));
 +      regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id),
 +                         PROG_PRES_MASK << layout->pres_shift,
 +                         shift << layout->pres_shift);
  
        return 0;
  }
@@@ -171,7 -173,7 +171,7 @@@ static const struct clk_ops programmabl
  };
  
  static struct clk * __init
 -at91_clk_register_programmable(struct at91_pmc *pmc,
 +at91_clk_register_programmable(struct regmap *regmap,
                               const char *name, const char **parent_names,
                               u8 num_parents, u8 id,
                               const struct clk_programmable_layout *layout)
        prog->id = id;
        prog->layout = layout;
        prog->hw.init = &init;
 -      prog->pmc = pmc;
 +      prog->regmap = regmap;
  
        clk = clk_register(NULL, &prog->hw);
        if (IS_ERR(clk))
@@@ -224,20 -226,19 +224,20 @@@ static const struct clk_programmable_la
  };
  
  static void __init
 -of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
 +of_at91_clk_prog_setup(struct device_node *np,
                       const struct clk_programmable_layout *layout)
  {
        int num;
        u32 id;
        struct clk *clk;
-       int num_parents;
+       unsigned int num_parents;
        const char *parent_names[PROG_SOURCE_MAX];
        const char *name;
        struct device_node *progclknp;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
+       if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
        if (!num || num > (PROG_ID_MAX + 1))
                return;
  
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
        for_each_child_of_node(np, progclknp) {
                if (of_property_read_u32(progclknp, "reg", &id))
                        continue;
                if (of_property_read_string(np, "clock-output-names", &name))
                        name = progclknp->name;
  
 -              clk = at91_clk_register_programmable(pmc, name,
 +              clk = at91_clk_register_programmable(regmap, name,
                                                     parent_names, num_parents,
                                                     id, layout);
                if (IS_ERR(clk))
  }
  
  
 -void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
 -                                       struct at91_pmc *pmc)
 +static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
  {
 -      of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout);
 +      of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
  }
 +CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
 +             of_at91rm9200_clk_prog_setup);
  
 -void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
 -                                        struct at91_pmc *pmc)
 +static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
  {
 -      of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout);
 +      of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
  }
 +CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
 +             of_at91sam9g45_clk_prog_setup);
  
 -void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
 -                                       struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
  {
 -      of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout);
 +      of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
 +             of_at91sam9x5_clk_prog_setup);
index 911e941f831848e07a449a85b83bb0569ed84d8c,402b45d38d253e466dd9ef083cfa0b2ff656eba2..61090b1146cfd93e1255eb40a4d690502f08c6f5
  
  #include <linux/clk-provider.h>
  #include <linux/clkdev.h>
 -#include <linux/slab.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/delay.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/of_irq.h>
 -#include <linux/io.h>
 -#include <linux/interrupt.h>
 -#include <linux/irq.h>
 -#include <linux/sched.h>
 -#include <linux/wait.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  #include "sckc.h"
@@@ -52,7 -58,7 +52,7 @@@ struct clk_slow_rc_osc 
  
  struct clk_sam9260_slow {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
  };
  
  #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
@@@ -245,7 -251,7 +245,7 @@@ at91_clk_register_slow_rc_osc(void __io
        init.ops = &slow_rc_osc_ops;
        init.parent_names = NULL;
        init.num_parents = 0;
-       init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
+       init.flags = CLK_IGNORE_UNUSED;
  
        osc->hw.init = &init;
        osc->sckcr = sckcr;
@@@ -360,11 -366,11 +360,11 @@@ void __init of_at91sam9x5_clk_slow_setu
  {
        struct clk *clk;
        const char *parent_names[2];
-       int num_parents;
+       unsigned int num_parents;
        const char *name = np->name;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > 2)
+       if (num_parents == 0 || num_parents > 2)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
  static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
  {
        struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
 +      unsigned int status;
  
 -      return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL);
 +      regmap_read(slowck->regmap, AT91_PMC_SR, &status);
 +
 +      return status & AT91_PMC_OSCSEL ? 1 : 0;
  }
  
  static const struct clk_ops sam9260_slow_ops = {
  };
  
  static struct clk * __init
 -at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
 +at91_clk_register_sam9260_slow(struct regmap *regmap,
                               const char *name,
                               const char **parent_names,
                               int num_parents)
        struct clk *clk = NULL;
        struct clk_init_data init;
  
 -      if (!pmc || !name)
 +      if (!name)
                return ERR_PTR(-EINVAL);
  
        if (!parent_names || !num_parents)
        init.flags = 0;
  
        slowck->hw.init = &init;
 -      slowck->pmc = pmc;
 +      slowck->regmap = regmap;
  
        clk = clk_register(NULL, &slowck->hw);
        if (IS_ERR(clk))
        return clk;
  }
  
 -void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
 -                                        struct at91_pmc *pmc)
 +static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
  {
        struct clk *clk;
        const char *parent_names[2];
-       int num_parents;
+       unsigned int num_parents;
        const char *name = np->name;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
        if (num_parents != 2)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91_clk_register_sam9260_slow(pmc, name, parent_names,
 +      clk = at91_clk_register_sam9260_slow(regmap, name, parent_names,
                                             num_parents);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +
 +CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
 +             of_at91sam9260_clk_slow_setup);
index e6948a52005a094dc3c2c23db365f9341fc9c98f,f525830ed5a16018fe1e20bed9777e7aa687ebeb..3c04b069d5b8f78975ee6af0b6a40d2fe3367e1a
@@@ -12,8 -12,8 +12,8 @@@
  #include <linux/clkdev.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/io.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
@@@ -24,7 -24,7 +24,7 @@@
  
  struct at91sam9x5_clk_smd {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
  };
  
  #define to_at91sam9x5_clk_smd(hw) \
  static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw,
                                                    unsigned long parent_rate)
  {
 -      u32 tmp;
 -      u8 smddiv;
        struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
 -      struct at91_pmc *pmc = smd->pmc;
 +      unsigned int smdr;
 +      u8 smddiv;
 +
 +      regmap_read(smd->regmap, AT91_PMC_SMD, &smdr);
 +      smddiv = (smdr & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT;
  
 -      tmp = pmc_read(pmc, AT91_PMC_SMD);
 -      smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT;
        return parent_rate / (smddiv + 1);
  }
  
@@@ -67,38 -67,40 +67,38 @@@ static long at91sam9x5_clk_smd_round_ra
  
  static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index)
  {
 -      u32 tmp;
        struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
 -      struct at91_pmc *pmc = smd->pmc;
  
        if (index > 1)
                return -EINVAL;
 -      tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS;
 -      if (index)
 -              tmp |= AT91_PMC_SMDS;
 -      pmc_write(pmc, AT91_PMC_SMD, tmp);
 +
 +      regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMDS,
 +                         index ? AT91_PMC_SMDS : 0);
 +
        return 0;
  }
  
  static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw)
  {
        struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
 -      struct at91_pmc *pmc = smd->pmc;
 +      unsigned int smdr;
  
 -      return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS;
 +      regmap_read(smd->regmap, AT91_PMC_SMD, &smdr);
 +
 +      return smdr & AT91_PMC_SMDS;
  }
  
  static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate,
                                       unsigned long parent_rate)
  {
 -      u32 tmp;
        struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
 -      struct at91_pmc *pmc = smd->pmc;
        unsigned long div = parent_rate / rate;
  
        if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1))
                return -EINVAL;
 -      tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV;
 -      tmp |= (div - 1) << SMD_DIV_SHIFT;
 -      pmc_write(pmc, AT91_PMC_SMD, tmp);
 +
 +      regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMD_DIV,
 +                         (div - 1) << SMD_DIV_SHIFT);
  
        return 0;
  }
@@@ -112,7 -114,7 +112,7 @@@ static const struct clk_ops at91sam9x5_
  };
  
  static struct clk * __init
 -at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name,
 +at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
                            const char **parent_names, u8 num_parents)
  {
        struct at91sam9x5_clk_smd *smd;
        init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
  
        smd->hw.init = &init;
 -      smd->pmc = pmc;
 +      smd->regmap = regmap;
  
        clk = clk_register(NULL, &smd->hw);
        if (IS_ERR(clk))
        return clk;
  }
  
 -void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
 -                                      struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
  {
        struct clk *clk;
-       int num_parents;
+       unsigned int num_parents;
        const char *parent_names[SMD_SOURCE_MAX];
        const char *name = np->name;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
+       if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91sam9x5_clk_register_smd(pmc, name, parent_names,
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
 +      clk = at91sam9x5_clk_register_smd(regmap, name, parent_names,
                                          num_parents);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
 +             of_at91sam9x5_clk_smd_setup);
index 650ca45892c0731cc7ecefe911ae32f0259951fa,be1c7f531837a65a2ac6d994cc589705ac3dfbec..d80bdb0a8b029750379107c5995c187c1b949747
@@@ -12,8 -12,8 +12,8 @@@
  #include <linux/clkdev.h>
  #include <linux/clk/at91_pmc.h>
  #include <linux/of.h>
 -#include <linux/of_address.h>
 -#include <linux/io.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/regmap.h>
  
  #include "pmc.h"
  
@@@ -27,7 -27,7 +27,7 @@@
  
  struct at91sam9x5_clk_usb {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
  };
  
  #define to_at91sam9x5_clk_usb(hw) \
@@@ -35,7 -35,7 +35,7 @@@
  
  struct at91rm9200_clk_usb {
        struct clk_hw hw;
 -      struct at91_pmc *pmc;
 +      struct regmap *regmap;
        u32 divisors[4];
  };
  
  static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
                                                    unsigned long parent_rate)
  {
 -      u32 tmp;
 -      u8 usbdiv;
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
 +      unsigned int usbr;
 +      u8 usbdiv;
  
 -      tmp = pmc_read(pmc, AT91_PMC_USB);
 -      usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
 +      regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
 +      usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
  
        return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
  }
@@@ -108,31 -109,33 +108,31 @@@ static int at91sam9x5_clk_usb_determine
  
  static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
  {
 -      u32 tmp;
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
  
        if (index > 1)
                return -EINVAL;
 -      tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS;
 -      if (index)
 -              tmp |= AT91_PMC_USBS;
 -      pmc_write(pmc, AT91_PMC_USB, tmp);
 +
 +      regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
 +                         index ? AT91_PMC_USBS : 0);
 +
        return 0;
  }
  
  static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
  {
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
 +      unsigned int usbr;
  
 -      return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS;
 +      regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
 +
 +      return usbr & AT91_PMC_USBS;
  }
  
  static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
                                       unsigned long parent_rate)
  {
 -      u32 tmp;
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
        unsigned long div;
  
        if (!rate)
        if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
                return -EINVAL;
  
 -      tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV;
 -      tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT;
 -      pmc_write(pmc, AT91_PMC_USB, tmp);
 +      regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV,
 +                         (div - 1) << SAM9X5_USB_DIV_SHIFT);
  
        return 0;
  }
@@@ -159,28 -163,28 +159,28 @@@ static const struct clk_ops at91sam9x5_
  static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
  {
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
  
 -      pmc_write(pmc, AT91_PMC_USB,
 -                pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS);
 +      regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
 +                         AT91_PMC_USBS);
 +
        return 0;
  }
  
  static void at91sam9n12_clk_usb_disable(struct clk_hw *hw)
  {
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
  
 -      pmc_write(pmc, AT91_PMC_USB,
 -                pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS);
 +      regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0);
  }
  
  static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw)
  {
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
 +      unsigned int usbr;
  
 -      return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS);
 +      regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
 +
 +      return usbr & AT91_PMC_USBS;
  }
  
  static const struct clk_ops at91sam9n12_usb_ops = {
  };
  
  static struct clk * __init
 -at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name,
 +at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
                            const char **parent_names, u8 num_parents)
  {
        struct at91sam9x5_clk_usb *usb;
                     CLK_SET_RATE_PARENT;
  
        usb->hw.init = &init;
 -      usb->pmc = pmc;
 +      usb->regmap = regmap;
  
        clk = clk_register(NULL, &usb->hw);
        if (IS_ERR(clk))
  }
  
  static struct clk * __init
 -at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name,
 +at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
                             const char *parent_name)
  {
        struct at91sam9x5_clk_usb *usb;
        init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
  
        usb->hw.init = &init;
 -      usb->pmc = pmc;
 +      usb->regmap = regmap;
  
        clk = clk_register(NULL, &usb->hw);
        if (IS_ERR(clk))
@@@ -253,12 -257,12 +253,12 @@@ static unsigned long at91rm9200_clk_usb
                                                    unsigned long parent_rate)
  {
        struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
 -      u32 tmp;
 +      unsigned int pllbr;
        u8 usbdiv;
  
 -      tmp = pmc_read(pmc, AT91_CKGR_PLLBR);
 -      usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT;
 +      regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr);
 +
 +      usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT;
        if (usb->divisors[usbdiv])
                return parent_rate / usb->divisors[usbdiv];
  
@@@ -306,8 -310,10 +306,8 @@@ static long at91rm9200_clk_usb_round_ra
  static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
                                       unsigned long parent_rate)
  {
 -      u32 tmp;
        int i;
        struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
 -      struct at91_pmc *pmc = usb->pmc;
        unsigned long div;
  
        if (!rate)
  
        for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
                if (usb->divisors[i] == div) {
 -                      tmp = pmc_read(pmc, AT91_CKGR_PLLBR) &
 -                            ~AT91_PMC_USBDIV;
 -                      tmp |= i << RM9200_USB_DIV_SHIFT;
 -                      pmc_write(pmc, AT91_CKGR_PLLBR, tmp);
 +                      regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR,
 +                                         AT91_PMC_USBDIV,
 +                                         i << RM9200_USB_DIV_SHIFT);
 +
                        return 0;
                }
        }
@@@ -335,7 -341,7 +335,7 @@@ static const struct clk_ops at91rm9200_
  };
  
  static struct clk * __init
 -at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name,
 +at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
                            const char *parent_name, const u32 *divisors)
  {
        struct at91rm9200_clk_usb *usb;
        init.flags = CLK_SET_RATE_PARENT;
  
        usb->hw.init = &init;
 -      usb->pmc = pmc;
 +      usb->regmap = regmap;
        memcpy(usb->divisors, divisors, sizeof(usb->divisors));
  
        clk = clk_register(NULL, &usb->hw);
        return clk;
  }
  
 -void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
 -                                      struct at91_pmc *pmc)
 +static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
  {
        struct clk *clk;
-       int num_parents;
+       unsigned int num_parents;
        const char *parent_names[USB_SOURCE_MAX];
        const char *name = np->name;
 +      struct regmap *regmap;
  
        num_parents = of_clk_get_parent_count(np);
-       if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
+       if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
                return;
  
        of_clk_parent_fill(np, parent_names, num_parents);
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
 +      clk = at91sam9x5_clk_register_usb(regmap, name, parent_names,
 +                                        num_parents);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
 +             of_at91sam9x5_clk_usb_setup);
  
 -void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
 -                                       struct at91_pmc *pmc)
 +static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
  {
        struct clk *clk;
        const char *parent_name;
        const char *name = np->name;
 +      struct regmap *regmap;
  
        parent_name = of_clk_get_parent_name(np, 0);
        if (!parent_name)
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91sam9n12_clk_register_usb(pmc, name, parent_name);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
 +      clk = at91sam9n12_clk_register_usb(regmap, name, parent_name);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
 +             of_at91sam9n12_clk_usb_setup);
  
 -void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
 -                                      struct at91_pmc *pmc)
 +static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
  {
        struct clk *clk;
        const char *parent_name;
        const char *name = np->name;
        u32 divisors[4] = {0, 0, 0, 0};
 +      struct regmap *regmap;
  
        parent_name = of_clk_get_parent_name(np, 0);
        if (!parent_name)
  
        of_property_read_string(np, "clock-output-names", &name);
  
 -      clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors);
 +      regmap = syscon_node_to_regmap(of_get_parent(np));
 +      if (IS_ERR(regmap))
 +              return;
 +
 +      clk = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
        if (IS_ERR(clk))
                return;
  
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
  }
 +CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
 +             of_at91rm9200_clk_usb_setup);
index a9353cd4ce178a948bf344f4e347269a6ee96ebd,48b8b64fd28f1211322c8df76eb3fc9f0b3478ba..a98b98e2a9e4404047d5f965924a660464a13ec6
@@@ -84,7 -84,7 +84,7 @@@ unsigned int pxa25x_get_clk_frequency_k
  static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw,
                                                unsigned long parent_rate)
  {
 -      unsigned long cccr = CCCR;
 +      unsigned long cccr = readl(CCCR);
        unsigned int m = M_clk_mult[(cccr >> 5) & 0x03];
  
        return parent_rate / m;
@@@ -99,7 -99,7 +99,7 @@@ PARENTS(pxa25x_osc3) = { "osc_3_6864mhz
  #define PXA25X_CKEN(dev_id, con_id, parents, mult, div,                       \
                    bit, is_lp, flags)                                  \
        PXA_CKEN(dev_id, con_id, bit, parents, mult, div, mult, div,    \
 -               is_lp,  &CKEN, CKEN_ ## bit, flags)
 +               is_lp,  CKEN, CKEN_ ## bit, flags)
  #define PXA25X_PBUS95_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay)       \
        PXA25X_CKEN(dev_id, con_id, pxa25x_pbus95_parents, mult_hp,     \
                    div_hp, bit, NULL, 0)
  
  #define PXA25X_CKEN_1RATE(dev_id, con_id, bit, parents, delay)                \
        PXA_CKEN_1RATE(dev_id, con_id, bit, parents,                    \
 -                     &CKEN, CKEN_ ## bit, 0)
 +                     CKEN, CKEN_ ## bit, 0)
  #define PXA25X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay)     \
        PXA_CKEN_1RATE(dev_id, con_id, bit, parents,                    \
 -                     &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
 +                     CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
  
  static struct desc_clk_cken pxa25x_clocks[] __initdata = {
        PXA25X_PBUS95_CKEN("pxa2xx-mci.0", NULL, MMC, 1, 5, 0),
@@@ -162,7 -162,7 +162,7 @@@ MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "co
  static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
  {
 -      unsigned long cccr = CCCR;
 +      unsigned long cccr = readl(CCCR);
        unsigned int n2 = N2_clk_mult[(cccr >> 7) & 0x07];
  
        return (parent_rate / n2) * 2;
@@@ -173,7 -173,7 +173,7 @@@ RATE_RO_OPS(clk_pxa25x_run, "run")
  static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw,
        unsigned long parent_rate)
  {
 -      unsigned long clkcfg, cccr = CCCR;
 +      unsigned long clkcfg, cccr = readl(CCCR);
        unsigned int l, m, n2, t;
  
        asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
@@@ -200,12 -200,10 +200,10 @@@ static void __init pxa25x_register_core
  static void __init pxa25x_register_plls(void)
  {
        clk_register_fixed_rate(NULL, "osc_3_6864mhz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
-                               3686400);
+                               CLK_GET_RATE_NOCACHE, 3686400);
        clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
-                               32768);
-       clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
+                               CLK_GET_RATE_NOCACHE, 32768);
+       clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
        clk_register_fixed_factor(NULL, "ppll_95_85mhz", "osc_3_6864mhz",
                                  0, 26, 1);
        clk_register_fixed_factor(NULL, "ppll_147_46mhz", "osc_3_6864mhz",
index fc2abf97edd7e822175a0cb8fe7b7166475505cc,e86cd5fa2eb4f36835dd5490842b72eb770bb569..c40b1804f58caf33f7b1bf6cac90cc22ea381248
@@@ -85,7 -85,7 +85,7 @@@ unsigned int pxa27x_get_clk_frequency_k
  
  bool pxa27x_is_ppll_disabled(void)
  {
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        return ccsr & (1 << CCCR_PPDIS_BIT);
  }
@@@ -93,7 -93,7 +93,7 @@@
  #define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp,         \
                    bit, is_lp, flags)                                  \
        PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp,   \
 -               is_lp,  &CKEN, CKEN_ ## bit, flags)
 +               is_lp,  CKEN, CKEN_ ## bit, flags)
  #define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
        PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp,       \
                    div_hp, bit, pxa27x_is_ppll_disabled, 0)
@@@ -106,10 -106,10 +106,10 @@@ PARENTS(pxa27x_membus) = { "lcd_base", 
  
  #define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay)                \
        PXA_CKEN_1RATE(dev_id, con_id, bit, parents,                    \
 -                     &CKEN, CKEN_ ## bit, 0)
 +                     CKEN, CKEN_ ## bit, 0)
  #define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay)     \
        PXA_CKEN_1RATE(dev_id, con_id, bit, parents,                    \
 -                     &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
 +                     CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
  
  static struct desc_clk_cken pxa27x_clocks[] __initdata = {
        PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
@@@ -151,7 -151,7 +151,7 @@@ static unsigned long clk_pxa27x_cpll_ge
        unsigned long clkcfg;
        unsigned int t, ht;
        unsigned int l, L, n2, N;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
        t  = clkcfg & (1 << 0);
@@@ -171,8 -171,8 +171,8 @@@ static unsigned long clk_pxa27x_lcd_bas
                                                  unsigned long parent_rate)
  {
        unsigned int l, osc_forced;
 -      unsigned long ccsr = CCSR;
 -      unsigned long cccr = CCCR;
 +      unsigned long ccsr = readl(CCSR);
 +      unsigned long cccr = readl(CCCR);
  
        l  = ccsr & CCSR_L_MASK;
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
  static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw)
  {
        unsigned int osc_forced;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        if (osc_forced)
@@@ -208,12 -208,12 +208,12 @@@ MUX_RO_RATE_RO_OPS(clk_pxa27x_lcd_base
  static void __init pxa27x_register_plls(void)
  {
        clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+                               CLK_GET_RATE_NOCACHE,
                                13 * MHz);
        clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+                               CLK_GET_RATE_NOCACHE,
                                32768 * KHz);
-       clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
+       clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
        clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
  }
  
@@@ -222,7 -222,7 +222,7 @@@ static unsigned long clk_pxa27x_core_ge
  {
        unsigned long clkcfg;
        unsigned int t, ht, b, osc_forced;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
@@@ -242,7 -242,7 +242,7 @@@ static u8 clk_pxa27x_core_get_parent(st
  {
        unsigned long clkcfg;
        unsigned int t, ht, b, osc_forced;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        if (osc_forced)
@@@ -263,7 -263,7 +263,7 @@@ MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "co
  static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
                                             unsigned long parent_rate)
  {
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
        unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
  
        return (parent_rate / n2) * 2;
@@@ -285,7 -285,7 +285,7 @@@ static unsigned long clk_pxa27x_system_
  {
        unsigned long clkcfg;
        unsigned int b, osc_forced;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
  static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
  {
        unsigned int osc_forced;
 -      unsigned long ccsr = CCSR;
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        if (osc_forced)
@@@ -318,8 -318,8 +318,8 @@@ static unsigned long clk_pxa27x_memory_
                                                unsigned long parent_rate)
  {
        unsigned int a, l, osc_forced;
 -      unsigned long cccr = CCCR;
 -      unsigned long ccsr = CCSR;
 +      unsigned long cccr = readl(CCCR);
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        a = cccr & (1 << CCCR_A_BIT);
  static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
  {
        unsigned int osc_forced, a;
 -      unsigned long cccr = CCCR;
 -      unsigned long ccsr = CCSR;
 +      unsigned long cccr = readl(CCCR);
 +      unsigned long ccsr = readl(CCSR);
  
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
        a = cccr & (1 << CCCR_A_BIT);
index ea679718601cbe6b92903a816a6e444a128d660b,9238d5f5a7fd7e9aa1472a715d4845ad82bb18a4..42bdaa772be06167a0974f6d975e33b8dc6bb5de
@@@ -284,15 -284,15 +284,15 @@@ static void __init pxa3xx_register_core
  static void __init pxa3xx_register_plls(void)
  {
        clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+                               CLK_GET_RATE_NOCACHE,
                                13 * MHz);
        clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+                               CLK_GET_RATE_NOCACHE,
                                32768);
        clk_register_fixed_rate(NULL, "ring_osc_120mhz", NULL,
-                               CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+                               CLK_GET_RATE_NOCACHE,
                                120 * MHz);
-       clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
+       clk_register_fixed_rate(NULL, "clk_dummy", NULL, 0, 0);
        clk_register_fixed_factor(NULL, "spll_624mhz", "osc_13mhz", 0, 48, 1);
        clk_register_fixed_factor(NULL, "ring_osc_60mhz", "ring_osc_120mhz",
                                  0, 1, 2);
@@@ -334,7 -334,8 +334,7 @@@ static void __init pxa3xx_base_clocks_i
        clk_register_clk_pxa3xx_system_bus();
        clk_register_clk_pxa3xx_ac97();
        clk_register_clk_pxa3xx_smemc();
 -      clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0,
 -                        (void __iomem *)&OSCC, 11, 0, NULL);
 +      clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0, OSCC, 11, 0, NULL);
        clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL,
                            clk_register_fixed_factor(NULL, "os-timer0",
                                                      "osc_13mhz", 0, 1, 4));
index 53e9c39f5103cd40dd07a89062c830819efae2f4,0703c8f08ef869638f8c2672827a1eea34e406e0..7cdb2d61f3e0666075ac25d6eb83b7fba88e872d
@@@ -177,6 -177,8 +177,8 @@@ static struct rockchip_clk_branch rk303
        GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED,
                        RK2928_CLKGATE_CON(0), 6, GFLAGS),
  
+       FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
        /*
         * Clock-Architecture Diagram 2
         */
                        RK2928_CLKGATE_CON(0), 8, GFLAGS),
        COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
                        RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+       FACTOR(0, "ddrphy", "ddrphy2x", 0, 1, 2),
  
        COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
                        RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
        COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
                        RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
                        RK2928_CLKGATE_CON(3), 11, GFLAGS),
+       FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4,
+                       RK2928_CLKGATE_CON(3), 12, GFLAGS),
  
        COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0,
                        RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS,
                        RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
                        RK2928_CLKGATE_CON(10), 5, GFLAGS),
  
 -      COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0,
 +      COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_3plls_p, CLK_SET_RATE_NO_REPARENT,
                        RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS),
        MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
        COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
                        RK2928_CLKSEL_CON(21), 4, 5, DFLAGS,
                        RK2928_CLKGATE_CON(2), 6, GFLAGS),
+       FACTOR(0, "sclk_macref_out", "hclk_peri_src", 0, 1, 2),
  
        MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
                        RK2928_CLKSEL_CON(31), 0, 1, MFLAGS),
        GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS),
        GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
  
-       GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
+       GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 12, GFLAGS),
        GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
  
-       /* hclk_video gates */
-       GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS),
  
        /* xin24m gates */
        GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS),
        GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS),
        GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
        GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
 -      GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS),
 +      GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS),
  
        /* pclk_peri gates */
        GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
@@@ -444,34 -448,11 +448,11 @@@ static void __init rk3036_clk_init(stru
  
        rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
  
-       /* xin12m is created by an cru-internal divider */
-       clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock xin12m: %ld\n",
-                       __func__, PTR_ERR(clk));
        clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
        if (IS_ERR(clk))
                pr_warn("%s: could not register clock usb480m: %ld\n",
                        __func__, PTR_ERR(clk));
  
-       clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock ddrphy: %ld\n",
-                       __func__, PTR_ERR(clk));
-       clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
-                                       "aclk_vcodec", 0, 1, 4);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
-                       __func__, PTR_ERR(clk));
-       clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
-                                       "hclk_peri_src", 0, 1, 2);
-       if (IS_ERR(clk))
-               pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
-                       __func__, PTR_ERR(clk));
        rockchip_clk_register_plls(rk3036_pll_clks,
                                   ARRAY_SIZE(rk3036_pll_clks),
                                   RK3036_GRF_SOC_STATUS0);
diff --combined include/linux/device.h
index 88192d098aed6656db545770cd3ca597ea261e1f,74674e0983158e35006b59f2eda058478ce4917c..002c59728dbe6012c5eac53c3f6a1eb885b8af05
@@@ -70,11 -70,8 +70,11 @@@ extern void bus_remove_file(struct bus_
   * @dev_groups:       Default attributes of the devices on the bus.
   * @drv_groups: Default attributes of the device drivers on the bus.
   * @match:    Called, perhaps multiple times, whenever a new device or driver
 - *            is added for this bus. It should return a nonzero value if the
 - *            given device can be handled by the given driver.
 + *            is added for this bus. It should return a positive value if the
 + *            given device can be handled by the given driver and zero
 + *            otherwise. It may also return error code if determining that
 + *            the driver supports the device is not possible. In case of
 + *            -EPROBE_DEFER it will queue the device for deferred probing.
   * @uevent:   Called when a device is added, removed, or a few other things
   *            that generate uevents to add the environment variables.
   * @probe:    Called when a new device or driver add to this bus, and callback
@@@ -685,6 -682,18 +685,18 @@@ void __iomem *devm_ioremap_resource(str
  int devm_add_action(struct device *dev, void (*action)(void *), void *data);
  void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
  
+ static inline int devm_add_action_or_reset(struct device *dev,
+                                          void (*action)(void *), void *data)
+ {
+       int ret;
+       ret = devm_add_action(dev, action, data);
+       if (ret)
+               action(data);
+       return ret;
+ }
  struct device_dma_parameters {
        /*
         * a low level driver may set these to teach IOMMU code about
@@@ -961,11 -970,6 +973,11 @@@ static inline void device_lock(struct d
        mutex_lock(&dev->mutex);
  }
  
 +static inline int device_lock_interruptible(struct device *dev)
 +{
 +      return mutex_lock_interruptible(&dev->mutex);
 +}
 +
  static inline int device_trylock(struct device *dev)
  {
        return mutex_trylock(&dev->mutex);