Merge branches 'clk-x86', 'clk-stm', 'clk-amlogic' and 'clk-allwinner' into clk-next
authorStephen Boyd <sboyd@kernel.org>
Wed, 12 Jan 2022 02:30:35 +0000 (18:30 -0800)
committerStephen Boyd <sboyd@kernel.org>
Wed, 12 Jan 2022 02:30:35 +0000 (18:30 -0800)
* clk-x86:
  clk: x86: Fix clk_gate_flags for RV_CLK_GATE
  clk: x86: Use dynamic con_id string during clk registration
  ACPI: APD: Add a fmw property clk-name
  drivers: acpi: acpi_apd: Remove unused device property "is-rv"
  x86: clk: clk-fch: Add support for newer family of AMD's SOC
  clk: Introduce clk-tps68470 driver
  platform/x86: int3472: Deal with probe ordering issues
  platform/x86: int3472: Pass tps68470_regulator_platform_data to the tps68470-regulator MFD-cell
  platform/x86: int3472: Pass tps68470_clk_platform_data to the tps68470-regulator MFD-cell
  platform/x86: int3472: Add get_sensor_adev_and_name() helper
  platform/x86: int3472: Split into 2 drivers
  platform_data: Add linux/platform_data/tps68470.h file
  i2c: acpi: Add i2c_acpi_new_device_by_fwnode() function
  i2c: acpi: Use acpi_dev_ready_for_enumeration() helper
  ACPI: delay enumeration of devices with a _DEP pointing to an INT3472 device

* clk-stm:
  clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system enter shell

* clk-amlogic:
  clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB

* clk-allwinner:
  clk: sunxi-ng: Add support for the D1 SoC clocks
  clk: sunxi-ng: gate: Add macros for gates with fixed dividers
  clk: sunxi-ng: mux: Add macros using clk_parent_data and clk_hw
  clk: sunxi-ng: mp: Add macros using clk_parent_data and clk_hw
  clk: sunxi-ng: div: Add macros using clk_parent_data and clk_hw
  dt-bindings: clk: Add compatibles for D1 CCUs
  clk: sunxi-ng: Allow the CCU core to be built as a module
  clk: sunxi-ng: Convert early providers to platform drivers
  clk: sunxi-ng: Allow drivers to be built as modules
  clk: sunxi-ng: Export symbols used by CCU drivers

69 files changed:
Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml
drivers/acpi/acpi_apd.c
drivers/acpi/scan.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-gate.c
drivers/clk/clk-gemini.c
drivers/clk/clk-lan966x.c [new file with mode: 0644]
drivers/clk/clk-stm32f4.c
drivers/clk/clk-stm32mp1.c
drivers/clk/clk-tps68470.c [new file with mode: 0644]
drivers/clk/clk.c
drivers/clk/imx/clk-pllv1.c
drivers/clk/meson/gxbb.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/r8a774a1-cpg-mssr.c
drivers/clk/renesas/r8a774b1-cpg-mssr.c
drivers/clk/renesas/r8a774c0-cpg-mssr.c
drivers/clk/renesas/r8a774e1-cpg-mssr.c
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/r8a77965-cpg-mssr.c
drivers/clk/renesas/r8a77980-cpg-mssr.c
drivers/clk/renesas/r8a77990-cpg-mssr.c
drivers/clk/renesas/r8a77995-cpg-mssr.c
drivers/clk/renesas/r8a779a0-cpg-mssr.c
drivers/clk/renesas/r8a779f0-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r9a07g044-cpg.c
drivers/clk/renesas/rcar-cpg-lib.c
drivers/clk/renesas/rcar-cpg-lib.h
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/rcar-gen4-cpg.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen4-cpg.h [new file with mode: 0644]
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/renesas/rzg2l-cpg.c
drivers/clk/renesas/rzg2l-cpg.h
drivers/clk/ti/adpll.c
drivers/clk/x86/clk-fch.c
drivers/clk/zynq/pll.c
drivers/i2c/i2c-core-acpi.c
drivers/mmc/host/renesas_sdhi.h
drivers/mmc/host/renesas_sdhi_core.c
drivers/mmc/host/renesas_sdhi_internal_dmac.c
drivers/platform/x86/intel/int3472/Makefile
drivers/platform/x86/intel/int3472/clk_and_regulator.c [new file with mode: 0644]
drivers/platform/x86/intel/int3472/common.c [new file with mode: 0644]
drivers/platform/x86/intel/int3472/common.h [new file with mode: 0644]
drivers/platform/x86/intel/int3472/discrete.c [new file with mode: 0644]
drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c [deleted file]
drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c [deleted file]
drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h [deleted file]
drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c [deleted file]
drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c [deleted file]
drivers/platform/x86/intel/int3472/tps68470.c [new file with mode: 0644]
drivers/platform/x86/intel/int3472/tps68470.h [new file with mode: 0644]
drivers/platform/x86/intel/int3472/tps68470_board_data.c [new file with mode: 0644]
include/acpi/acpi_bus.h
include/dt-bindings/clock/microchip,lan966x.h [new file with mode: 0644]
include/dt-bindings/clock/r8a779f0-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/power/r8a779f0-sysc.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/i2c.h
include/linux/mfd/tps68470.h
include/linux/platform_data/clk-fch.h
include/linux/platform_data/tps68470.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml b/Documentation/devicetree/bindings/clock/microchip,lan966x-gck.yaml
new file mode 100644 (file)
index 0000000..df2bec1
--- /dev/null
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/microchip,lan966x-gck.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip LAN966X Generic Clock Controller
+
+maintainers:
+  - Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
+
+description: |
+  The LAN966X Generic clock controller contains 3 PLLs - cpu_clk,
+  ddr_clk and sys_clk. This clock controller generates and supplies
+  clock to various peripherals within the SoC.
+
+properties:
+  compatible:
+    const: microchip,lan966x-gck
+
+  reg:
+    minItems: 1
+    items:
+      - description: Generic clock registers
+      - description: Optional gate clock registers
+
+  clocks:
+    items:
+      - description: CPU clock source
+      - description: DDR clock source
+      - description: System clock source
+
+  clock-names:
+    items:
+      - const: cpu
+      - const: ddr
+      - const: sys
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clks: clock-controller@e00c00a8 {
+        compatible = "microchip,lan966x-gck";
+        #clock-cells = <1>;
+        clocks = <&cpu_clk>, <&ddr_clk>, <&sys_clk>;
+        clock-names = "cpu", "ddr", "sys";
+        reg = <0xe00c00a8 0x38>;
+    };
+...
index 9b414fb..e0b8621 100644 (file)
@@ -48,6 +48,7 @@ properties:
       - renesas,r8a77990-cpg-mssr # R-Car E3
       - renesas,r8a77995-cpg-mssr # R-Car D3
       - renesas,r8a779a0-cpg-mssr # R-Car V3U
+      - renesas,r8a779f0-cpg-mssr # R-Car S4-8
 
   reg:
     maxItems: 1
index 6e02448..2b958b4 100644 (file)
@@ -87,8 +87,15 @@ static int fch_misc_setup(struct apd_private_data *pdata)
        if (ret < 0)
                return -ENOENT;
 
-       if (!acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, &obj))
-               clk_data->is_rv = obj->integer.value;
+       if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
+               clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
+                                             GFP_KERNEL);
+
+               strcpy(clk_data->name, obj->string.pointer);
+       } else {
+               /* Set default name to mclk if entry missing in firmware */
+               clk_data->name = "mclk";
+       }
 
        list_for_each_entry(rentry, &resource_list, node) {
                clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,
index a50f196..010ef0b 100644 (file)
@@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = {
        NULL
 };
 
+/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
+static const char * const acpi_honor_dep_ids[] = {
+       "INT3472", /* Camera sensor PMIC / clk and regulator info */
+       NULL
+};
+
 static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
 {
        struct acpi_device *device = NULL;
@@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
        struct acpi_dep_data *dep;
 
        list_for_each_entry(dep, &acpi_dep_list, node) {
-               if (dep->consumer == adev->handle)
+               if (dep->consumer == adev->handle) {
+                       if (dep->honor_dep)
+                               adev->flags.honor_deps = 1;
+
                        adev->dep_unmet++;
+               }
        }
 }
 
@@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
        for (count = 0, i = 0; i < dep_devices.count; i++) {
                struct acpi_device_info *info;
                struct acpi_dep_data *dep;
-               bool skip;
+               bool skip, honor_dep;
 
                status = acpi_get_object_info(dep_devices.handles[i], &info);
                if (ACPI_FAILURE(status)) {
@@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
                }
 
                skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
+               honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
                kfree(info);
 
                if (skip)
@@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
 
                dep->supplier = dep_devices.handles[i];
                dep->consumer = handle;
+               dep->honor_dep = honor_dep;
 
                mutex_lock(&acpi_dep_list_lock);
                list_add_tail(&dep->node , &acpi_dep_list);
@@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
                register_dock_dependent_device(device, ejd);
 
        acpi_bus_get_status(device);
-       /* Skip devices that are not present. */
-       if (!acpi_device_is_present(device)) {
+       /* Skip devices that are not ready for enumeration (e.g. not present) */
+       if (!acpi_dev_ready_for_enumeration(device)) {
                device->flags.initialized = false;
                acpi_device_clear_enumerated(device);
                device->flags.power_manageable = 0;
@@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
 }
 EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
 
+/**
+ * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
+ * @device: Pointer to the &struct acpi_device to check
+ *
+ * Check if the device is present and has no unmet dependencies.
+ *
+ * Return true if the device is ready for enumeratino. Otherwise, return false.
+ */
+bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
+{
+       if (device->flags.honor_deps && device->dep_unmet)
+               return false;
+
+       return acpi_device_is_present(device);
+}
+EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
+
 /**
  * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
  * @supplier: Pointer to the dependee device
index c5b3dc9..73243ce 100644 (file)
@@ -169,6 +169,14 @@ config COMMON_CLK_CDCE706
        help
          This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
 
+config COMMON_CLK_TPS68470
+       tristate "Clock Driver for TI TPS68470 PMIC"
+       depends on I2C
+       depends on INTEL_SKL_INT3472 || COMPILE_TEST
+       select REGMAP_I2C
+       help
+         This driver supports the clocks provided by the TPS68470 PMIC.
+
 config COMMON_CLK_CDCE925
        tristate "Clock driver for TI CDCE913/925/937/949 devices"
        depends on I2C
@@ -221,6 +229,13 @@ config COMMON_CLK_GEMINI
          This driver supports the SoC clocks on the Cortina Systems Gemini
          platform, also known as SL3516 or CS3516.
 
+config COMMON_CLK_LAN966X
+       bool "Generic Clock Controller driver for LAN966X SoC"
+       help
+         This driver provides support for Generic Clock Controller(GCK) on
+         LAN966X SoC. GCK generates and supplies clock to various peripherals
+         within the SoC.
+
 config COMMON_CLK_ASPEED
        bool "Clock driver for Aspeed BMC SoCs"
        depends on ARCH_ASPEED || COMPILE_TEST
index 6afe36b..154bf3c 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_HIGHBANK)           += clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)                 += clk-hsdk-pll.o
 obj-$(CONFIG_COMMON_CLK_K210)          += clk-k210.o
 obj-$(CONFIG_LMK04832)                 += clk-lmk04832.o
+obj-$(CONFIG_COMMON_CLK_LAN966X)       += clk-lan966x.o
 obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)     += clk-lochnagar.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX9485)       += clk-max9485.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_COMMON_CLK_SI570)                += clk-si570.o
 obj-$(CONFIG_COMMON_CLK_STM32F)                += clk-stm32f4.o
 obj-$(CONFIG_COMMON_CLK_STM32H7)       += clk-stm32h7.o
 obj-$(CONFIG_COMMON_CLK_STM32MP157)    += clk-stm32mp1.o
+obj-$(CONFIG_COMMON_CLK_TPS68470)      += clk-tps68470.o
 obj-$(CONFIG_CLK_TWL6040)              += clk-twl6040.o
 obj-$(CONFIG_ARCH_VT8500)              += clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_VC5)           += clk-versaclock5.o
index 070dc47..6428380 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -222,3 +223,37 @@ void clk_hw_unregister_gate(struct clk_hw *hw)
        kfree(gate);
 }
 EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);
+
+static void devm_clk_hw_release_gate(struct device *dev, void *res)
+{
+       clk_hw_unregister_gate(*(struct clk_hw **)res);
+}
+
+struct clk_hw *__devm_clk_hw_register_gate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags,
+               void __iomem *reg, u8 bit_idx,
+               u8 clk_gate_flags, spinlock_t *lock)
+{
+       struct clk_hw **ptr, *hw;
+
+       ptr = devres_alloc(devm_clk_hw_release_gate, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       hw = __clk_hw_register_gate(dev, np, name, parent_name, parent_hw,
+                                   parent_data, flags, reg, bit_idx,
+                                   clk_gate_flags, lock);
+
+       if (!IS_ERR(hw)) {
+               *ptr = hw;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return hw;
+}
+EXPORT_SYMBOL_GPL(__devm_clk_hw_register_gate);
index b51069e..a23fa6d 100644 (file)
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(gemini_clk_lock);
 #define PCI_DLL_TAP_SEL_MASK           0x1f
 
 /**
- * struct gemini_data_data - Gemini gated clocks
+ * struct gemini_gate_data - Gemini gated clocks
  * @bit_idx: the bit used to gate this clock in the clock register
  * @name: the clock name
  * @parent_name: the name of the parent clock
diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c
new file mode 100644 (file)
index 0000000..d1535ac
--- /dev/null
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Microchip LAN966x SoC Clock driver.
+ *
+ * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
+ *
+ * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/microchip,lan966x.h>
+
+#define GCK_ENA         BIT(0)
+#define GCK_SRC_SEL     GENMASK(9, 8)
+#define GCK_PRESCALER   GENMASK(23, 16)
+
+#define DIV_MAX                255
+
+static const char *clk_names[N_CLOCKS] = {
+       "qspi0", "qspi1", "qspi2", "sdmmc0",
+       "pi", "mcan0", "mcan1", "flexcom0",
+       "flexcom1", "flexcom2", "flexcom3",
+       "flexcom4", "timer1", "usb_refclk",
+};
+
+struct lan966x_gck {
+       struct clk_hw hw;
+       void __iomem *reg;
+};
+#define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)
+
+static const struct clk_parent_data lan966x_gck_pdata[] = {
+       { .fw_name = "cpu", },
+       { .fw_name = "ddr", },
+       { .fw_name = "sys", },
+};
+
+static struct clk_init_data init = {
+       .parent_data = lan966x_gck_pdata,
+       .num_parents = ARRAY_SIZE(lan966x_gck_pdata),
+};
+
+struct clk_gate_soc_desc {
+       const char *name;
+       int bit_idx;
+};
+
+static const struct clk_gate_soc_desc clk_gate_desc[] = {
+       { "uhphs", 11 },
+       { "udphs", 10 },
+       { "mcramc", 9 },
+       { "hmatrix", 8 },
+       { }
+};
+
+static DEFINE_SPINLOCK(clk_gate_lock);
+static void __iomem *base;
+
+static int lan966x_gck_enable(struct clk_hw *hw)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 val = readl(gck->reg);
+
+       val |= GCK_ENA;
+       writel(val, gck->reg);
+
+       return 0;
+}
+
+static void lan966x_gck_disable(struct clk_hw *hw)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 val = readl(gck->reg);
+
+       val &= ~GCK_ENA;
+       writel(val, gck->reg);
+}
+
+static int lan966x_gck_set_rate(struct clk_hw *hw,
+                               unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 div, val = readl(gck->reg);
+
+       if (rate == 0 || parent_rate == 0)
+               return -EINVAL;
+
+       /* Set Prescalar */
+       div = parent_rate / rate;
+       val &= ~GCK_PRESCALER;
+       val |= FIELD_PREP(GCK_PRESCALER, (div - 1));
+       writel(val, gck->reg);
+
+       return 0;
+}
+
+static long lan966x_gck_round_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long *parent_rate)
+{
+       unsigned int div;
+
+       if (rate == 0 || *parent_rate == 0)
+               return -EINVAL;
+
+       if (rate >= *parent_rate)
+               return *parent_rate;
+
+       div = DIV_ROUND_CLOSEST(*parent_rate, rate);
+
+       return *parent_rate / div;
+}
+
+static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 div, val = readl(gck->reg);
+
+       div = FIELD_GET(GCK_PRESCALER, val);
+
+       return parent_rate / (div + 1);
+}
+
+static int lan966x_gck_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
+{
+       struct clk_hw *parent;
+       int i;
+
+       for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
+               parent = clk_hw_get_parent_by_index(hw, i);
+               if (!parent)
+                       continue;
+
+               /* Allowed prescaler divider range is 0-255 */
+               if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) {
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = clk_hw_get_rate(parent);
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static u8 lan966x_gck_get_parent(struct clk_hw *hw)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 val = readl(gck->reg);
+
+       return FIELD_GET(GCK_SRC_SEL, val);
+}
+
+static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct lan966x_gck *gck = to_lan966x_gck(hw);
+       u32 val = readl(gck->reg);
+
+       val &= ~GCK_SRC_SEL;
+       val |= FIELD_PREP(GCK_SRC_SEL, index);
+       writel(val, gck->reg);
+
+       return 0;
+}
+
+static const struct clk_ops lan966x_gck_ops = {
+       .enable         = lan966x_gck_enable,
+       .disable        = lan966x_gck_disable,
+       .set_rate       = lan966x_gck_set_rate,
+       .round_rate     = lan966x_gck_round_rate,
+       .recalc_rate    = lan966x_gck_recalc_rate,
+       .determine_rate = lan966x_gck_determine_rate,
+       .set_parent     = lan966x_gck_set_parent,
+       .get_parent     = lan966x_gck_get_parent,
+};
+
+static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
+{
+       struct lan966x_gck *priv;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return ERR_PTR(-ENOMEM);
+
+       priv->reg = base + (i * 4);
+       priv->hw.init = &init;
+       ret = devm_clk_hw_register(dev, &priv->hw);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return &priv->hw;
+};
+
+static int lan966x_gate_clk_register(struct device *dev,
+                                    struct clk_hw_onecell_data *hw_data,
+                                    void __iomem *gate_base)
+{
+       int i;
+
+       for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) {
+               int idx = i - GCK_GATE_UHPHS;
+
+               hw_data->hws[i] =
+                       devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name,
+                                                 "lan966x", 0, base,
+                                                 clk_gate_desc[idx].bit_idx,
+                                                 0, &clk_gate_lock);
+
+               if (IS_ERR(hw_data->hws[i]))
+                       return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
+                                            "failed to register %s clock\n",
+                                            clk_gate_desc[idx].name);
+       }
+
+       return 0;
+}
+
+static int lan966x_clk_probe(struct platform_device *pdev)
+{
+       struct clk_hw_onecell_data *hw_data;
+       struct device *dev = &pdev->dev;
+       void __iomem *gate_base;
+       struct resource *res;
+       int i, ret;
+
+       hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS),
+                              GFP_KERNEL);
+       if (!hw_data)
+               return -ENOMEM;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       init.ops = &lan966x_gck_ops;
+
+       hw_data->num = GCK_GATE_UHPHS;
+
+       for (i = 0; i < GCK_GATE_UHPHS; i++) {
+               init.name = clk_names[i];
+               hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
+               if (IS_ERR(hw_data->hws[i])) {
+                       dev_err(dev, "failed to register %s clock\n",
+                               init.name);
+                       return PTR_ERR(hw_data->hws[i]);
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (res) {
+               gate_base = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(gate_base))
+                       return PTR_ERR(gate_base);
+
+               hw_data->num = N_CLOCKS;
+
+               ret = lan966x_gate_clk_register(dev, hw_data, gate_base);
+               if (ret)
+                       return ret;
+       }
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
+}
+
+static const struct of_device_id lan966x_clk_dt_ids[] = {
+       { .compatible = "microchip,lan966x-gck", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);
+
+static struct platform_driver lan966x_clk_driver = {
+       .probe  = lan966x_clk_probe,
+       .driver = {
+               .name = "lan966x-clk",
+               .of_match_table = lan966x_clk_dt_ids,
+       },
+};
+builtin_platform_driver(lan966x_clk_driver);
+
+MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
+MODULE_DESCRIPTION("LAN966X clock driver");
+MODULE_LICENSE("GPL v2");
index af46176..473dfe6 100644 (file)
@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 20,      "spi5",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
-       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@@ -211,7 +210,6 @@ static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 20,      "spi5",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
-       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
@@ -286,7 +284,6 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 23,      "sai2",         "apb2_div" },
-       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
@@ -364,7 +361,6 @@ static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 23,      "sai2",         "apb2_div" },
-       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 30,      "mdio",         "apb2_div" },
 };
 
index 4bd1fe7..863274a 100644 (file)
@@ -2253,8 +2253,6 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base,
        const struct stm32_rcc_match_data *data = match->data;
        struct stm32_reset_data *reset_data = NULL;
 
-       data = match->data;
-
        reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
        if (!reset_data)
                return -ENOMEM;
