aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2017-01-05 19:44:39 -0500
committerLee Jones <lee.jones@linaro.org>2017-02-13 04:29:44 -0500
commit56e1d40d3beab2f247d48574bf51fc5daeebc285 (patch)
tree715145f623a24ff8d44d4f2ba91404164a422255
parent1cb8af8d631f66dde37a918bdd08a924ba3c7c03 (diff)
mfd: cpcap: Add minimal support
Many Motorola phones like droid 4 are using a custom PMIC called CPCAP or 6556002. We can support it's core features quite easily with regmap_spi and regmap_irq. The children of cpcap, such as regulators, ADC and USB, can be just regular device drivers and defined in the dts file. They get probed as we call of_platform_populate() at the end of our probe, and then the children can just call dev_get_regmap(dev.parent, NULL) to get the regmap. Cc: devicetree@vger.kernel.org Cc: Marcel Partap <mpartap@gmx.net> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Michael Scott <michael.scott@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/mfd/motorola-cpcap.txt31
-rw-r--r--drivers/mfd/Kconfig11
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/motorola-cpcap.c259
-rw-r--r--include/linux/mfd/motorola-cpcap.h292
5 files changed, 594 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
new file mode 100644
index 000000000000..15bc885f9df4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
@@ -0,0 +1,31 @@
1Motorola CPCAP PMIC device tree binding
2
3Required properties:
4- compatible : One or both of "motorola,cpcap" or "ste,6556002"
5- reg : SPI chip select
6- interrupt-parent : The parent interrupt controller
7- interrupts : The interrupt line the device is connected to
8- interrupt-controller : Marks the device node as an interrupt controller
9- #interrupt-cells : The number of cells to describe an IRQ, should be 2
10- #address-cells : Child device offset number of cells, should be 1
11- #size-cells : Child device size number of cells, should be 0
12- spi-max-frequency : Typically set to 3000000
13- spi-cs-high : SPI chip select direction
14
15Example:
16
17&mcspi1 {
18 cpcap: pmic@0 {
19 compatible = "motorola,cpcap", "ste,6556002";
20 reg = <0>; /* cs0 */
21 interrupt-parent = <&gpio1>;
22 interrupts = <7 IRQ_TYPE_EDGE_RISING>;
23 interrupt-controller;
24 #interrupt-cells = <2>;
25 #address-cells = <1>;
26 #size-cells = <0>;
27 spi-max-frequency = <3000000>;
28 spi-cs-high;
29 };
30};
31
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index dbebe20c6d6d..496247a7f893 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -715,6 +715,17 @@ config EZX_PCAP
715 This enables the PCAP ASIC present on EZX Phones. This is 715 This enables the PCAP ASIC present on EZX Phones. This is
716 needed for MMC, TouchScreen, Sound, USB, etc.. 716 needed for MMC, TouchScreen, Sound, USB, etc..
717 717
718config MFD_CPCAP
719 tristate "Support for Motorola CPCAP"
720 depends on SPI
721 depends on OF || COMPILE_TEST
722 select REGMAP_SPI
723 select REGMAP_IRQ
724 help
725 Say yes here if you want to include driver for CPCAP.
726 It is used on many Motorola phones and tablets as a PMIC.
727 At least Motorola Droid 4 is known to use CPCAP.
728
718config MFD_VIPERBOARD 729config MFD_VIPERBOARD
719 tristate "Nano River Technologies Viperboard" 730 tristate "Nano River Technologies Viperboard"
720 select MFD_CORE 731 select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 876ca8600c51..31ce07611a6f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -97,6 +97,7 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
97obj-$(CONFIG_MFD_CORE) += mfd-core.o 97obj-$(CONFIG_MFD_CORE) += mfd-core.o
98 98
99obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o 99obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
100obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o
100 101
101obj-$(CONFIG_MCP) += mcp-core.o 102obj-$(CONFIG_MCP) += mcp-core.o
102obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o 103obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
new file mode 100644
index 000000000000..6aeada7d7ce5
--- /dev/null
+++ b/drivers/mfd/motorola-cpcap.c
@@ -0,0 +1,259 @@
1/*
2 * Motorola CPCAP PMIC core driver
3 *
4 * Copyright (C) 2016 Tony Lindgren <tony@atomide.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/device.h>
12#include <linux/err.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/of_device.h>
18#include <linux/regmap.h>
19#include <linux/sysfs.h>
20
21#include <linux/mfd/motorola-cpcap.h>
22#include <linux/spi/spi.h>
23
24#define CPCAP_NR_IRQ_REG_BANKS 6
25#define CPCAP_NR_IRQ_CHIPS 3
26
27struct cpcap_ddata {
28 struct spi_device *spi;
29 struct regmap_irq *irqs;
30 struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
31 const struct regmap_config *regmap_conf;
32 struct regmap *regmap;
33};
34
35static int cpcap_check_revision(struct cpcap_ddata *cpcap)
36{
37 u16 vendor, rev;
38 int ret;
39
40 ret = cpcap_get_vendor(&cpcap->spi->dev, cpcap->regmap, &vendor);
41 if (ret)
42 return ret;
43
44 ret = cpcap_get_revision(&cpcap->spi->dev, cpcap->regmap, &rev);
45 if (ret)
46 return ret;
47
48 dev_info(&cpcap->spi->dev, "CPCAP vendor: %s rev: %i.%i (%x)\n",
49 vendor == CPCAP_VENDOR_ST ? "ST" : "TI",
50 CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev),
51 rev);
52
53 if (rev < CPCAP_REVISION_2_1) {
54 dev_info(&cpcap->spi->dev,
55 "Please add old CPCAP revision support as needed\n");
56 return -ENODEV;
57 }
58
59 return 0;
60}
61
62/*
63 * First two irq chips are the two private macro interrupt chips, the third
64 * irq chip is for register banks 1 - 4 and is available for drivers to use.
65 */
66static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
67 {
68 .name = "cpcap-m2",
69 .num_regs = 1,
70 .status_base = CPCAP_REG_MI1,
71 .ack_base = CPCAP_REG_MI1,
72 .mask_base = CPCAP_REG_MIM1,
73 .use_ack = true,
74 },
75 {
76 .name = "cpcap-m2",
77 .num_regs = 1,
78 .status_base = CPCAP_REG_MI2,
79 .ack_base = CPCAP_REG_MI2,
80 .mask_base = CPCAP_REG_MIM2,
81 .use_ack = true,
82 },
83 {
84 .name = "cpcap1-4",
85 .num_regs = 4,
86 .status_base = CPCAP_REG_INT1,
87 .ack_base = CPCAP_REG_INT1,
88 .mask_base = CPCAP_REG_INTM1,
89 .type_base = CPCAP_REG_INTS1,
90 .use_ack = true,
91 },
92};
93
94static void cpcap_init_one_regmap_irq(struct cpcap_ddata *cpcap,
95 struct regmap_irq *rirq,
96 int irq_base, int irq)
97{
98 unsigned int reg_offset;
99 unsigned int bit, mask;
100
101 reg_offset = irq - irq_base;
102 reg_offset /= cpcap->regmap_conf->val_bits;
103 reg_offset *= cpcap->regmap_conf->reg_stride;
104
105 bit = irq % cpcap->regmap_conf->val_bits;
106 mask = (1 << bit);
107
108 rirq->reg_offset = reg_offset;
109 rirq->mask = mask;
110}
111
112static int cpcap_init_irq_chip(struct cpcap_ddata *cpcap, int irq_chip,
113 int irq_start, int nr_irqs)
114{
115 struct regmap_irq_chip *chip = &cpcap_irq_chip[irq_chip];
116 int i, ret;
117
118 for (i = irq_start; i < irq_start + nr_irqs; i++) {
119 struct regmap_irq *rirq = &cpcap->irqs[i];
120
121 cpcap_init_one_regmap_irq(cpcap, rirq, irq_start, i);
122 }
123 chip->irqs = &cpcap->irqs[irq_start];
124 chip->num_irqs = nr_irqs;
125 chip->irq_drv_data = cpcap;
126
127 ret = devm_regmap_add_irq_chip(&cpcap->spi->dev, cpcap->regmap,
128 cpcap->spi->irq,
129 IRQF_TRIGGER_RISING |
130 IRQF_SHARED, -1,
131 chip, &cpcap->irqdata[irq_chip]);
132 if (ret) {
133 dev_err(&cpcap->spi->dev, "could not add irq chip %i: %i\n",
134 irq_chip, ret);
135 return ret;
136 }
137
138 return 0;
139}
140
141static int cpcap_init_irq(struct cpcap_ddata *cpcap)
142{
143 int ret;
144
145 cpcap->irqs = devm_kzalloc(&cpcap->spi->dev,
146 sizeof(*cpcap->irqs) *
147 CPCAP_NR_IRQ_REG_BANKS *
148 cpcap->regmap_conf->val_bits,
149 GFP_KERNEL);
150 if (!cpcap->irqs)
151 return -ENOMEM;
152
153 ret = cpcap_init_irq_chip(cpcap, 0, 0, 16);
154 if (ret)
155 return ret;
156
157 ret = cpcap_init_irq_chip(cpcap, 1, 16, 16);
158 if (ret)
159 return ret;
160
161 ret = cpcap_init_irq_chip(cpcap, 2, 32, 64);
162 if (ret)
163 return ret;
164
165 enable_irq_wake(cpcap->spi->irq);
166
167 return 0;
168}
169
170static const struct of_device_id cpcap_of_match[] = {
171 { .compatible = "motorola,cpcap", },
172 { .compatible = "st,6556002", },
173 {},
174};
175MODULE_DEVICE_TABLE(of, cpcap_of_match);
176
177static const struct regmap_config cpcap_regmap_config = {
178 .reg_bits = 16,
179 .reg_stride = 4,
180 .pad_bits = 0,
181 .val_bits = 16,
182 .write_flag_mask = 0x8000,
183 .max_register = CPCAP_REG_ST_TEST2,
184 .cache_type = REGCACHE_NONE,
185 .reg_format_endian = REGMAP_ENDIAN_LITTLE,
186 .val_format_endian = REGMAP_ENDIAN_LITTLE,
187};
188
189static int cpcap_probe(struct spi_device *spi)
190{
191 const struct of_device_id *match;
192 struct cpcap_ddata *cpcap;
193 int ret;
194
195 match = of_match_device(of_match_ptr(cpcap_of_match), &spi->dev);
196 if (!match)
197 return -ENODEV;
198
199 cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
200 if (!cpcap)
201 return -ENOMEM;
202
203 cpcap->spi = spi;
204 spi_set_drvdata(spi, cpcap);
205
206 spi->bits_per_word = 16;
207 spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
208
209 ret = spi_setup(spi);
210 if (ret)
211 return ret;
212
213 cpcap->regmap_conf = &cpcap_regmap_config;
214 cpcap->regmap = devm_regmap_init_spi(spi, &cpcap_regmap_config);
215 if (IS_ERR(cpcap->regmap)) {
216 ret = PTR_ERR(cpcap->regmap);
217 dev_err(&cpcap->spi->dev, "Failed to initialize regmap: %d\n",
218 ret);
219
220 return ret;
221 }
222
223 ret = cpcap_check_revision(cpcap);
224 if (ret) {
225 dev_err(&cpcap->spi->dev, "Failed to detect CPCAP: %i\n", ret);
226 return ret;
227 }
228
229 ret = cpcap_init_irq(cpcap);
230 if (ret)
231 return ret;
232
233 return of_platform_populate(spi->dev.of_node, NULL, NULL,
234 &cpcap->spi->dev);
235}
236
237static int cpcap_remove(struct spi_device *pdev)
238{
239 struct cpcap_ddata *cpcap = spi_get_drvdata(pdev);
240
241 of_platform_depopulate(&cpcap->spi->dev);
242
243 return 0;
244}
245
246static struct spi_driver cpcap_driver = {
247 .driver = {
248 .name = "cpcap-core",
249 .of_match_table = cpcap_of_match,
250 },
251 .probe = cpcap_probe,
252 .remove = cpcap_remove,
253};
254module_spi_driver(cpcap_driver);
255
256MODULE_ALIAS("platform:cpcap");
257MODULE_DESCRIPTION("CPCAP driver");
258MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
259MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
new file mode 100644
index 000000000000..b4031c2b2214
--- /dev/null
+++ b/include/linux/mfd/motorola-cpcap.h
@@ -0,0 +1,292 @@
1/*
2 * The register defines are based on earlier cpcap.h in Motorola Linux kernel
3 * tree.
4 *
5 * Copyright (C) 2007-2009 Motorola, Inc.
6 *
7 * Rewritten for the real register offsets instead of enumeration
8 * to make the defines usable with Linux kernel regmap support
9 *
10 * Copyright (C) 2016 Tony Lindgren <tony@atomide.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#define CPCAP_VENDOR_ST 0
18#define CPCAP_VENDOR_TI 1
19
20#define CPCAP_REVISION_MAJOR(r) (((r) >> 4) + 1)
21#define CPCAP_REVISION_MINOR(r) ((r) & 0xf)
22
23#define CPCAP_REVISION_1_0 0x08
24#define CPCAP_REVISION_1_1 0x09
25#define CPCAP_REVISION_2_0 0x10
26#define CPCAP_REVISION_2_1 0x11
27
28/* CPCAP registers */
29#define CPCAP_REG_INT1 0x0000 /* Interrupt 1 */
30#define CPCAP_REG_INT2 0x0004 /* Interrupt 2 */
31#define CPCAP_REG_INT3 0x0008 /* Interrupt 3 */
32#define CPCAP_REG_INT4 0x000c /* Interrupt 4 */
33#define CPCAP_REG_INTM1 0x0010 /* Interrupt Mask 1 */
34#define CPCAP_REG_INTM2 0x0014 /* Interrupt Mask 2 */
35#define CPCAP_REG_INTM3 0x0018 /* Interrupt Mask 3 */
36#define CPCAP_REG_INTM4 0x001c /* Interrupt Mask 4 */
37#define CPCAP_REG_INTS1 0x0020 /* Interrupt Sense 1 */
38#define CPCAP_REG_INTS2 0x0024 /* Interrupt Sense 2 */
39#define CPCAP_REG_INTS3 0x0028 /* Interrupt Sense 3 */
40#define CPCAP_REG_INTS4 0x002c /* Interrupt Sense 4 */
41#define CPCAP_REG_ASSIGN1 0x0030 /* Resource Assignment 1 */
42#define CPCAP_REG_ASSIGN2 0x0034 /* Resource Assignment 2 */
43#define CPCAP_REG_ASSIGN3 0x0038 /* Resource Assignment 3 */
44#define CPCAP_REG_ASSIGN4 0x003c /* Resource Assignment 4 */
45#define CPCAP_REG_ASSIGN5 0x0040 /* Resource Assignment 5 */
46#define CPCAP_REG_ASSIGN6 0x0044 /* Resource Assignment 6 */
47#define CPCAP_REG_VERSC1 0x0048 /* Version Control 1 */
48#define CPCAP_REG_VERSC2 0x004c /* Version Control 2 */
49
50#define CPCAP_REG_MI1 0x0200 /* Macro Interrupt 1 */
51#define CPCAP_REG_MIM1 0x0204 /* Macro Interrupt Mask 1 */
52#define CPCAP_REG_MI2 0x0208 /* Macro Interrupt 2 */
53#define CPCAP_REG_MIM2 0x020c /* Macro Interrupt Mask 2 */
54#define CPCAP_REG_UCC1 0x0210 /* UC Control 1 */
55#define CPCAP_REG_UCC2 0x0214 /* UC Control 2 */
56
57#define CPCAP_REG_PC1 0x021c /* Power Cut 1 */
58#define CPCAP_REG_PC2 0x0220 /* Power Cut 2 */
59#define CPCAP_REG_BPEOL 0x0224 /* BP and EOL */
60#define CPCAP_REG_PGC 0x0228 /* Power Gate and Control */
61#define CPCAP_REG_MT1 0x022c /* Memory Transfer 1 */
62#define CPCAP_REG_MT2 0x0230 /* Memory Transfer 2 */
63#define CPCAP_REG_MT3 0x0234 /* Memory Transfer 3 */
64#define CPCAP_REG_PF 0x0238 /* Print Format */
65
66#define CPCAP_REG_SCC 0x0400 /* System Clock Control */
67#define CPCAP_REG_SW1 0x0404 /* Stop Watch 1 */
68#define CPCAP_REG_SW2 0x0408 /* Stop Watch 2 */
69#define CPCAP_REG_UCTM 0x040c /* UC Turbo Mode */
70#define CPCAP_REG_TOD1 0x0410 /* Time of Day 1 */
71#define CPCAP_REG_TOD2 0x0414 /* Time of Day 2 */
72#define CPCAP_REG_TODA1 0x0418 /* Time of Day Alarm 1 */
73#define CPCAP_REG_TODA2 0x041c /* Time of Day Alarm 2 */
74#define CPCAP_REG_DAY 0x0420 /* Day */
75#define CPCAP_REG_DAYA 0x0424 /* Day Alarm */
76#define CPCAP_REG_VAL1 0x0428 /* Validity 1 */
77#define CPCAP_REG_VAL2 0x042c /* Validity 2 */
78
79#define CPCAP_REG_SDVSPLL 0x0600 /* Switcher DVS and PLL */
80#define CPCAP_REG_SI2CC1 0x0604 /* Switcher I2C Control 1 */
81#define CPCAP_REG_Si2CC2 0x0608 /* Switcher I2C Control 2 */
82#define CPCAP_REG_S1C1 0x060c /* Switcher 1 Control 1 */
83#define CPCAP_REG_S1C2 0x0610 /* Switcher 1 Control 2 */
84#define CPCAP_REG_S2C1 0x0614 /* Switcher 2 Control 1 */
85#define CPCAP_REG_S2C2 0x0618 /* Switcher 2 Control 2 */
86#define CPCAP_REG_S3C 0x061c /* Switcher 3 Control */
87#define CPCAP_REG_S4C1 0x0620 /* Switcher 4 Control 1 */
88#define CPCAP_REG_S4C2 0x0624 /* Switcher 4 Control 2 */
89#define CPCAP_REG_S5C 0x0628 /* Switcher 5 Control */
90#define CPCAP_REG_S6C 0x062c /* Switcher 6 Control */
91#define CPCAP_REG_VCAMC 0x0630 /* VCAM Control */
92#define CPCAP_REG_VCSIC 0x0634 /* VCSI Control */
93#define CPCAP_REG_VDACC 0x0638 /* VDAC Control */
94#define CPCAP_REG_VDIGC 0x063c /* VDIG Control */
95#define CPCAP_REG_VFUSEC 0x0640 /* VFUSE Control */
96#define CPCAP_REG_VHVIOC 0x0644 /* VHVIO Control */
97#define CPCAP_REG_VSDIOC 0x0648 /* VSDIO Control */
98#define CPCAP_REG_VPLLC 0x064c /* VPLL Control */
99#define CPCAP_REG_VRF1C 0x0650 /* VRF1 Control */
100#define CPCAP_REG_VRF2C 0x0654 /* VRF2 Control */
101#define CPCAP_REG_VRFREFC 0x0658 /* VRFREF Control */
102#define CPCAP_REG_VWLAN1C 0x065c /* VWLAN1 Control */
103#define CPCAP_REG_VWLAN2C 0x0660 /* VWLAN2 Control */
104#define CPCAP_REG_VSIMC 0x0664 /* VSIM Control */
105#define CPCAP_REG_VVIBC 0x0668 /* VVIB Control */
106#define CPCAP_REG_VUSBC 0x066c /* VUSB Control */
107#define CPCAP_REG_VUSBINT1C 0x0670 /* VUSBINT1 Control */
108#define CPCAP_REG_VUSBINT2C 0x0674 /* VUSBINT2 Control */
109#define CPCAP_REG_URT 0x0678 /* Useroff Regulator Trigger */
110#define CPCAP_REG_URM1 0x067c /* Useroff Regulator Mask 1 */
111#define CPCAP_REG_URM2 0x0680 /* Useroff Regulator Mask 2 */
112
113#define CPCAP_REG_VAUDIOC 0x0800 /* VAUDIO Control */
114#define CPCAP_REG_CC 0x0804 /* Codec Control */
115#define CPCAP_REG_CDI 0x0808 /* Codec Digital Interface */
116#define CPCAP_REG_SDAC 0x080c /* Stereo DAC */
117#define CPCAP_REG_SDACDI 0x0810 /* Stereo DAC Digital Interface */
118#define CPCAP_REG_TXI 0x0814 /* TX Inputs */
119#define CPCAP_REG_TXMP 0x0818 /* TX MIC PGA's */
120#define CPCAP_REG_RXOA 0x081c /* RX Output Amplifiers */
121#define CPCAP_REG_RXVC 0x0820 /* RX Volume Control */
122#define CPCAP_REG_RXCOA 0x0824 /* RX Codec to Output Amps */
123#define CPCAP_REG_RXSDOA 0x0828 /* RX Stereo DAC to Output Amps */
124#define CPCAP_REG_RXEPOA 0x082c /* RX External PGA to Output Amps */
125#define CPCAP_REG_RXLL 0x0830 /* RX Low Latency */
126#define CPCAP_REG_A2LA 0x0834 /* A2 Loudspeaker Amplifier */
127#define CPCAP_REG_MIPIS1 0x0838 /* MIPI Slimbus 1 */
128#define CPCAP_REG_MIPIS2 0x083c /* MIPI Slimbus 2 */
129#define CPCAP_REG_MIPIS3 0x0840 /* MIPI Slimbus 3. */
130#define CPCAP_REG_LVAB 0x0844 /* LMR Volume and A4 Balanced. */
131
132#define CPCAP_REG_CCC1 0x0a00 /* Coulomb Counter Control 1 */
133#define CPCAP_REG_CRM 0x0a04 /* Charger and Reverse Mode */
134#define CPCAP_REG_CCCC2 0x0a08 /* Coincell and Coulomb Ctr Ctrl 2 */
135#define CPCAP_REG_CCS1 0x0a0c /* Coulomb Counter Sample 1 */
136#define CPCAP_REG_CCS2 0x0a10 /* Coulomb Counter Sample 2 */
137#define CPCAP_REG_CCA1 0x0a14 /* Coulomb Counter Accumulator 1 */
138#define CPCAP_REG_CCA2 0x0a18 /* Coulomb Counter Accumulator 2 */
139#define CPCAP_REG_CCM 0x0a1c /* Coulomb Counter Mode */
140#define CPCAP_REG_CCO 0x0a20 /* Coulomb Counter Offset */
141#define CPCAP_REG_CCI 0x0a24 /* Coulomb Counter Integrator */
142
143#define CPCAP_REG_ADCC1 0x0c00 /* A/D Converter Configuration 1 */
144#define CPCAP_REG_ADCC2 0x0c04 /* A/D Converter Configuration 2 */
145#define CPCAP_REG_ADCD0 0x0c08 /* A/D Converter Data 0 */
146#define CPCAP_REG_ADCD1 0x0c0c /* A/D Converter Data 1 */
147#define CPCAP_REG_ADCD2 0x0c10 /* A/D Converter Data 2 */
148#define CPCAP_REG_ADCD3 0x0c14 /* A/D Converter Data 3 */
149#define CPCAP_REG_ADCD4 0x0c18 /* A/D Converter Data 4 */
150#define CPCAP_REG_ADCD5 0x0c1c /* A/D Converter Data 5 */
151#define CPCAP_REG_ADCD6 0x0c20 /* A/D Converter Data 6 */
152#define CPCAP_REG_ADCD7 0x0c24 /* A/D Converter Data 7 */
153#define CPCAP_REG_ADCAL1 0x0c28 /* A/D Converter Calibration 1 */
154#define CPCAP_REG_ADCAL2 0x0c2c /* A/D Converter Calibration 2 */
155
156#define CPCAP_REG_USBC1 0x0e00 /* USB Control 1 */
157#define CPCAP_REG_USBC2 0x0e04 /* USB Control 2 */
158#define CPCAP_REG_USBC3 0x0e08 /* USB Control 3 */
159#define CPCAP_REG_UVIDL 0x0e0c /* ULPI Vendor ID Low */
160#define CPCAP_REG_UVIDH 0x0e10 /* ULPI Vendor ID High */
161#define CPCAP_REG_UPIDL 0x0e14 /* ULPI Product ID Low */
162#define CPCAP_REG_UPIDH 0x0e18 /* ULPI Product ID High */
163#define CPCAP_REG_UFC1 0x0e1c /* ULPI Function Control 1 */
164#define CPCAP_REG_UFC2 0x0e20 /* ULPI Function Control 2 */
165#define CPCAP_REG_UFC3 0x0e24 /* ULPI Function Control 3 */
166#define CPCAP_REG_UIC1 0x0e28 /* ULPI Interface Control 1 */
167#define CPCAP_REG_UIC2 0x0e2c /* ULPI Interface Control 2 */
168#define CPCAP_REG_UIC3 0x0e30 /* ULPI Interface Control 3 */
169#define CPCAP_REG_USBOTG1 0x0e34 /* USB OTG Control 1 */
170#define CPCAP_REG_USBOTG2 0x0e38 /* USB OTG Control 2 */
171#define CPCAP_REG_USBOTG3 0x0e3c /* USB OTG Control 3 */
172#define CPCAP_REG_UIER1 0x0e40 /* USB Interrupt Enable Rising 1 */
173#define CPCAP_REG_UIER2 0x0e44 /* USB Interrupt Enable Rising 2 */
174#define CPCAP_REG_UIER3 0x0e48 /* USB Interrupt Enable Rising 3 */
175#define CPCAP_REG_UIEF1 0x0e4c /* USB Interrupt Enable Falling 1 */
176#define CPCAP_REG_UIEF2 0x0e50 /* USB Interrupt Enable Falling 1 */
177#define CPCAP_REG_UIEF3 0x0e54 /* USB Interrupt Enable Falling 1 */
178#define CPCAP_REG_UIS 0x0e58 /* USB Interrupt Status */
179#define CPCAP_REG_UIL 0x0e5c /* USB Interrupt Latch */
180#define CPCAP_REG_USBD 0x0e60 /* USB Debug */
181#define CPCAP_REG_SCR1 0x0e64 /* Scratch 1 */
182#define CPCAP_REG_SCR2 0x0e68 /* Scratch 2 */
183#define CPCAP_REG_SCR3 0x0e6c /* Scratch 3 */
184
185#define CPCAP_REG_VMC 0x0eac /* Video Mux Control */
186#define CPCAP_REG_OWDC 0x0eb0 /* One Wire Device Control */
187#define CPCAP_REG_GPIO0 0x0eb4 /* GPIO 0 Control */
188
189#define CPCAP_REG_GPIO1 0x0ebc /* GPIO 1 Control */
190
191#define CPCAP_REG_GPIO2 0x0ec4 /* GPIO 2 Control */
192
193#define CPCAP_REG_GPIO3 0x0ecc /* GPIO 3 Control */
194
195#define CPCAP_REG_GPIO4 0x0ed4 /* GPIO 4 Control */
196
197#define CPCAP_REG_GPIO5 0x0edc /* GPIO 5 Control */
198
199#define CPCAP_REG_GPIO6 0x0ee4 /* GPIO 6 Control */
200
201#define CPCAP_REG_MDLC 0x1000 /* Main Display Lighting Control */
202#define CPCAP_REG_KLC 0x1004 /* Keypad Lighting Control */
203#define CPCAP_REG_ADLC 0x1008 /* Aux Display Lighting Control */
204#define CPCAP_REG_REDC 0x100c /* Red Triode Control */
205#define CPCAP_REG_GREENC 0x1010 /* Green Triode Control */
206#define CPCAP_REG_BLUEC 0x1014 /* Blue Triode Control */
207#define CPCAP_REG_CFC 0x1018 /* Camera Flash Control */
208#define CPCAP_REG_ABC 0x101c /* Adaptive Boost Control */
209#define CPCAP_REG_BLEDC 0x1020 /* Bluetooth LED Control */
210#define CPCAP_REG_CLEDC 0x1024 /* Camera Privacy LED Control */
211
212#define CPCAP_REG_OW1C 0x1200 /* One Wire 1 Command */
213#define CPCAP_REG_OW1D 0x1204 /* One Wire 1 Data */
214#define CPCAP_REG_OW1I 0x1208 /* One Wire 1 Interrupt */
215#define CPCAP_REG_OW1IE 0x120c /* One Wire 1 Interrupt Enable */
216
217#define CPCAP_REG_OW1 0x1214 /* One Wire 1 Control */
218
219#define CPCAP_REG_OW2C 0x1220 /* One Wire 2 Command */
220#define CPCAP_REG_OW2D 0x1224 /* One Wire 2 Data */
221#define CPCAP_REG_OW2I 0x1228 /* One Wire 2 Interrupt */
222#define CPCAP_REG_OW2IE 0x122c /* One Wire 2 Interrupt Enable */
223
224#define CPCAP_REG_OW2 0x1234 /* One Wire 2 Control */
225
226#define CPCAP_REG_OW3C 0x1240 /* One Wire 3 Command */
227#define CPCAP_REG_OW3D 0x1244 /* One Wire 3 Data */
228#define CPCAP_REG_OW3I 0x1248 /* One Wire 3 Interrupt */
229#define CPCAP_REG_OW3IE 0x124c /* One Wire 3 Interrupt Enable */
230
231#define CPCAP_REG_OW3 0x1254 /* One Wire 3 Control */
232#define CPCAP_REG_GCAIC 0x1258 /* GCAI Clock Control */
233#define CPCAP_REG_GCAIM 0x125c /* GCAI GPIO Mode */
234#define CPCAP_REG_LGDIR 0x1260 /* LMR GCAI GPIO Direction */
235#define CPCAP_REG_LGPU 0x1264 /* LMR GCAI GPIO Pull-up */
236#define CPCAP_REG_LGPIN 0x1268 /* LMR GCAI GPIO Pin */
237#define CPCAP_REG_LGMASK 0x126c /* LMR GCAI GPIO Mask */
238#define CPCAP_REG_LDEB 0x1270 /* LMR Debounce Settings */
239#define CPCAP_REG_LGDET 0x1274 /* LMR GCAI Detach Detect */
240#define CPCAP_REG_LMISC 0x1278 /* LMR Misc Bits */
241#define CPCAP_REG_LMACE 0x127c /* LMR Mace IC Support */
242
243#define CPCAP_REG_TEST 0x7c00 /* Test */
244
245#define CPCAP_REG_ST_TEST1 0x7d08 /* ST Test1 */
246
247#define CPCAP_REG_ST_TEST2 0x7d18 /* ST Test2 */
248
249/*
250 * Helpers for child devices to check the revision and vendor.
251 *
252 * REVISIT: No documentation for the bits below, please update
253 * to use proper names for defines when available.
254 */
255
256static inline int cpcap_get_revision(struct device *dev,
257 struct regmap *regmap,
258 u16 *revision)
259{
260 unsigned int val;
261 int ret;
262
263 ret = regmap_read(regmap, CPCAP_REG_VERSC1, &val);
264 if (ret) {
265 dev_err(dev, "Could not read revision\n");
266
267 return ret;
268 }
269
270 *revision = ((val >> 3) & 0x7) | ((val << 3) & 0x38);
271
272 return 0;
273}
274
275static inline int cpcap_get_vendor(struct device *dev,
276 struct regmap *regmap,
277 u16 *vendor)
278{
279 unsigned int val;
280 int ret;
281
282 ret = regmap_read(regmap, CPCAP_REG_VERSC1, &val);
283 if (ret) {
284 dev_err(dev, "Could not read vendor\n");
285
286 return ret;
287 }
288
289 *vendor = (val >> 6) & 0x7;
290
291 return 0;
292}