aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Reichel <sre@debian.org>2014-03-15 21:43:26 -0400
committerLee Jones <lee.jones@linaro.org>2014-03-18 04:13:23 -0400
commit2f39b70fef194a54c9decd8687bb05d576afebe5 (patch)
treea2a808796c150d93fbbb8c5f246bb7282d630670
parente7f22b75167d8b8a4d4c67d12b026a746aec05f6 (diff)
mfd: twl4030-madc: Add DT support and convert to IIO framework
This converts twl4030-madc module to use the Industrial IO ADC framework and adds device tree support. Signed-off-by: Sebastian Reichel <sre@debian.org> Tested-by: Marek Belisko <marek@goldelico.com> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/mfd/twl4030-madc.c127
1 files changed, 116 insertions, 11 deletions
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 54585617ab51..93ef91229cd3 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -47,11 +47,14 @@
47#include <linux/gfp.h> 47#include <linux/gfp.h>
48#include <linux/err.h> 48#include <linux/err.h>
49 49
50#include <linux/iio/iio.h>
51
50/* 52/*
51 * struct twl4030_madc_data - a container for madc info 53 * struct twl4030_madc_data - a container for madc info
52 * @dev - pointer to device structure for madc 54 * @dev - pointer to device structure for madc
53 * @lock - mutex protecting this data structure 55 * @lock - mutex protecting this data structure
54 * @requests - Array of request struct corresponding to SW1, SW2 and RT 56 * @requests - Array of request struct corresponding to SW1, SW2 and RT
57 * @use_second_irq - IRQ selection (main or co-processor)
55 * @imr - Interrupt mask register of MADC 58 * @imr - Interrupt mask register of MADC
56 * @isr - Interrupt status register of MADC 59 * @isr - Interrupt status register of MADC
57 */ 60 */
@@ -59,10 +62,71 @@ struct twl4030_madc_data {
59 struct device *dev; 62 struct device *dev;
60 struct mutex lock; /* mutex protecting this data structure */ 63 struct mutex lock; /* mutex protecting this data structure */
61 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS]; 64 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
65 bool use_second_irq;
62 int imr; 66 int imr;
63 int isr; 67 int isr;
64}; 68};
65 69
70static int twl4030_madc_read(struct iio_dev *iio_dev,
71 const struct iio_chan_spec *chan,
72 int *val, int *val2, long mask)
73{
74 struct twl4030_madc_data *madc = iio_priv(iio_dev);
75 struct twl4030_madc_request req;
76 int ret;
77
78 req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1;
79
80 req.channels = BIT(chan->channel);
81 req.active = false;
82 req.func_cb = NULL;
83 req.type = TWL4030_MADC_WAIT;
84 req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
85 req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
86
87 ret = twl4030_madc_conversion(&req);
88 if (ret < 0)
89 return ret;
90
91 *val = req.rbuf[chan->channel];
92
93 return IIO_VAL_INT;
94}
95
96static const struct iio_info twl4030_madc_iio_info = {
97 .read_raw = &twl4030_madc_read,
98 .driver_module = THIS_MODULE,
99};
100
101#define TWL4030_ADC_CHANNEL(_channel, _type, _name) { \
102 .type = _type, \
103 .channel = _channel, \
104 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
105 BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
106 BIT(IIO_CHAN_INFO_PROCESSED), \
107 .datasheet_name = _name, \
108 .indexed = 1, \
109}
110
111static const struct iio_chan_spec twl4030_madc_iio_channels[] = {
112 TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"),
113 TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"),
114 TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"),
115 TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"),
116 TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"),
117 TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"),
118 TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"),
119 TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"),
120 TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"),
121 TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"),
122 TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"),
123 TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"),
124 TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"),
125 TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"),
126 TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"),
127 TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"),
128};
129
66static struct twl4030_madc_data *twl4030_madc; 130static struct twl4030_madc_data *twl4030_madc;
67 131
68struct twl4030_prescale_divider_ratios { 132struct twl4030_prescale_divider_ratios {
@@ -702,28 +766,49 @@ static int twl4030_madc_probe(struct platform_device *pdev)
702{ 766{
703 struct twl4030_madc_data *madc; 767 struct twl4030_madc_data *madc;
704 struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev); 768 struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
769 struct device_node *np = pdev->dev.of_node;
705 int irq, ret; 770 int irq, ret;
706 u8 regval; 771 u8 regval;
772 struct iio_dev *iio_dev = NULL;
707 773
708 if (!pdata) { 774 if (!pdata && !np) {
709 dev_err(&pdev->dev, "platform_data not available\n"); 775 dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
710 return -EINVAL; 776 return -EINVAL;
711 } 777 }
712 madc = devm_kzalloc(&pdev->dev, sizeof(*madc), GFP_KERNEL); 778
713 if (!madc) 779 iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc));
780 if (!iio_dev) {
781 dev_err(&pdev->dev, "failed allocating iio device\n");
714 return -ENOMEM; 782 return -ENOMEM;
783 }
715 784
785 madc = iio_priv(iio_dev);
716 madc->dev = &pdev->dev; 786 madc->dev = &pdev->dev;
717 787
788 iio_dev->name = dev_name(&pdev->dev);
789 iio_dev->dev.parent = &pdev->dev;
790 iio_dev->dev.of_node = pdev->dev.of_node;
791 iio_dev->info = &twl4030_madc_iio_info;
792 iio_dev->modes = INDIO_DIRECT_MODE;
793 iio_dev->channels = twl4030_madc_iio_channels;
794 iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels);
795
718 /* 796 /*
719 * Phoenix provides 2 interrupt lines. The first one is connected to 797 * Phoenix provides 2 interrupt lines. The first one is connected to
720 * the OMAP. The other one can be connected to the other processor such 798 * the OMAP. The other one can be connected to the other processor such
721 * as modem. Hence two separate ISR and IMR registers. 799 * as modem. Hence two separate ISR and IMR registers.
722 */ 800 */
723 madc->imr = (pdata->irq_line == 1) ? 801 if (pdata)
724 TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2; 802 madc->use_second_irq = (pdata->irq_line != 1);
725 madc->isr = (pdata->irq_line == 1) ? 803 else
726 TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2; 804 madc->use_second_irq = of_property_read_bool(np,
805 "ti,system-uses-second-madc-irq");
806
807 madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
808 TWL4030_MADC_IMR1;
809 madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 :
810 TWL4030_MADC_ISR1;
811
727 ret = twl4030_madc_set_power(madc, 1); 812 ret = twl4030_madc_set_power(madc, 1);
728 if (ret < 0) 813 if (ret < 0)
729 return ret; 814 return ret;
@@ -768,7 +853,7 @@ static int twl4030_madc_probe(struct platform_device *pdev)
768 } 853 }
769 } 854 }
770 855
771 platform_set_drvdata(pdev, madc); 856 platform_set_drvdata(pdev, iio_dev);
772 mutex_init(&madc->lock); 857 mutex_init(&madc->lock);
773 858
774 irq = platform_get_irq(pdev, 0); 859 irq = platform_get_irq(pdev, 0);
@@ -776,11 +861,19 @@ static int twl4030_madc_probe(struct platform_device *pdev)
776 twl4030_madc_threaded_irq_handler, 861 twl4030_madc_threaded_irq_handler,
777 IRQF_TRIGGER_RISING, "twl4030_madc", madc); 862 IRQF_TRIGGER_RISING, "twl4030_madc", madc);
778 if (ret) { 863 if (ret) {
779 dev_dbg(&pdev->dev, "could not request irq\n"); 864 dev_err(&pdev->dev, "could not request irq\n");
780 goto err_i2c; 865 goto err_i2c;
781 } 866 }
782 twl4030_madc = madc; 867 twl4030_madc = madc;
868
869 ret = iio_device_register(iio_dev);
870 if (ret) {
871 dev_err(&pdev->dev, "could not register iio device\n");
872 goto err_i2c;
873 }
874