diff --git a/drivers/clk/clk-tps68470.c b/drivers/clk/clk-tps68470.c
new file mode 100644 (file)
index 0000000..e5fbefd
--- /dev/null
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for TPS68470 PMIC
+ *
+ * Copyright (c) 2021 Red Hat Inc.
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Authors:
+ *     Hans de Goede <hdegoede@redhat.com>
+ *     Zaikuo Wang <zaikuo.wang@intel.com>
+ *     Tianshu Qiu <tian.shu.qiu@intel.com>
+ *     Jian Xu Zheng <jian.xu.zheng@intel.com>
+ *     Yuning Pu <yuning.pu@intel.com>
+ *     Antti Laakso <antti.laakso@intel.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps68470.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/tps68470.h>
+#include <linux/regmap.h>
+
+#define TPS68470_CLK_NAME "tps68470-clk"
+
+#define to_tps68470_clkdata(clkd) \
+       container_of(clkd, struct tps68470_clkdata, clkout_hw)
+
+static struct tps68470_clkout_freqs {
+       unsigned long freq;
+       unsigned int xtaldiv;
+       unsigned int plldiv;
+       unsigned int postdiv;
+       unsigned int buckdiv;
+       unsigned int boostdiv;
+} clk_freqs[] = {
+/*
+ *  The PLL is used to multiply the crystal oscillator
+ *  frequency range of 3 MHz to 27 MHz by a programmable
+ *  factor of F = (M/N)*(1/P) such that the output
+ *  available at the HCLK_A or HCLK_B pins are in the range
+ *  of 4 MHz to 64 MHz in increments of 0.1 MHz.
+ *
+ * hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv)
+ *
+ * PLL_REF_CLK should be as close as possible to 100kHz
+ * PLL_REF_CLK = input clk / XTALDIV[7:0] + 30)
+ *
+ * PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320))
+ *
+ * BOOST should be as close as possible to 2Mhz
+ * BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) *
+ *
+ * BUCK should be as close as possible to 5.2Mhz
+ * BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5)
+ *
+ * osc_in   xtaldiv  plldiv   postdiv   hclk_#
+ * 20Mhz    170      32       1         19.2Mhz
+ * 20Mhz    170      40       1         20Mhz
+ * 20Mhz    170      80       1         24Mhz
+ */
+       { 19200000, 170, 32, 1, 2, 3 },
+       { 20000000, 170, 40, 1, 3, 4 },
+       { 24000000, 170, 80, 1, 4, 8 },
+};
+
+struct tps68470_clkdata {
+       struct clk_hw clkout_hw;
+       struct regmap *regmap;
+       unsigned long rate;
+};
+
+static int tps68470_clk_is_prepared(struct clk_hw *hw)
+{
+       struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
+       int val;
+
+       if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val))
+               return 0;
+
+       return val & TPS68470_PLL_EN_MASK;
+}
+
+static int tps68470_clk_prepare(struct clk_hw *hw)
+{
+       struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
+
+       regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1,
+                          (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_A_SHIFT) |
+                          (TPS68470_PLL_OUTPUT_ENABLE << TPS68470_OUTPUT_B_SHIFT));
+
+       regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL,
+                          TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK);
+
+       /*
+        * The PLLCTL reg lock bit is set by the PMIC after approx. 4ms and
+        * does not indicate a true lock, so just wait 4 ms.
+        */
+       usleep_range(4000, 5000);
+
+       return 0;
+}
+
+static void tps68470_clk_unprepare(struct clk_hw *hw)
+{
+       struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
+
+       /* Disable clock first ... */
+       regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0);
+
+       /* ... and then tri-state the clock outputs. */
+       regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0);
+}
+
+static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+       struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
+
+       return clkdata->rate;
+}
+
+/*
+ * This returns the index of the clk_freqs[] cfg with the closest rate for
+ * use in tps68470_clk_round_rate(). tps68470_clk_set_rate() checks that
+ * the rate of the returned cfg is an exact match.
+ */
+static unsigned int tps68470_clk_cfg_lookup(unsigned long rate)
+{
+       long diff, best_diff = LONG_MAX;
+       unsigned int i, best_idx = 0;
+
+       for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) {
+               diff = clk_freqs[i].freq - rate;
+               if (diff == 0)
+                       return i;
+
+               diff = abs(diff);
+               if (diff < best_diff) {
+                       best_diff = diff;
+                       best_idx = i;
+               }
+       }
+
+       return best_idx;
+}
+
+static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long *parent_rate)
+{
+       unsigned int idx = tps68470_clk_cfg_lookup(rate);
+
+       return clk_freqs[idx].freq;
+}
+
+static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw);
+       unsigned int idx = tps68470_clk_cfg_lookup(rate);
+
+       if (rate != clk_freqs[idx].freq)
+               return -EINVAL;
+
+       regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT);
+       regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv);
+       regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA);
+
+       regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL,
+                    TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT |
+                    TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT);
+
+       clkdata->rate = rate;
+
+       return 0;
+}
+
+static const struct clk_ops tps68470_clk_ops = {
+       .is_prepared = tps68470_clk_is_prepared,
+       .prepare = tps68470_clk_prepare,
+       .unprepare = tps68470_clk_unprepare,
+       .recalc_rate = tps68470_clk_recalc_rate,
+       .round_rate = tps68470_clk_round_rate,
+       .set_rate = tps68470_clk_set_rate,
+};
+
+static int tps68470_clk_probe(struct platform_device *pdev)
+{
+       struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data;
+       struct clk_init_data tps68470_clk_initdata = {
+               .name = TPS68470_CLK_NAME,
+               .ops = &tps68470_clk_ops,
+               /* Changing the dividers when the PLL is on is not allowed */
+               .flags = CLK_SET_RATE_GATE,
+       };
+       struct tps68470_clkdata *tps68470_clkdata;
+       int ret;
+
+       tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
+                                       GFP_KERNEL);
+       if (!tps68470_clkdata)
+               return -ENOMEM;
+
+       tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent);
+       tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata;
+
+       /* Set initial rate */
+       tps68470_clk_set_rate(&tps68470_clkdata->clkout_hw, clk_freqs[0].freq, 0);
+
+       ret = devm_clk_hw_register(&pdev->dev, &tps68470_clkdata->clkout_hw);
+       if (ret)
+               return ret;
+
+       ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw,
+                                         TPS68470_CLK_NAME, NULL);
+       if (ret)
+               return ret;
+
+       if (pdata) {
+               ret = devm_clk_hw_register_clkdev(&pdev->dev,
+                                                 &tps68470_clkdata->clkout_hw,
+                                                 pdata->consumer_con_id,
+                                                 pdata->consumer_dev_name);
+       }
+
+       return ret;
+}
+
+static struct platform_driver tps68470_clk_driver = {
+       .driver = {
+               .name = TPS68470_CLK_NAME,
+       },
+       .probe = tps68470_clk_probe,
+};
+
+/*
+ * The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers
+ * registering before the drivers for the camera-sensors which use them bind.
+ * subsys_initcall() ensures this when the drivers are builtin.
+ */
+static int __init tps68470_clk_init(void)
+{
+       return platform_driver_register(&tps68470_clk_driver);
+}
+subsys_initcall(tps68470_clk_init);
+
+static void __exit tps68470_clk_exit(void)
+{
+       platform_driver_unregister(&tps68470_clk_driver);
+}
+module_exit(tps68470_clk_exit);
+
+MODULE_ALIAS("platform:tps68470-clk");
+MODULE_DESCRIPTION("clock driver for TPS68470 pmic");
+MODULE_LICENSE("GPL");
index f467d63..c3c4849 100644 (file)
@@ -424,19 +424,20 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
 
        if (entry->hw) {
                parent = entry->hw->core;
-               /*
-                * We have a direct reference but it isn't registered yet?
-                * Orphan it and let clk_reparent() update the orphan status
-                * when the parent is registered.
-                */
-               if (!parent)
-                       parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
                if (PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
+       /*
+        * We have a direct reference but it isn't registered yet?
+        * Orphan it and let clk_reparent() update the orphan status
+        * when the parent is registered.
+        */
+       if (!parent)
+               parent = ERR_PTR(-EPROBE_DEFER);
+
        /* Only cache it if it's not an error */
        if (!IS_ERR(parent))
                entry->core = parent;
@@ -2965,7 +2966,9 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 {
        struct clk_core *child;
 
+       clk_pm_runtime_get(c);
        clk_summary_show_one(s, c, level);
+       clk_pm_runtime_put(c);
 
        hlist_for_each_entry(child, &c->children, child_node)
                clk_summary_show_subtree(s, child, level + 1);
@@ -3217,6 +3220,42 @@ static int current_parent_show(struct seq_file *s, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(current_parent);
 
+#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
+static ssize_t current_parent_write(struct file *file, const char __user *ubuf,
+                                   size_t count, loff_t *ppos)
+{
+       struct seq_file *s = file->private_data;
+       struct clk_core *core = s->private;
+       struct clk_core *parent;
+       u8 idx;
+       int err;
+
+       err = kstrtou8_from_user(ubuf, count, 0, &idx);
+       if (err < 0)
+               return err;
+
+       parent = clk_core_get_parent_by_index(core, idx);
+       if (!parent)
+               return -ENOENT;
+
+       clk_prepare_lock();
+       err = clk_core_set_parent_nolock(core, parent);
+       clk_prepare_unlock();
+       if (err)
+               return err;
+
+       return count;
+}
+
+static const struct file_operations current_parent_rw_fops = {
+       .open           = current_parent_open,
+       .write          = current_parent_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
 static int clk_duty_cycle_show(struct seq_file *s, void *data)
 {
        struct clk_core *core = s->private;
@@ -3282,8 +3321,12 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 #ifdef CLOCK_ALLOW_WRITE_DEBUGFS
        debugfs_create_file("clk_prepare_enable", 0644, root, core,
                            &clk_prepare_enable_fops);
-#endif
 
+       if (core->num_parents > 1)
+               debugfs_create_file("clk_parent", 0644, root, core,
+                                   &current_parent_rw_fops);
+       else
+#endif
        if (core->num_parents > 0)
                debugfs_create_file("clk_parent", 0444, root, core,
                                    &current_parent_fops);
@@ -3343,6 +3386,24 @@ static int __init clk_debug_init(void)
 {
        struct clk_core *core;
 
+#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
+       pr_warn("\n");
+       pr_warn("********************************************************************\n");
+       pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE           **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("**  WRITEABLE clk DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("** This means that this kernel is built to expose clk operations  **\n");
+       pr_warn("** such as parent or rate setting, enabling, disabling, etc.      **\n");
+       pr_warn("** to userspace, which may compromise security on your system.    **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("** If you see this message and you are not debugging the          **\n");
+       pr_warn("** kernel, report this immediately to your vendor!                **\n");
+       pr_warn("**                                                                **\n");
+       pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE           **\n");
+       pr_warn("********************************************************************\n");
+#endif
+
        rootdir = debugfs_create_dir("clk", NULL);
 
        debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
@@ -3413,9 +3474,6 @@ static int __clk_core_init(struct clk_core *core)
        unsigned long rate;
        int phase;
 
-       if (!core)
-               return -EINVAL;
-
        clk_prepare_lock();
 
        ret = clk_pm_runtime_get(core);
index 36ffb05..93ee81b 100644 (file)
@@ -8,20 +8,19 @@
 
 #include "clk.h"
 
+#define MFN_BITS       (10)
+#define MFN_SIGN       (BIT(MFN_BITS - 1))
+#define MFN_MASK       (MFN_SIGN - 1)
+
 /**
- * pll v1
+ * struct clk_pllv1 - IMX PLLv1 clock descriptor
  *
- * @clk_hw     clock source
- * @parent     the parent clock name
- * @base       base address of pll registers
+ * @hw:                clock source
+ * @base:      base address of pll registers
+ * @type:      type of IMX_PLLV1
  *
  * PLL clock version 1, found on i.MX1/21/25/27/31/35
  */
-
-#define MFN_BITS       (10)
-#define MFN_SIGN       (BIT(MFN_BITS - 1))
-#define MFN_MASK       (MFN_SIGN - 1)
-
 struct clk_pllv1 {
        struct clk_hw   hw;
        void __iomem    *base;
index d6eed76..608e0e8 100644 (file)
@@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = {
 };
 
 static struct clk_regmap gxbb_mpll0_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 25,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .lock = &meson_clk_lock,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll_prediv.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap gxl_mpll0_div = {
        .data = &(struct meson_clk_mpll_data){
                .sdm = {
                        .reg_off = HHI_MPLL_CNTL7,
@@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = {
        .hw.init = &(struct clk_init_data){
                .name = "mpll0",
                .ops = &clk_regmap_gate_ops,
-               .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
+               .parent_data = &(const struct clk_parent_data) {
+                       /*
+                        * Note:
+                        * GXL and GXBB have different SDM_EN registers. We
+                        * fallback to the global naming string mechanism so
+                        * mpll0_div picks up the appropriate one.
+                        */
+                       .name = "mpll0_div",
+                       .index = -1,
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
@@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
                [CLKID_VAPB_1]              = &gxbb_vapb_1.hw,
                [CLKID_VAPB_SEL]            = &gxbb_vapb_sel.hw,
                [CLKID_VAPB]                = &gxbb_vapb.hw,
-               [CLKID_MPLL0_DIV]           = &gxbb_mpll0_div.hw,
+               [CLKID_MPLL0_DIV]           = &gxl_mpll0_div.hw,
                [CLKID_MPLL1_DIV]           = &gxbb_mpll1_div.hw,
                [CLKID_MPLL2_DIV]           = &gxbb_mpll2_div.hw,
                [CLKID_MPLL_PREDIV]         = &gxbb_mpll_prediv.hw,
@@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = {
        &gxbb_mpll0,
        &gxbb_mpll1,
        &gxbb_mpll2,
-       &gxbb_mpll0_div,
+       &gxl_mpll0_div,
        &gxbb_mpll1_div,
        &gxbb_mpll2_div,
        &gxbb_cts_amclk_div,
index 6d02807..be6e6ae 100644 (file)
@@ -31,6 +31,7 @@ config CLK_RENESAS
        select CLK_R8A77990 if ARCH_R8A77990
        select CLK_R8A77995 if ARCH_R8A77995
        select CLK_R8A779A0 if ARCH_R8A779A0
+       select CLK_R8A779F0 if ARCH_R8A779F0
        select CLK_R9A06G032 if ARCH_R9A06G032
        select CLK_R9A07G044 if ARCH_R9A07G044
        select CLK_SH73A0 if ARCH_SH73A0
@@ -149,8 +150,11 @@ config CLK_R8A77995
 
 config CLK_R8A779A0
        bool "R-Car V3U clock support" if COMPILE_TEST
-       select CLK_RCAR_CPG_LIB
-       select CLK_RENESAS_CPG_MSSR
+       select CLK_RCAR_GEN4_CPG
+
+config CLK_R8A779F0
+       bool "R-Car S4-8 clock support" if COMPILE_TEST
+       select CLK_RCAR_GEN4_CPG
 
 config CLK_R9A06G032
        bool "RZ/N1D clock support" if COMPILE_TEST
@@ -178,6 +182,11 @@ config CLK_RCAR_GEN3_CPG
        select CLK_RCAR_CPG_LIB
        select CLK_RENESAS_CPG_MSSR
 
+config CLK_RCAR_GEN4_CPG
+       bool "R-Car Gen4 clock support" if COMPILE_TEST
+       select CLK_RCAR_CPG_LIB
+       select CLK_RENESAS_CPG_MSSR
+
 config CLK_RCAR_USB2_CLOCK_SEL
        bool "Renesas R-Car USB2 clock selector support"
        depends on ARCH_RENESAS || COMPILE_TEST
index 7d01870..8b34db1 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_CLK_R8A77980)            += r8a77980-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77990)             += r8a77990-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77995)             += r8a77995-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A779A0)             += r8a779a0-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A779F0)             += r8a779f0-cpg-mssr.o
 obj-$(CONFIG_CLK_R9A06G032)            += r9a06g032-clocks.o
 obj-$(CONFIG_CLK_R9A07G044)            += r9a07g044-cpg.o
 obj-$(CONFIG_CLK_SH73A0)               += clk-sh73a0.o
@@ -36,6 +37,7 @@ obj-$(CONFIG_CLK_SH73A0)              += clk-sh73a0.o
 obj-$(CONFIG_CLK_RCAR_CPG_LIB)         += rcar-cpg-lib.o
 obj-$(CONFIG_CLK_RCAR_GEN2_CPG)                += rcar-gen2-cpg.o
 obj-$(CONFIG_CLK_RCAR_GEN3_CPG)                += rcar-gen3-cpg.o
+obj-$(CONFIG_CLK_RCAR_GEN4_CPG)                += rcar-gen4-cpg.o
 obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL)  += rcar-usb2-clock-sel.o
 obj-$(CONFIG_CLK_RZG2L)                        += rzg2l-cpg.o
 
index 39b185d..95dd56b 100644 (file)
@@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774A1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774A1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774A1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774A1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774A1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774A1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774A1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774A1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774A1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774A1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774A1_CLK_SD0,   R8A774A1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774A1_CLK_SD1,   R8A774A1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774A1_CLK_SD2,   R8A774A1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774A1_CLK_SD3,   R8A774A1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774A1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A774A1_CLK_CP,    CLK_EXTAL,      2, 1),
index af602d8..56061b9 100644 (file)
@@ -97,10 +97,14 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774B1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774B1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774B1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774B1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774B1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774B1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774B1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774B1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774B1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774B1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774B1_CLK_SD0,   R8A774B1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774B1_CLK_SD1,   R8A774B1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774B1_CLK_SD2,   R8A774B1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774B1_CLK_SD3,   R8A774B1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774B1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A774B1_CLK_CP,    CLK_EXTAL,      2, 1),
index 5b938eb..b5eb5dc 100644 (file)
@@ -108,9 +108,12 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
        DEF_FIXED("s3d2",      R8A774C0_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",      R8A774C0_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",     R8A774C0_CLK_SD0,   CLK_SDSRC,     0x0074),
-       DEF_GEN3_SD("sd1",     R8A774C0_CLK_SD1,   CLK_SDSRC,     0x0078),
-       DEF_GEN3_SD("sd3",     R8A774C0_CLK_SD3,   CLK_SDSRC,     0x026c),
+       DEF_GEN3_SDH("sd0h",   R8A774C0_CLK_SD0H, CLK_SDSRC,         0x0074),
+       DEF_GEN3_SDH("sd1h",   R8A774C0_CLK_SD1H, CLK_SDSRC,         0x0078),
+       DEF_GEN3_SDH("sd3h",   R8A774C0_CLK_SD3H, CLK_SDSRC,         0x026c),
+       DEF_GEN3_SD("sd0",     R8A774C0_CLK_SD0,  R8A774C0_CLK_SD0H, 0x0074),
+       DEF_GEN3_SD("sd1",     R8A774C0_CLK_SD1,  R8A774C0_CLK_SD1H, 0x0078),
+       DEF_GEN3_SD("sd3",     R8A774C0_CLK_SD3,  R8A774C0_CLK_SD3H, 0x026c),
 
        DEF_FIXED("cl",        R8A774C0_CLK_CL,    CLK_PLL1,      48, 1),
        DEF_FIXED("cp",        R8A774C0_CLK_CP,    CLK_EXTAL,      2, 1),
index 40c7146..2950f0d 100644 (file)
@@ -100,10 +100,14 @@ static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A774E1_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A774E1_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A774E1_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A774E1_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A774E1_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A774E1_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A774E1_CLK_SD0H,  CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A774E1_CLK_SD1H,  CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A774E1_CLK_SD2H,  CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A774E1_CLK_SD3H,  CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A774E1_CLK_SD0,   R8A774E1_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A774E1_CLK_SD1,   R8A774E1_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A774E1_CLK_SD2,   R8A774E1_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A774E1_CLK_SD3,   R8A774E1_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A774E1_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A774E1_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index d6b1d01..991a443 100644 (file)
@@ -104,10 +104,14 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
        DEF_FIXED("s3d2",       R8A7795_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7795_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A7795_CLK_SD0H,  CLK_SDSRC,        0x074),
+       DEF_GEN3_SDH("sd1h",    R8A7795_CLK_SD1H,  CLK_SDSRC,        0x078),
+       DEF_GEN3_SDH("sd2h",    R8A7795_CLK_SD2H,  CLK_SDSRC,        0x268),
+       DEF_GEN3_SDH("sd3h",    R8A7795_CLK_SD3H,  CLK_SDSRC,        0x26c),
+       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   R8A7795_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   R8A7795_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   R8A7795_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   R8A7795_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A7795_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A7795_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index 9c22977..7950313 100644 (file)
@@ -106,10 +106,14 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A7796_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7796_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   CLK_SDSRC,     0x074),
-       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   CLK_SDSRC,     0x078),
-       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   CLK_SDSRC,     0x268),
-       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   CLK_SDSRC,     0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A7796_CLK_SD0H,  CLK_SDSRC,        0x074),
+       DEF_GEN3_SDH("sd1h",    R8A7796_CLK_SD1H,  CLK_SDSRC,        0x078),
+       DEF_GEN3_SDH("sd2h",    R8A7796_CLK_SD2H,  CLK_SDSRC,        0x268),
+       DEF_GEN3_SDH("sd3h",    R8A7796_CLK_SD3H,  CLK_SDSRC,        0x26c),
+       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   R8A7796_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   R8A7796_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   R8A7796_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   R8A7796_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A7796_CLK_CR,    CLK_PLL1_DIV4,  2, 1),
index 7eee45a..d687c29 100644 (file)
@@ -101,10 +101,14 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A77965_CLK_S3D2,      CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A77965_CLK_S3D4,      CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A77965_CLK_SD0,       CLK_SDSRC,      0x074),
-       DEF_GEN3_SD("sd1",      R8A77965_CLK_SD1,       CLK_SDSRC,      0x078),
-       DEF_GEN3_SD("sd2",      R8A77965_CLK_SD2,       CLK_SDSRC,      0x268),
-       DEF_GEN3_SD("sd3",      R8A77965_CLK_SD3,       CLK_SDSRC,      0x26c),
+       DEF_GEN3_SDH("sd0h",    R8A77965_CLK_SD0H,      CLK_SDSRC,         0x074),
+       DEF_GEN3_SDH("sd1h",    R8A77965_CLK_SD1H,      CLK_SDSRC,         0x078),
+       DEF_GEN3_SDH("sd2h",    R8A77965_CLK_SD2H,      CLK_SDSRC,         0x268),
+       DEF_GEN3_SDH("sd3h",    R8A77965_CLK_SD3H,      CLK_SDSRC,         0x26c),
+       DEF_GEN3_SD("sd0",      R8A77965_CLK_SD0,       R8A77965_CLK_SD0H, 0x074),
+       DEF_GEN3_SD("sd1",      R8A77965_CLK_SD1,       R8A77965_CLK_SD1H, 0x078),
+       DEF_GEN3_SD("sd2",      R8A77965_CLK_SD2,       R8A77965_CLK_SD2H, 0x268),
+       DEF_GEN3_SD("sd3",      R8A77965_CLK_SD3,       R8A77965_CLK_SD3H, 0x26c),
 
        DEF_FIXED("cl",         R8A77965_CLK_CL,        CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cr",         R8A77965_CLK_CR,        CLK_PLL1_DIV4,  2, 1),
index 9fe3722..f3cd64d 100644 (file)
@@ -96,7 +96,8 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A77980_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A77980_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A77980_CLK_SD0,   CLK_SDSRC,    0x0074),
+       DEF_GEN3_SDH("sd0h",    R8A77980_CLK_SD0H,  CLK_SDSRC,         0x0074),
+       DEF_GEN3_SD("sd0",      R8A77980_CLK_SD0,   R8A77980_CLK_SD0H, 0x0074),
 
        DEF_FIXED("cl",         R8A77980_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A77980_CLK_CP,    CLK_EXTAL,      2, 1),
index a582f2e..faf60f7 100644 (file)
@@ -100,9 +100,12 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
        DEF_FIXED("s3d2",      R8A77990_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",      R8A77990_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",     R8A77990_CLK_SD0,   CLK_SDSRC,     0x0074),
-       DEF_GEN3_SD("sd1",     R8A77990_CLK_SD1,   CLK_SDSRC,     0x0078),
-       DEF_GEN3_SD("sd3",     R8A77990_CLK_SD3,   CLK_SDSRC,     0x026c),
+       DEF_GEN3_SDH("sd0h",   R8A77990_CLK_SD0H,  CLK_SDSRC,         0x0074),
+       DEF_GEN3_SDH("sd1h",   R8A77990_CLK_SD1H,  CLK_SDSRC,         0x0078),
+       DEF_GEN3_SDH("sd3h",   R8A77990_CLK_SD3H,  CLK_SDSRC,         0x026c),
+       DEF_GEN3_SD("sd0",     R8A77990_CLK_SD0,   R8A77990_CLK_SD0H, 0x0074),
+       DEF_GEN3_SD("sd1",     R8A77990_CLK_SD1,   R8A77990_CLK_SD1H, 0x0078),
+       DEF_GEN3_SD("sd3",     R8A77990_CLK_SD3,   R8A77990_CLK_SD3H, 0x026c),
 
        DEF_FIXED("cl",        R8A77990_CLK_CL,    CLK_PLL1,      48, 1),
        DEF_FIXED("cr",        R8A77990_CLK_CR,    CLK_PLL1D2,     2, 1),
index 81c0bc1..7713cfd 100644 (file)
@@ -103,7 +103,8 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
        DEF_GEN3_PE("s3d2c",   R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
        DEF_GEN3_PE("s3d4c",   R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
 
-       DEF_GEN3_SD("sd0",     R8A77995_CLK_SD0,   CLK_SDSRC,     0x268),
+       DEF_GEN3_SDH("sd0h",   R8A77995_CLK_SD0H, CLK_SDSRC,         0x268),
+       DEF_GEN3_SD("sd0",     R8A77995_CLK_SD0,  R8A77995_CLK_SD0H, 0x268),
 
        DEF_DIV6P1("canfd",    R8A77995_CLK_CANFD, CLK_PLL0D3,    0x244),
        DEF_DIV6P1("mso",      R8A77995_CLK_MSO,   CLK_PLL1D2,    0x014),
index fbd7454..1c09d4e 100644 (file)
  * Copyright (C) 2015 Renesas Electronics Corp.
  */
 
-#include <linux/bug.h>
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/init.h>
-#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/pm.h>
-#include <linux/slab.h>
 #include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
 
-#include "rcar-cpg-lib.h"
 #include "renesas-cpg-mssr.h"
-
-enum rcar_r8a779a0_clk_types {
-       CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM,
-       CLK_TYPE_R8A779A0_PLL1,
-       CLK_TYPE_R8A779A0_PLL2X_3X,     /* PLL[23][01] */
-       CLK_TYPE_R8A779A0_PLL5,
-       CLK_TYPE_R8A779A0_Z,
-       CLK_TYPE_R8A779A0_SD,
-       CLK_TYPE_R8A779A0_MDSEL,        /* Select parent/divider using mode pin */
-       CLK_TYPE_R8A779A0_OSC,  /* OSC EXTAL predivider and fixed divider */
-       CLK_TYPE_R8A779A0_RPCSRC,
-       CLK_TYPE_R8A779A0_RPC,
-       CLK_TYPE_R8A779A0_RPCD2,
-};
-
-struct rcar_r8a779a0_cpg_pll_config {
-       u8 extal_div;
-       u8 pll1_mult;
-       u8 pll1_div;
-       u8 pll5_mult;
-       u8 pll5_div;
-       u8 osc_prediv;
-};
+#include "rcar-gen4-cpg.h"
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
@@ -85,33 +58,18 @@ enum clk_ids {
 };
 
 #define DEF_PLL(_name, _id, _offset)   \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_PLL2X_3X, CLK_MAIN, \
                 .offset = _offset)
 
-#define DEF_Z(_name, _id, _parent, _div, _offset)      \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_Z, _parent, .div = _div, \
-                .offset = _offset)
-
-#define DEF_SD(_name, _id, _parent, _offset)   \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
-
-#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL,   \
-                (_parent0) << 16 | (_parent1),         \
-                .div = (_div0) << 16 | (_div1), .offset = _md)
-
-#define DEF_OSC(_name, _id, _parent, _div)             \
-       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div)
-
 static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        /* External Clock Inputs */
        DEF_INPUT("extal",  CLK_EXTAL),
        DEF_INPUT("extalr", CLK_EXTALR),
 
        /* Internal Core Clocks */
-       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_R8A779A0_MAIN, CLK_EXTAL),
-       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_R8A779A0_PLL1, CLK_MAIN),
-       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_R8A779A0_PLL5, CLK_MAIN),
+       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_GEN4_PLL5, CLK_MAIN),
        DEF_PLL(".pll20", CLK_PLL20,    0x0834),
        DEF_PLL(".pll21", CLK_PLL21,    0x0838),
        DEF_PLL(".pll30", CLK_PLL30,    0x083c),
