aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Reilly <marc@cpdesign.com.au>2012-04-01 02:41:38 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-01 06:35:40 -0400
commita0c7c1d48ea9f53c67c79eda498bb8eda1422748 (patch)
treeb54f9495379ff485bcc63650be9687a69d3e55c4
parent91b5e741184ea9836cd7d7509e4f9b6eefa27df2 (diff)
mfd: Move the mc13xxx-core spi specific code into a separate module
All spi specific code is moved into a new module. The mc13xxx struct moves to a new local include file by necessity. A new config choice selects the SPI bus type support and by default is value of SPI_MASTER to remain compatible with existing configs. Signed-off-by: Marc Reilly <marc@cpdesign.com.au> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig17
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/mc13xxx-core.c148
-rw-r--r--drivers/mfd/mc13xxx-spi.c140
-rw-r--r--drivers/mfd/mc13xxx.h45
5 files changed, 204 insertions, 147 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 411a61a99404..9c8294c26efb 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -600,14 +600,23 @@ config MFD_MC13XXX
600 depends on SPI_MASTER 600 depends on SPI_MASTER
601 select MFD_CORE 601 select MFD_CORE
602 select MFD_MC13783 602 select MFD_MC13783
603 select REGMAP_SPI
604 help 603 help
605 Support for the Freescale (Atlas) PMIC and audio CODECs 604 Enable support for the Freescale MC13783 and MC13892 PMICs.
606 MC13783 and MC13892. 605 This driver provides common support for accessing the device,
607 This driver provides common support for accessing the device,
608 additional drivers must be enabled in order to use the 606 additional drivers must be enabled in order to use the
609 functionality of the device. 607 functionality of the device.
610 608
609if MFD_MC13XXX
610
611config MFD_MC13XXX_SPI
612 tristate "MC13xxx SPI interface" if SPI_MASTER
613 default SPI_MASTER
614 select REGMAP_SPI
615 help
616 Select this if your MC13xxx is connected via an SPI bus.
617
618endif
619
611config ABX500_CORE 620config ABX500_CORE
612 bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" 621 bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
613 default y if ARCH_U300 || ARCH_U8500 622 default y if ARCH_U300 || ARCH_U8500
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c4500c35d5ba..7ce5b5c15dee 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
54obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o 54obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
55 55
56obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o 56obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
57obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
57 58
58obj-$(CONFIG_MFD_CORE) += mfd-core.o 59obj-$(CONFIG_MFD_CORE) += mfd-core.o
59 60
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index d761a2e54b98..13a32b795615 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -15,36 +15,13 @@
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/spi/spi.h>
19#include <linux/mfd/core.h> 18#include <linux/mfd/core.h>
20#include <linux/mfd/mc13xxx.h> 19#include <linux/mfd/mc13xxx.h>
21#include <linux/of.h> 20#include <linux/of.h>
22#include <linux/of_device.h> 21#include <linux/of_device.h>
23#include <linux/of_gpio.h> 22#include <linux/of_gpio.h>
24#include <linux/regmap.h>
25#include <linux/err.h>
26 23
27enum mc13xxx_id { 24#include "mc13xxx.h"
28 MC13XXX_ID_MC13783,
29 MC13XXX_ID_MC13892,
30 MC13XXX_ID_INVALID,
31};
32
33struct mc13xxx {
34 struct regmap *regmap;
35
36 struct device *dev;
37 enum mc13xxx_id ictype;
38
39 struct mutex lock;
40 int irq;
41 int flags;
42
43 irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
44 void *irqdata[MC13XXX_NUM_IRQ];
45
46 int adcflags;
47};
48 25
49#define MC13XXX_IRQSTAT0 0 26#define MC13XXX_IRQSTAT0 0
50#define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0) 27#define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0)
@@ -151,8 +128,6 @@ struct mc13xxx {
151 128
152#define MC13XXX_ADC2 45 129#define MC13XXX_ADC2 45
153 130
154#define MC13XXX_NUMREGS 0x3f
155
156void mc13xxx_lock(struct mc13xxx *mc13xxx) 131void mc13xxx_lock(struct mc13xxx *mc13xxx)
157{ 132{
158 if (!mutex_trylock(&mc13xxx->lock)) { 133 if (!mutex_trylock(&mc13xxx->lock)) {
@@ -674,90 +649,7 @@ static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
674} 649}
675#endif 650#endif
676 651
677static const struct spi_device_id mc13xxx_device_id[] = { 652int mc13xxx_common_init(struct mc13xxx *mc13xxx,
678 {
679 .name = "mc13783",
680 .driver_data = MC13XXX_ID_MC13783,
681 }, {
682 .name = "mc13892",
683 .driver_data = MC13XXX_ID_MC13892,
684 }, {
685 /* sentinel */
686 }
687};
688MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
689
690static const struct of_device_id mc13xxx_dt_ids[] = {
691 { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
692 { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
693 { /* sentinel */ }
694};
695MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
696
697static struct regmap_config mc13xxx_regmap_spi_config = {
698 .reg_bits = 7,
699 .pad_bits = 1,
700 .val_bits = 24,
701
702 .max_register = MC13XXX_NUMREGS,
703
704 .cache_type = REGCACHE_NONE,
705};
706
707static int mc13xxx_common_init(struct mc13xxx *mc13xxx,
708 struct mc13xxx_platform_data *pdata, int irq);
709
710static void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx);
711
712static int mc13xxx_spi_probe(struct spi_device *spi)
713{
714 const struct of_device_id *of_id;
715 struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
716 struct mc13xxx *mc13xxx;
717 struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
718 int ret;
719
720 of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
721 if (of_id)
722 sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];
723
724 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
725 if (!mc13xxx)
726 return -ENOMEM;
727
728 dev_set_drvdata(&spi->dev, mc13xxx);
729 spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
730 spi->bits_per_word = 32;
731
732 mc13xxx->dev = &spi->dev;
733 mutex_init(&mc13xxx->lock);
734
735 mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config);
736 if (IS_ERR(mc13xxx->regmap)) {
737 ret = PTR_ERR(mc13xxx->regmap);
738 dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
739 ret);
740 dev_set_drvdata(&spi->dev, NULL);
741 kfree(mc13xxx);
742 return ret;
743 }
744
745 ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq);
746
747 if (ret) {
748 dev_set_drvdata(&spi->dev, NULL);
749 } else {
750 const struct spi_device_id *devid =
751 spi_get_device_id(spi);
752 if (!devid || devid->driver_data != mc13xxx->ictype)
753 dev_warn(mc13xxx->dev,
754 "device id doesn't match auto detection!\n");
755 }
756
757 return ret;
758}
759
760static int mc13xxx_common_init(struct mc13xxx *mc13xxx,
761 struct mc13xxx_platform_data *pdata, int irq) 653 struct mc13xxx_platform_data *pdata, int irq)
762{ 654{
763 int ret; 655 int ret;
@@ -823,17 +715,9 @@ err_revision:
823 715
824 return 0; 716 return 0;
825} 717}
718EXPORT_SYMBOL_GPL(mc13xxx_common_init);
826 719
827static int __devexit mc13xxx_spi_remove(struct spi_device *spi) 720void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx)
828{
829 struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);
830
831 mc13xxx_common_cleanup(mc13xxx);
832
833 return 0;
834}
835
836static void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx)
837{ 721{
838 free_irq(mc13xxx->irq, mc13xxx); 722 free_irq(mc13xxx->irq, mc13xxx);
839 723
@@ -843,29 +727,7 @@ static void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx)
843 727
844 kfree(mc13xxx); 728 kfree(mc13xxx);
845} 729}
846 730EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup);
847static struct spi_driver mc13xxx_spi_driver = {
848 .id_table = mc13xxx_device_id,
849 .driver = {
850 .name = "mc13xxx",
851 .owner = THIS_MODULE,
852 .of_match_table = mc13xxx_dt_ids,
853 },
854 .probe = mc13xxx_spi_probe,
855 .remove = __devexit_p(mc13xxx_spi_remove),
856};
857
858static int __init mc13xxx_init(void)
859{
860 return spi_register_driver(&mc13xxx_spi_driver);
861}
862subsys_initcall(mc13xxx_init);
863
864static void __exit mc13xxx_exit(void)
865{
866 spi_unregister_driver(&mc13xxx_spi_driver);
867}
868module_exit(mc13xxx_exit);
869 731
870MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC"); 732MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC");
871MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); 733MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
new file mode 100644
index 000000000000..3fcdab3eb8eb
--- /dev/null
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright 2009-2010 Pengutronix
3 * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
4 *
5 * loosely based on an earlier driver that has
6 * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
7 *
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License version 2 as published by the
10 * Free Software Foundation.
11 */
12
13#include <linux/slab.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/mutex.h>
17#include <linux/interrupt.h>
18#include <linux/mfd/core.h>
19#include <linux/mfd/mc13xxx.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/of_gpio.h>
23#include <linux/err.h>
24#include <linux/spi/spi.h>
25
26#include "mc13xxx.h"
27
28static const struct spi_device_id mc13xxx_device_id[] = {
29 {
30 .name = "mc13783",
31 .driver_data = MC13XXX_ID_MC13783,
32 }, {
33 .name = "mc13892",
34 .driver_data = MC13XXX_ID_MC13892,
35 }, {
36 /* sentinel */
37 }
38};
39MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
40
41static const struct of_device_id mc13xxx_dt_ids[] = {
42 { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
43 { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
44 { /* sentinel */ }
45};
46MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
47
48static struct regmap_config mc13xxx_regmap_spi_config = {
49 .reg_bits = 7,
50 .pad_bits = 1,
51 .val_bits = 24,
52
53 .max_register = MC13XXX_NUMREGS,
54
55 .cache_type = REGCACHE_NONE,
56};
57
58static int mc13xxx_spi_probe(struct spi_device *spi)
59{
60 const struct of_device_id *of_id;
61 struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
62 struct mc13xxx *mc13xxx;
63 struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
64 int ret;
65
66 of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
67 if (of_id)
68 sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];
69
70 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
71 if (!mc13xxx)
72 return -ENOMEM;
73
74 dev_set_drvdata(&spi->dev, mc13xxx);
75 spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
76 spi->bits_per_word = 32;
77
78 mc13xxx->dev = &spi->dev;
79 mutex_init(&mc13xxx->lock);
80
81 mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config);
82 if (IS_ERR(mc13xxx->regmap)) {
83 ret = PTR_ERR(mc13xxx->regmap);
84 dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
85 ret);
86 dev_set_drvdata(&spi->dev, NULL);
87 kfree(mc13xxx);
88 return ret;
89 }
90
91 ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq);
92
93 if (ret) {
94 dev_set_drvdata(&spi->dev, NULL);
95 } else {
96 const struct spi_device_id *devid =
97 spi_get_device_id(spi);
98 if (!devid || devid->driver_data != mc13xxx->ictype)
99 dev_warn(mc13xxx->dev,
100 "device id doesn't match auto detection!\n");
101 }
102
103 return ret;
104}
105
106static int __devexit mc13xxx_spi_remove(struct spi_device *spi)
107{
108 struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);
109
110 mc13xxx_common_cleanup(mc13xxx);
111
112 return 0;
113}
114
115static struct spi_driver mc13xxx_spi_driver = {
116 .id_table = mc13xxx_device_id,
117 .driver = {
118 .name = "mc13xxx",
119 .owner = THIS_MODULE,
120 .of_match_table = mc13xxx_dt_ids,
121 },
122 .probe = mc13xxx_spi_probe,
123 .remove = __devexit_p(mc13xxx_spi_remove),
124};
125
126static int __init mc13xxx_init(void)
127{
128 return spi_register_driver(&mc13xxx_spi_driver);
129}
130subsys_initcall(mc13xxx_init);
131
132static void __exit mc13xxx_exit(void)
133{
134 spi_unregister_driver(&mc13xxx_spi_driver);
135}
136module_exit(mc13xxx_exit);
137
138MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC");
139MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
140MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h
new file mode 100644
index 000000000000..bbba06feea06
--- /dev/null
+++ b/drivers/mfd/mc13xxx.h
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2012 Creative Product Design
3 * Marc Reilly <marc@cpdesign.com.au>
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 */
9#ifndef __DRIVERS_MFD_MC13XXX_H
10#define __DRIVERS_MFD_MC13XXX_H
11
12#include <linux/mutex.h>
13#include <linux/regmap.h>
14#include <linux/mfd/mc13xxx.h>
15
16enum mc13xxx_id {
17 MC13XXX_ID_MC13783,
18 MC13XXX_ID_MC13892,
19 MC13XXX_ID_INVALID,
20};
21
22#define MC13XXX_NUMREGS 0x3f
23
24struct mc13xxx {
25 struct regmap *regmap;
26
27 struct device *dev;
28 enum mc13xxx_id ictype;
29
30 struct mutex lock;
31 int irq;
32 int flags;
33
34 irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
35 void *irqdata[MC13XXX_NUM_IRQ];
36
37 int adcflags;
38};
39
40int mc13xxx_common_init(struct mc13xxx *mc13xxx,
41 struct mc13xxx_platform_data *pdata, int irq);
42
43void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx);
44
45#endif /* __DRIVERS_MFD_MC13XXX_H */