diff mbox

[v4,3/5] mfd: hi655x: Add hi665x pmic driver

Message ID 1451910472-126417-4-git-send-email-puck.chen@hisilicon.com
State Superseded
Headers show

Commit Message

Chen Feng Jan. 4, 2016, 12:27 p.m. UTC
Add pmic mfd driver to support hisilicon hi665x.

Signed-off-by: Chen Feng <puck.chen@hisilicon.com>

Signed-off-by: Fei Wang <w.f@huawei.com>

Signed-off-by: Xinwei Kong <kong.kongxinwei@hisilicon.com>

---
 drivers/mfd/Kconfig             |  10 +++
 drivers/mfd/Makefile            |   1 +
 drivers/mfd/hi655x-pmic.c       | 160 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/hi655x-pmic.h |  56 ++++++++++++++
 4 files changed, 227 insertions(+)
 create mode 100644 drivers/mfd/hi655x-pmic.c
 create mode 100644 include/linux/mfd/hi655x-pmic.h

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Comments

Lee Jones Jan. 11, 2016, 5:49 a.m. UTC | #1
Obviously I am unable to accept (or even review) this patch until
these issues are resolved.  Please fix and resubmit the set.

On Tue, 05 Jan 2016, kbuild test robot wrote:
> [auto build test WARNING on v4.4-rc8]

> [also build test WARNING on next-20160104]