@@ -128,14 +86,14 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        DEF_FIXED(".s3",                CLK_S3,         CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED(".sdsrc",             CLK_SDSRC,      CLK_PLL5_DIV4,  1, 1),
        DEF_RATE(".oco",                CLK_OCO,        32768),
-       DEF_BASE(".rpcsrc",      CLK_RPCSRC,       CLK_TYPE_R8A779A0_RPCSRC, CLK_PLL5),
-       DEF_BASE("rpc",          R8A779A0_CLK_RPC, CLK_TYPE_R8A779A0_RPC, CLK_RPCSRC),
-       DEF_BASE("rpcd2",        R8A779A0_CLK_RPCD2, CLK_TYPE_R8A779A0_RPCD2,
+       DEF_BASE(".rpcsrc",      CLK_RPCSRC,       CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+       DEF_BASE("rpc",          R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+       DEF_BASE("rpcd2",        R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2,
                 R8A779A0_CLK_RPC),
 
        /* Core Clock Outputs */
-       DEF_Z("z0",             R8A779A0_CLK_Z0,        CLK_PLL20,      2, 0),
-       DEF_Z("z1",             R8A779A0_CLK_Z1,        CLK_PLL21,      2, 8),
+       DEF_GEN4_Z("z0",        R8A779A0_CLK_Z0,        CLK_TYPE_GEN4_Z,        CLK_PLL20,      2, 0),
+       DEF_GEN4_Z("z1",        R8A779A0_CLK_Z1,        CLK_TYPE_GEN4_Z,        CLK_PLL21,      2, 8),
        DEF_FIXED("zx",         R8A779A0_CLK_ZX,        CLK_PLL20_DIV2, 2, 1),
        DEF_FIXED("s1d1",       R8A779A0_CLK_S1D1,      CLK_S1,         1, 1),
        DEF_FIXED("s1d2",       R8A779A0_CLK_S1D2,      CLK_S1,         2, 1),
@@ -159,15 +117,16 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        DEF_FIXED("cp",         R8A779A0_CLK_CP,        CLK_EXTAL,      2, 1),
        DEF_FIXED("cl16mck",    R8A779A0_CLK_CL16MCK,   CLK_PLL1_DIV2,  64, 1),
 
-       DEF_SD("sd0",           R8A779A0_CLK_SD0,       CLK_SDSRC,      0x870),
+       DEF_GEN4_SDH("sdh0",    R8A779A0_CLK_SD0H,      CLK_SDSRC,         0x870),
+       DEF_GEN4_SD("sd0",      R8A779A0_CLK_SD0,       R8A779A0_CLK_SD0H, 0x870),
 
        DEF_DIV6P1("mso",       R8A779A0_CLK_MSO,       CLK_PLL5_DIV4,  0x87c),
        DEF_DIV6P1("canfd",     R8A779A0_CLK_CANFD,     CLK_PLL5_DIV4,  0x878),
        DEF_DIV6P1("csi0",      R8A779A0_CLK_CSI0,      CLK_PLL5_DIV4,  0x880),
        DEF_DIV6P1("dsi",       R8A779A0_CLK_DSI,       CLK_PLL5_DIV4,  0x884),
 
-       DEF_OSC("osc",          R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
-       DEF_MDSEL("r",          R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+       DEF_GEN4_OSC("osc",     R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
+       DEF_GEN4_MDSEL("r",     R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
 };
 
 static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
@@ -271,256 +230,6 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
        DEF_MOD("vspx3",        1031,   R8A779A0_CLK_S1D1),
 };
 
-static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
-static unsigned int cpg_clk_extalr __initdata;
-static u32 cpg_mode __initdata;
-
-/*
- * Z0 Clock & Z1 Clock
- */
-#define CPG_FRQCRB                     0x00000804
-#define CPG_FRQCRB_KICK                        BIT(31)
-#define CPG_FRQCRC                     0x00000808
-
-struct cpg_z_clk {
-       struct clk_hw hw;
-       void __iomem *reg;
-       void __iomem *kick_reg;
-       unsigned long max_rate;         /* Maximum rate for normal mode */
-       unsigned int fixed_div;
-       u32 mask;
-};
-
-#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
-
-static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
-                                          unsigned long parent_rate)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int mult;
-       u32 val;
-
-       val = readl(zclk->reg) & zclk->mask;
-       mult = 32 - (val >> __ffs(zclk->mask));
-
-       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
-                                    32 * zclk->fixed_div);
-}
-
-static int cpg_z_clk_determine_rate(struct clk_hw *hw,
-                                   struct clk_rate_request *req)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int min_mult, max_mult, mult;
-       unsigned long rate, prate;
-
-       rate = min(req->rate, req->max_rate);
-       if (rate <= zclk->max_rate) {
-               /* Set parent rate to initial value for normal modes */
-               prate = zclk->max_rate;
-       } else {
-               /* Set increased parent rate for boost modes */
-               prate = rate;
-       }
-       req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
-                                                 prate * zclk->fixed_div);
-
-       prate = req->best_parent_rate / zclk->fixed_div;
-       min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
-       max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
-       if (max_mult < min_mult)
-               return -EINVAL;
-
-       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
-       mult = clamp(mult, min_mult, max_mult);
-
-       req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
-       return 0;
-}
-
-static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long parent_rate)
-{
-       struct cpg_z_clk *zclk = to_z_clk(hw);
-       unsigned int mult;
-       unsigned int i;
-
-       mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
-                                      parent_rate);
-       mult = clamp(mult, 1U, 32U);
-
-       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
-               return -EBUSY;
-
-       cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
-
-       /*
-        * Set KICK bit in FRQCRB to update hardware setting and wait for
-        * clock change completion.
-        */
-       cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
-
-       /*
-        * Note: There is no HW information about the worst case latency.
-        *
-        * Using experimental measurements, it seems that no more than
-        * ~10 iterations are needed, independently of the CPU rate.
-        * Since this value might be dependent on external xtal rate, pll1
-        * rate or even the other emulation clocks rate, use 1000 as a
-        * "super" safe value.
-        */
-       for (i = 1000; i; i--) {
-               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
-                       return 0;
-
-               cpu_relax();
-       }
-
-       return -ETIMEDOUT;
-}
-
-static const struct clk_ops cpg_z_clk_ops = {
-       .recalc_rate = cpg_z_clk_recalc_rate,
-       .determine_rate = cpg_z_clk_determine_rate,
-       .set_rate = cpg_z_clk_set_rate,
-};
-
-static struct clk * __init cpg_z_clk_register(const char *name,
-                                             const char *parent_name,
-                                             void __iomem *reg,
-                                             unsigned int div,
-                                             unsigned int offset)
-{
-       struct clk_init_data init = {};
-       struct cpg_z_clk *zclk;
-       struct clk *clk;
-
-       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
-       if (!zclk)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = name;
-       init.ops = &cpg_z_clk_ops;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       zclk->reg = reg + CPG_FRQCRC;
-       zclk->kick_reg = reg + CPG_FRQCRB;
-       zclk->hw.init = &init;
-       zclk->mask = GENMASK(offset + 4, offset);
-       zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
-
-       clk = clk_register(NULL, &zclk->hw);
-       if (IS_ERR(clk)) {
-               kfree(zclk);
-               return clk;
-       }
-
-       zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
-                        zclk->fixed_div;
-       return clk;
-}
-
-/*
- * RPC Clocks
- */
-#define CPG_RPCCKCR 0x874
-
-static const struct clk_div_table cpg_rpcsrc_div_table[] = {
-       { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
-};
-
-static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
-       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
-       struct clk **clks, void __iomem *base,
-       struct raw_notifier_head *notifiers)
-{
-       const struct clk *parent;
-       unsigned int mult = 1;
-       unsigned int div = 1;
-       u32 value;
-
-       parent = clks[core->parent & 0xffff];   /* some types use high bits */
-       if (IS_ERR(parent))
-               return ERR_CAST(parent);
-
-       switch (core->type) {
-       case CLK_TYPE_R8A779A0_MAIN:
-               div = cpg_pll_config->extal_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL1:
-               mult = cpg_pll_config->pll1_mult;
-               div = cpg_pll_config->pll1_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL2X_3X:
-               value = readl(base + core->offset);
-               mult = (((value >> 24) & 0x7f) + 1) * 2;
-               break;
-
-       case CLK_TYPE_R8A779A0_PLL5:
-               mult = cpg_pll_config->pll5_mult;
-               div = cpg_pll_config->pll5_div;
-               break;
-
-       case CLK_TYPE_R8A779A0_Z:
-               return cpg_z_clk_register(core->name, __clk_get_name(parent),
-                                         base, core->div, core->offset);
-
-       case CLK_TYPE_R8A779A0_SD:
-               return cpg_sd_clk_register(core->name, base, core->offset,
-                                          __clk_get_name(parent), notifiers,
-                                          false);
-               break;
-
-       case CLK_TYPE_R8A779A0_MDSEL:
-               /*
-                * Clock selectable between two parents and two fixed dividers
-                * using a mode pin
-                */
-               if (cpg_mode & BIT(core->offset)) {
-                       div = core->div & 0xffff;
-               } else {
-                       parent = clks[core->parent >> 16];
-                       if (IS_ERR(parent))
-                               return ERR_CAST(parent);
-                       div = core->div >> 16;
-               }
-               mult = 1;
-               break;
-
-       case CLK_TYPE_R8A779A0_OSC:
-               /*
-                * Clock combining OSC EXTAL predivider and a fixed divider
-                */
-               div = cpg_pll_config->osc_prediv * core->div;
-               break;
-
-       case CLK_TYPE_R8A779A0_RPCSRC:
-               return clk_register_divider_table(NULL, core->name,
-                                                 __clk_get_name(parent), 0,
-                                                 base + CPG_RPCCKCR, 3, 2, 0,
-                                                 cpg_rpcsrc_div_table,
-                                                 &cpg_lock);
-
-       case CLK_TYPE_R8A779A0_RPC:
-               return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
-                                           __clk_get_name(parent), notifiers);
-
-       case CLK_TYPE_R8A779A0_RPCD2:
-               return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
-                                             __clk_get_name(parent));
-
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
-       return clk_register_fixed_factor(NULL, core->name,
-                                        __clk_get_name(parent), 0, mult, div);
-}
-
 static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
        MOD_CLK_ID(907),        /* RWDT */
 };
@@ -539,17 +248,19 @@ static const unsigned int r8a779a0_crit_mod_clks[] __initconst = {
  */
 #define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
                                         (((md) & BIT(13)) >> 13))
-
-static const struct rcar_r8a779a0_cpg_pll_config cpg_pll_configs[4] = {
-       /* EXTAL div    PLL1 mult/div   PLL5 mult/div   OSC prediv */
-       { 1,            128,    1,      192,    1,      16,     },
-       { 1,            106,    1,      160,    1,      19,     },
-       { 0,            0,      0,      0,      0,      0,      },
-       { 2,            128,    1,      192,    1,      32,     },
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+       /* EXTAL div    PLL1 mult/div   PLL2 mult/div   PLL3 mult/div   PLL5 mult/div   PLL6 mult/div   OSC prediv */
+       { 1,            128,    1,      0,      0,      0,      0,      192,    1,      0,      0,      16,     },
+       { 1,            106,    1,      0,      0,      0,      0,      160,    1,      0,      0,      19,     },
+       { 0,            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      },
+       { 2,            128,    1,      0,      0,      0,      0,      192,    1,      0,      0,      32,     },
 };
 
+
 static int __init r8a779a0_cpg_mssr_init(struct device *dev)
 {
+       const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
        int error;
 
        error = rcar_rst_read_mode_pins(&cpg_mode);
@@ -557,10 +268,8 @@ static int __init r8a779a0_cpg_mssr_init(struct device *dev)
                return error;
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
-       cpg_clk_extalr = CLK_EXTALR;
-       spin_lock_init(&cpg_lock);
 
-       return 0;
+       return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
 }
 
 const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
@@ -581,7 +290,7 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = {
 
        /* Callbacks */
        .init = r8a779a0_cpg_mssr_init,
-       .cpg_clk_register = rcar_r8a779a0_cpg_clk_register,
+       .cpg_clk_register = rcar_gen4_cpg_clk_register,
 
-       .reg_layout = CLK_REG_LAYOUT_RCAR_V3U,
+       .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
 };
diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
new file mode 100644 (file)
index 0000000..e6ec02c
--- /dev/null
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a779f0 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on r8a779a0-cpg-mssr.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A779F0_CLK_R,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_EXTALR,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL1,
+       CLK_PLL2,
+       CLK_PLL3,
+       CLK_PLL5,
+       CLK_PLL6,
+       CLK_PLL1_DIV2,
+       CLK_PLL2_DIV2,
+       CLK_PLL3_DIV2,
+       CLK_PLL5_DIV2,
+       CLK_PLL5_DIV4,
+       CLK_PLL6_DIV2,
+       CLK_S0,
+       CLK_SDSRC,
+       CLK_RPCSRC,
+       CLK_OCO,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("extalr",     CLK_EXTALR),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main", CLK_MAIN,     CLK_TYPE_GEN4_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll1", CLK_PLL1,     CLK_TYPE_GEN4_PLL1, CLK_MAIN),
+       DEF_BASE(".pll2", CLK_PLL2,     CLK_TYPE_GEN4_PLL2, CLK_MAIN),
+       DEF_BASE(".pll3", CLK_PLL3,     CLK_TYPE_GEN4_PLL3, CLK_MAIN),
+       DEF_BASE(".pll5", CLK_PLL5,     CLK_TYPE_GEN4_PLL5, CLK_MAIN),
+       DEF_BASE(".pll6", CLK_PLL6,     CLK_TYPE_GEN4_PLL6, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,  CLK_PLL1,       2, 1),
+       DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2,  CLK_PLL2,       2, 1),
+       DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2,  CLK_PLL3,       2, 1),
+       DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2,  CLK_PLL5,       2, 1),
+       DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4,  CLK_PLL5_DIV2,  2, 1),
+       DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2,  CLK_PLL6,       2, 1),
+       DEF_FIXED(".s0",        CLK_S0,         CLK_PLL1_DIV2,  2, 1),
+       DEF_BASE(".sdsrc",      CLK_SDSRC,      CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+       DEF_RATE(".oco",        CLK_OCO,        32768),
+
+       DEF_BASE(".rpcsrc",     CLK_RPCSRC,             CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+       DEF_BASE(".rpc",        R8A779F0_CLK_RPC,       CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A779F0_CLK_RPCD2,     CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC),
+
+       /* Core Clock Outputs */
+       DEF_FIXED("s0d2",       R8A779F0_CLK_S0D2,      CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A779F0_CLK_S0D3,      CLK_S0,         3, 1),
+       DEF_FIXED("s0d4",       R8A779F0_CLK_S0D4,      CLK_S0,         4, 1),
+       DEF_FIXED("cl16m",      R8A779F0_CLK_CL16M,     CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_mm",    R8A779F0_CLK_S0D2_MM,   CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_mm",    R8A779F0_CLK_S0D3_MM,   CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_mm",    R8A779F0_CLK_S0D4_MM,   CLK_S0,         4, 1),
+       DEF_FIXED("cl16m_mm",   R8A779F0_CLK_CL16M_MM,  CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_rt",    R8A779F0_CLK_S0D2_RT,   CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_rt",    R8A779F0_CLK_S0D3_RT,   CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_rt",    R8A779F0_CLK_S0D4_RT,   CLK_S0,         4, 1),
+       DEF_FIXED("s0d6_rt",    R8A779F0_CLK_S0D6_RT,   CLK_S0,         6, 1),
+       DEF_FIXED("cl16m_rt",   R8A779F0_CLK_CL16M_RT,  CLK_S0,         48, 1),
+       DEF_FIXED("s0d3_per",   R8A779F0_CLK_S0D3_PER,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d6_per",   R8A779F0_CLK_S0D6_PER,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d12_per",  R8A779F0_CLK_S0D12_PER, CLK_S0,         12, 1),
+       DEF_FIXED("s0d24_per",  R8A779F0_CLK_S0D24_PER, CLK_S0,         24, 1),
+       DEF_FIXED("cl16m_per",  R8A779F0_CLK_CL16M_PER, CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_hsc",   R8A779F0_CLK_S0D2_HSC,  CLK_S0,         2, 1),
+       DEF_FIXED("s0d3_hsc",   R8A779F0_CLK_S0D3_HSC,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d4_hsc",   R8A779F0_CLK_S0D4_HSC,  CLK_S0,         4, 1),
+       DEF_FIXED("s0d6_hsc",   R8A779F0_CLK_S0D6_HSC,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d12_hsc",  R8A779F0_CLK_S0D12_HSC, CLK_S0,         12, 1),
+       DEF_FIXED("cl16m_hsc",  R8A779F0_CLK_CL16M_HSC, CLK_S0,         48, 1),
+       DEF_FIXED("s0d2_cc",    R8A779F0_CLK_S0D2_CC,   CLK_S0,         2, 1),
+       DEF_FIXED("rsw2",       R8A779F0_CLK_RSW2,      CLK_PLL5,       2, 1),
+       DEF_FIXED("cbfusa",     R8A779F0_CLK_CBFUSA,    CLK_EXTAL,      2, 1),
+       DEF_FIXED("cpex",       R8A779F0_CLK_CPEX,      CLK_EXTAL,      2, 1),
+
+       DEF_GEN4_SD("sd0",      R8A779F0_CLK_SD0,       CLK_SDSRC,      0x870),
+       DEF_DIV6P1("mso",       R8A779F0_CLK_MSO,       CLK_PLL5_DIV4,  0x87c),
+
+       DEF_GEN4_OSC("osc",     R8A779F0_CLK_OSC,       CLK_EXTAL,      8),
+       DEF_GEN4_MDSEL("r",     R8A779F0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+};
+
+static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
+       DEF_MOD("scif0",        702,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif1",        703,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif3",        704,    R8A779F0_CLK_S0D12_PER),
+       DEF_MOD("scif4",        705,    R8A779F0_CLK_S0D12_PER),
+};
+
+/*
+ * CPG Clock Data
+ */
+/*
+ *   MD         EXTAL          PLL1    PLL2    PLL3    PLL5    PLL6    OSC
+ * 14 13 (MHz)
+ * ----------------------------------------------------------------
+ * 0  0         16    / 1      x200    x150    x200    x200    x134    /15
+ * 0  1         20    / 1      x160    x120    x160    x160    x106    /19
+ * 1  0         Prohibited setting
+ * 1  1         40    / 2      x160    x120    x160    x160    x106    /38
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
+                                        (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = {
+       /* EXTAL div    PLL1 mult/div   PLL2 mult/div   PLL3 mult/div   PLL5 mult/div   PLL6 mult/div   OSC prediv */
+       { 1,            200,    1,      150,    1,      200,    1,      200,    1,      134,    1,      15,     },
+       { 1,            160,    1,      120,    1,      160,    1,      160,    1,      106,    1,      19,     },
+       { 0,            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      },
+       { 2,            160,    1,      120,    1,      160,    1,      160,    1,      106,    1,      38,     },
+};
+
+static int __init r8a779f0_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen4_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+       if (!cpg_pll_config->extal_div) {
+               dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+               return -EINVAL;
+       }
+
+       return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a779f0_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a779f0_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a779f0_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a779f0_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a779f0_mod_clks),
+       .num_hw_mod_clks = 28 * 32,
+
+       /* Callbacks */
+       .init = r8a779f0_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen4_cpg_clk_register,
+
+       .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4,
+};
index 47c1626..79042bf 100644 (file)
@@ -26,15 +26,15 @@ enum clk_ids {
        CLK_PLL1,
        CLK_PLL2,
        CLK_PLL2_DIV2,
-       CLK_PLL2_DIV16,
-       CLK_PLL2_DIV20,
+       CLK_PLL2_DIV2_8,
+       CLK_PLL2_DIV2_10,
        CLK_PLL3,
        CLK_PLL3_400,
        CLK_PLL3_533,
        CLK_PLL3_DIV2,
+       CLK_PLL3_DIV2_2,
        CLK_PLL3_DIV2_4,
        CLK_PLL3_DIV2_4_2,
-       CLK_PLL3_DIV4,
        CLK_SEL_PLL3_3,
        CLK_DIV_PLL3_C,
        CLK_PLL4,
@@ -50,12 +50,21 @@ enum clk_ids {
        CLK_PLL2_SDHI_266,
        CLK_SD0_DIV4,
        CLK_SD1_DIV4,
+       CLK_SEL_GPU2,
 
        /* Module Clocks */
        MOD_CLK_BASE,
 };
 
 /* Divider tables */
+static const struct clk_div_table dtable_1_8[] = {
+       {0, 1},
+       {1, 2},
+       {2, 4},
+       {3, 8},
+       {0, 0},
+};
+
 static const struct clk_div_table dtable_1_32[] = {
        {0, 1},
        {1, 2},
@@ -69,6 +78,7 @@ static const struct clk_div_table dtable_1_32[] = {
 static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
 static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
 static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
 
 static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
        /* External Clock Inputs */
@@ -94,13 +104,13 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
        DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
        DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
 
-       DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16),
-       DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20),
+       DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8),
+       DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10),
 
        DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2),
+       DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2),
        DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
        DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
-       DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4),
        DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3,
                sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY),
        DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3,
@@ -108,13 +118,16 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
 
        DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
        DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
+       DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2,
+               sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY),
 
        /* Core output clk */
-       DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1),
-       DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A,
+       DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8,
+               CLK_DIVIDER_HIWORD_MASK),
+       DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A,
                dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
        DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2),
-       DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1),
+       DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1),
        DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4,
                DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
        DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
@@ -132,6 +145,8 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
                   sel_shdi, ARRAY_SIZE(sel_shdi)),
        DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
        DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+       DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8,
+               CLK_DIVIDER_HIWORD_MASK),
 };
 
 static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
@@ -145,6 +160,24 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x52c, 0),
        DEF_MOD("dmac_pclk",    R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
                                0x52c, 1),
+       DEF_MOD("ostm0_pclk",   R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0,
+                               0x534, 0),
+       DEF_MOD("ostm1_clk",    R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0,
+                               0x534, 1),
+       DEF_MOD("ostm2_pclk",   R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
+                               0x534, 2),
+       DEF_MOD("wdt0_pclk",    R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0,
+                               0x548, 0),
+       DEF_MOD("wdt0_clk",     R9A07G044_WDT0_CLK, R9A07G044_OSCCLK,
+                               0x548, 1),
+       DEF_MOD("wdt1_pclk",    R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0,
+                               0x548, 2),
+       DEF_MOD("wdt1_clk",     R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
+                               0x548, 3),
+       DEF_MOD("wdt2_pclk",    R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0,
+                               0x548, 4),
+       DEF_MOD("wdt2_clk",     R9A07G044_WDT2_CLK, R9A07G044_OSCCLK,
+                               0x548, 5),
        DEF_MOD("spi_clk2",     R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
                                0x550, 0),
        DEF_MOD("spi_clk",      R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
@@ -165,6 +198,12 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x554, 6),
        DEF_MOD("sdhi1_aclk",   R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
                                0x554, 7),
+       DEF_MOD("gpu_clk",      R9A07G044_GPU_CLK, R9A07G044_CLK_G,
+                               0x558, 0),
+       DEF_MOD("gpu_axi_clk",  R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1,
+                               0x558, 1),
+       DEF_MOD("gpu_ace_clk",  R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1,
+                               0x558, 2),
        DEF_MOD("ssi0_pclk",    R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
                                0x570, 0),
        DEF_MOD("ssi0_sfr",     R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
@@ -217,6 +256,14 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x584, 4),
        DEF_MOD("sci0",         R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0,
                                0x588, 0),
