IRQ with ADXL345 accelerometer on Pengutronix BSP

Screwface
Hi,

I try to make an ADXL345 accelerometer working with linux. I use
Pengutronix BSP. I have modified my mach-mini2440.c platform file to
activate SPI as follow :

added lines

#include <linux/spi/spi.h>
#include <mach/spi.h>
#include <linux/input/adxl34x.h>

/* ADXL345 Accelerometer support */
static const struct adxl34x_platform_data adxl34x_info = {
        .x_axis_offset = 0,
        .y_axis_offset = 0,
        .z_axis_offset = 0,
        .tap_threshold = 0x31,
        .tap_duration = 0x10,
        .tap_latency = 0x60,
        .tap_window = 0xF0,
        .tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN,
        .act_axis_control = 0xFF,
        .activity_threshold = 5,
        .inactivity_threshold = 3,
        .inactivity_time = 4,
        .free_fall_threshold = 0x7,
        .free_fall_time = 0x20,
        .data_rate = 0x8,
        .data_range = ADXL_FULL_RES,
 
        .ev_type = EV_ABS,
        .ev_code_x = ABS_X,             /* EV_REL */
        .ev_code_y = ABS_Y,             /* EV_REL */
        .ev_code_z = ABS_Z,             /* EV_REL */
 
        .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z
*/
 
/*      .ev_code_ff = KEY_F,*/          /* EV_KEY */
/*      .ev_code_act_inactivity = KEY_A,*/      /* EV_KEY */
        .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
        .fifo_mode = ADXL_FIFO_STREAM,
        .orientation_enable = ADXL_EN_ORIENTATION_3D,
        .deadzone_angle = ADXL_DEADZONE_ANGLE_10p8,
        .divisor_length = ADXL_LP_FILTER_DIVISOR_16,
        /* EV_KEY {+Z, +Y, +X, -X, -Y, -Z} */
        .ev_codes_orient_3d = {BTN_Z, BTN_Y, BTN_X, BTN_A, BTN_B, BTN_C},
};

// First SPI slave
static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 1,
    .bus_num = 0,
    .pin_cs = S3C2410_GPG(2),
    .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};

static struct spi_board_info mini2440_spi_devs[] __initdata = {
  {       /* ADXL345 accelerometer */
    .modalias       = "adxl34x",
    .platform_data  = &adxl34x_info,
    .irq            = IRQ_EINT17,
    .chip_select    = 0,
    .max_speed_hz   = 5 * 1000 * 1000, /* max spi clock (SCK) speed in HZ
*/
    .bus_num        = 0,
    .mode=SPI_MODE_3,
  }
};
static struct platform_device *mini2440_devices[] __initdata = {
  ........
  &s3c_device_spi0,
};

static void __init mini2440_init(void)
{
        ........
  /* setup SPI */
  s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata;
  spi_register_board_info(mini2440_spi_devs,
                                 ARRAY_SIZE(mini2440_spi_devs));
        ........
}


I have also added this line in the config MACH_MINI2440 section of the
Kconfig file. I don't know which option does it select in which menu, but
I've seen it was needed
  select S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13

I have connected the pins of the ADXL345 as follow :

ADXL345          MINI2440
  CS                nSS_SPI
  INT1              EINT17  (not sure it is needed)
  INT2              not connected
  SDA               SPIMOSI
  SDO               SPIMISO
  SCL               SPICLK

My problem is the ADXL345 is not detected: during boot, I get this message
:
adxl34x spi0.0 : failed to probe ADXL34X accelerometer.

An Analog Devices document mentions this is due to a failed initialization
and communication with the ADXL34x. The advice is to check bus_num and
chip_select in the platform file.

I think I'm right on those items.
The thing which is unclead for me is the interrupt.
If I don't mention irq in  spi_board_info structure, I get an "irq ?"
during boot up. I have set it as it was mentionned for the CAN interface at
http://cor-net.org/2009/09/can-interface-for-the-mini2440-dev-board/ and
connected the line to EINT17 but without really understanding what I was
doing.

For me, the INT1 has to be configured in the ADXL345 to be rised up when
some particular movements are detected (tap, double tap, free fall). So
this pin is not mandatory.
On the other side, I'm not sure if there is something to do to tell the
EINT17 is an interrupt input pin.

I tried also in I2C mode, I got the device detected, but the board hangs if
I try an evtest on the corresponding event (event1)
The same Analog Devices document mentions something wrong with the
interrupt and advices to check the irq number in the platform file.

Can somebody :

- tell me which option is selected in kernel menuconfig when adding 'select
S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13' in the Kconfig file ?

- help me with this irq story: how to determine the correct IRQ, set and
configure it?

Thanks a lot!

Juergen Beisert
If you search for the "3C24XX_SPI_BUS0_GPE11_GPE12_GPE13" in the kernel you
will see, it compiles in the file
"arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c". The routine in this file
gets called via your "mini2440_spi0_platdata" structure. And this routine
itself sets up the pins for the SPI bus:
 - GPE13 for SPI CLK
 - GPE12 for SPI MOSI
 - GPE11 for SPI MISO

So, your ADXL345 SPI signals must be connected to these CPU's GPIOs to make
it work. There are alternatives (GPD10, GPD9, GPD8 and GPG7, GPG6, GPG5),
it depends where you have connected your external SPI device. On the other
hand the CPU is a 3.3 V type. What power supply does your ADXL345 use?

Screwface
Hi Juergen,

Thanks for your support!
I meant I wondered which option of the kernel menu 'make ARCH=arm
menuconfig' is triggered by 3C24XX_SPI_BUS0_GPE11_GPE12_GPE13. I have
looked in the drivers section but found nothing.
My question is more: Is it mandatory to add this line in the Kconfig file,
or is it possible to keep the original file and activate the correct option
in the kernel configuration menu.

