Commit fb02e3eb authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab Committed by Greg Kroah-Hartman

staging: hikey9xx: spmi driver: convert to regmap

Instead of doing its own SPMI I/O implementation, use the
already-existing regmap one.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Link: https://lore.kernel.org/r/7084885f3007ca5daf0d5bc85d038e26ee82dc0d.1611949675.git.mchehab+huawei@kernel.orgSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f92798c
...@@ -29,6 +29,7 @@ config MFD_HI6421_SPMI ...@@ -29,6 +29,7 @@ config MFD_HI6421_SPMI
depends on OF depends on OF
depends on SPMI depends on SPMI
select MFD_CORE select MFD_CORE
select REGMAP_SPMI
help help
Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
multi-functions, such as regulators, RTC, codec, Coulomb counter, multi-functions, such as regulators, RTC, codec, Coulomb counter,
...@@ -44,6 +45,7 @@ config REGULATOR_HI6421V600 ...@@ -44,6 +45,7 @@ config REGULATOR_HI6421V600
tristate "HiSilicon Hi6421v600 PMIC voltage regulator support" tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
depends on MFD_HI6421_SPMI && OF depends on MFD_HI6421_SPMI && OF
depends on REGULATOR depends on REGULATOR
select REGMAP
help help
This driver provides support for the voltage regulators on This driver provides support for the voltage regulators on
HiSilicon Hi6421v600 PMU / Codec IC. HiSilicon Hi6421v600 PMU / Codec IC.
......
...@@ -41,81 +41,22 @@ static const struct mfd_cell hi6421v600_devs[] = { ...@@ -41,81 +41,22 @@ static const struct mfd_cell hi6421v600_devs[] = {
{ .name = "hi6421v600-regulator", }, { .name = "hi6421v600-regulator", },
}; };
/* static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
* 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.
*/
int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg)
{ {
struct spmi_device *pdev; struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)priv;
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;
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);
return ret;
}
EXPORT_SYMBOL(hi6421_spmi_pmic_rmw);
static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
{
struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data;
unsigned long pending; unsigned long pending;
unsigned int data;
int i, offset; int i, offset;
for (i = 0; i < HISI_IRQ_ARRAY; i++) { for (i = 0; i < HISI_IRQ_ARRAY; i++) {
pending = hi6421_spmi_pmic_read(pmic, (i + SOC_PMIC_IRQ0_ADDR)); regmap_read(pmic->map, offset, &data);
pending &= HISI_MASK_FIELD; data &= HISI_MASK_FIELD;
if (pending != 0) if (data != 0)
pr_debug("pending[%d]=0x%lx\n\r", i, pending); pr_debug("data[%d]=0x%d\n\r", i, data);
regmap_write(pmic->map, i + SOC_PMIC_IRQ0_ADDR, data);
hi6421_spmi_pmic_write(pmic, (i + SOC_PMIC_IRQ0_ADDR), pending); /* for_each_set_bit() macro requires unsigned long */
pending = data;
/* solve powerkey order */ /* solve powerkey order */
if ((i == HISI_IRQ_KEY_NUM) && if ((i == HISI_IRQ_KEY_NUM) &&
...@@ -137,16 +78,18 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data) ...@@ -137,16 +78,18 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
static void hi6421_spmi_irq_mask(struct irq_data *d) static void hi6421_spmi_irq_mask(struct irq_data *d)
{ {
struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d); struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
u32 data, offset;
unsigned long flags; unsigned long flags;
unsigned int data;
u32 offset;
offset = (irqd_to_hwirq(d) >> 3); offset = (irqd_to_hwirq(d) >> 3);
offset += SOC_PMIC_IRQ_MASK_0_ADDR; offset += SOC_PMIC_IRQ_MASK_0_ADDR;
spin_lock_irqsave(&pmic->lock, flags); spin_lock_irqsave(&pmic->lock, flags);
data = hi6421_spmi_pmic_read(pmic, offset);
regmap_read(pmic->map, offset, &data);
data |= (1 << (irqd_to_hwirq(d) & 0x07)); data |= (1 << (irqd_to_hwirq(d) & 0x07));
hi6421_spmi_pmic_write(pmic, offset, data); regmap_write(pmic->map, offset, data);
spin_unlock_irqrestore(&pmic->lock, flags); spin_unlock_irqrestore(&pmic->lock, flags);
} }
...@@ -160,9 +103,9 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d) ...@@ -160,9 +103,9 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d)
offset += SOC_PMIC_IRQ_MASK_0_ADDR; offset += SOC_PMIC_IRQ_MASK_0_ADDR;
spin_lock_irqsave(&pmic->lock, flags); spin_lock_irqsave(&pmic->lock, flags);
data = hi6421_spmi_pmic_read(pmic, offset); regmap_read(pmic->map, offset, &data);
data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
hi6421_spmi_pmic_write(pmic, offset, data); regmap_write(pmic->map, offset, data);
spin_unlock_irqrestore(&pmic->lock, flags); spin_unlock_irqrestore(&pmic->lock, flags);
} }
...@@ -194,27 +137,36 @@ static const struct irq_domain_ops hi6421_spmi_domain_ops = { ...@@ -194,27 +137,36 @@ static const struct irq_domain_ops hi6421_spmi_domain_ops = {
static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic) static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic)
{ {
int i, pending; int i;
unsigned int pending;
for (i = 0 ; i < HISI_IRQ_ARRAY; i++) for (i = 0 ; i < HISI_IRQ_ARRAY; i++)
hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ_MASK_0_ADDR + i, regmap_write(pmic->map, SOC_PMIC_IRQ_MASK_0_ADDR + i,
HISI_MASK_STATE); HISI_MASK_STATE);
for (i = 0 ; i < HISI_IRQ_ARRAY; i++) { for (i = 0 ; i < HISI_IRQ_ARRAY; i++) {
pending = hi6421_spmi_pmic_read(pmic, SOC_PMIC_IRQ0_ADDR + i); regmap_read(pmic->map, SOC_PMIC_IRQ0_ADDR + i, &pending);
pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n",
SOC_PMIC_IRQ0_ADDR + i, pending); SOC_PMIC_IRQ0_ADDR + i, pending);
hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ0_ADDR + i, regmap_write(pmic->map, SOC_PMIC_IRQ0_ADDR + i,
HISI_MASK_STATE); HISI_MASK_STATE);
} }
} }
static const struct regmap_config spmi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = 0xffff,
.fast_io = true
};
static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct hi6421_spmi_pmic *pmic; struct hi6421_spmi_pmic *pmic;
struct regmap *map;
unsigned int virq; unsigned int virq;
int ret, i; int ret, i;
...@@ -222,9 +174,14 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) ...@@ -222,9 +174,14 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
if (!pmic) if (!pmic)
return -ENOMEM; return -ENOMEM;
map = devm_regmap_init_spmi_ext(pdev, &spmi_regmap_config);
if (IS_ERR(map))
return PTR_ERR(map);
spin_lock_init(&pmic->lock); spin_lock_init(&pmic->lock);
pmic->dev = dev; pmic->dev = dev;
pmic->map = map;
pmic->gpio = of_get_gpio(np, 0); pmic->gpio = of_get_gpio(np, 0);
if (pmic->gpio < 0) if (pmic->gpio < 0)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/mfd/hi6421-spmi-pmic.h> #include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/spmi.h> #include <linux/spmi.h>
...@@ -100,7 +101,7 @@ static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev) ...@@ -100,7 +101,7 @@ static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
struct hi6421_spmi_pmic *pmic = sreg->pmic; struct hi6421_spmi_pmic *pmic = sreg->pmic;
u32 reg_val; u32 reg_val;
reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); regmap_read(pmic->map, rdev->desc->enable_reg, &reg_val);
return ((reg_val & rdev->desc->enable_mask) != 0); return ((reg_val & rdev->desc->enable_mask) != 0);
} }
...@@ -114,9 +115,9 @@ static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) ...@@ -114,9 +115,9 @@ static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
/* cannot enable more than one regulator at one time */ /* cannot enable more than one regulator at one time */
mutex_lock(&sreg->enable_mutex); mutex_lock(&sreg->enable_mutex);
ret = hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, ret = regmap_update_bits(pmic->map, rdev->desc->enable_reg,
rdev->desc->enable_mask, rdev->desc->enable_mask,
rdev->desc->enable_mask); rdev->desc->enable_mask);
/* Avoid powering up multiple devices at the same time */ /* Avoid powering up multiple devices at the same time */
usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 60); usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 60);
...@@ -131,8 +132,8 @@ static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) ...@@ -131,8 +132,8 @@ static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev)
struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
struct hi6421_spmi_pmic *pmic = sreg->pmic; struct hi6421_spmi_pmic *pmic = sreg->pmic;
return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, return regmap_update_bits(pmic->map, rdev->desc->enable_reg,
rdev->desc->enable_mask, 0); rdev->desc->enable_mask, 0);
} }
static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev) static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
...@@ -141,7 +142,7 @@ static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev) ...@@ -141,7 +142,7 @@ static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
struct hi6421_spmi_pmic *pmic = sreg->pmic; struct hi6421_spmi_pmic *pmic = sreg->pmic;
u32 reg_val; u32 reg_val;
reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg); regmap_read(pmic->map, rdev->desc->vsel_reg, &reg_val);
return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1);
} }
...@@ -159,8 +160,8 @@ static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev, ...@@ -159,8 +160,8 @@ static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1); reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
/* set voltage selector */ /* set voltage selector */
return hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg, return regmap_update_bits(pmic->map, rdev->desc->vsel_reg,
rdev->desc->vsel_mask, reg_val); rdev->desc->vsel_mask, reg_val);
} }
static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
...@@ -169,7 +170,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) ...@@ -169,7 +170,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
struct hi6421_spmi_pmic *pmic = sreg->pmic; struct hi6421_spmi_pmic *pmic = sreg->pmic;
u32 reg_val; u32 reg_val;
reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); regmap_read(pmic->map, rdev->desc->enable_reg, &reg_val);
if (reg_val & sreg->eco_mode_mask) if (reg_val & sreg->eco_mode_mask)
return REGULATOR_MODE_IDLE; return REGULATOR_MODE_IDLE;
...@@ -195,8 +196,8 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, ...@@ -195,8 +196,8 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
return -EINVAL; return -EINVAL;
} }
return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, return regmap_update_bits(pmic->map, rdev->desc->enable_reg,
sreg->eco_mode_mask, val); sreg->eco_mode_mask, val);
} }
static unsigned int static unsigned int
...@@ -304,6 +305,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev) ...@@ -304,6 +305,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
config.dev = pdev->dev.parent; config.dev = pdev->dev.parent;
config.driver_data = sreg; config.driver_data = sreg;
config.regmap = pmic->map;
rdev = devm_regulator_register(dev, &info->desc, &config); rdev = devm_regulator_register(dev, &info->desc, &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define __HISI_PMIC_H #define __HISI_PMIC_H
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/regmap.h>
#define HISI_ECO_MODE_ENABLE (1) #define HISI_ECO_MODE_ENABLE (1)
#define HISI_ECO_MODE_DISABLE (0) #define HISI_ECO_MODE_DISABLE (0)
...@@ -25,13 +26,9 @@ struct hi6421_spmi_pmic { ...@@ -25,13 +26,9 @@ struct hi6421_spmi_pmic {
int irq; int irq;
int gpio; int gpio;
unsigned int *irqs; unsigned int *irqs;
struct regmap *map;
}; };
int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg);
int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val);
int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg,
u32 mask, u32 bits);
enum hi6421_spmi_pmic_irq_list { enum hi6421_spmi_pmic_irq_list {
OTMP = 0, OTMP = 0,
VBUS_CONNECT, VBUS_CONNECT,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment