SPI device in am3517

Dear all,

it is quite the same than on the beableboard that's why I'm posting a
question regarding the AM3517.
I'm trying to enable the SPI1 in the following manner:

- Correctly setup pin muxes in mux.c and mux.h to have SPI1 on pin
which I can have access to (connector).
- Filled in the spi_device_info structure with modalias = "spidev",
bus_num and chip_select fields.
- Created an init function which calls every omap_cfg_reg to change
the muxing on every SPI pin, and called the spi_register_board_info as
well.

In menuconfig I added support for SPIDEV and McSPI for OMAP24XX/
OMAP34XX.

The result is that once the kernel has booted I get the following tree
in the fs:

/sys/devices/platform/omap2_mcspi.1/spi1.0/spidev/
spidev1.0 ...........

But I do not actually see any device in /dev such as /dev/spidev1.0

Can you please give me a tip?

Thank you very much,

regards.

Here I post a detail of what I changed:

A) U-BOOT

I modified muxes in u-boot in the following file ~/board/omap3/
omap3517mcm1/omap3517mcm1.h

#define MUX_OMAP3517MCM1() \

...

MUX_VAL(CP(MCBSP1_CLKR), (IEN | PTD | DIS | M1)) /*MCSPI4_CLK */\
MUX_VAL(CP(MCBSP1_FSR), (IDIS | PTU | EN | M4)) /*GPIO_157*/\
MUX_VAL(CP(MCBSP1_DX), (IEN | PTD | DIS | M1)) /*MCSPI4_SIMO*/\
MUX_VAL(CP(MCBSP1_DR), (IEN | PTD | DIS | M1)) /*MCSPI4_SOMI*/\
MUX_VAL(CP(MCBSP_CLKS), (IEN | PTU | DIS | M4)) /*GPIO_160*/\
MUX_VAL(CP(MCBSP1_FSX), (IEN | PTD | EN | M1)) /*MCSPI4_CS0*/\
MUX_VAL(CP(MCBSP1_CLKX), (IEN | PTD | DIS | M4)) /*GPIO_162 */\

...

MUX_VAL(CP(MCSPI1_CLK), (IEN | PTD | DIS | M0)) /*McSPI1_CLK*/\
MUX_VAL(CP(MCSPI1_SIMO), (IEN | PTD | DIS | M0)) /*McSPI1_SIMO */\
MUX_VAL(CP(MCSPI1_SOMI), (IEN | PTD | DIS | M0)) /*McSPI1_SOMI */\
MUX_VAL(CP(MCSPI1_CS0), (IEN | PTD | EN | M0)) /*McSPI1_CS0*/\
MUX_VAL(CP(MCSPI1_CS1), (IEN | PTD | EN | M4)) /*GPIO_175*/\
               /* TS_PEN_IRQ */\
MUX_VAL(CP(MCSPI1_CS2), (IEN | PTU | DIS | M4)) /*GPIO_176*/\
               /* - LAN_INTR*/\
MUX_VAL(CP(MCSPI1_CS3), (IEN | PTD | EN | M0)) /*McSPI1_CS3*/\

...

Compiled everything and got u-boot running.

B) KERNEL

As I did in u-boot, I also changed muxing here in the kernel in the
following files:

~/kernel/arch/arm/mach-omap2/mux.h

enum omap34xx_index {

...

  /* SPI1 */
  AE14_3517_MCSPI1_CLK,
  AD15_3517_MCSPI1_SIMO,
  AC15_3517_MCSPI1_SOMI,
  AB15_3517_MCSPI1_CS0,
  AD14_3517_MCSPI1_CS1,
  AE15_3517_MCSPI1_CS2,
  AE16_3517_MCSPI1_CS3,

  /* SPI 4 */
  OMAP_3517_MCSPI4_CLK,
  OMAP_3517_MCSPI4_SIMO,
  OMAP_3517_MCSPI4_SOMI,
  OMAP_3517_MCSPI4_CS0,

};

And in ~/kernel/arch/arm/mach-omap2/mux.c