+       DEF_MOD("sci1",         R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0,
+                               0x588, 1),
+       DEF_MOD("rspi0",        R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0,
+                               0x590, 0),
+       DEF_MOD("rspi1",        R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0,
+                               0x590, 1),
+       DEF_MOD("rspi2",        R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0,
+                               0x590, 2),
        DEF_MOD("canfd",        R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0,
                                0x594, 0),
        DEF_MOD("gpio",         R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK,
@@ -225,6 +272,8 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
                                0x5a8, 0),
        DEF_MOD("adc_pclk",     R9A07G044_ADC_PCLK, R9A07G044_CLK_P0,
                                0x5a8, 1),
+       DEF_MOD("tsu_pclk",     R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU,
+                               0x5ac, 0),
 };
 
 static struct rzg2l_reset r9a07g044_resets[] = {
@@ -233,9 +282,18 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
        DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
        DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
+       DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0),
+       DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1),
+       DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2),
+       DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0),
+       DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
+       DEF_RST(R9A07G044_WDT2_PRESETN, 0x848, 2),
        DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
        DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
        DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
+       DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0),
+       DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1),
+       DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2),
        DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
        DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
        DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
@@ -256,6 +314,10 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_SCIF3_RST_SYSTEM_N, 0x884, 3),
        DEF_RST(R9A07G044_SCIF4_RST_SYSTEM_N, 0x884, 4),
        DEF_RST(R9A07G044_SCI0_RST, 0x888, 0),
+       DEF_RST(R9A07G044_SCI1_RST, 0x888, 1),
+       DEF_RST(R9A07G044_RSPI0_RST, 0x890, 0),
+       DEF_RST(R9A07G044_RSPI1_RST, 0x890, 1),
+       DEF_RST(R9A07G044_RSPI2_RST, 0x890, 2),
        DEF_RST(R9A07G044_CANFD_RSTP_N, 0x894, 0),
        DEF_RST(R9A07G044_CANFD_RSTC_N, 0x894, 1),
        DEF_RST(R9A07G044_GPIO_RSTN, 0x898, 0),
@@ -263,6 +325,7 @@ static struct rzg2l_reset r9a07g044_resets[] = {
        DEF_RST(R9A07G044_GPIO_SPARE_RESETN, 0x898, 2),
        DEF_RST(R9A07G044_ADC_PRESETN, 0x8a8, 0),
        DEF_RST(R9A07G044_ADC_ADRST_N, 0x8a8, 1),
+       DEF_RST(R9A07G044_TSU_PRESETN, 0x8ac, 0),
 };
 
 static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
index e93f001..e2e0447 100644 (file)
@@ -65,206 +65,49 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
 /*
  * SDn Clock
  */
-#define CPG_SD_STP_HCK         BIT(9)
-#define CPG_SD_STP_CK          BIT(8)
-
-#define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
-#define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
-
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
-{ \
-       .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
-              ((sd_srcfc) << 2) | \
-              ((sd_fc) << 0), \
-       .div = (sd_div), \
-}
 
-struct sd_div_table {
-       u32 val;
-       unsigned int div;
-};
+#define SDnSRCFC_SHIFT 2
+#define STPnHCK        BIT(9 - SDnSRCFC_SHIFT)
 
-struct sd_clock {
-       struct clk_hw hw;
-       const struct sd_div_table *div_table;
-       struct cpg_simple_notifier csn;
-       unsigned int div_num;
-       unsigned int cur_div_idx;
-};
-
-/* SDn divider
- *           sd_srcfc   sd_fc   div
- * stp_hck   (div)      (div)     = sd_srcfc x sd_fc
- *---------------------------------------------------------
- *  0         0 (1)      1 (4)      4 : SDR104 / HS200 / HS400 (8 TAP)
- *  0         1 (2)      1 (4)      8 : SDR50
- *  1         2 (4)      1 (4)     16 : HS / SDR25
- *  1         3 (8)      1 (4)     32 : NS / SDR12
- *  1         4 (16)     1 (4)     64
- *  0         0 (1)      0 (2)      2
- *  0         1 (2)      0 (2)      4 : SDR104 / HS200 / HS400 (4 TAP)
- *  1         2 (4)      0 (2)      8
- *  1         3 (8)      0 (2)     16
- *  1         4 (16)     0 (2)     32
- *
- *  NOTE: There is a quirk option to ignore the first row of the dividers
- *  table when searching for suitable settings. This is because HS400 on
- *  early ES versions of H3 and M3-W requires a specific setting to work.
- */
-static const struct sd_div_table cpg_sd_div_table[] = {
-/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  sd_srcfc,   sd_fc,  sd_div) */
-       CPG_SD_DIV_TABLE_DATA(0,        0,          1,        4),
-       CPG_SD_DIV_TABLE_DATA(0,        1,          1,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        2,          1,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        3,          1,       32),
-       CPG_SD_DIV_TABLE_DATA(1,        4,          1,       64),
-       CPG_SD_DIV_TABLE_DATA(0,        0,          0,        2),
-       CPG_SD_DIV_TABLE_DATA(0,        1,          0,        4),
-       CPG_SD_DIV_TABLE_DATA(1,        2,          0,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        3,          0,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        4,          0,       32),
+static const struct clk_div_table cpg_sdh_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
+       { STPnHCK | 4, 16 }, { 0, 0 },
 };
 
-#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
-
-static int cpg_sd_clock_enable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
-                      clock->div_table[clock->cur_div_idx].val &
-                      CPG_SD_STP_MASK);
-
-       return 0;
-}
-
-static void cpg_sd_clock_disable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
-}
-
-static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
+struct clk * __init cpg_sdh_clk_register(const char *name,
+       void __iomem *sdnckcr, const char *parent_name,
+       struct raw_notifier_head *notifiers)
 {
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
-}
+       struct cpg_simple_notifier *csn;
+       struct clk *clk;
 
-static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
+       csn = kzalloc(sizeof(*csn), GFP_KERNEL);
+       if (!csn)
+               return ERR_PTR(-ENOMEM);
 
-       return DIV_ROUND_CLOSEST(parent_rate,
-                                clock->div_table[clock->cur_div_idx].div);
-}
+       csn->reg = sdnckcr;
 
-static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
-                                      struct clk_rate_request *req)
-{
-       unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned long calc_rate, diff;
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++) {
-               calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
-                                             clock->div_table[i].div);
-               if (calc_rate < req->min_rate || calc_rate > req->max_rate)
-                       continue;
-
-               diff = calc_rate > req->rate ? calc_rate - req->rate
-                                            : req->rate - calc_rate;
-               if (diff < diff_min) {
-                       best_rate = calc_rate;
-                       diff_min = diff;
-               }
+       clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+                                        SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
+                                        &cpg_lock);
+       if (IS_ERR(clk)) {
+               kfree(csn);
+               return clk;
        }
 
-       if (best_rate == ULONG_MAX)
-               return -EINVAL;
-
-       req->rate = best_rate;
-       return 0;
-}
-
-static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++)
-               if (rate == DIV_ROUND_CLOSEST(parent_rate,
-                                             clock->div_table[i].div))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       clock->cur_div_idx = i;
-
-       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
-                      clock->div_table[i].val &
-                      (CPG_SD_STP_MASK | CPG_SD_FC_MASK));
-
-       return 0;
+       cpg_simple_notifier_register(notifiers, csn);
+       return clk;
 }
 
-static const struct clk_ops cpg_sd_clock_ops = {
-       .enable = cpg_sd_clock_enable,
-       .disable = cpg_sd_clock_disable,
-       .is_enabled = cpg_sd_clock_is_enabled,
-       .recalc_rate = cpg_sd_clock_recalc_rate,
-       .determine_rate = cpg_sd_clock_determine_rate,
-       .set_rate = cpg_sd_clock_set_rate,
+static const struct clk_div_table cpg_sd_div_table[] = {
+       { 0, 2 }, { 1, 4 }, { 0, 0 },
 };
 
 struct clk * __init cpg_sd_clk_register(const char *name,
-       void __iomem *base, unsigned int offset, const char *parent_name,
-       struct raw_notifier_head *notifiers, bool skip_first)
+       void __iomem *sdnckcr, const char *parent_name)
 {
-       struct clk_init_data init = {};
-       struct sd_clock *clock;
-       struct clk *clk;
-       u32 val;
-
-       clock = kzalloc(sizeof(*clock), GFP_KERNEL);
-       if (!clock)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = name;
-       init.ops = &cpg_sd_clock_ops;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       clock->csn.reg = base + offset;
-       clock->hw.init = &init;
-       clock->div_table = cpg_sd_div_table;
-       clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
-
-       if (skip_first) {
-               clock->div_table++;
-               clock->div_num--;
-       }
-
-       val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
-       val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
-       writel(val, clock->csn.reg);
-
-       clk = clk_register(NULL, &clock->hw);
-       if (IS_ERR(clk))
-               goto free_clock;
-
-       cpg_simple_notifier_register(notifiers, &clock->csn);
-       return clk;
-
-free_clock:
-       kfree(clock);
-       return clk;
+       return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
+                                         0, 2, 0, cpg_sd_div_table, &cpg_lock);
 }
 
 struct rpc_clock {
index 35c0217..94627df 100644 (file)
@@ -26,9 +26,12 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
 
 void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set);
 
+struct clk * __init cpg_sdh_clk_register(const char *name,
+       void __iomem *sdnckcr, const char *parent_name,
+       struct raw_notifier_head *notifiers);
+
 struct clk * __init cpg_sd_clk_register(const char *name,
-       void __iomem *base, unsigned int offset, const char *parent_name,
-       struct raw_notifier_head *notifiers, bool skip_first);
+       void __iomem *sdnckcr, const char *parent_name);
 
 struct clk * __init cpg_rpc_clk_register(const char *name,
        void __iomem *rpcckcr, const char *parent_name,
index 741f6e7..e668f23 100644 (file)
@@ -312,29 +312,20 @@ static u32 cpg_quirks __initdata;
 
 #define PLL_ERRATA     BIT(0)          /* Missing PLL0/2/4 post-divider */
 #define RCKCR_CKSEL    BIT(1)          /* Manual RCLK parent selection */
-#define SD_SKIP_FIRST  BIT(2)          /* Skip first clock in SD table */
 
 
 static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
        {
                .soc_id = "r8a7795", .revision = "ES1.0",
-               .data = (void *)(PLL_ERRATA | RCKCR_CKSEL | SD_SKIP_FIRST),
+               .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
        },
        {
                .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
-       },
-       {
-               .soc_id = "r8a7795", .revision = "ES2.0",
-               .data = (void *)SD_SKIP_FIRST,
+               .data = (void *)(RCKCR_CKSEL),
        },
        {
                .soc_id = "r8a7796", .revision = "ES1.0",
-               .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
-       },
-       {
-               .soc_id = "r8a7796", .revision = "ES1.1",
-               .data = (void *)SD_SKIP_FIRST,
+               .data = (void *)(RCKCR_CKSEL),
        },
        { /* sentinel */ }
 };
@@ -401,10 +392,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                        mult *= 2;
                break;
 
+       case CLK_TYPE_GEN3_SDH:
+               return cpg_sdh_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent), notifiers);
+
        case CLK_TYPE_GEN3_SD:
-               return cpg_sd_clk_register(core->name, base, core->offset,
-                                          __clk_get_name(parent), notifiers,
-                                          cpg_quirks & SD_SKIP_FIRST);
+               return cpg_sd_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent));
 
        case CLK_TYPE_GEN3_R:
                if (cpg_quirks & RCKCR_CKSEL) {
index 3d949c4..2bc0afa 100644 (file)
@@ -17,6 +17,7 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_PLL2,
        CLK_TYPE_GEN3_PLL3,
        CLK_TYPE_GEN3_PLL4,
+       CLK_TYPE_GEN3_SDH,
        CLK_TYPE_GEN3_SD,
        CLK_TYPE_GEN3_R,
        CLK_TYPE_GEN3_MDSEL,    /* Select parent/divider using mode pin */
@@ -32,6 +33,9 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_SOC_BASE,
 };
 
+#define DEF_GEN3_SDH(_name, _id, _parent, _offset)     \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN3_SDH, _parent, .offset = _offset)
+
 #define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
        DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
 
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c
new file mode 100644 (file)
index 0000000..54ebf4b
--- /dev/null
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ * Based on rcar-gen3-cpg.c
+ *
+ * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen4-cpg.h"
+#include "rcar-cpg-lib.h"
+
+static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initconst;
+static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+
+/*
+ * Z0 Clock & Z1 Clock
+ */
+#define CPG_FRQCRB                     0x00000804
+#define CPG_FRQCRB_KICK                        BIT(31)
+#define CPG_FRQCRC                     0x00000808
+
+struct cpg_z_clk {
+       struct clk_hw hw;
+       void __iomem *reg;
+       void __iomem *kick_reg;
+       unsigned long max_rate;         /* Maximum rate for normal mode */
+       unsigned int fixed_div;
+       u32 mask;
+};
+
+#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       u32 val;
+
+       val = readl(zclk->reg) & zclk->mask;
+       mult = 32 - (val >> __ffs(zclk->mask));
+
+       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
+                                    32 * zclk->fixed_div);
+}
+
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
+                                   struct clk_rate_request *req)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int min_mult, max_mult, mult;
+       unsigned long rate, prate;
+
+       rate = min(req->rate, req->max_rate);
+       if (rate <= zclk->max_rate) {
+               /* Set parent rate to initial value for normal modes */
+               prate = zclk->max_rate;
+       } else {
+               /* Set increased parent rate for boost modes */
+               prate = rate;
+       }
+       req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+                                                 prate * zclk->fixed_div);
+
+       prate = req->best_parent_rate / zclk->fixed_div;
+       min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
+       max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
+       if (max_mult < min_mult)
+               return -EINVAL;
+
+       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
+       mult = clamp(mult, min_mult, max_mult);
+
+       req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
+       return 0;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       unsigned int i;
+
+       mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
+                                      parent_rate);
+       mult = clamp(mult, 1U, 32U);
+
+       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+               return -EBUSY;
+
+       cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
+
+       /*
+        * Set KICK bit in FRQCRB to update hardware setting and wait for
+        * clock change completion.
+        */
+       cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
+
+       /*
+        * Note: There is no HW information about the worst case latency.
+        *
+        * Using experimental measurements, it seems that no more than
+        * ~10 iterations are needed, independently of the CPU rate.
+        * Since this value might be dependent on external xtal rate, pll1
+        * rate or even the other emulation clocks rate, use 1000 as a
+        * "super" safe value.
+        */
+       for (i = 1000; i; i--) {
+               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+       .recalc_rate = cpg_z_clk_recalc_rate,
+       .determine_rate = cpg_z_clk_determine_rate,
+       .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+                                             const char *parent_name,
+                                             void __iomem *reg,
+                                             unsigned int div,
+                                             unsigned int offset)
+{
+       struct clk_init_data init = {};
+       struct cpg_z_clk *zclk;
+       struct clk *clk;
+
+       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+       if (!zclk)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &cpg_z_clk_ops;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       zclk->reg = reg + CPG_FRQCRC;
+       zclk->kick_reg = reg + CPG_FRQCRB;
+       zclk->hw.init = &init;
+       zclk->mask = GENMASK(offset + 4, offset);
+       zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
+
+       clk = clk_register(NULL, &zclk->hw);
+       if (IS_ERR(clk)) {
+               kfree(zclk);
+               return clk;
+       }
+
+       zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
+                        zclk->fixed_div;
+       return clk;
+}
+
+/*
+ * RPC Clocks
+ */
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+       { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
+struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev,
+       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+       struct clk **clks, void __iomem *base,
+       struct raw_notifier_head *notifiers)
+{
+       const struct clk *parent;
+       unsigned int mult = 1;
+       unsigned int div = 1;
+       u32 value;
+
+       parent = clks[core->parent & 0xffff];   /* some types use high bits */
+       if (IS_ERR(parent))
+               return ERR_CAST(parent);
+
+       switch (core->type) {
+       case CLK_TYPE_GEN4_MAIN:
+               div = cpg_pll_config->extal_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL1:
+               mult = cpg_pll_config->pll1_mult;
+               div = cpg_pll_config->pll1_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL2:
+               mult = cpg_pll_config->pll2_mult;
+               div = cpg_pll_config->pll2_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL3:
+               mult = cpg_pll_config->pll3_mult;
+               div = cpg_pll_config->pll3_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL5:
+               mult = cpg_pll_config->pll5_mult;
+               div = cpg_pll_config->pll5_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL6:
+               mult = cpg_pll_config->pll6_mult;
+               div = cpg_pll_config->pll6_div;
+               break;
+
+       case CLK_TYPE_GEN4_PLL2X_3X:
+               value = readl(base + core->offset);
+               mult = (((value >> 24) & 0x7f) + 1) * 2;
+               break;
+
+       case CLK_TYPE_GEN4_Z:
+               return cpg_z_clk_register(core->name, __clk_get_name(parent),
+                                         base, core->div, core->offset);
+
+       case CLK_TYPE_GEN4_SDSRC:
+               div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 4;
+               break;
+
+       case CLK_TYPE_GEN4_SDH:
+               return cpg_sdh_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent), notifiers);
+
+       case CLK_TYPE_GEN4_SD:
+               return cpg_sd_clk_register(core->name, base + core->offset,
+                                          __clk_get_name(parent));
+
+       case CLK_TYPE_GEN4_MDSEL:
+               /*
+                * Clock selectable between two parents and two fixed dividers
+                * using a mode pin
+                */
+               if (cpg_mode & BIT(core->offset)) {
+                       div = core->div & 0xffff;
+               } else {
+                       parent = clks[core->parent >> 16];
+                       if (IS_ERR(parent))
+                               return ERR_CAST(parent);
+                       div = core->div >> 16;
+               }
+               mult = 1;
+               break;
+
+       case CLK_TYPE_GEN4_OSC:
+               /*
+                * Clock combining OSC EXTAL predivider and a fixed divider
+                */
+               div = cpg_pll_config->osc_prediv * core->div;
+               break;
+
+       case CLK_TYPE_GEN4_RPCSRC:
+               return clk_register_divider_table(NULL, core->name,
+                                                 __clk_get_name(parent), 0,
+                                                 base + CPG_RPCCKCR, 3, 2, 0,
+                                                 cpg_rpcsrc_div_table,
+                                                 &cpg_lock);
+
+       case CLK_TYPE_GEN4_RPC:
+               return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
+                                           __clk_get_name(parent), notifiers);
+
+       case CLK_TYPE_GEN4_RPCD2:
+               return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
+                                             __clk_get_name(parent));
+
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       return clk_register_fixed_factor(NULL, core->name,
+                                        __clk_get_name(parent), 0, mult, div);
+}
+
+int __init rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+                             unsigned int clk_extalr, u32 mode)
+{
+       cpg_pll_config = config;
+       cpg_clk_extalr = clk_extalr;
+       cpg_mode = mode;
+
+       spin_lock_init(&cpg_lock);
+
+       return 0;
+}
diff --git a/drivers/clk/renesas/rcar-gen4-cpg.h b/drivers/clk/renesas/rcar-gen4-cpg.h
new file mode 100644 (file)
index 0000000..afc8c02
--- /dev/null
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * R-Car Gen4 Clock Pulse Generator
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ *
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN4_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN4_CPG_H__
+
+enum rcar_gen4_clk_types {
+       CLK_TYPE_GEN4_MAIN = CLK_TYPE_CUSTOM,
+       CLK_TYPE_GEN4_PLL1,
+       CLK_TYPE_GEN4_PLL2,
+       CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */
+       CLK_TYPE_GEN4_PLL3,
+       CLK_TYPE_GEN4_PLL5,
+       CLK_TYPE_GEN4_PLL6,
+       CLK_TYPE_GEN4_SDSRC,
+       CLK_TYPE_GEN4_SDH,
+       CLK_TYPE_GEN4_SD,
+       CLK_TYPE_GEN4_MDSEL,    /* Select parent/divider using mode pin */
+       CLK_TYPE_GEN4_Z,
+       CLK_TYPE_GEN4_OSC,      /* OSC EXTAL predivider and fixed divider */
+       CLK_TYPE_GEN4_RPCSRC,
+       CLK_TYPE_GEN4_RPC,
+       CLK_TYPE_GEN4_RPCD2,
+
+       /* SoC specific definitions start here */
+       CLK_TYPE_GEN4_SOC_BASE,
+};
+
+#define DEF_GEN4_SDH(_name, _id, _parent, _offset)     \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_SDH, _parent, .offset = _offset)
+
+#define DEF_GEN4_SD(_name, _id, _parent, _offset)      \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_SD, _parent, .offset = _offset)
+
+#define DEF_GEN4_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_MDSEL,       \
+                (_parent0) << 16 | (_parent1),         \
+                .div = (_div0) << 16 | (_div1), .offset = _md)
+
+#define DEF_GEN4_OSC(_name, _id, _parent, _div)                \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN4_OSC, _parent, .div = _div)
+
+#define DEF_GEN4_Z(_name, _id, _type, _parent, _div, _offset)  \
+       DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
+
+struct rcar_gen4_cpg_pll_config {
+       u8 extal_div;
+       u8 pll1_mult;
+       u8 pll1_div;
+       u8 pll2_mult;
+       u8 pll2_div;
+       u8 pll3_mult;
+       u8 pll3_div;
+       u8 pll5_mult;
+       u8 pll5_div;
+       u8 pll6_mult;
+       u8 pll6_div;
+       u8 osc_prediv;
+};
+
+#define CPG_RPCCKCR    0x874
+#define SD0CKCR1       0x8a4
+
+struct clk *rcar_gen4_cpg_clk_register(struct device *dev,
+       const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
+       struct clk **clks, void __iomem *base,
+       struct raw_notifier_head *notifiers);
+int rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config,
+                      unsigned int clk_extalr, u32 mode);
+
+#endif
index 21f762a..5d2c3ed 100644 (file)
@@ -57,9 +57,11 @@ static const u16 mstpsr[] = {
        0x9A0, 0x9A4, 0x9A8, 0x9AC,
 };
 
-static const u16 mstpsr_for_v3u[] = {
+static const u16 mstpsr_for_gen4[] = {
        0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
-       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
+       0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, 0x2E3C,
+       0x2E40, 0x2E44, 0x2E48, 0x2E4C, 0x2E50, 0x2E54, 0x2E58, 0x2E5C,
+       0x2E60, 0x2E64, 0x2E68, 0x2E6C,
 };
 
 /*
@@ -71,9 +73,11 @@ static const u16 smstpcr[] = {
        0x990, 0x994, 0x998, 0x99C,
 };
 
-static const u16 mstpcr_for_v3u[] = {
+static const u16 mstpcr_for_gen4[] = {
        0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
-       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
+       0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, 0x2D3C,
+       0x2D40, 0x2D44, 0x2D48, 0x2D4C, 0x2D50, 0x2D54, 0x2D58, 0x2D5C,
+       0x2D60, 0x2D64, 0x2D68, 0x2D6C,
 };
 
 /*
@@ -95,9 +99,11 @@ static const u16 srcr[] = {
        0x920, 0x924, 0x928, 0x92C,
 };
 
-static const u16 srcr_for_v3u[] = {
+static const u16 srcr_for_gen4[] = {
        0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
-       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
+       0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, 0x2C3C,
+       0x2C40, 0x2C44, 0x2C48, 0x2C4C, 0x2C50, 0x2C54, 0x2C58, 0x2C5C,
+       0x2C60, 0x2C64, 0x2C68, 0x2C6C,
 };
 
 /*
@@ -109,9 +115,11 @@ static const u16 srstclr[] = {
        0x960, 0x964, 0x968, 0x96C,
 };
 
-static const u16 srstclr_for_v3u[] = {
+static const u16 srstclr_for_gen4[] = {
        0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
-       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
+       0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, 0x2CBC,
+       0x2CC0, 0x2CC4, 0x2CC8, 0x2CCC, 0x2CD0, 0x2CD4, 0x2CD8, 0x2CDC,
+       0x2CE0, 0x2CE4, 0x2CE8, 0x2CEC,
 };
 
 /**
@@ -158,7 +166,7 @@ struct cpg_mssr_priv {
        struct {
                u32 mask;
                u32 val;
-       } smstpcr_saved[ARRAY_SIZE(mstpsr_for_v3u)];
+       } smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
 
        struct clk *clks[];
 };
@@ -552,6 +560,11 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
                pm_clk_destroy(dev);
 }
 
+static void cpg_mssr_genpd_remove(void *data)
+{
+       pm_genpd_remove(data);
+}
+
 static int __init cpg_mssr_add_clk_domain(struct device *dev,
                                          const unsigned int *core_pm_clks,
                                          unsigned int num_core_pm_clks)
@@ -560,6 +573,7 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
        struct generic_pm_domain *genpd;
        struct cpg_mssr_clk_domain *pd;
        size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
+       int ret;
 
        pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
        if (!pd)
@@ -574,11 +588,17 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
                       GENPD_FLAG_ACTIVE_WAKEUP;
        genpd->attach_dev = cpg_mssr_attach_dev;
        genpd->detach_dev = cpg_mssr_detach_dev;
-       pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(dev, cpg_mssr_genpd_remove, genpd);
+       if (ret)
+               return ret;
+
        cpg_mssr_clk_domain = pd;
 
-       of_genpd_add_provider_simple(np, genpd);
-       return 0;
+       return of_genpd_add_provider_simple(np, genpd);
 }
 
 #ifdef CONFIG_RESET_CONTROLLER
@@ -827,6 +847,12 @@ static const struct of_device_id cpg_mssr_match[] = {
                .compatible = "renesas,r8a779a0-cpg-mssr",
                .data = &r8a779a0_cpg_mssr_info,
        },
+#endif
+#ifdef CONFIG_CLK_R8A779F0
+       {
+               .compatible = "renesas,r8a779f0-cpg-mssr",
+               .data = &r8a779f0_cpg_mssr_info,
+       },
 #endif
        { /* sentinel */ }
 };
