Merge branches 'clk-optional', 'clk-devm-clkdev-register', 'clk-allwinner', 'clk...
authorStephen Boyd <sboyd@kernel.org>
Fri, 8 Mar 2019 18:27:21 +0000 (10:27 -0800)
committerStephen Boyd <sboyd@kernel.org>
Fri, 8 Mar 2019 18:27:21 +0000 (10:27 -0800)
 - Add a {devm_}clk_get_optional() API
 - Add devm_clk_hw_register_clkdev() API to manage clkdev lookups

* clk-optional:
  clk: Add (devm_)clk_get_optional() functions
  clk: Add comment about __of_clk_get_by_name() error values

* clk-devm-clkdev-register:
  clk: clk-st: avoid clkdev lookup leak at remove
  clk: clk-max77686: Clean clkdev lookup leak and use devm
  clkdev: add managed clkdev lookup registration

* clk-allwinner:
  clk: sunxi-ng: sun8i-a23: Enable PLL-MIPI LDOs when ungating it

* clk-meson: (22 commits)
  clk: meson: meson8b: fix the naming of the APB clocks
  dt-bindings: clock: meson8b: add APB clock definition
  clk: meson: Add G12A AO Clock + Reset Controller
  dt-bindings: clk: add G12A AO Clock and Reset Bindings
  clk: meson: factorise meson64 peripheral clock controller drivers
  clk: meson: g12a: add peripheral clock controller
  dt-bindings: clk: meson: add g12a periph clock controller bindings
  clk: meson: pll: update driver for the g12a
  clk: meson: rework and clean drivers dependencies
  clk: meson: axg-audio does not require syscon
  clk: meson: use CONFIG_ARCH_MESON to enter meson clk directory
  clk: export some clk_hw function symbols for module drivers
  clk: meson: ao-clkc: claim clock controller input clocks from DT
  clk: meson: axg: claim clock controller input clock from DT
  clk: meson: gxbb: claim clock controller input clock from DT
  clk: meson: meson8b: add the GPU clock tree
  clk: meson: meson8b: use a separate clock table for Meson8
  clk: meson: axg-ao: add 32k generation subtree
  clk: meson: gxbb-ao: replace cec-32k with the dual divider
  clk: meson: add dual divider clock driver
  ...

* clk-renesas:
  clk: renesas: r8a774a1: Fix LAST_DT_CORE_CLK
  clk: renesas: r8a774c0: Fix LAST_DT_CORE_CLK
  clk: renesas: r8a774c0: Add TMU clock
  clk: renesas: r8a77980: Add RPC clocks
  clk: renesas: rcar-gen3: Add RPC clocks
  clk: renesas: rcar-gen3: Add spinlock
  clk: renesas: rcar-gen3: Factor out cpg_reg_modify()
  clk: renesas: r8a774c0: Correct parent clock of DU
  clk: renesas: r8a774a1: Add missing CANFD clock
  clk: renesas: r8a774c0: Add missing CANFD clock

1  2  3  4  5  6 
Documentation/driver-model/devres.txt
drivers/clk/Makefile
drivers/clk/clk.c
drivers/clk/clkdev.c

index b277cafce71eb25effa455c90f3c24d14430856d,83f38c0439cd7c474af31bca92fff979eaa21afa,805b7bf5d98f880b19fef774efde6a28e53b0b8a,b277cafce71eb25effa455c90f3c24d14430856d,b277cafce71eb25effa455c90f3c24d14430856d,b277cafce71eb25effa455c90f3c24d14430856d..d7d6f01e81fff52ed25f0930532c5cc10875c2dc
@@@@@@@ -242,9 -242,10 -242,10 -242,9 -242,9 -242,9 +242,11 @@@@@@@ certainly invest a bit more effort int
      
      CLOCK
        devm_clk_get()
+ ++++  devm_clk_get_optional()
        devm_clk_put()
        devm_clk_hw_register()
        devm_of_clk_add_hw_provider()
