aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrystian Garbaciak <krystian.garbaciak@diasemi.com>2013-07-29 13:00:43 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-08-19 21:15:52 -0400
commit8e685483b0ba17fe08cfc36fb86b3688a24b2090 (patch)
tree5d555fb3056e88923d8c058d32ed9ab2c28ae5a8
parent36ec66e0333355112148549f9846adcc0909482e (diff)
mfd: da9063: Add Dialog DA9063 core driver
This is MFD module providing access to registers and interrupts of DA906x series PMIC. It is used by other functional modules, registered as MFD cells. Driver uses regmap with paging to access extended register list. Register map is divided into two pages, where the second page is used during initialisation. This module provides support to following functional cells: - Regulators - RTC - HWMON - OnKey (power key misc input device) - Vibration (force-feedback input device) - Watchdog - LEDs Signed-off-by: Krystian Garbaciak <krystian.garbaciak@diasemi.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Reviewed-by: Mark Brown <broonie@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig12
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/da9063-core.c129
-rw-r--r--drivers/mfd/da9063-i2c.c182
-rw-r--r--include/linux/mfd/da9063/core.h55
-rw-r--r--include/linux/mfd/da9063/pdata.h111
6 files changed, 492 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 633ee43efae6..e0e46f50f95d 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -139,6 +139,18 @@ config MFD_DA9055
139 This driver can be built as a module. If built as a module it will be 139 This driver can be built as a module. If built as a module it will be
140 called "da9055" 140 called "da9055"
141 141
142config MFD_DA9063
143 bool "Dialog Semiconductor DA9063 PMIC Support"
144 select MFD_CORE
145 select REGMAP_I2C
146 select REGMAP_IRQ
147 depends on I2C=y && GENERIC_HARDIRQS
148 help
149 Say yes here for support for the Dialog Semiconductor DA9063 PMIC.
150 This includes the I2C driver and core APIs.
151 Additional drivers must be enabled in order to use the functionality
152 of the device.
153
142config MFD_MC13783 154config MFD_MC13783
143 tristate 155 tristate
144 156
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 3c90051ffa5a..0bb84d59f3fa 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -107,6 +107,9 @@ obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
107da9055-objs := da9055-core.o da9055-i2c.o 107da9055-objs := da9055-core.o da9055-i2c.o
108obj-$(CONFIG_MFD_DA9055) += da9055.o 108obj-$(CONFIG_MFD_DA9055) += da9055.o
109 109
110da9063-objs := da9063-core.o da9063-i2c.o
111obj-$(CONFIG_MFD_DA9063) += da9063.o
112
110obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o 113obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
111obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o 114obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
112obj-$(CONFIG_MFD_MAX8907) += max8907.o 115obj-$(CONFIG_MFD_MAX8907) += max8907.o
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
new file mode 100644
index 000000000000..29f3ed1f076c
--- /dev/null
+++ b/drivers/mfd/da9063-core.c
@@ -0,0 +1,129 @@
1/*
2 * da9063-core.c: Device access for Dialog DA9063 modules
3 *
4 * Copyright 2012 Dialog Semiconductors Ltd.
5 * Copyright 2013 Philipp Zabel, Pengutronix
6 *
7 * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>,
8 * Michal Hajduk <michal.hajduk@diasemi.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/device.h>
22#include <linux/delay.h>
23#include <linux/interrupt.h>
24#include <linux/mutex.h>
25#include <linux/mfd/core.h>
26#include <linux/regmap.h>
27
28#include <linux/mfd/da9063/core.h>
29#include <linux/mfd/da9063/pdata.h>
30#include <linux/mfd/da9063/registers.h>
31
32#include <linux/proc_fs.h>
33#include <linux/kthread.h>
34#include <linux/uaccess.h>
35
36
37static struct mfd_cell da9063_devs[] = {
38 {
39 .name = DA9063_DRVNAME_REGULATORS,
40 },
41 {
42 .name = DA9063_DRVNAME_LEDS,
43 },
44 {
45 .name = DA9063_DRVNAME_WATCHDOG,
46 },
47 {
48 .name = DA9063_DRVNAME_HWMON,
49 },
50 {
51 .name = DA9063_DRVNAME_ONKEY,
52 },
53 {
54 .name = DA9063_DRVNAME_RTC,
55 },
56 {
57 .name = DA9063_DRVNAME_VIBRATION,
58 },
59};
60
61int da9063_device_init(struct da9063 *da9063, unsigned int irq)
62{
63 struct da9063_pdata *pdata = da9063->dev->platform_data;
64 int model, revision;
65 int ret;
66
67 if (pdata) {
68 da9063->flags = pdata->flags;
69 da9063->irq_base = pdata->irq_base;
70 } else {
71 da9063->flags = 0;
72 da9063->irq_base = 0;
73 }
74 da9063->chip_irq = irq;
75
76 if (pdata && pdata->init != NULL) {
77 ret = pdata->init(da9063);
78 if (ret != 0) {
79 dev_err(da9063->dev,
80 "Platform initialization failed.\n");
81 return ret;
82 }
83 }
84
85 ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model);
86 if (ret < 0) {
87 dev_err(da9063->dev, "Cannot read chip model id.\n");
88 return -EIO;
89 }
90 if (model != PMIC_DA9063) {
91 dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
92 return -ENODEV;
93 }
94
95 ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &revision);
96 if (ret < 0) {
97 dev_err(da9063->dev, "Cannot read chip revision id.\n");
98 return -EIO;
99 }
100 revision >>= DA9063_CHIP_VARIANT_SHIFT;
101 if (revision != 3) {
102 dev_err(da9063->dev, "Unknown chip revision: %d\n", revision);
103 return -ENODEV;
104 }
105
106 da9063->model = model;
107 da9063->revision = revision;
108
109 dev_info(da9063->dev,
110 "Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n",
111 model, revision);
112
113 ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
114 ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
115 NULL);
116 if (ret)
117 dev_err(da9063->dev, "Cannot add MFD cells\n");
118
119 return ret;
120}
121
122void da9063_device_exit(struct da9063 *da9063)
123{
124 mfd_remove_devices(da9063->dev);
125}
126
127MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
128MODULE_AUTHOR("Krystian Garbaciak <krystian.garbaciak@diasemi.com>, Michal Hajduk <michal.hajduk@diasemi.com>");
129MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c
new file mode 100644
index 000000000000..8db5c805c64f
--- /dev/null
+++ b/drivers/mfd/da9063-i2c.c
@@ -0,0 +1,182 @@
1/* da9063-i2c.c: Interrupt support for Dialog DA9063
2 *
3 * Copyright 2012 Dialog Semiconductor Ltd.
4 * Copyright 2013 Philipp Zabel, Pengutronix
5 *
6 * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/i2c.h>
18#include <linux/regmap.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/err.h>
22
23#include <linux/mfd/core.h>
24#include <linux/mfd/da9063/core.h>
25#include <linux/mfd/da9063/pdata.h>
26#include <linux/mfd/da9063/registers.h>
27
28static const struct regmap_range da9063_readable_ranges[] = {
29 {
30 .range_min = DA9063_REG_PAGE_CON,
31 .range_max = DA9063_REG_SECOND_D,
32 }, {
33 .range_min = DA9063_REG_SEQ,
34 .range_max = DA9063_REG_ID_32_31,
35 }, {
36 .range_min = DA9063_REG_SEQ_A,
37 .range_max = DA9063_REG_AUTO3_LOW,
38 }, {
39 .range_min = DA9063_REG_T_OFFSET,
40 .range_max = DA9063_REG_GP_ID_19,
41 }, {
42 .range_min = DA9063_REG_CHIP_ID,
43 .range_max = DA9063_REG_CHIP_VARIANT,
44 },
45};
46
47static const struct regmap_range da9063_writeable_ranges[] = {
48 {
49 .range_min = DA9063_REG_PAGE_CON,
50 .range_max = DA9063_REG_PAGE_CON,
51 }, {
52 .range_min = DA9063_REG_FAULT_LOG,
53 .range_max = DA9063_REG_VSYS_MON,
54 }, {
55 .range_min = DA9063_REG_COUNT_S,
56 .range_max = DA9063_REG_ALARM_Y,
57 }, {
58 .range_min = DA9063_REG_SEQ,
59 .range_max = DA9063_REG_ID_32_31,
60 }, {
61 .range_min = DA9063_REG_SEQ_A,
62 .range_max = DA9063_REG_AUTO3_LOW,
63 }, {
64 .range_min = DA9063_REG_CONFIG_I,
65 .range_max = DA9063_REG_MON_REG_4,
66 }, {
67 .range_min = DA9063_REG_GP_ID_0,
68 .range_max = DA9063_REG_GP_ID_19,
69 },
70};
71
72static const struct regmap_range da9063_volatile_ranges[] = {
73 {
74 .range_min = DA9063_REG_STATUS_A,
75 .range_max = DA9063_REG_EVENT_D,
76 }, {
77 .range_min = DA9063_REG_CONTROL_F,
78 .range_max = DA9063_REG_CONTROL_F,
79 }, {
80 .range_min = DA9063_REG_ADC_MAN,
81 .range_max = DA9063_REG_ADC_MAN,
82 }, {
83 .range_min = DA9063_REG_ADC_RES_L,
84 .range_max = DA9063_REG_SECOND_D,
85 }, {
86 .range_min = DA9063_REG_MON_REG_5,
87 .range_max = DA9063_REG_MON_REG_6,
88 },
89};
90
91static const struct regmap_access_table da9063_readable_table = {
92 .yes_ranges = da9063_readable_ranges,
93 .n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
94};
95
96static const struct regmap_access_table da9063_writeable_table = {
97 .yes_ranges = da9063_writeable_ranges,
98 .n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
99};
100
101static const struct regmap_access_table da9063_volatile_table = {
102 .yes_ranges = da9063_volatile_ranges,
103 .n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
104};
105
106static const struct regmap_range_cfg da9063_range_cfg[] = {
107 {
108 .range_min = DA9063_REG_PAGE_CON,
109 .range_max = DA9063_REG_CHIP_VARIANT,
110 .selector_reg = DA9063_REG_PAGE_CON,
111 .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
112 .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
113 .window_start = 0,
114 .window_len = 256,
115 }
116};
117
118static struct regmap_config da9063_regmap_config = {
119 .reg_bits = 8,
120 .val_bits = 8,
121 .ranges = da9063_range_cfg,
122 .num_ranges = ARRAY_SIZE(da9063_range_cfg),
123 .max_register = DA9063_REG_CHIP_VARIANT,
124
125 .cache_type = REGCACHE_RBTREE,
126
127 .rd_table = &da9063_readable_table,
128 .wr_table = &da9063_writeable_table,
129 .volatile_table = &da9063_volatile_table,
130};
131
132static int da9063_i2c_probe(struct i2c_client *i2c,
133 const struct i2c_device_id *id)
134{
135 struct da9063 *da9063;
136 int ret;
137
138 da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);
139 if (da9063 == NULL)
140 return -ENOMEM;
141
142 i2c_set_clientdata(i2c, da9063);
143 da9063->dev = &i2c->dev;
144 da9063->chip_irq = i2c->irq;
145
146 da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
147 if (IS_ERR(da9063->regmap)) {
148 ret = PTR_ERR(da9063->regmap);
149 dev_err(da9063->dev, "Failed to allocate register map: %d\n",
150 ret);
151 return ret;
152 }
153
154 return da9063_device_init(da9063, i2c->irq);
155}
156
157static int da9063_i2c_remove(struct i2c_client *i2c)
158{
159 struct da9063 *da9063 = i2c_get_clientdata(i2c);
160
161 da9063_device_exit(da9063);
162
163 return 0;
164}
165
166static const struct i2c_device_id da9063_i2c_id[] = {
167 {"da9063", PMIC_DA9063},
168 {},
169};
170MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
171
172static struct i2c_driver da9063_i2c_driver = {
173 .driver = {
174 .name = "da9063",
175 .owner = THIS_MODULE,
176 },
177 .probe = da9063_i2c_probe,
178 .remove = da9063_i2c_remove,
179 .id_table = da9063_i2c_id,
180};
181
182module_i2c_driver(da9063_i2c_driver);
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h
new file mode 100644
index 000000000000..ec2fd2aa24ae
--- /dev/null
+++ b/include/linux/mfd/da9063/core.h
@@ -0,0 +1,55 @@
1/*
2 * Definitions for DA9063 MFD driver
3 *
4 * Copyright 2012 Dialog Semiconductor Ltd.
5 *
6 * Author: Michal Hajduk <michal.hajduk@diasemi.com>
7 * Krystian Garbaciak <krystian.garbaciak@diasemi.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#ifndef __MFD_DA9063_CORE_H__
17#define __MFD_DA9063_CORE_H__
18
19#include <linux/interrupt.h>
20#include <linux/mfd/da9063/registers.h>
21
22/* DA9063 modules */
23#define DA9063_DRVNAME_CORE "da9063-core"
24#define DA9063_DRVNAME_REGULATORS "da9063-regulators"
25#define DA9063_DRVNAME_LEDS "da9063-leds"
26#define DA9063_DRVNAME_WATCHDOG "da9063-watchdog"
27#define DA9063_DRVNAME_HWMON "da9063-hwmon"
28#define DA9063_DRVNAME_ONKEY "da9063-onkey"
29#define DA9063_DRVNAME_RTC "da9063-rtc"
30#define DA9063_DRVNAME_VIBRATION "da9063-vibration"
31
32enum da9063_models {
33 PMIC_DA9063 = 0x61,
34};
35
36struct da9063 {
37 /* Device */
38 struct device *dev;
39 unsigned short model;
40 unsigned short revision;
41 unsigned int flags;
42
43 /* Control interface */
44 struct regmap *regmap;
45
46 /* Interrupts */
47 int chip_irq;
48 unsigned int irq_base;
49};
50
51int da9063_device_init(struct da9063 *da9063, unsigned int irq);
52
53void da9063_device_exit(struct da9063 *da9063);
54
55#endif /* __MFD_DA9063_CORE_H__ */
diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h
new file mode 100644
index 000000000000..95c8742215a7
--- /dev/null
+++ b/include/linux/mfd/da9063/pdata.h
@@ -0,0 +1,111 @@
1/*
2 * Platform configuration options for DA9063
3 *
4 * Copyright 2012 Dialog Semiconductor Ltd.
5 *
6 * Author: Michal Hajduk <michal.hajduk@diasemi.com>
7 * Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#ifndef __MFD_DA9063_PDATA_H__
17#define __MFD_DA9063_PDATA_H__
18
19#include <linux/regulator/machine.h>
20
21/*
22 * Regulator configuration
23 */
24/* DA9063 regulator IDs */
25enum {
26 /* BUCKs */
27 DA9063_ID_BCORE1,
28 DA9063_ID_BCORE2,
29 DA9063_ID_BPRO,
30 DA9063_ID_BMEM,
31 DA9063_ID_BIO,
32 DA9063_ID_BPERI,
33
34 /* BCORE1 and BCORE2 in merged mode */
35 DA9063_ID_BCORES_MERGED,
36 /* BMEM and BIO in merged mode */
37 DA9063_ID_BMEM_BIO_MERGED,
38 /* When two BUCKs are merged, they cannot be reused separately */
39
40 /* LDOs */
41 DA9063_ID_LDO1,
42 DA9063_ID_LDO2,
43 DA9063_ID_LDO3,
44 DA9063_ID_LDO4,
45 DA9063_ID_LDO5,
46 DA9063_ID_LDO6,
47 DA9063_ID_LDO7,
48 DA9063_ID_LDO8,
49 DA9063_ID_LDO9,
50 DA9063_ID_LDO10,
51 DA9063_ID_LDO11,
52};
53
54/* Regulators platform data */
55struct da9063_regulator_data {
56 int id;
57 struct regulator_init_data *initdata;
58};
59
60struct da9063_regulators_pdata {
61 unsigned n_regulators;
62 struct da9063_regulator_data *regulator_data;
63};
64
65
66/*
67 * RGB LED configuration
68 */
69/* LED IDs for flags in struct led_info. */
70enum {
71 DA9063_GPIO11_LED,
72 DA9063_GPIO14_LED,
73 DA9063_GPIO15_LED,
74
75 DA9063_LED_NUM
76};
77#define DA9063_LED_ID_MASK 0x3
78
79/* LED polarity for flags in struct led_info. */
80#define DA9063_LED_HIGH_LEVEL_ACTIVE 0x0
81#define DA9063_LED_LOW_LEVEL_ACTIVE 0x4
82
83
84/*
85 * General PMIC configuration
86 */
87/* HWMON ADC channels configuration */
88#define DA9063_FLG_FORCE_IN0_MANUAL_MODE 0x0010
89#define DA9063_FLG_FORCE_IN0_AUTO_MODE 0x0020
90#define DA9063_FLG_FORCE_IN1_MANUAL_MODE 0x0040
91#define DA9063_FLG_FORCE_IN1_AUTO_MODE 0x0080
92#define DA9063_FLG_FORCE_IN2_MANUAL_MODE 0x0100
93#define DA9063_FLG_FORCE_IN2_AUTO_MODE 0x0200
94#define DA9063_FLG_FORCE_IN3_MANUAL_MODE 0x0400
95#define DA9063_FLG_FORCE_IN3_AUTO_MODE 0x0800
96
97/* Disable register caching. */
98#define DA9063_FLG_NO_CACHE 0x0008
99
100struct da9063;
101
102/* DA9063 platform data */
103struct da9063_pdata {
104 int (*init)(struct da9063 *da9063);
105 int irq_base;
106 unsigned flags;
107 struct da9063_regulators_pdata *regulators_pdata;
108 struct led_platform_data *leds_pdata;
109};
110
111#endif /* __MFD_DA9063_PDATA_H__ */