[RFC PATCH v1] EP93XX: Add ADC support

Ryan Mallon ryan at bluewatersys.com
Tue Oct 13 16:01:30 EDT 2009


Christian Gagneraud wrote:
> Ryan Mallon wrote:
>> Christian Gagneraud wrote:
>>> This patch add support for the ADC found in the EP93XX.
>>>
>>
>>> +};
>>> +
>>> +struct adc_device {
>>> +    struct platform_device *pdev;
>>> +    struct platform_device *owner;
>>> +    struct clk *clk;
>>> +    struct ep93xx_adc_client *cur;
>>> +    void __iomem *regs;
>>> +    int irq;
>>> +    unsigned int refm;              /* Reading when Vin = Vref- */
>>> +    unsigned int refp;              /* Reading when Vin = Vref+ */
>>> +};
>>> +
>>> +static struct adc_device *adc_dev;
>>> +
>>> +static LIST_HEAD(adc_pending);
>>> +
>>> +#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
>>
>> Bit of a nitpick, but can you move the structure definitions and
>>  above the first functions in this file.
> 
> Bit of nitpick, but I will move the first functions _below_ the
> structure definitions and variable declarations. :)

Heh, fair enough :-).

> 
>>
>>> +
>>> +static inline void ep93xx_adc_convert(struct adc_device *adc)
>>> +{
>>> +    unsigned long prev_switch;
>>> +    unsigned long next_switch;
>>> +
>>> +    /* Configure the switches */
>>> +    prev_switch = __raw_readl(EP93XX_TS_DIRECT);
>>> +    next_switch = adc->cur->channel;
>>> +    if (next_switch != prev_switch) {
>>> +        ep93xx_adc_set_reg(EP93XX_TS_DIRECT, next_switch);
>>> +        /* Channel switch settling time */
>>> +        /* TODO: depends on clock speed (500us or 2ms) */
>>> +        /* FIXME: the caller has disabled interrupts and the
>>> +         * caller can even be the irq handler. Should we
>>> +         * better fire a timer? */
>>> +        mdelay(2);
>>
>> Perhaps make the mdelay value a platform data in the meantime then?
> 
> Actually I need to use clock_get_rate I think. But yes, why not putting
> the clock configuration in the platform data in the meantime.
> 
> Any particular comment about using mdelay within local_irq_save/restore
> context (used to protect the list), and within an interrupt handler
> (needed to fire the next operation).

udelay and mdelay are busy wait loops, and are okay to use inside
interrupt context.

> 
>>
>>> +    data -= adc->refm;
>>> +
>>> +    client->nr_samples--;
>>> +
>>> +    ep93xx_convert_done(client, data, &client->nr_samples);
>>> +
>>> +    /* If all samples are done, disable IRQ, and kick start the next
>>> +     * one if any. */
>>
>> This comment doesn't make sense. If all samples are done, kick start the
>> next one? Am I missing something?
> 
> I will clarify the comment, actually I meant:
> If all samples are done for this client (channel), disable IRQ, and kick
> start the next client (channel) if any.

Okay, that makes sense. Can you change the comment to reflect this.

>>
>>> +
>>> +    platform_set_drvdata(pdev, adc);
>>> +
>>> +    /* Defaults from datasheet (approximated values) */
>>> +    adc->refm = 0xFFFF - 25000;
>>
>> Erk, why two different bases? Can we just #define these values somewhere.
> 
> I think I still need to find the best way to cope with that, 0xFFFF is
> because we're manipulating 16bits data and 25000 is the value for Vref/2
> (from datasheet).

Okay, makes sense. Can we make a #define with a comment then?

>>
>>> +    adc->refp = 25000;
>>> +    adc_dev = adc;
>>> +
>>> +    return 0;
>>> +
>>> +      err_clk:
>>> +    clk_put(adc->clk);
>>
>> clk_disable?
> 
> Why? isn't clk_put() the reverse of clk_get()?

Sorry, I misread the code. I though you could error exit after the
clk_enable above. Your error path is okay.

>>> +
>>> +static struct platform_driver ep93xx_adc_driver = {
>>> +    .driver = {
>>> +           .name = "ep93xx-analog",
>>
>> Why not ep93xx-adc?
> 
> As I said in a previous email, there's ADC stuff and there's touchscreen
> stuff, both use the same ressource, so I chossed a "neutral" name for
> these shared ressource (it's not ADC, it's not TS, it's "analog").
> 
> I'm really thinking about to make everything ADC centric.

As Hartley mentioned, if this is the interface to the ADC, and the
touchscreen driver uses ep93xx_adc_register, then this driver is the
only one which needs the clock.

I have a touchscreen driver lying around which needs to be ported to the
mainline. I will add getting it work with this driver to my list of
things to do.

>>> +
>>> +#ifndef __ASM_ARCH_HWMON_H
>>> +#define __ASM_ARCH_HWMON_H __FILE__
>>
>> Stray __FILE__?
> 
> Yes, I saw that as well, but as I said in another email, I first tried
> not to do cosmetic changes, so i leaved this guy as it was.

It shouldn't be there, just remove it.

>>
>>> +static struct ep93xx_hwmon_data ts72xx_hwmon_info = {
>>> +    /* POWER_IN*10K/150K (4.5-20V) */
>>> +    .in[0] = &(struct ep93xx_hwmon_chcfg) {
>>
>> That cast looks really ugly, is there a better way?
>>
>>> +        .name        = "ts72xx-vin",
>>> +                .channel        = TS72XX_ADC0,
>>> +        .mult        = 33*(15+1),
>>> +        .div        = 500*1,
>>
>> Spaces around operators please. Also why the explict multiplies
>> (especially by 1)?
> 
> I didn't want to put any magic numbers here, so it means 3.3V multiplied
> by 150K resistor in serie with 10K resistor, divided by a 10K resistor
> multiplied by the full scale value.

Perhaps a comment explaining this then?

One last thing. It might be an idea to split this into a few patches. At
least into one for the adc driver and one for the hwmon part. As it
stands the patch is quite large.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934



More information about the linux-arm-kernel mailing list