++ +++  devm_clk_hw_register_clkdev()
      
      DMA
        dmaenginem_async_device_register()
diff --combined drivers/clk/Makefile
index d6cd32bda771c15438a2fd06d031dab080461aa6,8a9440a9750043ad80969367ed1938a6a9be1029,8a9440a9750043ad80969367ed1938a6a9be1029,8a9440a9750043ad80969367ed1938a6a9be1029,8d780c4390f15d6a4388b9ec2c0dd028cf3eced5,8a9440a9750043ad80969367ed1938a6a9be1029..1db133652f0c3889a5f4d716ac32a32d403afd72
@@@@@@@ -27,7 -27,6 -27,6 -27,6 -27,6 -27,6 +27,7 @@@@@@@ obj-$(CONFIG_COMMON_CLK_CDCE925)      += clk
      obj-$(CONFIG_ARCH_CLPS711X)               += clk-clps711x.o
      obj-$(CONFIG_COMMON_CLK_CS2000_CP)        += clk-cs2000-cp.o
      obj-$(CONFIG_ARCH_EFM32)          += clk-efm32gg.o
 +++++obj-$(CONFIG_COMMON_CLK_FIXED_MMIO)       += clk-fixed-mmio.o
      obj-$(CONFIG_COMMON_CLK_GEMINI)           += clk-gemini.o
      obj-$(CONFIG_COMMON_CLK_ASPEED)           += clk-aspeed.o
      obj-$(CONFIG_ARCH_HIGHBANK)               += clk-highbank.o
@@@@@@@ -79,7 -78,7 -78,7 -78,7 -78,7 -78,7 +79,7 @@@@@@@ obj-$(CONFIG_ARCH_K3)                 += keystone
      obj-$(CONFIG_ARCH_KEYSTONE)               += keystone/
      obj-$(CONFIG_MACH_LOONGSON32)             += loongson1/
      obj-y                                     += mediatek/
---- -obj-$(CONFIG_COMMON_CLK_AMLOGIC)  += meson/
++++ +obj-$(CONFIG_ARCH_MESON)          += meson/
      obj-$(CONFIG_MACH_PIC32)          += microchip/
      ifeq ($(CONFIG_COMMON_CLK), y)
      obj-$(CONFIG_ARCH_MMP)                    += mmp/