#ifdef CONFIG_ARCH_OMAP34XX
static struct pin_config __initdata_or_module omap34xx_pins[] = {

...

/* MCSPI1 mux configuration */
MUX_CFG_34XX("AE14_3517_MCSPI1_CLK", 0x1c8,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AD15_3517_MCSPI1_SIMO", 0x1ca,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AC15_3517_MCSPI1_SOMI", 0x1cc,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
MUX_CFG_34XX("AB15_3517_MCSPI1_CS0", 0x1ce,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AD14_3517_MCSPI1_CS1", 0x1d0,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AE15_3517_MCSPI1_CS2", 0x1d2,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AE16_3517_MCSPI1_CS3", 0x1d4,
    OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)

/* MCSPI4 mux configuration */
MUX_CFG_34XX("OMAP_3517_MCSPI4_CLK", 0x18c,
    OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("OMAP_3517_MCSPI4_SIMO", 0x190,
    OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("OMAP_3517_MCSPI4_SOMI", 0x192,
    OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_INPUT_PULLUP)
MUX_CFG_34XX("OMAP_3517_MCSPI4_CS0", 0x196,
    OMAP34XX_MUX_MODE1 | OMAP34XX_PIN_OUTPUT)

};

....

Alignment is maintained between the two files in fact I don't have any
muxing errors and the display is still working.

Then I also added/modified ~/kernel/arch/arm/mach-omap2/board-
omap3517mcm1.c

/*
* SPI
*/
static struct omap2_mcspi_device_config mcm1_mcspi1_config = {
  .turbo_mode = 0,
  .single_channel = 1, /* 0: slave, 1: master */
};

static struct omap2_mcspi_device_config mcm1_mcspi4_config = {
  .turbo_mode = 0,
  .single_channel = 1, /* 0: slave, 1: master */
};

static struct spi_board_info omap3517mcm1_spi_board_info[] __initdata
= {
  [0] = {
    .modalias = "spidev",
    .bus_num = 1,
    .chip_select = 0,
    .max_speed_hz = 1500000,
    .controller_data = &mcm1_mcspi1_config,
    .mode = SPI_MODE_0,
  },
  [1] = {
    .modalias = "spidev",
    .bus_num = 4,
    .chip_select = 0,
    .max_speed_hz = 1500000,
    .controller_data = &mcm1_mcspi4_config,
  },

};

static void __init omap3517mcm1_mcspi_init(void)
{

  // Configurating mux pins
  omap_cfg_reg(AE14_3517_MCSPI1_CLK);
  omap_cfg_reg(AD15_3517_MCSPI1_SIMO);
  omap_cfg_reg(AC15_3517_MCSPI1_SOMI);
  omap_cfg_reg(AB15_3517_MCSPI1_CS0);
  omap_cfg_reg(AD14_3517_MCSPI1_CS1);
  omap_cfg_reg(AE15_3517_MCSPI1_CS2);
  omap_cfg_reg(AE16_3517_MCSPI1_CS3);

  omap_cfg_reg(OMAP_3517_MCSPI4_CLK);
  omap_cfg_reg(OMAP_3517_MCSPI4_SIMO);
  omap_cfg_reg(OMAP_3517_MCSPI4_SOMI);
  omap_cfg_reg(OMAP_3517_MCSPI4_CS0);

  spi_register_board_info(omap3517mcm1_spi_board_info,
    ARRAY_SIZE(omap3517mcm1_spi_board_info));

}

And called this function in the board initializations:

static void __init omap3517_mcm1_init(void)
{

...

  omap3517mcm1_mcspi_init();

...

}

C) Finally in menuconfig I've added all the features I wanted for the
SPI to be included in the kernel (not as modules)

# CONFIG_SCSI_SPI_ATTRS is not set
CONFIG_SPI=y
CONFIG_SPI_DEBUG=y
CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_GPIO is not set
CONFIG_SPI_OMAP24XX=y
# SPI Protocol Masters
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
# SPI GPIO expanders:
# CONFIG_MMC_SPI is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set

This is what I get from an egrep.

The crucial things ASAIK which need to be set are CONFIG_SPI,
CONFIG_SPI_MASTER, CONFIG_SPI_OMAP24XX and CONFIG_SPI_SPIDEV. The
problem is that in the end no devices such as spidev1.0 and spidev4.0
gets created by the kernel during boot in the dev folder.

I'd be so glad if you guys could help me out with this one,

thank you in advance,

best regards,

ivan

I am experiencing exactly the same problem.

I set the mux only in u-boot because the kernel should not set the mux if not instructed to by
CONFIG_ARCH_OMAP34XX
This works for USART1 , I2c2 and GPIOs.
Why should the mux configuration anyhow affect the device being present in /dev ,it is only a mux and the peripheral is in the OMAP anyhow.

By the way this does not bring us any further…I sill cannot get access to the device , the device in not in /dev and I get the same tree in the fs
/sys/devices/platform/omap2_mcspi.1/spi1.0/ …2.0 …3.0 …4.0

Best Regards

Fabio

I also use a slightly different code for setting up the interface during init

static struct spi_board_info beagle_spi_board_info[] = {
{
.modalias = “spidev”,
.max_speed_hz = 10000000, //10 Mbps
.bus_num = 3,
.chip_select = 0,
.mode = SPI_MODE_1,
},
};

static struct spi_board_info beagle_spi_board_info4[] = {
{
.modalias = “spidev”,
.max_speed_hz = 10000000, //10 Mbps
.bus_num = 4,
.chip_select = 0,
.mode = SPI_MODE_1,
},
};

static void omap3_beagle_init_spi(void)
{
printk(“Debug ================> MCSPI >>> start\n”)
//spi_register_board_info(beagle_spi_board_info, ARRAY_SIZE(beagle_spi_board_info));
// printk(“Debug ================> register using [spidev3] protocol driver >>> start\n”);
spi_register_board_info(beagle_spi_board_info2, ARRAY_SIZE(beagle_spi_board_info4));
printk(“Debug ================> register using [spidev4] protocol driver >>> end\n”);

printk(“Debug ================> MCSPI >>> end\n”);
}

static void __init omap3_beagle_init(void)
{
omap3_beagle_i2c_init();
platform_add_devices(omap3_beagle_devices,
ARRAY_SIZE(omap3_beagle_devices));
omap_board_config = omap3_beagle_config;
omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
omap_serial_init();

omap_cfg_reg(J25_34XX_GPIO170);

omap3beagle_enc28j60_init();

omap_cfg_reg(AG4_3530_GPIO134);
omap_cfg_reg(K26_34XX_GPIO161);
omap_cfg_reg(Y21_3530_GPIO156_OUT);
omap_cfg_reg(AF14_34XX_I2C3_SCL);
omap_cfg_reg(AG14_34XX_I2C3_SDA);
omap_cfg_reg(U21_3530_GPIO159_OUT);
gpio_direction_output(156, false);
gpio_direction_output(159, false);
// BMI Presence and Status
usb_musb_init();
usb_ehci_init();
omap3beagle_flash_init();
beagle_display_init();
omap_init_bmi_slots();

  • omap3_beagle_init_spi(); //FF
    }

Regards

Fabio

Hey Fabio,

looking at your code I see the following:

    spi_register_board_info(beagle_spi_board_info2,
ARRAY_SIZE(beagle_spi_board_info4));

I know this won't make any progress but the array size should be of
the beagle_spi_board_info2 instead of info4. Anyways I didn't go any
further and I passed to the 2.6.32 kernel to see if something has
changed. The problem I'm having now with this kernel version is that
mux management has changed completely and I adapted my part of code
but after boot by entering a "dmesg | grep mux" I get this:

<3>mux: Could not set signal i2c2_scl
<3>mux: Could not set signal i2c2_sda
<3>mux: Could not set signal i2c3_scl
<3>mux: Could not set signal i2c3_sda
<3>mux: Could not set signal mcspi1_clk
<3>mux: Could not set signal mcspi1_simo
<3>mux: Could not set signal mcspi1_somi
<3>mux: Could not set signal mcspi1_c0
<3>mux: Could not set signal mcspi1_c1
<3>mux: Could not set signal mcspi1_c2
<3>mux: Could not set signal mcspi1_c3
<3>mux: Could not set gpio57
<3>mux: Could not set signal hsusb1_stp
<3>mux: Could not set signal hsusb1_clk
<3>mux: Could not set signal hsusb1_dir
<3>mux: Could not set signal hsusb1_nxt
<3>mux: Could not set signal hsusb1_data0
<3>mux: Could not set signal hsusb1_data1
<3>mux: Could not set signal hsusb1_data2
<3>mux: Could not set signal hsusb1_data3
<3>mux: Could not set signal hsusb1_data4
<3>mux: Could not set signal hsusb1_data5
<3>mux: Could not set signal hsusb1_data6
<3>mux: Could not set signal hsusb1_data7
<3>mux: Could not set signal hsusb2_stp
<3>mux: Could not set signal hsusb2_clk
<3>mux: Could not set signal hsusb2_dir
<3>mux: Could not set signal hsusb2_nxt
<3>mux: Could not set signal hsusb2_data0
<3>mux: Could not set signal hsusb2_data1
<3>mux: Could not set signal hsusb2_data2
<3>mux: Could not set signal hsusb2_data3
<3>mux: Could not set signal hsusb2_data4
<3>mux: Could not set signal hsusb2_data5
<3>mux: Could not set signal hsusb2_data6
<3>mux: Could not set signal hsusb2_data7
<3>mux: Could not set signal sdmmc1_clk
<3>mux: Could not set signal sdmmc1_cmd
<3>mux: Could not set signal sdmmc1_dat0
<3>mux: Could not set signal sdmmc1_dat1
<3>mux: Could not set signal sdmmc1_dat2
<3>mux: Could not set signal sdmmc1_dat3
<3>mux: Could not set signal sdmmc1_dat4
<3>mux: Could not set signal sdmmc1_dat5
<3>mux: Could not set signal sdmmc1_dat6
<3>mux: Could not set signal sdmmc1_dat7
<3>mux: Could not set gpio182

Which means that the muxing is actually not working...

I'll let you know if I discover something more useful...

regards,

ivan

Dear Ivan,

sorry for the mistake, it was an old code I fixed after bitbake complained for the 2 instead of 4 and for a missing ; here
printk(“Debug ================> MCSPI >>> start\n”)

bit nonetheless the problem is not solved yet.
Well I read that the mux is not configured by the kernel as long as you don’t define the symbol CONFIG_ARCH_OMAP34XX in your mux.h for instance, that is included in your If you check your
~/kernel/arch/arm/mach-omap2/mux.c
the code is controlled by this preprocessor symbol.
I think that setting the muxes in u-boot and forgetting about it in the kernel can simplify the configuration.
This as long as nothing overrides the settings.

In my experience GPIOs, I2C2 and USART1 muxes can be configured in u-boot and that’s it.

Let’s keep updated.

By the way I’m also working on the LCD interface and designing an expansion board both for LCD and physical layer of the interfaces.

Fabio

The LCD works without any problems on my board.

Anyways now I'm working on kernel 2.6.32 and the muxing part changed
completely. I figured out how to make it work in 2.6.32. There a mux
init function which needs to be called before any mux change can be
done.
In fact in my board specific source file I added the following:

#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
  { .reg_offset = OMAP_MUX_TERMINATOR },
};
#else
#define board_mux NULL
#endif

And in the board init function before any mux change:

omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);

