aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/hikey9xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/hikey9xx')
-rw-r--r--drivers/staging/hikey9xx/Kconfig2
-rw-r--r--drivers/staging/hikey9xx/hi6421-spmi-pmic.c331
-rw-r--r--drivers/staging/hikey9xx/hi6421v600-regulator.c533
-rw-r--r--drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml108
-rw-r--r--drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml19
-rw-r--r--drivers/staging/hikey9xx/phy-hi3670-usb3.c81
-rw-r--r--drivers/staging/hikey9xx/phy-hi3670-usb3.yaml1
7 files changed, 419 insertions, 656 deletions
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 2e48ded92a7e..82bb4a22b286 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -29,6 +29,7 @@ config MFD_HI6421_SPMI
depends on OF
depends on SPMI
select MFD_CORE
+ select REGMAP_SPMI
help
Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
multi-functions, such as regulators, RTC, codec, Coulomb counter,
@@ -44,6 +45,7 @@ config REGULATOR_HI6421V600
tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
depends on MFD_HI6421_SPMI && OF
depends on REGULATOR
+ select REGMAP
help
This driver provides support for the voltage regulators on
HiSilicon Hi6421v600 PMU / Codec IC.
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 4f34a5282970..4ebcfea9f3bf 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -4,149 +4,105 @@
*
* Copyright (c) 2013 Linaro Ltd.
* Copyright (c) 2011 Hisilicon.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
*/
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
+#include <linux/bitops.h>
#include <linux/interrupt.h>
-#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/of_gpio.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>
-/* 8-bit register offset in PMIC */
-#define HISI_MASK_STATE 0xff
+enum hi6421_spmi_pmic_irq_list {
+ OTMP = 0,
+ VBUS_CONNECT,
+ VBUS_DISCONNECT,
+ ALARMON_R,
+ HOLD_6S,
+ HOLD_1S,
+ POWERKEY_UP,
+ POWERKEY_DOWN,
+ OCP_SCP_R,
+ COUL_R,
+ SIM0_HPD_R,
+ SIM0_HPD_F,
+ SIM1_HPD_R,
+ SIM1_HPD_F,
+ PMIC_IRQ_LIST_MAX,
+};
#define HISI_IRQ_ARRAY 2
#define HISI_IRQ_NUM (HISI_IRQ_ARRAY * 8)
-#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202
-#define SOC_PMIC_IRQ0_ADDR 0x0212
-
#define HISI_IRQ_KEY_NUM 0
-#define HISI_IRQ_KEY_VALUE 0xc0
-#define HISI_IRQ_KEY_DOWN 7
-#define HISI_IRQ_KEY_UP 6
-#define HISI_MASK_FIELD 0xFF
#define HISI_BITS 8
-
-/*define the first group interrupt register number*/
-#define HISI_PMIC_FIRST_GROUP_INT_NUM 2
-
-static const struct mfd_cell hi6421v600_devs[] = {
- { .name = "hi6421v600-regulator", },
-};
+#define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
+#define HISI_MASK GENMASK(HISI_BITS - 1, 0)
/*
- * The PMIC register is only 8-bit.
- * Hisilicon SoC use hardware to map PMIC register into SoC mapping.
- * At here, we are accessing SoC register with 32-bit.
+ * The IRQs are mapped as:
+ *
+ * ====================== ============= ============ =====
+ * IRQ MASK REGISTER IRQ REGISTER BIT
+ * ====================== ============= ============ =====
+ * OTMP 0x0202 0x212 bit 0
+ * VBUS_CONNECT 0x0202 0x212 bit 1
+ * VBUS_DISCONNECT 0x0202 0x212 bit 2
+ * ALARMON_R 0x0202 0x212 bit 3
+ * HOLD_6S 0x0202 0x212 bit 4
+ * HOLD_1S 0x0202 0x212 bit 5
+ * POWERKEY_UP 0x0202 0x212 bit 6
+ * POWERKEY_DOWN 0x0202 0x212 bit 7
+ *
+ * OCP_SCP_R 0x0203 0x213 bit 0
+ * COUL_R 0x0203 0x213 bit 1
+ * SIM0_HPD_R 0x0203 0x213 bit 2
+ * SIM0_HPD_F 0x0203 0x213 bit 3
+ * SIM1_HPD_R 0x0203 0x213 bit 4
+ * SIM1_HPD_F 0x0203 0x213 bit 5
+ * ====================== ============= ============ =====
*/
-int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg)
-{
- struct spmi_device *pdev;
- u8 read_value = 0;
- u32 ret;
-
- pdev = to_spmi_device(pmic->dev);
- if (!pdev) {
- pr_err("%s: pdev get failed!\n", __func__);
- return -ENODEV;
- }
-
- ret = spmi_ext_register_readl(pdev, reg, &read_value, 1);
- if (ret) {
- pr_err("%s: spmi_ext_register_readl failed!\n", __func__);
- return ret;
- }
- return read_value;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_read);
-
-int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val)
-{
- struct spmi_device *pdev;
- u32 ret;
-
- pdev = to_spmi_device(pmic->dev);
- if (!pdev) {
- pr_err("%s: pdev get failed!\n", __func__);
- return -ENODEV;
- }
-
- ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1);
- if (ret)
- pr_err("%s: spmi_ext_register_writel failed!\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_write);
-
-int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg,
- u32 mask, u32 bits)
-{
- unsigned long flags;
- u32 data;
- int ret;
+#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202
+#define SOC_PMIC_IRQ0_ADDR 0x0212
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, reg) & ~mask;
- data |= mask & bits;
- ret = hi6421_spmi_pmic_write(pmic, reg, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
+#define IRQ_MASK_REGISTER(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \
+ (irqd_to_hwirq(irq_data) >> 3))
+#define IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & 0x07)
- return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_rmw);
+static const struct mfd_cell hi6421v600_devs[] = {
+ { .name = "hi6421v600-regulator", },
+};
-static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
+static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
{
- struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data;
+ struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
unsigned long pending;
+ unsigned int in;
int i, offset;
for (i = 0; i < HISI_IRQ_ARRAY; i++) {
- pending = hi6421_spmi_pmic_read(pmic, (i + SOC_PMIC_IRQ0_ADDR));
- pending &= HISI_MASK_FIELD;
- if (pending != 0)
- pr_debug("pending[%d]=0x%lx\n\r", i, pending);
-
- hi6421_spmi_pmic_write(pmic, (i + SOC_PMIC_IRQ0_ADDR), pending);
-
- /* solve powerkey order */
- if ((i == HISI_IRQ_KEY_NUM) &&
- ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) {
- generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]);
- generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]);
+ regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
+ pending = HISI_MASK & in;
+ regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
+
+ if (i == HISI_IRQ_KEY_NUM &&
+ (pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE) {
+ generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
+ generic_handle_irq(ddata->irqs[POWERKEY_UP]);
pending &= (~HISI_IRQ_KEY_VALUE);
}
- if (pending) {
- for_each_set_bit(offset, &pending, HISI_BITS)
- generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]);
- }
+ if (!pending)
+ continue;
+
+ for_each_set_bit(offset, &pending, HISI_BITS)
+ generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]);
}
return IRQ_HANDLED;
@@ -154,34 +110,38 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
static void hi6421_spmi_irq_mask(struct irq_data *d)
{
- struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
- u32 data, offset;
+ struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
unsigned long flags;
+ unsigned int data;
+ u32 offset;
- offset = (irqd_to_hwirq(d) >> 3);
- offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+ offset = IRQ_MASK_REGISTER(d);
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, offset);
- data |= (1 << (irqd_to_hwirq(d) & 0x07));
- hi6421_spmi_pmic_write(pmic, offset, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
+ spin_lock_irqsave(&ddata->lock, flags);
+
+ regmap_read(ddata->regmap, offset, &data);
+ data |= IRQ_MASK_BIT(d);
+ regmap_write(ddata->regmap, offset, data);
+
+ spin_unlock_irqrestore(&ddata->lock, flags);
}
static void hi6421_spmi_irq_unmask(struct irq_data *d)
{
- struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+ struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
u32 data, offset;
unsigned long flags;
offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR;
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, offset);
+ spin_lock_irqsave(&ddata->lock, flags);
+
+ regmap_read(ddata->regmap, offset, &data);
data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
- hi6421_spmi_pmic_write(pmic, offset, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
+ regmap_write(ddata->regmap, offset, data);
+
+ spin_unlock_irqrestore(&ddata->lock, flags);
}
static struct irq_chip hi6421_spmi_pmu_irqchip = {
@@ -195,11 +155,11 @@ static struct irq_chip hi6421_spmi_pmu_irqchip = {
static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
- struct hi6421_spmi_pmic *pmic = d->host_data;
+ struct hi6421_spmi_pmic *ddata = d->host_data;
irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
handle_simple_irq, "hisi");
- irq_set_chip_data(virq, pmic);
+ irq_set_chip_data(virq, ddata);
irq_set_irq_type(virq, IRQ_TYPE_NONE);
return 0;
@@ -210,118 +170,111 @@ static const struct irq_domain_ops hi6421_spmi_domain_ops = {
.xlate = irq_domain_xlate_twocell,
};
-static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic)
+static void hi6421_spmi_pmic_irq_init(struct hi6421_spmi_pmic *ddata)
{
- int i, pending;
+ int i;
+ unsigned int pending;
- for (i = 0 ; i < HISI_IRQ_ARRAY; i++)
- hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ_MASK_0_ADDR + i,
- HISI_MASK_STATE);
+ for (i = 0; i < HISI_IRQ_ARRAY; i++)
+ regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
+ HISI_MASK);
- for (i = 0 ; i < HISI_IRQ_ARRAY; i++) {
- pending = hi6421_spmi_pmic_read(pmic, SOC_PMIC_IRQ0_ADDR + i);
-
- pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n",
- SOC_PMIC_IRQ0_ADDR + i, pending);
- hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ0_ADDR + i,
- HISI_MASK_STATE);
+ for (i = 0; i < HISI_IRQ_ARRAY; i++) {
+ regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
+ regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
+ HISI_MASK);
}
}
+static const struct regmap_config regmap_config = {
+ .reg_bits = 16,
+ .val_bits = HISI_BITS,
+ .max_register = 0xffff,
+ .fast_io = true
+};
+
static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct hi6421_spmi_pmic *pmic;
+ struct hi6421_spmi_pmic *ddata;
unsigned int virq;
int ret, i;
- pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
return -ENOMEM;
- spin_lock_init(&pmic->lock);
+ ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
+ if (IS_ERR(ddata->regmap))
+ return PTR_ERR(ddata->regmap);
- pmic->dev = dev;
+ spin_lock_init(&ddata->lock);
- pmic->gpio = of_get_gpio(np, 0);
- if (pmic->gpio < 0)
- return pmic->gpio;
+ ddata->dev = dev;
- if (!gpio_is_valid(pmic->gpio))
+ ddata->gpio = of_get_gpio(np, 0);
+ if (ddata->gpio < 0)
+ return ddata->gpio;
+
+ if (!gpio_is_valid(ddata->gpio))
return -EINVAL;
- ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN, "pmic");
+ ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
if (ret < 0) {
- dev_err(dev, "failed to request gpio%d\n", pmic->gpio);
+ dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
return ret;
}
- pmic->irq = gpio_to_irq(pmic->gpio);
+ ddata->irq = gpio_to_irq(ddata->gpio);
- hi6421_spmi_pmic_irq_prc(pmic);
+ hi6421_spmi_pmic_irq_init(ddata);
- pmic->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL);
- if (!pmic->irqs) {
- ret = -ENOMEM;
- goto irq_malloc;
- }
+ ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL);
+ if (!ddata->irqs)
+ return -ENOMEM;
- pmic->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0,
- &hi6421_spmi_domain_ops, pmic);
- if (!pmic->domain) {
- dev_err(dev, "failed irq domain add simple!\n");
- ret = -ENODEV;
- goto irq_malloc;
+ ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0,
+ &hi6421_spmi_domain_ops, ddata);
+ if (!ddata->domain) {
+ dev_err(dev, "Failed to create IRQ domain\n");
+ return -ENODEV;
}
for (i = 0; i < HISI_IRQ_NUM; i++) {
- virq = irq_create_mapping(pmic->domain, i);
+ virq = irq_create_mapping(ddata->domain, i);
if (!virq) {
- dev_err(dev, "Failed mapping hwirq\n");
- ret = -ENOSPC;
- goto irq_malloc;
+ dev_err(dev, "Failed to map H/W IRQ\n");
+ return -ENOSPC;
}
- pmic->irqs[i] = virq;
- dev_dbg(dev, "%s: pmic->irqs[%d] = %d\n",
- __func__, i, pmic->irqs[i]);
+ ddata->irqs[i] = virq;
}
- ret = request_threaded_irq(pmic->irq, hi6421_spmi_irq_handler, NULL,
+ ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
- "pmic", pmic);
+ "pmic", ddata);
if (ret < 0) {
- dev_err(dev, "could not claim pmic IRQ: error %d\n", ret);
- goto irq_malloc;
+ dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
+ ret);
+ return ret;
}
- dev_set_drvdata(&pdev->dev, pmic);
+ dev_set_drvdata(&pdev->dev, ddata);
- /*
- * The logic below will rely that the pmic is already stored at
- * drvdata.
- */
- dev_dbg(&pdev->dev, "SPMI-PMIC: adding children for %pOF\n",
- pdev->dev.of_node);
ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
NULL, 0, NULL);
- if (!ret)
- return 0;
-
- dev_err(dev, "Failed to add child devices: %d\n", ret);
-
-irq_malloc:
- free_irq(pmic->irq, pmic);
+ if (ret < 0)
+ dev_err(dev, "Failed to add child devices: %d\n", ret);
return ret;
}
static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
{
- struct hi6421_spmi_pmic *pmic = dev_get_drvdata(&pdev->dev);
+ struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
- free_irq(pmic->irq, pmic);
+ free_irq(ddata->irq, ddata);
}
static const struct of_device_id pmic_spmi_id_table[] = {
diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c
index 614b03c9ddfb..f6a14e9c3cbf 100644
--- a/drivers/staging/hikey9xx/hi6421v600-regulator.c
+++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c
@@ -1,183 +1,148 @@
// SPDX-License-Identifier: GPL-2.0
-/*
- * Device driver for regulators in Hisi IC
- *
- * Copyright (c) 2013 Linaro Ltd.
- * Copyright (c) 2011 Hisilicon.
- *
- * Guodong Xu <guodong.xu@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
+//
+// Device driver for regulators in Hisi IC
+//
+// Copyright (c) 2013 Linaro Ltd.
+// Copyright (c) 2011 Hisilicon.
+// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
+//
+// Guodong Xu <guodong.xu@linaro.org>
#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/io.h>
#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
#include <linux/spmi.h>
-#include <linux/time.h>
-#include <linux/uaccess.h>
-
-#define rdev_dbg(rdev, fmt, arg...) \
- pr_debug("%s: %s: " fmt, (rdev)->desc->name, __func__, ##arg)
-struct hi6421v600_regulator {
- struct regulator_desc rdesc;
+struct hi6421_spmi_reg_info {
+ struct regulator_desc desc;
struct hi6421_spmi_pmic *pmic;
- u32 eco_mode_mask, eco_uA;
+ u8 eco_mode_mask;
+ u32 eco_uA;
+
+ /* Serialize regulator enable logic */
+ struct mutex enable_mutex;
};
-static DEFINE_MUTEX(enable_mutex);
+static const unsigned int ldo3_voltages[] = {
+ 1500000, 1550000, 1600000, 1650000,
+ 1700000, 1725000, 1750000, 1775000,
+ 1800000, 1825000, 1850000, 1875000,
+ 1900000, 1925000, 1950000, 2000000
+};
-/*
- * helper function to ensure when it returns it is at least 'delay_us'
- * microseconds after 'since'.
- */
+static const unsigned int ldo4_voltages[] = {
+ 1725000, 1750000, 1775000, 1800000,
+ 1825000, 1850000, 1875000, 1900000
+};
-static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 reg_val;
+static const unsigned int ldo9_voltages[] = {
+ 1750000, 1800000, 1825000, 2800000,
+ 2850000, 2950000, 3000000, 3300000
+};
- reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg);
+static const unsigned int ldo15_voltages[] = {
+ 1800000, 1850000, 2400000, 2600000,
+ 2700000, 2850000, 2950000, 3000000
+};
- rdev_dbg(rdev,
- "enable_reg=0x%x, val= 0x%x, enable_state=%d\n",
- rdev->desc->enable_reg,
- reg_val, (reg_val & rdev->desc->enable_mask));
+static const unsigned int ldo17_voltages[] = {
+ 2500000, 2600000, 2700000, 2800000,
+ 3000000, 3100000, 3200000, 3300000
+};
- return ((reg_val & rdev->desc->enable_mask) != 0);
-}
+static const unsigned int ldo34_voltages[] = {
+ 2600000, 2700000, 2800000, 2900000,
+ 3000000, 3100000, 3200000, 3300000
+};
+
+/**
+ * HI6421V600_LDO() - specify a LDO power line
+ * @_id: LDO id name string
+ * @vtable: voltage table
+ * @ereg: enable register
+ * @emask: enable mask
+ * @vreg: voltage select register
+ * @odelay: off/on delay time in uS
+ * @etime: enable time in uS
+ * @ecomask: eco mode mask
+ * @ecoamp: eco mode load uppler limit in uA
+ */
+#define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \
+ odelay, etime, ecomask, ecoamp) \
+ [HI6421V600_##_id] = { \
+ .desc = { \
+ .name = #_id, \
+ .of_match = of_match_ptr(#_id), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .ops = &hi6421_spmi_ldo_rops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = HI6421V600_##_id, \
+ .owner = THIS_MODULE, \
+ .volt_table = vtable, \
+ .n_voltages = ARRAY_SIZE(vtable), \
+ .vsel_mask = (1 << (ARRAY_SIZE(vtable) - 1)) - 1, \
+ .vsel_reg = vreg, \
+ .enable_reg = ereg, \
+ .enable_mask = emask, \
+ .enable_time = etime, \
+ .ramp_delay = etime, \
+ .off_on_delay = odelay, \
+ }, \
+ .eco_mode_mask = ecomask, \
+ .eco_uA = ecoamp, \
+ }
static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
struct hi6421_spmi_pmic *pmic = sreg->pmic;
+ int ret;
/* cannot enable more than one regulator at one time */
- mutex_lock(&enable_mutex);
- usleep_range(HISI_REGS_ENA_PROTECT_TIME,
- HISI_REGS_ENA_PROTECT_TIME + 1000);
+ mutex_lock(&sreg->enable_mutex);
- /* set enable register */
- rdev_dbg(rdev,
- "off_on_delay=%d us, enable_reg=0x%x, enable_mask=0x%x\n",
- rdev->desc->off_on_delay, rdev->desc->enable_reg,
- rdev->desc->enable_mask);
+ ret = regmap_update_bits(pmic->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ rdev->desc->enable_mask);
- hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- rdev->desc->enable_mask,
- rdev->desc->enable_mask);
+ /* Avoid powering up multiple devices at the same time */
+ usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 60);
- mutex_unlock(&enable_mutex);
+ mutex_unlock(&sreg->enable_mutex);
- return 0;
+ return ret;
}
static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev)
{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
-
- /* set enable register to 0 */
- rdev_dbg(rdev, "enable_reg=0x%x, enable_mask=0x%x\n",
- rdev->desc->enable_reg, rdev->desc->enable_mask);
-
- hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- rdev->desc->enable_mask, 0);
-
- return 0;
-}
-
-static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 reg_val, selector;
-
- /* get voltage selector */
- reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg);
-
- selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1);
- rdev_dbg(rdev,
- "vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n",
- rdev->desc->vsel_reg, reg_val, selector,
- rdev->desc->ops->list_voltage(rdev, selector) / 1000);
-
- return selector;
-}
-
-static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
- unsigned int selector)
-{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 reg_val;
-
- if (unlikely(selector >= rdev->desc->n_voltages))
- return -EINVAL;
-
- reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
-
- /* set voltage selector */
- rdev_dbg(rdev,
- "vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n",
- rdev->desc->vsel_reg, rdev->desc->vsel_mask, reg_val,
- rdev->desc->ops->list_voltage(rdev, selector) / 1000);
-
- hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg,
- rdev->desc->vsel_mask, reg_val);
-
- return 0;
+ return regmap_update_bits(pmic->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask, 0);
}
static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
struct hi6421_spmi_pmic *pmic = sreg->pmic;
- unsigned int mode;
u32 reg_val;
- reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg);
+ regmap_read(pmic->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & sreg->eco_mode_mask)
- mode = REGULATOR_MODE_IDLE;
- else
- mode = REGULATOR_MODE_NORMAL;
-
- rdev_dbg(rdev,
- "enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n",
- rdev->desc->enable_reg, sreg->eco_mode_mask, reg_val,
- mode == REGULATOR_MODE_IDLE ? "idle" : "normal");
+ return REGULATOR_MODE_IDLE;
- return mode;
+ return REGULATOR_MODE_NORMAL;
}
static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
struct hi6421_spmi_pmic *pmic = sreg->pmic;
u32 val;
@@ -192,14 +157,8 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
return -EINVAL;
}
- /* set mode */
- rdev_dbg(rdev, "enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n",
- rdev->desc->enable_reg, sreg->eco_mode_mask, val);
-
- hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- sreg->eco_mode_mask, val);
-
- return 0;
+ return regmap_update_bits(pmic->regmap, rdev->desc->enable_reg,
+ sreg->eco_mode_mask, val);
}
static unsigned int
@@ -207,199 +166,84 @@ hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
int input_uV, int output_uV,
int load_uA)
{
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- if (load_uA || ((unsigned int)load_uA > sreg->eco_uA))
+ if (!sreg->eco_uA || ((unsigned int)load_uA > sreg->eco_uA))
return REGULATOR_MODE_NORMAL;
return REGULATOR_MODE_IDLE;
}
-static int hi6421_spmi_dt_parse(struct platform_device *pdev,
- struct hi6421v600_regulator *sreg,
- struct regulator_desc *rdesc)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- unsigned int *v_table;
- int ret;
-
- ret = of_property_read_u32(np, "reg", &rdesc->enable_reg);
- if (ret) {
- dev_err(dev, "missing reg property\n");
- return ret;
- }
-
- ret = of_property_read_u32(np, "vsel-reg", &rdesc->vsel_reg);
- if (ret) {
- dev_err(dev, "missing vsel-reg property\n");
- return ret;
- }
-
- ret = of_property_read_u32(np, "enable-mask", &rdesc->enable_mask);
- if (ret) {
- dev_err(dev, "missing enable-mask property\n");
- return ret;
- }
-
- /*
- * Not all regulators work on idle mode
- */
- ret = of_property_read_u32(np, "idle-mode-mask", &sreg->eco_mode_mask);
- if (ret) {
- dev_dbg(dev, "LDO doesn't support economy mode.\n");
- sreg->eco_mode_mask = 0;
- sreg->eco_uA = 0;
- } else {
- ret = of_property_read_u32(np, "eco-microamp", &sreg->eco_uA);
- if (ret) {
- dev_err(dev, "missing eco-microamp property\n");
- return ret;
- }
- }
-
- /* parse .off-on-delay */
- ret = of_property_read_u32(np, "off-on-delay-us",
- &rdesc->off_on_delay);
- if (ret) {
- dev_err(dev, "missing off-on-delay-us property\n");
- return ret;
- }
-
- /* parse .enable_time */
- ret = of_property_read_u32(np, "startup-delay-us",
- &rdesc->enable_time);
- if (ret) {
- dev_err(dev, "missing startup-delay-us property\n");
- return ret;
- }
-
- /* FIXME: are there a better value for this? */
- rdesc->ramp_delay = rdesc->enable_time;
-
- /* parse volt_table */
-
- rdesc->n_voltages = of_property_count_u32_elems(np, "voltage-table");
-
- v_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages,
- GFP_KERNEL);
- if (unlikely(!v_table))
- return -ENOMEM;
- rdesc->volt_table = v_table;
-
- ret = of_property_read_u32_array(np, "voltage-table",
- v_table, rdesc->n_voltages);
- if (ret) {
- dev_err(dev, "missing voltage-table property\n");
- return ret;
- }
-
- /*
- * Instead of explicitly requiring a mask for the voltage selector,
- * as they all start from bit zero (at least on the known LDOs),
- * just use the number of voltages at the voltage table, getting the
- * minimal mask that would pick everything.
- */
- rdesc->vsel_mask = (1 << (fls(rdesc->n_voltages) - 1)) - 1;
-
- dev_dbg(dev, "voltage selector settings: reg: 0x%x, mask: 0x%x\n",
- rdesc->vsel_reg, rdesc->vsel_mask);
-
- return 0;
-}
-
static const struct regulator_ops hi6421_spmi_ldo_rops = {
- .is_enabled = hi6421_spmi_regulator_is_enabled,
+ .is_enabled = regulator_is_enabled_regmap,
.enable = hi6421_spmi_regulator_enable,
.disable = hi6421_spmi_regulator_disable,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
- .get_voltage_sel = hi6421_spmi_regulator_get_voltage_sel,
- .set_voltage_sel = hi6421_spmi_regulator_set_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = hi6421_spmi_regulator_get_mode,
.set_mode = hi6421_spmi_regulator_set_mode,
.get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode,
};
-static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev,
- struct device_node *np,
- struct hi6421_spmi_pmic *pmic)
-{
- struct regulation_constraints *constraint;
- struct regulator_init_data *initdata;
- struct regulator_config config = { };
- struct hi6421v600_regulator *sreg;
- struct device *dev = &pdev->dev;
- struct regulator_desc *rdesc;
- struct regulator_dev *rdev;
- const char *supplyname;
- int ret;
-
- initdata = of_get_regulator_init_data(dev, np, NULL);
- if (!initdata) {
- dev_err(dev, "failed to get regulator data\n");
- return -EINVAL;
- }
-
- sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
- if (!sreg)
- return -ENOMEM;
-
- sreg->pmic = pmic;
- rdesc = &sreg->rdesc;
-
- rdesc->name = initdata->constraints.name;
- rdesc->ops = &hi6421_spmi_ldo_rops;
- rdesc->type = REGULATOR_VOLTAGE;
- rdesc->min_uV = initdata->constraints.min_uV;
-
- supplyname = of_get_property(np, "supply_name", NULL);
- if (supplyname)
- initdata->supply_regulator = supplyname;
-
- /* parse device tree data for regulator specific */
- ret = hi6421_spmi_dt_parse(pdev, sreg, rdesc);
- if (ret)
- return ret;
-
- /* hisi regulator supports two modes */
- constraint = &initdata->constraints;
-
- constraint->valid_modes_mask = REGULATOR_MODE_NORMAL;
- if (sreg->eco_mode_mask) {
- constraint->valid_modes_mask |= REGULATOR_MODE_IDLE;
- constraint->valid_ops_mask |= REGULATOR_CHANGE_MODE;
- }
-
- config.dev = &pdev->dev;
- config.init_data = initdata;
- config.driver_data = sreg;
- config.of_node = pdev->dev.of_node;
-
- /* register regulator */
- rdev = regulator_register(rdesc, &config);
- if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n",
- rdesc->name);
- return PTR_ERR(rdev);
- }
-
- rdev_dbg(rdev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n",
- constraint->valid_modes_mask, constraint->valid_ops_mask);
-
- dev_set_drvdata(dev, rdev);
+/* HI6421v600 regulators with known registers */
+enum hi6421_spmi_regulator_id {
+ HI6421V600_LDO3,
+ HI6421V600_LDO4,
+ HI6421V600_LDO9,
+ HI6421V600_LDO15,
+ HI6421V600_LDO16,
+ HI6421V600_LDO17,
+ HI6421V600_LDO33,
+ HI6421V600_LDO34,
+};
- return 0;
-}
+static struct hi6421_spmi_reg_info regulator_info[] = {
+ HI6421V600_LDO(LDO3, ldo3_voltages,
+ 0x16, 0x01, 0x51,
+ 20000, 120,
+ 0, 0),
+ HI6421V600_LDO(LDO4, ldo4_voltages,
+ 0x17, 0x01, 0x52,
+ 20000, 120,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO9, ldo9_voltages,
+ 0x1c, 0x01, 0x57,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO15, ldo15_voltages,
+ 0x21, 0x01, 0x5c,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO16, ldo15_voltages,
+ 0x22, 0x01, 0x5d,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO17, ldo17_voltages,
+ 0x23, 0x01, 0x5e,
+ 20000, 120,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO33, ldo17_voltages,
+ 0x32, 0x01, 0x6d,
+ 20000, 120,
+ 0, 0),
+ HI6421V600_LDO(LDO34, ldo34_voltages,
+ 0x33, 0x01, 0x6e,
+ 20000, 120,
+ 0, 0),
+};
static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
{
struct device *pmic_dev = pdev->dev.parent;
- struct device_node *np = pmic_dev->of_node;
- struct device_node *regulators, *child;
- struct platform_device *new_pdev;
+ struct regulator_config config = { };
+ struct hi6421_spmi_reg_info *sreg;
+ struct hi6421_spmi_reg_info *info;
+ struct device *dev = &pdev->dev;
struct hi6421_spmi_pmic *pmic;
- int ret;
+ struct regulator_dev *rdev;
+ int i;
/*
* This driver is meant to be called by hi6421-spmi-core,
@@ -410,69 +254,46 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
if (WARN_ON(!pmic))
return -ENODEV;
- regulators = of_get_child_by_name(np, "regulators");
- if (!regulators) {
- dev_err(&pdev->dev, "regulator node not found\n");
- return -ENODEV;
- }
+ sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
+ if (!sreg)
+ return -ENOMEM;
- /*
- * Parse all LDO regulator nodes
- */
- for_each_child_of_node(regulators, child) {
- dev_dbg(&pdev->dev, "adding child %pOF\n", child);
+ sreg->pmic = pmic;
+ mutex_init(&sreg->enable_mutex);
- new_pdev = platform_device_alloc(child->name, -1);
- new_pdev->dev.parent = pmic_dev;
- new_pdev->dev.of_node = of_node_get(child);
+ for (i = 0; i < ARRAY_SIZE(regulator_info); i++) {
+ info = &regulator_info[i];
- ret = platform_device_add(new_pdev);
- if (ret < 0) {
- platform_device_put(new_pdev);
- continue;
- }
+ config.dev = pdev->dev.parent;
+ config.driver_data = sreg;
+ config.regmap = pmic->regmap;
- ret = hi6421_spmi_regulator_probe_ldo(new_pdev, child, pmic);
- if (ret < 0)
- platform_device_put(new_pdev);
+ rdev = devm_regulator_register(dev, &info->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "failed to register %s\n",
+ info->desc.name);
+ return PTR_ERR(rdev);
+ }
}
- of_node_put(regulators);
-
- return 0;
-}
-
-static int hi6421_spmi_regulator_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev);
- struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev);
-
- regulator_unregister(rdev);
-
- if (rdev->desc->volt_table)
- devm_kfree(&pdev->dev, (unsigned int *)rdev->desc->volt_table);
-
- kfree(sreg);
-
return 0;
}
-static const struct platform_device_id hi6421v600_regulator_table[] = {
+static const struct platform_device_id hi6421_spmi_regulator_table[] = {
{ .name = "hi6421v600-regulator" },
{},
};
-MODULE_DEVICE_TABLE(platform, hi6421v600_regulator_table);
+MODULE_DEVICE_TABLE(platform, hi6421_spmi_regulator_table);
-static struct platform_driver hi6421v600_regulator_driver = {
- .id_table = hi6421v600_regulator_table,
+static struct platform_driver hi6421_spmi_regulator_driver = {
+ .id_table = hi6421_spmi_regulator_table,
.driver = {
- .name = "hi6421v600-regulator",
+ .name = "hi6421v600-regulator",
},
.probe = hi6421_spmi_regulator_probe,
- .remove = hi6421_spmi_regulator_remove,
};
-module_platform_driver(hi6421v600_regulator_driver);
+module_platform_driver(hi6421_spmi_regulator_driver);
-MODULE_DESCRIPTION("Hi6421v600 regulator driver");
+MODULE_DESCRIPTION("Hi6421v600 SPMI regulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
index 80e74c261e05..3b23ad56b31a 100644
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
@@ -55,52 +55,13 @@ properties:
$ref: "/schemas/regulator/regulator.yaml#"
- properties:
- reg:
- description: Enable register.
-
- '#address-cells':
- const: 1
-
- '#size-cells':
- const: 0
-
- vsel-reg:
- description: Voltage selector register.
-
- enable-mask:
- description: Bitmask used to enable the regulator.
-
- voltage-table:
- description: Table with the selector items for the voltage regulator.
- minItems: 2
- maxItems: 16
-
- off-on-delay-us:
- description: Time required for changing state to enabled in microseconds.
-
- startup-delay-us:
- description: Startup time in microseconds.
-
- idle-mode-mask:
- description: Bitmask used to put the regulator on idle mode.
-
- eco-microamp:
- description: Maximum current while on idle mode.
-
- required:
- - reg
- - vsel-reg
- - enable-mask
- - voltage-table
- - off-on-delay-us
- - startup-delay-us
-
required:
- compatible
- reg
- regulators
+additionalProperties: false
+
examples:
- |
/* pmic properties */
@@ -117,43 +78,58 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
- ldo3: ldo3@16 {
- reg = <0x16>;
- vsel-reg = <0x51>;
-
+ ldo3: LDO3 {
regulator-name = "ldo3";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <2000000>;
regulator-boot-on;
-
- enable-mask = <0x01>;
-
- voltage-table = <1500000>, <1550000>, <1600000>, <1650000>,
- <1700000>, <1725000>, <1750000>, <1775000>,
- <1800000>, <1825000>, <1850000>, <1875000>,
- <1900000>, <1925000>, <1950000>, <2000000>;
- off-on-delay-us = <20000>;
- startup-delay-us = <120>;
};
- ldo4: ldo4@17 { /* 40 PIN */
- reg = <0x17>;
- vsel-reg = <0x52>;
-
+ ldo4: LDO4 {
regulator-name = "ldo4";
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <1900000>;
regulator-boot-on;
+ };
+
+ ldo9: LDO9 {
+ regulator-name = "ldo9";
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo15: LDO15 {
+ regulator-name = "ldo15";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo16: LDO16 {
+ regulator-name = "ldo16";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ };
- enable-mask = <0x01>;
- idle-mode-mask = <0x10>;
- eco-microamp = <10000>;
+ ldo17: LDO17 {
+ regulator-name = "ldo17";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo33: LDO33 {
+ regulator-name = "ldo33";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
- hi6421-vsel = <0x52 0x07>;
- voltage-table = <1725000>, <1750000>, <1775000>, <1800000>,
- <1825000>, <1850000>, <1875000>, <1900000>;
- off-on-delay-us = <20000>;
- startup-delay-us = <120>;
+ ldo34: LDO34 {
+ regulator-name = "ldo34";
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3300000>;
};
};
};
diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
index f2a56fa4e78e..21f68a9c2df1 100644
--- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
@@ -26,14 +26,22 @@ properties:
reg:
maxItems: 1
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 0
+
spmi-channel:
description: |
number of the Kirin 970 SPMI channel where the SPMI devices are connected.
required:
- - compatible
- - reg
- - spmi-channel
+ - compatible
+ - reg
+ - spmi-channel
+ - "#address-cells"
+ - "#size-cells"
patternProperties:
"^pmic@[0-9a-f]$":
@@ -43,6 +51,8 @@ patternProperties:
are documented at
drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+additionalProperties: false
+
examples:
- |
bus {
@@ -51,11 +61,14 @@ examples:
spmi: spmi@fff24000 {
compatible = "hisilicon,kirin970-spmi-controller";
+ #address-cells = <2>;
+ #size-cells = <0>;
status = "ok";
reg = <0x0 0xfff24000 0x0 0x1000>;
spmi-channel = <2>;
pmic@0 {
+ reg = <0 0>;
/* pmic properties */
};
};
diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c
index 4fc013911a78..e7e579ce0302 100644
--- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c
+++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c
@@ -8,6 +8,7 @@
* Authors: Yu Chen <chenyu56@huawei.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
@@ -41,15 +42,15 @@
#define SC_CLK_USB3PHY_3MUX1_SEL BIT(25)
#define USB3OTG_CTRL0 (0x00)
-#define USB3OTG_CTRL3 (0x0C)
+#define USB3OTG_CTRL3 (0x0c)
#define USB3OTG_CTRL4 (0x10)
#define USB3OTG_CTRL5 (0x14)
-#define USB3OTG_CTRL7 (0x1C)
+#define USB3OTG_CTRL7 (0x1c)
#define USB_MISC_CFG50 (0x50)
#define USB_MISC_CFG54 (0x54)
#define USB_MISC_CFG58 (0x58)
-#define USB_MISC_CFG5C (0x5C)
-#define USB_MISC_CFGA0 (0xA0)
+#define USB_MISC_CFG5C (0x5c)
+#define USB_MISC_CFGA0 (0xa0)
#define TCA_CLK_RST (0x200)
#define TCA_INTR_EN (0x204)
#define TCA_INTR_STS (0x208)
@@ -66,14 +67,14 @@
#define CTRL5_USB2_SIDDQ BIT(0)
-#define CTRL7_USB2_REFCLKSEL_MASK (3 << 3)
-#define CTRL7_USB2_REFCLKSEL_ABB (3 << 3)
-#define CTRL7_USB2_REFCLKSEL_PAD (2 << 3)
+#define CTRL7_USB2_REFCLKSEL_MASK GENMASK(4, 3)
+#define CTRL7_USB2_REFCLKSEL_ABB (BIT(4) | BIT(3))
+#define CTRL7_USB2_REFCLKSEL_PAD BIT(4)
#define CFG50_USB3_PHY_TEST_POWERDOWN BIT(23)
-#define CFG54_USB31PHY_CR_ADDR_MASK (0xFFFF)
-#define CFG54_USB31PHY_CR_ADDR_SHIFT (16)
+#define CFG54_USB31PHY_CR_ADDR_MASK GENMASK(31, 16)
+
#define CFG54_USB3PHY_REF_USE_PAD BIT(12)
#define CFG54_PHY0_PMA_PWR_STABLE BIT(11)
#define CFG54_PHY0_PCS_PWR_STABLE BIT(9)
@@ -84,8 +85,7 @@
#define CFG54_USB31PHY_CR_CLK BIT(2)
#define CFG54_USB3_PHY0_ANA_PWR_EN BIT(1)
-#define CFG58_USB31PHY_CR_DATA_MASK (0xFFFF)
-#define CFG58_USB31PHY_CR_DATA_RD_START (16)
+#define CFG58_USB31PHY_CR_DATA_MASK GENMASK(31, 16)
#define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN BIT(1)
@@ -102,20 +102,20 @@
#define CLK_RST_SUSPEND_CLK_EN BIT(0)
#define GCFG_ROLE_HSTDEV BIT(4)
-#define GCFG_OP_MODE (3 << 0)
+#define GCFG_OP_MODE GENMASK(1, 0)
#define GCFG_OP_MODE_CTRL_SYNC_MODE BIT(0)
#define TCPC_VALID BIT(4)
#define TCPC_LOW_POWER_EN BIT(3)
-#define TCPC_MUX_CONTROL_MASK (3 << 0)
+#define TCPC_MUX_CONTROL_MASK GENMASK(1, 0)
#define TCPC_MUX_CONTROL_USB31 BIT(0)
#define SYSMODE_CFG_TYPEC_DISABLE BIT(3)
-#define VBUS_CTRL_POWERPRESENT_OVERRD (3 << 2)
-#define VBUS_CTRL_VBUSVALID_OVERRD (3 << 0)
+#define VBUS_CTRL_POWERPRESENT_OVERRD GENMASK(3, 2)
+#define VBUS_CTRL_VBUSVALID_OVERRD GENMASK(1, 0)
-#define KIRIN970_USB_DEFAULT_PHY_PARAM (0xFDFEE4)
+#define KIRIN970_USB_DEFAULT_PHY_PARAM (0xfdfee4)
#define KIRIN970_USB_DEFAULT_PHY_VBOOST (0x5)
#define TX_VBOOST_LVL_REG (0xf)
@@ -162,16 +162,14 @@ static int hi3670_phy_cr_set_sel(struct regmap *usb31misc)
static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction)
{
- int ret;
+ int ret, reg;
if (direction)
- ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
- CFG54_USB31PHY_CR_WR_EN,
- CFG54_USB31PHY_CR_WR_EN);
+ reg = CFG54_USB31PHY_CR_WR_EN;
else
- ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
- CFG54_USB31PHY_CR_RD_EN,
- CFG54_USB31PHY_CR_RD_EN);
+ reg = CFG54_USB31PHY_CR_RD_EN;
+
+ ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, reg, reg);
if (ret)
return ret;
@@ -180,16 +178,14 @@ static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction)
if (ret)
return ret;
- ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
- CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0);
-
- return ret;
+ return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+ CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0);
}
static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc)
{
u32 reg;
- int retry = 100000;
+ int retry = 10;
int ret;
while (retry-- > 0) {
@@ -202,6 +198,8 @@ static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc)
ret = hi3670_phy_cr_clk(usb31misc);
if (ret)
return ret;
+
+ usleep_range(10, 20);
}
return -ETIMEDOUT;
@@ -216,9 +214,9 @@ static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr)
if (ret)
return ret;
- reg &= ~(CFG54_USB31PHY_CR_ADDR_MASK << CFG54_USB31PHY_CR_ADDR_SHIFT);
- reg |= ((addr & CFG54_USB31PHY_CR_ADDR_MASK) << CFG54_USB31PHY_CR_ADDR_SHIFT);
- ret = regmap_write(usb31misc, USB_MISC_CFG54, reg);
+ reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr);
+ ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
+ CFG54_USB31PHY_CR_ADDR_MASK, reg);
return ret;
}
@@ -255,8 +253,7 @@ static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val)
if (ret)
return ret;
- *val = (reg >> CFG58_USB31PHY_CR_DATA_RD_START) &
- CFG58_USB31PHY_CR_DATA_MASK;
+ *val = FIELD_GET(CFG58_USB31PHY_CR_DATA_MASK, reg);
return 0;
}
@@ -281,7 +278,7 @@ static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val)
return ret;
ret = regmap_write(usb31misc, USB_MISC_CFG58,
- val & CFG58_USB31PHY_CR_DATA_MASK);
+ FIELD_PREP(CFG58_USB31PHY_CR_DATA_MASK, val));
if (ret)
return ret;
@@ -329,24 +326,24 @@ static int hi3670_phy_set_params(struct hi3670_priv *priv)
return ret;
}
-static int hi3670_is_abbclk_seleted(struct hi3670_priv *priv)
+static bool hi3670_is_abbclk_selected(struct hi3670_priv *priv)
{
u32 reg;
if (!priv->sctrl) {
dev_err(priv->dev, "priv->sctrl is null!\n");
- return 1;
+ return false;
}
if (regmap_read(priv->sctrl, SCTRL_SCDEEPSLEEPED, &reg)) {
dev_err(priv->dev, "SCTRL_SCDEEPSLEEPED read failed!\n");
- return 1;
+ return false;
}
if ((reg & USB_CLK_SELECTED) == 0)
- return 1;
+ return false;
- return 0;
+ return true;
}
static int hi3670_config_phy_clock(struct hi3670_priv *priv)
@@ -354,7 +351,7 @@ static int hi3670_config_phy_clock(struct hi3670_priv *priv)
u32 val, mask;
int ret;
- if (hi3670_is_abbclk_seleted(priv)) {
+ if (!hi3670_is_abbclk_selected(priv)) {
/* usb refclk iso disable */
ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS,
USB_REFCLK_ISO_EN);
@@ -571,7 +568,7 @@ static int hi3670_phy_exit(struct phy *phy)
if (ret)
goto out;
- if (hi3670_is_abbclk_seleted(priv)) {
+ if (!hi3670_is_abbclk_selected(priv)) {
/* disable usb_tcxo_en */
ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
@@ -588,7 +585,7 @@ out:
return ret;
}
-static struct phy_ops hi3670_phy_ops = {
+static const struct phy_ops hi3670_phy_ops = {
.init = hi3670_phy_init,
.exit = hi3670_phy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
index 125a5d6546ae..ebd78acfe2de 100644
--- a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
+++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
@@ -8,6 +8,7 @@ title: Hisilicon Kirin970 USB PHY
maintainers:
- Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
description: |+
Bindings for USB3 PHY on HiSilicon Kirin 970.