Search

Technical Discussion Group Forum

This forum is provided for user discussion. While Beacon EmbeddedWorks support staff and engineers participate, Beacon EmbeddedWorks does not guarantee the accuracy of all information within in the Technical Discussion Group (TDG).

The "Articles" forums provide brief Articles written by Beacon EmbeddedWorks engineers that address the most frequently asked technical questions.

To receive email notifications when updates are posted for a Beacon EmbeddedWorks product download, please subscribe to the TDG Forum of interest.

TDG Forum

PrevPrev Go to previous topic
NextNext Go to next topic
Last Post 28 Aug 2007 09:32 AM by  fszczerba
PMIC/SPI not working
 2 Replies
Sort:
You are not authorized to post a reply.
Author Messages
lwalkera
New Member
New Member
Posts:


--
23 Jul 2007 10:10 AM
    I've been trying to figure out how to get the PMIC drivers to work so that I can get access to the touch screen ADC channels and RTC. Looking at the schematics I saw that the PMIC chip is on CSPI2, so I enabled the MX31 CSPI driver and the CSPI2 channel (adding any others causes the kernel to hang on boot).
    The SPI master driver seems to load ok, but the probe for the device driver for the PMIC never gets called and when other modules try to use it, it ends up passing a null pointer for the *spi struct when it calls spi_sync().
    Has anyone gotten SPI or the PMIC to successfully work? I'm using 2.6.19.2 with zonque's patch set.
    davek
    New Member
    New Member
    Posts:


    --
    25 Jul 2007 07:16 AM
    I'm having the same trouble you're having. My kernel will hang on boot if I include the SPI driver, and I'm unable to get it to probe the PMIC as well. Hope someone here has some suggestions...
    fszczerba
    New Member
    New Member
    Posts:


    --
    28 Aug 2007 09:32 AM
    Make sure you have:

    CONFIG_SND_MXC_PMIC=y
    CONFIG_MXC_SPI_PMIC_CORE=y
    CONFIG_MXC_PMIC=y
    CONFIG_MXC_PMIC_CHARDEV=y
    CONFIG_MXC_PMIC_MC13783=y
    CONFIG_MXC_MC13783_AUDIO=y


    set in your .config. Then apply the following patch (assuming 2.6.19.2 with Daniel's patches):

    Index: linux-2.6.19.2-imx31/arch/arm/mach-mx3/mx31lite.c
    ===================================================================
    --- linux-2.6.19.2-imx31/arch/arm/mach-mx3/mx31lite.c (revision 6782)
    +++ linux-2.6.19.2-imx31/arch/arm/mach-mx3/mx31lite.c (revision 6783)
    @@ -26,6 +26,7 @@
    #include <linux/serial_8250.h>
    #include <linux/input.h>
    #include <linux/nodemask.h>
    +#include <linux/spi/spi.h>
    #if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
    #include <linux/mtd/mtd.h>
    #include <linux/mtd/map.h>
    @@ -242,7 +243,7 @@

    #if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE)

    -static struct mtd_partition mxc_nand_partitions[4] = {
    +static struct mtd_partition mxc_nand_partitions[] = {
    {
    .name = "nand.kernel",
    .offset = MTDPART_OFS_APPEND,
    @@ -281,6 +282,18 @@
    }
    #endif

    +static struct spi_board_info mxc_spi_board_info[] __initdata = {
    + {
    + .modalias = "pmic_spi",
    + .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
    + .max_speed_hz = 4000000,
    + .bus_num = 2,
    + .chip_select = 0,
    + },
    +};
    +
    +// TODO: #if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
    +
    /*!
    * Board specific fixup function. It is called by \b setup_arch() in
    * setup.c file very early on during kernel starts. It allows the user to
    @@ -401,6 +414,10 @@
    mxc_init_nor_mtd();
    mxc_init_nand_mtd();
    mxc_init_eth();
    +
    + spi_register_board_info(mxc_spi_board_info,
    + ARRAY_SIZE(mxc_spi_board_info));
    +
    }

    /*


    I also made a bunch of changes for improved debugging and error checking:

    Index: linux-2.6.19.2-imx31/arch/arm/mach-mx3/devices.c
    ===================================================================
    --- linux-2.6.19.2-imx31/arch/arm/mach-mx3/devices.c (revision 6782)
    +++ linux-2.6.19.2-imx31/arch/arm/mach-mx3/devices.c (revision 6783)
    @@ -541,19 +541,23 @@

    static inline void mxc_init_spi(void)
    {
    - /* SPBA configuration for CSPI2 - MCU is set */
    - spba_take_ownership(SPBA_CSPI2, SPBA_MASTER_A);
    #ifdef CONFIG_SPI_MXC_SELECT1
    if (platform_device_register(&mxcspi1_device) < 0)
    - printk("Error: Registering the SPI Controller_1\n");
    + printk(KERN_ERR "Error: Registering the SPI Controller_1\n");
    #endif /* CONFIG_SPI_MXC_SELECT1 */
    #ifdef CONFIG_SPI_MXC_SELECT2
    + /* SPBA configuration for CSPI2 - MCU is set
    + * note: only CSPI2 uses the SPBA???
    + */
    + if (spba_take_ownership(SPBA_CSPI2, SPBA_MASTER_A) < 0)
    + printk(KERN_ERR
    + "Error: Failed to take ownership of SPI Controller\n");
    if (platform_device_register(&mxcspi2_device) < 0)
    - printk("Error: Registering the SPI Controller_2\n");
    + printk(KERN_ERR "Error: Registering the SPI Controller_2\n");
    #endif /* CONFIG_SPI_MXC_SELECT2 */
    #ifdef CONFIG_SPI_MXC_SELECT3
    if (platform_device_register(&mxcspi3_device) < 0)
    - printk("Error: Registering the SPI Controller_3\n");
    + printk(KERN_ERR "Error: Registering the SPI Controller_3\n");
    #endif /* CONFIG_SPI_MXC_SELECT3 */
    }
    #else
    @@ -612,7 +616,9 @@
    mxc_init_pcmcia();

    /* SPBA configuration for SSI2 - SDMA and MCU are set */
    - spba_take_ownership(SPBA_SSI2, SPBA_MASTER_C | SPBA_MASTER_A);
    + if (spba_take_ownership(SPBA_SSI2, SPBA_MASTER_C | SPBA_MASTER_A) < 0)
    + printk(KERN_ERR
    + "Error: Failed to take ownership of SSI Controller\n");
    return 0;
    }

    Index: linux-2.6.19.2-imx31/drivers/mxc/pmic/core/mc13783.c
    ===================================================================
    --- linux-2.6.19.2-imx31/drivers/mxc/pmic/core/mc13783.c (revision 6782)
    +++ linux-2.6.19.2-imx31/drivers/mxc/pmic/core/mc13783.c (revision 6783)
    @@ -64,12 +64,17 @@
    unsigned int frame = 0;
    int ret = 0;

    - if (reg_num > MXC_PMIC_MAX_REG_NUM)
    + if (reg_num > MXC_PMIC_MAX_REG_NUM) {
    + printk(KERN_ERR "pmic_read: reg_num %u out of range\n", reg_num);
    return PMIC_ERROR;
    + }

    frame |= reg_num << MXC_PMIC_REG_NUM_SHIFT;

    ret = spi_rw(pmic_drv_data.spi, (u8 *) & frame, 1);
    + if (ret) {
    + printk(KERN_ALERT "pmic_read: spi_rw failed: %d\n", ret);
    + }

    *reg_val = frame & MXC_PMIC_FRAME_MASK;

    @@ -151,7 +156,10 @@
    int icid = 0;

    ver->id = PMIC_MC13783;
    - pmic_read(REG_REVISION, &rev_id);
    + if (pmic_read(REG_REVISION, &rev_id)) {
    + printk(KERN_NOTICE
    + "pmic_get_revision: pmic_read() failed\n");
    + }

    rev1 = (rev_id & 0x018) >> 3;
    rev2 = (rev_id & 0x007);
    Index: linux-2.6.19.2-imx31/drivers/mxc/pmic/core/pmic.h
    ===================================================================
    --- linux-2.6.19.2-imx31/drivers/mxc/pmic/core/pmic.h (revision 6782)
    +++ linux-2.6.19.2-imx31/drivers/mxc/pmic/core/pmic.h (revision 6783)
    @@ -58,11 +58,22 @@
    .delay_usecs = 0,
    };
    struct spi_message m;
    + int rval;

    spi_message_init(&m);
    spi_message_add_tail(&t, &m);
    - if (spi_sync(spi, &m) != 0 || m.status != 0)
    + rval = spi_sync(spi, &m);
    + if (unlikely(rval != 0)) {
    + printk(KERN_ALERT "pmic spi_rw: spi_sync returned %d\n", rval);
    return PMIC_ERROR;
    + }
    + if (unlikely(m.status != 0)) {
    + printk(KERN_ALERT "pmic spi_rw: msg status %d, transferred %u\n",
    + m.status, m.actual_length);
    + return PMIC_ERROR;
    + }
    +
    + dev_dbg(spi->dev, "pmic spi_rw: transferred %u, residual %d\n", m.actual_length, len-m.actual_length);
    return (len - m.actual_length);
    }

    Index: linux-2.6.19.2-imx31/drivers/spi/spi.c
    ===================================================================
    --- linux-2.6.19.2-imx31/drivers/spi/spi.c (revision 6782)
    +++ linux-2.6.19.2-imx31/drivers/spi/spi.c (revision 6783)
    @@ -484,6 +484,11 @@
    complete(arg);
    }

    +inline static const char * safe_str(const char *str)
    +{
    + return str ? str : "NULL";
    +}
    +
    /**
    * spi_sync - blocking/synchronous SPI data transfers
    * @spi: device with which data will be exchanged
    @@ -512,6 +517,12 @@
    DECLARE_COMPLETION_ONSTACK(done);
    int status;

    + pr_debug("spi_sync(): dev %s, master %s, transfer %p\n",
    + spi->dev.driver ? safe_str(spi->dev.driver->name) : "UNK",
    + spi->master->cdev.dev ?
    + safe_str(spi->master->cdev.dev->driver->name) : "UNK",
    + spi->master->transfer);
    +
    message->complete = spi_complete;
    message->context = &done;
    status = spi_async(spi, message);
    You are not authorized to post a reply.