Regarding the hardware connection, I used the pins you mentionned (GPE11,
GPE12, GPE13 so pins 25,26,27 and 28 of the GPIO connector). I take the
supply voltage from pins 2 and 3 of the same connector, so the sensor uses
3.3V. The datasheet mentions a supply range between 2.0V and 3.6V.
I think I'm right on the hardware part.

I think I'm wrong with interrupts (page 20 of the datasheet) as the
spi_board_info structure requests for an irq pin.


Here is the datasheet
http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf

Analog Devices document
http://www.google.fr/url?sa=t&rct=j&q=adxl345%20linux%20analog&a...

Juergen Beisert
You do not need a visible menu entry for a symbol like
"3C24XX_SPI_BUS0_GPE11_GPE12_GPE13". Just force it, if one selects the
platform that *requires* this feature.

The SPI framework provides many debug output on demand. Maybe you can
enable it to get an idea what is going wrong on your board.

The interrupt seems all right, because the DM9000 network driver uses the
same mechanism (just with EINT7).

Can you measure some activity on the SPI lines, when the ADXL345 driver
tries to access its device?

Screwface
I have enabled SPI debug in the kernel, but Ican't see any message during
boot. I have no files in /var/log/ also, so I wonder where are the
information stored.

I have no oscilloscope, so I cannot monitor signal lines. I'll look to do
it with my sound card.

Juergen Beisert
Debug messages are suppressed at boot time. You can see them when you run
the 'dmesg' utility after login. Or you can extend the kernel command line
with the keyword 'debug'. Then also the debug messages are shown at boot
time.

Alternatively you can slow down the SPI clock and using a simple voltmeter
so see, if the signals on these lines are changing.

Screwfcae
Thank you for the advice.

This is what dmesg gives :

s3c24xx-nand s3c2440-nand: clock idle support enabled
s3c2410-spi s3c2410-spi.0: bitbang at c397acf0
s3c2410-spi s3c2410-spi.0: registered master spi0
spi spi0.0: pre-scaler=25 (wanted 1000000, got 973557)
spi spi0.0: setup mode 3, 8 bits/w, 1000000 Hz max --> 0
s3c2410-spi s3c2410-spi.0: registered child spi0.0
dm9000 Ethernet Driver, V1.31
eth0: dm9000e at c487c300,c487e304 IRQ 51 MAC: d6:0c:f7:86:9a:62 (chip)
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
samsung-ts s3c2440-ts: driver attached, registering input device
input: S3C24XX TouchScreen as /devices/virtual/input/input0
adxl34x spi0.0: Failed to probe ADXL34x accelerometer
input: pwm-beeper as
/devices/platform/s3c24xx-pwm.0/pwm-beeper/input/input1


I'll try to test the hardware signals tomorrow.

Screwface
Hi,

I have performed tests as you mentionned by reducing the SPI speed and
measuring pins activity with a voltmeter. 
I have set SPI speed to 10Hz by putting 
.max_speed_hz   = 10,
in static struct spi_board_info mini2440_spi_devs[] __initdata structure

I didn't see anything: clock and MOSI lines are always about 3,22V. But I
can see MISO switch from 3,22V to 0V, and nSS_SPI going from 3,22 to 3,26V
when SPI is enabled.

So two possibilities: the SPI bus didn't slow down, or there is something
wrong and the lines are not correctly driven. The thing which makes me
hesitate is the fact that we can clearly see MISO line to be set as an
input I think, with the transition Hi to Lo TTL level...

Juergen Beisert
Add the "#define DEBUG" to the top of the file 'drivers/spi/spi-s3c24xx.c'
and see if the hardware is able to use such a slow frequency. In the driver
are some dev_dbg()s, maybe they help you to get an idea what happens.

Screwface
I modified the file as you advised. It seems the constant is already
defined : I get this message during kernel compile :

LD      sound/pci/lola/built-in.o
LD      sound/pci/lx6464es/built-in.o
drivers/spi/spi-s3c24xx.c:11:0: warning: "DEBUG" redefined [enabled by
default]
<command-line>:0:0: note: this is the location of the previous definition
LD      sound/pci/mixart/built-in.o


I looked again with dmesg and saw that 10Hz was not taken into account:

s3c24xx-nand s3c2440-nand: clock idle support enabled
s3c2410-spi s3c2410-spi.0: bitbang at c38a8af0
s3c2410-spi s3c2410-spi.0: registered master spi0
spi spi0.0: pre-scaler=255 (wanted 10, got 98876)
spi spi0.0: setup mode 3, 8 bits/w, 10 Hz max --> 0
s3c2410-spi s3c2410-spi.0: registered child spi0.0
dm9000 Ethernet Driver, V1.31

Maybe there is a minimum clock value somewhere. Anyway, I'm not sure to be
able to see something at 100kHz with a voltmeter.

Where are the debug information expected to be? In the dmesg output?

Juergen Beisert
The divider's max value is 255, so the SPI unit can slowdown the clock to
about 100 kHz. :( Okay, no way to measure it with a simple voltmeter.
I was in the hope to see more of the real transfer the ADXL345 driver does
to check for its device. But the s3c24xx_spi_txrx() routine does not
contain any debug code. Maybe you can add there some output to see what the
driver tries to send and what it receives.

carlos augusto
Hello, you got to run the accelerometer with mini2440?

Screwface
Hello Carlos,

I put this projet in standby. I didn't managed to get it working. I planned
to buy a cheap Cortex M3 oscilloscope on ebay to monitor spi signals. But
unfortunately, I have no time to spend on it for the moment. Anyway, if you
manage to do something, your report will be welcome here!

Regards