@@ -970,11 +996,11 @@ static int __init cpg_mssr_common_init(struct device *dev,
                priv->reset_clear_regs = srstclr;
        } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
                priv->control_regs = stbcr;
-       } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
-               priv->status_regs = mstpsr_for_v3u;
-               priv->control_regs = mstpcr_for_v3u;
-               priv->reset_regs = srcr_for_v3u;
-               priv->reset_clear_regs = srstclr_for_v3u;
+       } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN4) {
+               priv->status_regs = mstpsr_for_gen4;
+               priv->control_regs = mstpcr_for_gen4;
+               priv->reset_regs = srcr_for_gen4;
+               priv->reset_clear_regs = srstclr_for_gen4;
        } else {
                error = -EINVAL;
                goto out_err;
index 6b2a0ad..16810dd 100644 (file)
@@ -88,7 +88,7 @@ struct device_node;
 enum clk_reg_layout {
        CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
        CLK_REG_LAYOUT_RZ_A,
-       CLK_REG_LAYOUT_RCAR_V3U,
+       CLK_REG_LAYOUT_RCAR_GEN4,
 };
 
     /**
@@ -178,6 +178,7 @@ extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77990_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a779f0_cpg_mssr_info;
 
 void __init cpg_mssr_early_init(struct device_node *np,
                                const struct cpg_mssr_info *info);
index 4021f6c..edd0abe 100644 (file)
@@ -74,6 +74,7 @@ struct sd_hw_data {
  * @clks: Array containing all Core and Module Clocks
  * @num_core_clks: Number of Core Clocks in clks[]
  * @num_mod_clks: Number of Module Clocks in clks[]
+ * @num_resets: Number of Module Resets in info->resets[]
  * @last_dt_core_clk: ID of the last Core Clock exported to DT
  * @notifiers: Notifier chain to save/restore clock state for system resume
  * @info: Pointer to platform data
@@ -850,10 +851,16 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device
                pm_clk_destroy(dev);
 }
 
+static void rzg2l_cpg_genpd_remove(void *data)
+{
+       pm_genpd_remove(data);
+}
+
 static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
 {
        struct device_node *np = dev->of_node;
        struct generic_pm_domain *genpd;
+       int ret;
 
        genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL);
        if (!genpd)
@@ -864,10 +871,15 @@ static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
                       GENPD_FLAG_ACTIVE_WAKEUP;
        genpd->attach_dev = rzg2l_cpg_attach_dev;
        genpd->detach_dev = rzg2l_cpg_detach_dev;
-       pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+       if (ret)
+               return ret;
 
-       of_genpd_add_provider_simple(np, genpd);
-       return 0;
+       ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd);
+       if (ret)
+               return ret;
+
+       return of_genpd_add_provider_simple(np, genpd);
 }
 
 static int __init rzg2l_cpg_probe(struct platform_device *pdev)
index 7fb6b40..5729d10 100644 (file)
@@ -9,11 +9,14 @@
 #ifndef __RENESAS_RZG2L_CPG_H__
 #define __RENESAS_RZG2L_CPG_H__
 
+#define CPG_PL1_DDIV           (0x200)
 #define CPG_PL2_DDIV           (0x204)
 #define CPG_PL3A_DDIV          (0x208)
+#define CPG_PL6_DDIV           (0x210)
 #define CPG_PL2SDHI_DSEL       (0x218)
 #define CPG_CLKSTATUS          (0x280)
 #define CPG_PL3_SSEL           (0x408)
+#define CPG_PL6_SSEL           (0x414)
 #define CPG_PL6_ETH_SSEL       (0x418)
 
 #define CPG_CLKSTATUS_SELSDHI0_STS     BIT(28)
 
 #define DDIV_PACK(offset, bitpos, size) \
                (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
+#define DIVPL1A                DDIV_PACK(CPG_PL1_DDIV, 0, 2)
 #define DIVPL2A                DDIV_PACK(CPG_PL2_DDIV, 0, 3)
 #define DIVPL3A                DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
 #define DIVPL3B                DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
 #define DIVPL3C                DDIV_PACK(CPG_PL3A_DDIV, 8, 3)
+#define DIVGPU         DDIV_PACK(CPG_PL6_DDIV, 0, 2)
 
 #define SEL_PLL_PACK(offset, bitpos, size) \
                (((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
 
 #define SEL_PLL3_3     SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
 #define SEL_PLL6_2     SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
+#define SEL_GPU2       SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
 
 #define SEL_SDHI0      DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
 #define SEL_SDHI1      DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
@@ -168,6 +174,9 @@ struct rzg2l_reset {
  * @num_mod_clks: Number of entries in mod_clks[]
  * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
  *
+ * @resets: Array of Module Reset definitions
+ * @num_resets: Number of entries in resets[]
+ *
  * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
  *                 should not be disabled without a knowledgeable driver
  * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
index b341cd9..962502c 100644 (file)
@@ -807,7 +807,7 @@ static int ti_adpll_init_registers(struct ti_adpll_data *d)
 
 static int ti_adpll_init_inputs(struct ti_adpll_data *d)
 {
-       const char *error = "need at least %i inputs";
+       static const char error[] = "need at least %i inputs";
        struct clk *clock;
        int nr_inputs;
 
index 8f7c514..fdc060e 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
 /*
- * clock framework for AMD Stoney based clocks
+ * clock framework for AMD FCH controller block
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/pci.h>
 #include <linux/platform_data/clk-fch.h>
 #include <linux/platform_device.h>
 
 #define ST_CLK_GATE    3
 #define ST_MAX_CLKS    4
 
-#define RV_CLK_48M     0
-#define RV_CLK_GATE    1
-#define RV_MAX_CLKS    2
+#define CLK_48M_FIXED  0
+#define CLK_GATE_FIXED 1
+#define CLK_MAX_FIXED  2
+
+/* List of supported CPU ids for clk mux with 25Mhz clk support */
+#define AMD_CPU_ID_ST                  0x1576
 
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
+static const struct pci_device_id fch_pci_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_ST) },
+       { }
+};
+
 static int fch_clk_probe(struct platform_device *pdev)
 {
        struct fch_clk_data *fch_data;
+       struct pci_dev *rdev;
 
        fch_data = dev_get_platdata(&pdev->dev);
        if (!fch_data || !fch_data->base)
                return -EINVAL;
 
-       if (!fch_data->is_rv) {
+       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+       if (!rdev) {
+               dev_err(&pdev->dev, "FCH device not found\n");
+               return -ENODEV;
+       }
+
+       if (pci_match_id(fch_pci_ids, rdev)) {
                hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
                        NULL, 0, 48000000);
                hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
@@ -59,34 +75,38 @@ static int fch_clk_probe(struct platform_device *pdev)
                        OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
                devm_clk_hw_register_clkdev(&pdev->dev, hws[ST_CLK_GATE],
-                       "oscout1", NULL);
+                                           fch_data->name, NULL);
        } else {
-               hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+               hws[CLK_48M_FIXED] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
                        NULL, 0, 48000000);
 
-               hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+               hws[CLK_GATE_FIXED] = clk_hw_register_gate(NULL, "oscout1",
                        "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
-                       OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
+                       OSCCLKENB, 0, NULL);
 
-               devm_clk_hw_register_clkdev(&pdev->dev, hws[RV_CLK_GATE],
-                       "oscout1", NULL);
+               devm_clk_hw_register_clkdev(&pdev->dev, hws[CLK_GATE_FIXED],
+                                           fch_data->name, NULL);
        }
 
+       pci_dev_put(rdev);
        return 0;
 }
 
 static int fch_clk_remove(struct platform_device *pdev)
 {
        int i, clks;
-       struct fch_clk_data *fch_data;
+       struct pci_dev *rdev;
 
-       fch_data = dev_get_platdata(&pdev->dev);
+       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+       if (!rdev)
+               return -ENODEV;
 
-       clks = fch_data->is_rv ? RV_MAX_CLKS : ST_MAX_CLKS;
+       clks = pci_match_id(fch_pci_ids, rdev) ? CLK_MAX_FIXED : ST_MAX_CLKS;
 
        for (i = 0; i < clks; i++)
                clk_hw_unregister(hws[i]);
 
+       pci_dev_put(rdev);
        return 0;
 }
 
index 54f4184..e5f8fb7 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/io.h>
 
 /**
- * struct zynq_pll
+ * struct zynq_pll - pll clock
  * @hw:                Handle between common and hardware-specific interfaces
  * @pll_ctrl:  PLL control register
  * @pll_status:        PLL status register
@@ -46,7 +46,7 @@ struct zynq_pll {
  * @hw:                Handle between common and hardware-specific interfaces
  * @rate:      Desired clock frequency
  * @prate:     Clock frequency of parent clock
- * Returns frequency closest to @rate the hardware can generate.
+ * Return:     frequency closest to @rate the hardware can generate.
  */
 static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                unsigned long *prate)
@@ -66,7 +66,7 @@ static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
  * zynq_pll_recalc_rate() - Recalculate clock frequency
  * @hw:                        Handle between common and hardware-specific interfaces
  * @parent_rate:       Clock frequency of parent clock
- * Returns current clock frequency.
+ * Return:             current clock frequency.
  */
 static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
@@ -87,7 +87,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
 /**
  * zynq_pll_is_enabled - Check if a clock is enabled
  * @hw:                Handle between common and hardware-specific interfaces
- * Returns 1 if the clock is enabled, 0 otherwise.
+ * Return:     1 if the clock is enabled, 0 otherwise.
  *
  * Not sure this is a good idea, but since disabled means bypassed for
  * this clock implementation we say we are always enabled.
@@ -110,7 +110,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw)
 /**
  * zynq_pll_enable - Enable clock
  * @hw:                Handle between common and hardware-specific interfaces
- * Returns 0 on success
+ * Return: 0 on success
  */
 static int zynq_pll_enable(struct clk_hw *hw)
 {
@@ -179,7 +179,7 @@ static const struct clk_ops zynq_pll_ops = {
  * @pll_status:        Pointer to PLL status register
  * @lock_index:        Bit index to this PLL's lock status bit in @pll_status
  * @lock:      Register lock
- * Returns handle to the registered clock.
+ * Return:     handle to the registered clock.
  */
 struct clk *clk_register_zynq_pll(const char *name, const char *parent,
                void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
index 92c1cc0..c87ce22 100644 (file)
@@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
        struct list_head resource_list;
        int ret;
 
-       if (acpi_bus_get_status(adev) || !adev->status.present)
+       if (acpi_bus_get_status(adev))
                return -EINVAL;
 
+       if (!acpi_dev_ready_for_enumeration(adev))
+               return -ENODEV;
+
        if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)
                return -ENODEV;
 
@@ -473,8 +476,8 @@ struct notifier_block i2c_acpi_notifier = {
 };
 
 /**
- * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource
- * @dev:     Device owning the ACPI resources to get the client from
+ * i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource
+ * @fwnode:  fwnode with the ACPI resources to get the client from
  * @index:   Index of ACPI resource to get
  * @info:    describes the I2C device; note this is modified (addr gets set)
  * Context: can sleep
@@ -490,15 +493,20 @@ struct notifier_block i2c_acpi_notifier = {
  * Returns a pointer to the new i2c-client, or error pointer in case of failure.
  * Specifically, -EPROBE_DEFER is returned if the adapter is not found.
  */
-struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
-                                      struct i2c_board_info *info)
+struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
+                                                int index,
+                                                struct i2c_board_info *info)
 {
-       struct acpi_device *adev = ACPI_COMPANION(dev);
        struct i2c_acpi_lookup lookup;
        struct i2c_adapter *adapter;
+       struct acpi_device *adev;
        LIST_HEAD(resource_list);
        int ret;
 
+       adev = to_acpi_device_node(fwnode);
+       if (!adev)
+               return ERR_PTR(-ENODEV);
+
        memset(&lookup, 0, sizeof(lookup));
        lookup.info = info;
        lookup.device_handle = acpi_device_handle(adev);
@@ -520,7 +528,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
 
        return i2c_new_client_device(adapter, info);
 }
-EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
+EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode);
 
 bool i2c_acpi_waive_d0_probe(struct device *dev)
 {
index 0c45e82..66d308e 100644 (file)
@@ -18,6 +18,8 @@ struct renesas_sdhi_scc {
        u32 tap_hs400_4tap;     /* sampling clock position for HS400 (4 TAP) */
 };
 
+#define SDHI_FLAG_NEED_CLKH_FALLBACK   BIT(0)
+
 struct renesas_sdhi_of_data {
        unsigned long tmio_flags;
        u32           tmio_ocr_mask;
@@ -31,6 +33,7 @@ struct renesas_sdhi_of_data {
        int taps_num;
        unsigned int max_blk_count;
        unsigned short max_segs;
+       unsigned long sdhi_flags;
 };
 
 #define SDHI_CALIB_TABLE_MAX 32
@@ -57,6 +60,7 @@ struct tmio_mmc_dma {
 
 struct renesas_sdhi {
        struct clk *clk;
+       struct clk *clkh;
        struct clk *clk_cd;
        struct tmio_mmc_data mmc_data;
        struct tmio_mmc_dma dma_priv;
index a4407f3..415911e 100644 (file)
@@ -127,10 +127,12 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
 }
 
 static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
-                                           unsigned int new_clock)
+                                           unsigned int wanted_clock)
 {
        struct renesas_sdhi *priv = host_to_priv(host);
+       struct clk *ref_clk = priv->clk;
        unsigned int freq, diff, best_freq = 0, diff_min = ~0;
+       unsigned int new_clock, clkh_shift = 0;
        int i;
 
        /*
@@ -141,6 +143,16 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
        if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2) || mmc_doing_tune(host->mmc))
                return clk_get_rate(priv->clk);
 
+       if (priv->clkh) {
+               bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
+               bool need_slow_clkh = (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
+                                     (host->mmc->ios.timing == MMC_TIMING_MMC_HS400);
+               clkh_shift = use_4tap && need_slow_clkh ? 1 : 2;
+               ref_clk = priv->clkh;
+       }
+
+       new_clock = wanted_clock << clkh_shift;
+
        /*
         * We want the bus clock to be as close as possible to, but no
         * greater than, new_clock.  As we can divide by 1 << i for
@@ -148,11 +160,10 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
         * possible, but no greater than, new_clock << i.
         */
        for (i = min(9, ilog2(UINT_MAX / new_clock)); i >= 0; i--) {
-               freq = clk_round_rate(priv->clk, new_clock << i);
+               freq = clk_round_rate(ref_clk, new_clock << i);
                if (freq > (new_clock << i)) {
                        /* Too fast; look for a slightly slower option */
-                       freq = clk_round_rate(priv->clk,
-                                             (new_clock << i) / 4 * 3);
+                       freq = clk_round_rate(ref_clk, (new_clock << i) / 4 * 3);
                        if (freq > (new_clock << i))
                                continue;
                }
@@ -164,7 +175,10 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
                }
        }
 
-       clk_set_rate(priv->clk, best_freq);
+       clk_set_rate(ref_clk, best_freq);
+
+       if (priv->clkh)
+               clk_set_rate(priv->clk, best_freq >> clkh_shift);
 
        return clk_get_rate(priv->clk);
 }
@@ -904,11 +918,12 @@ int renesas_sdhi_probe(struct platform_device *pdev,
        dma_priv = &priv->dma_priv;
 
        priv->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(priv->clk)) {
-               ret = PTR_ERR(priv->clk);
-               dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(priv->clk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), "cannot get clock");
+
+       priv->clkh = devm_clk_get_optional(&pdev->dev, "clkh");
+       if (IS_ERR(priv->clkh))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clkh), "cannot get clkh");
 
        /*
         * Some controllers provide a 2nd clock just to run the internal card
@@ -921,9 +936,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
         * to the card detect circuit. That leaves us with if separate clocks
         * are presented, we must treat them both as virtually 1 clock.
         */
-       priv->clk_cd = devm_clk_get(&pdev->dev, "cd");
+       priv->clk_cd = devm_clk_get_optional(&pdev->dev, "cd");
        if (IS_ERR(priv->clk_cd))
-               priv->clk_cd = NULL;
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk_cd), "cannot get cd clock");
 
        priv->pinctrl = devm_pinctrl_get(&pdev->dev);
        if (!IS_ERR(priv->pinctrl)) {
@@ -947,6 +962,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
                mmc_data->max_segs = of_data->max_segs;
                dma_priv->dma_buswidth = of_data->dma_buswidth;
                host->bus_shift = of_data->bus_shift;
+               /* Fallback for old DTs */
+               if (!priv->clkh && of_data->sdhi_flags & SDHI_FLAG_NEED_CLKH_FALLBACK)
+                       priv->clkh = clk_get_parent(clk_get_parent(priv->clk));
+
        }
 
        host->write16_hook      = renesas_sdhi_write16_hook;