If I find out something in regards of the SPI I'll let you know.

Ivan

As you might imagine I work with kernel 2.6.29.
Why don’t you like my approach of setting the muxes in u-boot only?
Is there any drawback?

As far as I can see on my scope the lcd sync signals are fine, and the DSS driver works very well. I cannot debug without HW the LCD data … :slight_smile:

Fabio

Sorry for bothering you once again, but I still have some doubts.
I don’t know the spi linux driver at all but why should the kernel do not show up an spidev entry in /dev if the muxes are not set up properly?
The mcspi device is in the HW and setup in the kernel anyhow. I would expect to find spidev4 and be able to send data to the device but eventually not be able to drive the HW lines…
mmmm

what do you think?

Fabio

It's actually the same tought I'm having. But perhaps the mcspi device
gives a feedback to the upper layers telling them that muxes aren't
configured correctly therefore no device binding occures, but this is
only a guess...

Anyways I've updated everything in kernel 2.6.32 as mentioned in a
previous post and by issueing in shell the following command "dmesg |
grep mux", after boot I see that the muxes are correctly set this
time!!

...
<7>mux: Setting signal mcspi1_clk.mcspi1_clk 0x0100 -> 0x0000
<7>mux: Setting signal mcspi1_simo.mcspi1_simo 0x0100 -> 0x0000
<7>mux: Setting signal mcspi1_somi.mcspi1_somi 0x0100 -> 0x0100
<7>mux: Setting signal mcspi1_cs0.mcspi1_cs0 0x0108 -> 0x0000
<7>mux: Setting signal mcspi1_cs1.mcspi1_cs1 0x010c -> 0x0000
<7>mux: Setting signal mcspi1_cs2.mcspi1_cs2 0x0114 -> 0x0000
<7>mux: Setting signal mcspi1_cs3.mcspi1_cs3 0x0108 -> 0x0000
...

