aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/intel_msic.c501
-rw-r--r--include/linux/mfd/intel_msic.h456
4 files changed, 967 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ac8bd4feb047..b01fbe27822d 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -757,6 +757,15 @@ config MFD_AAT2870_CORE
757 additional drivers must be enabled in order to use the 757 additional drivers must be enabled in order to use the
758 functionality of the device. 758 functionality of the device.
759 759
760config MFD_INTEL_MSIC
761 bool "Support for Intel MSIC"
762 depends on INTEL_SCU_IPC
763 select MFD_CORE
764 help
765 Select this option to enable access to Intel MSIC (Avatele
766 Passage) chip. This chip embeds audio, battery, GPIO, etc.
767 devices used in Intel Medfield platforms.
768
760endmenu 769endmenu
761endif 770endif
762 771
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c58020303d18..7d53a7c530c8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -102,3 +102,4 @@ obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
102obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o 102obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
103obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o 103obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
104obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o 104obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
105obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
new file mode 100644
index 000000000000..bd086b9e852e
--- /dev/null
+++ b/drivers/mfd/intel_msic.c
@@ -0,0 +1,501 @@
1/*
2 * Driver for Intel MSIC
3 *
4 * Copyright (C) 2011, Intel Corporation
5 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/gpio.h>
13#include <linux/module.h>
14#include <linux/mfd/core.h>
15#include <linux/mfd/intel_msic.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18
19#include <asm/intel_scu_ipc.h>
20
21#define MSIC_VENDOR(id) ((id >> 6) & 3)
22#define MSIC_VERSION(id) (id & 0x3f)
23#define MSIC_MAJOR(id) ('A' + ((id >> 3) & 7))
24#define MSIC_MINOR(id) (id & 7)
25
26/*
27 * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
28 * Since IRQ block starts from address 0x002 we need to substract that from
29 * the actual IRQ status register address.
30 */
31#define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
32#define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
33
34/*
35 * The SCU hardware has limitation of 16 bytes per read/write buffer on
36 * Medfield.
37 */
38#define SCU_IPC_RWBUF_LIMIT 16
39
40/**
41 * struct intel_msic - an MSIC MFD instance
42 * @pdev: pointer to the platform device
43 * @vendor: vendor ID
44 * @version: chip version
45 * @irq_base: base address of the mapped MSIC SRAM interrupt tree
46 */
47struct intel_msic {
48 struct platform_device *pdev;
49 unsigned vendor;
50 unsigned version;
51 void __iomem *irq_base;
52};
53
54static struct resource msic_touch_resources[] = {
55 {
56 .flags = IORESOURCE_IRQ,
57 },
58};
59
60static struct resource msic_adc_resources[] = {
61 {
62 .flags = IORESOURCE_IRQ,
63 },
64};
65
66static struct resource msic_battery_resources[] = {
67 {
68 .flags = IORESOURCE_IRQ,
69 },
70};
71
72static struct resource msic_gpio_resources[] = {
73 {
74 .flags = IORESOURCE_IRQ,
75 },
76};
77
78static struct resource msic_audio_resources[] = {
79 {
80 .name = "IRQ",
81 .flags = IORESOURCE_IRQ,
82 },
83 /*
84 * We will pass IRQ_BASE to the driver now but this can be removed
85 * when/if the driver starts to use intel_msic_irq_read().
86 */
87 {
88 .name = "IRQ_BASE",
89 .flags = IORESOURCE_MEM,
90 .start = MSIC_IRQ_STATUS_ACCDET,
91 .end = MSIC_IRQ_STATUS_ACCDET,
92 },
93};
94
95static struct resource msic_hdmi_resources[] = {
96 {
97 .flags = IORESOURCE_IRQ,
98 },
99};
100
101static struct resource msic_thermal_resources[] = {
102 {
103 .flags = IORESOURCE_IRQ,
104 },
105};
106
107static struct resource msic_power_btn_resources[] = {
108 {
109 .flags = IORESOURCE_IRQ,
110 },
111};
112
113static struct resource msic_ocd_resources[] = {
114 {
115 .flags = IORESOURCE_IRQ,
116 },
117};
118
119/*
120 * Devices that are part of the MSIC and are available via firmware
121 * populated SFI DEVS table.
122 */
123static struct mfd_cell msic_devs[] = {
124 [INTEL_MSIC_BLOCK_TOUCH] = {
125 .name = "msic_touch",
126 .num_resources = ARRAY_SIZE(msic_touch_resources),
127 .resources = msic_touch_resources,
128 },
129 [INTEL_MSIC_BLOCK_ADC] = {
130 .name = "msic_adc",
131 .num_resources = ARRAY_SIZE(msic_adc_resources),
132 .resources = msic_adc_resources,
133 },
134 [INTEL_MSIC_BLOCK_BATTERY] = {
135 .name = "msic_battery",
136 .num_resources = ARRAY_SIZE(msic_battery_resources),
137 .resources = msic_battery_resources,
138 },
139 [INTEL_MSIC_BLOCK_GPIO] = {
140 .name = "msic_gpio",
141 .num_resources = ARRAY_SIZE(msic_gpio_resources),
142 .resources = msic_gpio_resources,
143 },
144 [INTEL_MSIC_BLOCK_AUDIO] = {
145 .name = "msic_audio",
146 .num_resources = ARRAY_SIZE(msic_audio_resources),
147 .resources = msic_audio_resources,
148 },
149 [INTEL_MSIC_BLOCK_HDMI] = {
150 .name = "msic_hdmi",
151 .num_resources = ARRAY_SIZE(msic_hdmi_resources),
152 .resources = msic_hdmi_resources,
153 },
154 [INTEL_MSIC_BLOCK_THERMAL] = {
155 .name = "msic_thermal",
156 .num_resources = ARRAY_SIZE(msic_thermal_resources),
157 .resources = msic_thermal_resources,
158 },
159 [INTEL_MSIC_BLOCK_POWER_BTN] = {
160 .name = "msic_power_btn",
161 .num_resources = ARRAY_SIZE(msic_power_btn_resources),
162 .resources = msic_power_btn_resources,
163 },
164 [INTEL_MSIC_BLOCK_OCD] = {
165 .name = "msic_ocd",
166 .num_resources = ARRAY_SIZE(msic_ocd_resources),
167 .resources = msic_ocd_resources,
168 },
169};
170
171/*
172 * Other MSIC related devices which are not directly available via SFI DEVS
173 * table. These can be pseudo devices, regulators etc. which are needed for
174 * different purposes.
175 *
176 * These devices appear only after the MSIC driver itself is initialized so
177 * we can guarantee that the SCU IPC interface is ready.
178 */
179static struct mfd_cell msic_other_devs[] = {
180 /* Audio codec in the MSIC */
181 {
182 .id = -1,
183 .name = "sn95031",
184 },
185};
186
187/**
188 * intel_msic_reg_read - read a single MSIC register
189 * @reg: register to read
190 * @val: register value is placed here
191 *
192 * Read a single register from MSIC. Returns %0 on success and negative
193 * errno in case of failure.
194 *
195 * Function may sleep.
196 */
197int intel_msic_reg_read(unsigned short reg, u8 *val)
198{
199 return intel_scu_ipc_ioread8(reg, val);
200}
201EXPORT_SYMBOL_GPL(intel_msic_reg_read);
202
203/**
204 * intel_msic_reg_write - write a single MSIC register
205 * @reg: register to write
206 * @val: value to write to that register
207 *
208 * Write a single MSIC register. Returns 0 on success and negative
209 * errno in case of failure.
210 *
211 * Function may sleep.
212 */
213int intel_msic_reg_write(unsigned short reg, u8 val)
214{
215 return intel_scu_ipc_iowrite8(reg, val);
216}
217EXPORT_SYMBOL_GPL(intel_msic_reg_write);
218
219/**
220 * intel_msic_reg_update - update a single MSIC register
221 * @reg: register to update
222 * @val: value to write to the register
223 * @mask: specifies which of the bits are updated (%0 = don't update,
224 * %1 = update)
225 *
226 * Perform an update to a register @reg. @mask is used to specify which
227 * bits are updated. Returns %0 in case of success and negative errno in
228 * case of failure.
229 *
230 * Function may sleep.
231 */
232int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
233{
234 return intel_scu_ipc_update_register(reg, val, mask);
235}
236EXPORT_SYMBOL_GPL(intel_msic_reg_update);
237
238/**
239 * intel_msic_bulk_read - read an array of registers
240 * @reg: array of register addresses to read
241 * @buf: array where the read values are placed
242 * @count: number of registers to read
243 *
244 * Function reads @count registers from the MSIC using addresses passed in
245 * @reg. Read values are placed in @buf. Reads are performed atomically
246 * wrt. MSIC.
247 *
248 * Returns %0 in case of success and negative errno in case of failure.
249 *
250 * Function may sleep.
251 */
252int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
253{
254 if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
255 return -EINVAL;
256
257 return intel_scu_ipc_readv(reg, buf, count);
258}
259EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
260
261/**
262 * intel_msic_bulk_write - write an array of values to the MSIC registers
263 * @reg: array of registers to write
264 * @buf: values to write to each register
265 * @count: number of registers to write
266 *
267 * Function writes @count registers in @buf to MSIC. Writes are performed
268 * atomically wrt MSIC. Returns %0 in case of success and negative errno in
269 * case of failure.
270 *
271 * Function may sleep.
272 */
273int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
274{
275 if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
276 return -EINVAL;
277
278 return intel_scu_ipc_writev(reg, buf, count);
279}
280EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
281
282/**
283 * intel_msic_irq_read - read a register from an MSIC interrupt tree
284 * @msic: MSIC instance
285 * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
286 * %INTEL_MSIC_RESETIRQ2)
287 * @val: value of the register is placed here
288 *
289 * This function can be used by an MSIC subdevice interrupt handler to read
290 * a register value from the MSIC interrupt tree. In this way subdevice
291 * drivers don't have to map in the interrupt tree themselves but can just
292 * call this function instead.
293 *
294 * Function doesn't sleep and is callable from interrupt context.
295 *
296 * Returns %-EINVAL if @reg is outside of the allowed register region.
297 */
298int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
299{
300 if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
301 return -EINVAL;
302
303 *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
304 return 0;
305}
306EXPORT_SYMBOL_GPL(intel_msic_irq_read);
307
308static int __devinit intel_msic_init_devices(struct intel_msic *msic)
309{
310 struct platform_device *pdev = msic->pdev;
311 struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
312 int ret, i;
313
314 if (pdata->gpio) {
315 struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
316
317 cell->platform_data = pdata->gpio;
318 cell->pdata_size = sizeof(*pdata->gpio);
319 }
320
321 if (pdata->ocd) {
322 unsigned gpio = pdata->ocd->gpio;
323
324 ret = gpio_request_one(gpio, GPIOF_IN, "ocd_gpio");
325 if (ret) {
326 dev_err(&pdev->dev, "failed to register OCD GPIO\n");
327 return ret;
328 }
329
330 ret = gpio_to_irq(gpio);
331 if (ret < 0) {
332 dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
333 gpio_free(gpio);
334 return ret;
335 }
336
337 /* Update the IRQ number for the OCD */
338 pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
339 }
340
341 for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
342 if (!pdata->irq[i])
343 continue;
344
345 ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
346 pdata->irq[i]);
347 if (ret)
348 goto fail;
349 }
350
351 ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
352 ARRAY_SIZE(msic_other_devs), NULL, 0);
353 if (ret)
354 goto fail;
355
356 return 0;
357
358fail:
359 mfd_remove_devices(&pdev->dev);
360 if (pdata->ocd)
361 gpio_free(pdata->ocd->gpio);
362
363 return ret;
364}
365
366static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
367{
368 struct platform_device *pdev = msic->pdev;
369 struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
370
371 mfd_remove_devices(&pdev->dev);
372
373 if (pdata->ocd)
374 gpio_free(pdata->ocd->gpio);
375}
376
377static int __devinit intel_msic_probe(struct platform_device *pdev)
378{
379 struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
380 struct intel_msic *msic;
381 struct resource *res;
382 u8 id0, id1;
383 int ret;
384
385 if (!pdata) {
386 dev_err(&pdev->dev, "no platform data passed\n");
387 return -EINVAL;
388 }
389
390 /* First validate that we have an MSIC in place */
391 ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
392 if (ret) {
393 dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
394 return -ENXIO;
395 }
396
397 ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
398 if (ret) {
399 dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
400 return -ENXIO;
401 }
402
403 if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
404 dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
405 return -ENXIO;
406 }
407
408 msic = kzalloc(sizeof(*msic), GFP_KERNEL);
409 if (!msic)
410 return -ENOMEM;
411
412 msic->vendor = MSIC_VENDOR(id0);
413 msic->version = MSIC_VERSION(id0);
414 msic->pdev = pdev;
415
416 /*
417 * Map in the MSIC interrupt tree area in SRAM. This is exposed to
418 * the clients via intel_msic_irq_read().
419 */
420 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
421 if (!res) {
422 dev_err(&pdev->dev, "failed to get SRAM iomem resource\n");
423 ret = -ENODEV;
424 goto fail_free_msic;
425 }
426
427 res = request_mem_region(res->start, resource_size(res), pdev->name);
428 if (!res) {
429 ret = -EBUSY;
430 goto fail_free_msic;
431 }
432
433 msic->irq_base = ioremap_nocache(res->start, resource_size(res));
434 if (!msic->irq_base) {
435 dev_err(&pdev->dev, "failed to map SRAM memory\n");
436 ret = -ENOMEM;
437 goto fail_release_region;
438 }
439
440 platform_set_drvdata(pdev, msic);
441
442 ret = intel_msic_init_devices(msic);
443 if (ret) {
444 dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
445 goto fail_unmap_mem;
446 }
447
448 dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
449 MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
450 msic->vendor);
451
452 return 0;
453
454fail_unmap_mem:
455 iounmap(msic->irq_base);
456fail_release_region:
457 release_mem_region(res->start, resource_size(res));
458fail_free_msic:
459 kfree(msic);
460
461 return ret;
462}
463
464static int __devexit intel_msic_remove(struct platform_device *pdev)
465{
466 struct intel_msic *msic = platform_get_drvdata(pdev);
467 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
468
469 intel_msic_remove_devices(msic);
470 platform_set_drvdata(pdev, NULL);
471 iounmap(msic->irq_base);
472 release_mem_region(res->start, resource_size(res));
473 kfree(msic);
474
475 return 0;
476}
477
478static struct platform_driver intel_msic_driver = {
479 .probe = intel_msic_probe,
480 .remove = __devexit_p(intel_msic_remove),
481 .driver = {
482 .name = "intel_msic",
483 .owner = THIS_MODULE,
484 },
485};
486
487static int __init intel_msic_init(void)
488{
489 return platform_driver_register(&intel_msic_driver);
490}
491module_init(intel_msic_init);
492
493static void __exit intel_msic_exit(void)
494{
495 platform_driver_unregister(&intel_msic_driver);
496}
497module_exit(intel_msic_exit);
498
499MODULE_DESCRIPTION("Driver for Intel MSIC");
500MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
501MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/intel_msic.h b/include/linux/mfd/intel_msic.h
new file mode 100644
index 000000000000..439a7a617bc9
--- /dev/null
+++ b/include/linux/mfd/intel_msic.h
@@ -0,0 +1,456 @@
1/*
2 * include/linux/mfd/intel_msic.h - Core interface for Intel MSIC
3 *
4 * Copyright (C) 2011, Intel Corporation
5 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __LINUX_MFD_INTEL_MSIC_H__
13#define __LINUX_MFD_INTEL_MSIC_H__
14
15/* ID */
16#define INTEL_MSIC_ID0 0x000 /* RO */
17#define INTEL_MSIC_ID1 0x001 /* RO */
18
19/* IRQ */
20#define INTEL_MSIC_IRQLVL1 0x002
21#define INTEL_MSIC_ADC1INT 0x003
22#define INTEL_MSIC_CCINT 0x004
23#define INTEL_MSIC_PWRSRCINT 0x005
24#define INTEL_MSIC_PWRSRCINT1 0x006
25#define INTEL_MSIC_CHRINT 0x007
26#define INTEL_MSIC_CHRINT1 0x008
27#define INTEL_MSIC_RTCIRQ 0x009
28#define INTEL_MSIC_GPIO0LVIRQ 0x00a
29#define INTEL_MSIC_GPIO1LVIRQ 0x00b
30#define INTEL_MSIC_GPIOHVIRQ 0x00c
31#define INTEL_MSIC_VRINT 0x00d
32#define INTEL_MSIC_OCAUDIO 0x00e
33#define INTEL_MSIC_ACCDET 0x00f
34#define INTEL_MSIC_RESETIRQ1 0x010
35#define INTEL_MSIC_RESETIRQ2 0x011
36#define INTEL_MSIC_MADC1INT 0x012
37#define INTEL_MSIC_MCCINT 0x013
38#define INTEL_MSIC_MPWRSRCINT 0x014
39#define INTEL_MSIC_MPWRSRCINT1 0x015
40#define INTEL_MSIC_MCHRINT 0x016
41#define INTEL_MSIC_MCHRINT1 0x017
42#define INTEL_MSIC_RTCIRQMASK 0x018
43#define INTEL_MSIC_GPIO0LVIRQMASK 0x019
44#define INTEL_MSIC_GPIO1LVIRQMASK 0x01a
45#define INTEL_MSIC_GPIOHVIRQMASK 0x01b
46#define INTEL_MSIC_VRINTMASK 0x01c
47#define INTEL_MSIC_OCAUDIOMASK 0x01d
48#define INTEL_MSIC_ACCDETMASK 0x01e
49#define INTEL_MSIC_RESETIRQ1MASK 0x01f
50#define INTEL_MSIC_RESETIRQ2MASK 0x020
51#define INTEL_MSIC_IRQLVL1MSK 0x021
52#define INTEL_MSIC_PBCONFIG 0x03e
53#define INTEL_MSIC_PBSTATUS 0x03f /* RO */
54
55/* GPIO */
56#define INTEL_MSIC_GPIO0LV7CTLO 0x040
57#define INTEL_MSIC_GPIO0LV6CTLO 0x041
58#define INTEL_MSIC_GPIO0LV5CTLO 0x042
59#define INTEL_MSIC_GPIO0LV4CTLO 0x043
60#define INTEL_MSIC_GPIO0LV3CTLO 0x044
61#define INTEL_MSIC_GPIO0LV2CTLO 0x045
62#define INTEL_MSIC_GPIO0LV1CTLO 0x046
63#define INTEL_MSIC_GPIO0LV0CTLO 0x047
64#define INTEL_MSIC_GPIO1LV7CTLOS 0x048
65#define INTEL_MSIC_GPIO1LV6CTLO 0x049
66#define INTEL_MSIC_GPIO1LV5CTLO 0x04a
67#define INTEL_MSIC_GPIO1LV4CTLO 0x04b
68#define INTEL_MSIC_GPIO1LV3CTLO 0x04c
69#define INTEL_MSIC_GPIO1LV2CTLO 0x04d
70#define INTEL_MSIC_GPIO1LV1CTLO 0x04e
71#define INTEL_MSIC_GPIO1LV0CTLO 0x04f
72#define INTEL_MSIC_GPIO0LV7CTLI 0x050
73#define INTEL_MSIC_GPIO0LV6CTLI 0x051
74#define INTEL_MSIC_GPIO0LV5CTLI 0x052
75#define INTEL_MSIC_GPIO0LV4CTLI 0x053
76#define INTEL_MSIC_GPIO0LV3CTLI 0x054
77#define INTEL_MSIC_GPIO0LV2CTLI 0x055
78#define INTEL_MSIC_GPIO0LV1CTLI 0x056
79#define INTEL_MSIC_GPIO0LV0CTLI 0x057
80#define INTEL_MSIC_GPIO1LV7CTLIS 0x058
81#define INTEL_MSIC_GPIO1LV6CTLI 0x059
82#define INTEL_MSIC_GPIO1LV5CTLI 0x05a
83#define INTEL_MSIC_GPIO1LV4CTLI 0x05b
84#define INTEL_MSIC_GPIO1LV3CTLI 0x05c
85#define INTEL_MSIC_GPIO1LV2CTLI 0x05d
86#define INTEL_MSIC_GPIO1LV1CTLI 0x05e
87#define INTEL_MSIC_GPIO1LV0CTLI 0x05f
88#define INTEL_MSIC_PWM0CLKDIV1 0x061
89#define INTEL_MSIC_PWM0CLKDIV0 0x062
90#define INTEL_MSIC_PWM1CLKDIV1 0x063
91#define INTEL_MSIC_PWM1CLKDIV0 0x064
92#define INTEL_MSIC_PWM2CLKDIV1 0x065
93#define INTEL_MSIC_PWM2CLKDIV0 0x066
94#define INTEL_MSIC_PWM0DUTYCYCLE 0x067
95#define INTEL_MSIC_PWM1DUTYCYCLE 0x068
96#define INTEL_MSIC_PWM2DUTYCYCLE 0x069
97#define INTEL_MSIC_GPIO0HV3CTLO 0x06d
98#define INTEL_MSIC_GPIO0HV2CTLO 0x06e
99#define INTEL_MSIC_GPIO0HV1CTLO 0x06f
100#define INTEL_MSIC_GPIO0HV0CTLO 0x070
101#define INTEL_MSIC_GPIO1HV3CTLO 0x071
102#define INTEL_MSIC_GPIO1HV2CTLO 0x072
103#define INTEL_MSIC_GPIO1HV1CTLO 0x073
104#define INTEL_MSIC_GPIO1HV0CTLO 0x074
105#define INTEL_MSIC_GPIO0HV3CTLI 0x075
106#define INTEL_MSIC_GPIO0HV2CTLI 0x076
107#define INTEL_MSIC_GPIO0HV1CTLI 0x077
108#define INTEL_MSIC_GPIO0HV0CTLI 0x078
109#define INTEL_MSIC_GPIO1HV3CTLI 0x079
110#define INTEL_MSIC_GPIO1HV2CTLI 0x07a
111#define INTEL_MSIC_GPIO1HV1CTLI 0x07b
112#define INTEL_MSIC_GPIO1HV0CTLI 0x07c
113
114/* SVID */
115#define INTEL_MSIC_SVIDCTRL0 0x080
116#define INTEL_MSIC_SVIDCTRL1 0x081
117#define INTEL_MSIC_SVIDCTRL2 0x082
118#define INTEL_MSIC_SVIDTXLASTPKT3 0x083 /* RO */
119#define INTEL_MSIC_SVIDTXLASTPKT2 0x084 /* RO */
120#define INTEL_MSIC_SVIDTXLASTPKT1 0x085 /* RO */
121#define INTEL_MSIC_SVIDTXLASTPKT0 0x086 /* RO */
122#define INTEL_MSIC_SVIDPKTOUTBYTE3 0x087
123#define INTEL_MSIC_SVIDPKTOUTBYTE2 0x088
124#define INTEL_MSIC_SVIDPKTOUTBYTE1 0x089
125#define INTEL_MSIC_SVIDPKTOUTBYTE0 0x08a
126#define INTEL_MSIC_SVIDRXVPDEBUG1 0x08b
127#define INTEL_MSIC_SVIDRXVPDEBUG0 0x08c
128#define INTEL_MSIC_SVIDRXLASTPKT3 0x08d /* RO */
129#define INTEL_MSIC_SVIDRXLASTPKT2 0x08e /* RO */
130#define INTEL_MSIC_SVIDRXLASTPKT1 0x08f /* RO */
131#define INTEL_MSIC_SVIDRXLASTPKT0 0x090 /* RO */
132#define INTEL_MSIC_SVIDRXCHKSTATUS3 0x091 /* RO */
133#define INTEL_MSIC_SVIDRXCHKSTATUS2 0x092 /* RO */
134#define INTEL_MSIC_SVIDRXCHKSTATUS1 0x093 /* RO */
135#define INTEL_MSIC_SVIDRXCHKSTATUS0 0x094 /* RO */
136
137/* VREG */
138#define INTEL_MSIC_VCCLATCH 0x0c0
139#define INTEL_MSIC_VNNLATCH 0x0c1
140#define INTEL_MSIC_VCCCNT 0x0c2
141#define INTEL_MSIC_SMPSRAMP 0x0c3
142#define INTEL_MSIC_VNNCNT 0x0c4
143#define INTEL_MSIC_VNNAONCNT 0x0c5
144#define INTEL_MSIC_VCC122AONCNT 0x0c6
145#define INTEL_MSIC_V180AONCNT 0x0c7
146#define INTEL_MSIC_V500CNT 0x0c8
147#define INTEL_MSIC_VIHFCNT 0x0c9
148#define INTEL_MSIC_LDORAMP1 0x0ca
149#define INTEL_MSIC_LDORAMP2 0x0cb
150#define INTEL_MSIC_VCC108AONCNT 0x0cc
151#define INTEL_MSIC_VCC108ASCNT 0x0cd
152#define INTEL_MSIC_VCC108CNT 0x0ce
153#define INTEL_MSIC_VCCA100ASCNT 0x0cf
154#define INTEL_MSIC_VCCA100CNT 0x0d0
155#define INTEL_MSIC_VCC180AONCNT 0x0d1
156#define INTEL_MSIC_VCC180CNT 0x0d2
157#define INTEL_MSIC_VCC330CNT 0x0d3
158#define INTEL_MSIC_VUSB330CNT 0x0d4
159#define INTEL_MSIC_VCCSDIOCNT 0x0d5
160#define INTEL_MSIC_VPROG1CNT 0x0d6
161#define INTEL_MSIC_VPROG2CNT 0x0d7
162#define INTEL_MSIC_VEMMCSCNT 0x0d8
163#define INTEL_MSIC_VEMMC1CNT 0x0d9
164#define INTEL_MSIC_VEMMC2CNT 0x0da
165#define INTEL_MSIC_VAUDACNT 0x0db
166#define INTEL_MSIC_VHSPCNT 0x0dc
167#define INTEL_MSIC_VHSNCNT 0x0dd
168#define INTEL_MSIC_VHDMICNT 0x0de
169#define INTEL_MSIC_VOTGCNT 0x0df
170#define INTEL_MSIC_V1P35CNT 0x0e0
171#define INTEL_MSIC_V330AONCNT 0x0e1
172
173/* RESET */
174#define INTEL_MSIC_CHIPCNTRL 0x100 /* WO */
175#define INTEL_MSIC_ERCONFIG 0x101
176
177/* BURST */
178#define INTEL_MSIC_BATCURRENTLIMIT12 0x102
179#define INTEL_MSIC_BATTIMELIMIT12 0x103
180#define INTEL_MSIC_BATTIMELIMIT3 0x104
181#define INTEL_MSIC_BATTIMEDB 0x105
182#define INTEL_MSIC_BRSTCONFIGOUTPUTS 0x106
183#define INTEL_MSIC_BRSTCONFIGACTIONS 0x107
184#define INTEL_MSIC_BURSTCONTROLSTATUS 0x108
185
186/* RTC */
187#define INTEL_MSIC_RTCB1 0x140 /* RO */
188#define INTEL_MSIC_RTCB2 0x141 /* RO */
189#define INTEL_MSIC_RTCB3 0x142 /* RO */
190#define INTEL_MSIC_RTCB4 0x143 /* RO */
191#define INTEL_MSIC_RTCOB1 0x144
192#define INTEL_MSIC_RTCOB2 0x145
193#define INTEL_MSIC_RTCOB3 0x146
194#define INTEL_MSIC_RTCOB4 0x147
195#define INTEL_MSIC_RTCAB1 0x148
196#define INTEL_MSIC_RTCAB2 0x149
197#define INTEL_MSIC_RTCAB3 0x14a
198#define INTEL_MSIC_RTCAB4 0x14b
199#define INTEL_MSIC_RTCWAB1 0x14c
200#define INTEL_MSIC_RTCWAB2 0x14d
201#define INTEL_MSIC_RTCWAB3 0x14e
202#define INTEL_MSIC_RTCWAB4 0x14f
203#define INTEL_MSIC_RTCSC1 0x150
204#define INTEL_MSIC_RTCSC2 0x151
205#define INTEL_MSIC_RTCSC3 0x152
206#define INTEL_MSIC_RTCSC4 0x153
207#define INTEL_MSIC_RTCSTATUS 0x154 /* RO */
208#define INTEL_MSIC_RTCCONFIG1 0x155
209#define INTEL_MSIC_RTCCONFIG2 0x156
210
211/* CHARGER */
212#define INTEL_MSIC_BDTIMER 0x180
213#define INTEL_MSIC_BATTRMV 0x181
214#define INTEL_MSIC_VBUSDET 0x182
215#define INTEL_MSIC_VBUSDET1 0x183
216#define INTEL_MSIC_ADPHVDET 0x184
217#define INTEL_MSIC_ADPLVDET 0x185
218#define INTEL_MSIC_ADPDETDBDM 0x186
219#define INTEL_MSIC_LOWBATTDET 0x187
220#define INTEL_MSIC_CHRCTRL 0x188
221#define INTEL_MSIC_CHRCVOLTAGE 0x189
222#define INTEL_MSIC_CHRCCURRENT 0x18a
223#define INTEL_MSIC_SPCHARGER 0x18b
224#define INTEL_MSIC_CHRTTIME 0x18c
225#define INTEL_MSIC_CHRCTRL1 0x18d
226#define INTEL_MSIC_PWRSRCLMT 0x18e
227#define INTEL_MSIC_CHRSTWDT 0x18f
228#define INTEL_MSIC_WDTWRITE 0x190 /* WO */
229#define INTEL_MSIC_CHRSAFELMT 0x191
230#define INTEL_MSIC_SPWRSRCINT 0x192 /* RO */
231#define INTEL_MSIC_SPWRSRCINT1 0x193 /* RO */
232#define INTEL_MSIC_CHRLEDPWM 0x194
233#define INTEL_MSIC_CHRLEDCTRL 0x195
234
235/* ADC */
236#define INTEL_MSIC_ADC1CNTL1 0x1c0
237#define INTEL_MSIC_ADC1CNTL2 0x1c1
238#define INTEL_MSIC_ADC1CNTL3 0x1c2
239#define INTEL_MSIC_ADC1OFFSETH 0x1c3 /* RO */
240#define INTEL_MSIC_ADC1OFFSETL 0x1c4 /* RO */
241#define INTEL_MSIC_ADC1ADDR0 0x1c5
242#define INTEL_MSIC_ADC1ADDR1 0x1c6
243#define INTEL_MSIC_ADC1ADDR2 0x1c7
244#define INTEL_MSIC_ADC1ADDR3 0x1c8
245#define INTEL_MSIC_ADC1ADDR4 0x1c9
246#define INTEL_MSIC_ADC1ADDR5 0x1ca
247#define INTEL_MSIC_ADC1ADDR6 0x1cb
248#define INTEL_MSIC_ADC1ADDR7 0x1cc
249#define INTEL_MSIC_ADC1ADDR8 0x1cd
250#define INTEL_MSIC_ADC1ADDR9 0x1ce
251#define INTEL_MSIC_ADC1ADDR10 0x1cf
252#define INTEL_MSIC_ADC1ADDR11 0x1d0
253#define INTEL_MSIC_ADC1ADDR12 0x1d1
254#define INTEL_MSIC_ADC1ADDR13 0x1d2
255#define INTEL_MSIC_ADC1ADDR14 0x1d3
256#define INTEL_MSIC_ADC1SNS0H 0x1d4 /* RO */
257#define INTEL_MSIC_ADC1SNS0L 0x1d5 /* RO */
258#define INTEL_MSIC_ADC1SNS1H 0x1d6 /* RO */
259#define INTEL_MSIC_ADC1SNS1L 0x1d7 /* RO */
260#define INTEL_MSIC_ADC1SNS2H 0x1d8 /* RO */
261#define INTEL_MSIC_ADC1SNS2L 0x1d9 /* RO */
262#define INTEL_MSIC_ADC1SNS3H 0x1da /* RO */
263#define INTEL_MSIC_ADC1SNS3L 0x1db /* RO */
264#define INTEL_MSIC_ADC1SNS4H 0x1dc /* RO */
265#define INTEL_MSIC_ADC1SNS4L 0x1dd /* RO */
266#define INTEL_MSIC_ADC1SNS5H 0x1de /* RO */
267#define INTEL_MSIC_ADC1SNS5L 0x1df /* RO */
268#define INTEL_MSIC_ADC1SNS6H 0x1e0 /* RO */
269#define INTEL_MSIC_ADC1SNS6L 0x1e1 /* RO */
270#define INTEL_MSIC_ADC1SNS7H 0x1e2 /* RO */
271#define INTEL_MSIC_ADC1SNS7L 0x1e3 /* RO */
272#define INTEL_MSIC_ADC1SNS8H 0x1e4 /* RO */
273#define INTEL_MSIC_ADC1SNS8L 0x1e5 /* RO */
274#define INTEL_MSIC_ADC1SNS9H 0x1e6 /* RO */
275#define INTEL_MSIC_ADC1SNS9L 0x1e7 /* RO */
276#define INTEL_MSIC_ADC1SNS10H 0x1e8 /* RO */
277#define INTEL_MSIC_ADC1SNS10L 0x1e9 /* RO */
278#define INTEL_MSIC_ADC1SNS11H 0x1ea /* RO */
279#define INTEL_MSIC_ADC1SNS11L 0x1eb /* RO */
280#define INTEL_MSIC_ADC1SNS12H 0x1ec /* RO */
281#define INTEL_MSIC_ADC1SNS12L 0x1ed /* RO */
282#define INTEL_MSIC_ADC1SNS13H 0x1ee /* RO */
283#define INTEL_MSIC_ADC1SNS13L 0x1ef /* RO */
284#define INTEL_MSIC_ADC1SNS14H 0x1f0 /* RO */
285#define INTEL_MSIC_ADC1SNS14L 0x1f1 /* RO */
286#define INTEL_MSIC_ADC1BV0H 0x1f2 /* RO */
287#define INTEL_MSIC_ADC1BV0L 0x1f3 /* RO */
288#define INTEL_MSIC_ADC1BV1H 0x1f4 /* RO */
289#define INTEL_MSIC_ADC1BV1L 0x1f5 /* RO */
290#define INTEL_MSIC_ADC1BV2H 0x1f6 /* RO */
291#define INTEL_MSIC_ADC1BV2L 0x1f7 /* RO */
292#define INTEL_MSIC_ADC1BV3H 0x1f8 /* RO */
293#define INTEL_MSIC_ADC1BV3L 0x1f9 /* RO */
294#define INTEL_MSIC_ADC1BI0H 0x1fa /* RO */
295#define INTEL_MSIC_ADC1BI0L 0x1fb /* RO */
296#define INTEL_MSIC_ADC1BI1H 0x1fc /* RO */
297#define INTEL_MSIC_ADC1BI1L 0x1fd /* RO */
298#define INTEL_MSIC_ADC1BI2H 0x1fe /* RO */
299#define INTEL_MSIC_ADC1BI2L 0x1ff /* RO */
300#define INTEL_MSIC_ADC1BI3H 0x200 /* RO */
301#define INTEL_MSIC_ADC1BI3L 0x201 /* RO */
302#define INTEL_MSIC_CCCNTL 0x202
303#define INTEL_MSIC_CCOFFSETH 0x203 /* RO */
304#define INTEL_MSIC_CCOFFSETL 0x204 /* RO */
305#define INTEL_MSIC_CCADCHA 0x205 /* RO */
306#define INTEL_MSIC_CCADCLA 0x206 /* RO */
307
308/* AUDIO */
309#define INTEL_MSIC_AUDPLLCTRL 0x240
310#define INTEL_MSIC_DMICBUF0123 0x241
311#define INTEL_MSIC_DMICBUF45 0x242
312#define INTEL_MSIC_DMICGPO 0x244
313#define INTEL_MSIC_DMICMUX 0x245
314#define INTEL_MSIC_DMICCLK 0x246
315#define INTEL_MSIC_MICBIAS 0x247
316#define INTEL_MSIC_ADCCONFIG 0x248
317#define INTEL_MSIC_MICAMP1 0x249
318#define INTEL_MSIC_MICAMP2 0x24a
319#define INTEL_MSIC_NOISEMUX 0x24b
320#define INTEL_MSIC_AUDIOMUX12 0x24c
321#define INTEL_MSIC_AUDIOMUX34 0x24d
322#define INTEL_MSIC_AUDIOSINC 0x24e
323#define INTEL_MSIC_AUDIOTXEN 0x24f
324#define INTEL_MSIC_HSEPRXCTRL 0x250
325#define INTEL_MSIC_IHFRXCTRL 0x251
326#define INTEL_MSIC_VOICETXVOL 0x252
327#define INTEL_MSIC_SIDETONEVOL 0x253
328#define INTEL_MSIC_MUSICSHARVOL 0x254
329#define INTEL_MSIC_VOICETXCTRL 0x255
330#define INTEL_MSIC_HSMIXER 0x256
331#define INTEL_MSIC_DACCONFIG 0x257
332#define INTEL_MSIC_SOFTMUTE 0x258
333#define INTEL_MSIC_HSLVOLCTRL 0x259
334#define INTEL_MSIC_HSRVOLCTRL 0x25a
335#define INTEL_MSIC_IHFLVOLCTRL 0x25b
336#define INTEL_MSIC_IHFRVOLCTRL 0x25c
337#define INTEL_MSIC_DRIVEREN 0x25d
338#define INTEL_MSIC_LINEOUTCTRL 0x25e
339#define INTEL_MSIC_VIB1CTRL1 0x25f
340#define INTEL_MSIC_VIB1CTRL2 0x260
341#define INTEL_MSIC_VIB1CTRL3 0x261
342#define INTEL_MSIC_VIB1SPIPCM_1 0x262
343#define INTEL_MSIC_VIB1SPIPCM_2 0x263
344#define INTEL_MSIC_VIB1CTRL5 0x264
345#define INTEL_MSIC_VIB2CTRL1 0x265
346#define INTEL_MSIC_VIB2CTRL2 0x266
347#define INTEL_MSIC_VIB2CTRL3 0x267
348#define INTEL_MSIC_VIB2SPIPCM_1 0x268
349#define INTEL_MSIC_VIB2SPIPCM_2 0x269
350#define INTEL_MSIC_VIB2CTRL5 0x26a
351#define INTEL_MSIC_BTNCTRL1 0x26b
352#define INTEL_MSIC_BTNCTRL2 0x26c
353#define INTEL_MSIC_PCM1TXSLOT01 0x26d
354#define INTEL_MSIC_PCM1TXSLOT23 0x26e
355#define INTEL_MSIC_PCM1TXSLOT45 0x26f
356#define INTEL_MSIC_PCM1RXSLOT0123 0x270
357#define INTEL_MSIC_PCM1RXSLOT045 0x271
358#define INTEL_MSIC_PCM2TXSLOT01 0x272
359#define INTEL_MSIC_PCM2TXSLOT23 0x273
360#define INTEL_MSIC_PCM2TXSLOT45 0x274
361#define INTEL_MSIC_PCM2RXSLOT01 0x275
362#define INTEL_MSIC_PCM2RXSLOT23 0x276
363#define INTEL_MSIC_PCM2RXSLOT45 0x277
364#define INTEL_MSIC_PCM1CTRL1 0x278
365#define INTEL_MSIC_PCM1CTRL2 0x279
366#define INTEL_MSIC_PCM1CTRL3 0x27a
367#define INTEL_MSIC_PCM2CTRL1 0x27b
368#define INTEL_MSIC_PCM2CTRL2 0x27c
369
370/* HDMI */
371#define INTEL_MSIC_HDMIPUEN 0x280
372#define INTEL_MSIC_HDMISTATUS 0x281 /* RO */
373
374/* Physical address of the start of the MSIC interrupt tree in SRAM */
375#define INTEL_MSIC_IRQ_PHYS_BASE 0xffff7fc0
376
377/**
378 * struct intel_msic_gpio_pdata - platform data for the MSIC GPIO driver
379 * @gpio_base: base number for the GPIOs
380 */
381struct intel_msic_gpio_pdata {
382 unsigned gpio_base;
383};
384
385/**
386 * struct intel_msic_ocd_pdata - platform data for the MSIC OCD driver
387 * @gpio: GPIO number used for OCD interrupts
388 *
389 * The MSIC MFD driver converts @gpio into an IRQ number and passes it to
390 * the OCD driver as %IORESOURCE_IRQ.
391 */
392struct intel_msic_ocd_pdata {
393 unsigned gpio;
394};
395
396/* MSIC embedded blocks (subdevices) */
397enum intel_msic_block {
398 INTEL_MSIC_BLOCK_TOUCH,
399 INTEL_MSIC_BLOCK_ADC,
400 INTEL_MSIC_BLOCK_BATTERY,
401 INTEL_MSIC_BLOCK_GPIO,
402 INTEL_MSIC_BLOCK_AUDIO,
403 INTEL_MSIC_BLOCK_HDMI,
404 INTEL_MSIC_BLOCK_THERMAL,
405 INTEL_MSIC_BLOCK_POWER_BTN,
406 INTEL_MSIC_BLOCK_OCD,
407
408 INTEL_MSIC_BLOCK_LAST,
409};
410
411/**
412 * struct intel_msic_platform_data - platform data for the MSIC driver
413 * @irq: array of interrupt numbers, one per device. If @irq is set to %0
414 * for a given block, the corresponding platform device is not
415 * created. For devices which don't have an interrupt, use %0xff
416 * (this is same as in SFI spec).
417 * @gpio: platform data for the MSIC GPIO driver
418 * @ocd: platform data for the MSIC OCD driver
419 *
420 * Once the MSIC driver is initialized, the register interface is ready to
421 * use. All the platform devices for subdevices are created after the
422 * register interface is ready so that we can guarantee its availability to
423 * the subdevice drivers.
424 *
425 * Interrupt numbers are passed to the subdevices via %IORESOURCE_IRQ
426 * resources of the created platform device.
427 */
428struct intel_msic_platform_data {
429 int irq[INTEL_MSIC_BLOCK_LAST];
430 struct intel_msic_gpio_pdata *gpio;
431 struct intel_msic_ocd_pdata *ocd;
432};
433
434struct intel_msic;
435
436extern int intel_msic_reg_read(unsigned short reg, u8 *val);
437extern int intel_msic_reg_write(unsigned short reg, u8 val);
438extern int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask);
439extern int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count);
440extern int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count);
441
442/*
443 * pdev_to_intel_msic - gets an MSIC instance from the platform device
444 * @pdev: platform device pointer
445 *
446 * The client drivers need to have pointer to the MSIC instance if they
447 * want to call intel_msic_irq_read(). This macro can be used for
448 * convenience to get the MSIC pointer from @pdev where needed. This is
449 * _only_ valid for devices which are managed by the MSIC.
450 */
451#define pdev_to_intel_msic(pdev) (dev_get_drvdata(pdev->dev.parent))
452
453extern int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg,
454 u8 *val);
455
456#endif /* __LINUX_MFD_INTEL_MSIC_H__ */