linux/drivers/mfd/hi655x-pmic.c
John Stultz 9e3d5c996b mfd: hi655x-pmic: Rename some interrupt macro names
Currently the hi655x-pmic driver has names for interrupt mask
values, but not for the interrupt numbers themselves.

So to allow for interrupt numbers to have sane names, rename
the mask values with the _MASK postfix and use the existing
names as the interrupt name

Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
2016-06-29 10:14:41 +01:00

164 lines
4.3 KiB
C

/*
* Device driver for MFD hi655x PMIC
*
* Copyright (c) 2016 Hisilicon.
*
* Authors:
* Chen Feng <puck.chen@hisilicon.com>
* Fei Wang <w.f@huawei.com>
*
* 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.
*/
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/mfd/hi655x-pmic.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
static const struct mfd_cell hi655x_pmic_devs[] = {
{ .name = "hi655x-regulator", },
};
static const struct regmap_irq hi655x_irqs[] = {
{ .reg_offset = 0, .mask = OTMP_D1R_INT_MASK },
{ .reg_offset = 0, .mask = VSYS_2P5_R_INT_MASK },
{ .reg_offset = 0, .mask = VSYS_UV_D3R_INT_MASK },
{ .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT_MASK },
{ .reg_offset = 0, .mask = PWRON_D4SR_INT_MASK },
{ .reg_offset = 0, .mask = PWRON_D20F_INT_MASK },
{ .reg_offset = 0, .mask = PWRON_D20R_INT_MASK },
{ .reg_offset = 0, .mask = RESERVE_INT_MASK },
};
static const struct regmap_irq_chip hi655x_irq_chip = {
.name = "hi655x-pmic",
.irqs = hi655x_irqs,
.num_regs = 1,
.num_irqs = ARRAY_SIZE(hi655x_irqs),
.status_base = HI655X_IRQ_STAT_BASE,
.ack_base = HI655X_IRQ_STAT_BASE,
.mask_base = HI655X_IRQ_MASK_BASE,
};
static struct regmap_config hi655x_regmap_config = {
.reg_bits = 32,
.reg_stride = HI655X_STRIDE,
.val_bits = 8,
.max_register = HI655X_BUS_ADDR(0xFFF),
};
static void hi655x_local_irq_clear(struct regmap *map)
{
int i;
regmap_write(map, HI655X_ANA_IRQM_BASE, HI655X_IRQ_CLR);
for (i = 0; i < HI655X_IRQ_ARRAY; i++) {
regmap_write(map, HI655X_IRQ_STAT_BASE + i * HI655X_STRIDE,
HI655X_IRQ_CLR);
}
}
static int hi655x_pmic_probe(struct platform_device *pdev)
{
int ret;
struct hi655x_pmic *pmic;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *base;
pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
pmic->dev = dev;
pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!pmic->res)
return -ENOENT;
base = devm_ioremap_resource(dev, pmic->res);
if (!base)
return -ENOMEM;
pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,
&hi655x_regmap_config);
regmap_read(pmic->regmap, HI655X_BUS_ADDR(HI655X_VER_REG), &pmic->ver);
if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) {
dev_warn(dev, "PMU version %d unsupported\n", pmic->ver);
return -EINVAL;
}
hi655x_local_irq_clear(pmic->regmap);
pmic->gpio = of_get_named_gpio(np, "pmic-gpios", 0);
if (!gpio_is_valid(pmic->gpio)) {
dev_err(dev, "Failed to get the pmic-gpios\n");
return -ENODEV;
}
ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN,
"hi655x_pmic_irq");
if (ret < 0) {
dev_err(dev, "Failed to request gpio %d ret = %d\n",
pmic->gpio, ret);
return ret;
}
ret = regmap_add_irq_chip(pmic->regmap, gpio_to_irq(pmic->gpio),
IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, 0,
&hi655x_irq_chip, &pmic->irq_data);
if (ret) {
dev_err(dev, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, pmic);
ret = mfd_add_devices(dev, PLATFORM_DEVID_AUTO, hi655x_pmic_devs,
ARRAY_SIZE(hi655x_pmic_devs), NULL, 0, NULL);
if (ret) {
dev_err(dev, "Failed to register device %d\n", ret);
regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data);
return ret;
}
return 0;
}
static int hi655x_pmic_remove(struct platform_device *pdev)
{
struct hi655x_pmic *pmic = platform_get_drvdata(pdev);
regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data);
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id hi655x_pmic_match[] = {
{ .compatible = "hisilicon,hi655x-pmic", },
{},
};
static struct platform_driver hi655x_pmic_driver = {
.driver = {
.name = "hi655x-pmic",
.of_match_table = of_match_ptr(hi655x_pmic_match),
},
.probe = hi655x_pmic_probe,
.remove = hi655x_pmic_remove,
};
module_platform_driver(hi655x_pmic_driver);
MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
MODULE_LICENSE("GPL v2");