Comparing the values with the registers definition in the AM3517
technical manual (page 676) I'm able to say that they are correctly
configured: everything other than the SOMI is defined as output. No
pull-up or pull-downs are defined (I have them external, where
required).

Another useful debug info I had (by enabling debug info in device
drivers, please see menuconfig) which prints out info about spidev
binding etc... And there doesn't seem to be any error.

I'll go on and try to discover why there's no device in /dev folder.

regards,

ivan

Also tried to leave the mux configuration only in u-boot and not
touching it anymore in the kernel but nothing has changed...

I did the same,

check intrducing dummy commands in mux.h too see if bitbake -c compile virtual/kernel eventually complains.

#ifdef CONFIG_OMAP_MUX
/* setup pin muxing in Linux */

+config_sybol_test

extern int omap1_mux_init(void);
extern int omap2_mux_init(void);
extern int omap_mux_register(struct omap_mux_cfg );
extern int omap_cfg_reg(unsigned long reg_cfg);
#else
/
boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
static inline int omap1_mux_init(void) { return 0; }
static inline int omap2_mux_init(void) { return 0; }
static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; }
#endif

check also this in order not to loose your defconfig

The defconfig is stored in
recipes/linux/linux-omap-//defconfig

What I usually do is:

  1. bitbake virtual/kernel -c configure
  2. cd tmp/work/foo/bar/git ; make menuconfig
  3. cp .config
    /OE/openembedded/recipes/linux/linux-omap-//defconfig
  4. bitbake bitbake virtual/kernel -c compile -f ; bitbake virtual/kernel -c
    deploy
  5. goto 2)