diff --combined drivers/clk/clk.c
index d2477a5058ac2eb2d7925f04ae435479ff1efc9a,75d13c0eff1243ebc29bbab45470e34f127e538c,75d13c0eff1243ebc29bbab45470e34f127e538c,75d13c0eff1243ebc29bbab45470e34f127e538c,5558af12f9dbb8175f61fcf0c63db8d710ccbfc4,75d13c0eff1243ebc29bbab45470e34f127e538c..af3882f0408065df913cd79cfd8b466675c1b97b
@@@@@@@ -394,16 -394,16 -394,16 -394,16 -394,19 -394,16 +394,19 @@@@@@@ bool clk_hw_is_prepared(const struct cl
      {
        return clk_core_is_prepared(hw->core);
      }
++++ +EXPORT_SYMBOL_GPL(clk_hw_is_prepared);
      
      bool clk_hw_rate_is_protected(const struct clk_hw *hw)
      {
        return clk_core_rate_is_protected(hw->core);
      }
++++ +EXPORT_SYMBOL_GPL(clk_hw_rate_is_protected);
      
      bool clk_hw_is_enabled(const struct clk_hw *hw)
      {
        return clk_core_is_enabled(hw->core);
      }
++++ +EXPORT_SYMBOL_GPL(clk_hw_is_enabled);
      
      bool __clk_is_enabled(struct clk *clk)
      {
@@@@@@@ -1513,20 -1513,10 -1513,10 -1513,10 -1516,10 -1513,10 +1516,20 @@@@@@@ static int clk_fetch_parent_index(struc
        if (!parent)
                return -EINVAL;
      
 -----  for (i = 0; i < core->num_parents; i++)
 -----          if (clk_core_get_parent_by_index(core, i) == parent)
 +++++  for (i = 0; i < core->num_parents; i++) {
 +++++          if (core->parents[i] == parent)
                        return i;
      
 +++++          if (core->parents[i])
 +++++                  continue;
 +++++
 +++++          /* Fallback to comparing globally unique names */
 +++++          if (!strcmp(parent->name, core->parent_names[i])) {
 +++++                  core->parents[i] = parent;
 +++++                  return i;
 +++++          }
 +++++  }
 +++++
        return -EINVAL;
      }
      
@@@@@@@ -2789,7 -2779,7 -2779,7 -2779,7 -2782,7 -2779,7 +2792,7 @@@@@@@ static void clk_dump_one(struct seq_fil
        seq_printf(s, "\"protect_count\": %d,", c->protect_count);
        seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
        seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
 -----  seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
 +++++  seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
        seq_printf(s, "\"duty_cycle\": %u",
                   clk_core_get_scaled_duty_cycle(c, 100000));
      }
diff --combined drivers/clk/clkdev.c
index 9ab3db8b3988375d02b88c5e76f0843a9a6c475f,5284fd191cca5d77e51ca1a397a6fa2d23caf64b,4621f8a91fc01f80f31b0e3949a8c8c1adb5c8d4,9ab3db8b3988375d02b88c5e76f0843a9a6c475f,9ab3db8b3988375d02b88c5e76f0843a9a6c475f,9ab3db8b3988375d02b88c5e76f0843a9a6c475f..4cfe39636105679cf97e2d04bab1eed189215baa
@@@@@@@ -52,6 -52,12 -52,6 -52,6 -52,6 -52,6 +52,12 @@@@@@@ struct clk *of_clk_get(struct device_no
      }
      EXPORT_SYMBOL(of_clk_get);
      
+ ++++/*
+ ++++ * Beware the return values when np is valid, but no clock provider is found.
+ ++++ * If name == NULL, the function returns -ENOENT.
+ ++++ * If name != NULL, the function returns -EINVAL. This is because __of_clk_get()
+ ++++ * is called even if of_property_match_string() returns an error.
+ ++++ */
      static struct clk *__of_clk_get_by_name(struct device_node *np,
                                        const char *dev_id,
                                        const char *name)
@@@@@@@ -401,6 -407,6 -401,23 -401,6 -401,6 -401,6 +407,23 @@@@@@@ static struct clk_lookup *__clk_registe
        return cl;
      }
      
++ +++static int do_clk_register_clkdev(struct clk_hw *hw,
++ +++  struct clk_lookup **cl, const char *con_id, const char *dev_id)
++ +++{
++ +++  if (IS_ERR(hw))
++ +++          return PTR_ERR(hw);
++ +++  /*
++ +++   * Since dev_id can be NULL, and NULL is handled specially, we must
++ +++   * pass it as either a NULL format string, or with "%s".
++ +++   */
++ +++  if (dev_id)
++ +++          *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
++ +++  else
++ +++          *cl = __clk_register_clkdev(hw, con_id, NULL);
++ +++
++ +++  return *cl ? 0 : -ENOMEM;
++ +++}
++ +++
      /**
       * clk_register_clkdev - register one clock lookup for a struct clk
       * @clk: struct clk to associate with all clk_lookups
@@@@@@@ -423,17 -429,17 -440,8 -423,17 -423,17 -423,17 +446,8 @@@@@@@ int clk_register_clkdev(struct clk *clk
        if (IS_ERR(clk))
                return PTR_ERR(clk);
      
-- ---  /*
-- ---   * Since dev_id can be NULL, and NULL is handled specially, we must
-- ---   * pass it as either a NULL format string, or with "%s".
-- ---   */
-- ---  if (dev_id)
-- ---          cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, "%s",
-- ---                                     dev_id);
-- ---  else
-- ---          cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, NULL);
-- ---
-- ---  return cl ? 0 : -ENOMEM;
++ +++  return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
++ +++                                        dev_id);
      }
      EXPORT_SYMBOL(clk_register_clkdev);
      