@@ -1044,7 +1063,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
             host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR |
                                 MMC_CAP2_HS400_1_8V))) {
                const struct renesas_sdhi_scc *taps = of_data->taps;
-               bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
+               bool use_4tap = quirks && quirks->hs400_4taps;
                bool hit = false;
 
                for (i = 0; i < of_data->taps_num; i++) {
index 7660f7e..9d2c600 100644 (file)
@@ -125,6 +125,22 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
        /* DMAC can handle 32bit blk count but only 1 segment */
        .max_blk_count  = UINT_MAX / TMIO_MAX_BLK_SIZE,
        .max_segs       = 1,
+       .sdhi_flags     = SDHI_FLAG_NEED_CLKH_FALLBACK,
+};
+
+static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_fallback = {
+       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
+                         TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+                         MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY,
+       .capabilities2  = MMC_CAP2_NO_WRITE_PROTECT | MMC_CAP2_MERGE_CAPABLE,
+       .bus_shift      = 2,
+       .scc_offset     = 0x1000,
+       .taps           = rcar_gen3_scc_taps,
+       .taps_num       = ARRAY_SIZE(rcar_gen3_scc_taps),
+       /* DMAC can handle 32bit blk count but only 1 segment */
+       .max_blk_count  = UINT_MAX / TMIO_MAX_BLK_SIZE,
+       .max_segs       = 1,
 };
 
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
@@ -214,6 +230,10 @@ static const struct renesas_sdhi_of_data_with_quirks of_r8a77965_compatible = {
        .quirks = &sdhi_quirks_r8a77965,
 };
 
+static const struct renesas_sdhi_of_data_with_quirks of_r8a77970_compatible = {
+       .of_data = &of_data_rcar_gen3_no_fallback,
+};
+
 static const struct renesas_sdhi_of_data_with_quirks of_r8a77980_compatible = {
        .of_data = &of_data_rcar_gen3,
        .quirks = &sdhi_quirks_nohs400,
@@ -235,6 +255,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
        { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },
        { .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
        { .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
+       { .compatible = "renesas,sdhi-r8a77970", .data = &of_r8a77970_compatible, },
        { .compatible = "renesas,sdhi-r8a77980", .data = &of_r8a77980_compatible, },
        { .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, },
        { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, },
index 2362e04..cfec778 100644 (file)
@@ -1,5 +1,4 @@
-obj-$(CONFIG_INTEL_SKL_INT3472)                += intel_skl_int3472.o
-intel_skl_int3472-y                    := intel_skl_int3472_common.o \
-                                          intel_skl_int3472_discrete.o \
-                                          intel_skl_int3472_tps68470.o \
-                                          intel_skl_int3472_clk_and_regulator.o
+obj-$(CONFIG_INTEL_SKL_INT3472)                += intel_skl_int3472_discrete.o \
+                                          intel_skl_int3472_tps68470.o
+intel_skl_int3472_discrete-y           := discrete.o clk_and_regulator.o common.o
+intel_skl_int3472_tps68470-y           := tps68470.o tps68470_board_data.o common.o
diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c
new file mode 100644 (file)
index 0000000..1cf9589
--- /dev/null
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+
+#include <linux/acpi.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+#include "common.h"
+
+/*
+ * The regulators have to have .ops to be valid, but the only ops we actually
+ * support are .enable and .disable which are handled via .ena_gpiod. Pass an
+ * empty struct to clear the check without lying about capabilities.
+ */
+static const struct regulator_ops int3472_gpio_regulator_ops;
+
+static int skl_int3472_clk_prepare(struct clk_hw *hw)
+{
+       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
+
+       gpiod_set_value_cansleep(clk->ena_gpio, 1);
+       gpiod_set_value_cansleep(clk->led_gpio, 1);
+
+       return 0;
+}
+
+static void skl_int3472_clk_unprepare(struct clk_hw *hw)
+{
+       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
+
+       gpiod_set_value_cansleep(clk->ena_gpio, 0);
+       gpiod_set_value_cansleep(clk->led_gpio, 0);
+}
+
+static int skl_int3472_clk_enable(struct clk_hw *hw)
+{
+       /*
+        * We're just turning a GPIO on to enable the clock, which operation
+        * has the potential to sleep. Given .enable() cannot sleep, but
+        * .prepare() can, we toggle the GPIO in .prepare() instead. Thus,
+        * nothing to do here.
+        */
+       return 0;
+}
+
+static void skl_int3472_clk_disable(struct clk_hw *hw)
+{
+       /* Likewise, nothing to do here... */
+}
+
+static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device *int3472)
+{
+       union acpi_object *obj;
+       unsigned int freq;
+
+       obj = skl_int3472_get_acpi_buffer(int3472->sensor, "SSDB");
+       if (IS_ERR(obj))
+               return 0; /* report rate as 0 on error */
+
+       if (obj->buffer.length < CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET + sizeof(u32)) {
+               dev_err(int3472->dev, "The buffer is too small\n");
+               kfree(obj);
+               return 0;
+       }
+
+       freq = *(u32 *)(obj->buffer.pointer + CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET);
+
+       kfree(obj);
+       return freq;
+}
+
+static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
+                                                unsigned long parent_rate)
+{
+       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
+
+       return clk->frequency;
+}
+
+static const struct clk_ops skl_int3472_clock_ops = {
+       .prepare = skl_int3472_clk_prepare,
+       .unprepare = skl_int3472_clk_unprepare,
+       .enable = skl_int3472_clk_enable,
+       .disable = skl_int3472_clk_disable,
+       .recalc_rate = skl_int3472_clk_recalc_rate,
+};
+
+int skl_int3472_register_clock(struct int3472_discrete_device *int3472)
+{
+       struct clk_init_data init = {
+               .ops = &skl_int3472_clock_ops,
+               .flags = CLK_GET_RATE_NOCACHE,
+       };
+       int ret;
+
+       init.name = kasprintf(GFP_KERNEL, "%s-clk",
+                             acpi_dev_name(int3472->adev));
+       if (!init.name)
+               return -ENOMEM;
+
+       int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
+
+       int3472->clock.clk_hw.init = &init;
+       int3472->clock.clk = clk_register(&int3472->adev->dev,
+                                         &int3472->clock.clk_hw);
+       if (IS_ERR(int3472->clock.clk)) {
+               ret = PTR_ERR(int3472->clock.clk);
+               goto out_free_init_name;
+       }
+
+       int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL,
+                                         int3472->sensor_name);
+       if (!int3472->clock.cl) {
+               ret = -ENOMEM;
+               goto err_unregister_clk;
+       }
+
+       kfree(init.name);
+       return 0;
+
+err_unregister_clk:
+       clk_unregister(int3472->clock.clk);
+out_free_init_name:
+       kfree(init.name);
+
+       return ret;
+}
+
+void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472)
+{
+       clkdev_drop(int3472->clock.cl);
+       clk_unregister(int3472->clock.clk);
+}
+
+int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
+                                  struct acpi_resource_gpio *agpio)
+{
+       const struct int3472_sensor_config *sensor_config;
+       char *path = agpio->resource_source.string_ptr;
+       struct regulator_consumer_supply supply_map;
+       struct regulator_init_data init_data = { };
+       struct regulator_config cfg = { };
+       int ret;
+
+       sensor_config = int3472->sensor_config;
+       if (IS_ERR(sensor_config)) {
+               dev_err(int3472->dev, "No sensor module config\n");
+               return PTR_ERR(sensor_config);
+       }
+
+       if (!sensor_config->supply_map.supply) {
+               dev_err(int3472->dev, "No supply name defined\n");
+               return -ENODEV;
+       }
+
+       init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
+       init_data.num_consumer_supplies = 1;
+       supply_map = sensor_config->supply_map;
+       supply_map.dev_name = int3472->sensor_name;
+       init_data.consumer_supplies = &supply_map;
+
+       snprintf(int3472->regulator.regulator_name,
+                sizeof(int3472->regulator.regulator_name), "%s-regulator",
+                acpi_dev_name(int3472->adev));
+       snprintf(int3472->regulator.supply_name,
+                GPIO_REGULATOR_SUPPLY_NAME_LENGTH, "supply-0");
+
+       int3472->regulator.rdesc = INT3472_REGULATOR(
+                                               int3472->regulator.regulator_name,
+                                               int3472->regulator.supply_name,
+                                               &int3472_gpio_regulator_ops);
+
+       int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0],
+                                                            "int3472,regulator");
+       if (IS_ERR(int3472->regulator.gpio)) {
+               dev_err(int3472->dev, "Failed to get regulator GPIO line\n");
+               return PTR_ERR(int3472->regulator.gpio);
+       }
+
+       cfg.dev = &int3472->adev->dev;
+       cfg.init_data = &init_data;
+       cfg.ena_gpiod = int3472->regulator.gpio;
+
+       int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc,
+                                                    &cfg);
+       if (IS_ERR(int3472->regulator.rdev)) {
+               ret = PTR_ERR(int3472->regulator.rdev);
+               goto err_free_gpio;
+       }
+
+       return 0;
+
+err_free_gpio:
+       gpiod_put(int3472->regulator.gpio);
+
+       return ret;
+}
+
+void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472)
+{
+       regulator_unregister(int3472->regulator.rdev);
+       gpiod_put(int3472->regulator.gpio);
+}
diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c
new file mode 100644 (file)
index 0000000..77cf058
--- /dev/null
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+
+#include <linux/acpi.h>
+#include <linux/slab.h>
+
+#include "common.h"
+
+union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       acpi_handle handle = adev->handle;
+       union acpi_object *obj;
+       acpi_status status;
+
+       status = acpi_evaluate_object(handle, id, NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return ERR_PTR(-ENODEV);
+
+       obj = buffer.pointer;
+       if (!obj)
+               return ERR_PTR(-ENODEV);
+
+       if (obj->type != ACPI_TYPE_BUFFER) {
+               acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
+               kfree(obj);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return obj;
+}
+
+int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
+{
+       union acpi_object *obj;
+       int ret;
+
+       obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
+       if (IS_ERR(obj))
+               return PTR_ERR(obj);
+
+       if (obj->buffer.length > sizeof(*cldb)) {
+               acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
+               ret = -EINVAL;
+               goto out_free_obj;
+       }
+
+       memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
+       ret = 0;
+
+out_free_obj:
+       kfree(obj);
+       return ret;
+}
+
+/* sensor_adev_ret may be NULL, name_ret must not be NULL */
+int skl_int3472_get_sensor_adev_and_name(struct device *dev,
+                                        struct acpi_device **sensor_adev_ret,
+                                        const char **name_ret)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct acpi_device *sensor;
+       int ret = 0;
+
+       sensor = acpi_dev_get_first_consumer_dev(adev);
+       if (!sensor) {
+               dev_err(dev, "INT3472 seems to have no dependents.\n");
+               return -ENODEV;
+       }
+
+       *name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
+                                  acpi_dev_name(sensor));
+       if (!*name_ret)
+               ret = -ENOMEM;
+
+       if (ret == 0 && sensor_adev_ret)
+               *sensor_adev_ret = sensor;
+       else
+               acpi_dev_put(sensor);
+
+       return ret;
+}
diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h
new file mode 100644 (file)
index 0000000..53270d1
--- /dev/null
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Author: Dan Scally <djrscally@gmail.com> */
+
+#ifndef _INTEL_SKL_INT3472_H
+#define _INTEL_SKL_INT3472_H
+
+#include <linux/clk-provider.h>
+#include <linux/gpio/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/types.h>
+
+/* FIXME drop this once the I2C_DEV_NAME_FORMAT macro has been added to include/linux/i2c.h */
+#ifndef I2C_DEV_NAME_FORMAT
+#define I2C_DEV_NAME_FORMAT                                    "i2c-%s"
+#endif
+
+/* PMIC GPIO Types */
+#define INT3472_GPIO_TYPE_RESET                                        0x00
+#define INT3472_GPIO_TYPE_POWERDOWN                            0x01
+#define INT3472_GPIO_TYPE_POWER_ENABLE                         0x0b
+#define INT3472_GPIO_TYPE_CLK_ENABLE                           0x0c
+#define INT3472_GPIO_TYPE_PRIVACY_LED                          0x0d
+
+#define INT3472_PDEV_MAX_NAME_LEN                              23
+#define INT3472_MAX_SENSOR_GPIOS                               3
+
+#define GPIO_REGULATOR_NAME_LENGTH                             21
+#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH                      9
+
+#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET                      86
+
+#define INT3472_REGULATOR(_name, _supply, _ops)                        \
+       (const struct regulator_desc) {                         \
+               .name = _name,                                  \
+               .supply_name = _supply,                         \
+               .type = REGULATOR_VOLTAGE,                      \
+               .ops = _ops,                                    \
+               .owner = THIS_MODULE,                           \
+       }
+
+#define to_int3472_clk(hw)                                     \
+       container_of(hw, struct int3472_gpio_clock, clk_hw)
+
+#define to_int3472_device(clk)                                 \
+       container_of(clk, struct int3472_discrete_device, clock)
+
+struct acpi_device;
+struct i2c_client;
+struct platform_device;
+
+struct int3472_cldb {
+       u8 version;
+       /*
+        * control logic type
+        * 0: UNKNOWN
+        * 1: DISCRETE(CRD-D)
+        * 2: PMIC TPS68470
+        * 3: PMIC uP6641
+        */
+       u8 control_logic_type;
+       u8 control_logic_id;
+       u8 sensor_card_sku;
+       u8 reserved[28];
+};
+
+struct int3472_gpio_function_remap {
+       const char *documented;
+       const char *actual;
+};
+
+struct int3472_sensor_config {
+       const char *sensor_module_name;
+       struct regulator_consumer_supply supply_map;
+       const struct int3472_gpio_function_remap *function_maps;
+};
+
+struct int3472_discrete_device {
+       struct acpi_device *adev;
+       struct device *dev;
+       struct acpi_device *sensor;
+       const char *sensor_name;
+
+       const struct int3472_sensor_config *sensor_config;
+
+       struct int3472_gpio_regulator {
+               char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
+               char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
+               struct gpio_desc *gpio;
+               struct regulator_dev *rdev;
+               struct regulator_desc rdesc;
+       } regulator;
+
+       struct int3472_gpio_clock {
+               struct clk *clk;
+               struct clk_hw clk_hw;
+               struct clk_lookup *cl;
+               struct gpio_desc *ena_gpio;
+               struct gpio_desc *led_gpio;
+               u32 frequency;
+       } clock;
+
+       unsigned int ngpios; /* how many GPIOs have we seen */
+       unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
+       struct gpiod_lookup_table gpios;
+};
+
+union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
+                                              char *id);
+int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
+int skl_int3472_get_sensor_adev_and_name(struct device *dev,
+                                        struct acpi_device **sensor_adev_ret,
+                                        const char **name_ret);
+
+int skl_int3472_register_clock(struct int3472_discrete_device *int3472);
+void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);
+
+int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
+                                  struct acpi_resource_gpio *agpio);
+void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);
+
+#endif
diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c
new file mode 100644 (file)
index 0000000..5b514fa
--- /dev/null
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+
+#include <linux/acpi.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+#include <linux/uuid.h>
+
+#include "common.h"
+
+/*
+ * 79234640-9e10-4fea-a5c1-b5aa8b19756f
+ * This _DSM GUID returns information about the GPIO lines mapped to a
+ * discrete INT3472 device. Function number 1 returns a count of the GPIO
+ * lines that are mapped. Subsequent functions return 32 bit ints encoding
+ * information about the GPIO line, including its purpose.
+ */
+static const guid_t int3472_gpio_guid =
+       GUID_INIT(0x79234640, 0x9e10, 0x4fea,
+                 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
+
+/*
+ * 822ace8f-2814-4174-a56b-5f029fe079ee
+ * This _DSM GUID returns a string from the sensor device, which acts as a
+ * module identifier.
+ */
+static const guid_t cio2_sensor_module_guid =
+       GUID_INIT(0x822ace8f, 0x2814, 0x4174,
+                 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
+
+/*
+ * Here follows platform specific mapping information that we can pass to
+ * the functions mapping resources to the sensors. Where the sensors have
+ * a power enable pin defined in DSDT we need to provide a supply name so
+ * the sensor drivers can find the regulator. The device name will be derived
+ * from the sensor's ACPI device within the code. Optionally, we can provide a
+ * NULL terminated array of function name mappings to deal with any platform
+ * specific deviations from the documented behaviour of GPIOs.
+ *
+ * Map a GPIO function name to NULL to prevent the driver from mapping that
+ * GPIO at all.
+ */
+
+static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = {
+       { "reset", NULL },
+       { "powerdown", "reset" },
+       { }
+};
+
+static const struct int3472_sensor_config int3472_sensor_configs[] = {
+       /* Lenovo Miix 510-12ISK - OV2680, Front */
+       { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps },
+       /* Lenovo Miix 510-12ISK - OV5648, Rear */
+       { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL },
+       /* Surface Go 1&2 - OV5693, Front */
+       { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL },
+};
+
+static const struct int3472_sensor_config *
+skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472)
+{
+       union acpi_object *obj;
+       unsigned int i;
+
+       obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
+                                     &cio2_sensor_module_guid, 0x00,
+                                     0x01, NULL, ACPI_TYPE_STRING);
+
+       if (!obj) {
+               dev_err(int3472->dev,
+                       "Failed to get sensor module string from _DSM\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       if (obj->string.type != ACPI_TYPE_STRING) {
+               dev_err(int3472->dev,
+                       "Sensor _DSM returned a non-string value\n");
+
+               ACPI_FREE(obj);
+               return ERR_PTR(-EINVAL);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) {
+               if (!strcmp(int3472_sensor_configs[i].sensor_module_name,
+                           obj->string.pointer))
+                       break;
+       }
+
+       ACPI_FREE(obj);
+
+       if (i >= ARRAY_SIZE(int3472_sensor_configs))
+               return ERR_PTR(-EINVAL);
+
+       return &int3472_sensor_configs[i];
+}
+
+static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
+                                         struct acpi_resource_gpio *agpio,
+                                         const char *func, u32 polarity)
+{
+       const struct int3472_sensor_config *sensor_config;
+       char *path = agpio->resource_source.string_ptr;
+       struct gpiod_lookup *table_entry;
+       struct acpi_device *adev;
+       acpi_handle handle;
+       acpi_status status;
+       int ret;
+
+       if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
+               dev_warn(int3472->dev, "Too many GPIOs mapped\n");
+               return -EINVAL;
+       }
+
+       sensor_config = int3472->sensor_config;
+       if (!IS_ERR(sensor_config) && sensor_config->function_maps) {
+               const struct int3472_gpio_function_remap *remap;
+
+               for (remap = sensor_config->function_maps; remap->documented; remap++) {
+                       if (!strcmp(func, remap->documented)) {
+                               func = remap->actual;
+                               break;
+                       }
+               }
+       }
+
+       /* Functions mapped to NULL should not be mapped to the sensor */
+       if (!func)
+               return 0;
+
+       status = acpi_get_handle(NULL, path, &handle);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
+
+       ret = acpi_bus_get_device(handle, &adev);
+       if (ret)
+               return -ENODEV;
+
+       table_entry = &int3472->gpios.table[int3472->n_sensor_gpios];
+       table_entry->key = acpi_dev_name(adev);
+       table_entry->chip_hwnum = agpio->pin_table[0];
+       table_entry->con_id = func;
+       table_entry->idx = 0;
+       table_entry->flags = polarity;
+
+       int3472->n_sensor_gpios++;
+
+       return 0;
+}
+
+static int skl_int3472_map_gpio_to_clk(struct int3472_discrete_device *int3472,
+                                      struct acpi_resource_gpio *agpio, u8 type)
+{
+       char *path = agpio->resource_source.string_ptr;
+       u16 pin = agpio->pin_table[0];
+       struct gpio_desc *gpio;
+
+       switch (type) {
+       case INT3472_GPIO_TYPE_CLK_ENABLE:
+               gpio = acpi_get_and_request_gpiod(path, pin, "int3472,clk-enable");
+               if (IS_ERR(gpio))
+                       return (PTR_ERR(gpio));
+
+               int3472->clock.ena_gpio = gpio;
+               break;
+       case INT3472_GPIO_TYPE_PRIVACY_LED:
+               gpio = acpi_get_and_request_gpiod(path, pin, "int3472,privacy-led");
+               if (IS_ERR(gpio))
+                       return (PTR_ERR(gpio));
+
+               int3472->clock.led_gpio = gpio;
+               break;
+       default:
+               dev_err(int3472->dev, "Invalid GPIO type 0x%02x for clock\n", type);
+               break;
+       }
+
+       return 0;
+}
+
+/**
+ * skl_int3472_handle_gpio_resources: Map PMIC resources to consuming sensor
+ * @ares: A pointer to a &struct acpi_resource
+ * @data: A pointer to a &struct int3472_discrete_device
+ *
+ * This function handles GPIO resources that are against an INT3472
+ * ACPI device, by checking the value of the corresponding _DSM entry.
+ * This will return a 32bit int, where the lowest byte represents the
+ * function of the GPIO pin:
+ *
+ * 0x00 Reset
+ * 0x01 Power down
+ * 0x0b Power enable
+ * 0x0c Clock enable
+ * 0x0d Privacy LED
+ *
+ * There are some known platform specific quirks where that does not quite
+ * hold up; for example where a pin with type 0x01 (Power down) is mapped to
+ * a sensor pin that performs a reset function or entries in _CRS and _DSM that
+ * do not actually correspond to a physical connection. These will be handled
+ * by the mapping sub-functions.
+ *
+ * GPIOs will either be mapped directly to the sensor device or else used
+ * to create clocks and regulators via the usual frameworks.
+ *
+ * Return:
+ * * 1         - To continue the loop
+ * * 0         - When all resources found are handled properly.
+ * * -EINVAL   - If the resource is not a GPIO IO resource
+ * * -ENODEV   - If the resource has no corresponding _DSM entry
+ * * -Other    - Errors propagated from one of the sub-functions.
+ */
+static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
+                                            void *data)
+{
+       struct int3472_discrete_device *int3472 = data;
+       struct acpi_resource_gpio *agpio;
+       union acpi_object *obj;
+       const char *err_msg;
+       int ret;
+       u8 type;
+
+       if (!acpi_gpio_get_io_resource(ares, &agpio))
+               return 1;
+
+       /*
+        * ngpios + 2 because the index of this _DSM function is 1-based and
+        * the first function is just a count.
+        */
+       obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
+                                     &int3472_gpio_guid, 0x00,
+                                     int3472->ngpios + 2,
+                                     NULL, ACPI_TYPE_INTEGER);
+
+       if (!obj) {
+               dev_warn(int3472->dev, "No _DSM entry for GPIO pin %u\n",
+                        agpio->pin_table[0]);
+               return 1;
+       }
+
+       type = obj->integer.value & 0xff;
+
+       switch (type) {
+       case INT3472_GPIO_TYPE_RESET:
+               ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "reset",
+                                                    GPIO_ACTIVE_LOW);
+               if (ret)
+                       err_msg = "Failed to map reset pin to sensor\n";
+
+               break;
+       case INT3472_GPIO_TYPE_POWERDOWN:
+               ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "powerdown",
+                                                    GPIO_ACTIVE_LOW);
+               if (ret)
+                       err_msg = "Failed to map powerdown pin to sensor\n";
+
+               break;
+       case INT3472_GPIO_TYPE_CLK_ENABLE:
+       case INT3472_GPIO_TYPE_PRIVACY_LED:
+               ret = skl_int3472_map_gpio_to_clk(int3472, agpio, type);
+               if (ret)
+                       err_msg = "Failed to map GPIO to clock\n";
+
+               break;
+       case INT3472_GPIO_TYPE_POWER_ENABLE:
+               ret = skl_int3472_register_regulator(int3472, agpio);
+               if (ret)
+                       err_msg = "Failed to map regulator to sensor\n";
+
+               break;
+       default:
+               dev_warn(int3472->dev,
+                        "GPIO type 0x%02x unknown; the sensor may not work\n",
+                        type);
+               ret = 1;
+               break;
+       }
+
+       int3472->ngpios++;
+       ACPI_FREE(obj);
+
+       if (ret < 0)
+               return dev_err_probe(int3472->dev, ret, err_msg);
+
+       return ret;
+}
+
+static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
+{
+       LIST_HEAD(resource_list);
+       int ret;
+
+       /*
+        * No error check, because not having a sensor config is not necessarily
+        * a failure mode.
+        */
+       int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472);
+
+       ret = acpi_dev_get_resources(int3472->adev, &resource_list,
+                                    skl_int3472_handle_gpio_resources,
+                                    int3472);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&resource_list);
+
+       /*
+        * If we find no clock enable GPIO pin then the privacy LED won't work.
+        * We've never seen that situation, but it's possible. Warn the user so
+        * it's clear what's happened.
+        */
+       if (int3472->clock.ena_gpio) {
+               ret = skl_int3472_register_clock(int3472);
+               if (ret)
+                       return ret;
+       } else {
+               if (int3472->clock.led_gpio)
+                       dev_warn(int3472->dev,
+                                "No clk GPIO. The privacy LED won't work\n");
+       }
+
+       int3472->gpios.dev_id = int3472->sensor_name;
+       gpiod_add_lookup_table(&int3472->gpios);
+
+       return 0;
+}
+
+static int skl_int3472_discrete_remove(struct platform_device *pdev);
+
+static int skl_int3472_discrete_probe(struct platform_device *pdev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+       struct int3472_discrete_device *int3472;
+       struct int3472_cldb cldb;
+       int ret;
+
+       ret = skl_int3472_fill_cldb(adev, &cldb);
+       if (ret) {
+               dev_err(&pdev->dev, "Couldn't fill CLDB structure\n");
+               return ret;
+       }
+
+       if (cldb.control_logic_type != 1) {
+               dev_err(&pdev->dev, "Unsupported control logic type %u\n",
+                       cldb.control_logic_type);
+               return -EINVAL;
+       }
+
+       /* Max num GPIOs we've seen plus a terminator */
+       int3472 = devm_kzalloc(&pdev->dev, struct_size(int3472, gpios.table,
+                              INT3472_MAX_SENSOR_GPIOS + 1), GFP_KERNEL);
+       if (!int3472)
+               return -ENOMEM;
+
+       int3472->adev = adev;
+       int3472->dev = &pdev->dev;
+       platform_set_drvdata(pdev, int3472);
+
+       ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor,
+                                                  &int3472->sensor_name);
+       if (ret)
+               return ret;
+
+       /*
+        * Initialising this list means we can call gpiod_remove_lookup_table()
+        * in failure paths without issue.
+        */
+       INIT_LIST_HEAD(&int3472->gpios.list);
+
+       ret = skl_int3472_parse_crs(int3472);
+       if (ret) {
+               skl_int3472_discrete_remove(pdev);
+               return ret;
+       }
+
+       acpi_dev_clear_dependencies(adev);
+       return 0;
+}
+
+static int skl_int3472_discrete_remove(struct platform_device *pdev)
+{
+       struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev);
+
+       gpiod_remove_lookup_table(&int3472->gpios);
+
+       if (int3472->clock.cl)
+               skl_int3472_unregister_clock(int3472);
+
+       gpiod_put(int3472->clock.ena_gpio);
+       gpiod_put(int3472->clock.led_gpio);
+
+       skl_int3472_unregister_regulator(int3472);
+
+       return 0;
+}
+
+static const struct acpi_device_id int3472_device_id[] = {
+       { "INT3472", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, int3472_device_id);
+
+static struct platform_driver int3472_discrete = {
+       .driver = {
+               .name = "int3472-discrete",
+               .acpi_match_table = int3472_device_id,
+       },
+       .probe = skl_int3472_discrete_probe,
+       .remove = skl_int3472_discrete_remove,
+};
+module_platform_driver(int3472_discrete);
+
+MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Discrete Device Driver");
+MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c
deleted file mode 100644 (file)
index 1700e75..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Author: Dan Scally <djrscally@gmail.com> */
-
-#include <linux/acpi.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/regulator/driver.h>
-#include <linux/slab.h>
-
-#include "intel_skl_int3472_common.h"
-
-/*
- * The regulators have to have .ops to be valid, but the only ops we actually
- * support are .enable and .disable which are handled via .ena_gpiod. Pass an
- * empty struct to clear the check without lying about capabilities.
- */
-static const struct regulator_ops int3472_gpio_regulator_ops;
-
-static int skl_int3472_clk_prepare(struct clk_hw *hw)
-{
-       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
-
-       gpiod_set_value_cansleep(clk->ena_gpio, 1);
-       gpiod_set_value_cansleep(clk->led_gpio, 1);
-
-       return 0;
-}
-
-static void skl_int3472_clk_unprepare(struct clk_hw *hw)
-{
-       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
-
-       gpiod_set_value_cansleep(clk->ena_gpio, 0);
-       gpiod_set_value_cansleep(clk->led_gpio, 0);
-}
-
-static int skl_int3472_clk_enable(struct clk_hw *hw)
-{
-       /*
-        * We're just turning a GPIO on to enable the clock, which operation
-        * has the potential to sleep. Given .enable() cannot sleep, but
-        * .prepare() can, we toggle the GPIO in .prepare() instead. Thus,
-        * nothing to do here.
-        */
-       return 0;
-}
-
-static void skl_int3472_clk_disable(struct clk_hw *hw)
-{
-       /* Likewise, nothing to do here... */
-}
-
-static unsigned int skl_int3472_get_clk_frequency(struct int3472_discrete_device *int3472)
-{
-       union acpi_object *obj;
-       unsigned int freq;
-
-       obj = skl_int3472_get_acpi_buffer(int3472->sensor, "SSDB");
-       if (IS_ERR(obj))
-               return 0; /* report rate as 0 on error */
-
-       if (obj->buffer.length < CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET + sizeof(u32)) {
-               dev_err(int3472->dev, "The buffer is too small\n");
-               kfree(obj);
-               return 0;
-       }
-
-       freq = *(u32 *)(obj->buffer.pointer + CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET);
-
-       kfree(obj);
-       return freq;
-}
-
-static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw,
-                                                unsigned long parent_rate)
-{
-       struct int3472_gpio_clock *clk = to_int3472_clk(hw);
-
-       return clk->frequency;
-}
-
-static const struct clk_ops skl_int3472_clock_ops = {
-       .prepare = skl_int3472_clk_prepare,
-       .unprepare = skl_int3472_clk_unprepare,
-       .enable = skl_int3472_clk_enable,
-       .disable = skl_int3472_clk_disable,
-       .recalc_rate = skl_int3472_clk_recalc_rate,
-};
-
-int skl_int3472_register_clock(struct int3472_discrete_device *int3472)
-{
-       struct clk_init_data init = {
-               .ops = &skl_int3472_clock_ops,
-               .flags = CLK_GET_RATE_NOCACHE,
-       };
-       int ret;
-
-       init.name = kasprintf(GFP_KERNEL, "%s-clk",
-                             acpi_dev_name(int3472->adev));
-       if (!init.name)
-               return -ENOMEM;
-
-       int3472->clock.frequency = skl_int3472_get_clk_frequency(int3472);
-
-       int3472->clock.clk_hw.init = &init;
-       int3472->clock.clk = clk_register(&int3472->adev->dev,
-                                         &int3472->clock.clk_hw);
-       if (IS_ERR(int3472->clock.clk)) {
-               ret = PTR_ERR(int3472->clock.clk);
-               goto out_free_init_name;
-       }
-
-       int3472->clock.cl = clkdev_create(int3472->clock.clk, NULL,
-                                         int3472->sensor_name);
-       if (!int3472->clock.cl) {
-               ret = -ENOMEM;
-               goto err_unregister_clk;
-       }
-
-       kfree(init.name);
-       return 0;
-
-err_unregister_clk:
-       clk_unregister(int3472->clock.clk);
-out_free_init_name:
-       kfree(init.name);
-
-       return ret;
-}
-
-void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472)
-{
-       clkdev_drop(int3472->clock.cl);
-       clk_unregister(int3472->clock.clk);
-}
-
-int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
-                                  struct acpi_resource_gpio *agpio)
-{
-       const struct int3472_sensor_config *sensor_config;
-       char *path = agpio->resource_source.string_ptr;
-       struct regulator_consumer_supply supply_map;
-       struct regulator_init_data init_data = { };
-       struct regulator_config cfg = { };
-       int ret;
-
-       sensor_config = int3472->sensor_config;
-       if (IS_ERR(sensor_config)) {
-               dev_err(int3472->dev, "No sensor module config\n");
-               return PTR_ERR(sensor_config);
-       }
-
-       if (!sensor_config->supply_map.supply) {
-               dev_err(int3472->dev, "No supply name defined\n");
-               return -ENODEV;
-       }
-
-       init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
-       init_data.num_consumer_supplies = 1;
-       supply_map = sensor_config->supply_map;
-       supply_map.dev_name = int3472->sensor_name;
-       init_data.consumer_supplies = &supply_map;
-
-       snprintf(int3472->regulator.regulator_name,
-                sizeof(int3472->regulator.regulator_name), "%s-regulator",
-                acpi_dev_name(int3472->adev));
-       snprintf(int3472->regulator.supply_name,
-                GPIO_REGULATOR_SUPPLY_NAME_LENGTH, "supply-0");
-
-       int3472->regulator.rdesc = INT3472_REGULATOR(
-                                               int3472->regulator.regulator_name,
-                                               int3472->regulator.supply_name,
-                                               &int3472_gpio_regulator_ops);
-
-       int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0],
-                                                            "int3472,regulator");
-       if (IS_ERR(int3472->regulator.gpio)) {
-               dev_err(int3472->dev, "Failed to get regulator GPIO line\n");
-               return PTR_ERR(int3472->regulator.gpio);
-       }
-
-       cfg.dev = &int3472->adev->dev;
-       cfg.init_data = &init_data;
-       cfg.ena_gpiod = int3472->regulator.gpio;
-
-       int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc,
-                                                    &cfg);
-       if (IS_ERR(int3472->regulator.rdev)) {
-               ret = PTR_ERR(int3472->regulator.rdev);
-               goto err_free_gpio;
-       }
-
-       return 0;
-
-err_free_gpio:
-       gpiod_put(int3472->regulator.gpio);
-
-       return ret;
-}
-
-void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472)
-{
-       regulator_unregister(int3472->regulator.rdev);
-       gpiod_put(int3472->regulator.gpio);
-}
diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.c
deleted file mode 100644 (file)
index 497e74f..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Author: Dan Scally <djrscally@gmail.com> */
-
-#include <linux/acpi.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "intel_skl_int3472_common.h"
-
-union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev, char *id)
-{
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       acpi_handle handle = adev->handle;
-       union acpi_object *obj;
-       acpi_status status;
-
-       status = acpi_evaluate_object(handle, id, NULL, &buffer);
-       if (ACPI_FAILURE(status))
-               return ERR_PTR(-ENODEV);
-
-       obj = buffer.pointer;
-       if (!obj)
-               return ERR_PTR(-ENODEV);
-
-       if (obj->type != ACPI_TYPE_BUFFER) {
-               acpi_handle_err(handle, "%s object is not an ACPI buffer\n", id);
-               kfree(obj);
-               return ERR_PTR(-EINVAL);
-       }
-
-       return obj;
-}
-
-int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
-{
-       union acpi_object *obj;
-       int ret;
-
-       obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
-       if (IS_ERR(obj))
-               return PTR_ERR(obj);
-
-       if (obj->buffer.length > sizeof(*cldb)) {
-               acpi_handle_err(adev->handle, "The CLDB buffer is too large\n");
-               ret = -EINVAL;
-               goto out_free_obj;
-       }
-
-       memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
-       ret = 0;
-
-out_free_obj:
-       kfree(obj);
-       return ret;
-}
-
-static const struct acpi_device_id int3472_device_id[] = {
-       { "INT3472", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(acpi, int3472_device_id);
-
-static struct platform_driver int3472_discrete = {
-       .driver = {
-               .name = "int3472-discrete",
-               .acpi_match_table = int3472_device_id,
-       },
-       .probe = skl_int3472_discrete_probe,
-       .remove = skl_int3472_discrete_remove,
-};
-
-static struct i2c_driver int3472_tps68470 = {
-       .driver = {
-               .name = "int3472-tps68470",
-               .acpi_match_table = int3472_device_id,
-       },
-       .probe_new = skl_int3472_tps68470_probe,
-};
-
-static int skl_int3472_init(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&int3472_discrete);
-       if (ret)
-               return ret;
-
-       ret = i2c_register_driver(THIS_MODULE, &int3472_tps68470);
-       if (ret)
-               platform_driver_unregister(&int3472_discrete);
-
-       return ret;
-}
-module_init(skl_int3472_init);
-
-static void skl_int3472_exit(void)
-{
-       platform_driver_unregister(&int3472_discrete);
-       i2c_del_driver(&int3472_tps68470);
-}
-module_exit(skl_int3472_exit);
-
-MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Device Driver");
-MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h b/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h
deleted file mode 100644 (file)
index 714fde7..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Author: Dan Scally <djrscally@gmail.com> */
-
-#ifndef _INTEL_SKL_INT3472_H
-#define _INTEL_SKL_INT3472_H
-
-#include <linux/clk-provider.h>
-#include <linux/gpio/machine.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/types.h>
-
-/* FIXME drop this once the I2C_DEV_NAME_FORMAT macro has been added to include/linux/i2c.h */
-#ifndef I2C_DEV_NAME_FORMAT
-#define I2C_DEV_NAME_FORMAT                                    "i2c-%s"
-#endif
-
-/* PMIC GPIO Types */
-#define INT3472_GPIO_TYPE_RESET                                        0x00
-#define INT3472_GPIO_TYPE_POWERDOWN                            0x01
-#define INT3472_GPIO_TYPE_POWER_ENABLE                         0x0b
-#define INT3472_GPIO_TYPE_CLK_ENABLE                           0x0c
-#define INT3472_GPIO_TYPE_PRIVACY_LED                          0x0d
-
-#define INT3472_PDEV_MAX_NAME_LEN                              23
-#define INT3472_MAX_SENSOR_GPIOS                               3
-
-#define GPIO_REGULATOR_NAME_LENGTH                             21
-#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH                      9
-
-#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET                      86
-
-#define INT3472_REGULATOR(_name, _supply, _ops)                        \
-       (const struct regulator_desc) {                         \
-               .name = _name,                                  \
-               .supply_name = _supply,                         \
-               .type = REGULATOR_VOLTAGE,                      \
-               .ops = _ops,                                    \
-               .owner = THIS_MODULE,                           \
-       }
-
-#define to_int3472_clk(hw)                                     \
-       container_of(hw, struct int3472_gpio_clock, clk_hw)
-
-#define to_int3472_device(clk)                                 \
-       container_of(clk, struct int3472_discrete_device, clock)
-
-struct acpi_device;
-struct i2c_client;
-struct platform_device;
-
-struct int3472_cldb {
-       u8 version;
-       /*
-        * control logic type
-        * 0: UNKNOWN
-        * 1: DISCRETE(CRD-D)
-        * 2: PMIC TPS68470
-        * 3: PMIC uP6641
-        */
-       u8 control_logic_type;
-       u8 control_logic_id;
-       u8 sensor_card_sku;
-       u8 reserved[28];
-};
-
-struct int3472_gpio_function_remap {
-       const char *documented;
-       const char *actual;
-};
-
-struct int3472_sensor_config {
-       const char *sensor_module_name;
-       struct regulator_consumer_supply supply_map;
-       const struct int3472_gpio_function_remap *function_maps;
-};
-
-struct int3472_discrete_device {
-       struct acpi_device *adev;
-       struct device *dev;
-       struct acpi_device *sensor;
-       const char *sensor_name;
-
-       const struct int3472_sensor_config *sensor_config;
-
-       struct int3472_gpio_regulator {
-               char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
-               char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
-               struct gpio_desc *gpio;
-               struct regulator_dev *rdev;
-               struct regulator_desc rdesc;
-       } regulator;
-
-       struct int3472_gpio_clock {
-               struct clk *clk;
-               struct clk_hw clk_hw;
-               struct clk_lookup *cl;
-               struct gpio_desc *ena_gpio;
-               struct gpio_desc *led_gpio;
-               u32 frequency;
-       } clock;
-
-       unsigned int ngpios; /* how many GPIOs have we seen */
-       unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
-       struct gpiod_lookup_table gpios;
-};
-
-int skl_int3472_discrete_probe(struct platform_device *pdev);
-int skl_int3472_discrete_remove(struct platform_device *pdev);
-int skl_int3472_tps68470_probe(struct i2c_client *client);
-union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
-                                              char *id);
-int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
-
-int skl_int3472_register_clock(struct int3472_discrete_device *int3472);
-void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);
-
-int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
-                                  struct acpi_resource_gpio *agpio);
-void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);
-
-#endif
diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c
deleted file mode 100644 (file)
index e59d79c..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Author: Dan Scally <djrscally@gmail.com> */
-
-#include <linux/acpi.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
-#include <linux/i2c.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/overflow.h>
-#include <linux/platform_device.h>
-#include <linux/uuid.h>
-
-#include "intel_skl_int3472_common.h"
-
-/*
- * 79234640-9e10-4fea-a5c1-b5aa8b19756f
- * This _DSM GUID returns information about the GPIO lines mapped to a
- * discrete INT3472 device. Function number 1 returns a count of the GPIO
- * lines that are mapped. Subsequent functions return 32 bit ints encoding
- * information about the GPIO line, including its purpose.
- */
-static const guid_t int3472_gpio_guid =
-       GUID_INIT(0x79234640, 0x9e10, 0x4fea,
-                 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
-
-/*
- * 822ace8f-2814-4174-a56b-5f029fe079ee
- * This _DSM GUID returns a string from the sensor device, which acts as a
- * module identifier.
- */
-static const guid_t cio2_sensor_module_guid =
-       GUID_INIT(0x822ace8f, 0x2814, 0x4174,
-                 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
-
-/*
- * Here follows platform specific mapping information that we can pass to
- * the functions mapping resources to the sensors. Where the sensors have
- * a power enable pin defined in DSDT we need to provide a supply name so
- * the sensor drivers can find the regulator. The device name will be derived
- * from the sensor's ACPI device within the code. Optionally, we can provide a
- * NULL terminated array of function name mappings to deal with any platform
- * specific deviations from the documented behaviour of GPIOs.
- *
- * Map a GPIO function name to NULL to prevent the driver from mapping that
- * GPIO at all.
- */
-
-static const struct int3472_gpio_function_remap ov2680_gpio_function_remaps[] = {
-       { "reset", NULL },
-       { "powerdown", "reset" },
-       { }
-};
-
-static const struct int3472_sensor_config int3472_sensor_configs[] = {
-       /* Lenovo Miix 510-12ISK - OV2680, Front */
-       { "GNDF140809R", { 0 }, ov2680_gpio_function_remaps },
-       /* Lenovo Miix 510-12ISK - OV5648, Rear */
-       { "GEFF150023R", REGULATOR_SUPPLY("avdd", NULL), NULL },
-       /* Surface Go 1&2 - OV5693, Front */
-       { "YHCU", REGULATOR_SUPPLY("avdd", NULL), NULL },
-};
-
-static const struct int3472_sensor_config *
-skl_int3472_get_sensor_module_config(struct int3472_discrete_device *int3472)
-{
-       union acpi_object *obj;
-       unsigned int i;
-
-       obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
-                                     &cio2_sensor_module_guid, 0x00,
-                                     0x01, NULL, ACPI_TYPE_STRING);
-
-       if (!obj) {
-               dev_err(int3472->dev,
-                       "Failed to get sensor module string from _DSM\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       if (obj->string.type != ACPI_TYPE_STRING) {
-               dev_err(int3472->dev,
-                       "Sensor _DSM returned a non-string value\n");
-
-               ACPI_FREE(obj);
-               return ERR_PTR(-EINVAL);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(int3472_sensor_configs); i++) {
-               if (!strcmp(int3472_sensor_configs[i].sensor_module_name,
-                           obj->string.pointer))
-                       break;
-       }
-
-       ACPI_FREE(obj);
-
-       if (i >= ARRAY_SIZE(int3472_sensor_configs))
-               return ERR_PTR(-EINVAL);
-
-       return &int3472_sensor_configs[i];
-}
-
-static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
-                                         struct acpi_resource_gpio *agpio,
-                                         const char *func, u32 polarity)
-{
-       const struct int3472_sensor_config *sensor_config;
-       char *path = agpio->resource_source.string_ptr;
-       struct gpiod_lookup *table_entry;
-       struct acpi_device *adev;
-       acpi_handle handle;
-       acpi_status status;
-       int ret;
-
-       if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
-               dev_warn(int3472->dev, "Too many GPIOs mapped\n");
-               return -EINVAL;
-       }
-
-       sensor_config = int3472->sensor_config;
-       if (!IS_ERR(sensor_config) && sensor_config->function_maps) {
-               const struct int3472_gpio_function_remap *remap;
-
-               for (remap = sensor_config->function_maps; remap->documented; remap++) {
-                       if (!strcmp(func, remap->documented)) {
-                               func = remap->actual;
-                               break;
-                       }
-               }
-       }
-
-       /* Functions mapped to NULL should not be mapped to the sensor */
-       if (!func)
-               return 0;
-
-       status = acpi_get_handle(NULL, path, &handle);
-       if (ACPI_FAILURE(status))
-               return -EINVAL;
-
-       ret = acpi_bus_get_device(handle, &adev);
-       if (ret)
-               return -ENODEV;
-
-       table_entry = &int3472->gpios.table[int3472->n_sensor_gpios];
-       table_entry->key = acpi_dev_name(adev);
-       table_entry->chip_hwnum = agpio->pin_table[0];
-       table_entry->con_id = func;
-       table_entry->idx = 0;
-       table_entry->flags = polarity;
-
-       int3472->n_sensor_gpios++;
-
-       return 0;
-}
-
-static int skl_int3472_map_gpio_to_clk(struct int3472_discrete_device *int3472,
-                                      struct acpi_resource_gpio *agpio, u8 type)
-{
-       char *path = agpio->resource_source.string_ptr;
-       u16 pin = agpio->pin_table[0];
-       struct gpio_desc *gpio;
-
-       switch (type) {
-       case INT3472_GPIO_TYPE_CLK_ENABLE:
-               gpio = acpi_get_and_request_gpiod(path, pin, "int3472,clk-enable");
-               if (IS_ERR(gpio))
-                       return (PTR_ERR(gpio));
-
-               int3472->clock.ena_gpio = gpio;
-               break;
-       case INT3472_GPIO_TYPE_PRIVACY_LED:
-               gpio = acpi_get_and_request_gpiod(path, pin, "int3472,privacy-led");
-               if (IS_ERR(gpio))
-                       return (PTR_ERR(gpio));
-
-               int3472->clock.led_gpio = gpio;
-               break;
-       default:
-               dev_err(int3472->dev, "Invalid GPIO type 0x%02x for clock\n", type);
-               break;
-       }
-
-       return 0;
-}
-
-/**
- * skl_int3472_handle_gpio_resources: Map PMIC resources to consuming sensor
- * @ares: A pointer to a &struct acpi_resource
- * @data: A pointer to a &struct int3472_discrete_device
- *
- * This function handles GPIO resources that are against an INT3472
- * ACPI device, by checking the value of the corresponding _DSM entry.
- * This will return a 32bit int, where the lowest byte represents the
- * function of the GPIO pin:
- *
- * 0x00 Reset
- * 0x01 Power down
- * 0x0b Power enable
- * 0x0c Clock enable
- * 0x0d Privacy LED
- *
- * There are some known platform specific quirks where that does not quite
- * hold up; for example where a pin with type 0x01 (Power down) is mapped to
- * a sensor pin that performs a reset function or entries in _CRS and _DSM that
- * do not actually correspond to a physical connection. These will be handled
- * by the mapping sub-functions.
- *
- * GPIOs will either be mapped directly to the sensor device or else used
- * to create clocks and regulators via the usual frameworks.
- *
- * Return:
- * * 1         - To continue the loop
- * * 0         - When all resources found are handled properly.
- * * -EINVAL   - If the resource is not a GPIO IO resource
- * * -ENODEV   - If the resource has no corresponding _DSM entry
- * * -Other    - Errors propagated from one of the sub-functions.
- */
-static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
-                                            void *data)
-{
-       struct int3472_discrete_device *int3472 = data;
-       struct acpi_resource_gpio *agpio;
-       union acpi_object *obj;
-       const char *err_msg;
-       int ret;
-       u8 type;
-
-       if (!acpi_gpio_get_io_resource(ares, &agpio))
-               return 1;
-
-       /*
-        * ngpios + 2 because the index of this _DSM function is 1-based and
-        * the first function is just a count.
-        */
-       obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
-                                     &int3472_gpio_guid, 0x00,
-                                     int3472->ngpios + 2,
-                                     NULL, ACPI_TYPE_INTEGER);
-
-       if (!obj) {
-               dev_warn(int3472->dev, "No _DSM entry for GPIO pin %u\n",
-                        agpio->pin_table[0]);
-               return 1;
-       }
-
-       type = obj->integer.value & 0xff;
-
-       switch (type) {
-       case INT3472_GPIO_TYPE_RESET:
-               ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "reset",
-                                                    GPIO_ACTIVE_LOW);
-               if (ret)
-                       err_msg = "Failed to map reset pin to sensor\n";
-
-               break;
-       case INT3472_GPIO_TYPE_POWERDOWN:
-               ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, "powerdown",
-                                                    GPIO_ACTIVE_LOW);
-               if (ret)
-                       err_msg = "Failed to map powerdown pin to sensor\n";
-
-               break;
-       case INT3472_GPIO_TYPE_CLK_ENABLE:
-       case INT3472_GPIO_TYPE_PRIVACY_LED:
-               ret = skl_int3472_map_gpio_to_clk(int3472, agpio, type);
-               if (ret)
-                       err_msg = "Failed to map GPIO to clock\n";
-
-               break;
-       case INT3472_GPIO_TYPE_POWER_ENABLE:
-               ret = skl_int3472_register_regulator(int3472, agpio);
-               if (ret)
-                       err_msg = "Failed to map regulator to sensor\n";
-
-               break;
-       default:
-               dev_warn(int3472->dev,
-                        "GPIO type 0x%02x unknown; the sensor may not work\n",
-                        type);
-               ret = 1;
-               break;
-       }
-
-       int3472->ngpios++;
-       ACPI_FREE(obj);
-
-       if (ret < 0)
-               return dev_err_probe(int3472->dev, ret, err_msg);
-
-       return ret;
-}
-
-static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472)
-{
-       LIST_HEAD(resource_list);
-       int ret;
-
-       /*
-        * No error check, because not having a sensor config is not necessarily
-        * a failure mode.
-        */
-       int3472->sensor_config = skl_int3472_get_sensor_module_config(int3472);
-
-       ret = acpi_dev_get_resources(int3472->adev, &resource_list,
-                                    skl_int3472_handle_gpio_resources,
-                                    int3472);
-       if (ret < 0)
-               return ret;
-
-       acpi_dev_free_resource_list(&resource_list);
-
-       /*
-        * If we find no clock enable GPIO pin then the privacy LED won't work.
-        * We've never seen that situation, but it's possible. Warn the user so
-        * it's clear what's happened.
-        */
-       if (int3472->clock.ena_gpio) {
-               ret = skl_int3472_register_clock(int3472);
-               if (ret)
-                       return ret;
-       } else {
-               if (int3472->clock.led_gpio)
-                       dev_warn(int3472->dev,
-                                "No clk GPIO. The privacy LED won't work\n");
-       }
-
-       int3472->gpios.dev_id = int3472->sensor_name;
-       gpiod_add_lookup_table(&int3472->gpios);
-
-       return 0;
-}
-
-int skl_int3472_discrete_probe(struct platform_device *pdev)
-{
-       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
-       struct int3472_discrete_device *int3472;
-       struct int3472_cldb cldb;
-       int ret;
-
-       ret = skl_int3472_fill_cldb(adev, &cldb);
-       if (ret) {
-               dev_err(&pdev->dev, "Couldn't fill CLDB structure\n");
-               return ret;
-       }
-
-       if (cldb.control_logic_type != 1) {
-               dev_err(&pdev->dev, "Unsupported control logic type %u\n",
-                       cldb.control_logic_type);
-               return -EINVAL;
-       }
-
-       /* Max num GPIOs we've seen plus a terminator */
-       int3472 = devm_kzalloc(&pdev->dev, struct_size(int3472, gpios.table,
-                              INT3472_MAX_SENSOR_GPIOS + 1), GFP_KERNEL);
-       if (!int3472)
-               return -ENOMEM;
-
-       int3472->adev = adev;
-       int3472->dev = &pdev->dev;
-       platform_set_drvdata(pdev, int3472);
-
-       int3472->sensor = acpi_dev_get_first_consumer_dev(adev);
-       if (!int3472->sensor) {
-               dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n");
-               return -ENODEV;
-       }
-
-       int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL,
-                                             I2C_DEV_NAME_FORMAT,
-                                             acpi_dev_name(int3472->sensor));
-       if (!int3472->sensor_name) {
-               ret = -ENOMEM;
-               goto err_put_sensor;
-       }
-
-       /*
-        * Initialising this list means we can call gpiod_remove_lookup_table()
-        * in failure paths without issue.
-        */
-       INIT_LIST_HEAD(&int3472->gpios.list);
-
-       ret = skl_int3472_parse_crs(int3472);
-       if (ret) {
-               skl_int3472_discrete_remove(pdev);
-               return ret;
-       }
-
-       return 0;
-
-err_put_sensor:
-       acpi_dev_put(int3472->sensor);
-
-       return ret;
-}
-
-int skl_int3472_discrete_remove(struct platform_device *pdev)
-{
-       struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev);
-
-       gpiod_remove_lookup_table(&int3472->gpios);
-
-       if (int3472->clock.cl)
-               skl_int3472_unregister_clock(int3472);
-
-       gpiod_put(int3472->clock.ena_gpio);
-       gpiod_put(int3472->clock.led_gpio);
-
-       skl_int3472_unregister_regulator(int3472);
-
-       return 0;
-}
diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c
deleted file mode 100644 (file)
index c05b4cf..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Author: Dan Scally <djrscally@gmail.com> */
-
-#include <linux/i2c.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tps68470.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include "intel_skl_int3472_common.h"
-
-#define DESIGNED_FOR_CHROMEOS          1
-#define DESIGNED_FOR_WINDOWS           2
-
-static const struct mfd_cell tps68470_cros[] = {
-       { .name = "tps68470-gpio" },
-       { .name = "tps68470_pmic_opregion" },
-};
-
-static const struct mfd_cell tps68470_win[] = {
-       { .name = "tps68470-gpio" },
-       { .name = "tps68470-clk" },
-       { .name = "tps68470-regulator" },
-};
-
-static const struct regmap_config tps68470_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-       .max_register = TPS68470_REG_MAX,
-};
-
-static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
-{
-       unsigned int version;
-       int ret;
-
-       /* Force software reset */
-       ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK);
-       if (ret)
-               return ret;
-
-       ret = regmap_read(regmap, TPS68470_REG_REVID, &version);
-       if (ret) {
-               dev_err(dev, "Failed to read revision register: %d\n", ret);
-               return ret;
-       }
-
-       dev_info(dev, "TPS68470 REVID: 0x%02x\n", version);
-
-       return 0;
-}
-
-/** skl_int3472_tps68470_calc_type: Check what platform a device is designed for
- * @adev: A pointer to a &struct acpi_device
- *
- * Check CLDB buffer against the PMIC's adev. If present, then we check
- * the value of control_logic_type field and follow one of the
- * following scenarios:
- *
- *     1. No CLDB - likely ACPI tables designed for ChromeOS. We
- *     create platform devices for the GPIOs and OpRegion drivers.
- *
- *     2. CLDB, with control_logic_type = 2 - probably ACPI tables
- *     made for Windows 2-in-1 platforms. Register pdevs for GPIO,
- *     Clock and Regulator drivers to bind to.
- *
- *     3. Any other value in control_logic_type, we should never have
- *     gotten to this point; fail probe and return.
- *
- * Return:
- * * 1         Device intended for ChromeOS
- * * 2         Device intended for Windows
- * * -EINVAL   Where @adev has an object named CLDB but it does not conform to
- *             our expectations
- */
-static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
-{
-       struct int3472_cldb cldb = { 0 };
-       int ret;
-
-       /*
-        * A CLDB buffer that exists, but which does not match our expectations
-        * should trigger an error so we don't blindly continue.
-        */
-       ret = skl_int3472_fill_cldb(adev, &cldb);
-       if (ret && ret != -ENODEV)
-               return ret;
-
-       if (ret)
-               return DESIGNED_FOR_CHROMEOS;
-
-       if (cldb.control_logic_type != 2)
-               return -EINVAL;
-
-       return DESIGNED_FOR_WINDOWS;
-}
-
-int skl_int3472_tps68470_probe(struct i2c_client *client)
-{
-       struct acpi_device *adev = ACPI_COMPANION(&client->dev);
-       struct regmap *regmap;
-       int device_type;
-       int ret;
-
-       regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
-       if (IS_ERR(regmap)) {
-               dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
-               return PTR_ERR(regmap);
-       }
-
-       i2c_set_clientdata(client, regmap);
-
-       ret = tps68470_chip_init(&client->dev, regmap);
-       if (ret < 0) {
-               dev_err(&client->dev, "TPS68470 init error %d\n", ret);
-               return ret;
-       }
-
-       device_type = skl_int3472_tps68470_calc_type(adev);
-       switch (device_type) {
-       case DESIGNED_FOR_WINDOWS:
-               ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
-                                          tps68470_win, ARRAY_SIZE(tps68470_win),
-                                          NULL, 0, NULL);
-               break;
-       case DESIGNED_FOR_CHROMEOS:
-               ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
-                                          tps68470_cros, ARRAY_SIZE(tps68470_cros),
-                                          NULL, 0, NULL);
-               break;
-       default:
-               dev_err(&client->dev, "Failed to add MFD devices\n");
-               return device_type;
-       }
-
-       return ret;
-}
diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c
new file mode 100644 (file)
index 0000000..22f61b4
--- /dev/null
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps68470.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/tps68470.h>
+#include <linux/regmap.h>
+#include <linux/string.h>
+
+#include "common.h"
+#include "tps68470.h"
+
+#define DESIGNED_FOR_CHROMEOS          1
+#define DESIGNED_FOR_WINDOWS           2
+
+#define TPS68470_WIN_MFD_CELL_COUNT    3
+
+static const struct mfd_cell tps68470_cros[] = {
+       { .name = "tps68470-gpio" },
+       { .name = "tps68470_pmic_opregion" },
+};
+
+static const struct regmap_config tps68470_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TPS68470_REG_MAX,
+};
+
+static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
+{
+       unsigned int version;
+       int ret;
+
+       /* Force software reset */
+       ret = regmap_write(regmap, TPS68470_REG_RESET, TPS68470_REG_RESET_MASK);
+       if (ret)
+               return ret;
+
+       ret = regmap_read(regmap, TPS68470_REG_REVID, &version);
+       if (ret) {
+               dev_err(dev, "Failed to read revision register: %d\n", ret);
+               return ret;
+       }
+
+       dev_info(dev, "TPS68470 REVID: 0x%02x\n", version);
+
+       return 0;
+}
+
+/** skl_int3472_tps68470_calc_type: Check what platform a device is designed for
+ * @adev: A pointer to a &struct acpi_device
+ *
+ * Check CLDB buffer against the PMIC's adev. If present, then we check
+ * the value of control_logic_type field and follow one of the
+ * following scenarios:
+ *
+ *     1. No CLDB - likely ACPI tables designed for ChromeOS. We
+ *     create platform devices for the GPIOs and OpRegion drivers.
+ *
+ *     2. CLDB, with control_logic_type = 2 - probably ACPI tables
+ *     made for Windows 2-in-1 platforms. Register pdevs for GPIO,
+ *     Clock and Regulator drivers to bind to.
+ *
+ *     3. Any other value in control_logic_type, we should never have
+ *     gotten to this point; fail probe and return.
+ *
+ * Return:
+ * * 1         Device intended for ChromeOS
+ * * 2         Device intended for Windows
+ * * -EINVAL   Where @adev has an object named CLDB but it does not conform to
+ *             our expectations
+ */
+static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
+{
+       struct int3472_cldb cldb = { 0 };
+       int ret;
+
+       /*
+        * A CLDB buffer that exists, but which does not match our expectations
+        * should trigger an error so we don't blindly continue.
+        */
+       ret = skl_int3472_fill_cldb(adev, &cldb);
+       if (ret && ret != -ENODEV)
+               return ret;
+
+       if (ret)
+               return DESIGNED_FOR_CHROMEOS;
+
+       if (cldb.control_logic_type != 2)
+               return -EINVAL;
+
+       return DESIGNED_FOR_WINDOWS;
+}
+
+static int skl_int3472_tps68470_probe(struct i2c_client *client)
+{
+       struct acpi_device *adev = ACPI_COMPANION(&client->dev);
+       const struct int3472_tps68470_board_data *board_data;
+       struct tps68470_clk_platform_data clk_pdata = {};
+       struct mfd_cell *cells;
+       struct regmap *regmap;
+       int device_type;
+       int ret;
+
+       ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
+                                                  &clk_pdata.consumer_dev_name);
+       if (ret)
+               return ret;
+
+       regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       i2c_set_clientdata(client, regmap);
+
+       ret = tps68470_chip_init(&client->dev, regmap);
+       if (ret < 0) {
+               dev_err(&client->dev, "TPS68470 init error %d\n", ret);
+               return ret;
+       }
+
+       device_type = skl_int3472_tps68470_calc_type(adev);
+       switch (device_type) {
+       case DESIGNED_FOR_WINDOWS:
+               board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
+               if (!board_data)
+                       return dev_err_probe(&client->dev, -ENODEV, "No board-data found for this model\n");
+
+               cells = kcalloc(TPS68470_WIN_MFD_CELL_COUNT, sizeof(*cells), GFP_KERNEL);
+               if (!cells)
+                       return -ENOMEM;
+
+               /*
+                * The order of the cells matters here! The clk must be first
+                * because the regulator depends on it. The gpios must be last,
+                * acpi_gpiochip_add() calls acpi_dev_clear_dependencies() and
+                * the clk + regulators must be ready when this happens.
+                */
+               cells[0].name = "tps68470-clk";
+               cells[0].platform_data = &clk_pdata;
+               cells[0].pdata_size = sizeof(clk_pdata);
+               cells[1].name = "tps68470-regulator";
+               cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
+               cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
+               cells[2].name = "tps68470-gpio";
+
+               gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
+
+               ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+                                          cells, TPS68470_WIN_MFD_CELL_COUNT,
+                                          NULL, 0, NULL);
+               kfree(cells);
+
+               if (ret)
+                       gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+
+               break;
+       case DESIGNED_FOR_CHROMEOS:
+               ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+                                          tps68470_cros, ARRAY_SIZE(tps68470_cros),
+                                          NULL, 0, NULL);
+               break;
+       default:
+               dev_err(&client->dev, "Failed to add MFD devices\n");
+               return device_type;
+       }
+
+       /*
+        * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add()
+        * for the GPIO cell already does this.
+        */
+
+       return ret;
+}
+
+static int skl_int3472_tps68470_remove(struct i2c_client *client)
+{
+       const struct int3472_tps68470_board_data *board_data;
+
+       board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
+       if (board_data)
+               gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+
+       return 0;
+}
+
+static const struct acpi_device_id int3472_device_id[] = {
+       { "INT3472", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, int3472_device_id);
+
+static struct i2c_driver int3472_tps68470 = {
+       .driver = {
+               .name = "int3472-tps68470",
+               .acpi_match_table = int3472_device_id,
+       },
+       .probe_new = skl_int3472_tps68470_probe,
+       .remove = skl_int3472_tps68470_remove,
+};
+module_i2c_driver(int3472_tps68470);
+
+MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver");
+MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator");
diff --git a/drivers/platform/x86/intel/int3472/tps68470.h b/drivers/platform/x86/intel/int3472/tps68470.h
new file mode 100644 (file)
index 0000000..cfd33eb
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TI TPS68470 PMIC platform data definition.
+ *
+ * Copyright (c) 2021 Red Hat Inc.
+ *
+ * Red Hat authors:
+ * Hans de Goede <hdegoede@redhat.com>
+ */
+
+#ifndef _INTEL_SKL_INT3472_TPS68470_H
+#define _INTEL_SKL_INT3472_TPS68470_H
+
+struct gpiod_lookup_table;
+struct tps68470_regulator_platform_data;
+
+struct int3472_tps68470_board_data {
+       const char *dev_name;
+       struct gpiod_lookup_table *tps68470_gpio_lookup_table;
+       const struct tps68470_regulator_platform_data *tps68470_regulator_pdata;
+};
+
+const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name);
+
+#endif
diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c
new file mode 100644 (file)
index 0000000..faa5570
--- /dev/null
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI TPS68470 PMIC platform data definition.
+ *
+ * Copyright (c) 2021 Dan Scally <djrscally@gmail.com>
+ * Copyright (c) 2021 Red Hat Inc.
+ *
+ * Red Hat authors:
+ * Hans de Goede <hdegoede@redhat.com>
+ */
+
+#include <linux/dmi.h>
+#include <linux/gpio/machine.h>
+#include <linux/platform_data/tps68470.h>
+#include <linux/regulator/machine.h>
+#include "tps68470.h"
+
+static struct regulator_consumer_supply int347a_core_consumer_supplies[] = {
+       REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"),
+};
+
+static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = {
+       REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"),
+};
+
+static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = {
+       REGULATOR_SUPPLY("vdd", "i2c-INT347A:00-VCM"),
+};
+
+static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = {
+       REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"),
+       REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"),
+};
+
+static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = {
+       .constraints = {
+               .min_uV = 1200000,
+               .max_uV = 1200000,
+               .apply_uV = true,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies),
+       .consumer_supplies = int347a_core_consumer_supplies,
+};
+
+static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = {
+       .constraints = {
+               .min_uV = 2815200,
+               .max_uV = 2815200,
+               .apply_uV = true,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies),
+       .consumer_supplies = int347a_ana_consumer_supplies,
+};
+
+static const struct regulator_init_data surface_go_tps68470_vcm_reg_init_data = {
+       .constraints = {
+               .min_uV = 2815200,
+               .max_uV = 2815200,
+               .apply_uV = true,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_vcm_consumer_supplies),
+       .consumer_supplies = int347a_vcm_consumer_supplies,
+};
+
+/* Ensure the always-on VIO regulator has the same voltage as VSIO */
+static const struct regulator_init_data surface_go_tps68470_vio_reg_init_data = {
+       .constraints = {
+               .min_uV = 1800600,
+               .max_uV = 1800600,
+               .apply_uV = true,
+               .always_on = true,
+       },
+};
+
+static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = {
+       .constraints = {
+               .min_uV = 1800600,
+               .max_uV = 1800600,
+               .apply_uV = true,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies),
+       .consumer_supplies = int347a_vsio_consumer_supplies,
+};
+
+static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = {
+       .reg_init_data = {
+               [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data,
+               [TPS68470_ANA]  = &surface_go_tps68470_ana_reg_init_data,
+               [TPS68470_VCM]  = &surface_go_tps68470_vcm_reg_init_data,
+               [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data,
+               [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data,
+       },
+};
+
+static struct gpiod_lookup_table surface_go_tps68470_gpios = {
+       .dev_id = "i2c-INT347A:00",
+       .table = {
+               GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW)
+       }
+};
+
+static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = {
+       .dev_name = "i2c-INT3472:05",
+       .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
+       .tps68470_regulator_pdata = &surface_go_tps68470_pdata,
+};
+
+static const struct dmi_system_id int3472_tps68470_board_data_table[] = {
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
+               },
+               .driver_data = (void *)&surface_go_tps68470_board_data,
+       },
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"),
+               },
+               .driver_data = (void *)&surface_go_tps68470_board_data,
+       },
+       { }
+};
+
+const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name)
+{
+       const struct int3472_tps68470_board_data *board_data;
+       const struct dmi_system_id *match;
+
+       for (match = dmi_first_match(int3472_tps68470_board_data_table);
+            match;
+            match = dmi_first_match(match + 1)) {
+               board_data = match->driver_data;
+               if (strcmp(board_data->dev_name, dev_name) == 0)
+                       return board_data;
+       }
+
+       return NULL;
+}
index 480f920..2f93ecf 100644 (file)
@@ -202,7 +202,8 @@ struct acpi_device_flags {
        u32 coherent_dma:1;
        u32 cca_seen:1;
        u32 enumeration_by_parent:1;
-       u32 reserved:19;
+       u32 honor_deps:1;
+       u32 reserved:18;
 };
 
 /* File System */