> [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

> 

> url:    https://github.com/0day-ci/linux/commits/Chen-Feng/Add-Support-for-Hi6220-PMIC-Hi6553-MFD-Core/20160104-203635

> config: parisc-allmodconfig (attached as .config)

> reproduce:

>         wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross

>         chmod +x ~/bin/make.cross

>         # save the attached .config to linux build tree

>         make.cross ARCH=parisc 

> 

> All warnings (new ones prefixed by >>):

> 

>    In file included from include/linux/platform_device.h:14:0,

>                     from drivers/mfd/hi655x-pmic.c:19:

>    include/linux/device.h:1329:1: warning: data definition has no type or storage class

>     module_init(__driver##_init); \

>     ^

>    include/linux/platform_device.h:222:2: note: in expansion of macro 'module_driver'

>      module_driver(__platform_driver, platform_driver_register, \

>      ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    include/linux/device.h:1329:1: error: type defaults to 'int' in declaration of 'module_init' [-Werror=implicit-int]

>     module_init(__driver##_init); \

>     ^

>    include/linux/platform_device.h:222:2: note: in expansion of macro 'module_driver'

>      module_driver(__platform_driver, platform_driver_register, \

>      ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    drivers/mfd/hi655x-pmic.c:156:1: warning: parameter names (without types) in function declaration

>    In file included from include/linux/platform_device.h:14:0,

>                     from drivers/mfd/hi655x-pmic.c:19:

>    include/linux/device.h:1334:1: warning: data definition has no type or storage class

>     module_exit(__driver##_exit);

>     ^

>    include/linux/platform_device.h:222:2: note: in expansion of macro 'module_driver'

>      module_driver(__platform_driver, platform_driver_register, \

>      ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    include/linux/device.h:1334:1: error: type defaults to 'int' in declaration of 'module_exit' [-Werror=implicit-int]

>     module_exit(__driver##_exit);

>     ^

>    include/linux/platform_device.h:222:2: note: in expansion of macro 'module_driver'

>      module_driver(__platform_driver, platform_driver_register, \

>      ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    drivers/mfd/hi655x-pmic.c:156:1: warning: parameter names (without types) in function declaration

>    drivers/mfd/hi655x-pmic.c:158:15: error: expected declaration specifiers or '...' before string constant

>     MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");

>                   ^

>    drivers/mfd/hi655x-pmic.c:159:20: error: expected declaration specifiers or '...' before string constant

>     MODULE_DESCRIPTION("Hisi hi655x pmic driver");

>                        ^

>    drivers/mfd/hi655x-pmic.c:160:16: error: expected declaration specifiers or '...' before string constant

>     MODULE_LICENSE("GPL v2");

>                    ^

>    In file included from include/linux/platform_device.h:14:0,

>                     from drivers/mfd/hi655x-pmic.c:19:

>    drivers/mfd/hi655x-pmic.c:156:24: warning: 'hi655x_pmic_driver_init' defined but not used [-Wunused-function]

>     module_platform_driver(hi655x_pmic_driver);

>                            ^

>    include/linux/device.h:1325:19: note: in definition of macro 'module_driver'

>     static int __init __driver##_init(void) \

>                       ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    drivers/mfd/hi655x-pmic.c:156:24: warning: 'hi655x_pmic_driver_exit' defined but not used [-Wunused-function]

>     module_platform_driver(hi655x_pmic_driver);

>                            ^

>    include/linux/device.h:1330:20: note: in definition of macro 'module_driver'

>     static void __exit __driver##_exit(void) \

>                        ^

> >> drivers/mfd/hi655x-pmic.c:156:1: note: in expansion of macro 'module_platform_driver'

>     module_platform_driver(hi655x_pmic_driver);

>     ^

>    cc1: some warnings being treated as errors

> 

> vim +/module_platform_driver +156 drivers/mfd/hi655x-pmic.c

> 

>     13	

>     14	#include <linux/io.h>

>     15	#include <linux/interrupt.h>

>     16	#include <linux/init.h>

>     17	#include <linux/gpio.h>

>     18	#include <linux/of_gpio.h>

>   > 19	#include <linux/platform_device.h>

>     20	#include <linux/of_platform.h>

>     21	#include <linux/mfd/hi655x-pmic.h>

>     22	#include <linux/regmap.h>

>     23	

>     24	static const struct of_device_id of_hi655x_pmic_child_match_tbl[] = {

>     25		{ .compatible = "hisilicon,hi655x-regulator", },

>     26		{},

>     27	};

>     28	

>     29	static const struct of_device_id of_hi655x_pmic_match_tbl[] = {

>     30		{ .compatible = "hisilicon,hi655x-pmic", },

>     31		{},

>     32	};

>     33	

>     34	static const struct regmap_irq hi655x_irqs[] = {

>     35		{ .reg_offset = 0, .mask = OTMP_D1R_INT },

>     36		{ .reg_offset = 0, .mask = VSYS_2P5_R_INT },

>     37		{ .reg_offset = 0, .mask = VSYS_UV_D3R_INT },

>     38		{ .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT },

>     39		{ .reg_offset = 0, .mask = PWRON_D4SR_INT },

>     40		{ .reg_offset = 0, .mask = PWRON_D20F_INT },

>     41		{ .reg_offset = 0, .mask = PWRON_D20R_INT },

>     42		{ .reg_offset = 0, .mask = RESERVE_INT },

>     43	};

>     44	

>     45	static const struct regmap_irq_chip hi655x_irq_chip = {

>     46		.name = "hi655x-pmic",

>     47		.irqs = hi655x_irqs,

>     48		.num_regs = 1,

>     49		.num_irqs = ARRAY_SIZE(hi655x_irqs),

>     50		.status_base = HI655X_IRQ_STAT_BASE,

>     51		.mask_base = HI655X_IRQ_MASK_BASE,

>     52	};

>     53	

>     54	static unsigned int hi655x_pmic_get_version(struct hi655x_pmic *pmic)

>     55	{

>     56		u32 val;

>     57	

>     58		regmap_read(pmic->regmap,

>     59			    HI655X_BUS_ADDR(HI655X_VER_REG), &val);

>     60	

>     61		return val;

>     62	}

>     63	

>     64	static struct regmap_config hi655x_regmap_config = {

>     65		.reg_bits = 32,

>     66		.reg_stride = HI655X_STRIDE,

>     67		.val_bits = 8,

>     68		.max_register = HI655X_BUS_ADDR(0xFFF),

>     69	};

>     70	

>     71	static void hi655x_local_irq_clear(struct regmap *map)

>     72	{

>     73		int i;

>     74	

>     75		regmap_write(map, HI655X_ANA_IRQM_BASE, HI655X_IRQ_CLR);

>     76		for (i = 0; i < HI655X_IRQ_ARRAY; i++) {

>     77			regmap_write(map, HI655X_IRQ_STAT_BASE + i * HI655X_STRIDE,

>     78				     HI655X_IRQ_CLR);

>     79		}

>     80	}

>     81	

>     82	static int hi655x_pmic_probe(struct platform_device *pdev)

>     83	{

>     84		int ret;

>     85		struct hi655x_pmic *pmic;

>     86		struct device *dev = &pdev->dev;

>     87		struct device_node *np = dev->of_node;

>     88		void __iomem *base;

>     89	

>     90		pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);

>     91		pmic->dev = dev;

>     92	

>     93		pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

>     94		if (!pmic->res) {

>     95			dev_err(dev, "platform_get_resource err\n");

>     96			return -ENOENT;

>     97		}

>     98		base = devm_ioremap_resource(dev, pmic->res);

>     99		if (!base) {

>    100			dev_err(dev, "cannot map register memory\n");

>    101			return -ENOMEM;

>    102		}

>    103		pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,

>    104							 &hi655x_regmap_config);

>    105	

>    106		pmic->ver = hi655x_pmic_get_version(pmic);

>    107		if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) {

>    108			dev_warn(dev, "it is wrong pmu version\n");

>    109			return -EINVAL;

>    110		}

>    111	

>    112		hi655x_local_irq_clear(pmic->regmap);

>    113	

>    114		pmic->gpio = of_get_named_gpio(np, "pmic-gpios", 0);

>    115		if (!gpio_is_valid(pmic->gpio)) {

>    116			dev_err(dev, "cannot get the pmic-gpios\n");

>    117			return -ENODEV;

>    118		}

>    119	

>    120		ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN, "hi655x_pmic_irq");

>    121		if (ret < 0) {

>    122			dev_err(dev, "failed to request gpio %d  ret = %d\n",

>    123				pmic->gpio, ret);

>    124			return ret;

>    125		}

>    126	

>    127		ret = regmap_add_irq_chip(pmic->regmap, gpio_to_irq(pmic->gpio),

>    128					  IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, 0,

>    129					  &hi655x_irq_chip, &pmic->irq_data);

>    130		if (ret) {

>    131			dev_err(dev, "add pmic irq chip error! ret %d\n", ret);

>    132			return ret;

>    133		}

>    134	

>    135		/* bind pmic to device */

>    136		platform_set_drvdata(pdev, pmic);

>    137	

>    138		/* populate sub nodes */

>    139		ret = of_platform_populate(np, of_hi655x_pmic_child_match_tbl,

>    140					   NULL, dev);

>    141		if (ret) {

>    142			regmap_del_irq_chip(pmic->irq, pmic->irq_data);

>    143			return ret;

>    144		}

>    145	

>    146		return 0;

>    147	}

>    148	

>    149	static struct platform_driver hi655x_pmic_driver = {

>    150		.driver	= {

>    151			.name =	"hi655x-pmic",

>    152			.of_match_table = of_hi655x_pmic_match_tbl,

>    153		},

>    154		.probe  = hi655x_pmic_probe,

>    155	};

>  > 156	module_platform_driver(hi655x_pmic_driver);

>    157	

>    158	MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");

>    159	MODULE_DESCRIPTION("Hisi hi655x pmic driver");

> 

> ---

> 0-DAY kernel test infrastructure                Open Source Technology Center

> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation




-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
diff mbox

Patch

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4d92df6..0c84186 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -284,6 +284,16 @@  config MFD_HI6421_PMIC
 	  menus in order to enable them.
 	  We communicate with the Hi6421 via memory-mapped I/O.
 
+config MFD_HI655X_PMIC
+	tristate "HiSilicon Hi655X series PMU/Codec IC"
+	depends on ARCH_HISI || COMPILE_TEST
+	depends on OF
+	select MFD_CORE
+	select REGMAP_MMIO
+	select REGMAP_IRQ
+	help
+	  Select this option to enable Hisilicon hi655x series pmic driver.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GPIOLIB && ARM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a8b76b8..6a7b0e1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -186,6 +186,7 @@  obj-$(CONFIG_MFD_STW481X)	+= stw481x.o
 obj-$(CONFIG_MFD_IPAQ_MICRO)	+= ipaq-micro.o
 obj-$(CONFIG_MFD_MENF21BMC)	+= menf21bmc.o
 obj-$(CONFIG_MFD_HI6421_PMIC)	+= hi6421-pmic-core.o
+obj-$(CONFIG_MFD_HI655X_PMIC)   += hi655x-pmic.o
 obj-$(CONFIG_MFD_DLN2)		+= dln2.o
 obj-$(CONFIG_MFD_RT5033)	+= rt5033.o
 obj-$(CONFIG_MFD_SKY81452)	+= sky81452.o
diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c
new file mode 100644
index 0000000..fa50aba
--- /dev/null
+++ b/drivers/mfd/hi655x-pmic.c
@@ -0,0 +1,160 @@ 
+/*
+ * Device driver for regulators in hi655x IC
+ *
+ * Copyright (c) 2016 Hisilicon.
+ *
+ * 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/io.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/hi655x-pmic.h>
+#include <linux/regmap.h>
+
+static const struct of_device_id of_hi655x_pmic_child_match_tbl[] = {
+	{ .compatible = "hisilicon,hi655x-regulator", },
+	{},
+};
+
+static const struct of_device_id of_hi655x_pmic_match_tbl[] = {
+	{ .compatible = "hisilicon,hi655x-pmic", },
+	{},
+};
+
+static const struct regmap_irq hi655x_irqs[] = {
+	{ .reg_offset = 0, .mask = OTMP_D1R_INT },
+	{ .reg_offset = 0, .mask = VSYS_2P5_R_INT },
+	{ .reg_offset = 0, .mask = VSYS_UV_D3R_INT },
+	{ .reg_offset = 0, .mask = VSYS_6P0_D200UR_INT },
+	{ .reg_offset = 0, .mask = PWRON_D4SR_INT },
+	{ .reg_offset = 0, .mask = PWRON_D20F_INT },
+	{ .reg_offset = 0, .mask = PWRON_D20R_INT },
+	{ .reg_offset = 0, .mask = RESERVE_INT },
+};
+
+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,
+	.mask_base = HI655X_IRQ_MASK_BASE,
+};
+
+static unsigned int hi655x_pmic_get_version(struct hi655x_pmic *pmic)
+{
+	u32 val;
+
+	regmap_read(pmic->regmap,
+		    HI655X_BUS_ADDR(HI655X_VER_REG), &val);
+
+	return val;
+}
+
+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);
+	pmic->dev = dev;
+
+	pmic->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pmic->res) {
+		dev_err(dev, "platform_get_resource err\n");
+		return -ENOENT;
+	}
+	base = devm_ioremap_resource(dev, pmic->res);
+	if (!base) {
+		dev_err(dev, "cannot map register memory\n");
+		return -ENOMEM;
+	}
+	pmic->regmap = devm_regmap_init_mmio_clk(dev, NULL, base,
+						 &hi655x_regmap_config);
+
+	pmic->ver = hi655x_pmic_get_version(pmic);
+	if ((pmic->ver < PMU_VER_START) || (pmic->ver > PMU_VER_END)) {
+		dev_warn(dev, "it is wrong pmu version\n");
+		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, "cannot 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, "add pmic irq chip error! ret %d\n", ret);
+		return ret;
+	}
+
+	/* bind pmic to device */
+	platform_set_drvdata(pdev, pmic);
+
+	/* populate sub nodes */
+	ret = of_platform_populate(np, of_hi655x_pmic_child_match_tbl,
+				   NULL, dev);
+	if (ret) {
+		regmap_del_irq_chip(pmic->irq, pmic->irq_data);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver hi655x_pmic_driver = {
+	.driver	= {
+		.name =	"hi655x-pmic",
+		.of_match_table = of_hi655x_pmic_match_tbl,
+	},
+	.probe  = hi655x_pmic_probe,
+};
+module_platform_driver(hi655x_pmic_driver);
+
+MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
+MODULE_DESCRIPTION("Hisi hi655x pmic driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/hi655x-pmic.h b/include/linux/mfd/hi655x-pmic.h
new file mode 100644
index 0000000..e1af0a1
--- /dev/null
+++ b/include/linux/mfd/hi655x-pmic.h
@@ -0,0 +1,56 @@ 
+/*
+ * Device driver for regulators in hi655x IC
+ *
+ * Copyright (c) 2016 Hisilicon.
+ *
+ * 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.
+ */
+
+#ifndef __HI655X_PMIC_H
+#define __HI655X_PMIC_H
+
+/* Hi655x registers are mapped to memory bus in 4 bytes stride */
+#define HI655X_STRIDE                   (4)
+#define HI655X_BUS_ADDR(x)              ((x) << 2)
+
+#define HI655X_BITS                     (8)
+
+#define HI655X_NR_IRQ                   (32)
+
+#define HI655X_IRQ_STAT_BASE            (0x003 << 2)
+#define HI655X_IRQ_MASK_BASE            (0x007 << 2)
+#define HI655X_ANA_IRQM_BASE            (0x1b5 << 2)
+#define HI655X_IRQ_ARRAY                (4)
+#define HI655X_IRQ_MASK                 (0xFF)
+#define HI655X_IRQ_CLR                  (0xFF)
+#define HI655X_VER_REG                  (0x00)
+
+#define PMU_VER_START                   (0x10)
+#define PMU_VER_END                     (0x38)
+
+#define RESERVE_INT                     (BIT(7))
+#define PWRON_D20R_INT                  (BIT(6))
+#define PWRON_D20F_INT                  (BIT(5))
+#define PWRON_D4SR_INT                  (BIT(4))
+#define VSYS_6P0_D200UR_INT             (BIT(3))
+#define VSYS_UV_D3R_INT                 (BIT(2))
+#define VSYS_2P5_R_INT                  (BIT(1))
+#define OTMP_D1R_INT                    (BIT(0))
+
+struct hi655x_pmic {
+	struct resource *res;
+	struct device *dev;
+	struct regmap *regmap;
+	struct clk *clk;
+	int irq;
+	int gpio;
+	unsigned int ver;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+#endif