aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-12-12 12:52:57 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2012-01-08 18:37:35 -0500
commit876989d58658858f27a461f0b4b43fa750a208f4 (patch)
tree6ccd9e3d9cf0c190083a1dcb1d192c91ab616261
parentaf9081ae64b941d32239b947882cd59ba855c5db (diff)
mfd: Add device tree probe support for mc13xxx
This adds device tree probe support for mc13xxx mfd driver. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--Documentation/devicetree/bindings/mfd/mc13xxx.txt53
-rw-r--r--drivers/mfd/mc13xxx-core.c106
2 files changed, 128 insertions, 31 deletions
diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
new file mode 100644
index 000000000000..4ed46a610633
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
@@ -0,0 +1,53 @@
1* Freescale MC13783/MC13892 Power Management Integrated Circuit (PMIC)
2
3Required properties:
4- compatible : Should be "fsl,mc13783" or "fsl,mc13892"
5
6Optional properties:
7- fsl,mc13xxx-uses-adc : Indicate the ADC is being used
8- fsl,mc13xxx-uses-codec : Indicate the Audio Codec is being used
9- fsl,mc13xxx-uses-rtc : Indicate the RTC is being used
10- fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used
11
12Sub-nodes:
13- regulators : Contain the regulator nodes. The name of regulator node
14 is being used by mc13xxx regulator driver to find the correct relator
15 device.
16
17 The bindings details of individual regulator device can be found in:
18 Documentation/devicetree/bindings/regulator/regulator.txt
19
20Examples:
21
22ecspi@70010000 { /* ECSPI1 */
23 fsl,spi-num-chipselects = <2>;
24 cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
25 <&gpio3 25 0>; /* GPIO4_25 */
26 status = "okay";
27
28 pmic: mc13892@0 {
29 #address-cells = <1>;
30 #size-cells = <0>;
31 compatible = "fsl,mc13892";
32 spi-max-frequency = <6000000>;
33 reg = <0>;
34 interrupt-parent = <&gpio0>;
35 interrupts = <8>;
36
37 regulators {
38 sw1_reg: mc13892__sw1 {
39 regulator-min-microvolt = <600000>;
40 regulator-max-microvolt = <1375000>;
41 regulator-boot-on;
42 regulator-always-on;
43 };
44
45 sw2_reg: mc13892__sw2 {
46 regulator-min-microvolt = <900000>;
47 regulator-max-microvolt = <1850000>;
48 regulator-boot-on;
49 regulator-always-on;
50 };
51 };
52 };
53};
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index d0d3dfafba5c..7122386b4e3c 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -18,11 +18,15 @@
18#include <linux/spi/spi.h> 18#include <linux/spi/spi.h>
19#include <linux/mfd/core.h> 19#include <linux/mfd/core.h>
20#include <linux/mfd/mc13xxx.h> 20#include <linux/mfd/mc13xxx.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
23#include <linux/of_gpio.h>
21 24
22struct mc13xxx { 25struct mc13xxx {
23 struct spi_device *spidev; 26 struct spi_device *spidev;
24 struct mutex lock; 27 struct mutex lock;
25 int irq; 28 int irq;
29 int flags;
26 30
27 irq_handler_t irqhandler[MC13XXX_NUM_IRQ]; 31 irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
28 void *irqdata[MC13XXX_NUM_IRQ]; 32 void *irqdata[MC13XXX_NUM_IRQ];
@@ -550,10 +554,7 @@ static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
550 554
551int mc13xxx_get_flags(struct mc13xxx *mc13xxx) 555int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
552{ 556{
553 struct mc13xxx_platform_data *pdata = 557 return mc13xxx->flags;
554 dev_get_platdata(&mc13xxx->spidev->dev);
555
556 return pdata->flags;
557} 558}
558EXPORT_SYMBOL(mc13xxx_get_flags); 559EXPORT_SYMBOL(mc13xxx_get_flags);
559 560
@@ -696,17 +697,67 @@ static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
696 return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0); 697 return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
697} 698}
698 699
700#ifdef CONFIG_OF
701static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
702{
703 struct device_node *np = mc13xxx->spidev->dev.of_node;
704
705 if (!np)
706 return -ENODEV;
707
708 if (of_get_property(np, "fsl,mc13xxx-uses-adc", NULL))
709 mc13xxx->flags |= MC13XXX_USE_ADC;
710
711 if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL))
712 mc13xxx->flags |= MC13XXX_USE_CODEC;
713
714 if (of_get_property(np, "fsl,mc13xxx-uses-rtc", NULL))
715 mc13xxx->flags |= MC13XXX_USE_RTC;
716
717 if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL))
718 mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
719
720 return 0;
721}
722#else
723static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
724{
725 return -ENODEV;
726}
727#endif
728
729static const struct spi_device_id mc13xxx_device_id[] = {
730 {
731 .name = "mc13783",
732 .driver_data = MC13XXX_ID_MC13783,
733 }, {
734 .name = "mc13892",
735 .driver_data = MC13XXX_ID_MC13892,
736 }, {
737 /* sentinel */
738 }
739};
740MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
741
742static const struct of_device_id mc13xxx_dt_ids[] = {
743 { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
744 { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
745 { /* sentinel */ }
746};
747MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
748
699static int mc13xxx_probe(struct spi_device *spi) 749static int mc13xxx_probe(struct spi_device *spi)
700{ 750{
751 const struct of_device_id *of_id;
752 struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
701 struct mc13xxx *mc13xxx; 753 struct mc13xxx *mc13xxx;
702 struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); 754 struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
703 enum mc13xxx_id id; 755 enum mc13xxx_id id;
704 int ret; 756 int ret;
705 757
706 if (!pdata) { 758 of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
707 dev_err(&spi->dev, "invalid platform data\n"); 759 if (of_id)
708 return -EINVAL; 760 sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];
709 }
710 761
711 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); 762 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
712 if (!mc13xxx) 763 if (!mc13xxx)
@@ -749,28 +800,33 @@ err_revision:
749 800
750 mc13xxx_unlock(mc13xxx); 801 mc13xxx_unlock(mc13xxx);
751 802
752 if (pdata->flags & MC13XXX_USE_ADC) 803 if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
804 mc13xxx->flags = pdata->flags;
805
806 if (mc13xxx->flags & MC13XXX_USE_ADC)
753 mc13xxx_add_subdevice(mc13xxx, "%s-adc"); 807 mc13xxx_add_subdevice(mc13xxx, "%s-adc");
754 808
755 if (pdata->flags & MC13XXX_USE_CODEC) 809 if (mc13xxx->flags & MC13XXX_USE_CODEC)
756 mc13xxx_add_subdevice(mc13xxx, "%s-codec"); 810 mc13xxx_add_subdevice(mc13xxx, "%s-codec");
757 811
758 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", 812 if (mc13xxx->flags & MC13XXX_USE_RTC)
759 &pdata->regulators, sizeof(pdata->regulators));
760
761 if (pdata->flags & MC13XXX_USE_RTC)
762 mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); 813 mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
763 814
764 if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) 815 if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
765 mc13xxx_add_subdevice(mc13xxx, "%s-ts"); 816 mc13xxx_add_subdevice(mc13xxx, "%s-ts");
766 817
767 if (pdata->leds) 818 if (pdata) {
819 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
820 &pdata->regulators, sizeof(pdata->regulators));
768 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", 821 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
769 pdata->leds, sizeof(*pdata->leds)); 822 pdata->leds, sizeof(*pdata->leds));
770
771 if (pdata->buttons)
772 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton", 823 mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
773 pdata->buttons, sizeof(*pdata->buttons)); 824 pdata->buttons, sizeof(*pdata->buttons));
825 } else {
826 mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
827 mc13xxx_add_subdevice(mc13xxx, "%s-led");
828 mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
829 }
774 830
775 return 0; 831 return 0;
776} 832}
@@ -788,24 +844,12 @@ static int __devexit mc13xxx_remove(struct spi_device *spi)
788 return 0; 844 return 0;
789} 845}
790 846
791static const struct spi_device_id mc13xxx_device_id[] = {
792 {
793 .name = "mc13783",
794 .driver_data = MC13XXX_ID_MC13783,
795 }, {
796 .name = "mc13892",
797 .driver_data = MC13XXX_ID_MC13892,
798 }, {
799 /* sentinel */
800 }
801};
802MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
803
804static struct spi_driver mc13xxx_driver = { 847static struct spi_driver mc13xxx_driver = {
805 .id_table = mc13xxx_device_id, 848 .id_table = mc13xxx_device_id,
806 .driver = { 849 .driver = {
807 .name = "mc13xxx", 850 .name = "mc13xxx",
808 .owner = THIS_MODULE, 851 .owner = THIS_MODULE,
852 .of_match_table = mc13xxx_dt_ids,
809 }, 853 },
810 .probe = mc13xxx_probe, 854 .probe = mc13xxx_probe,
811 .remove = __devexit_p(mc13xxx_remove), 855 .remove = __devexit_p(mc13xxx_remove),