Step 3 is there to ensure that my changes don’t get lost when cleaning the
recipe.

regards,

Koen

I am still struggling too…

Fabio

#ifdef CONFIG_OMAP_MUX
/* setup pin muxing in Linux */

dummy test----------------

extern int omap1_mux_init(void);
extern int omap2_mux_init(void);
extern int omap_mux_register(struct omap_mux_cfg );
extern int omap_cfg_reg(unsigned long reg_cfg);
#else
/
boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
static inline int omap1_mux_init(void) { return 0; }
static inline int omap2_mux_init(void) { return 0; }
static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; }
#endif

By the way ,

maybe this help :

if you enable the enc28j60 in the kernel, and leave everthing unchanged from bitbake -c configure virtual/kernel I see during startup that dmesg | grep spi shows that the kernel loads the enc28j60 driver and I can see 8 clock ticks on the scope on line spi4_clk…

Fabio

Ok... Do you get the enc28j60 device under the /dev directory?

Hey Fabio,

try to set the clk as input. I read about that it must be set like
this (it doesn't make any difference on my board but perhaps something
else is missing).

http://groups.google.com/group/beagleboard/browse_thread/thread/320ceba30172fba5
http://groups.google.com/group/beagleboard/browse_thread/thread/42988f0e14db0f01/df889508056f7cbd?lnk=gst&q=MCSPI3#df889508056f7cbd

Dear Ivan I have spidev4.0 listed in /dev and working ok (e.g. echo “AAAA” > /dev/spidev4.0 gives 4 times 8 clock ticks some 700 ns apart from eachother

This is how I did it

first config the kernel

CONFIG_SPI=y
CONFIG_SPI_DEBUG=y
CONFIG_SPI_MASTER=y

Can you verify whether SPI1 is working as well? Or if it's at least
present in /dev?

ivan

So as I wrote the code spi1.0 is present in /dev.
For this interface I didn’t set the mux properly in the code but it shuld be statightforward. McSPI1 is not available on the beagle.
I’ll try SPI3 next

Fabio

Could you post what you see with a dmesg | grep spi command?

Thank you,

ivan

This is what I see

root@beagleboard:/sys/bus/spi# cd devices/
root@beagleboard:/sys/bus/spi/devices# ls
spi1.0 spi4.0
root@beagleboard:/sys/bus/spi/devices#

root@beagleboard:/dev# ls | grep spi
spidev1.0
spidev4.0
root@beagleboard:/dev#

root@beagleboard:/dev# dmesg | grep spi
root@beagleboard:/dev#

root@beagleboard:/dev# echo “AAAA” > /dev/spidev4.0
root@beagleboard:/dev#

it actually works @ 48Mbit/s

Fabio