Hi,
After browsing the forums I can't really find anything that relates to my specific issue. Also, I am fairly new with the am335x so my apologies if I have overlooked something.
So here's the problem: I am writing a new device driver to read the A/D on a BBB rev C board (i.e. the am3358), but as soon as I load the module and enable the ADC I end up with read/write errors from internal flash within a fairly short amount of time - typically seconds to a minute (excerpt from syslog):
Jun 7 19:40:40 beaglebone kernel: [ 277.162917] mmcblk0: error -84 transferring data, sector 222360, nr 32, cmd response 0x900, card status 0xc00
Jun 7 19:40:40 beaglebone kernel: [ 277.173618] end_request: I/O error, dev mmcblk0, sector 222360
Jun 7 19:40:40 beaglebone kernel: [ 277.179861] Buffer I/O error on device mmcblk0p2, logical block 2963
Jun 7 19:40:40 beaglebone kernel: [ 277.186624] lost page write due to I/O error on mmcblk0p2
Jun 7 19:40:40 beaglebone kernel: [ 277.186690] end_request: I/O error, dev mmcblk0, sector 222368
The system is Linux beaglebone 3.8.13-bone47 #1 SMP Fri Apr 11 01:36:09 UTC 2014 armv7l GNU/Linux
The driver starts out by mapping in and writing 2 to the CM_WKUP_ADC_TSC_CLKCTRL register to enable the ADC clock and waiting for idle status to become 0.
Once this is done, the ADC is initialized with the following sequence of register writes (all register names prefixed with ADC_):
{ ADC_CTRL, 0x00000006 }, // stepconfig=w, chan-id, disable
{ ADC_SYSCONFIG, 0x00000004 }, // No idle mode
{ ADC_IRQENABLE_CLR, 0x000007ff }, // Clear all interrupts
{ ADC_IRQSTATUS, 0x000007ff }, // Clear all interrupt status
{ ADC_IRQWAKEUP, 0x00000000 }, // Wakeup disabled - really needed?
{ ADC_DMAENABLE_CLR, 0x00000003 }, // Disable all DMA
{ ADC_ADCRANGE, 0x00000000 }, // zero ranges
{ ADC_ADC_CLKDIV, CLKDIV }, // 3ff -> 146/15.785
{ ADC_IDLECONFIG, 0x00000000 }, // Idle step config = none
{ ADC_TS_CHARGE_STEPCONFIG, 0x00000000 },
{ ADC_TS_CHARGE_DELAY, 0x00000004 }, // Wait 4 cycles at end of sequence
// STEPCONFIG
{ ADC_STEPCONFIG1, (AIN_X<<19) | (AIN_X<<15) | (AVG<<2) | 1 },
{ ADC_STEPDELAY1, 0x40000000 }, // 64 cycles
{ ADC_STEPCONFIG2, (AIN_Y<<19) | (AIN_Y<<15) | (AVG<<2) | 1 },
{ ADC_STEPDELAY2, 0x40000000 }, // 64 cycles
{ ADC_STEPENABLE, 0x00000006 }, // Step 1 and 2
{ ADC_FIFO0THRESHOLD, 0x00000001 }, // Interrupt @ 1
{ ADC_IRQENABLE_SET, 0x00000004 }, // FIFO0 threshold interrupt
{ ADC_CTRL, 0x00000003 } // Enable ADC
What's interesting is that if I avoid writing the ADC_STEPENABLE register or not enabling the ADC with the final write of 3 to ADC_CTRL the problem goes away altogether.
The problem is not related to interrupts, not enabling them or using the minimal ISR below makes no difference:
irqreturn_t jsm_interrupt(int irq, void *dev_id)
{
iowrite32(0x04, &jsm_data.padc[ADC_IRQSTATUS]);
return IRQ_HANDLED;
}
It appears to me that enabling the ADC somehow interferes with the rest of the system in some unexpected way. Am I missing something here? Are there some other registers that need to be set to avoid this?
Any help would be greatly appreciated!
Regards,
Jan Nordqvist