@@ -285,6 +286,7 @@ struct acpi_dep_data {
        struct list_head node;
        acpi_handle supplier;
        acpi_handle consumer;
+       bool honor_dep;
 };
 
 /* Performance Management */
@@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
 bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
 
 void acpi_dev_clear_dependencies(struct acpi_device *supplier);
+bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
 struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
 struct acpi_device *
 acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
diff --git a/include/dt-bindings/clock/microchip,lan966x.h b/include/dt-bindings/clock/microchip,lan966x.h
new file mode 100644 (file)
index 0000000..6f9d43d
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021 Microchip Inc.
+ *
+ * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_LAN966X_H
+#define _DT_BINDINGS_CLK_LAN966X_H
+
+#define GCK_ID_QSPI0           0
+#define GCK_ID_QSPI1           1
+#define GCK_ID_QSPI2           2
+#define GCK_ID_SDMMC0          3
+#define GCK_ID_PI              4
+#define GCK_ID_MCAN0           5
+#define GCK_ID_MCAN1           6
+#define GCK_ID_FLEXCOM0                7
+#define GCK_ID_FLEXCOM1                8
+#define GCK_ID_FLEXCOM2                9
+#define GCK_ID_FLEXCOM3                10
+#define GCK_ID_FLEXCOM4                11
+#define GCK_ID_TIMER           12
+#define GCK_ID_USB_REFCLK      13
+
+/* Gate clocks */
+#define GCK_GATE_UHPHS         14
+#define GCK_GATE_UDPHS         15
+#define GCK_GATE_MCRAMC                16
+#define GCK_GATE_HMATRIX       17
+
+#define N_CLOCKS               18
+
+#endif
diff --git a/include/dt-bindings/clock/r8a779f0-cpg-mssr.h b/include/dt-bindings/clock/r8a779f0-cpg-mssr.h
new file mode 100644 (file)
index 0000000..f2ae1c6
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: (GPL-2.0 or MIT) */
+/*
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a779f0 CPG Core Clocks */
+
+#define R8A779F0_CLK_ZX                        0
+#define R8A779F0_CLK_ZS                        1
+#define R8A779F0_CLK_ZT                        2
+#define R8A779F0_CLK_ZTR               3
+#define R8A779F0_CLK_S0D2              4
+#define R8A779F0_CLK_S0D3              5
+#define R8A779F0_CLK_S0D4              6
+#define R8A779F0_CLK_S0D2_MM           7
+#define R8A779F0_CLK_S0D3_MM           8
+#define R8A779F0_CLK_S0D4_MM           9
+#define R8A779F0_CLK_S0D2_RT           10
+#define R8A779F0_CLK_S0D3_RT           11
+#define R8A779F0_CLK_S0D4_RT           12
+#define R8A779F0_CLK_S0D6_RT           13
+#define R8A779F0_CLK_S0D3_PER          14
+#define R8A779F0_CLK_S0D6_PER          15
+#define R8A779F0_CLK_S0D12_PER         16
+#define R8A779F0_CLK_S0D24_PER         17
+#define R8A779F0_CLK_S0D2_HSC          18
+#define R8A779F0_CLK_S0D3_HSC          19
+#define R8A779F0_CLK_S0D4_HSC          20
+#define R8A779F0_CLK_S0D6_HSC          21
+#define R8A779F0_CLK_S0D12_HSC         22
+#define R8A779F0_CLK_S0D2_CC           23
+#define R8A779F0_CLK_CL                        24
+#define R8A779F0_CLK_CL16M             25
+#define R8A779F0_CLK_CL16M_MM          26
+#define R8A779F0_CLK_CL16M_RT          27
+#define R8A779F0_CLK_CL16M_PER         28
+#define R8A779F0_CLK_CL16M_HSC         29
+#define R8A779F0_CLK_Z0                        30
+#define R8A779F0_CLK_Z1                        31
+#define R8A779F0_CLK_ZB3               32
+#define R8A779F0_CLK_ZB3D2             33
+#define R8A779F0_CLK_ZB3D4             34
+#define R8A779F0_CLK_SD0H              35
+#define R8A779F0_CLK_SD0               36
+#define R8A779F0_CLK_RPC               37
+#define R8A779F0_CLK_RPCD2             38
+#define R8A779F0_CLK_MSO               39
+#define R8A779F0_CLK_SASYNCRT          40
+#define R8A779F0_CLK_SASYNCPERD1       41
+#define R8A779F0_CLK_SASYNCPERD2       42
+#define R8A779F0_CLK_SASYNCPERD4       43
+#define R8A779F0_CLK_DBGSOC_HSC                44
+#define R8A779F0_CLK_RSW2              45
+#define R8A779F0_CLK_OSC               46
+#define R8A779F0_CLK_ZR                        47
+#define R8A779F0_CLK_CPEX              48
+#define R8A779F0_CLK_CBFUSA            49
+#define R8A779F0_CLK_R                 50
+
+#endif /* __DT_BINDINGS_CLOCK_R8A779F0_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/power/r8a779f0-sysc.h b/include/dt-bindings/power/r8a779f0-sysc.h
new file mode 100644 (file)
index 0000000..0ec8ad7
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: (GPL-2.0 or MIT) */
+/*
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A779F0_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A779F0_SYSC_H__
+
+/*
+ * These power domain indices match the Power Domain Register Numbers (PDR)
+ */
+
+#define R8A779F0_PD_A1E0D0C0           0
+#define R8A779F0_PD_A1E0D0C1           1
+#define R8A779F0_PD_A1E0D1C0           2
+#define R8A779F0_PD_A1E0D1C1           3
+#define R8A779F0_PD_A1E1D0C0           4
+#define R8A779F0_PD_A1E1D0C1           5
+#define R8A779F0_PD_A1E1D1C0           6
+#define R8A779F0_PD_A1E1D1C1           7
+#define R8A779F0_PD_A2E0D0             16
+#define R8A779F0_PD_A2E0D1             17
+#define R8A779F0_PD_A2E1D0             18
+#define R8A779F0_PD_A2E1D1             19
+#define R8A779F0_PD_A3E0               20
+#define R8A779F0_PD_A3E1               21
+
+/* Always-on power area */
+#define R8A779F0_PD_ALWAYS_ON          64
+
+#endif /* __DT_BINDINGS_POWER_R8A779A0_SYSC_H__*/
index f59c875..2faa6f7 100644 (file)
@@ -490,6 +490,13 @@ struct clk_hw *__clk_hw_register_gate(struct device *dev,
                unsigned long flags,
                void __iomem *reg, u8 bit_idx,
                u8 clk_gate_flags, spinlock_t *lock);
