2018-04-07 14:03:19

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v3 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

This patch adds a driver for the BMS (Battery Monitoring System)
block of the PM8941 PMIC, it uses a lookup table defined in the
device tree to generate a capacity from the BMS supplied OCV, it
then ammends the coulomb counter to that to increase the accuracy
of the estimated capacity.

Signed-off-by: Craig Tatlor <[email protected]>
---
drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/qcom_bms.c | 500 ++++++++++++++++++++++++++++++++
3 files changed, 510 insertions(+)
create mode 100644 drivers/power/supply/qcom_bms.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..6c354c37bc55 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -82,6 +82,15 @@ config BATTERY_ACT8945A
Say Y here to enable support for power supply provided by
Active-semi ActivePath ACT8945A charger.

+config BATTERY_BMS
+ tristate "Qualcomm Battery Monitoring System driver"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ depends on REGMAP_SPMI
+ help
+ Say Y to include support for the Battery Monitoring hardware
+ found in some Qualcomm PM series PMICs.
+
config BATTERY_CPCAP
tristate "Motorola CPCAP PMIC battery driver"
depends on MFD_CPCAP && IIO
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..04204174b047 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
+obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
new file mode 100644
index 000000000000..5aa6e906d1b9
--- /dev/null
+++ b/drivers/power/supply/qcom_bms.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL
+
+/*
+ * Qualcomm Battery Monitoring System driver
+ *
+ * Copyright (C) 2018 Craig Tatlor <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/iio/consumer.h>
+
+#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
+#define REG_BMS_SHDW_CC_DATA0 0xA8
+#define REG_BMS_CC_DATA_CTL 0x42
+#define REG_BMS_CC_CLEAR_CTL 0x4
+
+#define BMS_HOLD_OREG_DATA BIT(0)
+#define BMS_CLEAR_SHDW_CC BIT(6)
+
+#define CC_36_BIT_MASK 0xFFFFFFFFFLL
+#define SIGN_EXTEND_36_TO_64_MASK (-1LL ^ CC_36_BIT_MASK)
+
+#define BMS_CC_READING_RESOLUTION_N 542535
+#define BMS_CC_READING_RESOLUTION_D 10000
+#define BMS_CC_READING_TICKS 56
+#define BMS_SLEEP_CLK_HZ 32764
+
+#define SECONDS_PER_HOUR 3600
+#define TEMPERATURE_COLS 5
+#define MAX_CAPACITY_ROWS 50
+
+/* lookup table for ocv -> capacity conversion */
+struct bms_ocv_lut {
+ int rows;
+ s8 temp_legend[TEMPERATURE_COLS];
+ u8 capacity_legend[MAX_CAPACITY_ROWS];
+ u16 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
+};
+
+/* lookup table for battery temperature -> fcc conversion */
+struct bms_fcc_lut {
+ s8 temp_legend[TEMPERATURE_COLS];
+ u16 lut[TEMPERATURE_COLS];
+};
+
+struct bms_device_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply *bat;
+ struct power_supply_desc bat_desc;
+ struct bms_ocv_lut ocv_lut;
+ struct bms_fcc_lut fcc_lut;
+ struct iio_channel *adc;
+ spinlock_t bms_output_lock;
+ int base_addr;
+
+ int ocv_thr_irq;
+ int ocv;
+};
+
+static s64 sign_extend_s36(uint64_t raw)
+{
+ raw = raw & CC_36_BIT_MASK;
+
+ return (raw >> 35) == 0LL ?
+ raw : (SIGN_EXTEND_36_TO_64_MASK | raw);
+}
+
+static unsigned int interpolate(int y0, int x0, int y1, int x1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
+static unsigned int between(int left, int right, int val)
+{
+ if (left <= val && val >= right)
+ return 1;
+
+ return 0;
+}
+
+static unsigned int interpolate_capacity(int temp, u16 ocv,
+ struct bms_ocv_lut ocv_lut)
+{
+ unsigned int pcj_minus_one = 0, pcj = 0;
+ int i, j;
+
+ for (j = 0; j < TEMPERATURE_COLS; j++)
+ if (temp <= ocv_lut.temp_legend[j])
+ break;
+
+ if (ocv >= ocv_lut.lut[0][j])
+ return ocv_lut.capacity_legend[0];
+
+ if (ocv <= ocv_lut.lut[ocv_lut.rows - 1][j - 1])
+ return ocv_lut.capacity_legend[ocv_lut.rows - 1];
+
+ for (i = 0; i < ocv_lut.rows - 1; i++) {
+ if (pcj == 0 && between(ocv_lut.lut[i][j],
+ ocv_lut.lut[i+1][j], ocv))
+ pcj = interpolate(ocv_lut.capacity_legend[i],
+ ocv_lut.lut[i][j],
+ ocv_lut.capacity_legend[i + 1],
+ ocv_lut.lut[i+1][j],
+ ocv);
+
+ if (pcj_minus_one == 0 && between(ocv_lut.lut[i][j-1],
+ ocv_lut.lut[i+1][j-1], ocv))
+ pcj_minus_one = interpolate(ocv_lut.capacity_legend[i],
+ ocv_lut.lut[i][j-1],
+ ocv_lut.capacity_legend[i + 1],
+ ocv_lut.lut[i+1][j-1],
+ ocv);
+
+ if (pcj && pcj_minus_one)
+ return interpolate(pcj_minus_one,
+ ocv_lut.temp_legend[j-1],
+ pcj,
+ ocv_lut.temp_legend[j],
+ temp);
+ }
+
+ if (pcj)
+ return pcj;
+
+ if (pcj_minus_one)
+ return pcj_minus_one;
+
+ return 100;
+}
+
+static unsigned long interpolate_fcc(int temp, struct bms_fcc_lut fcc_lut)
+{
+ int i, fcc_mv;
+
+ for (i = 0; i < TEMPERATURE_COLS; i++)
+ if (temp <= fcc_lut.temp_legend[i])
+ break;
+
+ fcc_mv = interpolate(fcc_lut.lut[i - 1],
+ fcc_lut.temp_legend[i - 1],
+ fcc_lut.lut[i],
+ fcc_lut.temp_legend[i],
+ temp);
+
+ return fcc_mv * 10000;
+}
+
+static int bms_lock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to lock bms output: %d", ret);
+ return ret;
+ }
+
+ /*
+ * Sleep for 100 microseconds here to make sure there has
+ * been at least three cycles of the sleep clock so that
+ * the registers are correctly locked.
+ */
+ udelay(100);
+
+ return 0;
+}
+
+static int bms_unlock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, 0);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to unlock bms output: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bms_read_ocv(struct bms_device_info *di, int *ocv)
+{
+ unsigned long flags;
+ int ret;
+ u16 read_ocv;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = bms_lock_output_data(di);
+ if (ret < 0)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
+ if (ret < 0) {
+ dev_err(di->dev, "OCV read failed: %d", ret);
+ return ret;
+ }
+
+ dev_dbg(di->dev, "read OCV value of: %d", read_ocv);
+ *ocv = read_ocv;
+
+ ret = bms_unlock_output_data(di);
+
+err_lock:
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+
+ return ret;
+}
+
+static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
+{
+ unsigned long flags;
+ int ret;
+ s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = bms_lock_output_data(di);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_SHDW_CC_DATA0,
+ &cc_raw_s36, 5);
+ if (ret < 0) {
+ dev_err(di->dev, "coulomb counter read failed: %d", ret);
+ return ret;
+ }
+
+ ret = bms_unlock_output_data(di);
+ if (ret < 0)
+ return ret;
+
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+
+ cc_raw = sign_extend_s36(cc_raw_s36);
+
+ /* convert raw to uv */
+ cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
+ BMS_CC_READING_RESOLUTION_D);
+
+ /* convert uv to pvh */
+ cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
+ BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
+
+ /* divide by impedance */
+ *cc_uah = div_s64(cc_pvh, 10000);
+
+ dev_dbg(di->dev, "read coulomb counter value of: %lld", *cc_uah);
+
+ return 0;
+}
+
+static void bms_reset_cc(struct bms_device_info *di)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC,
+ BMS_CLEAR_SHDW_CC);
+ if (ret < 0) {
+ dev_err(di->dev, "coulomb counter reset failed: %d", ret);
+ goto err_lock;
+ }
+
+ /* wait two sleep cycles for cc to reset */
+ udelay(100);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC, 0);
+ if (ret < 0)
+ dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
+
+err_lock:
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+}
+
+static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
+{
+ unsigned long ocv_capacity, fcc;
+ int ret, temp, temp_degc;
+ s64 cc, capacity_nodiv;
+
+ ret = iio_read_channel_raw(di->adc, &temp);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp_degc = (temp + 500) / 1000;
+
+ ret = bms_read_cc(di, &cc);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read coulomb counter: %d", ret);
+ return ret;
+ }
+
+ ocv_capacity = interpolate_capacity(temp_degc, (di->ocv + 5) / 10,
+ di->ocv_lut);
+ fcc = interpolate_fcc(temp_degc, di->fcc_lut);
+
+ capacity_nodiv = ((fcc * ocv_capacity) / 100 - cc) * 100;
+ *capacity = div64_ul(capacity_nodiv, fcc);
+
+ return 0;
+}
+
+
+
+/*
+ * Return power_supply property
+ */
+static int bms_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bms_device_info *di = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bms_calculate_capacity(di, &val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (val->intval == INT_MAX || val->intval == INT_MIN)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static enum power_supply_property bms_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
+{
+ struct bms_device_info *di = dev_id;
+
+ if (bms_read_ocv(di, &di->ocv) < 0)
+ return IRQ_HANDLED;
+
+ bms_reset_cc(di);
+ return IRQ_HANDLED;
+}
+
+static int bms_probe(struct platform_device *pdev)
+{
+ struct power_supply_config psy_cfg = {};
+ struct bms_device_info *di;
+ int ret;
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, di);
+
+ di->dev = &pdev->dev;
+
+ di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!di->regmap) {
+ dev_err(di->dev, "Unable to get regmap");
+ return -EINVAL;
+ }
+
+ di->adc = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(di->adc))
+ return PTR_ERR(di->adc);
+
+ ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,ocv-temp-legend",
+ (u8 *)di->ocv_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no ocv temperature legend found");
+ return ret;
+ }
+
+ di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
+ "qcom,ocv-capacity-legend",
+ di->ocv_lut.capacity_legend, 0,
+ MAX_CAPACITY_ROWS);
+ if (di->ocv_lut.rows < 0) {
+ dev_err(di->dev, "no ocv capacity legend found");
+ return ret;
+ }
+
+ ret = of_property_read_variable_u16_array(di->dev->of_node,
+ "qcom,ocv-lut",
+ (u16 *)di->ocv_lut.lut,
+ TEMPERATURE_COLS,
+ TEMPERATURE_COLS *
+ MAX_CAPACITY_ROWS);
+ if (ret < 0) {
+ dev_err(di->dev, "no ocv lut array found");
+ return ret;
+ }
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,fcc-temp-legend",
+ (u8 *)di->fcc_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no fcc temperature legend found");
+ return ret;
+ }
+
+ ret = of_property_read_u16_array(di->dev->of_node,
+ "qcom,fcc-lut",
+ di->fcc_lut.lut,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no fcc lut array found");
+ return ret;
+ }
+
+ ret = bms_read_ocv(di, &di->ocv);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read initial ocv: %d", ret);
+ return ret;
+ }
+
+ di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
+
+ ret = devm_request_irq(di->dev, di->ocv_thr_irq,
+ bms_ocv_thr_irq_handler,
+ IRQF_TRIGGER_RISING,
+ pdev->name, di);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to request handler for ocv threshold IRQ");
+ return ret;
+ }
+
+ spin_lock_init(&di->bms_output_lock);
+
+ di->bat_desc.name = "bms";
+ di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat_desc.properties = bms_props;
+ di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
+ di->bat_desc.get_property = bms_get_property;
+
+ psy_cfg.drv_data = di;
+ di->bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+ if (IS_ERR(di->bat))
+ return PTR_ERR(di->bat);
+
+ return 0;
+}
+
+static const struct of_device_id bms_of_match[] = {
+ {.compatible = "qcom,pm8941-bms", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bms_of_match);
+
+static struct platform_driver bms_driver = {
+ .probe = bms_probe,
+ .driver = {
+ .name = "qcom-bms",
+ .of_match_table = of_match_ptr(bms_of_match),
+ },
+};
+module_platform_driver(bms_driver);
+
+MODULE_AUTHOR("Craig Tatlor <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm BMS driver");
+MODULE_LICENSE("GPL");
--
2.17.0



2018-04-07 14:03:54

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v3 2/3] dt-bindings: power: supply: qcom_bms: Add bindings

Add bindings for the Qualcomm Battery Monitoring system.

Signed-off-by: Craig Tatlor <[email protected]>
---
.../bindings/power/supply/qcom_bms.txt | 93 +++++++++++++++++++
1 file changed, 93 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt

diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
new file mode 100644
index 000000000000..6296399edc09
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
@@ -0,0 +1,93 @@
+Qualcomm Battery Measurement System
+
+The Qualcomm Battery Measurement System is found inside of Qualcomm PM8941
+PMICs. It provides OCV and coulomb counter registers that allow the kernel
+to infer a capacity level.
+
+Required properties:
+- compatible: Should contain "qcom,pm8941-bms".
+- reg: Specifies the SPMI address and length of the
+ controller's registers.
+- interrupts: OCV threshold interrupt.
+- io-channels: Should contain IIO channel specifier for the
+ ADC channel that reports battery temperature.
+- io-channel-names: Should contain "temp".
+- qcom,fcc-temp-legend: An array containing the temperature, in degC,
+ for each column of the FCC lookup table.
+- qcom,fcc-lut: An array of FCC values in mah, one entry for each
+ temperature defined in in qcom,fcc-temp-legend.
+- qcom,ocv-temp-legend: An array containing the temperature, in degC,
+ for each column of the OCV lookup table.
+- qcom,ocv-capacity-legend: An array containing the capacity for each
+ row of the OCV lookup table.
+- qcom,ocv-lut: An array of OCV values in mV, one entry for each
+ capacity defined in qcom,ocv-capacity-legend.
+
+Example:
+
+ pm8941_vadc: vadc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
+ };
+
+ bms@4000 {
+ compatible = "qcom,pm8941-bms";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ocv_thr";
+
+ io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
+ io-channel-names = "temp";
+
+ qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
+
+ qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
+ 80 75 70 65
+ 60 55 50 45
+ 40 35 30 25
+ 20 15 10 9
+ 8 7 6 5 4
+ 3 2 1 0>;
+
+ qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
+ 4261 4241 4259 4266 4246
+ 4201 4181 4201 4207 4187
+ 4153 4133 4150 4155 4135
+ 4105 4085 4100 4104 4084
+ 4058 4038 4052 4058 4038
+ 4012 3992 4004 4014 3994
+ 3970 3950 3959 3971 3951
+ 3931 3911 3915 3927 3907
+ 3899 3879 3880 3884 3864
+ 3873 3853 3851 3853 3833
+ 3848 3828 3827 3829 3809
+ 3829 3809 3808 3809 3789
+ 3815 3795 3791 3791 3771
+ 3801 3781 3775 3772 3752
+ 3785 3765 3751 3746 3726
+ 3767 3747 3727 3719 3699
+ 3750 3730 3702 3692 3672
+ 3728 3708 3680 3672 3652
+ 3720 3700 3676 3665 3645
+ 3712 3692 3670 3660 3645
+ 3695 3675 3658 3648 3633
+ 3662 3647 3629 3620 3610
+ 3620 3605 3589 3580 3570
+ 3562 3552 3538 3529 3519
+ 3490 3480 3474 3470 3465
+ 3403 3398 3388 3380 3375
+ 3320 3300 3255 3221 3206
+ 3000 3000 3000 3000 3000>;
+ };
+ };
+};
--
2.17.0


2018-04-07 14:05:51

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v3 3/3] MAINTAINERS: Add entry for the Qualcomm BMS

Signed-off-by: Craig Tatlor <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0c3ad62c638c..aaf54b665f86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11605,6 +11605,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/

+QUALCOMM BATTERY MONITORING SYSTEM
+M: Craig Tatlor <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/power/supply/qcom_bms.c
+
QUALCOMM CAMERA SUBSYSTEM DRIVER
M: Todor Tomov <[email protected]>
L: [email protected]
--
2.17.0


2018-04-07 16:41:18

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

On 04/07/2018 06:59 AM, Craig Tatlor wrote:
> This patch adds a driver for the BMS (Battery Monitoring System)
> block of the PM8941 PMIC, it uses a lookup table defined in the
> device tree to generate a capacity from the BMS supplied OCV, it
> then ammends the coulomb counter to that to increase the accuracy
> of the estimated capacity.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
> drivers/power/supply/Kconfig | 9 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/qcom_bms.c | 500 ++++++++++++++++++++++++++++++++
> 3 files changed, 510 insertions(+)
> create mode 100644 drivers/power/supply/qcom_bms.c

> diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
> new file mode 100644
> index 000000000000..5aa6e906d1b9
> --- /dev/null
> +++ b/drivers/power/supply/qcom_bms.c
> @@ -0,0 +1,500 @@

Hi,

> +static unsigned int between(int left, int right, int val)
> +{
> + if (left <= val && val >= right)

maybe double-check those if() conditions?
[or I need my morning coffee]

> + return 1;
> +
> + return 0;
> +}

thanks,
--
~Randy

2018-04-07 18:00:21

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

On Sat, Apr 07, 2018 at 09:37:21AM -0700, Randy Dunlap wrote:
> On 04/07/2018 06:59 AM, Craig Tatlor wrote:
> > This patch adds a driver for the BMS (Battery Monitoring System)
> > block of the PM8941 PMIC, it uses a lookup table defined in the
> > device tree to generate a capacity from the BMS supplied OCV, it
> > then ammends the coulomb counter to that to increase the accuracy
> > of the estimated capacity.
> >
> > Signed-off-by: Craig Tatlor <[email protected]>
> > ---
> > drivers/power/supply/Kconfig | 9 +
> > drivers/power/supply/Makefile | 1 +
> > drivers/power/supply/qcom_bms.c | 500 ++++++++++++++++++++++++++++++++
> > 3 files changed, 510 insertions(+)
> > create mode 100644 drivers/power/supply/qcom_bms.c
>
> > diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
> > new file mode 100644
> > index 000000000000..5aa6e906d1b9
> > --- /dev/null
> > +++ b/drivers/power/supply/qcom_bms.c
> > @@ -0,0 +1,500 @@
>
> Hi,
Hey
>
> > +static unsigned int between(int left, int right, int val)
> > +{
> > + if (left <= val && val >= right)
>
> maybe double-check those if() conditions?
> [or I need my morning coffee]
Yeah, they are wrong, will fix.
>
> > + return 1;
> > +
> > + return 0;
> > +}
>
> thanks,
> --
> ~Randy

2018-04-07 18:02:19

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v4 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

This patch adds a driver for the BMS (Battery Monitoring System)
block of the PM8941 PMIC, it uses a lookup table defined in the
device tree to generate a capacity from the BMS supplied OCV, it
then ammends the coulomb counter to that to increase the accuracy
of the estimated capacity.

Signed-off-by: Craig Tatlor <[email protected]>
---
drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/qcom_bms.c | 500 ++++++++++++++++++++++++++++++++
3 files changed, 510 insertions(+)
create mode 100644 drivers/power/supply/qcom_bms.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..6c354c37bc55 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -82,6 +82,15 @@ config BATTERY_ACT8945A
Say Y here to enable support for power supply provided by
Active-semi ActivePath ACT8945A charger.

+config BATTERY_BMS
+ tristate "Qualcomm Battery Monitoring System driver"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ depends on REGMAP_SPMI
+ help
+ Say Y to include support for the Battery Monitoring hardware
+ found in some Qualcomm PM series PMICs.
+
config BATTERY_CPCAP
tristate "Motorola CPCAP PMIC battery driver"
depends on MFD_CPCAP && IIO
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..04204174b047 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
+obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
new file mode 100644
index 000000000000..f31c99c03518
--- /dev/null
+++ b/drivers/power/supply/qcom_bms.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL
+
+/*
+ * Qualcomm Battery Monitoring System driver
+ *
+ * Copyright (C) 2018 Craig Tatlor <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/iio/consumer.h>
+
+#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
+#define REG_BMS_SHDW_CC_DATA0 0xA8
+#define REG_BMS_CC_DATA_CTL 0x42
+#define REG_BMS_CC_CLEAR_CTL 0x4
+
+#define BMS_HOLD_OREG_DATA BIT(0)
+#define BMS_CLEAR_SHDW_CC BIT(6)
+
+#define CC_36_BIT_MASK 0xFFFFFFFFFLL
+#define SIGN_EXTEND_36_TO_64_MASK (-1LL ^ CC_36_BIT_MASK)
+
+#define BMS_CC_READING_RESOLUTION_N 542535
+#define BMS_CC_READING_RESOLUTION_D 10000
+#define BMS_CC_READING_TICKS 56
+#define BMS_SLEEP_CLK_HZ 32764
+
+#define SECONDS_PER_HOUR 3600
+#define TEMPERATURE_COLS 5
+#define MAX_CAPACITY_ROWS 50
+
+/* lookup table for ocv -> capacity conversion */
+struct bms_ocv_lut {
+ int rows;
+ s8 temp_legend[TEMPERATURE_COLS];
+ u8 capacity_legend[MAX_CAPACITY_ROWS];
+ u16 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
+};
+
+/* lookup table for battery temperature -> fcc conversion */
+struct bms_fcc_lut {
+ s8 temp_legend[TEMPERATURE_COLS];
+ u16 lut[TEMPERATURE_COLS];
+};
+
+struct bms_device_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct power_supply *bat;
+ struct power_supply_desc bat_desc;
+ struct bms_ocv_lut ocv_lut;
+ struct bms_fcc_lut fcc_lut;
+ struct iio_channel *adc;
+ spinlock_t bms_output_lock;
+ int base_addr;
+
+ int ocv_thr_irq;
+ int ocv;
+};
+
+static s64 sign_extend_s36(uint64_t raw)
+{
+ raw = raw & CC_36_BIT_MASK;
+
+ return (raw >> 35) == 0LL ?
+ raw : (SIGN_EXTEND_36_TO_64_MASK | raw);
+}
+
+static unsigned int interpolate(int y0, int x0, int y1, int x1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
+static unsigned int between(int left, int right, int val)
+{
+ if (left <= val && val <= right)
+ return 1;
+
+ return 0;
+}
+
+static unsigned int interpolate_capacity(int temp, u16 ocv,
+ struct bms_ocv_lut ocv_lut)
+{
+ unsigned int pcj_minus_one = 0, pcj = 0;
+ int i, j;
+
+ for (j = 0; j < TEMPERATURE_COLS; j++)
+ if (temp <= ocv_lut.temp_legend[j])
+ break;
+
+ if (ocv >= ocv_lut.lut[0][j])
+ return ocv_lut.capacity_legend[0];
+
+ if (ocv <= ocv_lut.lut[ocv_lut.rows - 1][j - 1])
+ return ocv_lut.capacity_legend[ocv_lut.rows - 1];
+
+ for (i = 0; i < ocv_lut.rows - 1; i++) {
+ if (pcj == 0 && between(ocv_lut.lut[i][j],
+ ocv_lut.lut[i+1][j], ocv))
+ pcj = interpolate(ocv_lut.capacity_legend[i],
+ ocv_lut.lut[i][j],
+ ocv_lut.capacity_legend[i + 1],
+ ocv_lut.lut[i+1][j],
+ ocv);
+
+ if (pcj_minus_one == 0 && between(ocv_lut.lut[i][j-1],
+ ocv_lut.lut[i+1][j-1], ocv))
+ pcj_minus_one = interpolate(ocv_lut.capacity_legend[i],
+ ocv_lut.lut[i][j-1],
+ ocv_lut.capacity_legend[i + 1],
+ ocv_lut.lut[i+1][j-1],
+ ocv);
+
+ if (pcj && pcj_minus_one)
+ return interpolate(pcj_minus_one,
+ ocv_lut.temp_legend[j-1],
+ pcj,
+ ocv_lut.temp_legend[j],
+ temp);
+ }
+
+ if (pcj)
+ return pcj;
+
+ if (pcj_minus_one)
+ return pcj_minus_one;
+
+ return 100;
+}
+
+static unsigned long interpolate_fcc(int temp, struct bms_fcc_lut fcc_lut)
+{
+ int i, fcc_mv;
+
+ for (i = 0; i < TEMPERATURE_COLS; i++)
+ if (temp <= fcc_lut.temp_legend[i])
+ break;
+
+ fcc_mv = interpolate(fcc_lut.lut[i - 1],
+ fcc_lut.temp_legend[i - 1],
+ fcc_lut.lut[i],
+ fcc_lut.temp_legend[i],
+ temp);
+
+ return fcc_mv * 10000;
+}
+
+static int bms_lock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to lock bms output: %d", ret);
+ return ret;
+ }
+
+ /*
+ * Sleep for 100 microseconds here to make sure there has
+ * been at least three cycles of the sleep clock so that
+ * the registers are correctly locked.
+ */
+ udelay(100);
+
+ return 0;
+}
+
+static int bms_unlock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, 0);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to unlock bms output: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bms_read_ocv(struct bms_device_info *di, int *ocv)
+{
+ unsigned long flags;
+ int ret;
+ u16 read_ocv;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = bms_lock_output_data(di);
+ if (ret < 0)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
+ if (ret < 0) {
+ dev_err(di->dev, "OCV read failed: %d", ret);
+ return ret;
+ }
+
+ dev_dbg(di->dev, "read OCV value of: %d", read_ocv);
+ *ocv = read_ocv;
+
+ ret = bms_unlock_output_data(di);
+
+err_lock:
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+
+ return ret;
+}
+
+static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
+{
+ unsigned long flags;
+ int ret;
+ s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = bms_lock_output_data(di);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_SHDW_CC_DATA0,
+ &cc_raw_s36, 5);
+ if (ret < 0) {
+ dev_err(di->dev, "coulomb counter read failed: %d", ret);
+ return ret;
+ }
+
+ ret = bms_unlock_output_data(di);
+ if (ret < 0)
+ return ret;
+
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+
+ cc_raw = sign_extend_s36(cc_raw_s36);
+
+ /* convert raw to uv */
+ cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
+ BMS_CC_READING_RESOLUTION_D);
+
+ /* convert uv to pvh */
+ cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
+ BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR) * 10;
+
+ /* divide by impedance */
+ *cc_uah = div_s64(cc_pvh, 10000);
+
+ dev_dbg(di->dev, "read coulomb counter value of: %lld", *cc_uah);
+
+ return 0;
+}
+
+static void bms_reset_cc(struct bms_device_info *di)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&di->bms_output_lock, flags);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC,
+ BMS_CLEAR_SHDW_CC);
+ if (ret < 0) {
+ dev_err(di->dev, "coulomb counter reset failed: %d", ret);
+ goto err_lock;
+ }
+
+ /* wait two sleep cycles for cc to reset */
+ udelay(100);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC, 0);
+ if (ret < 0)
+ dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
+
+err_lock:
+ spin_unlock_irqrestore(&di->bms_output_lock, flags);
+}
+
+static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
+{
+ unsigned long ocv_capacity, fcc;
+ int ret, temp, temp_degc;
+ s64 cc, capacity_nodiv;
+
+ ret = iio_read_channel_raw(di->adc, &temp);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp_degc = (temp + 500) / 1000;
+
+ ret = bms_read_cc(di, &cc);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read coulomb counter: %d", ret);
+ return ret;
+ }
+
+ ocv_capacity = interpolate_capacity(temp_degc, (di->ocv + 5) / 10,
+ di->ocv_lut);
+ fcc = interpolate_fcc(temp_degc, di->fcc_lut);
+
+ capacity_nodiv = ((fcc * ocv_capacity) / 100 - cc) * 100;
+ *capacity = div64_ul(capacity_nodiv, fcc);
+
+ return 0;
+}
+
+
+
+/*
+ * Return power_supply property
+ */
+static int bms_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bms_device_info *di = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bms_calculate_capacity(di, &val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (val->intval == INT_MAX || val->intval == INT_MIN)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static enum power_supply_property bms_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
+{
+ struct bms_device_info *di = dev_id;
+
+ if (bms_read_ocv(di, &di->ocv) < 0)
+ return IRQ_HANDLED;
+
+ bms_reset_cc(di);
+ return IRQ_HANDLED;
+}
+
+static int bms_probe(struct platform_device *pdev)
+{
+ struct power_supply_config psy_cfg = {};
+ struct bms_device_info *di;
+ int ret;
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, di);
+
+ di->dev = &pdev->dev;
+
+ di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!di->regmap) {
+ dev_err(di->dev, "Unable to get regmap");
+ return -EINVAL;
+ }
+
+ di->adc = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(di->adc))
+ return PTR_ERR(di->adc);
+
+ ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,ocv-temp-legend",
+ (u8 *)di->ocv_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no ocv temperature legend found");
+ return ret;
+ }
+
+ di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
+ "qcom,ocv-capacity-legend",
+ di->ocv_lut.capacity_legend, 0,
+ MAX_CAPACITY_ROWS);
+ if (di->ocv_lut.rows < 0) {
+ dev_err(di->dev, "no ocv capacity legend found");
+ return ret;
+ }
+
+ ret = of_property_read_variable_u16_array(di->dev->of_node,
+ "qcom,ocv-lut",
+ (u16 *)di->ocv_lut.lut,
+ TEMPERATURE_COLS,
+ TEMPERATURE_COLS *
+ MAX_CAPACITY_ROWS);
+ if (ret < 0) {
+ dev_err(di->dev, "no ocv lut array found");
+ return ret;
+ }
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,fcc-temp-legend",
+ (u8 *)di->fcc_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no fcc temperature legend found");
+ return ret;
+ }
+
+ ret = of_property_read_u16_array(di->dev->of_node,
+ "qcom,fcc-lut",
+ di->fcc_lut.lut,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no fcc lut array found");
+ return ret;
+ }
+
+ ret = bms_read_ocv(di, &di->ocv);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read initial ocv: %d", ret);
+ return ret;
+ }
+
+ di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
+
+ ret = devm_request_irq(di->dev, di->ocv_thr_irq,
+ bms_ocv_thr_irq_handler,
+ IRQF_TRIGGER_RISING,
+ pdev->name, di);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to request handler for ocv threshold IRQ");
+ return ret;
+ }
+
+ spin_lock_init(&di->bms_output_lock);
+
+ di->bat_desc.name = "bms";
+ di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat_desc.properties = bms_props;
+ di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
+ di->bat_desc.get_property = bms_get_property;
+
+ psy_cfg.drv_data = di;
+ di->bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+ if (IS_ERR(di->bat))
+ return PTR_ERR(di->bat);
+
+ return 0;
+}
+
+static const struct of_device_id bms_of_match[] = {
+ {.compatible = "qcom,pm8941-bms", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bms_of_match);
+
+static struct platform_driver bms_driver = {
+ .probe = bms_probe,
+ .driver = {
+ .name = "qcom-bms",
+ .of_match_table = of_match_ptr(bms_of_match),
+ },
+};
+module_platform_driver(bms_driver);
+
+MODULE_AUTHOR("Craig Tatlor <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm BMS driver");
+MODULE_LICENSE("GPL");
--
2.17.0


2018-04-07 18:03:03

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings

Add bindings for the Qualcomm Battery Monitoring system.

Signed-off-by: Craig Tatlor <[email protected]>
---
.../bindings/power/supply/qcom_bms.txt | 93 +++++++++++++++++++
1 file changed, 93 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt

diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
new file mode 100644
index 000000000000..6296399edc09
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
@@ -0,0 +1,93 @@
+Qualcomm Battery Measurement System
+
+The Qualcomm Battery Measurement System is found inside of Qualcomm PM8941
+PMICs. It provides OCV and coulomb counter registers that allow the kernel
+to infer a capacity level.
+
+Required properties:
+- compatible: Should contain "qcom,pm8941-bms".
+- reg: Specifies the SPMI address and length of the
+ controller's registers.
+- interrupts: OCV threshold interrupt.
+- io-channels: Should contain IIO channel specifier for the
+ ADC channel that reports battery temperature.
+- io-channel-names: Should contain "temp".
+- qcom,fcc-temp-legend: An array containing the temperature, in degC,
+ for each column of the FCC lookup table.
+- qcom,fcc-lut: An array of FCC values in mah, one entry for each
+ temperature defined in in qcom,fcc-temp-legend.
+- qcom,ocv-temp-legend: An array containing the temperature, in degC,
+ for each column of the OCV lookup table.
+- qcom,ocv-capacity-legend: An array containing the capacity for each
+ row of the OCV lookup table.
+- qcom,ocv-lut: An array of OCV values in mV, one entry for each
+ capacity defined in qcom,ocv-capacity-legend.
+
+Example:
+
+ pm8941_vadc: vadc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
+ };
+
+ bms@4000 {
+ compatible = "qcom,pm8941-bms";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ocv_thr";
+
+ io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
+ io-channel-names = "temp";
+
+ qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
+
+ qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
+ 80 75 70 65
+ 60 55 50 45
+ 40 35 30 25
+ 20 15 10 9
+ 8 7 6 5 4
+ 3 2 1 0>;
+
+ qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
+ 4261 4241 4259 4266 4246
+ 4201 4181 4201 4207 4187
+ 4153 4133 4150 4155 4135
+ 4105 4085 4100 4104 4084
+ 4058 4038 4052 4058 4038
+ 4012 3992 4004 4014 3994
+ 3970 3950 3959 3971 3951
+ 3931 3911 3915 3927 3907
+ 3899 3879 3880 3884 3864
+ 3873 3853 3851 3853 3833
+ 3848 3828 3827 3829 3809
+ 3829 3809 3808 3809 3789
+ 3815 3795 3791 3791 3771
+ 3801 3781 3775 3772 3752
+ 3785 3765 3751 3746 3726
+ 3767 3747 3727 3719 3699
+ 3750 3730 3702 3692 3672
+ 3728 3708 3680 3672 3652
+ 3720 3700 3676 3665 3645
+ 3712 3692 3670 3660 3645
+ 3695 3675 3658 3648 3633
+ 3662 3647 3629 3620 3610
+ 3620 3605 3589 3580 3570
+ 3562 3552 3538 3529 3519
+ 3490 3480 3474 3470 3465
+ 3403 3398 3388 3380 3375
+ 3320 3300 3255 3221 3206
+ 3000 3000 3000 3000 3000>;
+ };
+ };
+};
--
2.17.0


2018-04-07 18:03:52

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v4 3/3] MAINTAINERS: Add entry for the Qualcomm BMS

Signed-off-by: Craig Tatlor <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0c3ad62c638c..aaf54b665f86 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11605,6 +11605,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/

+QUALCOMM BATTERY MONITORING SYSTEM
+M: Craig Tatlor <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/power/supply/qcom_bms.c
+
QUALCOMM CAMERA SUBSYSTEM DRIVER
M: Todor Tomov <[email protected]>
L: [email protected]
--
2.17.0


2018-04-13 16:37:12

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings

On Sat, Apr 07, 2018 at 06:57:45PM +0100, Craig Tatlor wrote:
> Add bindings for the Qualcomm Battery Monitoring system.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
> .../bindings/power/supply/qcom_bms.txt | 93 +++++++++++++++++++
> 1 file changed, 93 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>
> diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> new file mode 100644
> index 000000000000..6296399edc09
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> @@ -0,0 +1,93 @@
> +Qualcomm Battery Measurement System
> +
> +The Qualcomm Battery Measurement System is found inside of Qualcomm PM8941

Is it Monitoring or Measurment?

> +PMICs. It provides OCV and coulomb counter registers that allow the kernel
> +to infer a capacity level.

s/kernel/OS/

OCV?

> +
> +Required properties:
> +- compatible: Should contain "qcom,pm8941-bms".
> +- reg: Specifies the SPMI address and length of the
> + controller's registers.
> +- interrupts: OCV threshold interrupt.
> +- io-channels: Should contain IIO channel specifier for the
> + ADC channel that reports battery temperature.
> +- io-channel-names: Should contain "temp".
> +- qcom,fcc-temp-legend: An array containing the temperature, in degC,
> + for each column of the FCC lookup table.

What's FCC?

> +- qcom,fcc-lut: An array of FCC values in mah, one entry for each
> + temperature defined in in qcom,fcc-temp-legend.
> +- qcom,ocv-temp-legend: An array containing the temperature, in degC,
> + for each column of the OCV lookup table.
> +- qcom,ocv-capacity-legend: An array containing the capacity for each
> + row of the OCV lookup table.
> +- qcom,ocv-lut: An array of OCV values in mV, one entry for each
> + capacity defined in qcom,ocv-capacity-legend.

Need to specify the sizes of these if not 32-bit.

All these seem to have units, so add unit suffixes as defined in
property-units.txt.

> +
> +Example:
> +
> + pm8941_vadc: vadc@3100 {

adc@...

> + compatible = "qcom,spmi-vadc";
> + reg = <0x3100>;
> + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + #io-channel-cells = <1>;
> +
> + bat_temp {
> + reg = <VADC_LR_MUX1_BAT_THERM>;
> + };
> + };
> +
> + bms@4000 {
> + compatible = "qcom,pm8941-bms";
> + reg = <0x4000>;
> + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "ocv_thr";
> +
> + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
> + io-channel-names = "temp";
> +
> + qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
> + qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
> +
> + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
> + 80 75 70 65
> + 60 55 50 45
> + 40 35 30 25
> + 20 15 10 9
> + 8 7 6 5 4
> + 3 2 1 0>;
> +
> + qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
> + qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
> + 4261 4241 4259 4266 4246
> + 4201 4181 4201 4207 4187
> + 4153 4133 4150 4155 4135
> + 4105 4085 4100 4104 4084
> + 4058 4038 4052 4058 4038
> + 4012 3992 4004 4014 3994
> + 3970 3950 3959 3971 3951
> + 3931 3911 3915 3927 3907
> + 3899 3879 3880 3884 3864
> + 3873 3853 3851 3853 3833
> + 3848 3828 3827 3829 3809
> + 3829 3809 3808 3809 3789
> + 3815 3795 3791 3791 3771
> + 3801 3781 3775 3772 3752
> + 3785 3765 3751 3746 3726
> + 3767 3747 3727 3719 3699
> + 3750 3730 3702 3692 3672
> + 3728 3708 3680 3672 3652
> + 3720 3700 3676 3665 3645
> + 3712 3692 3670 3660 3645
> + 3695 3675 3658 3648 3633
> + 3662 3647 3629 3620 3610
> + 3620 3605 3589 3580 3570
> + 3562 3552 3538 3529 3519
> + 3490 3480 3474 3470 3465
> + 3403 3398 3388 3380 3375
> + 3320 3300 3255 3221 3206
> + 3000 3000 3000 3000 3000>;
> + };
> + };
> +};
> --
> 2.17.0
>

2018-04-13 17:10:32

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings



On 13 April 2018 17:35:27 BST, Rob Herring <[email protected]> wrote:
>On Sat, Apr 07, 2018 at 06:57:45PM +0100, Craig Tatlor wrote:
>> Add bindings for the Qualcomm Battery Monitoring system.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>> ---
>> .../bindings/power/supply/qcom_bms.txt | 93
>+++++++++++++++++++
>> 1 file changed, 93 insertions(+)
>> create mode 100644
>Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>
>> diff --git
>a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> new file mode 100644
>> index 000000000000..6296399edc09
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> @@ -0,0 +1,93 @@
>> +Qualcomm Battery Measurement System
>> +
>> +The Qualcomm Battery Measurement System is found inside of Qualcomm
>PM8941
>
>Is it Monitoring or Measurment?
>
>> +PMICs. It provides OCV and coulomb counter registers that allow the
>kernel
>> +to infer a capacity level.
>
>s/kernel/OS/
>
>OCV?
Open Circuit Voltage - should I expand this?
>
>> +
>> +Required properties:
>> +- compatible: Should contain "qcom,pm8941-bms".
>> +- reg: Specifies the SPMI address and length of
>the
>> + controller's registers.
>> +- interrupts: OCV threshold interrupt.
>> +- io-channels: Should contain IIO channel specifier for
>the
>> + ADC channel that reports battery temperature.
>> +- io-channel-names: Should contain "temp".
>> +- qcom,fcc-temp-legend: An array containing the temperature, in
>degC,
>> + for each column of the FCC lookup table.
>
>What's FCC?
Full charge capacity - Should i also expand this? or maybe explain in header paragraph?
>
>> +- qcom,fcc-lut: An array of FCC values in mah, one entry
>for each
>> + temperature defined in in qcom,fcc-temp-legend.
>> +- qcom,ocv-temp-legend: An array containing the temperature, in
>degC,
>> + for each column of the OCV lookup table.
>> +- qcom,ocv-capacity-legend: An array containing the capacity for
>each
>> + row of the OCV lookup table.
>> +- qcom,ocv-lut: An array of OCV values in mV, one entry
>for each
>> + capacity defined in qcom,ocv-capacity-legend.
>
>Need to specify the sizes of these if not 32-bit.
Right.
>
>All these seem to have units, so add unit suffixes as defined in
>property-units.txt.
Will do.
>
>> +
>> +Example:
>> +
>> + pm8941_vadc: vadc@3100 {
>
>adc@...
Okay.
>
>> + compatible = "qcom,spmi-vadc";
>> + reg = <0x3100>;
>> + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + #io-channel-cells = <1>;
>> +
>> + bat_temp {
>> + reg = <VADC_LR_MUX1_BAT_THERM>;
>> + };
>> + };
>> +
>> + bms@4000 {
>> + compatible = "qcom,pm8941-bms";
>> + reg = <0x4000>;
>> + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
>> + interrupt-names = "ocv_thr";
>> +
>> + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
>> + io-channel-names = "temp";
>> +
>> + qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
>> + qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
>> +
>> + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
>> + 80 75 70 65
>> + 60 55 50 45
>> + 40 35 30 25
>> + 20 15 10 9
>> + 8 7 6 5 4
>> + 3 2 1 0>;
>> +
>> + qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
>> + qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
>> + 4261 4241 4259 4266 4246
>> + 4201 4181 4201 4207 4187
>> + 4153 4133 4150 4155 4135
>> + 4105 4085 4100 4104 4084
>> + 4058 4038 4052 4058 4038
>> + 4012 3992 4004 4014 3994
>> + 3970 3950 3959 3971 3951
>> + 3931 3911 3915 3927 3907
>> + 3899 3879 3880 3884 3864
>> + 3873 3853 3851 3853 3833
>> + 3848 3828 3827 3829 3809
>> + 3829 3809 3808 3809 3789
>> + 3815 3795 3791 3791 3771
>> + 3801 3781 3775 3772 3752
>> + 3785 3765 3751 3746 3726
>> + 3767 3747 3727 3719 3699
>> + 3750 3730 3702 3692 3672
>> + 3728 3708 3680 3672 3652
>> + 3720 3700 3676 3665 3645
>> + 3712 3692 3670 3660 3645
>> + 3695 3675 3658 3648 3633
>> + 3662 3647 3629 3620 3610
>> + 3620 3605 3589 3580 3570
>> + 3562 3552 3538 3529 3519
>> + 3490 3480 3474 3470 3465
>> + 3403 3398 3388 3380 3375
>> + 3320 3300 3255 3221 3206
>> + 3000 3000 3000 3000 3000>;
>> + };
>> + };
>> +};
>> --
>> 2.17.0
>>

2018-04-13 17:12:47

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings



On 13 April 2018 18:08:54 BST, Craig Tatlor <[email protected]> wrote:
>
>
>On 13 April 2018 17:35:27 BST, Rob Herring <[email protected]> wrote:
>>On Sat, Apr 07, 2018 at 06:57:45PM +0100, Craig Tatlor wrote:
>>> Add bindings for the Qualcomm Battery Monitoring system.
>>>
>>> Signed-off-by: Craig Tatlor <[email protected]>
>>> ---
>>> .../bindings/power/supply/qcom_bms.txt | 93
>>+++++++++++++++++++
>>> 1 file changed, 93 insertions(+)
>>> create mode 100644
>>Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>>
>>> diff --git
>>a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>> new file mode 100644
>>> index 000000000000..6296399edc09
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>> @@ -0,0 +1,93 @@
>>> +Qualcomm Battery Measurement System
>>> +
>>> +The Qualcomm Battery Measurement System is found inside of Qualcomm
>>PM8941
>>
>>Is it Monitoring or Measurment?
Monitoring, not sure how I missed that :)
>>
>>> +PMICs. It provides OCV and coulomb counter registers that allow the
>>kernel
>>> +to infer a capacity level.
>>
>>s/kernel/OS/
>>
>>OCV?
>Open Circuit Voltage - should I expand this?
>>
>>> +
>>> +Required properties:
>>> +- compatible: Should contain "qcom,pm8941-bms".
>>> +- reg: Specifies the SPMI address and length
>of
>>the
>>> + controller's registers.
>>> +- interrupts: OCV threshold interrupt.
>>> +- io-channels: Should contain IIO channel specifier
>for
>>the
>>> + ADC channel that reports battery temperature.
>>> +- io-channel-names: Should contain "temp".
>>> +- qcom,fcc-temp-legend: An array containing the temperature, in
>>degC,
>>> + for each column of the FCC lookup table.
>>
>>What's FCC?
>Full charge capacity - Should i also expand this? or maybe explain in
>header paragraph?
>>
>>> +- qcom,fcc-lut: An array of FCC values in mah, one
>entry
>>for each
>>> + temperature defined in in qcom,fcc-temp-legend.
>>> +- qcom,ocv-temp-legend: An array containing the temperature, in
>>degC,
>>> + for each column of the OCV lookup table.
>>> +- qcom,ocv-capacity-legend: An array containing the capacity for
>>each
>>> + row of the OCV lookup table.
>>> +- qcom,ocv-lut: An array of OCV values in mV, one entry
>>for each
>>> + capacity defined in qcom,ocv-capacity-legend.
>>
>>Need to specify the sizes of these if not 32-bit.
>Right.
>>
>>All these seem to have units, so add unit suffixes as defined in
>>property-units.txt.
>Will do.
>>
>>> +
>>> +Example:
>>> +
>>> + pm8941_vadc: vadc@3100 {
>>
>>adc@...
>Okay.
>>
>>> + compatible = "qcom,spmi-vadc";
>>> + reg = <0x3100>;
>>> + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
>>> + #address-cells = <1>;
>>> + #size-cells = <0>;
>>> + #io-channel-cells = <1>;
>>> +
>>> + bat_temp {
>>> + reg = <VADC_LR_MUX1_BAT_THERM>;
>>> + };
>>> + };
>>> +
>>> + bms@4000 {
>>> + compatible = "qcom,pm8941-bms";
>>> + reg = <0x4000>;
>>> + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
>>> + interrupt-names = "ocv_thr";
>>> +
>>> + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
>>> + io-channel-names = "temp";
>>> +
>>> + qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
>>> + qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
>>> +
>>> + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
>>> + 80 75 70 65
>>> + 60 55 50 45
>>> + 40 35 30 25
>>> + 20 15 10 9
>>> + 8 7 6 5 4
>>> + 3 2 1 0>;
>>> +
>>> + qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
>>> + qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
>>> + 4261 4241 4259 4266 4246
>>> + 4201 4181 4201 4207 4187
>>> + 4153 4133 4150 4155 4135
>>> + 4105 4085 4100 4104 4084
>>> + 4058 4038 4052 4058 4038
>>> + 4012 3992 4004 4014 3994
>>> + 3970 3950 3959 3971 3951
>>> + 3931 3911 3915 3927 3907
>>> + 3899 3879 3880 3884 3864
>>> + 3873 3853 3851 3853 3833
>>> + 3848 3828 3827 3829 3809
>>> + 3829 3809 3808 3809 3789
>>> + 3815 3795 3791 3791 3771
>>> + 3801 3781 3775 3772 3752
>>> + 3785 3765 3751 3746 3726
>>> + 3767 3747 3727 3719 3699
>>> + 3750 3730 3702 3692 3672
>>> + 3728 3708 3680 3672 3652
>>> + 3720 3700 3676 3665 3645
>>> + 3712 3692 3670 3660 3645
>>> + 3695 3675 3658 3648 3633
>>> + 3662 3647 3629 3620 3610
>>> + 3620 3605 3589 3580 3570
>>> + 3562 3552 3538 3529 3519
>>> + 3490 3480 3474 3470 3465
>>> + 3403 3398 3388 3380 3375
>>> + 3320 3300 3255 3221 3206
>>> + 3000 3000 3000 3000 3000>;
>>> + };
>>> + };
>>> +};
>>> --
>>> 2.17.0
>>>

2018-04-15 12:57:30

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings

On Fri, Apr 13, 2018 at 11:35:27AM -0500, Rob Herring wrote:
> On Sat, Apr 07, 2018 at 06:57:45PM +0100, Craig Tatlor wrote:
> > Add bindings for the Qualcomm Battery Monitoring system.
> >
> > Signed-off-by: Craig Tatlor <[email protected]>
> > ---
> > .../bindings/power/supply/qcom_bms.txt | 93 +++++++++++++++++++
> > 1 file changed, 93 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> >
> > diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> > new file mode 100644
> > index 000000000000..6296399edc09
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> > @@ -0,0 +1,93 @@
> > +Qualcomm Battery Measurement System
> > +
> > +The Qualcomm Battery Measurement System is found inside of Qualcomm PM8941
>
> Is it Monitoring or Measurment?
>
> > +PMICs. It provides OCV and coulomb counter registers that allow the kernel
> > +to infer a capacity level.
>
> s/kernel/OS/
>
> OCV?
>
> > +
> > +Required properties:
> > +- compatible: Should contain "qcom,pm8941-bms".
> > +- reg: Specifies the SPMI address and length of the
> > + controller's registers.
> > +- interrupts: OCV threshold interrupt.
> > +- io-channels: Should contain IIO channel specifier for the
> > + ADC channel that reports battery temperature.
> > +- io-channel-names: Should contain "temp".
> > +- qcom,fcc-temp-legend: An array containing the temperature, in degC,
> > + for each column of the FCC lookup table.
>
> What's FCC?
>
> > +- qcom,fcc-lut: An array of FCC values in mah, one entry for each
> > + temperature defined in in qcom,fcc-temp-legend.
> > +- qcom,ocv-temp-legend: An array containing the temperature, in degC,
> > + for each column of the OCV lookup table.
> > +- qcom,ocv-capacity-legend: An array containing the capacity for each
> > + row of the OCV lookup table.
> > +- qcom,ocv-lut: An array of OCV values in mV, one entry for each
> > + capacity defined in qcom,ocv-capacity-legend.
>
> Need to specify the sizes of these if not 32-bit.
>
> All these seem to have units, so add unit suffixes as defined in
> property-units.txt.
Should i change code to use microamphours & microvolts or add a new
suffix?
>
> > +
> > +Example:
> > +
> > + pm8941_vadc: vadc@3100 {
>
> adc@...
>
> > + compatible = "qcom,spmi-vadc";
> > + reg = <0x3100>;
> > + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + #io-channel-cells = <1>;
> > +
> > + bat_temp {
> > + reg = <VADC_LR_MUX1_BAT_THERM>;
> > + };
> > + };
> > +
> > + bms@4000 {
> > + compatible = "qcom,pm8941-bms";
> > + reg = <0x4000>;
> > + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
> > + interrupt-names = "ocv_thr";
> > +
> > + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
> > + io-channel-names = "temp";
> > +
> > + qcom,fcc-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
> > + qcom,fcc-lut = /bits/ 16 <6010 6070 6680 6780 6670>;
> > +
> > + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85
> > + 80 75 70 65
> > + 60 55 50 45
> > + 40 35 30 25
> > + 20 15 10 9
> > + 8 7 6 5 4
> > + 3 2 1 0>;
> > +
> > + qcom,ocv-temp-legend = /bits/ 8 <(-10) 0 25 50 65>;
> > + qcom,ocv-lut = /bits/ 16 <4288 4288 4306 4315 4315
> > + 4261 4241 4259 4266 4246
> > + 4201 4181 4201 4207 4187
> > + 4153 4133 4150 4155 4135
> > + 4105 4085 4100 4104 4084
> > + 4058 4038 4052 4058 4038
> > + 4012 3992 4004 4014 3994
> > + 3970 3950 3959 3971 3951
> > + 3931 3911 3915 3927 3907
> > + 3899 3879 3880 3884 3864
> > + 3873 3853 3851 3853 3833
> > + 3848 3828 3827 3829 3809
> > + 3829 3809 3808 3809 3789
> > + 3815 3795 3791 3791 3771
> > + 3801 3781 3775 3772 3752
> > + 3785 3765 3751 3746 3726
> > + 3767 3747 3727 3719 3699
> > + 3750 3730 3702 3692 3672
> > + 3728 3708 3680 3672 3652
> > + 3720 3700 3676 3665 3645
> > + 3712 3692 3670 3660 3645
> > + 3695 3675 3658 3648 3633
> > + 3662 3647 3629 3620 3610
> > + 3620 3605 3589 3580 3570
> > + 3562 3552 3538 3529 3519
> > + 3490 3480 3474 3470 3465
> > + 3403 3398 3388 3380 3375
> > + 3320 3300 3255 3221 3206
> > + 3000 3000 3000 3000 3000>;
> > + };
> > + };
> > +};
> > --
> > 2.17.0
> >

2018-04-18 21:18:41

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] dt-bindings: power: supply: qcom_bms: Add bindings

On Sun, Apr 15, 2018 at 7:55 AM, Craig Tatlor <[email protected]> wrote:
> On Fri, Apr 13, 2018 at 11:35:27AM -0500, Rob Herring wrote:
>> On Sat, Apr 07, 2018 at 06:57:45PM +0100, Craig Tatlor wrote:
>> > Add bindings for the Qualcomm Battery Monitoring system.
>> >
>> > Signed-off-by: Craig Tatlor <[email protected]>
>> > ---
>> > .../bindings/power/supply/qcom_bms.txt | 93 +++++++++++++++++++
>> > 1 file changed, 93 insertions(+)
>> > create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> > new file mode 100644
>> > index 000000000000..6296399edc09
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> > @@ -0,0 +1,93 @@
>> > +Qualcomm Battery Measurement System
>> > +
>> > +The Qualcomm Battery Measurement System is found inside of Qualcomm PM8941
>>
>> Is it Monitoring or Measurment?
>>
>> > +PMICs. It provides OCV and coulomb counter registers that allow the kernel
>> > +to infer a capacity level.
>>
>> s/kernel/OS/
>>
>> OCV?
>>
>> > +
>> > +Required properties:
>> > +- compatible: Should contain "qcom,pm8941-bms".
>> > +- reg: Specifies the SPMI address and length of the
>> > + controller's registers.
>> > +- interrupts: OCV threshold interrupt.
>> > +- io-channels: Should contain IIO channel specifier for the
>> > + ADC channel that reports battery temperature.
>> > +- io-channel-names: Should contain "temp".
>> > +- qcom,fcc-temp-legend: An array containing the temperature, in degC,
>> > + for each column of the FCC lookup table.
>>
>> What's FCC?
>>
>> > +- qcom,fcc-lut: An array of FCC values in mah, one entry for each
>> > + temperature defined in in qcom,fcc-temp-legend.
>> > +- qcom,ocv-temp-legend: An array containing the temperature, in degC,
>> > + for each column of the OCV lookup table.
>> > +- qcom,ocv-capacity-legend: An array containing the capacity for each
>> > + row of the OCV lookup table.
>> > +- qcom,ocv-lut: An array of OCV values in mV, one entry for each
>> > + capacity defined in qcom,ocv-capacity-legend.
>>
>> Need to specify the sizes of these if not 32-bit.
>>
>> All these seem to have units, so add unit suffixes as defined in
>> property-units.txt.
> Should i change code to use microamphours & microvolts or add a new
> suffix?

It is preferred to use the existing ones unless you have some
justification to add new ones.

Rob

2018-04-26 11:36:08

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v4 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

On Sat, Apr 7, 2018 at 7:57 PM, Craig Tatlor <[email protected]> wrote:

Hi Craig! Thanks for your patch!

> This patch adds a driver for the BMS (Battery Monitoring System)
> block of the PM8941 PMIC, it uses a lookup table defined in the
> device tree to generate a capacity from the BMS supplied OCV, it
> then ammends the coulomb counter to that to increase the accuracy
> of the estimated capacity.
>
> Signed-off-by: Craig Tatlor <[email protected]>

Just some minor remarks.

NB: I see that you are writing from a private email address
so if you're working as a hobbyist on your precious sparetime
I have lower expectation on how much work you will put into
this, so see it more as suggestions than demands.

My overall feedback is that for algorithmic charger what
we need is infrastructure. What is currently piling up in
drivers/power/supply scares me a bit in it's lack of
framework and code reuse.

It also scares me because this is vital technology dealing
with physical devices and as such really need to have
modularized reusable reviewed code with several users
and deployments.

Code reuse would include:

- Mathematical helpers such as interpolation of
values from absolute values or tables
Suggestions below!
- State machines and transitions
- CC/CV alorithms (using the above)
- Many other things

Not that *I* can make the situation much better, I'm just
sharing my fears,

> +static s64 sign_extend_s36(uint64_t raw)
> +{
> + raw = raw & CC_36_BIT_MASK;
> +
> + return (raw >> 35) == 0LL ?
> + raw : (SIGN_EXTEND_36_TO_64_MASK | raw);
> +}

#include <linux/bitops.h>

Use sign_extend32()

> +static unsigned int interpolate(int y0, int x0, int y1, int x1, int x)
> +{
> + if (y0 == y1 || x == x0)
> + return y0;
> + if (x1 == x0 || x == x1)
> + return y1;
> +
> + return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
> +}
> +
> +static unsigned int between(int left, int right, int val)
> +{
> + if (left <= val && val <= right)
> + return 1;
> +
> + return 0;
> +}

How are these things not library functions?

Every cell of my brain says this code should be reusable.

Can you put this in <linux/fixp-arith.h>?

I bet a million to one that the video people will sooner or later
need linear interpolation and there are more users in the kernel
than drivers/power/, certainly drivers/iio as well.

If noone else says anything I vote to put at least the linear
interpolation into <linux/fixp-arith.h> with a bonus if you
move some of the current users in drivers/power over
while you're at it.

> +static unsigned int interpolate_capacity(int temp, u16 ocv,
> + struct bms_ocv_lut ocv_lut)
> +{
> + unsigned int pcj_minus_one = 0, pcj = 0;
> + int i, j;
> +
> + for (j = 0; j < TEMPERATURE_COLS; j++)
> + if (temp <= ocv_lut.temp_legend[j])
> + break;
> +
> + if (ocv >= ocv_lut.lut[0][j])
> + return ocv_lut.capacity_legend[0];
> +
> + if (ocv <= ocv_lut.lut[ocv_lut.rows - 1][j - 1])
> + return ocv_lut.capacity_legend[ocv_lut.rows - 1];
> +
> + for (i = 0; i < ocv_lut.rows - 1; i++) {
> + if (pcj == 0 && between(ocv_lut.lut[i][j],
> + ocv_lut.lut[i+1][j], ocv))
> + pcj = interpolate(ocv_lut.capacity_legend[i],
> + ocv_lut.lut[i][j],
> + ocv_lut.capacity_legend[i + 1],
> + ocv_lut.lut[i+1][j],
> + ocv);
> +
> + if (pcj_minus_one == 0 && between(ocv_lut.lut[i][j-1],
> + ocv_lut.lut[i+1][j-1], ocv))
> + pcj_minus_one = interpolate(ocv_lut.capacity_legend[i],
> + ocv_lut.lut[i][j-1],
> + ocv_lut.capacity_legend[i + 1],
> + ocv_lut.lut[i+1][j-1],
> + ocv);
> +
> + if (pcj && pcj_minus_one)
> + return interpolate(pcj_minus_one,
> + ocv_lut.temp_legend[j-1],
> + pcj,
> + ocv_lut.temp_legend[j],
> + temp);
> + }

This code really needs some comments to tell what is going on
here. Also I sense that you can break out a smaller function
for interpolation based on table values, such as a function
that would take a standard format of tables, look up where we
are in that table and interpolate from the neighboring values.

People can then later go in and refine the algorithms if they
e.g. want to introduce spline or RMS interpolation instead
and we can get better interpolation for everybody.

> +static unsigned long interpolate_fcc(int temp, struct bms_fcc_lut fcc_lut)
> +{
> + int i, fcc_mv;
> +
> + for (i = 0; i < TEMPERATURE_COLS; i++)
> + if (temp <= fcc_lut.temp_legend[i])
> + break;
> +
> + fcc_mv = interpolate(fcc_lut.lut[i - 1],
> + fcc_lut.temp_legend[i - 1],
> + fcc_lut.lut[i],
> + fcc_lut.temp_legend[i],
> + temp);
> +
> + return fcc_mv * 10000;
> +}

So then only this would really remain: pass a table and interpolate.

> +static int bms_lock_output_data(struct bms_device_info *di)
> +{
> + int ret;
> +
> + ret = regmap_update_bits(di->regmap, di->base_addr +
> + REG_BMS_CC_DATA_CTL,
> + BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to lock bms output: %d", ret);
> + return ret;
> + }

Reuse of regmap is very nice, thanks for doing it this way.

> +static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
> +static void bms_reset_cc(struct bms_device_info *di)

These indeed need to be mostly hardware-specific so they
are fine.

> +static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
> +{
> + unsigned long ocv_capacity, fcc;
> + int ret, temp, temp_degc;
> + s64 cc, capacity_nodiv;
> +
> + ret = iio_read_channel_raw(di->adc, &temp);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read temperature: %d", ret);
> + return ret;
> + }

Very nice that you use IIO ADC as a back-end.

> + temp_degc = (temp + 500) / 1000;

That deserves a comment I think. Like what the manual
says about this and why the raw temperature is given
like this.

Maybe you want to use DIV_ROUND_CLOSEST()
or DIV_ROUND_UP() from <linux/kernel.h> instead
of just "/"?

Maybe you want to use that in other places too like
the below divisions.

> + ret = bms_read_cc(di, &cc);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read coulomb counter: %d", ret);
> + return ret;
> + }
> +
> + ocv_capacity = interpolate_capacity(temp_degc, (di->ocv + 5) / 10,
> + di->ocv_lut);
> + fcc = interpolate_fcc(temp_degc, di->fcc_lut);
> +
> + capacity_nodiv = ((fcc * ocv_capacity) / 100 - cc) * 100;
> + *capacity = div64_ul(capacity_nodiv, fcc);

So I guess you fit the capacity between 0..100, please
add some comment on what's going on here.

> +static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
> +{
> + struct bms_device_info *di = dev_id;
> +
> + if (bms_read_ocv(di, &di->ocv) < 0)
> + return IRQ_HANDLED;
> +
> + bms_reset_cc(di);
> + return IRQ_HANDLED;
> +}

So that is a coloumb counter interrupt? Please add some
comment on when this gets called. Is it called whenever
a coloumb is added/removed from the battery?

> + ret = of_property_read_u8_array(di->dev->of_node,
> + "qcom,ocv-temp-legend",
> + (u8 *)di->ocv_lut.temp_legend,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no ocv temperature legend found");
> + return ret;
> + }
> +
> + di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
> + "qcom,ocv-capacity-legend",
> + di->ocv_lut.capacity_legend, 0,
> + MAX_CAPACITY_ROWS);
> + if (di->ocv_lut.rows < 0) {
> + dev_err(di->dev, "no ocv capacity legend found");
> + return ret;
> + }
> +
> + ret = of_property_read_variable_u16_array(di->dev->of_node,
> + "qcom,ocv-lut",
> + (u16 *)di->ocv_lut.lut,
> + TEMPERATURE_COLS,
> + TEMPERATURE_COLS *
> + MAX_CAPACITY_ROWS);
> + if (ret < 0) {
> + dev_err(di->dev, "no ocv lut array found");
> + return ret;
> + }
> +
> + ret = of_property_read_u8_array(di->dev->of_node,
> + "qcom,fcc-temp-legend",
> + (u8 *)di->fcc_lut.temp_legend,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no fcc temperature legend found");
> + return ret;
> + }
> +
> + ret = of_property_read_u16_array(di->dev->of_node,
> + "qcom,fcc-lut",
> + di->fcc_lut.lut,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no fcc lut array found");
> + return ret;
> + }

These tables (that I also suggest to use libraries to parse)
should probably have standardized DT names so other
battery drivers can use the same properties and we can
use the same DT parsing code for all.

> + ret = bms_read_ocv(di, &di->ocv);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read initial ocv: %d", ret);
> + return ret;
> + }

OCV = original coloumb counter value?

Please expand the acronym somewhere because I get
a bit lost.

Overall it is a very nicely coded driver. My worries are
all about code reuse, not code quality per se.

Yours,
Linus Walleij

2018-04-30 18:07:11

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v4 1/3] power: supply: Add support for the Qualcomm Battery Monitoring System

Thanks for review, replies inline.

On Thu, Apr 26, 2018 at 01:34:00PM +0200, Linus Walleij wrote:
> On Sat, Apr 7, 2018 at 7:57 PM, Craig Tatlor <[email protected]> wrote:
>
> Hi Craig! Thanks for your patch!
>
> > This patch adds a driver for the BMS (Battery Monitoring System)
> > block of the PM8941 PMIC, it uses a lookup table defined in the
> > device tree to generate a capacity from the BMS supplied OCV, it
> > then ammends the coulomb counter to that to increase the accuracy
> > of the estimated capacity.
> >
> > Signed-off-by: Craig Tatlor <[email protected]>
>
> Just some minor remarks.
>
> NB: I see that you are writing from a private email address
> so if you're working as a hobbyist on your precious sparetime
> I have lower expectation on how much work you will put into
> this, so see it more as suggestions than demands.
Yeah, I am a just hobbyist :)
>
> My overall feedback is that for algorithmic charger what
> we need is infrastructure. What is currently piling up in
> drivers/power/supply scares me a bit in it's lack of
> framework and code reuse.
>
> It also scares me because this is vital technology dealing
> with physical devices and as such really need to have
> modularized reusable reviewed code with several users
> and deployments.
>
> Code reuse would include:
>
> - Mathematical helpers such as interpolation of
> values from absolute values or tables
> Suggestions below!
> - State machines and transitions
> - CC/CV alorithms (using the above)
> - Many other things
>
> Not that *I* can make the situation much better, I'm just
> sharing my fears,
>
> > +static s64 sign_extend_s36(uint64_t raw)
> > +{
> > + raw = raw & CC_36_BIT_MASK;
> > +
> > + return (raw >> 35) == 0LL ?
> > + raw : (SIGN_EXTEND_36_TO_64_MASK | raw);
> > +}
>
> #include <linux/bitops.h>
>
> Use sign_extend32()
Right.
>
> > +static unsigned int interpolate(int y0, int x0, int y1, int x1, int x)
> > +{
> > + if (y0 == y1 || x == x0)
> > + return y0;
> > + if (x1 == x0 || x == x1)
> > + return y1;
> > +
> > + return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
> > +}
> > +
> > +static unsigned int between(int left, int right, int val)
> > +{
> > + if (left <= val && val <= right)
> > + return 1;
> > +
> > + return 0;
> > +}
>
> How are these things not library functions?
>
> Every cell of my brain says this code should be reusable.
>
> Can you put this in <linux/fixp-arith.h>?
>
> I bet a million to one that the video people will sooner or later
> need linear interpolation and there are more users in the kernel
> than drivers/power/, certainly drivers/iio as well.
>
> If noone else says anything I vote to put at least the linear
> interpolation into <linux/fixp-arith.h> with a bonus if you
> move some of the current users in drivers/power over
> while you're at it.
I was pretty surprised there wasn't a library function for it
aswell, i will add it there.
>
> > +static unsigned int interpolate_capacity(int temp, u16 ocv,
> > + struct bms_ocv_lut ocv_lut)
> > +{
> > + unsigned int pcj_minus_one = 0, pcj = 0;
> > + int i, j;
> > +
> > + for (j = 0; j < TEMPERATURE_COLS; j++)
> > + if (temp <= ocv_lut.temp_legend[j])
> > + break;
> > +
> > + if (ocv >= ocv_lut.lut[0][j])
> > + return ocv_lut.capacity_legend[0];
> > +
> > + if (ocv <= ocv_lut.lut[ocv_lut.rows - 1][j - 1])
> > + return ocv_lut.capacity_legend[ocv_lut.rows - 1];
> > +
> > + for (i = 0; i < ocv_lut.rows - 1; i++) {
> > + if (pcj == 0 && between(ocv_lut.lut[i][j],
> > + ocv_lut.lut[i+1][j], ocv))
> > + pcj = interpolate(ocv_lut.capacity_legend[i],
> > + ocv_lut.lut[i][j],
> > + ocv_lut.capacity_legend[i + 1],
> > + ocv_lut.lut[i+1][j],
> > + ocv);
> > +
> > + if (pcj_minus_one == 0 && between(ocv_lut.lut[i][j-1],
> > + ocv_lut.lut[i+1][j-1], ocv))
> > + pcj_minus_one = interpolate(ocv_lut.capacity_legend[i],
> > + ocv_lut.lut[i][j-1],
> > + ocv_lut.capacity_legend[i + 1],
> > + ocv_lut.lut[i+1][j-1],
> > + ocv);
> > +
> > + if (pcj && pcj_minus_one)
> > + return interpolate(pcj_minus_one,
> > + ocv_lut.temp_legend[j-1],
> > + pcj,
> > + ocv_lut.temp_legend[j],
> > + temp);
> > + }
>
> This code really needs some comments to tell what is going on
> here. Also I sense that you can break out a smaller function
> for interpolation based on table values, such as a function
> that would take a standard format of tables, look up where we
> are in that table and interpolate from the neighboring values.
Yeah, ill add some comments.
Tbh i'm not really sure how that would work as I interpolate from
values at several different indecies, can you expand ont this?
>
> People can then later go in and refine the algorithms if they
> e.g. want to introduce spline or RMS interpolation instead
> and we can get better interpolation for everybody.
>
> > +static unsigned long interpolate_fcc(int temp, struct bms_fcc_lut fcc_lut)
> > +{
> > + int i, fcc_mv;
> > +
> > + for (i = 0; i < TEMPERATURE_COLS; i++)
> > + if (temp <= fcc_lut.temp_legend[i])
> > + break;
> > +
> > + fcc_mv = interpolate(fcc_lut.lut[i - 1],
> > + fcc_lut.temp_legend[i - 1],
> > + fcc_lut.lut[i],
> > + fcc_lut.temp_legend[i],
> > + temp);
> > +
> > + return fcc_mv * 10000;
> > +}
>
> So then only this would really remain: pass a table and interpolate.
>
> > +static int bms_lock_output_data(struct bms_device_info *di)
> > +{
> > + int ret;
> > +
> > + ret = regmap_update_bits(di->regmap, di->base_addr +
> > + REG_BMS_CC_DATA_CTL,
> > + BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
> > + if (ret < 0) {
> > + dev_err(di->dev, "failed to lock bms output: %d", ret);
> > + return ret;
> > + }
>
> Reuse of regmap is very nice, thanks for doing it this way.
>
> > +static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
> > +static void bms_reset_cc(struct bms_device_info *di)
>
> These indeed need to be mostly hardware-specific so they
> are fine.
>
Thanks :)
> > +static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
> > +{
> > + unsigned long ocv_capacity, fcc;
> > + int ret, temp, temp_degc;
> > + s64 cc, capacity_nodiv;
> > +
> > + ret = iio_read_channel_raw(di->adc, &temp);
> > + if (ret < 0) {
> > + dev_err(di->dev, "failed to read temperature: %d", ret);
> > + return ret;
> > + }
>
> Very nice that you use IIO ADC as a back-end.
>
> > + temp_degc = (temp + 500) / 1000;
>
> That deserves a comment I think. Like what the manual
> says about this and why the raw temperature is given
> like this.
>
> Maybe you want to use DIV_ROUND_CLOSEST()
> or DIV_ROUND_UP() from <linux/kernel.h> instead
> of just "/"?
>
> Maybe you want to use that in other places too like
> the below divisions.
That was just converting it to celcius, adding 500 to round it.
I'll skip that and make bindings use millicelcius.
>
> > + ret = bms_read_cc(di, &cc);
> > + if (ret < 0) {
> > + dev_err(di->dev, "failed to read coulomb counter: %d", ret);
> > + return ret;
> > + }
> > +
> > + ocv_capacity = interpolate_capacity(temp_degc, (di->ocv + 5) / 10,
> > + di->ocv_lut);
> > + fcc = interpolate_fcc(temp_degc, di->fcc_lut);
> > +
> > + capacity_nodiv = ((fcc * ocv_capacity) / 100 - cc) * 100;
> > + *capacity = div64_ul(capacity_nodiv, fcc);
>
> So I guess you fit the capacity between 0..100, please
> add some comment on what's going on here.
Basically,
1. Read coulomb counter delta since last ocv update
2. Interpolate open circuit voltage (ocv) and full charge capacity (fcc)
3. Math just ammends the coulomb counter delta to the last taken ocv
reading, Used the nodiv variable to make it a bit more but i could
probably just take that out.

Will add something like this in code.
>
> > +static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
> > +{
> > + struct bms_device_info *di = dev_id;
> > +
> > + if (bms_read_ocv(di, &di->ocv) < 0)
> > + return IRQ_HANDLED;
> > +
> > + bms_reset_cc(di);
> > + return IRQ_HANDLED;
> > +}
>
> So that is a coloumb counter interrupt? Please add some
> comment on when this gets called. Is it called whenever
> a coloumb is added/removed from the battery?
Its called whenever a new open circuit voltage reading happens, which
only occurs when device us using very little power (probably below 10mA).
The coulomb counter is reset because its kept as a delta.
>
> > + ret = of_property_read_u8_array(di->dev->of_node,
> > + "qcom,ocv-temp-legend",
> > + (u8 *)di->ocv_lut.temp_legend,
> > + TEMPERATURE_COLS);
> > + if (ret < 0) {
> > + dev_err(di->dev, "no ocv temperature legend found");
> > + return ret;
> > + }
> > +
> > + di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
> > + "qcom,ocv-capacity-legend",
> > + di->ocv_lut.capacity_legend, 0,
> > + MAX_CAPACITY_ROWS);
> > + if (di->ocv_lut.rows < 0) {
> > + dev_err(di->dev, "no ocv capacity legend found");
> > + return ret;
> > + }
> > +
> > + ret = of_property_read_variable_u16_array(di->dev->of_node,
> > + "qcom,ocv-lut",
> > + (u16 *)di->ocv_lut.lut,
> > + TEMPERATURE_COLS,
> > + TEMPERATURE_COLS *
> > + MAX_CAPACITY_ROWS);
> > + if (ret < 0) {
> > + dev_err(di->dev, "no ocv lut array found");
> > + return ret;
> > + }
> > +
> > + ret = of_property_read_u8_array(di->dev->of_node,
> > + "qcom,fcc-temp-legend",
> > + (u8 *)di->fcc_lut.temp_legend,
> > + TEMPERATURE_COLS);
> > + if (ret < 0) {
> > + dev_err(di->dev, "no fcc temperature legend found");
> > + return ret;
> > + }
> > +
> > + ret = of_property_read_u16_array(di->dev->of_node,
> > + "qcom,fcc-lut",
> > + di->fcc_lut.lut,
> > + TEMPERATURE_COLS);
> > + if (ret < 0) {
> > + dev_err(di->dev, "no fcc lut array found");
> > + return ret;
> > + }
>
> These tables (that I also suggest to use libraries to parse)
> should probably have standardized DT names so other
> battery drivers can use the same properties and we can
> use the same DT parsing code for all.
Okay, any recommendations on names?
>
> > + ret = bms_read_ocv(di, &di->ocv);
> > + if (ret < 0) {
> > + dev_err(di->dev, "failed to read initial ocv: %d", ret);
> > + return ret;
> > + }
>
> OCV = original coloumb counter value?
Nope, open circuit voltage.
>
> Please expand the acronym somewhere because I get
> a bit lost.
Will do.
>
> Overall it is a very nicely coded driver. My worries are
> all about code reuse, not code quality per se.
Thanks!
>
> Yours,
> Linus Walleij

2018-06-07 19:08:40

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v5 1/4] fixp-arith: add a linear interpolation function

Adds a function to interpolate against two points,
this is carried arount as a helper function by tons of drivers.

Signed-off-by: Craig Tatlor <[email protected]>
---
include/linux/fixp-arith.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
index d4686fe1cac7..c21de4f358dd 100644
--- a/include/linux/fixp-arith.h
+++ b/include/linux/fixp-arith.h
@@ -153,4 +153,24 @@ static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
#define fixp_cos32_rad(rad, twopi) \
fixp_sin32_rad(rad + twopi / 4, twopi)

+
+/**
+ * fixp_linear_interpolate() - interpolates a value from two known points
+ *
+ * @x0: x value of point 0
+ * @y0: y value of point 0
+ * @x1: x value of point 1
+ * @y1: y value of point 1
+ * @x: the linear interpolant
+ */
+static inline int fixp_linear_interpolate(int x0, int y0, int x1, int y1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
#endif
--
2.17.0


2018-06-07 19:08:41

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v5 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

This patch adds a driver for the BMS (Battery Monitoring System)
block of the PM8941 PMIC, it uses a lookup table defined in the
device tree to generate a capacity from the BMS supplied OCV, it
then ammends the coulomb counter to that to increase the accuracy
of the estimated capacity.

Signed-off-by: Craig Tatlor <[email protected]>
---
* Changes from v4:
Cleaned up percentage interpolation function,
uses new fixp interpolation helper,
added some more error cases,
uses devm_power_supply_register(),
uses a DIV_ROUND_CLOSEST for division and
uses micro(volts / amp hours) instead of
milli (volts / amp hours).

drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/qcom_bms.c | 487 ++++++++++++++++++++++++++++++++
3 files changed, 497 insertions(+)
create mode 100644 drivers/power/supply/qcom_bms.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..6c354c37bc55 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -82,6 +82,15 @@ config BATTERY_ACT8945A
Say Y here to enable support for power supply provided by
Active-semi ActivePath ACT8945A charger.

+config BATTERY_BMS
+ tristate "Qualcomm Battery Monitoring System driver"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ depends on REGMAP_SPMI
+ help
+ Say Y to include support for the Battery Monitoring hardware
+ found in some Qualcomm PM series PMICs.
+
config BATTERY_CPCAP
tristate "Motorola CPCAP PMIC battery driver"
depends on MFD_CPCAP && IIO
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..04204174b047 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
+obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
new file mode 100644
index 000000000000..e1d6fdbf11d1
--- /dev/null
+++ b/drivers/power/supply/qcom_bms.c
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: GPL
+
+/*
+ * Qualcomm Battery Monitoring System driver
+ *
+ * Copyright (C) 2018 Craig Tatlor <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/fixp-arith.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/iio/consumer.h>
+
+#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
+#define REG_BMS_SHDW_CC_DATA0 0xA8
+#define REG_BMS_CC_DATA_CTL 0x42
+#define REG_BMS_CC_CLEAR_CTL 0x4
+
+#define BMS_HOLD_OREG_DATA BIT(0)
+#define BMS_CLEAR_SHDW_CC BIT(6)
+
+#define BMS_CC_READING_RESOLUTION_N 542535
+#define BMS_CC_READING_RESOLUTION_D 10000
+#define BMS_CC_READING_TICKS 56
+#define BMS_SLEEP_CLK_HZ 32764
+
+#define SECONDS_PER_HOUR 3600
+#define TEMPERATURE_COLS 5
+#define MAX_CAPACITY_ROWS 50
+
+/* lookup table for ocv -> capacity conversion */
+struct bms_ocv_lut {
+ int rows;
+ s8 temp_legend[TEMPERATURE_COLS];
+ u8 capacity_legend[MAX_CAPACITY_ROWS];
+ u32 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
+};
+
+/* lookup table for battery temperature -> fcc conversion */
+struct bms_fcc_lut {
+ s8 temp_legend[TEMPERATURE_COLS];
+ u32 lut[TEMPERATURE_COLS];
+};
+
+struct bms_device_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct bms_ocv_lut ocv_lut;
+ struct power_supply_desc bat_desc;
+ struct bms_fcc_lut fcc_lut;
+ struct iio_channel *adc;
+ struct mutex bms_output_lock;
+ u32 base_addr;
+
+ int ocv_thr_irq;
+ u32 ocv;
+};
+
+static bool between(int left, int right, int val)
+{
+ if (left <= val && val <= right)
+ return true;
+
+ if (left >= val && val >= right)
+ return true;
+
+ return false;
+}
+
+static int interpolate_capacity(int temp, u32 ocv,
+ struct bms_ocv_lut *ocv_lut)
+{
+ int pcj_minus_one = 0, pcj = 0, i2 = 0, i3 = 0, i, j;
+
+ for (j = 0; j < TEMPERATURE_COLS; j++)
+ if (temp <= ocv_lut->temp_legend[j])
+ break;
+
+ if (ocv >= ocv_lut->lut[0][j])
+ return ocv_lut->capacity_legend[0];
+
+ if (ocv <= ocv_lut->lut[ocv_lut->rows-1][j-1])
+ return ocv_lut->capacity_legend[ocv_lut->rows-1];
+
+ for (i = 0; i < ocv_lut->rows-1; i++) {
+ if (between(ocv_lut->lut[i][j],
+ ocv_lut->lut[i+1][j], ocv))
+ i2 = i;
+
+ if (between(ocv_lut->lut[i][j-1],
+ ocv_lut->lut[i+1][j-1], ocv))
+ i3 = i;
+ }
+
+ /* interpolate two capacities */
+ pcj = fixp_linear_interpolate(ocv_lut->lut[i2][j],
+ ocv_lut->capacity_legend[i2],
+ ocv_lut->lut[i2+1][j],
+ ocv_lut->capacity_legend[i2+1],
+ ocv);
+
+ pcj_minus_one = fixp_linear_interpolate(ocv_lut->lut[i3][j-1],
+ ocv_lut->capacity_legend[i3],
+ ocv_lut->lut[i3+1][j-1],
+ ocv_lut->capacity_legend[i3+1],
+ ocv);
+
+ /* interpolate them with the battery temperature */
+ return fixp_linear_interpolate(ocv_lut->temp_legend[j-1],
+ pcj_minus_one,
+ ocv_lut->temp_legend[j],
+ pcj,
+ temp);
+}
+
+static int interpolate_fcc(int temp, struct bms_fcc_lut *fcc_lut)
+{
+ int i;
+
+ for (i = 0; i < TEMPERATURE_COLS; i++)
+ if (temp <= fcc_lut->temp_legend[i])
+ break;
+
+ return fixp_linear_interpolate(fcc_lut->temp_legend[i-1],
+ fcc_lut->lut[i-1],
+ fcc_lut->temp_legend[i],
+ fcc_lut->lut[i],
+ temp);
+}
+
+static int bms_lock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
+ if (ret) {
+ dev_err(di->dev, "failed to lock bms output: %d", ret);
+ return ret;
+ }
+
+ /*
+ * Sleep for at least 100 microseconds here to make sure
+ * there has been at least three cycles of the sleep clock
+ * so that the registers are correctly locked.
+ */
+ usleep_range(100, 1000);
+
+ return 0;
+}
+
+static int bms_unlock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, 0);
+ if (ret) {
+ dev_err(di->dev, "failed to unlock bms output: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bms_read_ocv(struct bms_device_info *di, u32 *ocv)
+{
+ int ret;
+ u16 read_ocv;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr+
+ REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
+ if (ret) {
+ dev_err(di->dev, "open circuit voltage read failed: %d", ret);
+ goto err_read;
+ }
+
+ dev_dbg(di->dev, "read open circuit voltage of: %d mv", read_ocv);
+
+
+ *ocv = read_ocv * 1000;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
+{
+ int ret;
+ s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_SHDW_CC_DATA0,
+ &cc_raw_s36, 5);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter read failed: %d", ret);
+ goto err_read;
+ }
+
+ ret = bms_unlock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ mutex_unlock(&di->bms_output_lock);
+
+ cc_raw = sign_extend32(cc_raw_s36, 28);
+
+ /* convert raw to uv */
+ cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
+ BMS_CC_READING_RESOLUTION_D);
+
+ /* convert uv to pvh */
+ cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
+ BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR);
+
+ /* divide by impedance */
+ *cc_uah = div_s64(cc_pvh, 10000);
+
+ dev_dbg(di->dev, "read coulomb counter value of: %lld uah", *cc_uah);
+
+ return 0;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static void bms_reset_cc(struct bms_device_info *di)
+{
+ int ret;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC,
+ BMS_CLEAR_SHDW_CC);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter reset failed: %d", ret);
+ goto err_lock;
+ }
+
+ /* wait at least three sleep cycles for cc to reset */
+ usleep_range(100, 1000);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC, 0);
+ if (ret)
+ dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+}
+
+static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
+{
+ unsigned long fcc;
+ int ret, temp, ocv_capacity, temp_degc;
+ s64 cc = 0;
+
+ ret = iio_read_channel_raw(di->adc, &temp);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp_degc = DIV_ROUND_CLOSEST(temp, 1000);
+
+ ret = bms_read_cc(di, &cc);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read coulomb counter: %d", ret);
+ return ret;
+ }
+
+ /* interpolate capacity from open circuit voltage */
+ ocv_capacity = interpolate_capacity(temp_degc, di->ocv,
+ &di->ocv_lut);
+
+ /* interpolate the full charge capacity from temperature */
+ fcc = interpolate_fcc(temp_degc, &di->fcc_lut);
+
+ /* append coloumb counter to capacity */
+ *capacity = DIV_ROUND_CLOSEST(fcc * ocv_capacity, 100);
+ *capacity = div_s64((*capacity - cc) * 100, fcc);
+
+ return 0;
+}
+
+
+
+/*
+ * Return power_supply property
+ */
+static int bms_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bms_device_info *di = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bms_calculate_capacity(di, &val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (val->intval == INT_MAX || val->intval == INT_MIN)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static enum power_supply_property bms_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
+{
+ struct bms_device_info *di = dev_id;
+
+ if (bms_read_ocv(di, &di->ocv) < 0)
+ return IRQ_HANDLED;
+
+ bms_reset_cc(di);
+ return IRQ_HANDLED;
+}
+
+static int bms_probe(struct platform_device *pdev)
+{
+ struct power_supply_config psy_cfg = {};
+ struct bms_device_info *di;
+ struct power_supply *bat;
+ int ret;
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->dev = &pdev->dev;
+
+ di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!di->regmap) {
+ dev_err(di->dev, "Unable to get regmap");
+ return -EINVAL;
+ }
+
+ di->adc = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(di->adc))
+ return PTR_ERR(di->adc);
+
+ ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,ocv-temp-legend-celsius",
+ (u8 *)di->ocv_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage temperature legend found");
+ return ret;
+ }
+
+ di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
+ "qcom,ocv-capacity-legend",
+ di->ocv_lut.capacity_legend, 0,
+ MAX_CAPACITY_ROWS);
+ if (di->ocv_lut.rows < 0) {
+ dev_err(di->dev, "no open circuit voltage capacity legend found");
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(di->dev->of_node,
+ "qcom,ocv-lut-microvolt",
+ (u32 *)di->ocv_lut.lut,
+ TEMPERATURE_COLS,
+ TEMPERATURE_COLS *
+ MAX_CAPACITY_ROWS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage lut array found");
+ return ret;
+ }
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,fcc-temp-legend-celsius",
+ (u8 *)di->fcc_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity temperature legend found");
+ return ret;
+ }
+
+ ret = of_property_read_u32_array(di->dev->of_node,
+ "qcom,fcc-lut-microamp-hours",
+ di->fcc_lut.lut,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity lut array found");
+ return ret;
+ }
+
+ ret = bms_read_ocv(di, &di->ocv);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read initial open circuit voltage: %d",
+ ret);
+ return ret;
+ }
+
+ mutex_init(&di->bms_output_lock);
+
+ di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
+
+ ret = devm_request_threaded_irq(di->dev, di->ocv_thr_irq, NULL,
+ bms_ocv_thr_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ pdev->name, di);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to request handler for open circuit voltage threshold IRQ");
+ return ret;
+ }
+
+
+ di->bat_desc.name = "bms";
+ di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat_desc.properties = bms_props;
+ di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
+ di->bat_desc.get_property = bms_get_property;
+
+ psy_cfg.drv_data = di;
+ bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+
+ return PTR_ERR_OR_ZERO(bat);
+}
+
+static const struct of_device_id bms_of_match[] = {
+ {.compatible = "qcom,pm8941-bms", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bms_of_match);
+
+static struct platform_driver bms_driver = {
+ .probe = bms_probe,
+ .driver = {
+ .name = "qcom-bms",
+ .of_match_table = of_match_ptr(bms_of_match),
+ },
+};
+module_platform_driver(bms_driver);
+
+MODULE_AUTHOR("Craig Tatlor <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm BMS driver");
+MODULE_LICENSE("GPL");
--
2.17.0


2018-06-07 19:09:09

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v5 4/4] MAINTAINERS: Add entry for the Qualcomm BMS

Signed-off-by: Craig Tatlor <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c125f705f78..be485caf9313 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11646,6 +11646,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/

+QUALCOMM BATTERY MONITORING SYSTEM
+M: Craig Tatlor <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/power/supply/qcom_bms.c
+
QUALCOMM CAMERA SUBSYSTEM DRIVER
M: Todor Tomov <[email protected]>
L: [email protected]
--
2.17.0


2018-06-07 19:09:41

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v5 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Add bindings for the Qualcomm Battery Monitoring system.

Signed-off-by: Craig Tatlor <[email protected]>
---
* Changes from v4:
Uses proper units and expands some definitions,
along with changing vadc@ to adc@.

.../bindings/power/supply/qcom_bms.txt | 91 +++++++++++++++++++
1 file changed, 91 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt

diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
new file mode 100644
index 000000000000..a1a32d6ab460
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
@@ -0,0 +1,91 @@
+Qualcomm Battery Monitoring System
+
+The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
+PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
+that allow the OS to infer a capacity level.
+
+Required properties:
+- compatible: Should contain "qcom,pm8941-bms".
+- reg: Specifies the SPMI address and length of the
+ controller's registers.
+- interrupts: OCV threshold interrupt.
+- io-channels: Should contain IIO channel specifier for the
+ ADC channel that reports battery temperature.
+- io-channel-names: Should contain "temp".
+- qcom,fcc-temp-legend-celcius: An array containing the temperature, in degC,
+ for each column of the full charge capacity
+ lookup table.
+- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uah,
+ one entry for each temperature defined in in
+ qcom,fcc-temp-legend-celcius.
+- qcom,ocv-temp-legend-celcius: An array containing the temperature, in degC,
+ for each column of the OCV lookup table.
+- qcom,ocv-capacity-legend: An array containing the capacity for each
+ row of the OCV lookup table.
+- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
+ capacity defined in qcom,ocv-capacity-legend.
+
+Example:
+ pm8941_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
+ };
+
+ bms@4000 {
+ compatible = "qcom,pm8941-bms";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ocv_thr";
+
+ io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
+ io-channel-names = "temp";
+
+ qcom,fcc-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,fcc-lut-microamp-hours = <3230000 3260000 3380000 3410000 3360000>;
+
+ qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75
+ 70 65 60 55 50 45
+ 40 35 30 25 20 15
+ 10 9 8 7 6 5 4 3 2
+ 1 0>;
+ qcom,ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,ocv-lut-microvolt = <43050000 43050000 43030000 42990000 42950000
+ 42770000 42570000 42550000 42510000 42310000
+ 42180000 41980000 41970000 41920000 41720000
+ 41590000 41390000 41450000 41400000 41200000
+ 41010000 40810000 40920000 40890000 40690000
+ 40480000 40280000 40440000 40420000 40220000
+ 40040000 39840000 40010000 39980000 39780000
+ 39620000 39420000 39550000 39560000 39360000
+ 39210000 39010000 39090000 39160000 38960000
+ 38830000 38630000 38740000 38790000 38590000
+ 38550000 38350000 38440000 38430000 38230000
+ 38310000 38110000 38230000 38180000 37980000
+ 38190000 37990000 38040000 38000000 37800000
+ 38060000 37860000 37900000 37840000 37640000
+ 37890000 37690000 37770000 37660000 37460000
+ 37720000 37520000 37560000 37450000 37250000
+ 37480000 37280000 37290000 37250000 37050000
+ 37240000 37040000 37020000 36990000 36790000
+ 37030000 36830000 36730000 36700000 36500000
+ 36940000 36740000 36670000 36640000 36440000
+ 36850000 36650000 36600000 36590000 36390000
+ 36750000 36550000 36520000 36550000 36350000
+ 36690000 36490000 36380000 36400000 36200000
+ 36460000 36260000 36180000 36120000 35920000
+ 36080000 35880000 35680000 35640000 35440000
+ 35510000 35310000 35050000 35020000 34820000
+ 34730000 34530000 34300000 34250000 34050000
+ 33870000 33670000 33040000 32820000 32620000
+ 30000000 30000000 30000000 30000000 30000000>;
+ };
+ };
+};
--
2.17.0


2018-06-07 19:13:34

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH v5 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

On 06/07/2018 11:12 AM, Craig Tatlor wrote:
> This patch adds a driver for the BMS (Battery Monitoring System)
> block of the PM8941 PMIC, it uses a lookup table defined in the
> device tree to generate a capacity from the BMS supplied OCV, it
> then ammends the coulomb counter to that to increase the accuracy

amends

> of the estimated capacity.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---

> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index 428b426842f4..6c354c37bc55 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -82,6 +82,15 @@ config BATTERY_ACT8945A
> Say Y here to enable support for power supply provided by
> Active-semi ActivePath ACT8945A charger.
>
> +config BATTERY_BMS
> + tristate "Qualcomm Battery Monitoring System driver"
> + depends on MFD_SPMI_PMIC || COMPILE_TEST
> + depends on OF
> + depends on REGMAP_SPMI

select REGMAP_SPMI

I'm not a fan of "select", but it does not have a prompt string so it isn't
user settable (not directly; it can be set indirectly).
And all other uses of it in Kconfig files use "select".

> + help
> + Say Y to include support for the Battery Monitoring hardware
> + found in some Qualcomm PM series PMICs.
> +
> config BATTERY_CPCAP
> tristate "Motorola CPCAP PMIC battery driver"
> depends on MFD_CPCAP && IIO


--
~Randy

2018-06-11 18:16:36

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v5 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

On Thu, Jun 07, 2018 at 07:12:51PM +0100, Craig Tatlor wrote:
> Add bindings for the Qualcomm Battery Monitoring system.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
> * Changes from v4:
> Uses proper units and expands some definitions,
> along with changing vadc@ to adc@.
>
> .../bindings/power/supply/qcom_bms.txt | 91 +++++++++++++++++++
> 1 file changed, 91 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>
> diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> new file mode 100644
> index 000000000000..a1a32d6ab460
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> @@ -0,0 +1,91 @@
> +Qualcomm Battery Monitoring System
> +
> +The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
> +PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
> +that allow the OS to infer a capacity level.
> +
> +Required properties:
> +- compatible: Should contain "qcom,pm8941-bms".
> +- reg: Specifies the SPMI address and length of the
> + controller's registers.
> +- interrupts: OCV threshold interrupt.
> +- io-channels: Should contain IIO channel specifier for the
> + ADC channel that reports battery temperature.
> +- io-channel-names: Should contain "temp".
> +- qcom,fcc-temp-legend-celcius: An array containing the temperature, in degC,
> + for each column of the full charge capacity
> + lookup table.
> +- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uah,
> + one entry for each temperature defined in in
> + qcom,fcc-temp-legend-celcius.
> +- qcom,ocv-temp-legend-celcius: An array containing the temperature, in degC,
> + for each column of the OCV lookup table.
> +- qcom,ocv-capacity-legend: An array containing the capacity for each
> + row of the OCV lookup table.
> +- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
> + capacity defined in qcom,ocv-capacity-legend.

Need to say which of these are 8-bit values.

With that,

Reviewed-by: Rob Herring <[email protected]>

2018-06-13 11:07:10

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 1/4] fixp-arith: add a linear interpolation function

On Thu, Jun 7, 2018 at 8:12 PM, Craig Tatlor <[email protected]> wrote:

> Adds a function to interpolate against two points,
> this is carried arount as a helper function by tons of drivers.
>
> Signed-off-by: Craig Tatlor <[email protected]>

The linear formula seems to fit the most natural form of linear
interpolation.

I bet some John Carmack algorithm type people will soon
start to optimize this... :D

Reviewed-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2018-06-13 11:14:11

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 1/4] fixp-arith: add a linear interpolation function

On Wed, Jun 13, 2018 at 1:06 PM, Linus Walleij <[email protected]> wrote:
> On Thu, Jun 7, 2018 at 8:12 PM, Craig Tatlor <[email protected]> wrote:
>
>> Adds a function to interpolate against two points,
>> this is carried arount as a helper function by tons of drivers.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>
> The linear formula seems to fit the most natural form of linear
> interpolation.
>
> I bet some John Carmack algorithm type people will soon
> start to optimize this... :D

For your entertainment here is some sunday reading:
https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/

Yours,
Linus Walleij

2018-06-13 16:00:10

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v5 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

On Thu, Jun 07, 2018 at 12:08:20PM -0700, Randy Dunlap wrote:
> On 06/07/2018 11:12 AM, Craig Tatlor wrote:
> > This patch adds a driver for the BMS (Battery Monitoring System)
> > block of the PM8941 PMIC, it uses a lookup table defined in the
> > device tree to generate a capacity from the BMS supplied OCV, it
> > then ammends the coulomb counter to that to increase the accuracy
>
> amends
>
> > of the estimated capacity.
> >
> > Signed-off-by: Craig Tatlor <[email protected]>
> > ---
>
> > diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> > index 428b426842f4..6c354c37bc55 100644
> > --- a/drivers/power/supply/Kconfig
> > +++ b/drivers/power/supply/Kconfig
> > @@ -82,6 +82,15 @@ config BATTERY_ACT8945A
> > Say Y here to enable support for power supply provided by
> > Active-semi ActivePath ACT8945A charger.
> >
> > +config BATTERY_BMS
> > + tristate "Qualcomm Battery Monitoring System driver"
> > + depends on MFD_SPMI_PMIC || COMPILE_TEST
> > + depends on OF
> > + depends on REGMAP_SPMI
>
> select REGMAP_SPMI
>
> I'm not a fan of "select", but it does not have a prompt string so it isn't
> user settable (not directly; it can be set indirectly).
> And all other uses of it in Kconfig files use "select".
>
> > + help
> > + Say Y to include support for the Battery Monitoring hardware
> > + found in some Qualcomm PM series PMICs.
> > +
> > config BATTERY_CPCAP
> > tristate "Motorola CPCAP PMIC battery driver"
> > depends on MFD_CPCAP && IIO
>
Thanks for the review.
>
> --
> ~Randy

2018-06-13 16:01:16

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v5 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

On Mon, Jun 11, 2018 at 12:15:15PM -0600, Rob Herring wrote:
> On Thu, Jun 07, 2018 at 07:12:51PM +0100, Craig Tatlor wrote:
> > Add bindings for the Qualcomm Battery Monitoring system.
> >
> > Signed-off-by: Craig Tatlor <[email protected]>
> > ---
> > * Changes from v4:
> > Uses proper units and expands some definitions,
> > along with changing vadc@ to adc@.
> >
> > .../bindings/power/supply/qcom_bms.txt | 91 +++++++++++++++++++
> > 1 file changed, 91 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> >
> > diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> > new file mode 100644
> > index 000000000000..a1a32d6ab460
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> > @@ -0,0 +1,91 @@
> > +Qualcomm Battery Monitoring System
> > +
> > +The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
> > +PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
> > +that allow the OS to infer a capacity level.
> > +
> > +Required properties:
> > +- compatible: Should contain "qcom,pm8941-bms".
> > +- reg: Specifies the SPMI address and length of the
> > + controller's registers.
> > +- interrupts: OCV threshold interrupt.
> > +- io-channels: Should contain IIO channel specifier for the
> > + ADC channel that reports battery temperature.
> > +- io-channel-names: Should contain "temp".
> > +- qcom,fcc-temp-legend-celcius: An array containing the temperature, in degC,
> > + for each column of the full charge capacity
> > + lookup table.
> > +- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uah,
> > + one entry for each temperature defined in in
> > + qcom,fcc-temp-legend-celcius.
> > +- qcom,ocv-temp-legend-celcius: An array containing the temperature, in degC,
> > + for each column of the OCV lookup table.
> > +- qcom,ocv-capacity-legend: An array containing the capacity for each
> > + row of the OCV lookup table.
> > +- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
> > + capacity defined in qcom,ocv-capacity-legend.
>
> Need to say which of these are 8-bit values.
>
> With that,
>
> Reviewed-by: Rob Herring <[email protected]>

Thanks for the review, will mark as 8 bit in v6

2018-06-13 16:02:55

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v5 1/4] fixp-arith: add a linear interpolation function

On Wed, Jun 13, 2018 at 01:12:45PM +0200, Linus Walleij wrote:
> On Wed, Jun 13, 2018 at 1:06 PM, Linus Walleij <[email protected]> wrote:
> > On Thu, Jun 7, 2018 at 8:12 PM, Craig Tatlor <[email protected]> wrote:
> >
> >> Adds a function to interpolate against two points,
> >> this is carried arount as a helper function by tons of drivers.
> >>
> >> Signed-off-by: Craig Tatlor <[email protected]>
> >
> > The linear formula seems to fit the most natural form of linear
> > interpolation.
> >
> > I bet some John Carmack algorithm type people will soon
> > start to optimize this... :D
>
> For your entertainment here is some sunday reading:
> https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
>
> Yours,
> Linus Walleij

Thanks, interesting read.

2018-06-13 16:08:15

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v6 1/4] fixp-arith: add a linear interpolation function

Adds a function to interpolate against two points,
this is carried arount as a helper function by tons of drivers.

Signed-off-by: Craig Tatlor <[email protected]>
---
include/linux/fixp-arith.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
index d4686fe1cac7..c21de4f358dd 100644
--- a/include/linux/fixp-arith.h
+++ b/include/linux/fixp-arith.h
@@ -153,4 +153,24 @@ static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
#define fixp_cos32_rad(rad, twopi) \
fixp_sin32_rad(rad + twopi / 4, twopi)

+
+/**
+ * fixp_linear_interpolate() - interpolates a value from two known points
+ *
+ * @x0: x value of point 0
+ * @y0: y value of point 0
+ * @x1: x value of point 1
+ * @y1: y value of point 1
+ * @x: the linear interpolant
+ */
+static inline int fixp_linear_interpolate(int x0, int y0, int x1, int y1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
#endif
--
2.17.0


2018-06-13 16:08:58

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v6 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

This patch adds a driver for the BMS (Battery Monitoring System)
block of the PM8941 PMIC, it uses a lookup table defined in the
device tree to generate a capacity from the BMS supplied OCV, it
then amends the coulomb counter to that to increase the accuracy
of the estimated capacity.

Signed-off-by: Craig Tatlor <[email protected]>
---

* Changes from v5:
Uses select for REGMAP_SPMI.

* Changes from v4:
Cleaned up percentage interpolation function,
uses new fixp interpolation helper,
added some more error cases,
uses devm_power_supply_register(),
uses a DIV_ROUND_CLOSEST for division and
uses micro(volts / amp hours) instead of
milli (volts / amp hours).

drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/qcom_bms.c | 487 ++++++++++++++++++++++++++++++++
3 files changed, 497 insertions(+)
create mode 100644 drivers/power/supply/qcom_bms.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..75f2f375f992 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -82,6 +82,15 @@ config BATTERY_ACT8945A
Say Y here to enable support for power supply provided by
Active-semi ActivePath ACT8945A charger.

+config BATTERY_BMS
+ tristate "Qualcomm Battery Monitoring System driver"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ select REGMAP_SPMI
+ help
+ Say Y to include support for the Battery Monitoring hardware
+ found in some Qualcomm PM series PMICs.
+
config BATTERY_CPCAP
tristate "Motorola CPCAP PMIC battery driver"
depends on MFD_CPCAP && IIO
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..04204174b047 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
+obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
new file mode 100644
index 000000000000..e1d6fdbf11d1
--- /dev/null
+++ b/drivers/power/supply/qcom_bms.c
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: GPL
+
+/*
+ * Qualcomm Battery Monitoring System driver
+ *
+ * Copyright (C) 2018 Craig Tatlor <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/fixp-arith.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/iio/consumer.h>
+
+#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
+#define REG_BMS_SHDW_CC_DATA0 0xA8
+#define REG_BMS_CC_DATA_CTL 0x42
+#define REG_BMS_CC_CLEAR_CTL 0x4
+
+#define BMS_HOLD_OREG_DATA BIT(0)
+#define BMS_CLEAR_SHDW_CC BIT(6)
+
+#define BMS_CC_READING_RESOLUTION_N 542535
+#define BMS_CC_READING_RESOLUTION_D 10000
+#define BMS_CC_READING_TICKS 56
+#define BMS_SLEEP_CLK_HZ 32764
+
+#define SECONDS_PER_HOUR 3600
+#define TEMPERATURE_COLS 5
+#define MAX_CAPACITY_ROWS 50
+
+/* lookup table for ocv -> capacity conversion */
+struct bms_ocv_lut {
+ int rows;
+ s8 temp_legend[TEMPERATURE_COLS];
+ u8 capacity_legend[MAX_CAPACITY_ROWS];
+ u32 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
+};
+
+/* lookup table for battery temperature -> fcc conversion */
+struct bms_fcc_lut {
+ s8 temp_legend[TEMPERATURE_COLS];
+ u32 lut[TEMPERATURE_COLS];
+};
+
+struct bms_device_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct bms_ocv_lut ocv_lut;
+ struct power_supply_desc bat_desc;
+ struct bms_fcc_lut fcc_lut;
+ struct iio_channel *adc;
+ struct mutex bms_output_lock;
+ u32 base_addr;
+
+ int ocv_thr_irq;
+ u32 ocv;
+};
+
+static bool between(int left, int right, int val)
+{
+ if (left <= val && val <= right)
+ return true;
+
+ if (left >= val && val >= right)
+ return true;
+
+ return false;
+}
+
+static int interpolate_capacity(int temp, u32 ocv,
+ struct bms_ocv_lut *ocv_lut)
+{
+ int pcj_minus_one = 0, pcj = 0, i2 = 0, i3 = 0, i, j;
+
+ for (j = 0; j < TEMPERATURE_COLS; j++)
+ if (temp <= ocv_lut->temp_legend[j])
+ break;
+
+ if (ocv >= ocv_lut->lut[0][j])
+ return ocv_lut->capacity_legend[0];
+
+ if (ocv <= ocv_lut->lut[ocv_lut->rows-1][j-1])
+ return ocv_lut->capacity_legend[ocv_lut->rows-1];
+
+ for (i = 0; i < ocv_lut->rows-1; i++) {
+ if (between(ocv_lut->lut[i][j],
+ ocv_lut->lut[i+1][j], ocv))
+ i2 = i;
+
+ if (between(ocv_lut->lut[i][j-1],
+ ocv_lut->lut[i+1][j-1], ocv))
+ i3 = i;
+ }
+
+ /* interpolate two capacities */
+ pcj = fixp_linear_interpolate(ocv_lut->lut[i2][j],
+ ocv_lut->capacity_legend[i2],
+ ocv_lut->lut[i2+1][j],
+ ocv_lut->capacity_legend[i2+1],
+ ocv);
+
+ pcj_minus_one = fixp_linear_interpolate(ocv_lut->lut[i3][j-1],
+ ocv_lut->capacity_legend[i3],
+ ocv_lut->lut[i3+1][j-1],
+ ocv_lut->capacity_legend[i3+1],
+ ocv);
+
+ /* interpolate them with the battery temperature */
+ return fixp_linear_interpolate(ocv_lut->temp_legend[j-1],
+ pcj_minus_one,
+ ocv_lut->temp_legend[j],
+ pcj,
+ temp);
+}
+
+static int interpolate_fcc(int temp, struct bms_fcc_lut *fcc_lut)
+{
+ int i;
+
+ for (i = 0; i < TEMPERATURE_COLS; i++)
+ if (temp <= fcc_lut->temp_legend[i])
+ break;
+
+ return fixp_linear_interpolate(fcc_lut->temp_legend[i-1],
+ fcc_lut->lut[i-1],
+ fcc_lut->temp_legend[i],
+ fcc_lut->lut[i],
+ temp);
+}
+
+static int bms_lock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
+ if (ret) {
+ dev_err(di->dev, "failed to lock bms output: %d", ret);
+ return ret;
+ }
+
+ /*
+ * Sleep for at least 100 microseconds here to make sure
+ * there has been at least three cycles of the sleep clock
+ * so that the registers are correctly locked.
+ */
+ usleep_range(100, 1000);
+
+ return 0;
+}
+
+static int bms_unlock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, 0);
+ if (ret) {
+ dev_err(di->dev, "failed to unlock bms output: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bms_read_ocv(struct bms_device_info *di, u32 *ocv)
+{
+ int ret;
+ u16 read_ocv;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr+
+ REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
+ if (ret) {
+ dev_err(di->dev, "open circuit voltage read failed: %d", ret);
+ goto err_read;
+ }
+
+ dev_dbg(di->dev, "read open circuit voltage of: %d mv", read_ocv);
+
+
+ *ocv = read_ocv * 1000;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
+{
+ int ret;
+ s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_SHDW_CC_DATA0,
+ &cc_raw_s36, 5);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter read failed: %d", ret);
+ goto err_read;
+ }
+
+ ret = bms_unlock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ mutex_unlock(&di->bms_output_lock);
+
+ cc_raw = sign_extend32(cc_raw_s36, 28);
+
+ /* convert raw to uv */
+ cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
+ BMS_CC_READING_RESOLUTION_D);
+
+ /* convert uv to pvh */
+ cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
+ BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR);
+
+ /* divide by impedance */
+ *cc_uah = div_s64(cc_pvh, 10000);
+
+ dev_dbg(di->dev, "read coulomb counter value of: %lld uah", *cc_uah);
+
+ return 0;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static void bms_reset_cc(struct bms_device_info *di)
+{
+ int ret;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC,
+ BMS_CLEAR_SHDW_CC);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter reset failed: %d", ret);
+ goto err_lock;
+ }
+
+ /* wait at least three sleep cycles for cc to reset */
+ usleep_range(100, 1000);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC, 0);
+ if (ret)
+ dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+}
+
+static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
+{
+ unsigned long fcc;
+ int ret, temp, ocv_capacity, temp_degc;
+ s64 cc = 0;
+
+ ret = iio_read_channel_raw(di->adc, &temp);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp_degc = DIV_ROUND_CLOSEST(temp, 1000);
+
+ ret = bms_read_cc(di, &cc);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read coulomb counter: %d", ret);
+ return ret;
+ }
+
+ /* interpolate capacity from open circuit voltage */
+ ocv_capacity = interpolate_capacity(temp_degc, di->ocv,
+ &di->ocv_lut);
+
+ /* interpolate the full charge capacity from temperature */
+ fcc = interpolate_fcc(temp_degc, &di->fcc_lut);
+
+ /* append coloumb counter to capacity */
+ *capacity = DIV_ROUND_CLOSEST(fcc * ocv_capacity, 100);
+ *capacity = div_s64((*capacity - cc) * 100, fcc);
+
+ return 0;
+}
+
+
+
+/*
+ * Return power_supply property
+ */
+static int bms_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bms_device_info *di = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bms_calculate_capacity(di, &val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (val->intval == INT_MAX || val->intval == INT_MIN)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static enum power_supply_property bms_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
+{
+ struct bms_device_info *di = dev_id;
+
+ if (bms_read_ocv(di, &di->ocv) < 0)
+ return IRQ_HANDLED;
+
+ bms_reset_cc(di);
+ return IRQ_HANDLED;
+}
+
+static int bms_probe(struct platform_device *pdev)
+{
+ struct power_supply_config psy_cfg = {};
+ struct bms_device_info *di;
+ struct power_supply *bat;
+ int ret;
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->dev = &pdev->dev;
+
+ di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!di->regmap) {
+ dev_err(di->dev, "Unable to get regmap");
+ return -EINVAL;
+ }
+
+ di->adc = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(di->adc))
+ return PTR_ERR(di->adc);
+
+ ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,ocv-temp-legend-celsius",
+ (u8 *)di->ocv_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage temperature legend found");
+ return ret;
+ }
+
+ di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
+ "qcom,ocv-capacity-legend",
+ di->ocv_lut.capacity_legend, 0,
+ MAX_CAPACITY_ROWS);
+ if (di->ocv_lut.rows < 0) {
+ dev_err(di->dev, "no open circuit voltage capacity legend found");
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(di->dev->of_node,
+ "qcom,ocv-lut-microvolt",
+ (u32 *)di->ocv_lut.lut,
+ TEMPERATURE_COLS,
+ TEMPERATURE_COLS *
+ MAX_CAPACITY_ROWS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage lut array found");
+ return ret;
+ }
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,fcc-temp-legend-celsius",
+ (u8 *)di->fcc_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity temperature legend found");
+ return ret;
+ }
+
+ ret = of_property_read_u32_array(di->dev->of_node,
+ "qcom,fcc-lut-microamp-hours",
+ di->fcc_lut.lut,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity lut array found");
+ return ret;
+ }
+
+ ret = bms_read_ocv(di, &di->ocv);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read initial open circuit voltage: %d",
+ ret);
+ return ret;
+ }
+
+ mutex_init(&di->bms_output_lock);
+
+ di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
+
+ ret = devm_request_threaded_irq(di->dev, di->ocv_thr_irq, NULL,
+ bms_ocv_thr_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ pdev->name, di);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to request handler for open circuit voltage threshold IRQ");
+ return ret;
+ }
+
+
+ di->bat_desc.name = "bms";
+ di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat_desc.properties = bms_props;
+ di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
+ di->bat_desc.get_property = bms_get_property;
+
+ psy_cfg.drv_data = di;
+ bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+
+ return PTR_ERR_OR_ZERO(bat);
+}
+
+static const struct of_device_id bms_of_match[] = {
+ {.compatible = "qcom,pm8941-bms", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bms_of_match);
+
+static struct platform_driver bms_driver = {
+ .probe = bms_probe,
+ .driver = {
+ .name = "qcom-bms",
+ .of_match_table = of_match_ptr(bms_of_match),
+ },
+};
+module_platform_driver(bms_driver);
+
+MODULE_AUTHOR("Craig Tatlor <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm BMS driver");
+MODULE_LICENSE("GPL");
--
2.17.0


2018-06-13 16:09:24

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v6 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Add bindings for the Qualcomm Battery Monitoring system.

Signed-off-by: Craig Tatlor <[email protected]>
---

* Changes from v5:
Mentions which values are 8 bit.

* Changes from v4:
Uses proper units and expands some definitions,
along with changing vadc@ to adc@.
.../bindings/power/supply/qcom_bms.txt | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt

diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
new file mode 100644
index 000000000000..9a29a2eb9f04
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
@@ -0,0 +1,92 @@
+Qualcomm Battery Monitoring System
+
+The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
+PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
+that allow the OS to infer a capacity level.
+
+Required properties:
+- compatible: Should contain "qcom,pm8941-bms".
+- reg: Specifies the SPMI address and length of the
+ controller's registers.
+- interrupts: OCV threshold interrupt.
+- io-channels: Should contain IIO channel specifier for the
+ ADC channel that reports battery temperature.
+- io-channel-names: Should contain "temp".
+- qcom,fcc-temp-legend-celcius: An 8 bit array containing the temperature,
+ in degC, for each column of the full charge
+ capacity lookup table.
+- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uah,
+ one entry for each temperature defined in in
+ qcom,fcc-temp-legend-celcius.
+- qcom,ocv-temp-legend-celcius: An 8 bit array containing the temperature,
+ in degC, for each column of the OCV lookup
+ table.
+- qcom,ocv-capacity-legend: An 8 bit array containing the capacity for each
+ row of the OCV lookup table.
+- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
+ capacity defined in qcom,ocv-capacity-legend.
+
+Example:
+ pm8941_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
+ };
+
+ bms@4000 {
+ compatible = "qcom,pm8941-bms";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ocv_thr";
+
+ io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
+ io-channel-names = "temp";
+
+ qcom,fcc-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,fcc-lut-microamp-hours = <3230000 3260000 3380000 3410000 3360000>;
+
+ qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75
+ 70 65 60 55 50 45
+ 40 35 30 25 20 15
+ 10 9 8 7 6 5 4 3 2
+ 1 0>;
+ qcom,ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,ocv-lut-microvolt = <43050000 43050000 43030000 42990000 42950000
+ 42770000 42570000 42550000 42510000 42310000
+ 42180000 41980000 41970000 41920000 41720000
+ 41590000 41390000 41450000 41400000 41200000
+ 41010000 40810000 40920000 40890000 40690000
+ 40480000 40280000 40440000 40420000 40220000
+ 40040000 39840000 40010000 39980000 39780000
+ 39620000 39420000 39550000 39560000 39360000
+ 39210000 39010000 39090000 39160000 38960000
+ 38830000 38630000 38740000 38790000 38590000
+ 38550000 38350000 38440000 38430000 38230000
+ 38310000 38110000 38230000 38180000 37980000
+ 38190000 37990000 38040000 38000000 37800000
+ 38060000 37860000 37900000 37840000 37640000
+ 37890000 37690000 37770000 37660000 37460000
+ 37720000 37520000 37560000 37450000 37250000
+ 37480000 37280000 37290000 37250000 37050000
+ 37240000 37040000 37020000 36990000 36790000
+ 37030000 36830000 36730000 36700000 36500000
+ 36940000 36740000 36670000 36640000 36440000
+ 36850000 36650000 36600000 36590000 36390000
+ 36750000 36550000 36520000 36550000 36350000
+ 36690000 36490000 36380000 36400000 36200000
+ 36460000 36260000 36180000 36120000 35920000
+ 36080000 35880000 35680000 35640000 35440000
+ 35510000 35310000 35050000 35020000 34820000
+ 34730000 34530000 34300000 34250000 34050000
+ 33870000 33670000 33040000 32820000 32620000
+ 30000000 30000000 30000000 30000000 30000000>;
+ };
+ };
+};
--
2.17.0


2018-06-13 16:10:53

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v6 4/4] MAINTAINERS: Add entry for the Qualcomm BMS

Signed-off-by: Craig Tatlor <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c125f705f78..be485caf9313 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11646,6 +11646,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/

+QUALCOMM BATTERY MONITORING SYSTEM
+M: Craig Tatlor <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/power/supply/qcom_bms.c
+
QUALCOMM CAMERA SUBSYSTEM DRIVER
M: Todor Tomov <[email protected]>
L: [email protected]
--
2.17.0


2018-06-13 22:54:25

by Matthias Kaehlcke

[permalink] [raw]
Subject: Re: [PATCH v6 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

(sorry if you receive two variants of this mail, I sent one earlier
today but for some reason it didn't make it to the lists)

On Wed, Jun 13, 2018 at 05:06:24PM +0100, Craig Tatlor wrote:
> Add bindings for the Qualcomm Battery Monitoring system.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
>
> * Changes from v5:
> Mentions which values are 8 bit.
>
> * Changes from v4:
> Uses proper units and expands some definitions,
> along with changing vadc@ to adc@.
> .../bindings/power/supply/qcom_bms.txt | 92 +++++++++++++++++++
> 1 file changed, 92 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>
> diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> new file mode 100644
> index 000000000000..9a29a2eb9f04
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> @@ -0,0 +1,92 @@
> +Qualcomm Battery Monitoring System
> +
> +The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
> +PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
> +that allow the OS to infer a capacity level.
> +
> +Required properties:
> +- compatible: Should contain "qcom,pm8941-bms".
> +- reg: Specifies the SPMI address and length of the
> + controller's registers.
> +- interrupts: OCV threshold interrupt.
> +- io-channels: Should contain IIO channel specifier for the
> + ADC channel that reports battery temperature.
> +- io-channel-names: Should contain "temp".
> +- qcom,fcc-temp-legend-celcius: An 8 bit array containing the temperature,
> + in degC, for each column of the full charge
> + capacity lookup table.

s/celcius/celsius/

same for qcom,ocv-temp-legend-celcius

> +- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uah,
> + one entry for each temperature defined in in

nit: s/uah/uAh/

Thanks

Matthias

2018-06-14 14:09:08

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v6 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

On Wed, Jun 13, 2018 at 6:06 PM, Craig Tatlor <[email protected]> wrote:

> This patch adds a driver for the BMS (Battery Monitoring System)
> block of the PM8941 PMIC, it uses a lookup table defined in the
> device tree to generate a capacity from the BMS supplied OCV, it
> then amends the coulomb counter to that to increase the accuracy
> of the estimated capacity.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
>
> * Changes from v5:
> Uses select for REGMAP_SPMI.

Looks very nice to me!
Reviewed-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2018-06-14 15:17:00

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v7 1/4] fixp-arith: add a linear interpolation function

Adds a function to interpolate against two points,
this is carried arount as a helper function by tons of drivers.

Signed-off-by: Craig Tatlor <[email protected]>
Reviewed-by: Linus Walleij <[email protected]>
---
include/linux/fixp-arith.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
index d4686fe1cac7..b9e2bb59a734 100644
--- a/include/linux/fixp-arith.h
+++ b/include/linux/fixp-arith.h
@@ -153,4 +153,24 @@ static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
#define fixp_cos32_rad(rad, twopi) \
fixp_sin32_rad(rad + twopi / 4, twopi)

+
+/**
+ * fixp_linear_interpolate() - interpolates a value from two known points
+ *
+ * @x0: x value of point 0
+ * @y0: y value of point 0
+ * @x1: x value of point 1
+ * @y1: y value of point 1
+ * @x: the linear interpolant
+ */
+static inline int fixp_linear_interpolate(int x0, int y0, int x1, int y1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
#endif
--
2.17.0


2018-06-14 15:17:10

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Add bindings for the Qualcomm Battery Monitoring system.

Signed-off-by: Craig Tatlor <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---

* Changes from v6:
s/celcius/celsius
change uah to uAh.

* Changes from v5:
Mentions which values are 8 bit.

* Changes from v4:
Uses proper units and expands some definitions,
along with changing vadc@ to adc@.

.../bindings/power/supply/qcom_bms.txt | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt

diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
new file mode 100644
index 000000000000..dc0a9ab9aa64
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
@@ -0,0 +1,92 @@
+Qualcomm Battery Monitoring System
+
+The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
+PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
+that allow the OS to infer a capacity level.
+
+Required properties:
+- compatible: Should contain "qcom,pm8941-bms".
+- reg: Specifies the SPMI address and length of the
+ controller's registers.
+- interrupts: OCV threshold interrupt.
+- io-channels: Should contain IIO channel specifier for the
+ ADC channel that reports battery temperature.
+- io-channel-names: Should contain "temp".
+- qcom,fcc-temp-legend-celsius: An 8 bit array containing the temperature,
+ in degC, for each column of the full charge
+ capacity lookup table.
+- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uAh,
+ one entry for each temperature defined in in
+ qcom,fcc-temp-legend-celsius.
+- qcom,ocv-temp-legend-celsius: An 8 bit array containing the temperature,
+ in degC, for each column of the OCV lookup
+ table.
+- qcom,ocv-capacity-legend: An 8 bit array containing the capacity for each
+ row of the OCV lookup table.
+- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
+ capacity defined in qcom,ocv-capacity-legend.
+
+Example:
+ pm8941_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
+ };
+
+ bms@4000 {
+ compatible = "qcom,pm8941-bms";
+ reg = <0x4000>;
+ interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "ocv_thr";
+
+ io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
+ io-channel-names = "temp";
+
+ qcom,fcc-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,fcc-lut-microamp-hours = <3230000 3260000 3380000 3410000 3360000>;
+
+ qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75
+ 70 65 60 55 50 45
+ 40 35 30 25 20 15
+ 10 9 8 7 6 5 4 3 2
+ 1 0>;
+ qcom,ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
+ qcom,ocv-lut-microvolt = <43050000 43050000 43030000 42990000 42950000
+ 42770000 42570000 42550000 42510000 42310000
+ 42180000 41980000 41970000 41920000 41720000
+ 41590000 41390000 41450000 41400000 41200000
+ 41010000 40810000 40920000 40890000 40690000
+ 40480000 40280000 40440000 40420000 40220000
+ 40040000 39840000 40010000 39980000 39780000
+ 39620000 39420000 39550000 39560000 39360000
+ 39210000 39010000 39090000 39160000 38960000
+ 38830000 38630000 38740000 38790000 38590000
+ 38550000 38350000 38440000 38430000 38230000
+ 38310000 38110000 38230000 38180000 37980000
+ 38190000 37990000 38040000 38000000 37800000
+ 38060000 37860000 37900000 37840000 37640000
+ 37890000 37690000 37770000 37660000 37460000
+ 37720000 37520000 37560000 37450000 37250000
+ 37480000 37280000 37290000 37250000 37050000
+ 37240000 37040000 37020000 36990000 36790000
+ 37030000 36830000 36730000 36700000 36500000
+ 36940000 36740000 36670000 36640000 36440000
+ 36850000 36650000 36600000 36590000 36390000
+ 36750000 36550000 36520000 36550000 36350000
+ 36690000 36490000 36380000 36400000 36200000
+ 36460000 36260000 36180000 36120000 35920000
+ 36080000 35880000 35680000 35640000 35440000
+ 35510000 35310000 35050000 35020000 34820000
+ 34730000 34530000 34300000 34250000 34050000
+ 33870000 33670000 33040000 32820000 32620000
+ 30000000 30000000 30000000 30000000 30000000>;
+ };
+ };
+};
--
2.17.0


2018-06-14 15:17:14

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v7 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

This patch adds a driver for the BMS (Battery Monitoring System)
block of the PM8941 PMIC, it uses a lookup table defined in the
device tree to generate a capacity from the BMS supplied OCV, it
then amends the coulomb counter to that to increase the accuracy
of the estimated capacity.

Signed-off-by: Craig Tatlor <[email protected]>
Reviewed-by: Linus Walleij <[email protected]>
---

* Changes from v5:
Uses select for REGMAP_SPMI.

* Changes from v4:
Cleaned up percentage interpolation function,
uses new fixp interpolation helper,
added some more error cases,
uses devm_power_supply_register(),
uses a DIV_ROUND_CLOSEST for division and
uses micro(volts / amp hours) instead of
milli (volts / amp hours).

drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/qcom_bms.c | 487 ++++++++++++++++++++++++++++++++
3 files changed, 497 insertions(+)
create mode 100644 drivers/power/supply/qcom_bms.c

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..75f2f375f992 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -82,6 +82,15 @@ config BATTERY_ACT8945A
Say Y here to enable support for power supply provided by
Active-semi ActivePath ACT8945A charger.

+config BATTERY_BMS
+ tristate "Qualcomm Battery Monitoring System driver"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ depends on OF
+ select REGMAP_SPMI
+ help
+ Say Y to include support for the Battery Monitoring hardware
+ found in some Qualcomm PM series PMICs.
+
config BATTERY_CPCAP
tristate "Motorola CPCAP PMIC battery driver"
depends on MFD_CPCAP && IIO
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..04204174b047 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
+obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
new file mode 100644
index 000000000000..718fd745c0f7
--- /dev/null
+++ b/drivers/power/supply/qcom_bms.c
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: GPL
+
+/*
+ * Qualcomm Battery Monitoring System driver
+ *
+ * Copyright (C) 2018 Craig Tatlor <[email protected]>
+ */
+
+#include <linux/module.h>
+#include <linux/fixp-arith.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/iio/consumer.h>
+
+#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
+#define REG_BMS_SHDW_CC_DATA0 0xA8
+#define REG_BMS_CC_DATA_CTL 0x42
+#define REG_BMS_CC_CLEAR_CTL 0x4
+
+#define BMS_HOLD_OREG_DATA BIT(0)
+#define BMS_CLEAR_SHDW_CC BIT(6)
+
+#define BMS_CC_READING_RESOLUTION_N 542535
+#define BMS_CC_READING_RESOLUTION_D 10000
+#define BMS_CC_READING_TICKS 56
+#define BMS_SLEEP_CLK_HZ 32764
+
+#define SECONDS_PER_HOUR 3600
+#define TEMPERATURE_COLS 5
+#define MAX_CAPACITY_ROWS 50
+
+/* lookup table for ocv -> capacity conversion */
+struct bms_ocv_lut {
+ int rows;
+ s8 temp_legend[TEMPERATURE_COLS];
+ u8 capacity_legend[MAX_CAPACITY_ROWS];
+ u32 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
+};
+
+/* lookup table for battery temperature -> fcc conversion */
+struct bms_fcc_lut {
+ s8 temp_legend[TEMPERATURE_COLS];
+ u32 lut[TEMPERATURE_COLS];
+};
+
+struct bms_device_info {
+ struct device *dev;
+ struct regmap *regmap;
+ struct bms_ocv_lut ocv_lut;
+ struct power_supply_desc bat_desc;
+ struct bms_fcc_lut fcc_lut;
+ struct iio_channel *adc;
+ struct mutex bms_output_lock;
+ u32 base_addr;
+
+ int ocv_thr_irq;
+ u32 ocv;
+};
+
+static bool between(int left, int right, int val)
+{
+ if (left <= val && val <= right)
+ return true;
+
+ if (left >= val && val >= right)
+ return true;
+
+ return false;
+}
+
+static int interpolate_capacity(int temp, u32 ocv,
+ struct bms_ocv_lut *ocv_lut)
+{
+ int pcj_minus_one = 0, pcj = 0, i2 = 0, i3 = 0, i, j;
+
+ for (j = 0; j < TEMPERATURE_COLS; j++)
+ if (temp <= ocv_lut->temp_legend[j])
+ break;
+
+ if (ocv >= ocv_lut->lut[0][j])
+ return ocv_lut->capacity_legend[0];
+
+ if (ocv <= ocv_lut->lut[ocv_lut->rows-1][j-1])
+ return ocv_lut->capacity_legend[ocv_lut->rows-1];
+
+ for (i = 0; i < ocv_lut->rows-1; i++) {
+ if (between(ocv_lut->lut[i][j],
+ ocv_lut->lut[i+1][j], ocv))
+ i2 = i;
+
+ if (between(ocv_lut->lut[i][j-1],
+ ocv_lut->lut[i+1][j-1], ocv))
+ i3 = i;
+ }
+
+ /* interpolate two capacities */
+ pcj = fixp_linear_interpolate(ocv_lut->lut[i2][j],
+ ocv_lut->capacity_legend[i2],
+ ocv_lut->lut[i2+1][j],
+ ocv_lut->capacity_legend[i2+1],
+ ocv);
+
+ pcj_minus_one = fixp_linear_interpolate(ocv_lut->lut[i3][j-1],
+ ocv_lut->capacity_legend[i3],
+ ocv_lut->lut[i3+1][j-1],
+ ocv_lut->capacity_legend[i3+1],
+ ocv);
+
+ /* interpolate them with the battery temperature */
+ return fixp_linear_interpolate(ocv_lut->temp_legend[j-1],
+ pcj_minus_one,
+ ocv_lut->temp_legend[j],
+ pcj,
+ temp);
+}
+
+static int interpolate_fcc(int temp, struct bms_fcc_lut *fcc_lut)
+{
+ int i;
+
+ for (i = 0; i < TEMPERATURE_COLS; i++)
+ if (temp <= fcc_lut->temp_legend[i])
+ break;
+
+ return fixp_linear_interpolate(fcc_lut->temp_legend[i-1],
+ fcc_lut->lut[i-1],
+ fcc_lut->temp_legend[i],
+ fcc_lut->lut[i],
+ temp);
+}
+
+static int bms_lock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
+ if (ret) {
+ dev_err(di->dev, "failed to lock bms output: %d", ret);
+ return ret;
+ }
+
+ /*
+ * Sleep for at least 100 microseconds here to make sure
+ * there has been at least three cycles of the sleep clock
+ * so that the registers are correctly locked.
+ */
+ usleep_range(100, 1000);
+
+ return 0;
+}
+
+static int bms_unlock_output_data(struct bms_device_info *di)
+{
+ int ret;
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_DATA_CTL,
+ BMS_HOLD_OREG_DATA, 0);
+ if (ret) {
+ dev_err(di->dev, "failed to unlock bms output: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bms_read_ocv(struct bms_device_info *di, u32 *ocv)
+{
+ int ret;
+ u16 read_ocv;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr+
+ REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
+ if (ret) {
+ dev_err(di->dev, "open circuit voltage read failed: %d", ret);
+ goto err_read;
+ }
+
+ dev_dbg(di->dev, "read open circuit voltage of: %d mv", read_ocv);
+
+
+ *ocv = read_ocv * 1000;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
+{
+ int ret;
+ s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = bms_lock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ ret = regmap_bulk_read(di->regmap, di->base_addr +
+ REG_BMS_SHDW_CC_DATA0,
+ &cc_raw_s36, 5);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter read failed: %d", ret);
+ goto err_read;
+ }
+
+ ret = bms_unlock_output_data(di);
+ if (ret)
+ goto err_lock;
+
+ mutex_unlock(&di->bms_output_lock);
+
+ cc_raw = sign_extend32(cc_raw_s36, 28);
+
+ /* convert raw to uv */
+ cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
+ BMS_CC_READING_RESOLUTION_D);
+
+ /* convert uv to pvh */
+ cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
+ BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR);
+
+ /* divide by impedance */
+ *cc_uah = div_s64(cc_pvh, 10000);
+
+ dev_dbg(di->dev, "read coulomb counter value of: %lld uah", *cc_uah);
+
+ return 0;
+
+err_read:
+ bms_unlock_output_data(di);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+
+ return ret;
+}
+
+static void bms_reset_cc(struct bms_device_info *di)
+{
+ int ret;
+
+ mutex_lock(&di->bms_output_lock);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC,
+ BMS_CLEAR_SHDW_CC);
+ if (ret) {
+ dev_err(di->dev, "coulomb counter reset failed: %d", ret);
+ goto err_lock;
+ }
+
+ /* wait at least three sleep cycles for cc to reset */
+ usleep_range(100, 1000);
+
+ ret = regmap_update_bits(di->regmap, di->base_addr +
+ REG_BMS_CC_CLEAR_CTL,
+ BMS_CLEAR_SHDW_CC, 0);
+ if (ret)
+ dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
+
+err_lock:
+ mutex_unlock(&di->bms_output_lock);
+}
+
+static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
+{
+ unsigned long fcc;
+ int ret, temp, ocv_capacity, temp_degc;
+ s64 cc = 0;
+
+ ret = iio_read_channel_raw(di->adc, &temp);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp_degc = DIV_ROUND_CLOSEST(temp, 1000);
+
+ ret = bms_read_cc(di, &cc);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read coulomb counter: %d", ret);
+ return ret;
+ }
+
+ /* interpolate capacity from open circuit voltage */
+ ocv_capacity = interpolate_capacity(temp_degc, di->ocv,
+ &di->ocv_lut);
+
+ /* interpolate the full charge capacity from temperature */
+ fcc = interpolate_fcc(temp_degc, &di->fcc_lut);
+
+ /* append coloumb counter to capacity */
+ *capacity = DIV_ROUND_CLOSEST(fcc * ocv_capacity, 100);
+ *capacity = div_s64((*capacity - cc) * 100, fcc);
+
+ return 0;
+}
+
+
+
+/*
+ * Return power_supply property
+ */
+static int bms_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct bms_device_info *di = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = bms_calculate_capacity(di, &val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (val->intval == INT_MAX || val->intval == INT_MIN)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static enum power_supply_property bms_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
+{
+ struct bms_device_info *di = dev_id;
+
+ if (bms_read_ocv(di, &di->ocv) < 0)
+ return IRQ_HANDLED;
+
+ bms_reset_cc(di);
+ return IRQ_HANDLED;
+}
+
+static int bms_probe(struct platform_device *pdev)
+{
+ struct power_supply_config psy_cfg = {};
+ struct bms_device_info *di;
+ struct power_supply *bat;
+ int ret;
+
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->dev = &pdev->dev;
+
+ di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!di->regmap) {
+ dev_err(di->dev, "Unable to get regmap");
+ return -EINVAL;
+ }
+
+ di->adc = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(di->adc))
+ return PTR_ERR(di->adc);
+
+ ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,ocv-temp-legend-celsius",
+ (u8 *)di->ocv_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage temperature legend found");
+ return ret;
+ }
+
+ di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
+ "qcom,ocv-capacity-legend",
+ di->ocv_lut.capacity_legend, 0,
+ MAX_CAPACITY_ROWS);
+ if (di->ocv_lut.rows < 0) {
+ dev_err(di->dev, "no open circuit voltage capacity legend found");
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(di->dev->of_node,
+ "qcom,ocv-lut-microvolt",
+ (u32 *)di->ocv_lut.lut,
+ TEMPERATURE_COLS,
+ TEMPERATURE_COLS *
+ MAX_CAPACITY_ROWS);
+ if (ret < 0) {
+ dev_err(di->dev, "no open circuit voltage lut array found");
+ return ret;
+ }
+
+ ret = of_property_read_u8_array(di->dev->of_node,
+ "qcom,fcc-temp-legend-celsius",
+ (u8 *)di->fcc_lut.temp_legend,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity temperature legend found");
+ return ret;
+ }
+
+ ret = of_property_read_u32_array(di->dev->of_node,
+ "qcom,fcc-lut-microamp-hours",
+ di->fcc_lut.lut,
+ TEMPERATURE_COLS);
+ if (ret < 0) {
+ dev_err(di->dev, "no full charge capacity lut array found");
+ return ret;
+ }
+
+ ret = bms_read_ocv(di, &di->ocv);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to read initial open circuit voltage: %d",
+ ret);
+ return ret;
+ }
+
+ mutex_init(&di->bms_output_lock);
+
+ di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
+
+ ret = devm_request_threaded_irq(di->dev, di->ocv_thr_irq, NULL,
+ bms_ocv_thr_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ pdev->name, di);
+ if (ret < 0) {
+ dev_err(di->dev, "failed to request handler for open circuit voltage threshold IRQ");
+ return ret;
+ }
+
+
+ di->bat_desc.name = "bms";
+ di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat_desc.properties = bms_props;
+ di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
+ di->bat_desc.get_property = bms_get_property;
+
+ psy_cfg.drv_data = di;
+ bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+
+ return PTR_ERR_OR_ZERO(bat);
+}
+
+static const struct of_device_id bms_of_match[] = {
+ {.compatible = "qcom,pm8941-bms", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bms_of_match);
+
+static struct platform_driver bms_driver = {
+ .probe = bms_probe,
+ .driver = {
+ .name = "qcom-bms",
+ .of_match_table = of_match_ptr(bms_of_match),
+ },
+};
+module_platform_driver(bms_driver);
+
+MODULE_AUTHOR("Craig Tatlor <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm BMS driver");
+MODULE_LICENSE("GPL");
--
2.17.0


2018-06-14 15:18:16

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v7 4/4] MAINTAINERS: Add entry for the Qualcomm BMS

Signed-off-by: Craig Tatlor <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9c125f705f78..be485caf9313 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11646,6 +11646,12 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
S: Supported
F: drivers/net/wireless/ath/ath9k/

+QUALCOMM BATTERY MONITORING SYSTEM
+M: Craig Tatlor <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/power/supply/qcom_bms.c
+
QUALCOMM CAMERA SUBSYSTEM DRIVER
M: Todor Tomov <[email protected]>
L: [email protected]
--
2.17.0


2018-08-10 20:23:02

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

Add support for the global clock controller found on SDM660
based devices. This should allow most non-multimedia device
drivers to probe and control their clocks.
Based on CAF implementation.

Signed-off-by: Craig Tatlor <[email protected]>
---
.../devicetree/bindings/clock/qcom,gcc.txt | 1 +
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gcc-sdm660.c | 2479 +++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
5 files changed, 2649 insertions(+)
create mode 100644 drivers/clk/qcom/gcc-sdm660.c
create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 664ea1fd6c76..e498ad2e8db8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -19,6 +19,7 @@ Required properties :
"qcom,gcc-msm8996"
"qcom,gcc-msm8998"
"qcom,gcc-mdm9615"
+ "qcom,gcc-sdm660"
"qcom,gcc-sdm845"

- reg : shall contain base register location and length
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9c3480dcc38a..c4bda6d24c1f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -226,6 +226,15 @@ config MSM_GCC_8998
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, UFS, SD/eMMC, PCIe, etc.

+config SDM_GCC_660
+ tristate "SDM660 Global Clock Controller"
+ select QCOM_GDSC
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on SDM660 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2C, USB, UFS, SDDC, PCIe, etc.
+
config SDM_GCC_845
tristate "SDM845 Global Clock Controller"
select QCOM_GDSC
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 762c01137c2f..6e37d30d7c02 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
+obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
new file mode 100644
index 000000000000..bdb445aa4baa
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -0,0 +1,2479 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-sdm660.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+#include "gdsc.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+ P_XO,
+ P_SLEEP_CLK,
+ P_GPLL0,
+ P_GPLL1,
+ P_GPLL4,
+ P_GPLL0_EARLY_DIV,
+ P_GPLL1_EARLY_DIV,
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0[] = {
+ "xo",
+ "gpll0",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "sleep_clk",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const char * const gcc_parent_names_xo_sleep_clk[] = {
+ "xo",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll4[] = {
+ "xo",
+ "gpll4",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 3 },
+ { P_GPLL1, 4 },
+ { P_GPLL4, 5 },
+ { P_GPLL1_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll1",
+ "gpll4",
+ "gpll1_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll4",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 2 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll4",
+};
+
+static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "xo",
+ .parent_names = (const char *[]){ "xo_board" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll0_early = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll0_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early_div",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+ .offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll1_early = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll1_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early_div",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll1",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll4",
+ .parent_names = (const char *[]) { "gpll4_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x19020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(15000000, P_GPLL0, 10, 1, 4),
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1900c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1b020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1b00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1d020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1d00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1f020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1f00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
+ F(3686400, P_GPLL0, 1, 96, 15625),
+ F(7372800, P_GPLL0, 1, 192, 15625),
+ F(14745600, P_GPLL0, 1, 384, 15625),
+ F(16000000, P_GPLL0, 5, 2, 15),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_GPLL0, 1, 4, 75),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(46400000, P_GPLL0, 1, 29, 375),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(51200000, P_GPLL0, 1, 32, 375),
+ F(56000000, P_GPLL0, 1, 7, 75),
+ F(58982400, P_GPLL0, 1, 1536, 15625),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(63157895, P_GPLL0, 9.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x1a00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x1c00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x26020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2600c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x28020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2800c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2a020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2a00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2c020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2c00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x2700c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x2900c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gp1_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x64004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x65004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x66004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll0_clk_src = {
+ .cmd_rcgr = 0x4805c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_gpll0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll0_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
+ F(384000000, P_GPLL4, 4, 0, 0),
+ F(768000000, P_GPLL4, 2, 0, 0),
+ F(1536000000, P_GPLL4, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll4_clk_src = {
+ .cmd_rcgr = 0x48074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll4,
+ .freq_tbl = ftbl_hmss_gpll4_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll4_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll4,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_rbcpr_clk_src = {
+ .cmd_rcgr = 0x48044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_rbcpr_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x33010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
+ F(160400000, P_GPLL1, 5, 0, 0),
+ F(267333333, P_GPLL1, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 qspi_ser_clk_src = {
+ .cmd_rcgr = 0x4d00c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .freq_tbl = ftbl_qspi_ser_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(384000000, P_GPLL4, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x1602c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x16010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x14010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+ .cmd_rcgr = 0x75018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_ice_core_clk_src = {
+ .cmd_rcgr = 0x76010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 ufs_phy_aux_clk_src = {
+ .cmd_rcgr = 0x76044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
+ F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_unipro_core_clk_src = {
+ .cmd_rcgr = 0x76028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_unipro_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_master_clk_src = {
+ .cmd_rcgr = 0x2f010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x2f024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ F(133333333, P_GPLL0, 4.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0xf014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0xf028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+ F(1200000, P_XO, 16, 0, 0),
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .cmd_rcgr = 0x5000c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb3_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_aggre2_ufs_axi_clk = {
+ .halt_reg = 0x75034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre2_usb3_axi_clk = {
+ .halt_reg = 0xf03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_gfx_clk = {
+ .halt_reg = 0x7106c,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x7106c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_hmss_axi_clk = {
+ .halt_reg = 0x48004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_hmss_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_mss_q6_axi_clk = {
+ .halt_reg = 0x4401c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4401c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_mss_q6_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x19008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x19004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x1b008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x1b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x1d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x1d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x1f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x1f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x1a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x1c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x25004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x26008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x26004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x28008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x28004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x2a008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x2a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x2c008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x2c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x27004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x29004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x38004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb2_axi_clk = {
+ .halt_reg = 0x5058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb2_axi_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
+ .halt_reg = 0x5018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_dcc_ahb_clk = {
+ .halt_reg = 0x84004,
+ .clkr = {
+ .enable_reg = 0x84004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_dcc_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x64000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x64000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_names = (const char *[]){
+ "gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x65000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x65000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_names = (const char *[]){
+ "gp2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x66000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x66000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_names = (const char *[]){
+ "gp3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_bimc_gfx_clk = {
+ .halt_reg = 0x71010,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x71004,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_dvm_bus_clk = {
+ .halt_reg = 0x4808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_dvm_bus_clk",
+ .ops = &clk_branch2_ops,
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_rbcpr_clk = {
+ .halt_reg = 0x48008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x48008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_rbcpr_clk",
+ .parent_names = (const char *[]){
+ "hmss_rbcpr_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+ .halt_reg = 0x9004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_noc_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_sys_noc_axi_clk = {
+ .halt_reg = 0x9000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_sys_noc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .halt_reg = 0x8a000,
+ .clkr = {
+ .enable_reg = 0x8a000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
+ .halt_reg = 0x8a004,
+ .clkr = {
+ .enable_reg = 0x8a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_mnoc_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .halt_reg = 0x8a040,
+ .clkr = {
+ .enable_reg = 0x8a040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_snoc_axi_clk = {
+ .halt_reg = 0x8a03c,
+ .clkr = {
+ .enable_reg = 0x8a03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_snoc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_names = (const char *[]){
+ "pdm2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x33004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x33004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x34004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ahb_clk = {
+ .halt_reg = 0x4d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ser_clk = {
+ .halt_reg = 0x4d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ser_clk",
+ .parent_names = (const char *[]){
+ "qspi_ser_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx0_usb2_clkref_clk = {
+ .halt_reg = 0x88018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx0_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx1_usb2_clkref_clk = {
+ .halt_reg = 0x88014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx1_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x16008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x16004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x1600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x14008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x14004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ahb_clk = {
+ .halt_reg = 0x7500c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7500c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+ .halt_reg = 0x75008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_clkref_clk = {
+ .halt_reg = 0x88008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x88008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ice_core_clk = {
+ .halt_reg = 0x7600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ice_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_aux_clk = {
+ .halt_reg = 0x76040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "ufs_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+ .halt_reg = 0x75014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+ .halt_reg = 0x7605c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x7605c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+ .halt_reg = 0x75010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_unipro_core_clk = {
+ .halt_reg = 0x76008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_unipro_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_unipro_core_clk_src",
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_master_clk = {
+ .halt_reg = 0x2f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_master_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src"
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_mock_utmi_clk = {
+ .halt_reg = 0x2f00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb20_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_sleep_clk = {
+ .halt_reg = 0x2f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0xf008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_master_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0xf010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb30_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0xf00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_clkref_clk = {
+ .halt_reg = 0x8800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .halt_reg = 0x50000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x50000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "usb3_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .halt_reg = 0x50004,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x50004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_pipe_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .halt_reg = 0x6a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc ufs_gdsc = {
+ .gdscr = 0x75004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "ufs_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc usb_30_gdsc = {
+ .gdscr = 0xf004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "usb_30_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc pcie_0_gdsc = {
+ .gdscr = 0x6b004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+struct clk_hw *gcc_sdm660_hws[] = {
+ [GCC_XO] = &xo.hw,
+ [GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
+ [GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,
+};
+
+static struct clk_regmap *gcc_660_clocks[] = {
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
+ [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
+ [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+ [GCC_BIMC_HMSS_AXI_CLK] = &gcc_bimc_hmss_axi_clk.clkr,
+ [GCC_BIMC_MSS_Q6_AXI_CLK] = &gcc_bimc_mss_q6_axi_clk.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CFG_NOC_USB2_AXI_CLK] = &gcc_cfg_noc_usb2_axi_clk.clkr,
+ [GCC_CFG_NOC_USB3_AXI_CLK] = &gcc_cfg_noc_usb3_axi_clk.clkr,
+ [GCC_DCC_AHB_CLK] = &gcc_dcc_ahb_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GPU_BIMC_GFX_CLK] = &gcc_gpu_bimc_gfx_clk.clkr,
+ [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+ [GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
+ [GCC_HMSS_DVM_BUS_CLK] = &gcc_hmss_dvm_bus_clk.clkr,
+ [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
+ [GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
+ [GCC_MMSS_GPLL0_DIV_CLK] = &gcc_mmss_gpll0_div_clk.clkr,
+ [GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr,
+ [GCC_MMSS_SYS_NOC_AXI_CLK] = &gcc_mmss_sys_noc_axi_clk.clkr,
+ [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
+ [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
+ [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
+ [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
+ [GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr,
+ [GCC_RX0_USB2_CLKREF_CLK] = &gcc_rx0_usb2_clkref_clk.clkr,
+ [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+ [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+ [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
+ [GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr,
+ [GCC_UFS_PHY_AUX_CLK] = &gcc_ufs_phy_aux_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+ [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+ [GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr,
+ [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
+ [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
+ [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+ [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+ [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_EARLY] = &gpll0_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL1_EARLY] = &gpll1_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
+ [HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
+ [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+ [UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr,
+ [UFS_PHY_AUX_CLK_SRC] = &ufs_phy_aux_clk_src.clkr,
+ [UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
+ [USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr,
+ [USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+};
+
+static struct gdsc *gcc_660_gdscs[] = {
+ [UFS_GDSC] = &ufs_gdsc,
+ [USB_30_GDSC] = &usb_30_gdsc,
+ [PCIE_0_GDSC] = &pcie_0_gdsc,
+};
+
+static const struct qcom_reset_map gcc_660_resets[] = {
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+ [GCC_UFS_BCR] = { 0x75000 },
+ [GCC_USB3_DP_PHY_BCR] = { 0x50028 },
+ [GCC_USB3_PHY_BCR] = { 0x50020 },
+ [GCC_USB3PHY_PHY_BCR] = { 0x50024 },
+ [GCC_USB_20_BCR] = { 0x2f000 },
+ [GCC_USB_30_BCR] = { 0xf000 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+};
+
+static const struct regmap_config gcc_660_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x94000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_660_desc = {
+ .config = &gcc_660_regmap_config,
+ .clks = gcc_660_clocks,
+ .num_clks = ARRAY_SIZE(gcc_660_clocks),
+ .resets = gcc_660_resets,
+ .num_resets = ARRAY_SIZE(gcc_660_resets),
+ .gdscs = gcc_660_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_660_gdscs),
+};
+
+static const struct of_device_id gcc_660_match_table[] = {
+ { .compatible = "qcom,gcc-sdm660" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_660_match_table);
+
+static int gcc_660_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gcc_660_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /*
+ * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
+ * turned off by hardware during certain apps low power modes.
+ */
+ ret = regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
+ if (ret)
+ return ret;
+
+ /* Register the hws */
+ for (i = 0; i < ARRAY_SIZE(gcc_sdm660_hws); i++) {
+ ret = devm_clk_hw_register(&pdev->dev, gcc_sdm660_hws[i]);
+ if (ret)
+ return ret;
+ }
+
+ return qcom_cc_really_probe(pdev, &gcc_660_desc, regmap);
+}
+
+static struct platform_driver gcc_660_driver = {
+ .probe = gcc_660_probe,
+ .driver = {
+ .name = "gcc-sdm660",
+ .of_match_table = gcc_660_match_table,
+ },
+};
+
+static int __init gcc_660_init(void)
+{
+ return platform_driver_register(&gcc_660_driver);
+}
+core_initcall_sync(gcc_660_init);
+
+static void __exit gcc_660_exit(void)
+{
+ platform_driver_unregister(&gcc_660_driver);
+}
+module_exit(gcc_660_exit);
+
+MODULE_DESCRIPTION("QCOM GCC sdm660 Driver");
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
new file mode 100644
index 000000000000..76aabcc5e7e3
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_660_H
+#define _DT_BINDINGS_CLK_MSM_GCC_660_H
+
+#define GCC_XO 0
+#define GCC_GPLL0_EARLY_DIV 1
+#define GCC_GPLL1_EARLY_DIV 2
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
+#define BLSP1_UART1_APPS_CLK_SRC 11
+#define BLSP1_UART2_APPS_CLK_SRC 12
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
+#define BLSP2_UART1_APPS_CLK_SRC 21
+#define BLSP2_UART2_APPS_CLK_SRC 22
+#define GCC_AGGRE2_UFS_AXI_CLK 23
+#define GCC_AGGRE2_USB3_AXI_CLK 24
+#define GCC_BIMC_GFX_CLK 25
+#define GCC_BIMC_HMSS_AXI_CLK 26
+#define GCC_BIMC_MSS_Q6_AXI_CLK 27
+#define GCC_BLSP1_AHB_CLK 28
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 29
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 30
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 31
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 32
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 33
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 34
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 35
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 36
+#define GCC_BLSP1_UART1_APPS_CLK 37
+#define GCC_BLSP1_UART2_APPS_CLK 38
+#define GCC_BLSP2_AHB_CLK 39
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 40
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 41
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 42
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 43
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 44
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 46
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 45
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 46
+#define GCC_BLSP2_UART1_APPS_CLK 47
+#define GCC_BLSP2_UART2_APPS_CLK 48
+#define GCC_BOOT_ROM_AHB_CLK 49
+#define GCC_CFG_NOC_USB2_AXI_CLK 50
+#define GCC_CFG_NOC_USB3_AXI_CLK 51
+#define GCC_DCC_AHB_CLK 52
+#define GCC_GP1_CLK 53
+#define GCC_GP2_CLK 54
+#define GCC_GP3_CLK 55
+#define GCC_GPU_BIMC_GFX_CLK 56
+#define GCC_GPU_CFG_AHB_CLK 57
+#define GCC_GPU_GPLL0_CLK 58
+#define GCC_GPU_GPLL0_DIV_CLK 59
+#define GCC_HMSS_DVM_BUS_CLK 60
+#define GCC_HMSS_RBCPR_CLK 61
+#define GCC_MMSS_GPLL0_CLK 62
+#define GCC_MMSS_GPLL0_DIV_CLK 63
+#define GCC_MMSS_NOC_CFG_AHB_CLK 64
+#define GCC_MMSS_SYS_NOC_AXI_CLK 65
+#define GCC_MSS_CFG_AHB_CLK 66
+#define GCC_MSS_GPLL0_DIV_CLK 67
+#define GCC_MSS_MNOC_BIMC_AXI_CLK 68
+#define GCC_MSS_Q6_BIMC_AXI_CLK 69
+#define GCC_MSS_SNOC_AXI_CLK 70
+#define GCC_PDM2_CLK 71
+#define GCC_PDM_AHB_CLK 72
+#define GCC_PRNG_AHB_CLK 73
+#define GCC_QSPI_AHB_CLK 74
+#define GCC_QSPI_SER_CLK 75
+#define GCC_SDCC1_AHB_CLK 76
+#define GCC_SDCC1_APPS_CLK 77
+#define GCC_SDCC1_ICE_CORE_CLK 78
+#define GCC_SDCC2_AHB_CLK 79
+#define GCC_SDCC2_APPS_CLK 80
+#define GCC_UFS_AHB_CLK 81
+#define GCC_UFS_AXI_CLK 82
+#define GCC_UFS_CLKREF_CLK 83
+#define GCC_UFS_ICE_CORE_CLK 84
+#define GCC_UFS_PHY_AUX_CLK 85
+#define GCC_UFS_RX_SYMBOL_0_CLK 86
+#define GCC_UFS_RX_SYMBOL_1_CLK 87
+#define GCC_UFS_TX_SYMBOL_0_CLK 88
+#define GCC_UFS_UNIPRO_CORE_CLK 89
+#define GCC_USB20_MASTER_CLK 90
+#define GCC_USB20_MOCK_UTMI_CLK 91
+#define GCC_USB20_SLEEP_CLK 92
+#define GCC_USB30_MASTER_CLK 93
+#define GCC_USB30_MOCK_UTMI_CLK 94
+#define GCC_USB30_SLEEP_CLK 95
+#define GCC_USB3_CLKREF_CLK 96
+#define GCC_USB3_PHY_AUX_CLK 97
+#define GCC_USB3_PHY_PIPE_CLK 98
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 99
+#define GP1_CLK_SRC 100
+#define GP2_CLK_SRC 101
+#define GP3_CLK_SRC 102
+#define GPLL0 103
+#define GPLL0_EARLY 104
+#define GPLL1 105
+#define GPLL1_EARLY 106
+#define GPLL4 107
+#define GPLL4_EARLY 108
+#define HMSS_GPLL0_CLK_SRC 109
+#define HMSS_GPLL4_CLK_SRC 110
+#define HMSS_RBCPR_CLK_SRC 111
+#define PDM2_CLK_SRC 112
+#define QSPI_SER_CLK_SRC 113
+#define SDCC1_APPS_CLK_SRC 114
+#define SDCC1_ICE_CORE_CLK_SRC 115
+#define SDCC2_APPS_CLK_SRC 116
+#define UFS_AXI_CLK_SRC 117
+#define UFS_ICE_CORE_CLK_SRC 118
+#define UFS_PHY_AUX_CLK_SRC 119
+#define UFS_UNIPRO_CORE_CLK_SRC 120
+#define USB20_MASTER_CLK_SRC 121
+#define USB20_MOCK_UTMI_CLK_SRC 122
+#define USB30_MASTER_CLK_SRC 123
+#define USB30_MOCK_UTMI_CLK_SRC 124
+#define USB3_PHY_AUX_CLK_SRC 125
+#define GPLL0_OUT_MSSCC 126
+#define GCC_UFS_AXI_HW_CTL_CLK 127
+#define GCC_UFS_ICE_CORE_HW_CTL_CLK 128
+#define GCC_UFS_PHY_AUX_HW_CTL_CLK 129
+#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 130
+#define GCC_RX0_USB2_CLKREF_CLK 131
+#define GCC_RX1_USB2_CLKREF_CLK 132
+
+#define PCIE_0_GDSC 0
+#define UFS_GDSC 1
+#define USB_30_GDSC 2
+
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_UFS_BCR 2
+#define GCC_USB3_DP_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB3PHY_PHY_BCR 5
+#define GCC_USB_20_BCR 6
+#define GCC_USB_30_BCR 7
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
+
+#endif
--
2.18.0


2018-08-11 21:31:56

by Fengguang Wu

[permalink] [raw]
Subject: [RFC PATCH] clk: qcom: gcc_sdm660_hws[] can be static


Fixes: 851e534f5d75 ("clk: qcom: Add Global Clock controller (GCC) driver for SDM660")
Signed-off-by: kbuild test robot <[email protected]>
---
gcc-sdm660.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index bdb445a..cec8b41 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -2252,7 +2252,7 @@ static struct gdsc pcie_0_gdsc = {
.flags = VOTABLE,
};

-struct clk_hw *gcc_sdm660_hws[] = {
+static struct clk_hw *gcc_sdm660_hws[] = {
[GCC_XO] = &xo.hw,
[GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
[GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,

2018-08-11 21:32:40

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

Hi Craig,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on agross/for-next]
[also build test WARNING on v4.18-rc8]
[cannot apply to next-20180810]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Craig-Tatlor/clk-qcom-Add-Global-Clock-controller-GCC-driver-for-SDM660/20180811-150111
base: https://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> drivers/clk/qcom/gcc-sdm660.c:2255:15: sparse: symbol 'gcc_sdm660_hws' was not declared. Should it be static?
drivers/clk/qcom/gcc-sdm660.c:2304:10: sparse: Initializer entry defined twice
drivers/clk/qcom/gcc-sdm660.c:2306:10: also defined here

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

2018-08-13 07:45:39

by Taniya Das

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

Hello Craig,

Could you please correct the authorship and also provide the reference
to code where this is picked from?

On 8/11/2018 1:51 AM, Craig Tatlor wrote:
> Add support for the global clock controller found on SDM660
> based devices. This should allow most non-multimedia device
> drivers to probe and control their clocks.
> Based on CAF implementation.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
> .../devicetree/bindings/clock/qcom,gcc.txt | 1 +
> drivers/clk/qcom/Kconfig | 9 +
> drivers/clk/qcom/Makefile | 1 +
> drivers/clk/qcom/gcc-sdm660.c | 2479 +++++++++++++++++
> include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
> 5 files changed, 2649 insertions(+)
> create mode 100644 drivers/clk/qcom/gcc-sdm660.c
> create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h
>
> diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
> index 664ea1fd6c76..e498ad2e8db8 100644
> --- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
> +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
> @@ -19,6 +19,7 @@ Required properties :
> "qcom,gcc-msm8996"
> "qcom,gcc-msm8998"
> "qcom,gcc-mdm9615"
> + "qcom,gcc-sdm660"
> "qcom,gcc-sdm845"
>
> - reg : shall contain base register location and length
> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
> index 9c3480dcc38a..c4bda6d24c1f 100644
> --- a/drivers/clk/qcom/Kconfig
> +++ b/drivers/clk/qcom/Kconfig
> @@ -226,6 +226,15 @@ config MSM_GCC_8998
> Say Y if you want to use peripheral devices such as UART, SPI,
> i2c, USB, UFS, SD/eMMC, PCIe, etc.
>
> +config SDM_GCC_660
> + tristate "SDM660 Global Clock Controller"
> + select QCOM_GDSC
> + depends on COMMON_CLK_QCOM
> + help
> + Support for the global clock controller on SDM660 devices.
> + Say Y if you want to use peripheral devices such as UART, SPI,
> + i2C, USB, UFS, SDDC, PCIe, etc.
> +
> config SDM_GCC_845
> tristate "SDM845 Global Clock Controller"
> select QCOM_GDSC
> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
> index 762c01137c2f..6e37d30d7c02 100644
> --- a/drivers/clk/qcom/Makefile
> +++ b/drivers/clk/qcom/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
> obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
> obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
> obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
> +obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
> obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
> obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
> obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
> diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
> new file mode 100644
> index 000000000000..bdb445aa4baa
> --- /dev/null
> +++ b/drivers/clk/qcom/gcc-sdm660.c
> @@ -0,0 +1,2479 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2018, Craig Tatlor.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/bitops.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/clk-provider.h>
> +#include <linux/regmap.h>
> +#include <linux/reset-controller.h>
> +
> +#include <dt-bindings/clock/qcom,gcc-sdm660.h>
> +
> +#include "common.h"
> +#include "clk-regmap.h"
> +#include "clk-alpha-pll.h"
> +#include "clk-rcg.h"
> +#include "clk-branch.h"
> +#include "reset.h"
> +#include "gdsc.h"
> +
> +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
> +
> +enum {
> + P_XO,
> + P_SLEEP_CLK,
> + P_GPLL0,
> + P_GPLL1,
> + P_GPLL4,
> + P_GPLL0_EARLY_DIV,
> + P_GPLL1_EARLY_DIV,
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> + { P_GPLL0_EARLY_DIV, 6 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
> + "xo",
> + "gpll0",
> + "gpll0_early_div",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0[] = {
> + "xo",
> + "gpll0",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> + { P_SLEEP_CLK, 5 },
> + { P_GPLL0_EARLY_DIV, 6 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
> + "xo",
> + "gpll0",
> + "sleep_clk",
> + "gpll0_early_div",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
> + { P_XO, 0 },
> + { P_SLEEP_CLK, 5 },
> +};
> +
> +static const char * const gcc_parent_names_xo_sleep_clk[] = {
> + "xo",
> + "sleep_clk",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll4[] = {
> + { P_XO, 0 },
> + { P_GPLL4, 5 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll4[] = {
> + "xo",
> + "gpll4",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> + { P_GPLL0_EARLY_DIV, 3 },
> + { P_GPLL1, 4 },
> + { P_GPLL4, 5 },
> + { P_GPLL1_EARLY_DIV, 6 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
> + "xo",
> + "gpll0",
> + "gpll0_early_div",
> + "gpll1",
> + "gpll4",
> + "gpll1_early_div",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> + { P_GPLL4, 5 },
> + { P_GPLL0_EARLY_DIV, 6 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
> + "xo",
> + "gpll0",
> + "gpll4",
> + "gpll0_early_div",
> +};
> +
> +static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
> + { P_XO, 0 },
> + { P_GPLL0, 1 },
> + { P_GPLL0_EARLY_DIV, 2 },
> + { P_GPLL4, 5 },
> +};
> +
> +static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
> + "xo",
> + "gpll0",
> + "gpll0_early_div",
> + "gpll4",
> +};
> +
> +static struct clk_fixed_factor xo = {
> + .mult = 1,
> + .div = 1,
> + .hw.init = &(struct clk_init_data){
> + .name = "xo",
> + .parent_names = (const char *[]){ "xo_board" },
> + .num_parents = 1,
> + .ops = &clk_fixed_factor_ops,
> + },
> +};
> +
> +static struct clk_alpha_pll gpll0_early = {
> + .offset = 0x0,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr = {
> + .enable_reg = 0x52000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gpll0_early",
> + .parent_names = (const char *[]){ "xo" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_ops,
> + },
> + },
> +};
> +
> +static struct clk_fixed_factor gpll0_early_div = {
> + .mult = 1,
> + .div = 2,
> + .hw.init = &(struct clk_init_data){
> + .name = "gpll0_early_div",
> + .parent_names = (const char *[]){ "gpll0_early" },
> + .num_parents = 1,
> + .ops = &clk_fixed_factor_ops,
> + },
> +};
> +
> +static struct clk_alpha_pll_postdiv gpll0 = {
> + .offset = 0x00000,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "gpll0",
> + .parent_names = (const char *[]){ "gpll0_early" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_postdiv_ops,
> + },
> +};
> +
> +static struct clk_alpha_pll gpll1_early = {
> + .offset = 0x1000,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr = {
> + .enable_reg = 0x52000,
> + .enable_mask = BIT(1),
> + .hw.init = &(struct clk_init_data){
> + .name = "gpll1_early",
> + .parent_names = (const char *[]){ "xo" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_ops,
> + },
> + },
> +};
> +
> +static struct clk_fixed_factor gpll1_early_div = {
> + .mult = 1,
> + .div = 2,
> + .hw.init = &(struct clk_init_data){
> + .name = "gpll1_early_div",
> + .parent_names = (const char *[]){ "gpll1_early" },
> + .num_parents = 1,
> + .ops = &clk_fixed_factor_ops,
> + },
> +};
> +
> +static struct clk_alpha_pll_postdiv gpll1 = {
> + .offset = 0x1000,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "gpll1",
> + .parent_names = (const char *[]){ "gpll1_early" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_postdiv_ops,
> + },
> +};
> +
> +static struct clk_alpha_pll gpll4_early = {
> + .offset = 0x77000,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr = {
> + .enable_reg = 0x52000,
> + .enable_mask = BIT(4),
> + .hw.init = &(struct clk_init_data){
> + .name = "gpll4_early",
> + .parent_names = (const char *[]){ "xo" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_ops,
> + },
> + },
> +};
> +
> +static struct clk_alpha_pll_postdiv gpll4 = {
> + .offset = 0x77000,
> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
> + .clkr.hw.init = &(struct clk_init_data)
> + {
> + .name = "gpll4",
> + .parent_names = (const char *[]) { "gpll4_early" },
> + .num_parents = 1,
> + .ops = &clk_alpha_pll_postdiv_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(50000000, P_GPLL0, 12, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x19020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup1_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
> + F(960000, P_XO, 10, 1, 2),
> + F(4800000, P_XO, 4, 0, 0),
> + F(9600000, P_XO, 2, 0, 0),
> + F(15000000, P_GPLL0, 10, 1, 4),
> + F(19200000, P_XO, 1, 0, 0),
> + F(25000000, P_GPLL0, 12, 1, 2),
> + F(50000000, P_GPLL0, 12, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
> + .cmd_rcgr = 0x1900c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup1_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x1b020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup2_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
> + .cmd_rcgr = 0x1b00c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup2_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x1d020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup3_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
> + .cmd_rcgr = 0x1d00c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup3_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x1f020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup4_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
> + .cmd_rcgr = 0x1f00c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_qup4_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
> + F(3686400, P_GPLL0, 1, 96, 15625),
> + F(7372800, P_GPLL0, 1, 192, 15625),
> + F(14745600, P_GPLL0, 1, 384, 15625),
> + F(16000000, P_GPLL0, 5, 2, 15),
> + F(19200000, P_XO, 1, 0, 0),
> + F(24000000, P_GPLL0, 5, 1, 5),
> + F(32000000, P_GPLL0, 1, 4, 75),
> + F(40000000, P_GPLL0, 15, 0, 0),
> + F(46400000, P_GPLL0, 1, 29, 375),
> + F(48000000, P_GPLL0, 12.5, 0, 0),
> + F(51200000, P_GPLL0, 1, 32, 375),
> + F(56000000, P_GPLL0, 1, 7, 75),
> + F(58982400, P_GPLL0, 1, 1536, 15625),
> + F(60000000, P_GPLL0, 10, 0, 0),
> + F(63157895, P_GPLL0, 9.5, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
> + .cmd_rcgr = 0x1a00c,
> + .mnd_width = 16,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_uart1_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
> + .cmd_rcgr = 0x1c00c,
> + .mnd_width = 16,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp1_uart2_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x26020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup1_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
> + .cmd_rcgr = 0x2600c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup1_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x28020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup2_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
> + .cmd_rcgr = 0x2800c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup2_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x2a020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup3_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
> + .cmd_rcgr = 0x2a00c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup3_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
> + .cmd_rcgr = 0x2c020,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup4_i2c_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
> + .cmd_rcgr = 0x2c00c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_qup4_spi_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
> + .cmd_rcgr = 0x2700c,
> + .mnd_width = 16,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_uart1_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
> + .cmd_rcgr = 0x2900c,
> + .mnd_width = 16,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "blsp2_uart2_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_gp1_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(100000000, P_GPLL0, 6, 0, 0),
> + F(200000000, P_GPLL0, 3, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 gp1_clk_src = {
> + .cmd_rcgr = 0x64004,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
> + .freq_tbl = ftbl_gp1_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "gp1_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
> + .num_parents = 4,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 gp2_clk_src = {
> + .cmd_rcgr = 0x65004,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
> + .freq_tbl = ftbl_gp1_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "gp2_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
> + .num_parents = 4,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 gp3_clk_src = {
> + .cmd_rcgr = 0x66004,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
> + .freq_tbl = ftbl_gp1_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "gp3_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
> + .num_parents = 4,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
> + F(300000000, P_GPLL0, 2, 0, 0),
> + F(600000000, P_GPLL0, 1, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 hmss_gpll0_clk_src = {
> + .cmd_rcgr = 0x4805c,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_hmss_gpll0_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "hmss_gpll0_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
> + F(384000000, P_GPLL4, 4, 0, 0),
> + F(768000000, P_GPLL4, 2, 0, 0),
> + F(1536000000, P_GPLL4, 1, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 hmss_gpll4_clk_src = {
> + .cmd_rcgr = 0x48074,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll4,
> + .freq_tbl = ftbl_hmss_gpll4_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "hmss_gpll4_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll4,
> + .num_parents = 2,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 hmss_rbcpr_clk_src = {
> + .cmd_rcgr = 0x48044,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "hmss_rbcpr_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0,
> + .num_parents = 2,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_pdm2_clk_src[] = {
> + F(60000000, P_GPLL0, 10, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 pdm2_clk_src = {
> + .cmd_rcgr = 0x33010,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_pdm2_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "pdm2_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
> + F(160400000, P_GPLL1, 5, 0, 0),
> + F(267333333, P_GPLL1, 3, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 qspi_ser_clk_src = {
> + .cmd_rcgr = 0x4d00c,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
> + .freq_tbl = ftbl_qspi_ser_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "qspi_ser_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
> + .num_parents = 6,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
> + F(144000, P_XO, 16, 3, 25),
> + F(400000, P_XO, 12, 1, 4),
> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
> + F(100000000, P_GPLL0, 6, 0, 0),
> + F(192000000, P_GPLL4, 8, 0, 0),
> + F(384000000, P_GPLL4, 4, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 sdcc1_apps_clk_src = {
> + .cmd_rcgr = 0x1602c,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
> + .freq_tbl = ftbl_sdcc1_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "sdcc1_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
> + .num_parents = 4,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
> + F(150000000, P_GPLL0, 4, 0, 0),
> + F(200000000, P_GPLL0, 3, 0, 0),
> + F(300000000, P_GPLL0, 2, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 sdcc1_ice_core_clk_src = {
> + .cmd_rcgr = 0x16010,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "sdcc1_ice_core_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
> + F(144000, P_XO, 16, 3, 25),
> + F(400000, P_XO, 12, 1, 4),
> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
> + F(100000000, P_GPLL0, 6, 0, 0),
> + F(192000000, P_GPLL4, 8, 0, 0),
> + F(200000000, P_GPLL0, 3, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 sdcc2_apps_clk_src = {
> + .cmd_rcgr = 0x14010,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
> + .freq_tbl = ftbl_sdcc2_apps_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "sdcc2_apps_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
> + .num_parents = 4,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
> + F(100000000, P_GPLL0, 6, 0, 0),
> + F(150000000, P_GPLL0, 4, 0, 0),
> + F(200000000, P_GPLL0, 3, 0, 0),
> + F(240000000, P_GPLL0, 2.5, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 ufs_axi_clk_src = {
> + .cmd_rcgr = 0x75018,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_ufs_axi_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "ufs_axi_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
> + F(150000000, P_GPLL0, 4, 0, 0),
> + F(300000000, P_GPLL0, 2, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 ufs_ice_core_clk_src = {
> + .cmd_rcgr = 0x76010,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_ufs_ice_core_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "ufs_ice_core_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_rcg2 ufs_phy_aux_clk_src = {
> + .cmd_rcgr = 0x76044,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_sleep_clk,
> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "ufs_phy_aux_clk_src",
> + .parent_names = gcc_parent_names_xo_sleep_clk,
> + .num_parents = 2,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
> + F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
> + F(75000000, P_GPLL0, 8, 0, 0),
> + F(150000000, P_GPLL0, 4, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 ufs_unipro_core_clk_src = {
> + .cmd_rcgr = 0x76028,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_ufs_unipro_core_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "ufs_unipro_core_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(60000000, P_GPLL0, 10, 0, 0),
> + F(120000000, P_GPLL0, 5, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 usb20_master_clk_src = {
> + .cmd_rcgr = 0x2f010,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_usb20_master_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "usb20_master_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(60000000, P_GPLL0, 10, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 usb20_mock_utmi_clk_src = {
> + .cmd_rcgr = 0x2f024,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "usb20_mock_utmi_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
> + F(120000000, P_GPLL0, 5, 0, 0),
> + F(133333333, P_GPLL0, 4.5, 0, 0),
> + F(150000000, P_GPLL0, 4, 0, 0),
> + F(200000000, P_GPLL0, 3, 0, 0),
> + F(240000000, P_GPLL0, 2.5, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 usb30_master_clk_src = {
> + .cmd_rcgr = 0xf014,
> + .mnd_width = 8,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_usb30_master_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "usb30_master_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
> + F(19200000, P_XO, 1, 0, 0),
> + F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
> + F(60000000, P_GPLL0, 10, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 usb30_mock_utmi_clk_src = {
> + .cmd_rcgr = 0xf028,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
> + .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "usb30_mock_utmi_clk_src",
> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
> + .num_parents = 3,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
> + F(1200000, P_XO, 16, 0, 0),
> + F(19200000, P_XO, 1, 0, 0),
> + { }
> +};
> +
> +static struct clk_rcg2 usb3_phy_aux_clk_src = {
> + .cmd_rcgr = 0x5000c,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = gcc_parent_map_xo_sleep_clk,
> + .freq_tbl = ftbl_usb3_phy_aux_clk_src,
> + .clkr.hw.init = &(struct clk_init_data){
> + .name = "usb3_phy_aux_clk_src",
> + .parent_names = gcc_parent_names_xo_sleep_clk,
> + .num_parents = 2,
> + .ops = &clk_rcg2_ops,
> + },
> +};
> +
> +static struct clk_branch gcc_aggre2_ufs_axi_clk = {
> + .halt_reg = 0x75034,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x75034,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_aggre2_ufs_axi_clk",
> + .parent_names = (const char *[]){
> + "ufs_axi_clk_src",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_aggre2_usb3_axi_clk = {
> + .halt_reg = 0xf03c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0xf03c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_aggre2_usb3_axi_clk",
> + .parent_names = (const char *[]){
> + "usb30_master_clk_src",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_bimc_gfx_clk = {
> + .halt_reg = 0x7106c,
> + .halt_check = BRANCH_VOTED,
> + .clkr = {
> + .enable_reg = 0x7106c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_bimc_gfx_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_bimc_hmss_axi_clk = {
> + .halt_reg = 0x48004,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x52004,
> + .enable_mask = BIT(22),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_bimc_hmss_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_bimc_mss_q6_axi_clk = {
> + .halt_reg = 0x4401c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x4401c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_bimc_mss_q6_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_ahb_clk = {
> + .halt_reg = 0x17004,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x52004,
> + .enable_mask = BIT(17),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
> + .halt_reg = 0x19008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x19008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup1_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup1_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
> + .halt_reg = 0x19004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x19004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup1_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup1_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
> + .halt_reg = 0x1b008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1b008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup2_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup2_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
> + .halt_reg = 0x1b004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1b004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup2_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup2_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
> + .halt_reg = 0x1d008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1d008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup3_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup3_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
> + .halt_reg = 0x1d004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1d004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup3_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup3_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
> + .halt_reg = 0x1f008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1f008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup4_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup4_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
> + .halt_reg = 0x1f004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1f004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_qup4_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_qup4_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_uart1_apps_clk = {
> + .halt_reg = 0x1a004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1a004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_uart1_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_uart1_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp1_uart2_apps_clk = {
> + .halt_reg = 0x1c004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1c004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp1_uart2_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp1_uart2_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_ahb_clk = {
> + .halt_reg = 0x25004,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x52004,
> + .enable_mask = BIT(15),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
> + .halt_reg = 0x26008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x26008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup1_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup1_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
> + .halt_reg = 0x26004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x26004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup1_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup1_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
> + .halt_reg = 0x28008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x28008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup2_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup2_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
> + .halt_reg = 0x28004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x28004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup2_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup2_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
> + .halt_reg = 0x2a008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2a008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup3_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup3_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
> + .halt_reg = 0x2a004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2a004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup3_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup3_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
> + .halt_reg = 0x2c008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2c008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup4_i2c_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup4_i2c_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
> + .halt_reg = 0x2c004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2c004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_qup4_spi_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_qup4_spi_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_uart1_apps_clk = {
> + .halt_reg = 0x27004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x27004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_uart1_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_uart1_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_blsp2_uart2_apps_clk = {
> + .halt_reg = 0x29004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x29004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_blsp2_uart2_apps_clk",
> + .parent_names = (const char *[]){
> + "blsp2_uart2_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_boot_rom_ahb_clk = {
> + .halt_reg = 0x38004,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x52004,
> + .enable_mask = BIT(10),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_boot_rom_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_cfg_noc_usb2_axi_clk = {
> + .halt_reg = 0x5058,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x5058,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_cfg_noc_usb2_axi_clk",
> + .parent_names = (const char *[]){
> + "usb20_master_clk_src",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
> + .halt_reg = 0x5018,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x5018,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_cfg_noc_usb3_axi_clk",
> + .parent_names = (const char *[]){
> + "usb30_master_clk_src",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_dcc_ahb_clk = {
> + .halt_reg = 0x84004,
> + .clkr = {
> + .enable_reg = 0x84004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_dcc_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gp1_clk = {
> + .halt_reg = 0x64000,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x64000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gp1_clk",
> + .parent_names = (const char *[]){
> + "gp1_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gp2_clk = {
> + .halt_reg = 0x65000,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x65000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gp2_clk",
> + .parent_names = (const char *[]){
> + "gp2_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gp3_clk = {
> + .halt_reg = 0x66000,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x66000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gp3_clk",
> + .parent_names = (const char *[]){
> + "gp3_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gpu_bimc_gfx_clk = {
> + .halt_reg = 0x71010,
> + .halt_check = BRANCH_VOTED,
> + .clkr = {
> + .enable_reg = 0x71010,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gpu_bimc_gfx_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gpu_cfg_ahb_clk = {
> + .halt_reg = 0x71004,
> + .halt_check = BRANCH_VOTED,
> + .clkr = {
> + .enable_reg = 0x71004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gpu_cfg_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gpu_gpll0_clk = {
> + .halt_reg = 0x5200c,
> + .halt_check = BRANCH_HALT_DELAY,
> + .clkr = {
> + .enable_reg = 0x5200c,
> + .enable_mask = BIT(4),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gpu_gpll0_clk",
> + .parent_names = (const char *[]){
> + "gpll0",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_gpu_gpll0_div_clk = {
> + .halt_reg = 0x5200c,
> + .halt_check = BRANCH_HALT_DELAY,
> + .clkr = {
> + .enable_reg = 0x5200c,
> + .enable_mask = BIT(3),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_gpu_gpll0_div_clk",
> + .parent_names = (const char *[]){
> + "gpll0_early_div",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_hmss_dvm_bus_clk = {
> + .halt_reg = 0x4808c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x4808c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_hmss_dvm_bus_clk",
> + .ops = &clk_branch2_ops,
> + .flags = CLK_IGNORE_UNUSED,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_hmss_rbcpr_clk = {
> + .halt_reg = 0x48008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x48008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_hmss_rbcpr_clk",
> + .parent_names = (const char *[]){
> + "hmss_rbcpr_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mmss_gpll0_clk = {
> + .halt_reg = 0x5200c,
> + .halt_check = BRANCH_HALT_DELAY,
> + .clkr = {
> + .enable_reg = 0x5200c,
> + .enable_mask = BIT(1),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mmss_gpll0_clk",
> + .parent_names = (const char *[]){
> + "gpll0",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mmss_gpll0_div_clk = {
> + .halt_reg = 0x5200c,
> + .halt_check = BRANCH_HALT_DELAY,
> + .clkr = {
> + .enable_reg = 0x5200c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mmss_gpll0_div_clk",
> + .parent_names = (const char *[]){
> + "gpll0_early_div",
> + },
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
> + .halt_reg = 0x9004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x9004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mmss_noc_cfg_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mmss_sys_noc_axi_clk = {
> + .halt_reg = 0x9000,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x9000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mmss_sys_noc_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mss_cfg_ahb_clk = {
> + .halt_reg = 0x8a000,
> + .clkr = {
> + .enable_reg = 0x8a000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mss_cfg_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
> + .halt_reg = 0x8a004,
> + .clkr = {
> + .enable_reg = 0x8a004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mss_mnoc_bimc_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
> + .halt_reg = 0x8a040,
> + .clkr = {
> + .enable_reg = 0x8a040,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mss_q6_bimc_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_mss_snoc_axi_clk = {
> + .halt_reg = 0x8a03c,
> + .clkr = {
> + .enable_reg = 0x8a03c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_mss_snoc_axi_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_pdm2_clk = {
> + .halt_reg = 0x3300c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x3300c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_pdm2_clk",
> + .parent_names = (const char *[]){
> + "pdm2_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_pdm_ahb_clk = {
> + .halt_reg = 0x33004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x33004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_pdm_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_prng_ahb_clk = {
> + .halt_reg = 0x34004,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x52004,
> + .enable_mask = BIT(13),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_prng_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_qspi_ahb_clk = {
> + .halt_reg = 0x4d004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x4d004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_qspi_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_qspi_ser_clk = {
> + .halt_reg = 0x4d008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x4d008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_qspi_ser_clk",
> + .parent_names = (const char *[]){
> + "qspi_ser_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_rx0_usb2_clkref_clk = {
> + .halt_reg = 0x88018,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x88018,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_rx0_usb2_clkref_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_rx1_usb2_clkref_clk = {
> + .halt_reg = 0x88014,
> + .halt_check = BRANCH_HALT_VOTED,
> + .clkr = {
> + .enable_reg = 0x88014,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_rx1_usb2_clkref_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_sdcc1_ahb_clk = {
> + .halt_reg = 0x16008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x16008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_sdcc1_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_sdcc1_apps_clk = {
> + .halt_reg = 0x16004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x16004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_sdcc1_apps_clk",
> + .parent_names = (const char *[]){
> + "sdcc1_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_sdcc1_ice_core_clk = {
> + .halt_reg = 0x1600c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x1600c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_sdcc1_ice_core_clk",
> + .parent_names = (const char *[]){
> + "sdcc1_ice_core_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_sdcc2_ahb_clk = {
> + .halt_reg = 0x14008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x14008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_sdcc2_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_sdcc2_apps_clk = {
> + .halt_reg = 0x14004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x14004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_sdcc2_apps_clk",
> + .parent_names = (const char *[]){
> + "sdcc2_apps_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_ahb_clk = {
> + .halt_reg = 0x7500c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x7500c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_ahb_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_axi_clk = {
> + .halt_reg = 0x75008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x75008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_axi_clk",
> + .parent_names = (const char *[]){
> + "ufs_axi_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_clkref_clk = {
> + .halt_reg = 0x88008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x88008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_clkref_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_ice_core_clk = {
> + .halt_reg = 0x7600c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x7600c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_ice_core_clk",
> + .parent_names = (const char *[]){
> + "ufs_ice_core_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_phy_aux_clk = {
> + .halt_reg = 0x76040,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x76040,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_phy_aux_clk",
> + .parent_names = (const char *[]){
> + "ufs_phy_aux_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
> + .halt_reg = 0x75014,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x75014,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_rx_symbol_0_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
> + .halt_reg = 0x7605c,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x7605c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_rx_symbol_1_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
> + .halt_reg = 0x75010,
> + .halt_check = BRANCH_HALT_SKIP,
> + .clkr = {
> + .enable_reg = 0x75010,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_tx_symbol_0_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_ufs_unipro_core_clk = {
> + .halt_reg = 0x76008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x76008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_ufs_unipro_core_clk",
> + .parent_names = (const char *[]){
> + "ufs_unipro_core_clk_src",
> + },
> + .flags = CLK_SET_RATE_PARENT,
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb20_master_clk = {
> + .halt_reg = 0x2f004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2f004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb20_master_clk",
> + .parent_names = (const char *[]){
> + "usb20_master_clk_src"
> + },
> + .flags = CLK_SET_RATE_PARENT,
> + .num_parents = 1,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb20_mock_utmi_clk = {
> + .halt_reg = 0x2f00c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2f00c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb20_mock_utmi_clk",
> + .parent_names = (const char *[]){
> + "usb20_mock_utmi_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb20_sleep_clk = {
> + .halt_reg = 0x2f008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x2f008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb20_sleep_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb30_master_clk = {
> + .halt_reg = 0xf008,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0xf008,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb30_master_clk",
> + .parent_names = (const char *[]){
> + "usb30_master_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb30_mock_utmi_clk = {
> + .halt_reg = 0xf010,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0xf010,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb30_mock_utmi_clk",
> + .parent_names = (const char *[]){
> + "usb30_mock_utmi_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb30_sleep_clk = {
> + .halt_reg = 0xf00c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0xf00c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb30_sleep_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb3_clkref_clk = {
> + .halt_reg = 0x8800c,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x8800c,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb3_clkref_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb3_phy_aux_clk = {
> + .halt_reg = 0x50000,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x50000,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb3_phy_aux_clk",
> + .parent_names = (const char *[]){
> + "usb3_phy_aux_clk_src",
> + },
> + .num_parents = 1,
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb3_phy_pipe_clk = {
> + .halt_reg = 0x50004,
> + .halt_check = BRANCH_HALT_DELAY,
> + .clkr = {
> + .enable_reg = 0x50004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb3_phy_pipe_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
> + .halt_reg = 0x6a004,
> + .halt_check = BRANCH_HALT,
> + .clkr = {
> + .enable_reg = 0x6a004,
> + .enable_mask = BIT(0),
> + .hw.init = &(struct clk_init_data){
> + .name = "gcc_usb_phy_cfg_ahb2phy_clk",
> + .ops = &clk_branch2_ops,
> + },
> + },
> +};
> +
> +static struct gdsc ufs_gdsc = {
> + .gdscr = 0x75004,
> + .gds_hw_ctrl = 0x0,
> + .pd = {
> + .name = "ufs_gdsc",
> + },
> + .pwrsts = PWRSTS_OFF_ON,
> + .flags = VOTABLE,
> +};
> +
> +static struct gdsc usb_30_gdsc = {
> + .gdscr = 0xf004,
> + .gds_hw_ctrl = 0x0,
> + .pd = {
> + .name = "usb_30_gdsc",
> + },
> + .pwrsts = PWRSTS_OFF_ON,
> + .flags = VOTABLE,
> +};
> +
> +static struct gdsc pcie_0_gdsc = {
> + .gdscr = 0x6b004,
> + .gds_hw_ctrl = 0x0,
> + .pd = {
> + .name = "pcie_0_gdsc",
> + },
> + .pwrsts = PWRSTS_OFF_ON,
> + .flags = VOTABLE,
> +};
> +
> +struct clk_hw *gcc_sdm660_hws[] = {
> + [GCC_XO] = &xo.hw,
> + [GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
> + [GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,
> +};
> +
> +static struct clk_regmap *gcc_660_clocks[] = {
> + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
> + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
> + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
> + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
> + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
> + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
> + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
> + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
> + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
> + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
> + [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
> + [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
> + [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
> + [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
> + [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
> + [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
> + [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
> + [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
> + [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
> + [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
> + [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
> + [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
> + [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
> + [GCC_BIMC_HMSS_AXI_CLK] = &gcc_bimc_hmss_axi_clk.clkr,
> + [GCC_BIMC_MSS_Q6_AXI_CLK] = &gcc_bimc_mss_q6_axi_clk.clkr,
> + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
> + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
> + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
> + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
> + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
> + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
> + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
> + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
> + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
> + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
> + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
> + [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
> + [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
> + [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
> + [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
> + [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
> + [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
> + [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
> + [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
> + [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
> + [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
> + [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
> + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
> + [GCC_CFG_NOC_USB2_AXI_CLK] = &gcc_cfg_noc_usb2_axi_clk.clkr,
> + [GCC_CFG_NOC_USB3_AXI_CLK] = &gcc_cfg_noc_usb3_axi_clk.clkr,
> + [GCC_DCC_AHB_CLK] = &gcc_dcc_ahb_clk.clkr,
> + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
> + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
> + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
> + [GCC_GPU_BIMC_GFX_CLK] = &gcc_gpu_bimc_gfx_clk.clkr,
> + [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
> + [GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
> + [GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
> + [GCC_HMSS_DVM_BUS_CLK] = &gcc_hmss_dvm_bus_clk.clkr,
> + [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
> + [GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
> + [GCC_MMSS_GPLL0_DIV_CLK] = &gcc_mmss_gpll0_div_clk.clkr,
> + [GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr,
> + [GCC_MMSS_SYS_NOC_AXI_CLK] = &gcc_mmss_sys_noc_axi_clk.clkr,
> + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
> + [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
> + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
> + [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
> + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
> + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
> + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
> + [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
> + [GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr,
> + [GCC_RX0_USB2_CLKREF_CLK] = &gcc_rx0_usb2_clkref_clk.clkr,
> + [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
> + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
> + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
> + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
> + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
> + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
> + [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
> + [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
> + [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
> + [GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr,
> + [GCC_UFS_PHY_AUX_CLK] = &gcc_ufs_phy_aux_clk.clkr,
> + [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
> + [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
> + [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
> + [GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr,
> + [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
> + [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
> + [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr,
> + [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
> + [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
> + [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
> + [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr,
> + [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
> + [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
> + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
> + [GP1_CLK_SRC] = &gp1_clk_src.clkr,
> + [GP2_CLK_SRC] = &gp2_clk_src.clkr,
> + [GP3_CLK_SRC] = &gp3_clk_src.clkr,
> + [GPLL0] = &gpll0.clkr,
> + [GPLL0_EARLY] = &gpll0_early.clkr,
> + [GPLL1] = &gpll1.clkr,
> + [GPLL1_EARLY] = &gpll1_early.clkr,
> + [GPLL1] = &gpll1.clkr,
> + [GPLL4_EARLY] = &gpll4_early.clkr,
> + [GPLL4] = &gpll4.clkr,
> + [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
> + [HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
> + [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
> + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
> + [QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr,
> + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
> + [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
> + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
> + [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
> + [UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr,
> + [UFS_PHY_AUX_CLK_SRC] = &ufs_phy_aux_clk_src.clkr,
> + [UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
> + [USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr,
> + [USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr,
> + [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
> + [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
> + [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
> +};
> +
> +static struct gdsc *gcc_660_gdscs[] = {
> + [UFS_GDSC] = &ufs_gdsc,
> + [USB_30_GDSC] = &usb_30_gdsc,
> + [PCIE_0_GDSC] = &pcie_0_gdsc,
> +};
> +
> +static const struct qcom_reset_map gcc_660_resets[] = {
> + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
> + [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
> + [GCC_UFS_BCR] = { 0x75000 },
> + [GCC_USB3_DP_PHY_BCR] = { 0x50028 },
> + [GCC_USB3_PHY_BCR] = { 0x50020 },
> + [GCC_USB3PHY_PHY_BCR] = { 0x50024 },
> + [GCC_USB_20_BCR] = { 0x2f000 },
> + [GCC_USB_30_BCR] = { 0xf000 },
> + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
> +};
> +
> +static const struct regmap_config gcc_660_regmap_config = {
> + .reg_bits = 32,
> + .reg_stride = 4,
> + .val_bits = 32,
> + .max_register = 0x94000,
> + .fast_io = true,
> +};
> +
> +static const struct qcom_cc_desc gcc_660_desc = {
> + .config = &gcc_660_regmap_config,
> + .clks = gcc_660_clocks,
> + .num_clks = ARRAY_SIZE(gcc_660_clocks),
> + .resets = gcc_660_resets,
> + .num_resets = ARRAY_SIZE(gcc_660_resets),
> + .gdscs = gcc_660_gdscs,
> + .num_gdscs = ARRAY_SIZE(gcc_660_gdscs),
> +};
> +
> +static const struct of_device_id gcc_660_match_table[] = {
> + { .compatible = "qcom,gcc-sdm660" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, gcc_660_match_table);
> +
> +static int gcc_660_probe(struct platform_device *pdev)
> +{
> + int i, ret = 0;
> + struct regmap *regmap;
> +
> + regmap = qcom_cc_map(pdev, &gcc_660_desc);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + /*
> + * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
> + * turned off by hardware during certain apps low power modes.
> + */
> + ret = regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
> + if (ret)
> + return ret;
> +
> + /* Register the hws */
> + for (i = 0; i < ARRAY_SIZE(gcc_sdm660_hws); i++) {
> + ret = devm_clk_hw_register(&pdev->dev, gcc_sdm660_hws[i]);
> + if (ret)
> + return ret;
> + }
> +
> + return qcom_cc_really_probe(pdev, &gcc_660_desc, regmap);
> +}
> +
> +static struct platform_driver gcc_660_driver = {
> + .probe = gcc_660_probe,
> + .driver = {
> + .name = "gcc-sdm660",
> + .of_match_table = gcc_660_match_table,
> + },
> +};
> +
> +static int __init gcc_660_init(void)
> +{
> + return platform_driver_register(&gcc_660_driver);
> +}
> +core_initcall_sync(gcc_660_init);
> +
> +static void __exit gcc_660_exit(void)
> +{
> + platform_driver_unregister(&gcc_660_driver);
> +}
> +module_exit(gcc_660_exit);
> +
> +MODULE_DESCRIPTION("QCOM GCC sdm660 Driver");
> diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
> new file mode 100644
> index 000000000000..76aabcc5e7e3
> --- /dev/null
> +++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
> @@ -0,0 +1,159 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2018, Craig Tatlor.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_MSM_GCC_660_H
> +#define _DT_BINDINGS_CLK_MSM_GCC_660_H
> +
> +#define GCC_XO 0
> +#define GCC_GPLL0_EARLY_DIV 1
> +#define GCC_GPLL1_EARLY_DIV 2
> +#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
> +#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
> +#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
> +#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
> +#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
> +#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
> +#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
> +#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
> +#define BLSP1_UART1_APPS_CLK_SRC 11
> +#define BLSP1_UART2_APPS_CLK_SRC 12
> +#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
> +#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
> +#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
> +#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
> +#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
> +#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
> +#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
> +#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
> +#define BLSP2_UART1_APPS_CLK_SRC 21
> +#define BLSP2_UART2_APPS_CLK_SRC 22
> +#define GCC_AGGRE2_UFS_AXI_CLK 23
> +#define GCC_AGGRE2_USB3_AXI_CLK 24
> +#define GCC_BIMC_GFX_CLK 25
> +#define GCC_BIMC_HMSS_AXI_CLK 26
> +#define GCC_BIMC_MSS_Q6_AXI_CLK 27
> +#define GCC_BLSP1_AHB_CLK 28
> +#define GCC_BLSP1_QUP1_I2C_APPS_CLK 29
> +#define GCC_BLSP1_QUP1_SPI_APPS_CLK 30
> +#define GCC_BLSP1_QUP2_I2C_APPS_CLK 31
> +#define GCC_BLSP1_QUP2_SPI_APPS_CLK 32
> +#define GCC_BLSP1_QUP3_I2C_APPS_CLK 33
> +#define GCC_BLSP1_QUP3_SPI_APPS_CLK 34
> +#define GCC_BLSP1_QUP4_I2C_APPS_CLK 35
> +#define GCC_BLSP1_QUP4_SPI_APPS_CLK 36
> +#define GCC_BLSP1_UART1_APPS_CLK 37
> +#define GCC_BLSP1_UART2_APPS_CLK 38
> +#define GCC_BLSP2_AHB_CLK 39
> +#define GCC_BLSP2_QUP1_I2C_APPS_CLK 40
> +#define GCC_BLSP2_QUP1_SPI_APPS_CLK 41
> +#define GCC_BLSP2_QUP2_I2C_APPS_CLK 42
> +#define GCC_BLSP2_QUP2_SPI_APPS_CLK 43
> +#define GCC_BLSP2_QUP3_I2C_APPS_CLK 44
> +#define GCC_BLSP2_QUP3_SPI_APPS_CLK 46
> +#define GCC_BLSP2_QUP4_I2C_APPS_CLK 45
> +#define GCC_BLSP2_QUP4_SPI_APPS_CLK 46
> +#define GCC_BLSP2_UART1_APPS_CLK 47
> +#define GCC_BLSP2_UART2_APPS_CLK 48
> +#define GCC_BOOT_ROM_AHB_CLK 49
> +#define GCC_CFG_NOC_USB2_AXI_CLK 50
> +#define GCC_CFG_NOC_USB3_AXI_CLK 51
> +#define GCC_DCC_AHB_CLK 52
> +#define GCC_GP1_CLK 53
> +#define GCC_GP2_CLK 54
> +#define GCC_GP3_CLK 55
> +#define GCC_GPU_BIMC_GFX_CLK 56
> +#define GCC_GPU_CFG_AHB_CLK 57
> +#define GCC_GPU_GPLL0_CLK 58
> +#define GCC_GPU_GPLL0_DIV_CLK 59
> +#define GCC_HMSS_DVM_BUS_CLK 60
> +#define GCC_HMSS_RBCPR_CLK 61
> +#define GCC_MMSS_GPLL0_CLK 62
> +#define GCC_MMSS_GPLL0_DIV_CLK 63
> +#define GCC_MMSS_NOC_CFG_AHB_CLK 64
> +#define GCC_MMSS_SYS_NOC_AXI_CLK 65
> +#define GCC_MSS_CFG_AHB_CLK 66
> +#define GCC_MSS_GPLL0_DIV_CLK 67
> +#define GCC_MSS_MNOC_BIMC_AXI_CLK 68
> +#define GCC_MSS_Q6_BIMC_AXI_CLK 69
> +#define GCC_MSS_SNOC_AXI_CLK 70
> +#define GCC_PDM2_CLK 71
> +#define GCC_PDM_AHB_CLK 72
> +#define GCC_PRNG_AHB_CLK 73
> +#define GCC_QSPI_AHB_CLK 74
> +#define GCC_QSPI_SER_CLK 75
> +#define GCC_SDCC1_AHB_CLK 76
> +#define GCC_SDCC1_APPS_CLK 77
> +#define GCC_SDCC1_ICE_CORE_CLK 78
> +#define GCC_SDCC2_AHB_CLK 79
> +#define GCC_SDCC2_APPS_CLK 80
> +#define GCC_UFS_AHB_CLK 81
> +#define GCC_UFS_AXI_CLK 82
> +#define GCC_UFS_CLKREF_CLK 83
> +#define GCC_UFS_ICE_CORE_CLK 84
> +#define GCC_UFS_PHY_AUX_CLK 85
> +#define GCC_UFS_RX_SYMBOL_0_CLK 86
> +#define GCC_UFS_RX_SYMBOL_1_CLK 87
> +#define GCC_UFS_TX_SYMBOL_0_CLK 88
> +#define GCC_UFS_UNIPRO_CORE_CLK 89
> +#define GCC_USB20_MASTER_CLK 90
> +#define GCC_USB20_MOCK_UTMI_CLK 91
> +#define GCC_USB20_SLEEP_CLK 92
> +#define GCC_USB30_MASTER_CLK 93
> +#define GCC_USB30_MOCK_UTMI_CLK 94
> +#define GCC_USB30_SLEEP_CLK 95
> +#define GCC_USB3_CLKREF_CLK 96
> +#define GCC_USB3_PHY_AUX_CLK 97
> +#define GCC_USB3_PHY_PIPE_CLK 98
> +#define GCC_USB_PHY_CFG_AHB2PHY_CLK 99
> +#define GP1_CLK_SRC 100
> +#define GP2_CLK_SRC 101
> +#define GP3_CLK_SRC 102
> +#define GPLL0 103
> +#define GPLL0_EARLY 104
> +#define GPLL1 105
> +#define GPLL1_EARLY 106
> +#define GPLL4 107
> +#define GPLL4_EARLY 108
> +#define HMSS_GPLL0_CLK_SRC 109
> +#define HMSS_GPLL4_CLK_SRC 110
> +#define HMSS_RBCPR_CLK_SRC 111
> +#define PDM2_CLK_SRC 112
> +#define QSPI_SER_CLK_SRC 113
> +#define SDCC1_APPS_CLK_SRC 114
> +#define SDCC1_ICE_CORE_CLK_SRC 115
> +#define SDCC2_APPS_CLK_SRC 116
> +#define UFS_AXI_CLK_SRC 117
> +#define UFS_ICE_CORE_CLK_SRC 118
> +#define UFS_PHY_AUX_CLK_SRC 119
> +#define UFS_UNIPRO_CORE_CLK_SRC 120
> +#define USB20_MASTER_CLK_SRC 121
> +#define USB20_MOCK_UTMI_CLK_SRC 122
> +#define USB30_MASTER_CLK_SRC 123
> +#define USB30_MOCK_UTMI_CLK_SRC 124
> +#define USB3_PHY_AUX_CLK_SRC 125
> +#define GPLL0_OUT_MSSCC 126
> +#define GCC_UFS_AXI_HW_CTL_CLK 127
> +#define GCC_UFS_ICE_CORE_HW_CTL_CLK 128
> +#define GCC_UFS_PHY_AUX_HW_CTL_CLK 129
> +#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 130
> +#define GCC_RX0_USB2_CLKREF_CLK 131
> +#define GCC_RX1_USB2_CLKREF_CLK 132
> +
> +#define PCIE_0_GDSC 0
> +#define UFS_GDSC 1
> +#define USB_30_GDSC 2
> +
> +#define GCC_QUSB2PHY_PRIM_BCR 0
> +#define GCC_QUSB2PHY_SEC_BCR 1
> +#define GCC_UFS_BCR 2
> +#define GCC_USB3_DP_PHY_BCR 3
> +#define GCC_USB3_PHY_BCR 4
> +#define GCC_USB3PHY_PHY_BCR 5
> +#define GCC_USB_20_BCR 6
> +#define GCC_USB_30_BCR 7
> +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
> +
> +#endif
>

--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation.

--

2018-08-13 07:56:17

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660



On 13 August 2018 07:55:34 BST, Taniya Das <[email protected]> wrote:
>Hello Craig,
>
>Could you please correct the authorship and also provide the reference
>to code where this is picked from?
Okay,
Got code from here https://github.com/sonyxperiadev/kernel/blob/aosp/LA.UM.6.4.r1/drivers/clk/qcom/gcc-sdm660.c
but changed it quite a bit for upstream,
Should I change the commit author and add your signed off by and say I did cleanups on my signed off by.

Also, hey, you wrote the original driver :)
>
>On 8/11/2018 1:51 AM, Craig Tatlor wrote:
>> Add support for the global clock controller found on SDM660
>> based devices. This should allow most non-multimedia device
>> drivers to probe and control their clocks.
>> Based on CAF implementation.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>> ---
>> .../devicetree/bindings/clock/qcom,gcc.txt | 1 +
>> drivers/clk/qcom/Kconfig | 9 +
>> drivers/clk/qcom/Makefile | 1 +
>> drivers/clk/qcom/gcc-sdm660.c | 2479
>+++++++++++++++++
>> include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
>> 5 files changed, 2649 insertions(+)
>> create mode 100644 drivers/clk/qcom/gcc-sdm660.c
>> create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> index 664ea1fd6c76..e498ad2e8db8 100644
>> --- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> @@ -19,6 +19,7 @@ Required properties :
>> "qcom,gcc-msm8996"
>> "qcom,gcc-msm8998"
>> "qcom,gcc-mdm9615"
>> + "qcom,gcc-sdm660"
>> "qcom,gcc-sdm845"
>>
>> - reg : shall contain base register location and length
>> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
>> index 9c3480dcc38a..c4bda6d24c1f 100644
>> --- a/drivers/clk/qcom/Kconfig
>> +++ b/drivers/clk/qcom/Kconfig
>> @@ -226,6 +226,15 @@ config MSM_GCC_8998
>> Say Y if you want to use peripheral devices such as UART, SPI,
>> i2c, USB, UFS, SD/eMMC, PCIe, etc.
>>
>> +config SDM_GCC_660
>> + tristate "SDM660 Global Clock Controller"
>> + select QCOM_GDSC
>> + depends on COMMON_CLK_QCOM
>> + help
>> + Support for the global clock controller on SDM660 devices.
>> + Say Y if you want to use peripheral devices such as UART, SPI,
>> + i2C, USB, UFS, SDDC, PCIe, etc.
>> +
>> config SDM_GCC_845
>> tristate "SDM845 Global Clock Controller"
>> select QCOM_GDSC
>> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
>> index 762c01137c2f..6e37d30d7c02 100644
>> --- a/drivers/clk/qcom/Makefile
>> +++ b/drivers/clk/qcom/Makefile
>> @@ -38,6 +38,7 @@ obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>> obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
>> obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
>> obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
>> +obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
>> obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
>> obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
>> obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
>> diff --git a/drivers/clk/qcom/gcc-sdm660.c
>b/drivers/clk/qcom/gcc-sdm660.c
>> new file mode 100644
>> index 000000000000..bdb445aa4baa
>> --- /dev/null
>> +++ b/drivers/clk/qcom/gcc-sdm660.c
>> @@ -0,0 +1,2479 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2016-2017, The Linux Foundation. All rights
>reserved.
>> + * Copyright (c) 2018, Craig Tatlor.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/bitops.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/regmap.h>
>> +#include <linux/reset-controller.h>
>> +
>> +#include <dt-bindings/clock/qcom,gcc-sdm660.h>
>> +
>> +#include "common.h"
>> +#include "clk-regmap.h"
>> +#include "clk-alpha-pll.h"
>> +#include "clk-rcg.h"
>> +#include "clk-branch.h"
>> +#include "reset.h"
>> +#include "gdsc.h"
>> +
>> +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
>> +
>> +enum {
>> + P_XO,
>> + P_SLEEP_CLK,
>> + P_GPLL0,
>> + P_GPLL1,
>> + P_GPLL4,
>> + P_GPLL0_EARLY_DIV,
>> + P_GPLL1_EARLY_DIV,
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_gpll0[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_gpll0[] = {
>> + "xo",
>> + "gpll0",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_SLEEP_CLK, 5 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "sleep_clk",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
>> + { P_XO, 0 },
>> + { P_SLEEP_CLK, 5 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_sleep_clk[] = {
>> + "xo",
>> + "sleep_clk",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_gpll4[] = {
>> + { P_XO, 0 },
>> + { P_GPLL4, 5 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_gpll4[] = {
>> + "xo",
>> + "gpll4",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] =
>{
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 3 },
>> + { P_GPLL1, 4 },
>> + { P_GPLL4, 5 },
>> + { P_GPLL1_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[]
>= {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> + "gpll1",
>> + "gpll4",
>> + "gpll1_early_div",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL4, 5 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll4",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 2 },
>> + { P_GPLL4, 5 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> + "gpll4",
>> +};
>> +
>> +static struct clk_fixed_factor xo = {
>> + .mult = 1,
>> + .div = 1,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "xo",
>> + .parent_names = (const char *[]){ "xo_board" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll0_early = {
>> + .offset = 0x0,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(0),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll0_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor gpll0_early_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll0_early_div",
>> + .parent_names = (const char *[]){ "gpll0_early" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll0 = {
>> + .offset = 0x00000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gpll0",
>> + .parent_names = (const char *[]){ "gpll0_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll1_early = {
>> + .offset = 0x1000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(1),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll1_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor gpll1_early_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll1_early_div",
>> + .parent_names = (const char *[]){ "gpll1_early" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll1 = {
>> + .offset = 0x1000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gpll1",
>> + .parent_names = (const char *[]){ "gpll1_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll4_early = {
>> + .offset = 0x77000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(4),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll4_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll4 = {
>> + .offset = 0x77000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data)
>> + {
>> + .name = "gpll4",
>> + .parent_names = (const char *[]) { "gpll4_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(50000000, P_GPLL0, 12, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x19020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup1_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
>> + F(960000, P_XO, 10, 1, 2),
>> + F(4800000, P_XO, 4, 0, 0),
>> + F(9600000, P_XO, 2, 0, 0),
>> + F(15000000, P_GPLL0, 10, 1, 4),
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(25000000, P_GPLL0, 12, 1, 2),
>> + F(50000000, P_GPLL0, 12, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1900c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup1_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1b020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup2_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1b00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup2_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1d020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup3_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1d00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup3_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1f020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup4_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1f00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup4_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
>> + F(3686400, P_GPLL0, 1, 96, 15625),
>> + F(7372800, P_GPLL0, 1, 192, 15625),
>> + F(14745600, P_GPLL0, 1, 384, 15625),
>> + F(16000000, P_GPLL0, 5, 2, 15),
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(24000000, P_GPLL0, 5, 1, 5),
>> + F(32000000, P_GPLL0, 1, 4, 75),
>> + F(40000000, P_GPLL0, 15, 0, 0),
>> + F(46400000, P_GPLL0, 1, 29, 375),
>> + F(48000000, P_GPLL0, 12.5, 0, 0),
>> + F(51200000, P_GPLL0, 1, 32, 375),
>> + F(56000000, P_GPLL0, 1, 7, 75),
>> + F(58982400, P_GPLL0, 1, 1536, 15625),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + F(63157895, P_GPLL0, 9.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
>> + .cmd_rcgr = 0x1a00c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_uart1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
>> + .cmd_rcgr = 0x1c00c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_uart2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x26020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup1_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2600c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup1_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x28020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup2_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2800c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup2_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x2a020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup3_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2a00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup3_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x2c020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup4_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2c00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup4_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
>> + .cmd_rcgr = 0x2700c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_uart1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
>> + .cmd_rcgr = 0x2900c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_uart2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_gp1_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 gp1_clk_src = {
>> + .cmd_rcgr = 0x64004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp1_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 gp2_clk_src = {
>> + .cmd_rcgr = 0x65004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp2_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 gp3_clk_src = {
>> + .cmd_rcgr = 0x66004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp3_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + F(600000000, P_GPLL0, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_gpll0_clk_src = {
>> + .cmd_rcgr = 0x4805c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_hmss_gpll0_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_gpll0_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
>> + F(384000000, P_GPLL4, 4, 0, 0),
>> + F(768000000, P_GPLL4, 2, 0, 0),
>> + F(1536000000, P_GPLL4, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_gpll4_clk_src = {
>> + .cmd_rcgr = 0x48074,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll4,
>> + .freq_tbl = ftbl_hmss_gpll4_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_gpll4_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll4,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_rbcpr_clk_src = {
>> + .cmd_rcgr = 0x48044,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_rbcpr_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_pdm2_clk_src[] = {
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 pdm2_clk_src = {
>> + .cmd_rcgr = 0x33010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_pdm2_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "pdm2_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
>> + F(160400000, P_GPLL1, 5, 0, 0),
>> + F(267333333, P_GPLL1, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 qspi_ser_clk_src = {
>> + .cmd_rcgr = 0x4d00c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map =
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>> + .freq_tbl = ftbl_qspi_ser_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "qspi_ser_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>> + .num_parents = 6,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
>> + F(144000, P_XO, 16, 3, 25),
>> + F(400000, P_XO, 12, 1, 4),
>> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(192000000, P_GPLL4, 8, 0, 0),
>> + F(384000000, P_GPLL4, 4, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc1_apps_clk_src = {
>> + .cmd_rcgr = 0x1602c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
>> + .freq_tbl = ftbl_sdcc1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
>> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc1_ice_core_clk_src = {
>> + .cmd_rcgr = 0x16010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc1_ice_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
>> + F(144000, P_XO, 16, 3, 25),
>> + F(400000, P_XO, 12, 1, 4),
>> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(192000000, P_GPLL4, 8, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc2_apps_clk_src = {
>> + .cmd_rcgr = 0x14010,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
>> + .freq_tbl = ftbl_sdcc2_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(240000000, P_GPLL0, 2.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_axi_clk_src = {
>> + .cmd_rcgr = 0x75018,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_axi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_axi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
>> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_ice_core_clk_src = {
>> + .cmd_rcgr = 0x76010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_ice_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_ice_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 ufs_phy_aux_clk_src = {
>> + .cmd_rcgr = 0x76044,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_sleep_clk,
>> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_phy_aux_clk_src",
>> + .parent_names = gcc_parent_names_xo_sleep_clk,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
>> + F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
>> + F(75000000, P_GPLL0, 8, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_unipro_core_clk_src = {
>> + .cmd_rcgr = 0x76028,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_unipro_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_unipro_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + F(120000000, P_GPLL0, 5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb20_master_clk_src = {
>> + .cmd_rcgr = 0x2f010,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb20_master_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb20_master_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb20_mock_utmi_clk_src = {
>> + .cmd_rcgr = 0x2f024,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb20_mock_utmi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
>> + F(120000000, P_GPLL0, 5, 0, 0),
>> + F(133333333, P_GPLL0, 4.5, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(240000000, P_GPLL0, 2.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb30_master_clk_src = {
>> + .cmd_rcgr = 0xf014,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb30_master_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb30_master_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb30_mock_utmi_clk_src = {
>> + .cmd_rcgr = 0xf028,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb30_mock_utmi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
>> + F(1200000, P_XO, 16, 0, 0),
>> + F(19200000, P_XO, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb3_phy_aux_clk_src = {
>> + .cmd_rcgr = 0x5000c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_sleep_clk,
>> + .freq_tbl = ftbl_usb3_phy_aux_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb3_phy_aux_clk_src",
>> + .parent_names = gcc_parent_names_xo_sleep_clk,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_branch gcc_aggre2_ufs_axi_clk = {
>> + .ha

--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

2018-08-13 09:46:25

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660



On 13 August 2018 07:55:34 BST, Taniya Das <[email protected]> wrote:
>Hello Craig,
>
>Could you please correct the authorship and also provide the reference
>to code where this is picked from?
>
Also, don't you have a program that just spits out the clock setup?
And I did leave copyright in file.
>On 8/11/2018 1:51 AM, Craig Tatlor wrote:
>> Add support for the global clock controller found on SDM660
>> based devices. This should allow most non-multimedia device
>> drivers to probe and control their clocks.
>> Based on CAF implementation.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>> ---
>> .../devicetree/bindings/clock/qcom,gcc.txt | 1 +
>> drivers/clk/qcom/Kconfig | 9 +
>> drivers/clk/qcom/Makefile | 1 +
>> drivers/clk/qcom/gcc-sdm660.c | 2479
>+++++++++++++++++
>> include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
>> 5 files changed, 2649 insertions(+)
>> create mode 100644 drivers/clk/qcom/gcc-sdm660.c
>> create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> index 664ea1fd6c76..e498ad2e8db8 100644
>> --- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>> @@ -19,6 +19,7 @@ Required properties :
>> "qcom,gcc-msm8996"
>> "qcom,gcc-msm8998"
>> "qcom,gcc-mdm9615"
>> + "qcom,gcc-sdm660"
>> "qcom,gcc-sdm845"
>>
>> - reg : shall contain base register location and length
>> diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
>> index 9c3480dcc38a..c4bda6d24c1f 100644
>> --- a/drivers/clk/qcom/Kconfig
>> +++ b/drivers/clk/qcom/Kconfig
>> @@ -226,6 +226,15 @@ config MSM_GCC_8998
>> Say Y if you want to use peripheral devices such as UART, SPI,
>> i2c, USB, UFS, SD/eMMC, PCIe, etc.
>>
>> +config SDM_GCC_660
>> + tristate "SDM660 Global Clock Controller"
>> + select QCOM_GDSC
>> + depends on COMMON_CLK_QCOM
>> + help
>> + Support for the global clock controller on SDM660 devices.
>> + Say Y if you want to use peripheral devices such as UART, SPI,
>> + i2C, USB, UFS, SDDC, PCIe, etc.
>> +
>> config SDM_GCC_845
>> tristate "SDM845 Global Clock Controller"
>> select QCOM_GDSC
>> diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
>> index 762c01137c2f..6e37d30d7c02 100644
>> --- a/drivers/clk/qcom/Makefile
>> +++ b/drivers/clk/qcom/Makefile
>> @@ -38,6 +38,7 @@ obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
>> obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
>> obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
>> obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
>> +obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
>> obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
>> obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
>> obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
>> diff --git a/drivers/clk/qcom/gcc-sdm660.c
>b/drivers/clk/qcom/gcc-sdm660.c
>> new file mode 100644
>> index 000000000000..bdb445aa4baa
>> --- /dev/null
>> +++ b/drivers/clk/qcom/gcc-sdm660.c
>> @@ -0,0 +1,2479 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2016-2017, The Linux Foundation. All rights
>reserved.
>> + * Copyright (c) 2018, Craig Tatlor.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/bitops.h>
>> +#include <linux/err.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/regmap.h>
>> +#include <linux/reset-controller.h>
>> +
>> +#include <dt-bindings/clock/qcom,gcc-sdm660.h>
>> +
>> +#include "common.h"
>> +#include "clk-regmap.h"
>> +#include "clk-alpha-pll.h"
>> +#include "clk-rcg.h"
>> +#include "clk-branch.h"
>> +#include "reset.h"
>> +#include "gdsc.h"
>> +
>> +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
>> +
>> +enum {
>> + P_XO,
>> + P_SLEEP_CLK,
>> + P_GPLL0,
>> + P_GPLL1,
>> + P_GPLL4,
>> + P_GPLL0_EARLY_DIV,
>> + P_GPLL1_EARLY_DIV,
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_gpll0[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_gpll0[] = {
>> + "xo",
>> + "gpll0",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_SLEEP_CLK, 5 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "sleep_clk",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
>> + { P_XO, 0 },
>> + { P_SLEEP_CLK, 5 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_sleep_clk[] = {
>> + "xo",
>> + "sleep_clk",
>> +};
>> +
>> +static const struct parent_map gcc_parent_map_xo_gpll4[] = {
>> + { P_XO, 0 },
>> + { P_GPLL4, 5 },
>> +};
>> +
>> +static const char * const gcc_parent_names_xo_gpll4[] = {
>> + "xo",
>> + "gpll4",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] =
>{
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 3 },
>> + { P_GPLL1, 4 },
>> + { P_GPLL4, 5 },
>> + { P_GPLL1_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[]
>= {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> + "gpll1",
>> + "gpll4",
>> + "gpll1_early_div",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL4, 5 },
>> + { P_GPLL0_EARLY_DIV, 6 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll4",
>> + "gpll0_early_div",
>> +};
>> +
>> +static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
>> + { P_XO, 0 },
>> + { P_GPLL0, 1 },
>> + { P_GPLL0_EARLY_DIV, 2 },
>> + { P_GPLL4, 5 },
>> +};
>> +
>> +static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
>> + "xo",
>> + "gpll0",
>> + "gpll0_early_div",
>> + "gpll4",
>> +};
>> +
>> +static struct clk_fixed_factor xo = {
>> + .mult = 1,
>> + .div = 1,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "xo",
>> + .parent_names = (const char *[]){ "xo_board" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll0_early = {
>> + .offset = 0x0,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(0),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll0_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor gpll0_early_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll0_early_div",
>> + .parent_names = (const char *[]){ "gpll0_early" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll0 = {
>> + .offset = 0x00000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gpll0",
>> + .parent_names = (const char *[]){ "gpll0_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll1_early = {
>> + .offset = 0x1000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(1),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll1_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor gpll1_early_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll1_early_div",
>> + .parent_names = (const char *[]){ "gpll1_early" },
>> + .num_parents = 1,
>> + .ops = &clk_fixed_factor_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll1 = {
>> + .offset = 0x1000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gpll1",
>> + .parent_names = (const char *[]){ "gpll1_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll gpll4_early = {
>> + .offset = 0x77000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr = {
>> + .enable_reg = 0x52000,
>> + .enable_mask = BIT(4),
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gpll4_early",
>> + .parent_names = (const char *[]){ "xo" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_ops,
>> + },
>> + },
>> +};
>> +
>> +static struct clk_alpha_pll_postdiv gpll4 = {
>> + .offset = 0x77000,
>> + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>> + .clkr.hw.init = &(struct clk_init_data)
>> + {
>> + .name = "gpll4",
>> + .parent_names = (const char *[]) { "gpll4_early" },
>> + .num_parents = 1,
>> + .ops = &clk_alpha_pll_postdiv_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(50000000, P_GPLL0, 12, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x19020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup1_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
>> + F(960000, P_XO, 10, 1, 2),
>> + F(4800000, P_XO, 4, 0, 0),
>> + F(9600000, P_XO, 2, 0, 0),
>> + F(15000000, P_GPLL0, 10, 1, 4),
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(25000000, P_GPLL0, 12, 1, 2),
>> + F(50000000, P_GPLL0, 12, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1900c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup1_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1b020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup2_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1b00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup2_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1d020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup3_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1d00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup3_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x1f020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup4_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x1f00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_qup4_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
>> + F(3686400, P_GPLL0, 1, 96, 15625),
>> + F(7372800, P_GPLL0, 1, 192, 15625),
>> + F(14745600, P_GPLL0, 1, 384, 15625),
>> + F(16000000, P_GPLL0, 5, 2, 15),
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(24000000, P_GPLL0, 5, 1, 5),
>> + F(32000000, P_GPLL0, 1, 4, 75),
>> + F(40000000, P_GPLL0, 15, 0, 0),
>> + F(46400000, P_GPLL0, 1, 29, 375),
>> + F(48000000, P_GPLL0, 12.5, 0, 0),
>> + F(51200000, P_GPLL0, 1, 32, 375),
>> + F(56000000, P_GPLL0, 1, 7, 75),
>> + F(58982400, P_GPLL0, 1, 1536, 15625),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + F(63157895, P_GPLL0, 9.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
>> + .cmd_rcgr = 0x1a00c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_uart1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
>> + .cmd_rcgr = 0x1c00c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp1_uart2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x26020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup1_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2600c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup1_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x28020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup2_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2800c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup2_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x2a020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup3_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2a00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup3_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
>> + .cmd_rcgr = 0x2c020,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup4_i2c_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
>> + .cmd_rcgr = 0x2c00c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_qup4_spi_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
>> + .cmd_rcgr = 0x2700c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_uart1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
>> + .cmd_rcgr = 0x2900c,
>> + .mnd_width = 16,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "blsp2_uart2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_gp1_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 gp1_clk_src = {
>> + .cmd_rcgr = 0x64004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp1_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 gp2_clk_src = {
>> + .cmd_rcgr = 0x65004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp2_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 gp3_clk_src = {
>> + .cmd_rcgr = 0x66004,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .freq_tbl = ftbl_gp1_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "gp3_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + F(600000000, P_GPLL0, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_gpll0_clk_src = {
>> + .cmd_rcgr = 0x4805c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_hmss_gpll0_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_gpll0_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
>> + F(384000000, P_GPLL4, 4, 0, 0),
>> + F(768000000, P_GPLL4, 2, 0, 0),
>> + F(1536000000, P_GPLL4, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_gpll4_clk_src = {
>> + .cmd_rcgr = 0x48074,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll4,
>> + .freq_tbl = ftbl_hmss_gpll4_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_gpll4_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll4,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 hmss_rbcpr_clk_src = {
>> + .cmd_rcgr = 0x48044,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "hmss_rbcpr_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_pdm2_clk_src[] = {
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 pdm2_clk_src = {
>> + .cmd_rcgr = 0x33010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_pdm2_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "pdm2_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
>> + F(160400000, P_GPLL1, 5, 0, 0),
>> + F(267333333, P_GPLL1, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 qspi_ser_clk_src = {
>> + .cmd_rcgr = 0x4d00c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map =
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>> + .freq_tbl = ftbl_qspi_ser_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "qspi_ser_clk_src",
>> + .parent_names =
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>> + .num_parents = 6,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
>> + F(144000, P_XO, 16, 3, 25),
>> + F(400000, P_XO, 12, 1, 4),
>> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(192000000, P_GPLL4, 8, 0, 0),
>> + F(384000000, P_GPLL4, 4, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc1_apps_clk_src = {
>> + .cmd_rcgr = 0x1602c,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
>> + .freq_tbl = ftbl_sdcc1_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc1_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
>> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc1_ice_core_clk_src = {
>> + .cmd_rcgr = 0x16010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc1_ice_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
>> + F(144000, P_XO, 16, 3, 25),
>> + F(400000, P_XO, 12, 1, 4),
>> + F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>> + F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(192000000, P_GPLL4, 8, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 sdcc2_apps_clk_src = {
>> + .cmd_rcgr = 0x14010,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
>> + .freq_tbl = ftbl_sdcc2_apps_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "sdcc2_apps_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
>> + .num_parents = 4,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
>> + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>> + F(100000000, P_GPLL0, 6, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(240000000, P_GPLL0, 2.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_axi_clk_src = {
>> + .cmd_rcgr = 0x75018,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_axi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_axi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
>> + F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(300000000, P_GPLL0, 2, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_ice_core_clk_src = {
>> + .cmd_rcgr = 0x76010,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_ice_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_ice_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_rcg2 ufs_phy_aux_clk_src = {
>> + .cmd_rcgr = 0x76044,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_sleep_clk,
>> + .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_phy_aux_clk_src",
>> + .parent_names = gcc_parent_names_xo_sleep_clk,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
>> + F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
>> + F(75000000, P_GPLL0, 8, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 ufs_unipro_core_clk_src = {
>> + .cmd_rcgr = 0x76028,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_ufs_unipro_core_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "ufs_unipro_core_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + F(120000000, P_GPLL0, 5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb20_master_clk_src = {
>> + .cmd_rcgr = 0x2f010,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb20_master_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb20_master_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb20_mock_utmi_clk_src = {
>> + .cmd_rcgr = 0x2f024,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb20_mock_utmi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
>> + F(120000000, P_GPLL0, 5, 0, 0),
>> + F(133333333, P_GPLL0, 4.5, 0, 0),
>> + F(150000000, P_GPLL0, 4, 0, 0),
>> + F(200000000, P_GPLL0, 3, 0, 0),
>> + F(240000000, P_GPLL0, 2.5, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb30_master_clk_src = {
>> + .cmd_rcgr = 0xf014,
>> + .mnd_width = 8,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb30_master_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb30_master_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
>> + F(19200000, P_XO, 1, 0, 0),
>> + F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
>> + F(60000000, P_GPLL0, 10, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb30_mock_utmi_clk_src = {
>> + .cmd_rcgr = 0xf028,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>> + .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb30_mock_utmi_clk_src",
>> + .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>> + .num_parents = 3,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
>> + F(1200000, P_XO, 16, 0, 0),
>> + F(19200000, P_XO, 1, 0, 0),
>> + { }
>> +};
>> +
>> +static struct clk_rcg2 usb3_phy_aux_clk_src = {
>> + .cmd_rcgr = 0x5000c,
>> + .mnd_width = 0,
>> + .hid_width = 5,
>> + .parent_map = gcc_parent_map_xo_sleep_clk,
>> + .freq_tbl = ftbl_usb3_phy_aux_clk_src,
>> + .clkr.hw.init = &(struct clk_init_data){
>> + .name = "usb3_phy_aux_clk_src",
>> + .parent_names = gcc_parent_names_xo_sleep_clk,
>> + .num_parents = 2,
>> + .ops = &clk_rcg2_ops,
>> + },
>> +};
>> +
>> +static struct clk_branch gcc_aggre2_ufs_axi_clk = {
>> + .ha

--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

2018-09-16 20:03:37

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

Hi,

First of all thanks for the patch and big sorry for the long delay
in reviewing this. I did not find enough time to do it properly
until now :(

On Thu, Jun 14, 2018 at 04:14:15PM +0100, Craig Tatlor wrote:
> This patch adds a driver for the BMS (Battery Monitoring System)
> block of the PM8941 PMIC, it uses a lookup table defined in the
> device tree to generate a capacity from the BMS supplied OCV, it
> then amends the coulomb counter to that to increase the accuracy
> of the estimated capacity.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> Reviewed-by: Linus Walleij <[email protected]>
> ---
>
> * Changes from v5:
> Uses select for REGMAP_SPMI.
>
> * Changes from v4:
> Cleaned up percentage interpolation function,
> uses new fixp interpolation helper,
> added some more error cases,
> uses devm_power_supply_register(),
> uses a DIV_ROUND_CLOSEST for division and
> uses micro(volts / amp hours) instead of
> milli (volts / amp hours).
>
> drivers/power/supply/Kconfig | 9 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/qcom_bms.c | 487 ++++++++++++++++++++++++++++++++
> 3 files changed, 497 insertions(+)
> create mode 100644 drivers/power/supply/qcom_bms.c
>
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index 428b426842f4..75f2f375f992 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -82,6 +82,15 @@ config BATTERY_ACT8945A
> Say Y here to enable support for power supply provided by
> Active-semi ActivePath ACT8945A charger.
>
> +config BATTERY_BMS
> + tristate "Qualcomm Battery Monitoring System driver"
> + depends on MFD_SPMI_PMIC || COMPILE_TEST
> + depends on OF
> + select REGMAP_SPMI
> + help
> + Say Y to include support for the Battery Monitoring hardware
> + found in some Qualcomm PM series PMICs.
> +
> config BATTERY_CPCAP
> tristate "Motorola CPCAP PMIC battery driver"
> depends on MFD_CPCAP && IIO
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index e83aa843bcc6..04204174b047 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
> obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
> obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
> obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
> +obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
> obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
> obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
> obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
> diff --git a/drivers/power/supply/qcom_bms.c b/drivers/power/supply/qcom_bms.c
> new file mode 100644
> index 000000000000..718fd745c0f7
> --- /dev/null
> +++ b/drivers/power/supply/qcom_bms.c
> @@ -0,0 +1,487 @@
> +// SPDX-License-Identifier: GPL
> +
> +/*
> + * Qualcomm Battery Monitoring System driver
> + *
> + * Copyright (C) 2018 Craig Tatlor <[email protected]>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/fixp-arith.h>
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/slab.h>
> +#include <linux/bitops.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/regmap.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/iio/consumer.h>
> +
> +#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
> +#define REG_BMS_SHDW_CC_DATA0 0xA8
> +#define REG_BMS_CC_DATA_CTL 0x42
> +#define REG_BMS_CC_CLEAR_CTL 0x4
> +
> +#define BMS_HOLD_OREG_DATA BIT(0)
> +#define BMS_CLEAR_SHDW_CC BIT(6)
> +
> +#define BMS_CC_READING_RESOLUTION_N 542535
> +#define BMS_CC_READING_RESOLUTION_D 10000
> +#define BMS_CC_READING_TICKS 56
> +#define BMS_SLEEP_CLK_HZ 32764
> +
> +#define SECONDS_PER_HOUR 3600
> +#define TEMPERATURE_COLS 5
> +#define MAX_CAPACITY_ROWS 50
> +
> +/* lookup table for ocv -> capacity conversion */
> +struct bms_ocv_lut {
> + int rows;
> + s8 temp_legend[TEMPERATURE_COLS];
> + u8 capacity_legend[MAX_CAPACITY_ROWS];
> + u32 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
> +};
> +
> +/* lookup table for battery temperature -> fcc conversion */
> +struct bms_fcc_lut {
> + s8 temp_legend[TEMPERATURE_COLS];
> + u32 lut[TEMPERATURE_COLS];
> +};
> +
> +struct bms_device_info {
> + struct device *dev;
> + struct regmap *regmap;
> + struct bms_ocv_lut ocv_lut;
> + struct power_supply_desc bat_desc;
> + struct bms_fcc_lut fcc_lut;
> + struct iio_channel *adc;
> + struct mutex bms_output_lock;
> + u32 base_addr;
> +
> + int ocv_thr_irq;
> + u32 ocv;
> +};
> +
> +static bool between(int left, int right, int val)
> +{
> + if (left <= val && val <= right)
> + return true;
> +
> + if (left >= val && val >= right)
> + return true;
> +
> + return false;
> +}
> +
> +static int interpolate_capacity(int temp, u32 ocv,
> + struct bms_ocv_lut *ocv_lut)
> +{
> + int pcj_minus_one = 0, pcj = 0, i2 = 0, i3 = 0, i, j;
> +
> + for (j = 0; j < TEMPERATURE_COLS; j++)
> + if (temp <= ocv_lut->temp_legend[j])
> + break;
> +
> + if (ocv >= ocv_lut->lut[0][j])
> + return ocv_lut->capacity_legend[0];
> +
> + if (ocv <= ocv_lut->lut[ocv_lut->rows-1][j-1])
> + return ocv_lut->capacity_legend[ocv_lut->rows-1];
> +
> + for (i = 0; i < ocv_lut->rows-1; i++) {
> + if (between(ocv_lut->lut[i][j],
> + ocv_lut->lut[i+1][j], ocv))
> + i2 = i;
> +
> + if (between(ocv_lut->lut[i][j-1],
> + ocv_lut->lut[i+1][j-1], ocv))
> + i3 = i;
> + }
> +
> + /* interpolate two capacities */
> + pcj = fixp_linear_interpolate(ocv_lut->lut[i2][j],
> + ocv_lut->capacity_legend[i2],
> + ocv_lut->lut[i2+1][j],
> + ocv_lut->capacity_legend[i2+1],
> + ocv);
> +
> + pcj_minus_one = fixp_linear_interpolate(ocv_lut->lut[i3][j-1],
> + ocv_lut->capacity_legend[i3],
> + ocv_lut->lut[i3+1][j-1],
> + ocv_lut->capacity_legend[i3+1],
> + ocv);
> +
> + /* interpolate them with the battery temperature */
> + return fixp_linear_interpolate(ocv_lut->temp_legend[j-1],
> + pcj_minus_one,
> + ocv_lut->temp_legend[j],
> + pcj,
> + temp);
> +}
> +
> +static int interpolate_fcc(int temp, struct bms_fcc_lut *fcc_lut)
> +{
> + int i;
> +
> + for (i = 0; i < TEMPERATURE_COLS; i++)
> + if (temp <= fcc_lut->temp_legend[i])
> + break;
> +
> + return fixp_linear_interpolate(fcc_lut->temp_legend[i-1],
> + fcc_lut->lut[i-1],
> + fcc_lut->temp_legend[i],
> + fcc_lut->lut[i],
> + temp);
> +}
> +
> +static int bms_lock_output_data(struct bms_device_info *di)
> +{
> + int ret;
> +
> + ret = regmap_update_bits(di->regmap, di->base_addr +
> + REG_BMS_CC_DATA_CTL,
> + BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
> + if (ret) {
> + dev_err(di->dev, "failed to lock bms output: %d", ret);
> + return ret;
> + }
> +
> + /*
> + * Sleep for at least 100 microseconds here to make sure
> + * there has been at least three cycles of the sleep clock
> + * so that the registers are correctly locked.
> + */
> + usleep_range(100, 1000);
> +
> + return 0;
> +}
> +
> +static int bms_unlock_output_data(struct bms_device_info *di)
> +{
> + int ret;
> +
> + ret = regmap_update_bits(di->regmap, di->base_addr +
> + REG_BMS_CC_DATA_CTL,
> + BMS_HOLD_OREG_DATA, 0);
> + if (ret) {
> + dev_err(di->dev, "failed to unlock bms output: %d", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int bms_read_ocv(struct bms_device_info *di, u32 *ocv)
> +{
> + int ret;
> + u16 read_ocv;
> +
> + mutex_lock(&di->bms_output_lock);
> +
> + ret = bms_lock_output_data(di);
> + if (ret)
> + goto err_lock;
> +
> + ret = regmap_bulk_read(di->regmap, di->base_addr+
> + REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
> + if (ret) {
> + dev_err(di->dev, "open circuit voltage read failed: %d", ret);
> + goto err_read;
> + }
> +
> + dev_dbg(di->dev, "read open circuit voltage of: %d mv", read_ocv);
> +
> +

one empty line is enough.

> + *ocv = read_ocv * 1000;
> +
> +err_read:
> + bms_unlock_output_data(di);
> +
> +err_lock:
> + mutex_unlock(&di->bms_output_lock);
> +
> + return ret;
> +}
> +
> +static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
> +{
> + int ret;
> + s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
> +
> + mutex_lock(&di->bms_output_lock);
> +
> + ret = bms_lock_output_data(di);
> + if (ret)
> + goto err_lock;
> +
> + ret = regmap_bulk_read(di->regmap, di->base_addr +
> + REG_BMS_SHDW_CC_DATA0,
> + &cc_raw_s36, 5);
> + if (ret) {
> + dev_err(di->dev, "coulomb counter read failed: %d", ret);
> + goto err_read;
> + }
> +
> + ret = bms_unlock_output_data(di);
> + if (ret)
> + goto err_lock;
> +
> + mutex_unlock(&di->bms_output_lock);
> +
> + cc_raw = sign_extend32(cc_raw_s36, 28);
> +
> + /* convert raw to uv */
> + cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
> + BMS_CC_READING_RESOLUTION_D);
> +
> + /* convert uv to pvh */
> + cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
> + BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR);
> +
> + /* divide by impedance */
> + *cc_uah = div_s64(cc_pvh, 10000);
> +
> + dev_dbg(di->dev, "read coulomb counter value of: %lld uah", *cc_uah);
> +
> + return 0;
> +
> +err_read:
> + bms_unlock_output_data(di);
> +
> +err_lock:
> + mutex_unlock(&di->bms_output_lock);
> +
> + return ret;
> +}
> +
> +static void bms_reset_cc(struct bms_device_info *di)
> +{
> + int ret;
> +
> + mutex_lock(&di->bms_output_lock);
> +
> + ret = regmap_update_bits(di->regmap, di->base_addr +
> + REG_BMS_CC_CLEAR_CTL,
> + BMS_CLEAR_SHDW_CC,
> + BMS_CLEAR_SHDW_CC);
> + if (ret) {
> + dev_err(di->dev, "coulomb counter reset failed: %d", ret);
> + goto err_lock;
> + }
> +
> + /* wait at least three sleep cycles for cc to reset */
> + usleep_range(100, 1000);
> +
> + ret = regmap_update_bits(di->regmap, di->base_addr +
> + REG_BMS_CC_CLEAR_CTL,
> + BMS_CLEAR_SHDW_CC, 0);
> + if (ret)
> + dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
> +
> +err_lock:
> + mutex_unlock(&di->bms_output_lock);
> +}
> +
> +static int bms_calculate_capacity(struct bms_device_info *di, int *capacity)
> +{
> + unsigned long fcc;
> + int ret, temp, ocv_capacity, temp_degc;
> + s64 cc = 0;
> +
> + ret = iio_read_channel_raw(di->adc, &temp);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read temperature: %d", ret);
> + return ret;
> + }
> +
> + temp_degc = DIV_ROUND_CLOSEST(temp, 1000);
> +
> + ret = bms_read_cc(di, &cc);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read coulomb counter: %d", ret);
> + return ret;
> + }
> +
> + /* interpolate capacity from open circuit voltage */
> + ocv_capacity = interpolate_capacity(temp_degc, di->ocv,
> + &di->ocv_lut);
> +
> + /* interpolate the full charge capacity from temperature */
> + fcc = interpolate_fcc(temp_degc, &di->fcc_lut);
> +
> + /* append coloumb counter to capacity */
> + *capacity = DIV_ROUND_CLOSEST(fcc * ocv_capacity, 100);
> + *capacity = div_s64((*capacity - cc) * 100, fcc);
> +
> + return 0;
> +}
> +
> +
> +

one empty line is enough.

> +/*
> + * Return power_supply property
> + */
> +static int bms_get_property(struct power_supply *psy,
> + enum power_supply_property psp,
> + union power_supply_propval *val)
> +{
> + struct bms_device_info *di = power_supply_get_drvdata(psy);
> + int ret;
> +
> + switch (psp) {
> + case POWER_SUPPLY_PROP_CAPACITY:
> + ret = bms_calculate_capacity(di, &val->intval);
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> + if (val->intval == INT_MAX || val->intval == INT_MIN)
> + ret = -EINVAL;
> +
> + return ret;
> +}
> +
> +static enum power_supply_property bms_props[] = {
> + POWER_SUPPLY_PROP_CAPACITY,
> +};

Why does the driver not expose the following battery information?

temperature info via POWER_SUPPLY_PROP_TEMP
ocv info via POWER_SUPPLY_PROP_VOLTAGE_OCV
CC info via POWER_SUPPLY_PROP_CHARGE_COUNTER
max current via POWER_SUPPLY_PROP_CURRENT_MAX

> +static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
> +{
> + struct bms_device_info *di = dev_id;
> +
> + if (bms_read_ocv(di, &di->ocv) < 0)
> + return IRQ_HANDLED;
> +
> + bms_reset_cc(di);
> + return IRQ_HANDLED;
> +}

You want to call power_supply_changed() here to notify userspace.

> +static int bms_probe(struct platform_device *pdev)
> +{
> + struct power_supply_config psy_cfg = {};
> + struct bms_device_info *di;
> + struct power_supply *bat;
> + int ret;
> +
> + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
> + if (!di)
> + return -ENOMEM;
> +
> + di->dev = &pdev->dev;
> +
> + di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!di->regmap) {
> + dev_err(di->dev, "Unable to get regmap");
> + return -EINVAL;
> + }
> +
> + di->adc = devm_iio_channel_get(&pdev->dev, "temp");
> + if (IS_ERR(di->adc))
> + return PTR_ERR(di->adc);
> +
> + ret = of_property_read_u32(di->dev->of_node, "reg", &di->base_addr);
> + if (ret < 0)
> + return ret;
> +
> + ret = of_property_read_u8_array(di->dev->of_node,
> + "qcom,ocv-temp-legend-celsius",
> + (u8 *)di->ocv_lut.temp_legend,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no open circuit voltage temperature legend found");
> + return ret;
> + }
> +
> + di->ocv_lut.rows = of_property_read_variable_u8_array(di->dev->of_node,
> + "qcom,ocv-capacity-legend",
> + di->ocv_lut.capacity_legend, 0,
> + MAX_CAPACITY_ROWS);
> + if (di->ocv_lut.rows < 0) {
> + dev_err(di->dev, "no open circuit voltage capacity legend found");
> + return ret;
> + }
> +
> + ret = of_property_read_variable_u32_array(di->dev->of_node,
> + "qcom,ocv-lut-microvolt",
> + (u32 *)di->ocv_lut.lut,
> + TEMPERATURE_COLS,
> + TEMPERATURE_COLS *
> + MAX_CAPACITY_ROWS);
> + if (ret < 0) {
> + dev_err(di->dev, "no open circuit voltage lut array found");
> + return ret;
> + }
> +
> + ret = of_property_read_u8_array(di->dev->of_node,
> + "qcom,fcc-temp-legend-celsius",
> + (u8 *)di->fcc_lut.temp_legend,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no full charge capacity temperature legend found");
> + return ret;
> + }
> +
> + ret = of_property_read_u32_array(di->dev->of_node,
> + "qcom,fcc-lut-microamp-hours",
> + di->fcc_lut.lut,
> + TEMPERATURE_COLS);
> + if (ret < 0) {
> + dev_err(di->dev, "no full charge capacity lut array found");
> + return ret;
> + }
> +
> + ret = bms_read_ocv(di, &di->ocv);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to read initial open circuit voltage: %d",
> + ret);
> + return ret;
> + }
> +
> + mutex_init(&di->bms_output_lock);
> +
> + di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
> +
> + ret = devm_request_threaded_irq(di->dev, di->ocv_thr_irq, NULL,
> + bms_ocv_thr_irq_handler,
> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> + pdev->name, di);
> + if (ret < 0) {
> + dev_err(di->dev, "failed to request handler for open circuit voltage threshold IRQ");
> + return ret;
> + }
> +
> +

one empty line is enough.

> + di->bat_desc.name = "bms";
> + di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
> + di->bat_desc.properties = bms_props;
> + di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
> + di->bat_desc.get_property = bms_get_property;
> +
> + psy_cfg.drv_data = di;

psy_cfg.of_node = pdev->dev.of_node;

> + bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
> +
> + return PTR_ERR_OR_ZERO(bat);
> +}
> +
> +static const struct of_device_id bms_of_match[] = {
> + {.compatible = "qcom,pm8941-bms", },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, bms_of_match);
> +
> +static struct platform_driver bms_driver = {
> + .probe = bms_probe,
> + .driver = {
> + .name = "qcom-bms",
> + .of_match_table = of_match_ptr(bms_of_match),
> + },
> +};
> +module_platform_driver(bms_driver);
> +
> +MODULE_AUTHOR("Craig Tatlor <[email protected]>");
> +MODULE_DESCRIPTION("Qualcomm BMS driver");
> +MODULE_LICENSE("GPL");

Apart from the things above I would like to see the information
about the battery cell itself being moved to 'struct
power_supply_battery_info', see also my comment in the DT bindings.

-- Sebastian


Attachments:
(No filename) (18.22 kB)
signature.asc (849.00 B)
Download all attachments

2018-09-16 20:06:01

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Hi,

Sorry for my long delay in reviewing this. I like the binding,
but the "qcom," specific properties should become common properties
in

Documentation/devicetree/bindings/power/supply/battery.txt

and referenced via monitored-battery.

-- Sebastian

On Thu, Jun 14, 2018 at 04:14:16PM +0100, Craig Tatlor wrote:
> Add bindings for the Qualcomm Battery Monitoring system.
>
> Signed-off-by: Craig Tatlor <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>
> ---
>
> * Changes from v6:
> s/celcius/celsius
> change uah to uAh.
>
> * Changes from v5:
> Mentions which values are 8 bit.
>
> * Changes from v4:
> Uses proper units and expands some definitions,
> along with changing vadc@ to adc@.
>
> .../bindings/power/supply/qcom_bms.txt | 92 +++++++++++++++++++
> 1 file changed, 92 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>
> diff --git a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> new file mode 100644
> index 000000000000..dc0a9ab9aa64
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
> @@ -0,0 +1,92 @@
> +Qualcomm Battery Monitoring System
> +
> +The Qualcomm Battery Monitoring System is found inside of Qualcomm PM8941
> +PMICs. It provides open circuit voltage (OCV) and coulomb counter registers
> +that allow the OS to infer a capacity level.
> +
> +Required properties:
> +- compatible: Should contain "qcom,pm8941-bms".
> +- reg: Specifies the SPMI address and length of the
> + controller's registers.
> +- interrupts: OCV threshold interrupt.
> +- io-channels: Should contain IIO channel specifier for the
> + ADC channel that reports battery temperature.
> +- io-channel-names: Should contain "temp".
> +- qcom,fcc-temp-legend-celsius: An 8 bit array containing the temperature,
> + in degC, for each column of the full charge
> + capacity lookup table.
> +- qcom,fcc-lut-microamp-hours: An array of full charge capacity values in uAh,
> + one entry for each temperature defined in in
> + qcom,fcc-temp-legend-celsius.
> +- qcom,ocv-temp-legend-celsius: An 8 bit array containing the temperature,
> + in degC, for each column of the OCV lookup
> + table.
> +- qcom,ocv-capacity-legend: An 8 bit array containing the capacity for each
> + row of the OCV lookup table.
> +- qcom,ocv-lut-microvolt: An array of OCV values in uV, one entry for each
> + capacity defined in qcom,ocv-capacity-legend.
> +
> +Example:
> + pm8941_vadc: adc@3100 {
> + compatible = "qcom,spmi-vadc";
> + reg = <0x3100>;
> + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + #io-channel-cells = <1>;
> +
> + bat_temp {
> + reg = <VADC_LR_MUX1_BAT_THERM>;
> + };
> + };
> +
> + bms@4000 {
> + compatible = "qcom,pm8941-bms";
> + reg = <0x4000>;
> + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "ocv_thr";
> +
> + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
> + io-channel-names = "temp";
> +
> + qcom,fcc-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
> + qcom,fcc-lut-microamp-hours = <3230000 3260000 3380000 3410000 3360000>;
> +
> + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75
> + 70 65 60 55 50 45
> + 40 35 30 25 20 15
> + 10 9 8 7 6 5 4 3 2
> + 1 0>;
> + qcom,ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
> + qcom,ocv-lut-microvolt = <43050000 43050000 43030000 42990000 42950000
> + 42770000 42570000 42550000 42510000 42310000
> + 42180000 41980000 41970000 41920000 41720000
> + 41590000 41390000 41450000 41400000 41200000
> + 41010000 40810000 40920000 40890000 40690000
> + 40480000 40280000 40440000 40420000 40220000
> + 40040000 39840000 40010000 39980000 39780000
> + 39620000 39420000 39550000 39560000 39360000
> + 39210000 39010000 39090000 39160000 38960000
> + 38830000 38630000 38740000 38790000 38590000
> + 38550000 38350000 38440000 38430000 38230000
> + 38310000 38110000 38230000 38180000 37980000
> + 38190000 37990000 38040000 38000000 37800000
> + 38060000 37860000 37900000 37840000 37640000
> + 37890000 37690000 37770000 37660000 37460000
> + 37720000 37520000 37560000 37450000 37250000
> + 37480000 37280000 37290000 37250000 37050000
> + 37240000 37040000 37020000 36990000 36790000
> + 37030000 36830000 36730000 36700000 36500000
> + 36940000 36740000 36670000 36640000 36440000
> + 36850000 36650000 36600000 36590000 36390000
> + 36750000 36550000 36520000 36550000 36350000
> + 36690000 36490000 36380000 36400000 36200000
> + 36460000 36260000 36180000 36120000 35920000
> + 36080000 35880000 35680000 35640000 35440000
> + 35510000 35310000 35050000 35020000 34820000
> + 34730000 34530000 34300000 34250000 34050000
> + 33870000 33670000 33040000 32820000 32620000
> + 30000000 30000000 30000000 30000000 30000000>;
> + };
> + };
> +};
> --
> 2.17.0
>


Attachments:
(No filename) (6.27 kB)
signature.asc (849.00 B)
Download all attachments

2018-09-20 14:37:42

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings



On 16 September 2018 13:10:45 BST, Sebastian Reichel <[email protected]> wrote:
>Hi,
>
>Sorry for my long delay in reviewing this. I like the binding,
>but the "qcom," specific properties should become common properties
>in
>
>Documentation/devicetree/bindings/power/supply/battery.txt
Thanks for the review, what bindings for ocv would you prefer? The spreadtrum ones or mine?
>and referenced via monitored-battery.
>
>-- Sebastian
>
>On Thu, Jun 14, 2018 at 04:14:16PM +0100, Craig Tatlor wrote:
>> Add bindings for the Qualcomm Battery Monitoring system.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>> Reviewed-by: Rob Herring <[email protected]>
>> ---
>>
>> * Changes from v6:
>> s/celcius/celsius
>> change uah to uAh.
>>
>> * Changes from v5:
>
>> Mentions which values are 8 bit.
>
>>
>
>> * Changes from v4:
>
>> Uses proper units and expands some definitions,
>
>> along with changing vadc@ to adc@.
>>
>> .../bindings/power/supply/qcom_bms.txt | 92
>+++++++++++++++++++
>> 1 file changed, 92 insertions(+)
>> create mode 100644
>Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>>
>> diff --git
>a/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> new file mode 100644
>> index 000000000000..dc0a9ab9aa64
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/supply/qcom_bms.txt
>> @@ -0,0 +1,92 @@
>> +Qualcomm Battery Monitoring System
>> +
>> +The Qualcomm Battery Monitoring System is found inside of Qualcomm
>PM8941
>> +PMICs. It provides open circuit voltage (OCV) and coulomb counter
>registers
>> +that allow the OS to infer a capacity level.
>> +
>> +Required properties:
>> +- compatible: Should contain "qcom,pm8941-bms".
>> +- reg: Specifies the SPMI address and
>length of the
>> + controller's registers.
>> +- interrupts: OCV threshold interrupt.
>> +- io-channels: Should contain IIO channel specifier
>for the
>> + ADC channel that reports battery temperature.
>> +- io-channel-names: Should contain "temp".
>> +- qcom,fcc-temp-legend-celsius: An 8 bit array containing the
>temperature,
>> + in degC, for each column of the full charge
>> + capacity lookup table.
>> +- qcom,fcc-lut-microamp-hours: An array of full charge capacity
>values in uAh,
>> + one entry for each temperature defined in in
>> + qcom,fcc-temp-legend-celsius.
>> +- qcom,ocv-temp-legend-celsius: An 8 bit array containing the
>temperature,
>> + in degC, for each column of the OCV lookup
>> + table.
>> +- qcom,ocv-capacity-legend: An 8 bit array containing the
>capacity for each
>> + row of the OCV lookup table.
>> +- qcom,ocv-lut-microvolt: An array of OCV values in uV, one
>entry for each
>> + capacity defined in qcom,ocv-capacity-legend.
>> +
>> +Example:
>> + pm8941_vadc: adc@3100 {
>> + compatible = "qcom,spmi-vadc";
>> + reg = <0x3100>;
>> + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + #io-channel-cells = <1>;
>> +
>> + bat_temp {
>> + reg = <VADC_LR_MUX1_BAT_THERM>;
>> + };
>> + };
>> +
>> + bms@4000 {
>> + compatible = "qcom,pm8941-bms";
>> + reg = <0x4000>;
>> + interrupts = <0x0 0x40 0x4 IRQ_TYPE_EDGE_RISING>;
>> + interrupt-names = "ocv_thr";
>> +
>> + io-channels = <&pm8941_vadc VADC_LR_MUX1_BAT_THERM>;
>> + io-channel-names = "temp";
>> +
>> + qcom,fcc-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
>> + qcom,fcc-lut-microamp-hours = <3230000 3260000 3380000 3410000
>3360000>;
>> +
>> + qcom,ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75
>> + 70 65 60 55 50 45
>> + 40 35 30 25 20 15
>> + 10 9 8 7 6 5 4 3 2
>> + 1 0>;
>> + qcom,ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
>> + qcom,ocv-lut-microvolt = <43050000 43050000 43030000 42990000
>42950000
>> + 42770000 42570000 42550000 42510000 42310000
>> + 42180000 41980000 41970000 41920000 41720000
>> + 41590000 41390000 41450000 41400000 41200000
>> + 41010000 40810000 40920000 40890000 40690000
>> + 40480000 40280000 40440000 40420000 40220000
>> + 40040000 39840000 40010000 39980000 39780000
>> + 39620000 39420000 39550000 39560000 39360000
>> + 39210000 39010000 39090000 39160000 38960000
>> + 38830000 38630000 38740000 38790000 38590000
>> + 38550000 38350000 38440000 38430000 38230000
>> + 38310000 38110000 38230000 38180000 37980000
>> + 38190000 37990000 38040000 38000000 37800000
>> + 38060000 37860000 37900000 37840000 37640000
>> + 37890000 37690000 37770000 37660000 37460000
>> + 37720000 37520000 37560000 37450000 37250000
>> + 37480000 37280000 37290000 37250000 37050000
>> + 37240000 37040000 37020000 36990000 36790000
>> + 37030000 36830000 36730000 36700000 36500000
>> + 36940000 36740000 36670000 36640000 36440000
>> + 36850000 36650000 36600000 36590000 36390000
>> + 36750000 36550000 36520000 36550000 36350000
>> + 36690000 36490000 36380000 36400000 36200000
>> + 36460000 36260000 36180000 36120000 35920000
>> + 36080000 35880000 35680000 35640000 35440000
>> + 35510000 35310000 35050000 35020000 34820000
>> + 34730000 34530000 34300000 34250000 34050000
>> + 33870000 33670000 33040000 32820000 32620000
>> + 30000000 30000000 30000000 30000000 30000000>;
>> + };
>> + };
>> +};
>> --
>> 2.17.0
>>

--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

2018-09-20 14:45:56

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v7 2/4] power: supply: Add support for the Qualcomm Battery Monitoring System

Replies inline

On 16 September 2018 14:48:36 BST, Sebastian Reichel <[email protected]> wrote:
>Hi,
>
>First of all thanks for the patch and big sorry for the long delay
>in reviewing this. I did not find enough time to do it properly
>until now :(
>
>On Thu, Jun 14, 2018 at 04:14:15PM +0100, Craig Tatlor wrote:
>> This patch adds a driver for the BMS (Battery Monitoring System)
>> block of the PM8941 PMIC, it uses a lookup table defined in the
>> device tree to generate a capacity from the BMS supplied OCV, it
>> then amends the coulomb counter to that to increase the accuracy
>> of the estimated capacity.
>>
>> Signed-off-by: Craig Tatlor <[email protected]>
>> Reviewed-by: Linus Walleij <[email protected]>
>> ---
>>
>> * Changes from v5:
>
>> Uses select for REGMAP_SPMI.
>
>>
>
>> * Changes from v4:
>
>> Cleaned up percentage interpolation function,
>
>> uses new fixp interpolation helper,
>
>> added some more error cases,
>
>> uses devm_power_supply_register(),
>
>> uses a DIV_ROUND_CLOSEST for division and
>
>> uses micro(volts / amp hours) instead of
>
>> milli (volts / amp hours).
>>
>> drivers/power/supply/Kconfig | 9 +
>> drivers/power/supply/Makefile | 1 +
>> drivers/power/supply/qcom_bms.c | 487
>++++++++++++++++++++++++++++++++
>> 3 files changed, 497 insertions(+)
>> create mode 100644 drivers/power/supply/qcom_bms.c
>>
>> diff --git a/drivers/power/supply/Kconfig
>b/drivers/power/supply/Kconfig
>> index 428b426842f4..75f2f375f992 100644
>> --- a/drivers/power/supply/Kconfig
>> +++ b/drivers/power/supply/Kconfig
>> @@ -82,6 +82,15 @@ config BATTERY_ACT8945A
>> Say Y here to enable support for power supply provided by
>> Active-semi ActivePath ACT8945A charger.
>>
>> +config BATTERY_BMS
>> + tristate "Qualcomm Battery Monitoring System driver"
>> + depends on MFD_SPMI_PMIC || COMPILE_TEST
>> + depends on OF
>> + select REGMAP_SPMI
>> + help
>> + Say Y to include support for the Battery Monitoring hardware
>> + found in some Qualcomm PM series PMICs.
>> +
>> config BATTERY_CPCAP
>> tristate "Motorola CPCAP PMIC battery driver"
>> depends on MFD_CPCAP && IIO
>> diff --git a/drivers/power/supply/Makefile
>b/drivers/power/supply/Makefile
>> index e83aa843bcc6..04204174b047 100644
>> --- a/drivers/power/supply/Makefile
>> +++ b/drivers/power/supply/Makefile
>> @@ -21,6 +21,7 @@ obj-$(CONFIG_BATTERY_88PM860X) +=
>88pm860x_battery.o
>> obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
>> obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
>> obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
>> +obj-$(CONFIG_BATTERY_BMS) += qcom_bms.o
>> obj-$(CONFIG_BATTERY_CPCAP) += cpcap-battery.o
>> obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
>> obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o
>> diff --git a/drivers/power/supply/qcom_bms.c
>b/drivers/power/supply/qcom_bms.c
>> new file mode 100644
>> index 000000000000..718fd745c0f7
>> --- /dev/null
>> +++ b/drivers/power/supply/qcom_bms.c
>> @@ -0,0 +1,487 @@
>> +// SPDX-License-Identifier: GPL
>> +
>> +/*
>> + * Qualcomm Battery Monitoring System driver
>> + *
>> + * Copyright (C) 2018 Craig Tatlor <[email protected]>
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/fixp-arith.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/power_supply.h>
>> +#include <linux/slab.h>
>> +#include <linux/bitops.h>
>> +#include <linux/of.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/regmap.h>
>> +#include <linux/irq.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/iio/consumer.h>
>> +
>> +#define REG_BMS_OCV_FOR_SOC_DATA0 0x90
>> +#define REG_BMS_SHDW_CC_DATA0 0xA8
>> +#define REG_BMS_CC_DATA_CTL 0x42
>> +#define REG_BMS_CC_CLEAR_CTL 0x4
>> +
>> +#define BMS_HOLD_OREG_DATA BIT(0)
>> +#define BMS_CLEAR_SHDW_CC BIT(6)
>> +
>> +#define BMS_CC_READING_RESOLUTION_N 542535
>> +#define BMS_CC_READING_RESOLUTION_D 10000
>> +#define BMS_CC_READING_TICKS 56
>> +#define BMS_SLEEP_CLK_HZ 32764
>> +
>> +#define SECONDS_PER_HOUR 3600
>> +#define TEMPERATURE_COLS 5
>> +#define MAX_CAPACITY_ROWS 50
>> +
>> +/* lookup table for ocv -> capacity conversion */
>> +struct bms_ocv_lut {
>> + int rows;
>> + s8 temp_legend[TEMPERATURE_COLS];
>> + u8 capacity_legend[MAX_CAPACITY_ROWS];
>> + u32 lut[MAX_CAPACITY_ROWS][TEMPERATURE_COLS];
>> +};
>> +
>> +/* lookup table for battery temperature -> fcc conversion */
>> +struct bms_fcc_lut {
>> + s8 temp_legend[TEMPERATURE_COLS];
>> + u32 lut[TEMPERATURE_COLS];
>> +};
>> +
>> +struct bms_device_info {
>> + struct device *dev;
>> + struct regmap *regmap;
>> + struct bms_ocv_lut ocv_lut;
>> + struct power_supply_desc bat_desc;
>> + struct bms_fcc_lut fcc_lut;
>> + struct iio_channel *adc;
>> + struct mutex bms_output_lock;
>> + u32 base_addr;
>> +
>> + int ocv_thr_irq;
>> + u32 ocv;
>> +};
>> +
>> +static bool between(int left, int right, int val)
>> +{
>> + if (left <= val && val <= right)
>> + return true;
>> +
>> + if (left >= val && val >= right)
>> + return true;
>> +
>> + return false;
>> +}
>> +
>> +static int interpolate_capacity(int temp, u32 ocv,
>> + struct bms_ocv_lut *ocv_lut)
>> +{
>> + int pcj_minus_one = 0, pcj = 0, i2 = 0, i3 = 0, i, j;
>> +
>> + for (j = 0; j < TEMPERATURE_COLS; j++)
>> + if (temp <= ocv_lut->temp_legend[j])
>> + break;
>> +
>> + if (ocv >= ocv_lut->lut[0][j])
>> + return ocv_lut->capacity_legend[0];
>> +
>> + if (ocv <= ocv_lut->lut[ocv_lut->rows-1][j-1])
>> + return ocv_lut->capacity_legend[ocv_lut->rows-1];
>> +
>> + for (i = 0; i < ocv_lut->rows-1; i++) {
>> + if (between(ocv_lut->lut[i][j],
>> + ocv_lut->lut[i+1][j], ocv))
>> + i2 = i;
>> +
>> + if (between(ocv_lut->lut[i][j-1],
>> + ocv_lut->lut[i+1][j-1], ocv))
>> + i3 = i;
>> + }
>> +
>> + /* interpolate two capacities */
>> + pcj = fixp_linear_interpolate(ocv_lut->lut[i2][j],
>> + ocv_lut->capacity_legend[i2],
>> + ocv_lut->lut[i2+1][j],
>> + ocv_lut->capacity_legend[i2+1],
>> + ocv);
>> +
>> + pcj_minus_one = fixp_linear_interpolate(ocv_lut->lut[i3][j-1],
>> + ocv_lut->capacity_legend[i3],
>> + ocv_lut->lut[i3+1][j-1],
>> + ocv_lut->capacity_legend[i3+1],
>> + ocv);
>> +
>> + /* interpolate them with the battery temperature */
>> + return fixp_linear_interpolate(ocv_lut->temp_legend[j-1],
>> + pcj_minus_one,
>> + ocv_lut->temp_legend[j],
>> + pcj,
>> + temp);
>> +}
>> +
>> +static int interpolate_fcc(int temp, struct bms_fcc_lut *fcc_lut)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < TEMPERATURE_COLS; i++)
>> + if (temp <= fcc_lut->temp_legend[i])
>> + break;
>> +
>> + return fixp_linear_interpolate(fcc_lut->temp_legend[i-1],
>> + fcc_lut->lut[i-1],
>> + fcc_lut->temp_legend[i],
>> + fcc_lut->lut[i],
>> + temp);
>> +}
>> +
>> +static int bms_lock_output_data(struct bms_device_info *di)
>> +{
>> + int ret;
>> +
>> + ret = regmap_update_bits(di->regmap, di->base_addr +
>> + REG_BMS_CC_DATA_CTL,
>> + BMS_HOLD_OREG_DATA, BMS_HOLD_OREG_DATA);
>> + if (ret) {
>> + dev_err(di->dev, "failed to lock bms output: %d", ret);
>> + return ret;
>> + }
>> +
>> + /*
>> + * Sleep for at least 100 microseconds here to make sure
>> + * there has been at least three cycles of the sleep clock
>> + * so that the registers are correctly locked.
>> + */
>> + usleep_range(100, 1000);
>> +
>> + return 0;
>> +}
>> +
>> +static int bms_unlock_output_data(struct bms_device_info *di)
>> +{
>> + int ret;
>> +
>> + ret = regmap_update_bits(di->regmap, di->base_addr +
>> + REG_BMS_CC_DATA_CTL,
>> + BMS_HOLD_OREG_DATA, 0);
>> + if (ret) {
>> + dev_err(di->dev, "failed to unlock bms output: %d", ret);
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int bms_read_ocv(struct bms_device_info *di, u32 *ocv)
>> +{
>> + int ret;
>> + u16 read_ocv;
>> +
>> + mutex_lock(&di->bms_output_lock);
>> +
>> + ret = bms_lock_output_data(di);
>> + if (ret)
>> + goto err_lock;
>> +
>> + ret = regmap_bulk_read(di->regmap, di->base_addr+
>> + REG_BMS_OCV_FOR_SOC_DATA0, &read_ocv, 2);
>> + if (ret) {
>> + dev_err(di->dev, "open circuit voltage read failed: %d", ret);
>> + goto err_read;
>> + }
>> +
>> + dev_dbg(di->dev, "read open circuit voltage of: %d mv", read_ocv);
>> +
>> +
>
>one empty line is enough.
Will fix
>
>> + *ocv = read_ocv * 1000;
>> +
>> +err_read:
>> + bms_unlock_output_data(di);
>> +
>> +err_lock:
>> + mutex_unlock(&di->bms_output_lock);
>> +
>> + return ret;
>> +}
>> +
>> +static int bms_read_cc(struct bms_device_info *di, s64 *cc_uah)
>> +{
>> + int ret;
>> + s64 cc_raw_s36, cc_raw, cc_uv, cc_pvh;
>> +
>> + mutex_lock(&di->bms_output_lock);
>> +
>> + ret = bms_lock_output_data(di);
>> + if (ret)
>> + goto err_lock;
>> +
>> + ret = regmap_bulk_read(di->regmap, di->base_addr +
>> + REG_BMS_SHDW_CC_DATA0,
>> + &cc_raw_s36, 5);
>> + if (ret) {
>> + dev_err(di->dev, "coulomb counter read failed: %d", ret);
>> + goto err_read;
>> + }
>> +
>> + ret = bms_unlock_output_data(di);
>> + if (ret)
>> + goto err_lock;
>> +
>> + mutex_unlock(&di->bms_output_lock);
>> +
>> + cc_raw = sign_extend32(cc_raw_s36, 28);
>> +
>> + /* convert raw to uv */
>> + cc_uv = div_s64(cc_raw * BMS_CC_READING_RESOLUTION_N,
>> + BMS_CC_READING_RESOLUTION_D);
>> +
>> + /* convert uv to pvh */
>> + cc_pvh = div_s64(cc_uv * BMS_CC_READING_TICKS * 100000,
>> + BMS_SLEEP_CLK_HZ * SECONDS_PER_HOUR);
>> +
>> + /* divide by impedance */
>> + *cc_uah = div_s64(cc_pvh, 10000);
>> +
>> + dev_dbg(di->dev, "read coulomb counter value of: %lld uah",
>*cc_uah);
>> +
>> + return 0;
>> +
>> +err_read:
>> + bms_unlock_output_data(di);
>> +
>> +err_lock:
>> + mutex_unlock(&di->bms_output_lock);
>> +
>> + return ret;
>> +}
>> +
>> +static void bms_reset_cc(struct bms_device_info *di)
>> +{
>> + int ret;
>> +
>> + mutex_lock(&di->bms_output_lock);
>> +
>> + ret = regmap_update_bits(di->regmap, di->base_addr +
>> + REG_BMS_CC_CLEAR_CTL,
>> + BMS_CLEAR_SHDW_CC,
>> + BMS_CLEAR_SHDW_CC);
>> + if (ret) {
>> + dev_err(di->dev, "coulomb counter reset failed: %d", ret);
>> + goto err_lock;
>> + }
>> +
>> + /* wait at least three sleep cycles for cc to reset */
>> + usleep_range(100, 1000);
>> +
>> + ret = regmap_update_bits(di->regmap, di->base_addr +
>> + REG_BMS_CC_CLEAR_CTL,
>> + BMS_CLEAR_SHDW_CC, 0);
>> + if (ret)
>> + dev_err(di->dev, "coulomb counter re-enable failed: %d", ret);
>> +
>> +err_lock:
>> + mutex_unlock(&di->bms_output_lock);
>> +}
>> +
>> +static int bms_calculate_capacity(struct bms_device_info *di, int
>*capacity)
>> +{
>> + unsigned long fcc;
>> + int ret, temp, ocv_capacity, temp_degc;
>> + s64 cc = 0;
>> +
>> + ret = iio_read_channel_raw(di->adc, &temp);
>> + if (ret < 0) {
>> + dev_err(di->dev, "failed to read temperature: %d", ret);
>> + return ret;
>> + }
>> +
>> + temp_degc = DIV_ROUND_CLOSEST(temp, 1000);
>> +
>> + ret = bms_read_cc(di, &cc);
>> + if (ret < 0) {
>> + dev_err(di->dev, "failed to read coulomb counter: %d", ret);
>> + return ret;
>> + }
>> +
>> + /* interpolate capacity from open circuit voltage */
>> + ocv_capacity = interpolate_capacity(temp_degc, di->ocv,
>> + &di->ocv_lut);
>> +
>> + /* interpolate the full charge capacity from temperature */
>> + fcc = interpolate_fcc(temp_degc, &di->fcc_lut);
>> +
>> + /* append coloumb counter to capacity */
>> + *capacity = DIV_ROUND_CLOSEST(fcc * ocv_capacity, 100);
>> + *capacity = div_s64((*capacity - cc) * 100, fcc);
>> +
>> + return 0;
>> +}
>> +
>> +
>> +
>
>one empty line is enough.
Will fix
>
>> +/*
>> + * Return power_supply property
>> + */
>> +static int bms_get_property(struct power_supply *psy,
>> + enum power_supply_property psp,
>> + union power_supply_propval *val)
>> +{
>> + struct bms_device_info *di = power_supply_get_drvdata(psy);
>> + int ret;
>> +
>> + switch (psp) {
>> + case POWER_SUPPLY_PROP_CAPACITY:
>> + ret = bms_calculate_capacity(di, &val->intval);
>> + break;
>> + default:
>> + ret = -EINVAL;
>> + break;
>> + }
>> +
>> + if (val->intval == INT_MAX || val->intval == INT_MIN)
>> + ret = -EINVAL;
>> +
>> + return ret;
>> +}
>> +
>> +static enum power_supply_property bms_props[] = {
>> + POWER_SUPPLY_PROP_CAPACITY,
>> +};
>
>Why does the driver not expose the following battery information?
>
>temperature info via POWER_SUPPLY_PROP_TEMP
>ocv info via POWER_SUPPLY_PROP_VOLTAGE_OCV
>CC info via POWER_SUPPLY_PROP_CHARGE_COUNTER
>max current via POWER_SUPPLY_PROP_CURRENT_MAX

1. This is handled in the tsens driver iirc
2. Ocv is very inaccurate as it is only updated when device uses a very low amount of power (<10ma)
3. This isn't possible (unless you want to just give out the value anyway) due to the way the driver tracks the cc (resets on every ocv update)
4.this is done in the smbb driver, the BMS is only a fuelguage and not a fully blown charging ic
>
>> +static irqreturn_t bms_ocv_thr_irq_handler(int irq, void *dev_id)
>> +{
>> + struct bms_device_info *di = dev_id;
>> +
>> + if (bms_read_ocv(di, &di->ocv) < 0)
>> + return IRQ_HANDLED;
>> +
>> + bms_reset_cc(di);
>> + return IRQ_HANDLED;
>> +}
>
>You want to call power_supply_changed() here to notify userspace.
This doesn't mean battery is charged, just means ocv was updated (device used < 10ma of power)
>
>> +static int bms_probe(struct platform_device *pdev)
>> +{
>> + struct power_supply_config psy_cfg = {};
>> + struct bms_device_info *di;
>> + struct power_supply *bat;
>> + int ret;
>> +
>> + di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
>> + if (!di)
>> + return -ENOMEM;
>> +
>> + di->dev = &pdev->dev;
>> +
>> + di->regmap = dev_get_regmap(pdev->dev.parent, NULL);
>> + if (!di->regmap) {
>> + dev_err(di->dev, "Unable to get regmap");
>> + return -EINVAL;
>> + }
>> +
>> + di->adc = devm_iio_channel_get(&pdev->dev, "temp");
>> + if (IS_ERR(di->adc))
>> + return PTR_ERR(di->adc);
>> +
>> + ret = of_property_read_u32(di->dev->of_node, "reg",
>&di->base_addr);
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = of_property_read_u8_array(di->dev->of_node,
>> + "qcom,ocv-temp-legend-celsius",
>> + (u8 *)di->ocv_lut.temp_legend,
>> + TEMPERATURE_COLS);
>> + if (ret < 0) {
>> + dev_err(di->dev, "no open circuit voltage temperature legend
>found");
>> + return ret;
>> + }
>> +
>> + di->ocv_lut.rows =
>of_property_read_variable_u8_array(di->dev->of_node,
>> + "qcom,ocv-capacity-legend",
>> + di->ocv_lut.capacity_legend, 0,
>> + MAX_CAPACITY_ROWS);
>> + if (di->ocv_lut.rows < 0) {
>> + dev_err(di->dev, "no open circuit voltage capacity legend found");
>> + return ret;
>> + }
>> +
>> + ret = of_property_read_variable_u32_array(di->dev->of_node,
>> + "qcom,ocv-lut-microvolt",
>> + (u32 *)di->ocv_lut.lut,
>> + TEMPERATURE_COLS,
>> + TEMPERATURE_COLS *
>> + MAX_CAPACITY_ROWS);
>> + if (ret < 0) {
>> + dev_err(di->dev, "no open circuit voltage lut array found");
>> + return ret;
>> + }
>> +
>> + ret = of_property_read_u8_array(di->dev->of_node,
>> + "qcom,fcc-temp-legend-celsius",
>> + (u8 *)di->fcc_lut.temp_legend,
>> + TEMPERATURE_COLS);
>> + if (ret < 0) {
>> + dev_err(di->dev, "no full charge capacity temperature legend
>found");
>> + return ret;
>> + }
>> +
>> + ret = of_property_read_u32_array(di->dev->of_node,
>> + "qcom,fcc-lut-microamp-hours",
>> + di->fcc_lut.lut,
>> + TEMPERATURE_COLS);
>> + if (ret < 0) {
>> + dev_err(di->dev, "no full charge capacity lut array found");
>> + return ret;
>> + }
>> +
>> + ret = bms_read_ocv(di, &di->ocv);
>> + if (ret < 0) {
>> + dev_err(di->dev, "failed to read initial open circuit voltage:
>%d",
>> + ret);
>> + return ret;
>> + }
>> +
>> + mutex_init(&di->bms_output_lock);
>> +
>> + di->ocv_thr_irq = platform_get_irq_byname(pdev, "ocv_thr");
>> +
>> + ret = devm_request_threaded_irq(di->dev, di->ocv_thr_irq, NULL,
>> + bms_ocv_thr_irq_handler,
>> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
>> + pdev->name, di);
>> + if (ret < 0) {
>> + dev_err(di->dev, "failed to request handler for open circuit
>voltage threshold IRQ");
>> + return ret;
>> + }
>> +
>> +
>
>one empty line is enough.
>
>> + di->bat_desc.name = "bms";
>> + di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
>> + di->bat_desc.properties = bms_props;
>> + di->bat_desc.num_properties = ARRAY_SIZE(bms_props);
>> + di->bat_desc.get_property = bms_get_property;
>> +
>> + psy_cfg.drv_data = di;
>
>psy_cfg.of_node = pdev->dev.of_node;
>
>> + bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
>> +
>> + return PTR_ERR_OR_ZERO(bat);
>> +}
>> +
>> +static const struct of_device_id bms_of_match[] = {
>> + {.compatible = "qcom,pm8941-bms", },
>> + { },
>> +};
>> +MODULE_DEVICE_TABLE(of, bms_of_match);
>> +
>> +static struct platform_driver bms_driver = {
>> + .probe = bms_probe,
>> + .driver = {
>> + .name = "qcom-bms",
>> + .of_match_table = of_match_ptr(bms_of_match),
>> + },
>> +};
>> +module_platform_driver(bms_driver);
>> +
>> +MODULE_AUTHOR("Craig Tatlor <[email protected]>");
>> +MODULE_DESCRIPTION("Qualcomm BMS driver");
>> +MODULE_LICENSE("GPL");
>
>Apart from the things above I would like to see the information
>about the battery cell itself being moved to 'struct
>power_supply_battery_info', see also my comment in the DT bindings.
Sure, will look into it
>
>-- Sebastian

2018-09-20 17:00:32

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

[Dropped a couple of people from CC, added Baolin]

Hi Craig, Baolin and Rob,

On Thu, Sep 20, 2018 at 03:32:29PM +0100, Craig wrote:
> On 16 September 2018 13:10:45 BST, Sebastian Reichel <[email protected]> wrote:
> >Sorry for my long delay in reviewing this. I like the binding,
> >but the "qcom," specific properties should become common properties
> >in
> >
> >Documentation/devicetree/bindings/power/supply/battery.txt
> >and referenced via monitored-battery.

> Thanks for the review, what bindings for ocv would you prefer? The
> spreadtrum ones or mine?

Most importantly I want to see only one generic binding supporting
both use cases. As far as I can see there are two major differences:

1. Qcom uses legend properties and SC27XX embedds this into data
2. Qcom supports temperature based mapping

The second point is easy: Not having temperature information can
be a subset of the data with temperature info. The main thing to
discuss are the legend properties. I suppose we have these
proposals:

Proposal A (from Qcom BMS binding):

ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75 70 65 60 55 50 45 ...>;
ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
ocv-lut-microvolt = <43050000 43050000 43030000 42990000

Proposal B (from SC27XX binding):

ocv-cap-table = <4185 100>, <4113 95>, <4066 90>, <4022 85> ...;

I prefer the second binding (with mV -> uV), but I think it becomes
messy when temperature is added. What do you think about the
following proposal (derived from pinctrl style):

Proposal C:

ocv-capacity-table-temperatures = <(-10) 0 10>;
ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;

-- Sebastian


Attachments:
(No filename) (1.82 kB)
signature.asc (849.00 B)
Download all attachments

2018-09-20 19:14:31

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings



On 20 September 2018 17:58:47 BST, Sebastian Reichel <[email protected]> wrote:
>[Dropped a couple of people from CC, added Baolin]
>
>Hi Craig, Baolin and Rob,
>
>On Thu, Sep 20, 2018 at 03:32:29PM +0100, Craig wrote:
>> On 16 September 2018 13:10:45 BST, Sebastian Reichel
><[email protected]> wrote:
>> >Sorry for my long delay in reviewing this. I like the binding,
>> >but the "qcom," specific properties should become common properties
>> >in
>> >
>> >Documentation/devicetree/bindings/power/supply/battery.txt
>> >and referenced via monitored-battery.
>
>> Thanks for the review, what bindings for ocv would you prefer? The
>> spreadtrum ones or mine?
>
>Most importantly I want to see only one generic binding supporting
>both use cases. As far as I can see there are two major differences:
>
>1. Qcom uses legend properties and SC27XX embedds this into data
>2. Qcom supports temperature based mapping
>
>The second point is easy: Not having temperature information can
>be a subset of the data with temperature info. The main thing to
>discuss are the legend properties. I suppose we have these
>proposals:
>
>Proposal A (from Qcom BMS binding):
>
>ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75 70 65 60 55 50 45
>...>;
>ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
>ocv-lut-microvolt = <43050000 43050000 43030000 42990000
>
>Proposal B (from SC27XX binding):
>
>ocv-cap-table = <4185 100>, <4113 95>, <4066 90>, <4022 85> ...;
>
>I prefer the second binding (with mV -> uV), but I think it becomes
>messy when temperature is added. What do you think about the
>following proposal (derived from pinctrl style):
>
>Proposal C:
>
>ocv-capacity-table-temperatures = <(-10) 0 10>;
>ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
>ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
>ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;
>
>-- Sebastian

C looks good to me however I do kinda think it should be millivolts as I don't think any hardware reads in microvolts and the zeroes make it look quite ugly

2018-09-20 20:09:15

by Baolin Wang

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Hi Sebastian,

On 21 September 2018 at 00:58, Sebastian Reichel
<[email protected]> wrote:
> [Dropped a couple of people from CC, added Baolin]
>
> Hi Craig, Baolin and Rob,
>
> On Thu, Sep 20, 2018 at 03:32:29PM +0100, Craig wrote:
>> On 16 September 2018 13:10:45 BST, Sebastian Reichel <[email protected]> wrote:
>> >Sorry for my long delay in reviewing this. I like the binding,
>> >but the "qcom," specific properties should become common properties
>> >in
>> >
>> >Documentation/devicetree/bindings/power/supply/battery.txt
>> >and referenced via monitored-battery.
>
>> Thanks for the review, what bindings for ocv would you prefer? The
>> spreadtrum ones or mine?
>
> Most importantly I want to see only one generic binding supporting
> both use cases. As far as I can see there are two major differences:
>
> 1. Qcom uses legend properties and SC27XX embedds this into data
> 2. Qcom supports temperature based mapping
>
> The second point is easy: Not having temperature information can
> be a subset of the data with temperature info. The main thing to
> discuss are the legend properties. I suppose we have these
> proposals:
>
> Proposal A (from Qcom BMS binding):
>
> ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75 70 65 60 55 50 45 ...>;
> ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
> ocv-lut-microvolt = <43050000 43050000 43030000 42990000
>
> Proposal B (from SC27XX binding):
>
> ocv-cap-table = <4185 100>, <4113 95>, <4066 90>, <4022 85> ...;
>
> I prefer the second binding (with mV -> uV), but I think it becomes
> messy when temperature is added. What do you think about the
> following proposal (derived from pinctrl style):
>
> Proposal C:
>
> ocv-capacity-table-temperatures = <(-10) 0 10>;
> ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
> ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
> ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;

For SC27XX, we have no temperatures consideration, but I think
Proposal C can be compatible with our case.

--
Baolin Wang
Best Regards

2018-09-21 01:41:35

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

Hi,

On Fri, Sep 21, 2018 at 04:08:28AM +0800, Baolin Wang wrote:
> Hi Sebastian,
>
> On 21 September 2018 at 00:58, Sebastian Reichel
> <[email protected]> wrote:
> > [Dropped a couple of people from CC, added Baolin]
> >
> > Hi Craig, Baolin and Rob,
> >
> > On Thu, Sep 20, 2018 at 03:32:29PM +0100, Craig wrote:
> >> On 16 September 2018 13:10:45 BST, Sebastian Reichel <[email protected]> wrote:
> >> >Sorry for my long delay in reviewing this. I like the binding,
> >> >but the "qcom," specific properties should become common properties
> >> >in
> >> >
> >> >Documentation/devicetree/bindings/power/supply/battery.txt
> >> >and referenced via monitored-battery.
> >
> >> Thanks for the review, what bindings for ocv would you prefer? The
> >> spreadtrum ones or mine?
> >
> > Most importantly I want to see only one generic binding supporting
> > both use cases. As far as I can see there are two major differences:
> >
> > 1. Qcom uses legend properties and SC27XX embedds this into data
> > 2. Qcom supports temperature based mapping
> >
> > The second point is easy: Not having temperature information can
> > be a subset of the data with temperature info. The main thing to
> > discuss are the legend properties. I suppose we have these
> > proposals:
> >
> > Proposal A (from Qcom BMS binding):
> >
> > ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75 70 65 60 55 50 45 ...>;
> > ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
> > ocv-lut-microvolt = <43050000 43050000 43030000 42990000
> >
> > Proposal B (from SC27XX binding):
> >
> > ocv-cap-table = <4185 100>, <4113 95>, <4066 90>, <4022 85> ...;
> >
> > I prefer the second binding (with mV -> uV), but I think it becomes
> > messy when temperature is added. What do you think about the
> > following proposal (derived from pinctrl style):
> >
> > Proposal C:
> >
> > ocv-capacity-table-temperatures = <(-10) 0 10>;
> > ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
> > ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
> > ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;
>
> For SC27XX, we have no temperatures consideration, but I think
> Proposal C can be compatible with our case.

Yes. I think for SC27XX proposal C could be used like this:

ocv-capacity-table-temperatures = <20>; /* room temperature */
ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;

With only one curve defined it would be used for all temperatures.

-- Sebastian


Attachments:
(No filename) (2.55 kB)
signature.asc (849.00 B)
Download all attachments

2018-09-21 01:43:00

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

On Thu, Sep 20, 2018 at 08:13:52PM +0100, Craig wrote:
> On 20 September 2018 17:58:47 BST, Sebastian Reichel <[email protected]> wrote:
> >[Dropped a couple of people from CC, added Baolin]
> >
> >Hi Craig, Baolin and Rob,
> >
> >On Thu, Sep 20, 2018 at 03:32:29PM +0100, Craig wrote:
> >> On 16 September 2018 13:10:45 BST, Sebastian Reichel
> ><[email protected]> wrote:
> >> >Sorry for my long delay in reviewing this. I like the binding,
> >> >but the "qcom," specific properties should become common properties
> >> >in
> >> >
> >> >Documentation/devicetree/bindings/power/supply/battery.txt
> >> >and referenced via monitored-battery.
> >
> >> Thanks for the review, what bindings for ocv would you prefer? The
> >> spreadtrum ones or mine?
> >
> >Most importantly I want to see only one generic binding supporting
> >both use cases. As far as I can see there are two major differences:
> >
> >1. Qcom uses legend properties and SC27XX embedds this into data
> >2. Qcom supports temperature based mapping
> >
> >The second point is easy: Not having temperature information can
> >be a subset of the data with temperature info. The main thing to
> >discuss are the legend properties. I suppose we have these
> >proposals:
> >
> >Proposal A (from Qcom BMS binding):
> >
> >ocv-capacity-legend = /bits/ 8 <100 95 90 85 80 75 70 65 60 55 50 45
> >...>;
> >ocv-temp-legend-celsius = /bits/ 8 <(-10) 0 25 50 65>;
> >ocv-lut-microvolt = <43050000 43050000 43030000 42990000
> >
> >Proposal B (from SC27XX binding):
> >
> >ocv-cap-table = <4185 100>, <4113 95>, <4066 90>, <4022 85> ...;
> >
> >I prefer the second binding (with mV -> uV), but I think it becomes
> >messy when temperature is added. What do you think about the
> >following proposal (derived from pinctrl style):
> >
> >Proposal C:
> >
> >ocv-capacity-table-temperatures = <(-10) 0 10>;
> >ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
> >ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
> >ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;
> >
> >-- Sebastian
>
> C looks good to me however I do kinda think it should be
> millivolts as I don't think any hardware reads in microvolts and
> the zeroes make it look quite ugly

I agree, that it looks a bit ugly in the table. Nevertheless I think we
should use microvolts, since that is being used by all other properties.

-- Sebastian


Attachments:
(No filename) (2.45 kB)
signature.asc (849.00 B)
Download all attachments

2018-09-21 15:42:12

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] dt-bindings: power: supply: qcom_bms: Add bindings

On Thu, Sep 20, 2018 at 9:58 AM Sebastian Reichel
<[email protected]> wrote:

> I prefer the second binding (with mV -> uV), but I think it becomes
> messy when temperature is added. What do you think about the
> following proposal (derived from pinctrl style):
>
> Proposal C:
>
> ocv-capacity-table-temperatures = <(-10) 0 10>;
> ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
> ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
> ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;

I think this looks very elegant. It's going to be very
easy and intuitive for people who need to maintain these
device trees and it will be easy to handle in centralized code
for all platforms. Even with the microvolt notation.

If possible could we go with this?

Yours,
Linus Walleij

2018-09-24 12:47:12

by Heiko Stuebner

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

Hi Craig,

Am Montag, 13. August 2018, 09:45:09 CEST schrieb Craig Tatlor:
> On 13 August 2018 07:55:34 BST, Taniya Das <[email protected]> wrote:
> >Hello Craig,
> >
> >Could you please correct the authorship and also provide the reference
> >to code where this is picked from?
> Okay,
> Got code from here https://github.com/sonyxperiadev/kernel/blob/aosp/LA.UM.6.4.r1/drivers/clk/qcom/gcc-sdm660.c
> but changed it quite a bit for upstream,
> Should I change the commit author and add your signed off by and say I did cleanups on my signed off by.

yep, for something this huge it is really the correct way to keep the
original authorship intact as Taniya did the initial big work, and just
add you change-description, so something like

---- 8< ------
Add support for the global clock controller found on SDM660
based devices. This should allow most non-multimedia device
drivers to probe and control their clocks.
Based on CAF implementation.

Signed-off-by: Taniya Das <[email protected]>
[ description of changes ... often seen in these brackets ]
Signed-off-by: Craig Tatlor <[email protected]>
---- 8< ------

Also, do you plan to continue working on this, as I would be interessted
in the clock driver for a sdm660-based phone as well.


Thanks
Heiko



2018-09-24 15:00:21

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH] clk: qcom: Add Global Clock controller (GCC) driver for SDM660



On 24 September 2018 13:44:33 BST, Heiko Stuebner <[email protected]> wrote:
>Hi Craig,
>
>Am Montag, 13. August 2018, 09:45:09 CEST schrieb Craig Tatlor:
>> On 13 August 2018 07:55:34 BST, Taniya Das <[email protected]>
>wrote:
>> >Hello Craig,
>> >
>> >Could you please correct the authorship and also provide the
>reference
>> >to code where this is picked from?
>> Okay,
>> Got code from here
>https://github.com/sonyxperiadev/kernel/blob/aosp/LA.UM.6.4.r1/drivers/clk/qcom/gcc-sdm660.c
>> but changed it quite a bit for upstream,
>> Should I change the commit author and add your signed off by and say
>I did cleanups on my signed off by.
>
>yep, for something this huge it is really the correct way to keep the
>original authorship intact as Taniya did the initial big work, and just
>add you change-description, so something like
>
>---- 8< ------
>Add support for the global clock controller found on SDM660
>based devices. This should allow most non-multimedia device
>drivers to probe and control their clocks.
>Based on CAF implementation.
>
>Signed-off-by: Taniya Das <[email protected]>
>[ description of changes ... often seen in these brackets ]
>Signed-off-by: Craig Tatlor <[email protected]>
>---- 8< ------
>
Sure, will do, though I'm sure qcom have a program to generate the drivers :)

>Also, do you plan to continue working on this, as I would be
>interessted
>in the clock driver for a sdm660-based phone as well
Yup, was really just waiting for reply to this question,
>
>
>Thanks
>Heiko

--

2018-09-25 16:36:47

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v2] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

From: Taniya Das <[email protected]>

Add support for the global clock controller found on SDM660
based devices. This should allow most non-multimedia device
drivers to probe and control their clocks.
Based on CAF implementation.

Signed-off-by: Taniya Das <[email protected]>
[craig: rename parents to fit upstream, and other cleanups]
Signed-off-by: Craig Tatlor <[email protected]>
---
.../devicetree/bindings/clock/qcom,gcc.txt | 1 +
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gcc-sdm660.c | 2479 +++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
5 files changed, 2649 insertions(+)
create mode 100644 drivers/clk/qcom/gcc-sdm660.c
create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 664ea1fd6c76..e498ad2e8db8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -19,6 +19,7 @@ Required properties :
"qcom,gcc-msm8996"
"qcom,gcc-msm8998"
"qcom,gcc-mdm9615"
+ "qcom,gcc-sdm660"
"qcom,gcc-sdm845"

- reg : shall contain base register location and length
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 5b181b182f40..4d478b261dfe 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -243,6 +243,15 @@ config SDM_CAMCC_845
Support for the camera clock controller on SDM845 devices.
Say Y if you want to support camera devices and camera functionality.

+config SDM_GCC_660
+ tristate "SDM660 Global Clock Controller"
+ select QCOM_GDSC
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on SDM660 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2C, USB, UFS, SDDC, PCIe, etc.
+
config SDM_GCC_845
tristate "SDM845 Global Clock Controller"
select QCOM_GDSC
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 935f142bc155..ab892f6d847c 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
+obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
new file mode 100644
index 000000000000..cec8b4145b71
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -0,0 +1,2479 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-sdm660.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+#include "gdsc.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+ P_XO,
+ P_SLEEP_CLK,
+ P_GPLL0,
+ P_GPLL1,
+ P_GPLL4,
+ P_GPLL0_EARLY_DIV,
+ P_GPLL1_EARLY_DIV,
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0[] = {
+ "xo",
+ "gpll0",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "sleep_clk",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const char * const gcc_parent_names_xo_sleep_clk[] = {
+ "xo",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll4[] = {
+ "xo",
+ "gpll4",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 3 },
+ { P_GPLL1, 4 },
+ { P_GPLL4, 5 },
+ { P_GPLL1_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll1",
+ "gpll4",
+ "gpll1_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll4",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 2 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll4",
+};
+
+static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "xo",
+ .parent_names = (const char *[]){ "xo_board" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll0_early = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll0_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early_div",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+ .offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll1_early = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll1_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early_div",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll1",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll4",
+ .parent_names = (const char *[]) { "gpll4_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x19020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(15000000, P_GPLL0, 10, 1, 4),
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1900c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1b020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1b00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1d020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1d00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1f020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1f00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
+ F(3686400, P_GPLL0, 1, 96, 15625),
+ F(7372800, P_GPLL0, 1, 192, 15625),
+ F(14745600, P_GPLL0, 1, 384, 15625),
+ F(16000000, P_GPLL0, 5, 2, 15),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_GPLL0, 1, 4, 75),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(46400000, P_GPLL0, 1, 29, 375),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(51200000, P_GPLL0, 1, 32, 375),
+ F(56000000, P_GPLL0, 1, 7, 75),
+ F(58982400, P_GPLL0, 1, 1536, 15625),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(63157895, P_GPLL0, 9.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x1a00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x1c00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x26020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2600c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x28020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2800c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2a020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2a00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2c020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2c00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x2700c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x2900c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gp1_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x64004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x65004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x66004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll0_clk_src = {
+ .cmd_rcgr = 0x4805c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_gpll0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll0_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
+ F(384000000, P_GPLL4, 4, 0, 0),
+ F(768000000, P_GPLL4, 2, 0, 0),
+ F(1536000000, P_GPLL4, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll4_clk_src = {
+ .cmd_rcgr = 0x48074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll4,
+ .freq_tbl = ftbl_hmss_gpll4_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll4_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll4,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_rbcpr_clk_src = {
+ .cmd_rcgr = 0x48044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_rbcpr_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x33010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
+ F(160400000, P_GPLL1, 5, 0, 0),
+ F(267333333, P_GPLL1, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 qspi_ser_clk_src = {
+ .cmd_rcgr = 0x4d00c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .freq_tbl = ftbl_qspi_ser_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(384000000, P_GPLL4, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x1602c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x16010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x14010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+ .cmd_rcgr = 0x75018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_ice_core_clk_src = {
+ .cmd_rcgr = 0x76010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 ufs_phy_aux_clk_src = {
+ .cmd_rcgr = 0x76044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
+ F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_unipro_core_clk_src = {
+ .cmd_rcgr = 0x76028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_unipro_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_master_clk_src = {
+ .cmd_rcgr = 0x2f010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x2f024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ F(133333333, P_GPLL0, 4.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0xf014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0xf028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+ F(1200000, P_XO, 16, 0, 0),
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .cmd_rcgr = 0x5000c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb3_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_aggre2_ufs_axi_clk = {
+ .halt_reg = 0x75034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre2_usb3_axi_clk = {
+ .halt_reg = 0xf03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_gfx_clk = {
+ .halt_reg = 0x7106c,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x7106c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_hmss_axi_clk = {
+ .halt_reg = 0x48004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_hmss_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_mss_q6_axi_clk = {
+ .halt_reg = 0x4401c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4401c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_mss_q6_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x19008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x19004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x1b008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x1b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x1d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x1d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x1f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x1f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x1a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x1c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x25004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x26008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x26004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x28008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x28004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x2a008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x2a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x2c008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x2c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x27004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x29004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x38004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb2_axi_clk = {
+ .halt_reg = 0x5058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb2_axi_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
+ .halt_reg = 0x5018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_dcc_ahb_clk = {
+ .halt_reg = 0x84004,
+ .clkr = {
+ .enable_reg = 0x84004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_dcc_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x64000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x64000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_names = (const char *[]){
+ "gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x65000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x65000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_names = (const char *[]){
+ "gp2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x66000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x66000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_names = (const char *[]){
+ "gp3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_bimc_gfx_clk = {
+ .halt_reg = 0x71010,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x71004,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_dvm_bus_clk = {
+ .halt_reg = 0x4808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_dvm_bus_clk",
+ .ops = &clk_branch2_ops,
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_rbcpr_clk = {
+ .halt_reg = 0x48008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x48008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_rbcpr_clk",
+ .parent_names = (const char *[]){
+ "hmss_rbcpr_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+ .halt_reg = 0x9004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_noc_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_sys_noc_axi_clk = {
+ .halt_reg = 0x9000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_sys_noc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .halt_reg = 0x8a000,
+ .clkr = {
+ .enable_reg = 0x8a000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
+ .halt_reg = 0x8a004,
+ .clkr = {
+ .enable_reg = 0x8a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_mnoc_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .halt_reg = 0x8a040,
+ .clkr = {
+ .enable_reg = 0x8a040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_snoc_axi_clk = {
+ .halt_reg = 0x8a03c,
+ .clkr = {
+ .enable_reg = 0x8a03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_snoc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_names = (const char *[]){
+ "pdm2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x33004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x33004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x34004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ahb_clk = {
+ .halt_reg = 0x4d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ser_clk = {
+ .halt_reg = 0x4d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ser_clk",
+ .parent_names = (const char *[]){
+ "qspi_ser_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx0_usb2_clkref_clk = {
+ .halt_reg = 0x88018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx0_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx1_usb2_clkref_clk = {
+ .halt_reg = 0x88014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx1_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x16008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x16004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x1600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x14008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x14004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ahb_clk = {
+ .halt_reg = 0x7500c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7500c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+ .halt_reg = 0x75008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_clkref_clk = {
+ .halt_reg = 0x88008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x88008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ice_core_clk = {
+ .halt_reg = 0x7600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ice_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_aux_clk = {
+ .halt_reg = 0x76040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "ufs_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+ .halt_reg = 0x75014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+ .halt_reg = 0x7605c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x7605c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+ .halt_reg = 0x75010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_unipro_core_clk = {
+ .halt_reg = 0x76008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_unipro_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_unipro_core_clk_src",
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_master_clk = {
+ .halt_reg = 0x2f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_master_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src"
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_mock_utmi_clk = {
+ .halt_reg = 0x2f00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb20_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_sleep_clk = {
+ .halt_reg = 0x2f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0xf008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_master_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0xf010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb30_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0xf00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_clkref_clk = {
+ .halt_reg = 0x8800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .halt_reg = 0x50000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x50000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "usb3_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .halt_reg = 0x50004,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x50004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_pipe_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .halt_reg = 0x6a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc ufs_gdsc = {
+ .gdscr = 0x75004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "ufs_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc usb_30_gdsc = {
+ .gdscr = 0xf004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "usb_30_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc pcie_0_gdsc = {
+ .gdscr = 0x6b004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct clk_hw *gcc_sdm660_hws[] = {
+ [GCC_XO] = &xo.hw,
+ [GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
+ [GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,
+};
+
+static struct clk_regmap *gcc_660_clocks[] = {
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
+ [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
+ [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+ [GCC_BIMC_HMSS_AXI_CLK] = &gcc_bimc_hmss_axi_clk.clkr,
+ [GCC_BIMC_MSS_Q6_AXI_CLK] = &gcc_bimc_mss_q6_axi_clk.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CFG_NOC_USB2_AXI_CLK] = &gcc_cfg_noc_usb2_axi_clk.clkr,
+ [GCC_CFG_NOC_USB3_AXI_CLK] = &gcc_cfg_noc_usb3_axi_clk.clkr,
+ [GCC_DCC_AHB_CLK] = &gcc_dcc_ahb_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GPU_BIMC_GFX_CLK] = &gcc_gpu_bimc_gfx_clk.clkr,
+ [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+ [GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
+ [GCC_HMSS_DVM_BUS_CLK] = &gcc_hmss_dvm_bus_clk.clkr,
+ [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
+ [GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
+ [GCC_MMSS_GPLL0_DIV_CLK] = &gcc_mmss_gpll0_div_clk.clkr,
+ [GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr,
+ [GCC_MMSS_SYS_NOC_AXI_CLK] = &gcc_mmss_sys_noc_axi_clk.clkr,
+ [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
+ [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
+ [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
+ [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
+ [GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr,
+ [GCC_RX0_USB2_CLKREF_CLK] = &gcc_rx0_usb2_clkref_clk.clkr,
+ [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+ [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+ [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
+ [GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr,
+ [GCC_UFS_PHY_AUX_CLK] = &gcc_ufs_phy_aux_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+ [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+ [GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr,
+ [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
+ [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
+ [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+ [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+ [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_EARLY] = &gpll0_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL1_EARLY] = &gpll1_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
+ [HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
+ [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+ [UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr,
+ [UFS_PHY_AUX_CLK_SRC] = &ufs_phy_aux_clk_src.clkr,
+ [UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
+ [USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr,
+ [USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+};
+
+static struct gdsc *gcc_660_gdscs[] = {
+ [UFS_GDSC] = &ufs_gdsc,
+ [USB_30_GDSC] = &usb_30_gdsc,
+ [PCIE_0_GDSC] = &pcie_0_gdsc,
+};
+
+static const struct qcom_reset_map gcc_660_resets[] = {
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+ [GCC_UFS_BCR] = { 0x75000 },
+ [GCC_USB3_DP_PHY_BCR] = { 0x50028 },
+ [GCC_USB3_PHY_BCR] = { 0x50020 },
+ [GCC_USB3PHY_PHY_BCR] = { 0x50024 },
+ [GCC_USB_20_BCR] = { 0x2f000 },
+ [GCC_USB_30_BCR] = { 0xf000 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+};
+
+static const struct regmap_config gcc_660_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x94000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_660_desc = {
+ .config = &gcc_660_regmap_config,
+ .clks = gcc_660_clocks,
+ .num_clks = ARRAY_SIZE(gcc_660_clocks),
+ .resets = gcc_660_resets,
+ .num_resets = ARRAY_SIZE(gcc_660_resets),
+ .gdscs = gcc_660_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_660_gdscs),
+};
+
+static const struct of_device_id gcc_660_match_table[] = {
+ { .compatible = "qcom,gcc-sdm660" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_660_match_table);
+
+static int gcc_660_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gcc_660_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /*
+ * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
+ * turned off by hardware during certain apps low power modes.
+ */
+ ret = regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
+ if (ret)
+ return ret;
+
+ /* Register the hws */
+ for (i = 0; i < ARRAY_SIZE(gcc_sdm660_hws); i++) {
+ ret = devm_clk_hw_register(&pdev->dev, gcc_sdm660_hws[i]);
+ if (ret)
+ return ret;
+ }
+
+ return qcom_cc_really_probe(pdev, &gcc_660_desc, regmap);
+}
+
+static struct platform_driver gcc_660_driver = {
+ .probe = gcc_660_probe,
+ .driver = {
+ .name = "gcc-sdm660",
+ .of_match_table = gcc_660_match_table,
+ },
+};
+
+static int __init gcc_660_init(void)
+{
+ return platform_driver_register(&gcc_660_driver);
+}
+core_initcall_sync(gcc_660_init);
+
+static void __exit gcc_660_exit(void)
+{
+ platform_driver_unregister(&gcc_660_driver);
+}
+module_exit(gcc_660_exit);
+
+MODULE_DESCRIPTION("QCOM GCC sdm660 Driver");
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
new file mode 100644
index 000000000000..76aabcc5e7e3
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_660_H
+#define _DT_BINDINGS_CLK_MSM_GCC_660_H
+
+#define GCC_XO 0
+#define GCC_GPLL0_EARLY_DIV 1
+#define GCC_GPLL1_EARLY_DIV 2
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
+#define BLSP1_UART1_APPS_CLK_SRC 11
+#define BLSP1_UART2_APPS_CLK_SRC 12
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
+#define BLSP2_UART1_APPS_CLK_SRC 21
+#define BLSP2_UART2_APPS_CLK_SRC 22
+#define GCC_AGGRE2_UFS_AXI_CLK 23
+#define GCC_AGGRE2_USB3_AXI_CLK 24
+#define GCC_BIMC_GFX_CLK 25
+#define GCC_BIMC_HMSS_AXI_CLK 26
+#define GCC_BIMC_MSS_Q6_AXI_CLK 27
+#define GCC_BLSP1_AHB_CLK 28
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 29
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 30
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 31
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 32
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 33
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 34
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 35
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 36
+#define GCC_BLSP1_UART1_APPS_CLK 37
+#define GCC_BLSP1_UART2_APPS_CLK 38
+#define GCC_BLSP2_AHB_CLK 39
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 40
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 41
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 42
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 43
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 44
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 46
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 45
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 46
+#define GCC_BLSP2_UART1_APPS_CLK 47
+#define GCC_BLSP2_UART2_APPS_CLK 48
+#define GCC_BOOT_ROM_AHB_CLK 49
+#define GCC_CFG_NOC_USB2_AXI_CLK 50
+#define GCC_CFG_NOC_USB3_AXI_CLK 51
+#define GCC_DCC_AHB_CLK 52
+#define GCC_GP1_CLK 53
+#define GCC_GP2_CLK 54
+#define GCC_GP3_CLK 55
+#define GCC_GPU_BIMC_GFX_CLK 56
+#define GCC_GPU_CFG_AHB_CLK 57
+#define GCC_GPU_GPLL0_CLK 58
+#define GCC_GPU_GPLL0_DIV_CLK 59
+#define GCC_HMSS_DVM_BUS_CLK 60
+#define GCC_HMSS_RBCPR_CLK 61
+#define GCC_MMSS_GPLL0_CLK 62
+#define GCC_MMSS_GPLL0_DIV_CLK 63
+#define GCC_MMSS_NOC_CFG_AHB_CLK 64
+#define GCC_MMSS_SYS_NOC_AXI_CLK 65
+#define GCC_MSS_CFG_AHB_CLK 66
+#define GCC_MSS_GPLL0_DIV_CLK 67
+#define GCC_MSS_MNOC_BIMC_AXI_CLK 68
+#define GCC_MSS_Q6_BIMC_AXI_CLK 69
+#define GCC_MSS_SNOC_AXI_CLK 70
+#define GCC_PDM2_CLK 71
+#define GCC_PDM_AHB_CLK 72
+#define GCC_PRNG_AHB_CLK 73
+#define GCC_QSPI_AHB_CLK 74
+#define GCC_QSPI_SER_CLK 75
+#define GCC_SDCC1_AHB_CLK 76
+#define GCC_SDCC1_APPS_CLK 77
+#define GCC_SDCC1_ICE_CORE_CLK 78
+#define GCC_SDCC2_AHB_CLK 79
+#define GCC_SDCC2_APPS_CLK 80
+#define GCC_UFS_AHB_CLK 81
+#define GCC_UFS_AXI_CLK 82
+#define GCC_UFS_CLKREF_CLK 83
+#define GCC_UFS_ICE_CORE_CLK 84
+#define GCC_UFS_PHY_AUX_CLK 85
+#define GCC_UFS_RX_SYMBOL_0_CLK 86
+#define GCC_UFS_RX_SYMBOL_1_CLK 87
+#define GCC_UFS_TX_SYMBOL_0_CLK 88
+#define GCC_UFS_UNIPRO_CORE_CLK 89
+#define GCC_USB20_MASTER_CLK 90
+#define GCC_USB20_MOCK_UTMI_CLK 91
+#define GCC_USB20_SLEEP_CLK 92
+#define GCC_USB30_MASTER_CLK 93
+#define GCC_USB30_MOCK_UTMI_CLK 94
+#define GCC_USB30_SLEEP_CLK 95
+#define GCC_USB3_CLKREF_CLK 96
+#define GCC_USB3_PHY_AUX_CLK 97
+#define GCC_USB3_PHY_PIPE_CLK 98
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 99
+#define GP1_CLK_SRC 100
+#define GP2_CLK_SRC 101
+#define GP3_CLK_SRC 102
+#define GPLL0 103
+#define GPLL0_EARLY 104
+#define GPLL1 105
+#define GPLL1_EARLY 106
+#define GPLL4 107
+#define GPLL4_EARLY 108
+#define HMSS_GPLL0_CLK_SRC 109
+#define HMSS_GPLL4_CLK_SRC 110
+#define HMSS_RBCPR_CLK_SRC 111
+#define PDM2_CLK_SRC 112
+#define QSPI_SER_CLK_SRC 113
+#define SDCC1_APPS_CLK_SRC 114
+#define SDCC1_ICE_CORE_CLK_SRC 115
+#define SDCC2_APPS_CLK_SRC 116
+#define UFS_AXI_CLK_SRC 117
+#define UFS_ICE_CORE_CLK_SRC 118
+#define UFS_PHY_AUX_CLK_SRC 119
+#define UFS_UNIPRO_CORE_CLK_SRC 120
+#define USB20_MASTER_CLK_SRC 121
+#define USB20_MOCK_UTMI_CLK_SRC 122
+#define USB30_MASTER_CLK_SRC 123
+#define USB30_MOCK_UTMI_CLK_SRC 124
+#define USB3_PHY_AUX_CLK_SRC 125
+#define GPLL0_OUT_MSSCC 126
+#define GCC_UFS_AXI_HW_CTL_CLK 127
+#define GCC_UFS_ICE_CORE_HW_CTL_CLK 128
+#define GCC_UFS_PHY_AUX_HW_CTL_CLK 129
+#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 130
+#define GCC_RX0_USB2_CLKREF_CLK 131
+#define GCC_RX1_USB2_CLKREF_CLK 132
+
+#define PCIE_0_GDSC 0
+#define UFS_GDSC 1
+#define USB_30_GDSC 2
+
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_UFS_BCR 2
+#define GCC_USB3_DP_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB3PHY_PHY_BCR 5
+#define GCC_USB_20_BCR 6
+#define GCC_USB_30_BCR 7
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
+
+#endif
--
2.18.0


2018-09-25 17:37:07

by Craig Tatlor

[permalink] [raw]
Subject: [PATCH v3] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

From: Taniya Das <[email protected]>

Add support for the global clock controller found on SDM660
based devices. This should allow most non-multimedia device
drivers to probe and control their clocks.
Based on CAF implementation.

Signed-off-by: Taniya Das <[email protected]>
[craig: rename parents to fit upstream, and other cleanups]
Signed-off-by: Craig Tatlor <[email protected]>
---
Changes from V1:
Change authorship
Add sdm630 compatible
.../devicetree/bindings/clock/qcom,gcc.txt | 1 +
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gcc-sdm660.c | 2480 +++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
5 files changed, 2650 insertions(+)
create mode 100644 drivers/clk/qcom/gcc-sdm660.c
create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 664ea1fd6c76..e498ad2e8db8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -38,6 +38,8 @@ Required properties :
"qcom,gcc-msm8996"
"qcom,gcc-msm8998"
"qcom,gcc-mdm9615"
+ "qcom,gcc-sdm630"
+ "qcom,gcc-sdm660"
"qcom,gcc-sdm845"

- reg : shall contain base register location and length
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 5b181b182f40..4d478b261dfe 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -243,6 +243,15 @@ config SDM_CAMCC_845
Support for the camera clock controller on SDM845 devices.
Say Y if you want to support camera devices and camera functionality.

+config SDM_GCC_660
+ tristate "SDM660 Global Clock Controller"
+ select QCOM_GDSC
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on SDM660 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2C, USB, UFS, SDDC, PCIe, etc.
+
config SDM_GCC_845
tristate "SDM845 Global Clock Controller"
select QCOM_GDSC
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 935f142bc155..ab892f6d847c 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
+obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
new file mode 100644
index 000000000000..641bba611b5f
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -0,0 +1,2480 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-sdm660.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+#include "gdsc.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+ P_XO,
+ P_SLEEP_CLK,
+ P_GPLL0,
+ P_GPLL1,
+ P_GPLL4,
+ P_GPLL0_EARLY_DIV,
+ P_GPLL1_EARLY_DIV,
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0[] = {
+ "xo",
+ "gpll0",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "sleep_clk",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
+ { P_XO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const char * const gcc_parent_names_xo_sleep_clk[] = {
+ "xo",
+ "sleep_clk",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll4[] = {
+ "xo",
+ "gpll4",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 3 },
+ { P_GPLL1, 4 },
+ { P_GPLL4, 5 },
+ { P_GPLL1_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll1",
+ "gpll4",
+ "gpll1_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 },
+ { P_GPLL0_EARLY_DIV, 6 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
+ "xo",
+ "gpll0",
+ "gpll4",
+ "gpll0_early_div",
+};
+
+static const struct parent_map gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_EARLY_DIV, 2 },
+ { P_GPLL4, 5 },
+};
+
+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
+ "xo",
+ "gpll0",
+ "gpll0_early_div",
+ "gpll4",
+};
+
+static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "xo",
+ .parent_names = (const char *[]){ "xo_board" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll0_early = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll0_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early_div",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+ .offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_names = (const char *[]){ "gpll0_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll1_early = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_fixed_factor gpll1_early_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_early_div",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll1 = {
+ .offset = 0x1000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll1",
+ .parent_names = (const char *[]){ "gpll1_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static struct clk_alpha_pll gpll4_early = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_early",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+ .offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data)
+ {
+ .name = "gpll4",
+ .parent_names = (const char *[]) { "gpll4_early" },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x19020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(15000000, P_GPLL0, 10, 1, 4),
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1900c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1b020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1b00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1d020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1d00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x1f020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x1f00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
+ F(3686400, P_GPLL0, 1, 96, 15625),
+ F(7372800, P_GPLL0, 1, 192, 15625),
+ F(14745600, P_GPLL0, 1, 384, 15625),
+ F(16000000, P_GPLL0, 5, 2, 15),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_GPLL0, 1, 4, 75),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(46400000, P_GPLL0, 1, 29, 375),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(51200000, P_GPLL0, 1, 32, 375),
+ F(56000000, P_GPLL0, 1, 7, 75),
+ F(58982400, P_GPLL0, 1, 1536, 15625),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(63157895, P_GPLL0, 9.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x1a00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x1c00c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x26020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2600c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x28020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2800c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2a020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2a00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x2c020,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x2c00c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x2700c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x2900c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gp1_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x64004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x65004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x66004,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll0_clk_src = {
+ .cmd_rcgr = 0x4805c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_gpll0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll0_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
+ F(384000000, P_GPLL4, 4, 0, 0),
+ F(768000000, P_GPLL4, 2, 0, 0),
+ F(1536000000, P_GPLL4, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_gpll4_clk_src = {
+ .cmd_rcgr = 0x48074,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll4,
+ .freq_tbl = ftbl_hmss_gpll4_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll4_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll4,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hmss_rbcpr_clk_src = {
+ .cmd_rcgr = 0x48044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_rbcpr_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x33010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
+ F(160400000, P_GPLL1, 5, 0, 0),
+ F(267333333, P_GPLL1, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 qspi_ser_clk_src = {
+ .cmd_rcgr = 0x4d00c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .freq_tbl = ftbl_qspi_ser_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(384000000, P_GPLL4, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x1602c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .cmd_rcgr = 0x16010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 8, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x14010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+ .cmd_rcgr = 0x75018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_ice_core_clk_src = {
+ .cmd_rcgr = 0x76010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 ufs_phy_aux_clk_src = {
+ .cmd_rcgr = 0x76044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
+ F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_unipro_core_clk_src = {
+ .cmd_rcgr = 0x76028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_ufs_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_unipro_core_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_master_clk_src = {
+ .cmd_rcgr = 0x2f010,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x2f024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+ F(133333333, P_GPLL0, 4.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0xf014,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0xf028,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+ F(1200000, P_XO, 16, 0, 0),
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .cmd_rcgr = 0x5000c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_xo_sleep_clk,
+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb3_phy_aux_clk_src",
+ .parent_names = gcc_parent_names_xo_sleep_clk,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_aggre2_ufs_axi_clk = {
+ .halt_reg = 0x75034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre2_usb3_axi_clk = {
+ .halt_reg = 0xf03c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_gfx_clk = {
+ .halt_reg = 0x7106c,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x7106c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_hmss_axi_clk = {
+ .halt_reg = 0x48004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_hmss_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_bimc_mss_q6_axi_clk = {
+ .halt_reg = 0x4401c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4401c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bimc_mss_q6_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x19008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x19004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x19004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x1b008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x1b004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1b004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x1d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x1d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x1f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x1f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x1a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x1c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x25004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x26008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x26004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x26004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x28008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x28004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x28004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x2a008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x2a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x2c008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x2c004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2c004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x27004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x27004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x29004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x29004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x38004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb2_axi_clk = {
+ .halt_reg = 0x5058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb2_axi_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
+ .halt_reg = 0x5018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_dcc_ahb_clk = {
+ .halt_reg = 0x84004,
+ .clkr = {
+ .enable_reg = 0x84004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_dcc_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x64000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x64000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_names = (const char *[]){
+ "gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x65000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x65000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_names = (const char *[]){
+ "gp2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x66000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x66000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_names = (const char *[]){
+ "gp3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_bimc_gfx_clk = {
+ .halt_reg = 0x71010,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_bimc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_cfg_ahb_clk = {
+ .halt_reg = 0x71004,
+ .halt_check = BRANCH_VOTED,
+ .clkr = {
+ .enable_reg = 0x71004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_dvm_bus_clk = {
+ .halt_reg = 0x4808c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4808c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_dvm_bus_clk",
+ .ops = &clk_branch2_ops,
+ .flags = CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch gcc_hmss_rbcpr_clk = {
+ .halt_reg = 0x48008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x48008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_rbcpr_clk",
+ .parent_names = (const char *[]){
+ "hmss_rbcpr_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_clk",
+ .parent_names = (const char *[]){
+ "gpll0",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_gpll0_div_clk = {
+ .halt_reg = 0x5200c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x5200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_div_clk",
+ .parent_names = (const char *[]){
+ "gpll0_early_div",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+ .halt_reg = 0x9004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_noc_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mmss_sys_noc_axi_clk = {
+ .halt_reg = 0x9000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_sys_noc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .halt_reg = 0x8a000,
+ .clkr = {
+ .enable_reg = 0x8a000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
+ .halt_reg = 0x8a004,
+ .clkr = {
+ .enable_reg = 0x8a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_mnoc_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .halt_reg = 0x8a040,
+ .clkr = {
+ .enable_reg = 0x8a040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_mss_snoc_axi_clk = {
+ .halt_reg = 0x8a03c,
+ .clkr = {
+ .enable_reg = 0x8a03c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_snoc_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_names = (const char *[]){
+ "pdm2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x33004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x33004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x34004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52004,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ahb_clk = {
+ .halt_reg = 0x4d004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qspi_ser_clk = {
+ .halt_reg = 0x4d008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4d008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ser_clk",
+ .parent_names = (const char *[]){
+ "qspi_ser_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx0_usb2_clkref_clk = {
+ .halt_reg = 0x88018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx0_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_rx1_usb2_clkref_clk = {
+ .halt_reg = 0x88014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x88014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_rx1_usb2_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x16008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x16004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .halt_reg = 0x1600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x14008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x14004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ahb_clk = {
+ .halt_reg = 0x7500c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7500c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+ .halt_reg = 0x75008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x75008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_clkref_clk = {
+ .halt_reg = 0x88008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x88008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ice_core_clk = {
+ .halt_reg = 0x7600c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x7600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ice_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_ice_core_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_aux_clk = {
+ .halt_reg = 0x76040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76040,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "ufs_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+ .halt_reg = 0x75014,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+ .halt_reg = 0x7605c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x7605c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+ .halt_reg = 0x75010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x75010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_unipro_core_clk = {
+ .halt_reg = 0x76008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x76008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_unipro_core_clk",
+ .parent_names = (const char *[]){
+ "ufs_unipro_core_clk_src",
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_master_clk = {
+ .halt_reg = 0x2f004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_master_clk",
+ .parent_names = (const char *[]){
+ "usb20_master_clk_src"
+ },
+ .flags = CLK_SET_RATE_PARENT,
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_mock_utmi_clk = {
+ .halt_reg = 0x2f00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb20_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb20_sleep_clk = {
+ .halt_reg = 0x2f008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2f008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0xf008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_master_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0xf010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb30_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0xf00c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0xf00c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_clkref_clk = {
+ .halt_reg = 0x8800c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x8800c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_clkref_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .halt_reg = 0x50000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x50000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_aux_clk",
+ .parent_names = (const char *[]){
+ "usb3_phy_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .halt_reg = 0x50004,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x50004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_pipe_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .halt_reg = 0x6a004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6a004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc ufs_gdsc = {
+ .gdscr = 0x75004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "ufs_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc usb_30_gdsc = {
+ .gdscr = 0xf004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "usb_30_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct gdsc pcie_0_gdsc = {
+ .gdscr = 0x6b004,
+ .gds_hw_ctrl = 0x0,
+ .pd = {
+ .name = "pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE,
+};
+
+static struct clk_hw *gcc_sdm660_hws[] = {
+ [GCC_XO] = &xo.hw,
+ [GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
+ [GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,
+};
+
+static struct clk_regmap *gcc_660_clocks[] = {
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
+ [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
+ [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+ [GCC_BIMC_HMSS_AXI_CLK] = &gcc_bimc_hmss_axi_clk.clkr,
+ [GCC_BIMC_MSS_Q6_AXI_CLK] = &gcc_bimc_mss_q6_axi_clk.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CFG_NOC_USB2_AXI_CLK] = &gcc_cfg_noc_usb2_axi_clk.clkr,
+ [GCC_CFG_NOC_USB3_AXI_CLK] = &gcc_cfg_noc_usb3_axi_clk.clkr,
+ [GCC_DCC_AHB_CLK] = &gcc_dcc_ahb_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_GPU_BIMC_GFX_CLK] = &gcc_gpu_bimc_gfx_clk.clkr,
+ [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+ [GCC_GPU_GPLL0_CLK] = &gcc_gpu_gpll0_clk.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK] = &gcc_gpu_gpll0_div_clk.clkr,
+ [GCC_HMSS_DVM_BUS_CLK] = &gcc_hmss_dvm_bus_clk.clkr,
+ [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr,
+ [GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr,
+ [GCC_MMSS_GPLL0_DIV_CLK] = &gcc_mmss_gpll0_div_clk.clkr,
+ [GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr,
+ [GCC_MMSS_SYS_NOC_AXI_CLK] = &gcc_mmss_sys_noc_axi_clk.clkr,
+ [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
+ [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr,
+ [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
+ [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
+ [GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr,
+ [GCC_RX0_USB2_CLKREF_CLK] = &gcc_rx0_usb2_clkref_clk.clkr,
+ [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+ [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+ [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr,
+ [GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr,
+ [GCC_UFS_PHY_AUX_CLK] = &gcc_ufs_phy_aux_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+ [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+ [GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr,
+ [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr,
+ [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr,
+ [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr,
+ [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+ [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+ [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_EARLY] = &gpll0_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL1_EARLY] = &gpll1_early.clkr,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+ [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
+ [HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
+ [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+ [UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr,
+ [UFS_PHY_AUX_CLK_SRC] = &ufs_phy_aux_clk_src.clkr,
+ [UFS_UNIPRO_CORE_CLK_SRC] = &ufs_unipro_core_clk_src.clkr,
+ [USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr,
+ [USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+};
+
+static struct gdsc *gcc_660_gdscs[] = {
+ [UFS_GDSC] = &ufs_gdsc,
+ [USB_30_GDSC] = &usb_30_gdsc,
+ [PCIE_0_GDSC] = &pcie_0_gdsc,
+};
+
+static const struct qcom_reset_map gcc_660_resets[] = {
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+ [GCC_UFS_BCR] = { 0x75000 },
+ [GCC_USB3_DP_PHY_BCR] = { 0x50028 },
+ [GCC_USB3_PHY_BCR] = { 0x50020 },
+ [GCC_USB3PHY_PHY_BCR] = { 0x50024 },
+ [GCC_USB_20_BCR] = { 0x2f000 },
+ [GCC_USB_30_BCR] = { 0xf000 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+};
+
+static const struct regmap_config gcc_660_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x94000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_660_desc = {
+ .config = &gcc_660_regmap_config,
+ .clks = gcc_660_clocks,
+ .num_clks = ARRAY_SIZE(gcc_660_clocks),
+ .resets = gcc_660_resets,
+ .num_resets = ARRAY_SIZE(gcc_660_resets),
+ .gdscs = gcc_660_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_660_gdscs),
+};
+
+static const struct of_device_id gcc_660_match_table[] = {
+ { .compatible = "qcom,gcc-sdm630" },
+ { .compatible = "qcom,gcc-sdm660" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_660_match_table);
+
+static int gcc_660_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &gcc_660_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /*
+ * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be
+ * turned off by hardware during certain apps low power modes.
+ */
+ ret = regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
+ if (ret)
+ return ret;
+
+ /* Register the hws */
+ for (i = 0; i < ARRAY_SIZE(gcc_sdm660_hws); i++) {
+ ret = devm_clk_hw_register(&pdev->dev, gcc_sdm660_hws[i]);
+ if (ret)
+ return ret;
+ }
+
+ return qcom_cc_really_probe(pdev, &gcc_660_desc, regmap);
+}
+
+static struct platform_driver gcc_660_driver = {
+ .probe = gcc_660_probe,
+ .driver = {
+ .name = "gcc-sdm660",
+ .of_match_table = gcc_660_match_table,
+ },
+};
+
+static int __init gcc_660_init(void)
+{
+ return platform_driver_register(&gcc_660_driver);
+}
+core_initcall_sync(gcc_660_init);
+
+static void __exit gcc_660_exit(void)
+{
+ platform_driver_unregister(&gcc_660_driver);
+}
+module_exit(gcc_660_exit);
+
+MODULE_DESCRIPTION("QCOM GCC sdm660 Driver");
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
new file mode 100644
index 000000000000..76aabcc5e7e3
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, Craig Tatlor.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_660_H
+#define _DT_BINDINGS_CLK_MSM_GCC_660_H
+
+#define GCC_XO 0
+#define GCC_GPLL0_EARLY_DIV 1
+#define GCC_GPLL1_EARLY_DIV 2
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
+#define BLSP1_UART1_APPS_CLK_SRC 11
+#define BLSP1_UART2_APPS_CLK_SRC 12
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
+#define BLSP2_UART1_APPS_CLK_SRC 21
+#define BLSP2_UART2_APPS_CLK_SRC 22
+#define GCC_AGGRE2_UFS_AXI_CLK 23
+#define GCC_AGGRE2_USB3_AXI_CLK 24
+#define GCC_BIMC_GFX_CLK 25
+#define GCC_BIMC_HMSS_AXI_CLK 26
+#define GCC_BIMC_MSS_Q6_AXI_CLK 27
+#define GCC_BLSP1_AHB_CLK 28
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 29
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 30
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 31
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 32
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 33
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 34
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 35
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 36
+#define GCC_BLSP1_UART1_APPS_CLK 37
+#define GCC_BLSP1_UART2_APPS_CLK 38
+#define GCC_BLSP2_AHB_CLK 39
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 40
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 41
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 42
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 43
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 44
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 46
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 45
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 46
+#define GCC_BLSP2_UART1_APPS_CLK 47
+#define GCC_BLSP2_UART2_APPS_CLK 48
+#define GCC_BOOT_ROM_AHB_CLK 49
+#define GCC_CFG_NOC_USB2_AXI_CLK 50
+#define GCC_CFG_NOC_USB3_AXI_CLK 51
+#define GCC_DCC_AHB_CLK 52
+#define GCC_GP1_CLK 53
+#define GCC_GP2_CLK 54
+#define GCC_GP3_CLK 55
+#define GCC_GPU_BIMC_GFX_CLK 56
+#define GCC_GPU_CFG_AHB_CLK 57
+#define GCC_GPU_GPLL0_CLK 58
+#define GCC_GPU_GPLL0_DIV_CLK 59
+#define GCC_HMSS_DVM_BUS_CLK 60
+#define GCC_HMSS_RBCPR_CLK 61
+#define GCC_MMSS_GPLL0_CLK 62
+#define GCC_MMSS_GPLL0_DIV_CLK 63
+#define GCC_MMSS_NOC_CFG_AHB_CLK 64
+#define GCC_MMSS_SYS_NOC_AXI_CLK 65
+#define GCC_MSS_CFG_AHB_CLK 66
+#define GCC_MSS_GPLL0_DIV_CLK 67
+#define GCC_MSS_MNOC_BIMC_AXI_CLK 68
+#define GCC_MSS_Q6_BIMC_AXI_CLK 69
+#define GCC_MSS_SNOC_AXI_CLK 70
+#define GCC_PDM2_CLK 71
+#define GCC_PDM_AHB_CLK 72
+#define GCC_PRNG_AHB_CLK 73
+#define GCC_QSPI_AHB_CLK 74
+#define GCC_QSPI_SER_CLK 75
+#define GCC_SDCC1_AHB_CLK 76
+#define GCC_SDCC1_APPS_CLK 77
+#define GCC_SDCC1_ICE_CORE_CLK 78
+#define GCC_SDCC2_AHB_CLK 79
+#define GCC_SDCC2_APPS_CLK 80
+#define GCC_UFS_AHB_CLK 81
+#define GCC_UFS_AXI_CLK 82
+#define GCC_UFS_CLKREF_CLK 83
+#define GCC_UFS_ICE_CORE_CLK 84
+#define GCC_UFS_PHY_AUX_CLK 85
+#define GCC_UFS_RX_SYMBOL_0_CLK 86
+#define GCC_UFS_RX_SYMBOL_1_CLK 87
+#define GCC_UFS_TX_SYMBOL_0_CLK 88
+#define GCC_UFS_UNIPRO_CORE_CLK 89
+#define GCC_USB20_MASTER_CLK 90
+#define GCC_USB20_MOCK_UTMI_CLK 91
+#define GCC_USB20_SLEEP_CLK 92
+#define GCC_USB30_MASTER_CLK 93
+#define GCC_USB30_MOCK_UTMI_CLK 94
+#define GCC_USB30_SLEEP_CLK 95
+#define GCC_USB3_CLKREF_CLK 96
+#define GCC_USB3_PHY_AUX_CLK 97
+#define GCC_USB3_PHY_PIPE_CLK 98
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 99
+#define GP1_CLK_SRC 100
+#define GP2_CLK_SRC 101
+#define GP3_CLK_SRC 102
+#define GPLL0 103
+#define GPLL0_EARLY 104
+#define GPLL1 105
+#define GPLL1_EARLY 106
+#define GPLL4 107
+#define GPLL4_EARLY 108
+#define HMSS_GPLL0_CLK_SRC 109
+#define HMSS_GPLL4_CLK_SRC 110
+#define HMSS_RBCPR_CLK_SRC 111
+#define PDM2_CLK_SRC 112
+#define QSPI_SER_CLK_SRC 113
+#define SDCC1_APPS_CLK_SRC 114
+#define SDCC1_ICE_CORE_CLK_SRC 115
+#define SDCC2_APPS_CLK_SRC 116
+#define UFS_AXI_CLK_SRC 117
+#define UFS_ICE_CORE_CLK_SRC 118
+#define UFS_PHY_AUX_CLK_SRC 119
+#define UFS_UNIPRO_CORE_CLK_SRC 120
+#define USB20_MASTER_CLK_SRC 121
+#define USB20_MOCK_UTMI_CLK_SRC 122
+#define USB30_MASTER_CLK_SRC 123
+#define USB30_MOCK_UTMI_CLK_SRC 124
+#define USB3_PHY_AUX_CLK_SRC 125
+#define GPLL0_OUT_MSSCC 126
+#define GCC_UFS_AXI_HW_CTL_CLK 127
+#define GCC_UFS_ICE_CORE_HW_CTL_CLK 128
+#define GCC_UFS_PHY_AUX_HW_CTL_CLK 129
+#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 130
+#define GCC_RX0_USB2_CLKREF_CLK 131
+#define GCC_RX1_USB2_CLKREF_CLK 132
+
+#define PCIE_0_GDSC 0
+#define UFS_GDSC 1
+#define USB_30_GDSC 2
+
+#define GCC_QUSB2PHY_PRIM_BCR 0
+#define GCC_QUSB2PHY_SEC_BCR 1
+#define GCC_UFS_BCR 2
+#define GCC_USB3_DP_PHY_BCR 3
+#define GCC_USB3_PHY_BCR 4
+#define GCC_USB3PHY_PHY_BCR 5
+#define GCC_USB_20_BCR 6
+#define GCC_USB_30_BCR 7
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
+
+#endif
--
2.18.0


2018-09-27 19:52:25

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

On Tue, Sep 25, 2018 at 06:35:58PM +0100, Craig Tatlor wrote:
> From: Taniya Das <[email protected]>
>
> Add support for the global clock controller found on SDM660
> based devices. This should allow most non-multimedia device
> drivers to probe and control their clocks.
> Based on CAF implementation.
>
> Signed-off-by: Taniya Das <[email protected]>
> [craig: rename parents to fit upstream, and other cleanups]
> Signed-off-by: Craig Tatlor <[email protected]>
> ---
> Changes from V1:
> Change authorship
> Add sdm630 compatible
> .../devicetree/bindings/clock/qcom,gcc.txt | 1 +

Acked-by: Rob Herring <[email protected]>

> drivers/clk/qcom/Kconfig | 9 +
> drivers/clk/qcom/Makefile | 1 +
> drivers/clk/qcom/gcc-sdm660.c | 2480 +++++++++++++++++
> include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
> 5 files changed, 2650 insertions(+)
> create mode 100644 drivers/clk/qcom/gcc-sdm660.c
> create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h

2018-10-08 06:52:14

by Craig Tatlor

[permalink] [raw]
Subject: Re: [PATCH v3] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

(Resend due to broken email client) any reviews for this?

On 25 September 2018 18:35:58 BST, Craig Tatlor <[email protected]> wrote:
>From: Taniya Das <[email protected]>
>
>Add support for the global clock controller found on SDM660
>based devices. This should allow most non-multimedia device
>drivers to probe and control their clocks.
>Based on CAF implementation.
>
>Signed-off-by: Taniya Das <[email protected]>
>[craig: rename parents to fit upstream, and other cleanups]
>Signed-off-by: Craig Tatlor <[email protected]>
>---
>Changes from V1:
> Change authorship
> Add sdm630 compatible
> .../devicetree/bindings/clock/qcom,gcc.txt | 1 +
> drivers/clk/qcom/Kconfig | 9 +
> drivers/clk/qcom/Makefile | 1 +
> drivers/clk/qcom/gcc-sdm660.c | 2480 +++++++++++++++++
> include/dt-bindings/clock/qcom,gcc-sdm660.h | 159 ++
> 5 files changed, 2650 insertions(+)
> create mode 100644 drivers/clk/qcom/gcc-sdm660.c
> create mode 100644 include/dt-bindings/clock/qcom,gcc-sdm660.h
>
>diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>index 664ea1fd6c76..e498ad2e8db8 100644
>--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
>@@ -38,6 +38,8 @@ Required properties :
> "qcom,gcc-msm8996"
> "qcom,gcc-msm8998"
> "qcom,gcc-mdm9615"
>+ "qcom,gcc-sdm630"
>+ "qcom,gcc-sdm660"
> "qcom,gcc-sdm845"
>
> - reg : shall contain base register location and length
>diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
>index 5b181b182f40..4d478b261dfe 100644
>--- a/drivers/clk/qcom/Kconfig
>+++ b/drivers/clk/qcom/Kconfig
>@@ -243,6 +243,15 @@ config SDM_CAMCC_845
> Support for the camera clock controller on SDM845 devices.
> Say Y if you want to support camera devices and camera
>functionality.
>
>+config SDM_GCC_660
>+ tristate "SDM660 Global Clock Controller"
>+ select QCOM_GDSC
>+ depends on COMMON_CLK_QCOM
>+ help
>+ Support for the global clock controller on SDM660 devices.
>+ Say Y if you want to use peripheral devices such as UART, SPI,
>+ i2C, USB, UFS, SDDC, PCIe, etc.
>+
> config SDM_GCC_845
> tristate "SDM845 Global Clock Controller"
> select QCOM_GDSC
>diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
>index 935f142bc155..ab892f6d847c 100644
>--- a/drivers/clk/qcom/Makefile
>+++ b/drivers/clk/qcom/Makefile
>@@ -41,6 +41,7 @@ obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
> obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
> obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
> obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
>+obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
> obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
> obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
> obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
>diff --git a/drivers/clk/qcom/gcc-sdm660.c
>b/drivers/clk/qcom/gcc-sdm660.c
>new file mode 100644
>index 000000000000..641bba611b5f
>--- /dev/null
>+++ b/drivers/clk/qcom/gcc-sdm660.c
>@@ -0,0 +1,2480 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
>+ * Copyright (c) 2018, Craig Tatlor.
>+ */
>+
>+#include <linux/kernel.h>
>+#include <linux/bitops.h>
>+#include <linux/err.h>
>+#include <linux/platform_device.h>
>+#include <linux/module.h>
>+#include <linux/of.h>
>+#include <linux/of_device.h>
>+#include <linux/clk-provider.h>
>+#include <linux/regmap.h>
>+#include <linux/reset-controller.h>
>+
>+#include <dt-bindings/clock/qcom,gcc-sdm660.h>
>+
>+#include "common.h"
>+#include "clk-regmap.h"
>+#include "clk-alpha-pll.h"
>+#include "clk-rcg.h"
>+#include "clk-branch.h"
>+#include "reset.h"
>+#include "gdsc.h"
>+
>+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
>+
>+enum {
>+ P_XO,
>+ P_SLEEP_CLK,
>+ P_GPLL0,
>+ P_GPLL1,
>+ P_GPLL4,
>+ P_GPLL0_EARLY_DIV,
>+ P_GPLL1_EARLY_DIV,
>+};
>+
>+static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div[] = {
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+ { P_GPLL0_EARLY_DIV, 6 },
>+};
>+
>+static const char * const gcc_parent_names_xo_gpll0_gpll0_early_div[]
>= {
>+ "xo",
>+ "gpll0",
>+ "gpll0_early_div",
>+};
>+
>+static const struct parent_map gcc_parent_map_xo_gpll0[] = {
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+};
>+
>+static const char * const gcc_parent_names_xo_gpll0[] = {
>+ "xo",
>+ "gpll0",
>+};
>+
>+static const struct parent_map
>gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+ { P_SLEEP_CLK, 5 },
>+ { P_GPLL0_EARLY_DIV, 6 },
>+};
>+
>+static const char * const
>gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div[] = {
>+ "xo",
>+ "gpll0",
>+ "sleep_clk",
>+ "gpll0_early_div",
>+};
>+
>+static const struct parent_map gcc_parent_map_xo_sleep_clk[] = {
>+ { P_XO, 0 },
>+ { P_SLEEP_CLK, 5 },
>+};
>+
>+static const char * const gcc_parent_names_xo_sleep_clk[] = {
>+ "xo",
>+ "sleep_clk",
>+};
>+
>+static const struct parent_map gcc_parent_map_xo_gpll4[] = {
>+ { P_XO, 0 },
>+ { P_GPLL4, 5 },
>+};
>+
>+static const char * const gcc_parent_names_xo_gpll4[] = {
>+ "xo",
>+ "gpll4",
>+};
>+
>+static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[] =
>{
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+ { P_GPLL0_EARLY_DIV, 3 },
>+ { P_GPLL1, 4 },
>+ { P_GPLL4, 5 },
>+ { P_GPLL1_EARLY_DIV, 6 },
>+};
>+
>+static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div[]
>= {
>+ "xo",
>+ "gpll0",
>+ "gpll0_early_div",
>+ "gpll1",
>+ "gpll4",
>+ "gpll1_early_div",
>+};
>+
>+static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div[] = {
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+ { P_GPLL4, 5 },
>+ { P_GPLL0_EARLY_DIV, 6 },
>+};
>+
>+static const char * const
>gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div[] = {
>+ "xo",
>+ "gpll0",
>+ "gpll4",
>+ "gpll0_early_div",
>+};
>+
>+static const struct parent_map
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4[] = {
>+ { P_XO, 0 },
>+ { P_GPLL0, 1 },
>+ { P_GPLL0_EARLY_DIV, 2 },
>+ { P_GPLL4, 5 },
>+};
>+
>+static const char * const
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4[] = {
>+ "xo",
>+ "gpll0",
>+ "gpll0_early_div",
>+ "gpll4",
>+};
>+
>+static struct clk_fixed_factor xo = {
>+ .mult = 1,
>+ .div = 1,
>+ .hw.init = &(struct clk_init_data){
>+ .name = "xo",
>+ .parent_names = (const char *[]){ "xo_board" },
>+ .num_parents = 1,
>+ .ops = &clk_fixed_factor_ops,
>+ },
>+};
>+
>+static struct clk_alpha_pll gpll0_early = {
>+ .offset = 0x0,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr = {
>+ .enable_reg = 0x52000,
>+ .enable_mask = BIT(0),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gpll0_early",
>+ .parent_names = (const char *[]){ "xo" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_fixed_factor gpll0_early_div = {
>+ .mult = 1,
>+ .div = 2,
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gpll0_early_div",
>+ .parent_names = (const char *[]){ "gpll0_early" },
>+ .num_parents = 1,
>+ .ops = &clk_fixed_factor_ops,
>+ },
>+};
>+
>+static struct clk_alpha_pll_postdiv gpll0 = {
>+ .offset = 0x00000,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "gpll0",
>+ .parent_names = (const char *[]){ "gpll0_early" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_postdiv_ops,
>+ },
>+};
>+
>+static struct clk_alpha_pll gpll1_early = {
>+ .offset = 0x1000,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr = {
>+ .enable_reg = 0x52000,
>+ .enable_mask = BIT(1),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gpll1_early",
>+ .parent_names = (const char *[]){ "xo" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_fixed_factor gpll1_early_div = {
>+ .mult = 1,
>+ .div = 2,
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gpll1_early_div",
>+ .parent_names = (const char *[]){ "gpll1_early" },
>+ .num_parents = 1,
>+ .ops = &clk_fixed_factor_ops,
>+ },
>+};
>+
>+static struct clk_alpha_pll_postdiv gpll1 = {
>+ .offset = 0x1000,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "gpll1",
>+ .parent_names = (const char *[]){ "gpll1_early" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_postdiv_ops,
>+ },
>+};
>+
>+static struct clk_alpha_pll gpll4_early = {
>+ .offset = 0x77000,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr = {
>+ .enable_reg = 0x52000,
>+ .enable_mask = BIT(4),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gpll4_early",
>+ .parent_names = (const char *[]){ "xo" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_alpha_pll_postdiv gpll4 = {
>+ .offset = 0x77000,
>+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
>+ .clkr.hw.init = &(struct clk_init_data)
>+ {
>+ .name = "gpll4",
>+ .parent_names = (const char *[]) { "gpll4_early" },
>+ .num_parents = 1,
>+ .ops = &clk_alpha_pll_postdiv_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(50000000, P_GPLL0, 12, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x19020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup1_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
>+ F(960000, P_XO, 10, 1, 2),
>+ F(4800000, P_XO, 4, 0, 0),
>+ F(9600000, P_XO, 2, 0, 0),
>+ F(15000000, P_GPLL0, 10, 1, 4),
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(25000000, P_GPLL0, 12, 1, 2),
>+ F(50000000, P_GPLL0, 12, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x1900c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup1_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x1b020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup2_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x1b00c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup2_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x1d020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup3_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x1d00c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup3_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x1f020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup4_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x1f00c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_qup4_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = {
>+ F(3686400, P_GPLL0, 1, 96, 15625),
>+ F(7372800, P_GPLL0, 1, 192, 15625),
>+ F(14745600, P_GPLL0, 1, 384, 15625),
>+ F(16000000, P_GPLL0, 5, 2, 15),
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(24000000, P_GPLL0, 5, 1, 5),
>+ F(32000000, P_GPLL0, 1, 4, 75),
>+ F(40000000, P_GPLL0, 15, 0, 0),
>+ F(46400000, P_GPLL0, 1, 29, 375),
>+ F(48000000, P_GPLL0, 12.5, 0, 0),
>+ F(51200000, P_GPLL0, 1, 32, 375),
>+ F(56000000, P_GPLL0, 1, 7, 75),
>+ F(58982400, P_GPLL0, 1, 1536, 15625),
>+ F(60000000, P_GPLL0, 10, 0, 0),
>+ F(63157895, P_GPLL0, 9.5, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
>+ .cmd_rcgr = 0x1a00c,
>+ .mnd_width = 16,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_uart1_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
>+ .cmd_rcgr = 0x1c00c,
>+ .mnd_width = 16,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp1_uart2_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x26020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup1_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x2600c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup1_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x28020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup2_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x2800c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup2_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x2a020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup3_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x2a00c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup3_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
>+ .cmd_rcgr = 0x2c020,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup4_i2c_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
>+ .cmd_rcgr = 0x2c00c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_qup4_spi_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
>+ .cmd_rcgr = 0x2700c,
>+ .mnd_width = 16,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_uart1_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
>+ .cmd_rcgr = 0x2900c,
>+ .mnd_width = 16,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "blsp2_uart2_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_gp1_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(100000000, P_GPLL0, 6, 0, 0),
>+ F(200000000, P_GPLL0, 3, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 gp1_clk_src = {
>+ .cmd_rcgr = 0x64004,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .freq_tbl = ftbl_gp1_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "gp1_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .num_parents = 4,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 gp2_clk_src = {
>+ .cmd_rcgr = 0x65004,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .freq_tbl = ftbl_gp1_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "gp2_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .num_parents = 4,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 gp3_clk_src = {
>+ .cmd_rcgr = 0x66004,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .freq_tbl = ftbl_gp1_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "gp3_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_sleep_clk_gpll0_early_div,
>+ .num_parents = 4,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_hmss_gpll0_clk_src[] = {
>+ F(300000000, P_GPLL0, 2, 0, 0),
>+ F(600000000, P_GPLL0, 1, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 hmss_gpll0_clk_src = {
>+ .cmd_rcgr = 0x4805c,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_hmss_gpll0_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "hmss_gpll0_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_hmss_gpll4_clk_src[] = {
>+ F(384000000, P_GPLL4, 4, 0, 0),
>+ F(768000000, P_GPLL4, 2, 0, 0),
>+ F(1536000000, P_GPLL4, 1, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 hmss_gpll4_clk_src = {
>+ .cmd_rcgr = 0x48074,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll4,
>+ .freq_tbl = ftbl_hmss_gpll4_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "hmss_gpll4_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll4,
>+ .num_parents = 2,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_hmss_rbcpr_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 hmss_rbcpr_clk_src = {
>+ .cmd_rcgr = 0x48044,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "hmss_rbcpr_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0,
>+ .num_parents = 2,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_pdm2_clk_src[] = {
>+ F(60000000, P_GPLL0, 10, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 pdm2_clk_src = {
>+ .cmd_rcgr = 0x33010,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_pdm2_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "pdm2_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(80200000, P_GPLL1_EARLY_DIV, 5, 0, 0),
>+ F(160400000, P_GPLL1, 5, 0, 0),
>+ F(267333333, P_GPLL1, 3, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 qspi_ser_clk_src = {
>+ .cmd_rcgr = 0x4d00c,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map =
>gcc_parent_map_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>+ .freq_tbl = ftbl_qspi_ser_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "qspi_ser_clk_src",
>+ .parent_names =
>gcc_parent_names_xo_gpll0_gpll0_early_div_gpll1_gpll4_gpll1_early_div,
>+ .num_parents = 6,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
>+ F(144000, P_XO, 16, 3, 25),
>+ F(400000, P_XO, 12, 1, 4),
>+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>+ F(100000000, P_GPLL0, 6, 0, 0),
>+ F(192000000, P_GPLL4, 8, 0, 0),
>+ F(384000000, P_GPLL4, 4, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 sdcc1_apps_clk_src = {
>+ .cmd_rcgr = 0x1602c,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll4_gpll0_early_div,
>+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "sdcc1_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll4_gpll0_early_div,
>+ .num_parents = 4,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
>+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>+ F(150000000, P_GPLL0, 4, 0, 0),
>+ F(200000000, P_GPLL0, 3, 0, 0),
>+ F(300000000, P_GPLL0, 2, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 sdcc1_ice_core_clk_src = {
>+ .cmd_rcgr = 0x16010,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "sdcc1_ice_core_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = {
>+ F(144000, P_XO, 16, 3, 25),
>+ F(400000, P_XO, 12, 1, 4),
>+ F(20000000, P_GPLL0_EARLY_DIV, 5, 1, 3),
>+ F(25000000, P_GPLL0_EARLY_DIV, 6, 1, 2),
>+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>+ F(100000000, P_GPLL0, 6, 0, 0),
>+ F(192000000, P_GPLL4, 8, 0, 0),
>+ F(200000000, P_GPLL0, 3, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 sdcc2_apps_clk_src = {
>+ .cmd_rcgr = 0x14010,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div_gpll4,
>+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "sdcc2_apps_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
>+ .num_parents = 4,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_ufs_axi_clk_src[] = {
>+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
>+ F(100000000, P_GPLL0, 6, 0, 0),
>+ F(150000000, P_GPLL0, 4, 0, 0),
>+ F(200000000, P_GPLL0, 3, 0, 0),
>+ F(240000000, P_GPLL0, 2.5, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 ufs_axi_clk_src = {
>+ .cmd_rcgr = 0x75018,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_ufs_axi_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "ufs_axi_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
>+ F(75000000, P_GPLL0_EARLY_DIV, 4, 0, 0),
>+ F(150000000, P_GPLL0, 4, 0, 0),
>+ F(300000000, P_GPLL0, 2, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 ufs_ice_core_clk_src = {
>+ .cmd_rcgr = 0x76010,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "ufs_ice_core_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_rcg2 ufs_phy_aux_clk_src = {
>+ .cmd_rcgr = 0x76044,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_sleep_clk,
>+ .freq_tbl = ftbl_hmss_rbcpr_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "ufs_phy_aux_clk_src",
>+ .parent_names = gcc_parent_names_xo_sleep_clk,
>+ .num_parents = 2,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_ufs_unipro_core_clk_src[] = {
>+ F(37500000, P_GPLL0_EARLY_DIV, 8, 0, 0),
>+ F(75000000, P_GPLL0, 8, 0, 0),
>+ F(150000000, P_GPLL0, 4, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 ufs_unipro_core_clk_src = {
>+ .cmd_rcgr = 0x76028,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_ufs_unipro_core_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "ufs_unipro_core_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_usb20_master_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(60000000, P_GPLL0, 10, 0, 0),
>+ F(120000000, P_GPLL0, 5, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 usb20_master_clk_src = {
>+ .cmd_rcgr = 0x2f010,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_usb20_master_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "usb20_master_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_usb20_mock_utmi_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(60000000, P_GPLL0, 10, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 usb20_mock_utmi_clk_src = {
>+ .cmd_rcgr = 0x2f024,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_usb20_mock_utmi_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "usb20_mock_utmi_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(66666667, P_GPLL0_EARLY_DIV, 4.5, 0, 0),
>+ F(120000000, P_GPLL0, 5, 0, 0),
>+ F(133333333, P_GPLL0, 4.5, 0, 0),
>+ F(150000000, P_GPLL0, 4, 0, 0),
>+ F(200000000, P_GPLL0, 3, 0, 0),
>+ F(240000000, P_GPLL0, 2.5, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 usb30_master_clk_src = {
>+ .cmd_rcgr = 0xf014,
>+ .mnd_width = 8,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_usb30_master_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "usb30_master_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
>+ F(19200000, P_XO, 1, 0, 0),
>+ F(40000000, P_GPLL0_EARLY_DIV, 7.5, 0, 0),
>+ F(60000000, P_GPLL0, 10, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
>+ .cmd_rcgr = 0xf028,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
>+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "usb30_mock_utmi_clk_src",
>+ .parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div,
>+ .num_parents = 3,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
>+ F(1200000, P_XO, 16, 0, 0),
>+ F(19200000, P_XO, 1, 0, 0),
>+ { }
>+};
>+
>+static struct clk_rcg2 usb3_phy_aux_clk_src = {
>+ .cmd_rcgr = 0x5000c,
>+ .mnd_width = 0,
>+ .hid_width = 5,
>+ .parent_map = gcc_parent_map_xo_sleep_clk,
>+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
>+ .clkr.hw.init = &(struct clk_init_data){
>+ .name = "usb3_phy_aux_clk_src",
>+ .parent_names = gcc_parent_names_xo_sleep_clk,
>+ .num_parents = 2,
>+ .ops = &clk_rcg2_ops,
>+ },
>+};
>+
>+static struct clk_branch gcc_aggre2_ufs_axi_clk = {
>+ .halt_reg = 0x75034,
>+ .halt_check = BRANCH_HALT,
>+ .clkr = {
>+ .enable_reg = 0x75034,
>+ .enable_mask = BIT(0),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_aggre2_ufs_axi_clk",
>+ .parent_names = (const char *[]){
>+ "ufs_axi_clk_src",
>+ },
>+ .num_parents = 1,
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_aggre2_usb3_axi_clk = {
>+ .halt_reg = 0xf03c,
>+ .halt_check = BRANCH_HALT,
>+ .clkr = {
>+ .enable_reg = 0xf03c,
>+ .enable_mask = BIT(0),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_aggre2_usb3_axi_clk",
>+ .parent_names = (const char *[]){
>+ "usb30_master_clk_src",
>+ },
>+ .num_parents = 1,
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_bimc_gfx_clk = {
>+ .halt_reg = 0x7106c,
>+ .halt_check = BRANCH_VOTED,
>+ .clkr = {
>+ .enable_reg = 0x7106c,
>+ .enable_mask = BIT(0),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_bimc_gfx_clk",
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_bimc_hmss_axi_clk = {
>+ .halt_reg = 0x48004,
>+ .halt_check = BRANCH_HALT_VOTED,
>+ .clkr = {
>+ .enable_reg = 0x52004,
>+ .enable_mask = BIT(22),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_bimc_hmss_axi_clk",
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_bimc_mss_q6_axi_clk = {
>+ .halt_reg = 0x4401c,
>+ .halt_check = BRANCH_HALT,
>+ .clkr = {
>+ .enable_reg = 0x4401c,
>+ .enable_mask = BIT(0),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_bimc_mss_q6_axi_clk",
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_blsp1_ahb_clk = {
>+ .halt_reg = 0x17004,
>+ .halt_check = BRANCH_HALT_VOTED,
>+ .clkr = {
>+ .enable_reg = 0x52004,
>+ .enable_mask = BIT(17),
>+ .hw.init = &(struct clk_init_data){
>+ .name = "gcc_blsp1_ahb_clk",
>+ .ops = &clk_branch2_ops,
>+ },
>+ },
>+};
>+
>+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk

2018-10-16 22:06:46

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v3] clk: qcom: Add Global Clock controller (GCC) driver for SDM660

Quoting Craig Tatlor (2018-09-25 10:35:58)
> From: Taniya Das <[email protected]>
>
> Add support for the global clock controller found on SDM660
> based devices. This should allow most non-multimedia device
> drivers to probe and control their clocks.
> Based on CAF implementation.
>
> Signed-off-by: Taniya Das <[email protected]>
> [craig: rename parents to fit upstream, and other cleanups]
> Signed-off-by: Craig Tatlor <[email protected]>
> ---

Applied to clk-next

But there was some noise:

drivers/clk/qcom/gcc-sdm660.c:2304:10: warning: Initializer entry defined twice
drivers/clk/qcom/gcc-sdm660.c:2306:10: also defined here

and I didn't like seeing gcc_660, so I applied this fixup on top:

diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c
index 1722a9b181e2..9efb55092ebf 100644
--- a/drivers/clk/qcom/gcc-sdm660.c
+++ b/drivers/clk/qcom/gcc-sdm660.c
@@ -2253,12 +2253,12 @@ static struct gdsc pcie_0_gdsc = {
};

static struct clk_hw *gcc_sdm660_hws[] = {
- [GCC_XO] = &xo.hw,
- [GCC_GPLL0_EARLY_DIV] = &gpll0_early_div.hw,
- [GCC_GPLL1_EARLY_DIV] = &gpll1_early_div.hw,
+ &xo.hw,
+ &gpll0_early_div.hw,
+ &gpll1_early_div.hw,
};

-static struct clk_regmap *gcc_660_clocks[] = {
+static struct clk_regmap *gcc_sdm660_clocks[] = {
[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
@@ -2365,9 +2365,8 @@ static struct clk_regmap *gcc_660_clocks[] = {
[GPLL0_EARLY] = &gpll0_early.clkr,
[GPLL1] = &gpll1.clkr,
[GPLL1_EARLY] = &gpll1_early.clkr,
- [GPLL1] = &gpll1.clkr,
- [GPLL4_EARLY] = &gpll4_early.clkr,
[GPLL4] = &gpll4.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
[HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr,
[HMSS_GPLL4_CLK_SRC] = &hmss_gpll4_clk_src.clkr,
[HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr,
@@ -2387,13 +2386,13 @@ static struct clk_regmap *gcc_660_clocks[] = {
[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
};

-static struct gdsc *gcc_660_gdscs[] = {
+static struct gdsc *gcc_sdm660_gdscs[] = {
[UFS_GDSC] = &ufs_gdsc,
[USB_30_GDSC] = &usb_30_gdsc,
[PCIE_0_GDSC] = &pcie_0_gdsc,
};

-static const struct qcom_reset_map gcc_660_resets[] = {
+static const struct qcom_reset_map gcc_sdm660_resets[] = {
[GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
[GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
[GCC_UFS_BCR] = { 0x75000 },
@@ -2405,7 +2404,7 @@ static const struct qcom_reset_map gcc_660_resets[] = {
[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
};

-static const struct regmap_config gcc_660_regmap_config = {
+static const struct regmap_config gcc_sdm660_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@@ -2413,29 +2412,29 @@ static const struct regmap_config gcc_660_regmap_config = {
.fast_io = true,
};

-static const struct qcom_cc_desc gcc_660_desc = {
- .config = &gcc_660_regmap_config,
- .clks = gcc_660_clocks,
- .num_clks = ARRAY_SIZE(gcc_660_clocks),
- .resets = gcc_660_resets,
- .num_resets = ARRAY_SIZE(gcc_660_resets),
- .gdscs = gcc_660_gdscs,
- .num_gdscs = ARRAY_SIZE(gcc_660_gdscs),
+static const struct qcom_cc_desc gcc_sdm660_desc = {
+ .config = &gcc_sdm660_regmap_config,
+ .clks = gcc_sdm660_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sdm660_clocks),
+ .resets = gcc_sdm660_resets,
+ .num_resets = ARRAY_SIZE(gcc_sdm660_resets),
+ .gdscs = gcc_sdm660_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sdm660_gdscs),
};

-static const struct of_device_id gcc_660_match_table[] = {
+static const struct of_device_id gcc_sdm660_match_table[] = {
{ .compatible = "qcom,gcc-sdm630" },
{ .compatible = "qcom,gcc-sdm660" },
{ }
};
-MODULE_DEVICE_TABLE(of, gcc_660_match_table);
+MODULE_DEVICE_TABLE(of, gcc_sdm660_match_table);

-static int gcc_660_probe(struct platform_device *pdev)
+static int gcc_sdm660_probe(struct platform_device *pdev)
{
int i, ret = 0;
struct regmap *regmap;

- regmap = qcom_cc_map(pdev, &gcc_660_desc);
+ regmap = qcom_cc_map(pdev, &gcc_sdm660_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);

@@ -2454,27 +2453,27 @@ static int gcc_660_probe(struct platform_device *pdev)
return ret;
}

- return qcom_cc_really_probe(pdev, &gcc_660_desc, regmap);
+ return qcom_cc_really_probe(pdev, &gcc_sdm660_desc, regmap);
}

-static struct platform_driver gcc_660_driver = {
- .probe = gcc_660_probe,
+static struct platform_driver gcc_sdm660_driver = {
+ .probe = gcc_sdm660_probe,
.driver = {
.name = "gcc-sdm660",
- .of_match_table = gcc_660_match_table,
+ .of_match_table = gcc_sdm660_match_table,
},
};

-static int __init gcc_660_init(void)
+static int __init gcc_sdm660_init(void)
{
- return platform_driver_register(&gcc_660_driver);
+ return platform_driver_register(&gcc_sdm660_driver);
}
-core_initcall_sync(gcc_660_init);
+core_initcall_sync(gcc_sdm660_init);

-static void __exit gcc_660_exit(void)
+static void __exit gcc_sdm660_exit(void)
{
- platform_driver_unregister(&gcc_660_driver);
+ platform_driver_unregister(&gcc_sdm660_driver);
}
-module_exit(gcc_660_exit);
+module_exit(gcc_sdm660_exit);

MODULE_DESCRIPTION("QCOM GCC sdm660 Driver");
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h
index 76aabcc5e7e3..468302282913 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm660.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h
@@ -7,140 +7,137 @@
#ifndef _DT_BINDINGS_CLK_MSM_GCC_660_H
#define _DT_BINDINGS_CLK_MSM_GCC_660_H

-#define GCC_XO 0
-#define GCC_GPLL0_EARLY_DIV 1
-#define GCC_GPLL1_EARLY_DIV 2
-#define BLSP1_QUP1_I2C_APPS_CLK_SRC 3
-#define BLSP1_QUP1_SPI_APPS_CLK_SRC 4
-#define BLSP1_QUP2_I2C_APPS_CLK_SRC 5
-#define BLSP1_QUP2_SPI_APPS_CLK_SRC 6
-#define BLSP1_QUP3_I2C_APPS_CLK_SRC 7
-#define BLSP1_QUP3_SPI_APPS_CLK_SRC 8
-#define BLSP1_QUP4_I2C_APPS_CLK_SRC 9
-#define BLSP1_QUP4_SPI_APPS_CLK_SRC 10
-#define BLSP1_UART1_APPS_CLK_SRC 11
-#define BLSP1_UART2_APPS_CLK_SRC 12
-#define BLSP2_QUP1_I2C_APPS_CLK_SRC 13
-#define BLSP2_QUP1_SPI_APPS_CLK_SRC 14
-#define BLSP2_QUP2_I2C_APPS_CLK_SRC 15
-#define BLSP2_QUP2_SPI_APPS_CLK_SRC 16
-#define BLSP2_QUP3_I2C_APPS_CLK_SRC 17
-#define BLSP2_QUP3_SPI_APPS_CLK_SRC 18
-#define BLSP2_QUP4_I2C_APPS_CLK_SRC 19
-#define BLSP2_QUP4_SPI_APPS_CLK_SRC 20
-#define BLSP2_UART1_APPS_CLK_SRC 21
-#define BLSP2_UART2_APPS_CLK_SRC 22
-#define GCC_AGGRE2_UFS_AXI_CLK 23
-#define GCC_AGGRE2_USB3_AXI_CLK 24
-#define GCC_BIMC_GFX_CLK 25
-#define GCC_BIMC_HMSS_AXI_CLK 26
-#define GCC_BIMC_MSS_Q6_AXI_CLK 27
-#define GCC_BLSP1_AHB_CLK 28
-#define GCC_BLSP1_QUP1_I2C_APPS_CLK 29
-#define GCC_BLSP1_QUP1_SPI_APPS_CLK 30
-#define GCC_BLSP1_QUP2_I2C_APPS_CLK 31
-#define GCC_BLSP1_QUP2_SPI_APPS_CLK 32
-#define GCC_BLSP1_QUP3_I2C_APPS_CLK 33
-#define GCC_BLSP1_QUP3_SPI_APPS_CLK 34
-#define GCC_BLSP1_QUP4_I2C_APPS_CLK 35
-#define GCC_BLSP1_QUP4_SPI_APPS_CLK 36
-#define GCC_BLSP1_UART1_APPS_CLK 37
-#define GCC_BLSP1_UART2_APPS_CLK 38
-#define GCC_BLSP2_AHB_CLK 39
-#define GCC_BLSP2_QUP1_I2C_APPS_CLK 40
-#define GCC_BLSP2_QUP1_SPI_APPS_CLK 41
-#define GCC_BLSP2_QUP2_I2C_APPS_CLK 42
-#define GCC_BLSP2_QUP2_SPI_APPS_CLK 43
-#define GCC_BLSP2_QUP3_I2C_APPS_CLK 44
-#define GCC_BLSP2_QUP3_SPI_APPS_CLK 46
-#define GCC_BLSP2_QUP4_I2C_APPS_CLK 45
-#define GCC_BLSP2_QUP4_SPI_APPS_CLK 46
-#define GCC_BLSP2_UART1_APPS_CLK 47
-#define GCC_BLSP2_UART2_APPS_CLK 48
-#define GCC_BOOT_ROM_AHB_CLK 49
-#define GCC_CFG_NOC_USB2_AXI_CLK 50
-#define GCC_CFG_NOC_USB3_AXI_CLK 51
-#define GCC_DCC_AHB_CLK 52
-#define GCC_GP1_CLK 53
-#define GCC_GP2_CLK 54
-#define GCC_GP3_CLK 55
-#define GCC_GPU_BIMC_GFX_CLK 56
-#define GCC_GPU_CFG_AHB_CLK 57
-#define GCC_GPU_GPLL0_CLK 58
-#define GCC_GPU_GPLL0_DIV_CLK 59
-#define GCC_HMSS_DVM_BUS_CLK 60
-#define GCC_HMSS_RBCPR_CLK 61
-#define GCC_MMSS_GPLL0_CLK 62
-#define GCC_MMSS_GPLL0_DIV_CLK 63
-#define GCC_MMSS_NOC_CFG_AHB_CLK 64
-#define GCC_MMSS_SYS_NOC_AXI_CLK 65
-#define GCC_MSS_CFG_AHB_CLK 66
-#define GCC_MSS_GPLL0_DIV_CLK 67
-#define GCC_MSS_MNOC_BIMC_AXI_CLK 68
-#define GCC_MSS_Q6_BIMC_AXI_CLK 69
-#define GCC_MSS_SNOC_AXI_CLK 70
-#define GCC_PDM2_CLK 71
-#define GCC_PDM_AHB_CLK 72
-#define GCC_PRNG_AHB_CLK 73
-#define GCC_QSPI_AHB_CLK 74
-#define GCC_QSPI_SER_CLK 75
-#define GCC_SDCC1_AHB_CLK 76
-#define GCC_SDCC1_APPS_CLK 77
-#define GCC_SDCC1_ICE_CORE_CLK 78
-#define GCC_SDCC2_AHB_CLK 79
-#define GCC_SDCC2_APPS_CLK 80
-#define GCC_UFS_AHB_CLK 81
-#define GCC_UFS_AXI_CLK 82
-#define GCC_UFS_CLKREF_CLK 83
-#define GCC_UFS_ICE_CORE_CLK 84
-#define GCC_UFS_PHY_AUX_CLK 85
-#define GCC_UFS_RX_SYMBOL_0_CLK 86
-#define GCC_UFS_RX_SYMBOL_1_CLK 87
-#define GCC_UFS_TX_SYMBOL_0_CLK 88
-#define GCC_UFS_UNIPRO_CORE_CLK 89
-#define GCC_USB20_MASTER_CLK 90
-#define GCC_USB20_MOCK_UTMI_CLK 91
-#define GCC_USB20_SLEEP_CLK 92
-#define GCC_USB30_MASTER_CLK 93
-#define GCC_USB30_MOCK_UTMI_CLK 94
-#define GCC_USB30_SLEEP_CLK 95
-#define GCC_USB3_CLKREF_CLK 96
-#define GCC_USB3_PHY_AUX_CLK 97
-#define GCC_USB3_PHY_PIPE_CLK 98
-#define GCC_USB_PHY_CFG_AHB2PHY_CLK 99
-#define GP1_CLK_SRC 100
-#define GP2_CLK_SRC 101
-#define GP3_CLK_SRC 102
-#define GPLL0 103
-#define GPLL0_EARLY 104
-#define GPLL1 105
-#define GPLL1_EARLY 106
-#define GPLL4 107
-#define GPLL4_EARLY 108
-#define HMSS_GPLL0_CLK_SRC 109
-#define HMSS_GPLL4_CLK_SRC 110
-#define HMSS_RBCPR_CLK_SRC 111
-#define PDM2_CLK_SRC 112
-#define QSPI_SER_CLK_SRC 113
-#define SDCC1_APPS_CLK_SRC 114
-#define SDCC1_ICE_CORE_CLK_SRC 115
-#define SDCC2_APPS_CLK_SRC 116
-#define UFS_AXI_CLK_SRC 117
-#define UFS_ICE_CORE_CLK_SRC 118
-#define UFS_PHY_AUX_CLK_SRC 119
-#define UFS_UNIPRO_CORE_CLK_SRC 120
-#define USB20_MASTER_CLK_SRC 121
-#define USB20_MOCK_UTMI_CLK_SRC 122
-#define USB30_MASTER_CLK_SRC 123
-#define USB30_MOCK_UTMI_CLK_SRC 124
-#define USB3_PHY_AUX_CLK_SRC 125
-#define GPLL0_OUT_MSSCC 126
-#define GCC_UFS_AXI_HW_CTL_CLK 127
-#define GCC_UFS_ICE_CORE_HW_CTL_CLK 128
-#define GCC_UFS_PHY_AUX_HW_CTL_CLK 129
-#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 130
-#define GCC_RX0_USB2_CLKREF_CLK 131
-#define GCC_RX1_USB2_CLKREF_CLK 132
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 0
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 1
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 2
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 3
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 4
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 5
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 6
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 7
+#define BLSP1_UART1_APPS_CLK_SRC 8
+#define BLSP1_UART2_APPS_CLK_SRC 9
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 10
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 11
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 12
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 13
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 14
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 15
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 16
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 17
+#define BLSP2_UART1_APPS_CLK_SRC 18
+#define BLSP2_UART2_APPS_CLK_SRC 19
+#define GCC_AGGRE2_UFS_AXI_CLK 20
+#define GCC_AGGRE2_USB3_AXI_CLK 21
+#define GCC_BIMC_GFX_CLK 22
+#define GCC_BIMC_HMSS_AXI_CLK 23
+#define GCC_BIMC_MSS_Q6_AXI_CLK 24
+#define GCC_BLSP1_AHB_CLK 25
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 26
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 27
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 28
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 29
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 30
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 31
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 32
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 33
+#define GCC_BLSP1_UART1_APPS_CLK 34
+#define GCC_BLSP1_UART2_APPS_CLK 35
+#define GCC_BLSP2_AHB_CLK 36
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 37
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 38
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 39
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 40
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 41
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 42
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 43
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 44
+#define GCC_BLSP2_UART1_APPS_CLK 45
+#define GCC_BLSP2_UART2_APPS_CLK 46
+#define GCC_BOOT_ROM_AHB_CLK 47
+#define GCC_CFG_NOC_USB2_AXI_CLK 48
+#define GCC_CFG_NOC_USB3_AXI_CLK 49
+#define GCC_DCC_AHB_CLK 50
+#define GCC_GP1_CLK 51
+#define GCC_GP2_CLK 52
+#define GCC_GP3_CLK 53
+#define GCC_GPU_BIMC_GFX_CLK 54
+#define GCC_GPU_CFG_AHB_CLK 55
+#define GCC_GPU_GPLL0_CLK 56
+#define GCC_GPU_GPLL0_DIV_CLK 57
+#define GCC_HMSS_DVM_BUS_CLK 58
+#define GCC_HMSS_RBCPR_CLK 59
+#define GCC_MMSS_GPLL0_CLK 60
+#define GCC_MMSS_GPLL0_DIV_CLK 61
+#define GCC_MMSS_NOC_CFG_AHB_CLK 62
+#define GCC_MMSS_SYS_NOC_AXI_CLK 63
+#define GCC_MSS_CFG_AHB_CLK 64
+#define GCC_MSS_GPLL0_DIV_CLK 65
+#define GCC_MSS_MNOC_BIMC_AXI_CLK 66
+#define GCC_MSS_Q6_BIMC_AXI_CLK 67
+#define GCC_MSS_SNOC_AXI_CLK 68
+#define GCC_PDM2_CLK 69
+#define GCC_PDM_AHB_CLK 70
+#define GCC_PRNG_AHB_CLK 71
+#define GCC_QSPI_AHB_CLK 72
+#define GCC_QSPI_SER_CLK 73
+#define GCC_SDCC1_AHB_CLK 74
+#define GCC_SDCC1_APPS_CLK 75
+#define GCC_SDCC1_ICE_CORE_CLK 76
+#define GCC_SDCC2_AHB_CLK 77
+#define GCC_SDCC2_APPS_CLK 78
+#define GCC_UFS_AHB_CLK 79
+#define GCC_UFS_AXI_CLK 80
+#define GCC_UFS_CLKREF_CLK 81
+#define GCC_UFS_ICE_CORE_CLK 82
+#define GCC_UFS_PHY_AUX_CLK 83
+#define GCC_UFS_RX_SYMBOL_0_CLK 84
+#define GCC_UFS_RX_SYMBOL_1_CLK 85
+#define GCC_UFS_TX_SYMBOL_0_CLK 86
+#define GCC_UFS_UNIPRO_CORE_CLK 87
+#define GCC_USB20_MASTER_CLK 88
+#define GCC_USB20_MOCK_UTMI_CLK 89
+#define GCC_USB20_SLEEP_CLK 90
+#define GCC_USB30_MASTER_CLK 91
+#define GCC_USB30_MOCK_UTMI_CLK 92
+#define GCC_USB30_SLEEP_CLK 93
+#define GCC_USB3_CLKREF_CLK 94
+#define GCC_USB3_PHY_AUX_CLK 95
+#define GCC_USB3_PHY_PIPE_CLK 96
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 97
+#define GP1_CLK_SRC 98
+#define GP2_CLK_SRC 99
+#define GP3_CLK_SRC 100
+#define GPLL0 101
+#define GPLL0_EARLY 102
+#define GPLL1 103
+#define GPLL1_EARLY 104
+#define GPLL4 105
+#define GPLL4_EARLY 106
+#define HMSS_GPLL0_CLK_SRC 107
+#define HMSS_GPLL4_CLK_SRC 108
+#define HMSS_RBCPR_CLK_SRC 109
+#define PDM2_CLK_SRC 110
+#define QSPI_SER_CLK_SRC 111
+#define SDCC1_APPS_CLK_SRC 112
+#define SDCC1_ICE_CORE_CLK_SRC 113
+#define SDCC2_APPS_CLK_SRC 114
+#define UFS_AXI_CLK_SRC 115
+#define UFS_ICE_CORE_CLK_SRC 116
+#define UFS_PHY_AUX_CLK_SRC 117
+#define UFS_UNIPRO_CORE_CLK_SRC 118
+#define USB20_MASTER_CLK_SRC 119
+#define USB20_MOCK_UTMI_CLK_SRC 120
+#define USB30_MASTER_CLK_SRC 121
+#define USB30_MOCK_UTMI_CLK_SRC 122
+#define USB3_PHY_AUX_CLK_SRC 123
+#define GPLL0_OUT_MSSCC 124
+#define GCC_UFS_AXI_HW_CTL_CLK 125
+#define GCC_UFS_ICE_CORE_HW_CTL_CLK 126
+#define GCC_UFS_PHY_AUX_HW_CTL_CLK 127
+#define GCC_UFS_UNIPRO_CORE_HW_CTL_CLK 128
+#define GCC_RX0_USB2_CLKREF_CLK 129
+#define GCC_RX1_USB2_CLKREF_CLK 130

#define PCIE_0_GDSC 0
#define UFS_GDSC 1