Re: [PATCH v2] iio: iadc: Qualcomm SPMI PMIC current ADC driver

From: Jonathan Cameron
Date: Sat Sep 27 2014 - 05:51:02 EST


On 25/09/14 20:21, Ivan T. Ivanov wrote:
> On Thu, 2014-09-25 at 17:02 +0100, Mark Rutland wrote:
>> On Thu, Sep 25, 2014 at 10:47:15AM +0100, Ivan T. Ivanov wrote:
>>> Hi Mark,
>>>
>>> On Wed, 2014-09-24 at 18:05 +0100, Mark Rutland wrote:
>>>> On Wed, Sep 24, 2014 at 05:00:42PM +0100, Ivan T. Ivanov wrote:
>>>>> On Wed, 2014-09-24 at 15:55 +0100, Mark Rutland wrote:
>>>>>> On Wed, Sep 24, 2014 at 02:58:23PM +0100, Ivan T. Ivanov wrote:
>>>>>>> The current ADC is peripheral of Qualcomm SPMI PMIC chips. It has
>>>>>>> 16 bits resolution and register space inside PMIC accessible across
>>>>>>> SPMI bus.
>>>>>>>
>>>>>>> The driver registers itself through IIO interface.
>>>>>>>
>>>>>>> Signed-off-by: Ivan T. Ivanov <iivanov@xxxxxxxxxx>
>>>>>>> ---
>>>>>>> Changes:
>>>>>>> - Fix Kconfig dependencies
>>>>>>> - Reword Kconfig help text
>>>>>>> - Replace IIO_CHAN_INFO_PROCESSED with IIO_CHAN_INFO_RAW and IIO_CHAN_INFO_SCALE,
>>>>>>> This enable client drivers to use microampers precission, instead miliamps.
>>>>>>> - Use const array for iio_schan_spec-fiers.
>>>>>>> - Fix spelling errors and adress review comments.
>>>>>>>
>>>>>>> Previous version:
>>>>>>> https://www.mail-archive.com/linux-kernel@xxxxxxxxxxxxxxx/msg728360.html
>>>>>>>
>>>>>>> .../devicetree/bindings/iio/adc/qcom,spmi-iadc.txt | 61 ++
>>>>>>> drivers/iio/adc/Kconfig | 11 +
>>>>>>> drivers/iio/adc/Makefile | 1 +
>>>>>>> drivers/iio/adc/qcom-spmi-iadc.c | 691 +++++++++++++++++++++
>>>>>>> 4 files changed, 764 insertions(+)
>>>>>>> create mode 100644 Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.txt
>>>>>>> create mode 100644 drivers/iio/adc/qcom-spmi-iadc.c
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.txt b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.txt
>>>>>>> new file mode 100644
>>>>>>> index 0000000..06e58b6
>>>>>>> --- /dev/null
>>>>>>> +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-iadc.txt
>>>>>>> @@ -0,0 +1,61 @@
>>>>>>> +Qualcomm's SPMI PMIC current ADC
>>>>>>> +
>>>>>>> +QPNP PMIC current ADC (IADC) provides interface to clients to read current.
>>>>>>> +A 16 bit ADC is used for current measurements.
>>>>>>> +
>>>>>>> +IADC node:
>>>>>>> +
>>>>>>> +- compatible:
>>>>>>> + Usage: required
>>>>>>> + Value type: <string>
>>>>>>> + Definition: Should contain "qcom,spmi-iadc".
>>>>>>> +
>>>>>>> +- reg:
>>>>>>> + Usage: required
>>>>>>> + Value type: <prop-encoded-array>
>>>>>>> + Definition: IADC base address and length in the SPMI PMIC register map.
>>>>>>> + TRIM_CNST_RDS register address and length(1)
>>>>>>
>>>>>> Are these two register regions? Please make the order explicit somehow
>>>>>> (either say first/second/third/etc, or use reg-names).
>>>>>
>>>>> Will make order explicit.
>>>>>
>>>>>>
>>>>>> Are they both part of the IADC, or is one part of an external/shared
>>>>>> component?
>>>>>
>>>>> I think that this is shared component.
>>>>
>>>> If it's not a portion of the ADC itself, then that should probably be
>>>> described as a separate unit, and referred to by phandle. What else is
>>>> that unit, and what else is said unit used by?
>>>
>>> Please read below.
>>
>> From my reading of the below, it's not clear we even need the TRIM
>> register values. If we do, and that's in a separate peripheral, that
>> register region should not be described directly in the IADC node. We
>> should have a reference to the other peripheral.
>
> Yes, we need them. Just to clarify, they are two TRIM registers. One
> is part of the IADC and the other is part of the BMS. If the one in
> IADC can not accumulate internal resistor deviation we have to read
> also one in BMS.
>
> Do we have any standard way for such kind inter-device register
> readings? Just note these devices are sub-functions of the PMIC,
> which are accessed from SoC over SPMI bus. Address ranges are
> not ioremmed or claimed by device drivers.
>
>>
>>>>>>> +- interrupts:
>>>>>>> + Usage: optional
>>>>>>> + Value type: <prop-encoded-array>
>>>>>>> + Definition: End of conversion interrupt number. If property is
>>>>>>> + missing driver will use polling to detect end of conversion
>>>>>>> + completion.
>>>>>>
>>>>>> Driver details shouldn't be in the binding. If the driver can poll,
>>>>>> that's good, but it should be dropped form this description.
>>>>>>
>>>>>
>>>>> Will remove driver details.
>>>>>
>>>>>> Is this the only interrupt?
>>>>>>
>>>>>
>>>>> Yes.
>>>>>
>>>>>> What do you mean be "End of conversion interrupt number"? Just describe
>>>>>> what the interrupt logically is from the PoV of the device -- interrupts
>>>>>> is a standard property so we don't need to be too explicit about the
>>>>>> type.
>>>>>
>>>>> Badly worded. Just, "End of conversion interrupt"?
>>>>
>>>> The part I didn't understand was what was meant by "End of conversion",
>>>> but dropping "number" is certainly better.
>>>
>>> It is clear now, right? End of ADC conversion.
>>
>> Sorry if I'm being thick here, but it's still somewhat confusing to me.
>> That's a consequence of me not being familiar with the HW more than
>> anything, I'm just missing simple details regarding the model of
>> operation, suchs as exactly what the "end of ADC conversion" entails.
>> There are a few things that could potentially mean depending on how the
>> HW was designed and intended to be used.
>>
>> Does the device periodically sample, convert some number of values
>> (possibly just 1), and trigger an interrupt to state that a buffer is
>> full / values are available? Or is the interrupt triggered for some
>> other reason?
>
> Interrupt is triggered after ADC convert analog signal to digital.
> Other details are irrelevant, I believe.
Often called a data ready interrupt. However, here it is per channel
so perhaps that description is confusing as well...
>
>>
>>>>>>> +- qcom,rsense:
>>>>>>> + Usage: optional
>>>>>>> + Value type: <u32>
>>>>>>> + Definition: External sense register value in Ohm. Defining this
>>>>>>> + propery will instruct ADC to use external ADC sense channel.
>>>>>>> + If property is not defined ADC will use internal sense channel.
>>>>>>
>>>>>> The latter two sentences sound like a driver description.
>>>>>>
>>>>>> What exactly is the difference between the internal and external
>>>>>> channels, and what exactly is the value in the sense register used for?
>>>>>
>>>>> Internal - when using chip build-in resistor
>>>>> External - when using off-chip resistor
>>>>
>>>> Would it be possible to use the internal channel when you have an
>>>> external resistor?
>>>>
>>>> If so, does the device have a channel per resistor, or can either
>>>> resistor be selected and applied to the single channel the device has?
>>>>
>>>
>>> They are two dedicated channels. Channel zero can only measure current
>>> over internal resistor (MOSFET). Channel two can only measure current
>>> over external resistor. This ADC is part of Battery Monitor System
>>> (BMS), i.e. it is not general purpose ADC. Based on DT files in
>>> codeaurora repository, only one of the channels is used, probably
>>> chosen at schematics design time. In practice, on the systems that
>>> use battery, there is always two resistors, and they are connected
>>> in sequence, just one of them should be zero. External resistor
>>> could be with higher quality, I suppose.
>>
>> I see. So there are two channels, but in all instances so far only one
>> is wired up to anything?
>
> I will say, Yes :-).
>
>>
>>>> This might be better worded as "external-registor-ohms".
>>>
>>> Ok.
>>>
>>>>
>>>>>
>>>>>>
>>>>>> The binding should describe the logical properties of the device rather
>>>>>> than the specific programming model details.
>>>>>>
>>>>>>> +
>>>>>>> +- qcom,rds-trim:
>>>>>>> + Usage: optional
>>>>>>> + Value type: <u32>
>>>>>>> + Definition: Calculate internal sense resistor value based TRIM_CNST_RDS,
>>>>>>> + IADC RDS and manufacturer.
>>>>>>> + 0: Read the IADC and SMBB trim register and apply the default
>>>>>>> + RSENSE if conditions are met.
>>>>>>> + 1: Read the IADC, SMBB trim register and manufacturer type and
>>>>>>> + apply the default RSENSE if conditions are met.
>>>>>>> + 2: Read the IADC, SMBB trim register and apply the default RSENSE
>>>>>>> + if conditions are met.
>>>>>>> + If property is not defined driver will use qcom,rsense value if
>>>>>>> + defined or internal sense resistor value trimmed into register.
>>>>>>
>>>>>> Having read this a few times, I still don't understand which I would use
>>>>>> and when.
>>>>>>
>>>>>> Which conditions need to be met in each of these cases?
>>>>>>
>>>>>> When does the manufacturer need to be taken into account and what does
>>>>>> it even mean for that to be the case? That sounds very much like a
>>>>>> driver detail rather than a HW property.
>>>>>>
>>>>>> Cases 0 and 2 seem to be the same, just with s/, / and /. I cannot
>>>>>> figure out the intended difference between the two.
>>>>>>
>>>>>> The last sentence is very much a driver description.
>>>>>
>>>>> Sorry. I have tried to make it better. Now looking again DT files
>>>>> in codeaurora tree I see that 0 is used in pm8941, 1 is used in
>>>>> pm8110 and 2 is used for pm8226. So I will remove this property
>>>>> and handle this inside driver based on chip version.
>>>>
>>>> Is this only to determine the value of the internal resistor?
>>>
>>> No. Ideal value for internal resistor is supposed to be 10Mohms.
>>> One register(8 bits) hold production time trimmed value, which represent
>>> difference against ideal value. It looks like some times real resistor
>>> values is too far from ideal and register can't hold the difference, so
>>> some additional hints are needed. In this case value trimmed to
>>> register into BMS peripheral.
>>
>> Ok. So from my PoV, the answer to my question is 'yes'. All that
>> information is used to determine the actual (rather than ideal) value of
>> the internal resistor.
>>
>> How variable is this value? Does it vary per board, only per SoC
>> version? Would the suggested "internal-resistor-ohms" property be
>> sufficient, or is the value too variable for that to work?
>
> It vary, per chip. Note this is PMIC chip accessed from SoC
> over SPMI bus.
>
>>
>>>> If that isn't probable in a standard way across all variations, would an
>>>> "internal-resistor-ohms" property be sufficient?
>>>>
>>>>>
>>>>>>
>>>>>>> +
>>>>>>> +Example:
>>>>>>> + /* IADC node */
>>>>>>> + pmic_iadc: iadc@3600 {
>>>>>>> + compatible = "qcom,spmi-iadc";
>>>>>>> + reg = <0x3600 0x100>,
>>>>>>> + <0x12f1 0x1>;
>>>>>>> + interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>;
>>>>>>> + qcom,rds-trim = <0>;
>>>>>>> + };
>>>>>>> +
>>>>>>> + /* IIO client node */
>>>>>>> + bat {
>>>>>>> + io-channels = <&pmic_iadc 0>;
>>>>>>> + io-channel-names = "iadc";
>>>>>>> + };
>>>>>>
>>>>>> Surely you need #iio-cells on the IADC node?
>>>>>
>>>>> Yes, I need to add it.
>>>>>
>>>>>>
>>>>>> Given the client seems to pass a specifier value, does this have
>>>>>> multiple channels, or only a single channel?
>>>>>
>>>>> Driver register only one IIO channel, so #io-channel-cells
>>>>> should be <0>.
>>>>
>>>> Ok. Regardless of what the driver does, does the hardware have
>>>> multi-channel capability?
>>>
>>> Strictly speaking, yes. But I don't see how both of them could
>>> used at the same time in practice.
>>
>> Even if that is the case, sure we can support #iio-cells = <1> and refer
>> to the channels as you numbered them above (zero for internal, one for
>> external)?
>
> Ok, will rework it.
>
> Thank you,
> Ivan
>
>>
>> Mark.
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/