+struct clk_hw *__devm_clk_hw_register_gate(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data,
+               unsigned long flags,
+               void __iomem *reg, u8 bit_idx,
+               u8 clk_gate_flags, spinlock_t *lock);
 struct clk *clk_register_gate(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 bit_idx,
@@ -544,6 +551,22 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
        __clk_hw_register_gate((dev), NULL, (name), NULL, NULL, (parent_data), \
                               (flags), (reg), (bit_idx),                     \
                               (clk_gate_flags), (lock))
+/**
+ * devm_clk_hw_register_gate - register a gate clock with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+#define devm_clk_hw_register_gate(dev, name, parent_name, flags, reg, bit_idx,\
+                                 clk_gate_flags, lock)                       \
+       __devm_clk_hw_register_gate((dev), NULL, (name), (parent_name), NULL, \
+                              NULL, (flags), (reg), (bit_idx),               \
+                              (clk_gate_flags), (lock))
 void clk_unregister_gate(struct clk *clk);
 void clk_hw_unregister_gate(struct clk_hw *hw);
 int clk_gate_is_enabled(struct clk_hw *hw);
index 16119ac..7d4f52c 100644 (file)
@@ -1025,8 +1025,9 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
                               struct acpi_resource_i2c_serialbus **i2c);
 int i2c_acpi_client_count(struct acpi_device *adev);
 u32 i2c_acpi_find_bus_speed(struct device *dev);
-struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
-                                      struct i2c_board_info *info);
+struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
+                                                int index,
+                                                struct i2c_board_info *info);
 struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
 bool i2c_acpi_waive_d0_probe(struct device *dev);
 #else
@@ -1043,8 +1044,9 @@ static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
 {
        return 0;
 }
-static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
-                                       int index, struct i2c_board_info *info)
+static inline struct i2c_client *i2c_acpi_new_device_by_fwnode(
+                                       struct fwnode_handle *fwnode, int index,
+                                       struct i2c_board_info *info)
 {
        return ERR_PTR(-ENODEV);
 }
@@ -1058,4 +1060,11 @@ static inline bool i2c_acpi_waive_d0_probe(struct device *dev)
 }
 #endif /* CONFIG_ACPI */
 
+static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
+                                                    int index,
+                                                    struct i2c_board_info *info)
+{
+       return i2c_acpi_new_device_by_fwnode(dev_fwnode(dev), index, info);
+}
+
 #endif /* _LINUX_I2C_H */
index ffe8112..7807fa3 100644 (file)
 #define TPS68470_CLKCFG1_MODE_A_MASK   GENMASK(1, 0)
 #define TPS68470_CLKCFG1_MODE_B_MASK   GENMASK(3, 2)
 
+#define TPS68470_CLKCFG2_DRV_STR_2MA   0x05
+#define TPS68470_PLL_OUTPUT_ENABLE     0x02
+#define TPS68470_CLK_SRC_XTAL          BIT(0)
+#define TPS68470_PLLSWR_DEFAULT                GENMASK(1, 0)
+#define TPS68470_OSC_EXT_CAP_DEFAULT   0x05
+
+#define TPS68470_OUTPUT_A_SHIFT                0x00
+#define TPS68470_OUTPUT_B_SHIFT                0x02
+#define TPS68470_CLK_SRC_SHIFT         GENMASK(2, 0)
+#define TPS68470_OSC_EXT_CAP_SHIFT     BIT(2)
+
 #define TPS68470_GPIO_CTL_REG_A(x)     (TPS68470_REG_GPCTL0A + (x) * 2)
 #define TPS68470_GPIO_CTL_REG_B(x)     (TPS68470_REG_GPCTL0B + (x) * 2)
 #define TPS68470_GPIO_MODE_MASK                GENMASK(1, 0)
index b9f6824..11a2a23 100644 (file)
@@ -12,7 +12,7 @@
 
 struct fch_clk_data {
        void __iomem *base;
-       u32 is_rv;
+       char *name;
 };
 
 #endif /* __CLK_FCH_H */
diff --git a/include/linux/platform_data/tps68470.h b/include/linux/platform_data/tps68470.h
new file mode 100644 (file)
index 0000000..126d082
--- /dev/null
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * TI TPS68470 PMIC platform data definition.
+ *
+ * Copyright (c) 2021 Red Hat Inc.
+ *
+ * Red Hat authors:
+ * Hans de Goede <hdegoede@redhat.com>
+ */
+#ifndef __PDATA_TPS68470_H
+#define __PDATA_TPS68470_H
+
+enum tps68470_regulators {
+       TPS68470_CORE,
+       TPS68470_ANA,
+       TPS68470_VCM,
+       TPS68470_VIO,
+       TPS68470_VSIO,
+       TPS68470_AUX1,
+       TPS68470_AUX2,
+       TPS68470_NUM_REGULATORS
+};
+
+struct regulator_init_data;
+
+struct tps68470_regulator_platform_data {
+       const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS];
+};
+
+struct tps68470_clk_platform_data {
+       const char *consumer_dev_name;
+       const char *consumer_con_id;
+};
+
+#endif