Commit 18926edebcb82ca325abf843293801d4ff43436a
1 parent
9a28b8834c
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
iio: ti_am335x_adc: Allow to specify input line
The TSC part allows to specify the input lines. The IIO part assumes that it usues always the last few, that means if IIO has adc-channels set to 2 it will use channel 6 and 7. However it might make sense to use only 6. This patch changes the device property (which was introduced recently and was never in an official release) in a way that the user can specify which of the AIN lines should be used. In Addition to this, the name is now AINx where x is the channel number i.e. for AIN6 we would have 6. Prior this, it always started counting at 0 which is confusing. In addition to this, it also checks for correct step number during reading and does not rely on proper FIFO depth. Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Showing 3 changed files with 56 additions and 23 deletions Side-by-side Diff
arch/arm/boot/dts/am335x-evm.dts
drivers/iio/adc/ti_am335x_adc.c
... | ... | @@ -32,6 +32,8 @@ |
32 | 32 | struct tiadc_device { |
33 | 33 | struct ti_tscadc_dev *mfd_tscadc; |
34 | 34 | int channels; |
35 | + u8 channel_line[8]; | |
36 | + u8 channel_step[8]; | |
35 | 37 | }; |
36 | 38 | |
37 | 39 | static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) |
... | ... | @@ -57,7 +59,7 @@ |
57 | 59 | static void tiadc_step_config(struct tiadc_device *adc_dev) |
58 | 60 | { |
59 | 61 | unsigned int stepconfig; |
60 | - int i, channels = 0, steps; | |
62 | + int i, steps; | |
61 | 63 | u32 step_en; |
62 | 64 | |
63 | 65 | /* |
64 | 66 | |
65 | 67 | |
... | ... | @@ -71,16 +73,18 @@ |
71 | 73 | */ |
72 | 74 | |
73 | 75 | steps = TOTAL_STEPS - adc_dev->channels; |
74 | - channels = TOTAL_CHANNELS - adc_dev->channels; | |
75 | - | |
76 | 76 | stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; |
77 | 77 | |
78 | - for (i = steps; i < TOTAL_STEPS; i++) { | |
79 | - tiadc_writel(adc_dev, REG_STEPCONFIG(i), | |
80 | - stepconfig | STEPCONFIG_INP(channels)); | |
81 | - tiadc_writel(adc_dev, REG_STEPDELAY(i), | |
78 | + for (i = 0; i < adc_dev->channels; i++) { | |
79 | + int chan; | |
80 | + | |
81 | + chan = adc_dev->channel_line[i]; | |
82 | + tiadc_writel(adc_dev, REG_STEPCONFIG(steps), | |
83 | + stepconfig | STEPCONFIG_INP(chan)); | |
84 | + tiadc_writel(adc_dev, REG_STEPDELAY(steps), | |
82 | 85 | STEPCONFIG_OPENDLY); |
83 | - channels++; | |
86 | + adc_dev->channel_step[i] = steps; | |
87 | + steps++; | |
84 | 88 | } |
85 | 89 | step_en = get_adc_step_mask(adc_dev); |
86 | 90 | am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); |
87 | 91 | |
... | ... | @@ -115,9 +119,9 @@ |
115 | 119 | |
116 | 120 | chan->type = IIO_VOLTAGE; |
117 | 121 | chan->indexed = 1; |
118 | - chan->channel = i; | |
122 | + chan->channel = adc_dev->channel_line[i]; | |
119 | 123 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
120 | - chan->datasheet_name = chan_name_ain[i]; | |
124 | + chan->datasheet_name = chan_name_ain[chan->channel]; | |
121 | 125 | chan->scan_type.sign = 'u'; |
122 | 126 | chan->scan_type.realbits = 12; |
123 | 127 | chan->scan_type.storagebits = 32; |
... | ... | @@ -139,7 +143,8 @@ |
139 | 143 | { |
140 | 144 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
141 | 145 | int i; |
142 | - unsigned int fifo1count, readx1; | |
146 | + unsigned int fifo1count, read; | |
147 | + u32 step = UINT_MAX; | |
143 | 148 | |
144 | 149 | /* |
145 | 150 | * When the sub-system is first enabled, |
146 | 151 | |
... | ... | @@ -152,11 +157,20 @@ |
152 | 157 | * Hence we need to flush out this data. |
153 | 158 | */ |
154 | 159 | |
160 | + for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) { | |
161 | + if (chan->channel == adc_dev->channel_line[i]) { | |
162 | + step = adc_dev->channel_step[i]; | |
163 | + break; | |
164 | + } | |
165 | + } | |
166 | + if (WARN_ON_ONCE(step == UINT_MAX)) | |
167 | + return -EINVAL; | |
168 | + | |
155 | 169 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); |
156 | 170 | for (i = 0; i < fifo1count; i++) { |
157 | - readx1 = tiadc_readl(adc_dev, REG_FIFO1); | |
158 | - if (i == chan->channel) | |
159 | - *val = readx1 & 0xfff; | |
171 | + read = tiadc_readl(adc_dev, REG_FIFO1); | |
172 | + if (read >> 16 == step) | |
173 | + *val = read & 0xfff; | |
160 | 174 | } |
161 | 175 | am335x_tsc_se_update(adc_dev->mfd_tscadc); |
162 | 176 | |
163 | 177 | |
... | ... | @@ -172,8 +186,11 @@ |
172 | 186 | struct iio_dev *indio_dev; |
173 | 187 | struct tiadc_device *adc_dev; |
174 | 188 | struct device_node *node = pdev->dev.of_node; |
189 | + struct property *prop; | |
190 | + const __be32 *cur; | |
175 | 191 | int err; |
176 | - u32 val32; | |
192 | + u32 val; | |
193 | + int channels = 0; | |
177 | 194 | |
178 | 195 | if (!node) { |
179 | 196 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); |
... | ... | @@ -190,11 +207,11 @@ |
190 | 207 | |
191 | 208 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); |
192 | 209 | |
193 | - err = of_property_read_u32(node, | |
194 | - "ti,adc-channels", &val32); | |
195 | - if (err < 0) | |
196 | - goto err_free_device; | |
197 | - adc_dev->channels = val32; | |
210 | + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { | |
211 | + adc_dev->channel_line[channels] = val; | |
212 | + channels++; | |
213 | + } | |
214 | + adc_dev->channels = channels; | |
198 | 215 | |
199 | 216 | indio_dev->dev.parent = &pdev->dev; |
200 | 217 | indio_dev->name = dev_name(&pdev->dev); |
drivers/mfd/ti_am335x_tscadc.c
... | ... | @@ -91,9 +91,13 @@ |
91 | 91 | struct clk *clk; |
92 | 92 | struct device_node *node = pdev->dev.of_node; |
93 | 93 | struct mfd_cell *cell; |
94 | + struct property *prop; | |
95 | + const __be32 *cur; | |
96 | + u32 val; | |
94 | 97 | int err, ctrl; |
95 | 98 | int clk_value, clock_rate; |
96 | 99 | int tsc_wires = 0, adc_channels = 0, total_channels; |
100 | + int readouts = 0; | |
97 | 101 | |
98 | 102 | if (!pdev->dev.of_node) { |
99 | 103 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); |
100 | 104 | |
... | ... | @@ -102,10 +106,17 @@ |
102 | 106 | |
103 | 107 | node = of_get_child_by_name(pdev->dev.of_node, "tsc"); |
104 | 108 | of_property_read_u32(node, "ti,wires", &tsc_wires); |
109 | + of_property_read_u32(node, "ti,coordiante-readouts", &readouts); | |
105 | 110 | |
106 | 111 | node = of_get_child_by_name(pdev->dev.of_node, "adc"); |
107 | - of_property_read_u32(node, "ti,adc-channels", &adc_channels); | |
108 | - | |
112 | + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { | |
113 | + adc_channels++; | |
114 | + if (val > 7) { | |
115 | + dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n", | |
116 | + val); | |
117 | + return -EINVAL; | |
118 | + } | |
119 | + } | |
109 | 120 | total_channels = tsc_wires + adc_channels; |
110 | 121 | if (total_channels > 8) { |
111 | 122 | dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); |
... | ... | @@ -113,6 +124,11 @@ |
113 | 124 | } |
114 | 125 | if (total_channels == 0) { |
115 | 126 | dev_err(&pdev->dev, "Need atleast one channel.\n"); |
127 | + return -EINVAL; | |
128 | + } | |
129 | + | |
130 | + if (readouts * 2 + 2 + adc_channels > 16) { | |
131 | + dev_err(&pdev->dev, "Too many step configurations requested\n"); | |
116 | 132 | return -EINVAL; |
117 | 133 | } |
118 | 134 |