@@@@@@@ -456,18 -462,18 -464,75 -456,18 -456,18 -456,18 +470,75 @@@@@@@ int clk_hw_register_clkdev(struct clk_h
      {
        struct clk_lookup *cl;
      
-- ---  if (IS_ERR(hw))
-- ---          return PTR_ERR(hw);
++ +++  return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
++ +++}
++ +++EXPORT_SYMBOL(clk_hw_register_clkdev);
      
-- ---  /*
-- ---   * Since dev_id can be NULL, and NULL is handled specially, we must
-- ---   * pass it as either a NULL format string, or with "%s".
-- ---   */
-- ---  if (dev_id)
-- ---          cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
-- ---  else
-- ---          cl = __clk_register_clkdev(hw, con_id, NULL);
++ +++static void devm_clkdev_release(struct device *dev, void *res)
++ +++{
++ +++  clkdev_drop(*(struct clk_lookup **)res);
++ +++}
+  +++
 -      return cl ? 0 : -ENOMEM;
++ +++static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
++ +++{
++ +++  struct clk_lookup **l = res;
 +    
-  ---  return cl ? 0 : -ENOMEM;
++ +++  return *l == data;
      }
-- ---EXPORT_SYMBOL(clk_hw_register_clkdev);
++ +++
++ +++/**
++ +++ * devm_clk_release_clkdev - Resource managed clkdev lookup release
++ +++ * @dev: device this lookup is bound
++ +++ * @con_id: connection ID string on device
++ +++ * @dev_id: format string describing device name
++ +++ *
++ +++ * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
++ +++ * Normally this function will not need to be called and the resource
++ +++ * management code will ensure that the resource is freed.
++ +++ */
++ +++void devm_clk_release_clkdev(struct device *dev, const char *con_id,
++ +++                       const char *dev_id)
++ +++{
++ +++  struct clk_lookup *cl;
++ +++  int rval;
++ +++
++ +++  cl = clk_find(dev_id, con_id);
++ +++  WARN_ON(!cl);
++ +++  rval = devres_release(dev, devm_clkdev_release,
++ +++                        devm_clk_match_clkdev, cl);
++ +++  WARN_ON(rval);
++ +++}
++ +++EXPORT_SYMBOL(devm_clk_release_clkdev);
++ +++
++ +++/**
++ +++ * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
++ +++ * @dev: device this lookup is bound
++ +++ * @hw: struct clk_hw to associate with all clk_lookups
++ +++ * @con_id: connection ID string on device
++ +++ * @dev_id: format string describing device name
++ +++ *
++ +++ * con_id or dev_id may be NULL as a wildcard, just as in the rest of
++ +++ * clkdev.
++ +++ *
++ +++ * To make things easier for mass registration, we detect error clk_hws
++ +++ * from a previous clk_hw_register_*() call, and return the error code for
++ +++ * those.  This is to permit this function to be called immediately
++ +++ * after clk_hw_register_*().
++ +++ */
++ +++int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
++ +++                          const char *con_id, const char *dev_id)
++ +++{
++ +++  int rval = -ENOMEM;
++ +++  struct clk_lookup **cl;
++ +++
++ +++  cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
++ +++  if (cl) {
++ +++          rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
++ +++          if (!rval)
++ +++                  devres_add(dev, cl);
++ +++          else
++ +++                  devres_free(cl);
++ +++  }
++ +++  return rval;
++ +++}
++ +++EXPORT_SYMBOL(devm_clk_hw_register_clkdev);