[linux-cirrus] Re: EP9302 on-chip ADC

  • From: Robert Ernst <r.ernst@xxxxxxxx>
  • To: linux-cirrus@xxxxxxxxxxxxx
  • Date: Thu, 2 Mar 2006 18:38:00 +0100

> We are trying to use the on-chip ADC of a custom board based on Cirrus
> Logic EP9302.  The User's Guide of EP9301 stated that the ADCEN bit should
> be set high and ADCPD should be set low in order to use ADC. We tried to 
> write the device config register to set those bits,  but for some reason
> the bits would always be reset to it's original value.

A lot of the Syscon registers may only be written when you unlock them by 
writing 0xAA to the Syscon SWLock register first, _and_ you have to make sure 
that no Syscon register access occurs between unlocking and writing, for 
example:

        unsigned long reg;

        cli();
        reg = inl(SYSCON_ADCCLKDIV);
        SysconSetLocked(SYSCON_ADCCLKDIV, reg | SYSCON_ADCCLKDIV_ADCEN);
        reg = inl(SYSCON_DEVCFG);
        SysconSetLocked(SYSCON_DEVCFG, reg | SYSCON_DEVCFG_ADCEN);
        reg = inl(SYSCON_DEVCFG);
        SysconSetLocked(SYSCON_DEVCFG, reg & ~SYSCON_DEVCFG_ADCPD);
        sti();

Turning off the interrupts makes sure that there is no race condition with 
other processes that might try to change the SYSCON_* registers at the same 
time, and using the SysconSetLocked() macro takes care of unlocking.

Note: there is a lock register for the ADC channel select register, too!

hope that helps,

Robert

Other related posts: