This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

kernel-2.6.39.3 with OOPS during call module_init(davinci_spi_init);

Other Parts Discussed in Thread: DA8XX, OMAP-L137

All,

I met an oops under DA850 with SPI support, the follow are oops information:

RFH0-0>insmod davinci_spi.ko
[  112.442562] Unable to handle kernel NULL pointer dereference at virtual address 0000005c
[  112.450666] pgd = c38fc000
[  112.453382] [0000005c] *pgd=c1113831, *pte=00000000, *ppte=00000000
[  112.459668] Internal error: Oops: 17 [#1] PREEMPT
[  112.464363] last sysfs file:
[  112.467327] Modules linked in: davinci_spi(+) spi_bitbang [last unloaded: spi_bitbang]
[  112.475267] CPU: 0    Not tainted  (2.6.39.3 #2)
[  112.479909] PC is at _clear_bit+0x20/0x38
[  112.483954] LR is at prepare_unused_channel_list+0x50/0x70
[  112.489442] pc : [<c022d248>]    lr : [<c015fcfc>]    psr: 60000093
[  112.489462] sp : c38e7da0  ip : 60000013  fp : 00000000
[  112.500906] r10: 00000012  r9 : c112e2f0  r8 : c112e200
[  112.506125] r7 : c037c144  r6 : c036ed88  r5 : 00000002  r4 : 00000038
[  112.512643] r3 : 00040000  r2 : 00000012  r1 : 0000005c  r0 : 00000000
[  112.519164] Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
[  112.526379] Control: 0005317f  Table: c38fc000  DAC: 00000015
[  112.532120] Process insmod (pid: 144, stack limit = 0xc38e6270)
[  112.538033] Stack: (0xc38e7da0 to 0xc38e8000)
[  112.542409] 7da0: c015fcac 00000000 c38e7db8 c015fcac 00000000 c0258cbc c381a0f8 c3837510
[  112.550594] 7dc0: 00000000 bf00c1a0 00000012 00000013 c037c144 c01600a8 00000012 bf00c1a0
[  112.558779] 7de0: c112e2f0 c112e2f0 c036ec30 00000013 c036ec94 c112e200 c036ed90 00000012
[  112.566966] 7e00: 00000000 bf00c458 c38408a0 c112e2f0 c036ed90 c036ed90 bf00d01c bf00d01c
[  112.575151] 7e20: 00000000 0000001e 0000001c c025a9b4 c025a9a0 c025999c 00000000 c036ed90
[  112.583336] 7e40: c036edc4 bf00d01c 00000000 c0259ab0 bf00d01c c38e7e60 c0259a50 c0258cbc
[  112.591523] 7e60: c381a0f8 c3837510 bf00d01c bf00d01c c38e2660 c0378d20 00000000 c0259334
[  112.599708] 7e80: bf00cfd6 bf00cfd6 00000000 bf00d01c 00000000 00000001 bf010000 00000000
[  112.607892] 7ea0: 0000001c c0259f8c 00000000 bf00d008 00000000 00000001 bf010000 00000000
[  112.616076] 7ec0: 0000001c c025adb8 bf00d058 00000000 00000001 c0155518 c0370c64 00000001
[  112.624259] 7ee0: bf00d058 bf00d058 bf00d0a0 bf00d058 00000000 00000001 c1122400 00000001
[  112.632446] 7f00: 0000001c c018fb00 bf00d064 c0155310 c018d808 c02e4c60 bf00d17c 00070e42
[  112.640631] 7f20: 00000350 c406d000 000028b0 c406e3ec c406e2af c406f3c4 c38f0480 000011a4
[  112.648812] 7f40: 00001364 00000000 00000000 0000001c 0000001d 00000014 00000000 00000010
[  112.656993] 7f60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[  112.665178] 7f80: c38f0540 fffffe00 00000069 bef35e74 00000080 c0156144 c38e6000 00000000
[  112.673364] 7fa0: 00000000 c0155fc0 fffffe00 00000069 00080040 000028b0 00070e42 7fffffff
[  112.681548] 7fc0: fffffe00 00000069 bef35e74 00000080 bef35e78 00070e42 bef35e78 00000000
[  112.689729] 7fe0: 00000001 bef35b34 00013d3c 4024bfc4 60000010 00080040 00000000 00000000
[  112.697917] Code: e3a03001 e1a03213 e10fc000 e321f093 (e7912100)
[  112.704171] ---[ end trace f9fac7a4e3a0840b ]---
Segmentation fault

Under board's kernel specific file:

static struct spi_board_info da850_spi_board_info[] __initdata = {
    {
        .modalias               = "ks8851",
        .mode                   = SPI_MODE_0,
        .bus_num                = 1,
        .chip_select            = 0,
        .max_speed_hz           = 24000000,
        .irq                    = ETH_KS8851_IRQ,
    },
};

static struct gpio da850_eth_gpios[] __initdata = {
#if 0
    { ETH_KS8851_POWER_ON,    GPIOF_OUT_INIT_HIGH,    "eth_power"    },
    { ETH_KS8851_QUART,    GPIOF_OUT_INIT_HIGH,    "quart"        },
#endif
    { ETH_KS8851_IRQ,    GPIOF_IN,        "eth_irq"    },
};

static int __init da850_ethernet_init(void)
{
    int status;

    /*  Request of GPIO lines */
    status = gpio_request_array(da850_eth_gpios,
            ARRAY_SIZE(da850_eth_gpios));
    if (status)
    {
        pr_err("Cannot request ETH GPIOs\n");
    }
    return status;
}

static __init void da850_rru_init(void)
{
    int ret = 0;
    u32 cfgchip2 = 0;

    ret = davinci_cfg_reg_list(da850_i2c0_pins);
    if (ret)
        pr_warning("da850_rru_init: i2c0 mux setup failed: %d\n",
                ret);

    ret = da8xx_register_i2c(0, &da850_rru_i2c_0_pdata);
    if (ret)
        pr_warning("da850_rru_init: i2c0 registration failed: %d\n",
                ret);


    ret = da8xx_register_watchdog();
    if (ret)
        pr_warning("da830_rru_init: watchdog registration failed: %d\n",
                ret);

    davinci_serial_init(&da850_rru_uart_config);

    i2c_register_board_info(1, da850_rru_i2c_devices,
            ARRAY_SIZE(da850_rru_i2c_devices));

    /*
     * shut down uart 0 and 1; they are not used on the board and
     * accessing them causes endless "too much work in irq53" messages
     * with arago fs
     */
    __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30);
    __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30);
//    __raw_writel(0, IO_ADDRESS(DA8XX_UART2_BASE) + 0x30);

    ret = da8xx_register_rtc();
    if (ret)
        pr_warning("da850_rru_init: rtc setup failed: %d\n", ret);

    ret = da8xx_register_cpuidle();
    if (ret)
        pr_warning("da850_rru_init: cpuidle registration failed: %d\n",
                ret);

    ret = da850_register_pm(&da850_pm_device);
    if (ret)
        pr_warning("da850_rru_init: suspend registration failed: %d\n",
                ret);

    pr_err("pinmux0: %x\n", __raw_readl(DA8XX_SYSCFG0_VIRT(0x120)));
    pr_err("cfgchip2: %x\n", __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)));

#if 0
    init_ks8851_resource();
    platform_add_devices(da850_rru_devices, ARRAY_SIZE(da850_rru_devices));
#endif

    ret = da850_ethernet_init();
    if( ret != 0 )
    {
        pr_err("Failed to do da850 ethernet initialization\n");
    }
    else
    {
        da850_spi_board_info[0].irq = gpio_to_irq(ETH_KS8851_IRQ);
        ret = da8xx_register_spi(1, da850_spi_board_info, ARRAY_SIZE(da850_spi_board_info));
        if (ret)
        {
            printk("fduan001: failed to do initilize the spi register\n"); # never runned here
        }
    }
}

CONFIG FILE:

CONFIG_SPI=y

CONFIG_SPI_DAVINCI=m

CONFIG_SPI_BITBANG=m

CONFIG_KS8851=y # i changed this option to n, oops happen the same

I don't know why the standard driver could meet such problem. 

BR

Fei Xia Duan

/*
 * DA8XX/OMAP L1XX platform device data
 *
 * Copyright (c) 2007-2009, MontaVista Software, Inc. <source@mvista.com>
 * Derived from code that was:
 *    Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>

#include <mach/cputype.h>
#include <mach/common.h>
#include <mach/time.h>
#include <mach/da8xx.h>
#include <mach/cpuidle.h>

#include "clock.h"

#define DA8XX_TPCC_BASE            0x01c00000
#define DA850_MMCSD1_BASE        0x01e1b000
#define DA850_TPCC1_BASE        0x01e30000
#define DA8XX_TPTC0_BASE        0x01c08000
#define DA8XX_TPTC1_BASE        0x01c08400
#define DA850_TPTC2_BASE        0x01e38000
#define DA8XX_WDOG_BASE            0x01c21000 /* DA8XX_TIMER64P1_BASE */
#define DA8XX_I2C0_BASE            0x01c22000
#define DA8XX_RTC_BASE            0x01C23000
#define DA8XX_EMAC_CPPI_PORT_BASE    0x01e20000
#define DA8XX_EMAC_CPGMACSS_BASE    0x01e22000
#define DA8XX_EMAC_CPGMAC_BASE        0x01e23000
#define DA8XX_EMAC_MDIO_BASE        0x01e24000
#define DA8XX_GPIO_BASE            0x01e26000
#define DA8XX_I2C1_BASE            0x01e28000
#define DA8XX_SPI0_BASE            0x01c41000
#define DA830_SPI1_BASE            0x01e12000
#define DA850_SPI1_BASE            0x01f0e000

#define DA8XX_EMAC_CTRL_REG_OFFSET    0x3000
#define DA8XX_EMAC_MOD_REG_OFFSET    0x2000
#define DA8XX_EMAC_RAM_OFFSET        0x0000
#define DA8XX_EMAC_CTRL_RAM_SIZE    SZ_8K

#define DA8XX_DMA_SPI0_RX    EDMA_CTLR_CHAN(0, 14)
#define DA8XX_DMA_SPI0_TX    EDMA_CTLR_CHAN(0, 15)
#define DA8XX_DMA_MMCSD0_RX    EDMA_CTLR_CHAN(0, 16)
#define DA8XX_DMA_MMCSD0_TX    EDMA_CTLR_CHAN(0, 17)
#define DA8XX_DMA_SPI1_RX    EDMA_CTLR_CHAN(0, 18)
#define DA8XX_DMA_SPI1_TX    EDMA_CTLR_CHAN(0, 19)
#define DA850_DMA_MMCSD1_RX    EDMA_CTLR_CHAN(1, 28)
#define DA850_DMA_MMCSD1_TX    EDMA_CTLR_CHAN(1, 29)

void __iomem *da8xx_syscfg0_base;
void __iomem *da8xx_syscfg1_base;

static struct plat_serial8250_port da8xx_serial_pdata[] = {
    {
        .mapbase    = DA8XX_UART0_BASE,
        .irq        = IRQ_DA8XX_UARTINT0,
        .flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
                    UPF_IOREMAP,
        .iotype        = UPIO_MEM,
        .regshift    = 2,
    },
    {
        .mapbase    = DA8XX_UART1_BASE,
        .irq        = IRQ_DA8XX_UARTINT1,
        .flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
                    UPF_IOREMAP,
        .iotype        = UPIO_MEM,
        .regshift    = 2,
    },
    {
        .mapbase    = DA8XX_UART2_BASE,
        .irq        = IRQ_DA8XX_UARTINT2,
        .flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
                    UPF_IOREMAP,
        .iotype        = UPIO_MEM,
        .regshift    = 2,
    },
    {
        .flags    = 0,
    },
};

struct platform_device da8xx_serial_device = {
    .name    = "serial8250",
    .id    = PLAT8250_DEV_PLATFORM,
    .dev    = {
        .platform_data    = da8xx_serial_pdata,
    },
};

static const s8 da8xx_queue_tc_mapping[][2] = {
    /* {event queue no, TC no} */
    {0, 0},
    {1, 1},
    {-1, -1}
};

static const s8 da8xx_queue_priority_mapping[][2] = {
    /* {event queue no, Priority} */
    {0, 3},
    {1, 7},
    {-1, -1}
};

static const s8 da850_queue_tc_mapping[][2] = {
    /* {event queue no, TC no} */
    {0, 0},
    {-1, -1}
};

static const s8 da850_queue_priority_mapping[][2] = {
    /* {event queue no, Priority} */
    {0, 3},
    {-1, -1}
};

static struct edma_soc_info da830_edma_cc0_info = {
    .n_channel        = 32,
    .n_region        = 4,
    .n_slot            = 128,
    .n_tc            = 2,
    .n_cc            = 1,
    .queue_tc_mapping    = da8xx_queue_tc_mapping,
    .queue_priority_mapping    = da8xx_queue_priority_mapping,
};

static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
    &da830_edma_cc0_info,
};

static struct edma_soc_info da850_edma_cc_info[] = {
    {
        .n_channel        = 32,
        .n_region        = 4,
        .n_slot            = 128,
        .n_tc            = 2,
        .n_cc            = 1,
        .queue_tc_mapping    = da8xx_queue_tc_mapping,
        .queue_priority_mapping    = da8xx_queue_priority_mapping,
    },
    {
        .n_channel        = 32,
        .n_region        = 4,
        .n_slot            = 128,
        .n_tc            = 1,
        .n_cc            = 1,
        .queue_tc_mapping    = da850_queue_tc_mapping,
        .queue_priority_mapping    = da850_queue_priority_mapping,
    },
};

static struct edma_soc_info *da850_edma_info[EDMA_MAX_CC] = {
    &da850_edma_cc_info[0],
    &da850_edma_cc_info[1],
};

static struct resource da830_edma_resources[] = {
    {
        .name    = "edma_cc0",
        .start    = DA8XX_TPCC_BASE,
        .end    = DA8XX_TPCC_BASE + SZ_32K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_tc0",
        .start    = DA8XX_TPTC0_BASE,
        .end    = DA8XX_TPTC0_BASE + SZ_1K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_tc1",
        .start    = DA8XX_TPTC1_BASE,
        .end    = DA8XX_TPTC1_BASE + SZ_1K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma0",
        .start    = IRQ_DA8XX_CCINT0,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .name    = "edma0_err",
        .start    = IRQ_DA8XX_CCERRINT,
        .flags    = IORESOURCE_IRQ,
    },
};

static struct resource da850_edma_resources[] = {
    {
        .name    = "edma_cc0",
        .start    = DA8XX_TPCC_BASE,
        .end    = DA8XX_TPCC_BASE + SZ_32K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_tc0",
        .start    = DA8XX_TPTC0_BASE,
        .end    = DA8XX_TPTC0_BASE + SZ_1K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_tc1",
        .start    = DA8XX_TPTC1_BASE,
        .end    = DA8XX_TPTC1_BASE + SZ_1K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_cc1",
        .start    = DA850_TPCC1_BASE,
        .end    = DA850_TPCC1_BASE + SZ_32K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma_tc2",
        .start    = DA850_TPTC2_BASE,
        .end    = DA850_TPTC2_BASE + SZ_1K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .name    = "edma0",
        .start    = IRQ_DA8XX_CCINT0,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .name    = "edma0_err",
        .start    = IRQ_DA8XX_CCERRINT,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .name    = "edma1",
        .start    = IRQ_DA850_CCINT1,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .name    = "edma1_err",
        .start    = IRQ_DA850_CCERRINT1,
        .flags    = IORESOURCE_IRQ,
    },
};

static struct platform_device da830_edma_device = {
    .name        = "edma",
    .id        = -1,
    .dev = {
        .platform_data = da830_edma_info,
    },
    .num_resources    = ARRAY_SIZE(da830_edma_resources),
    .resource    = da830_edma_resources,
};

static struct platform_device da850_edma_device = {
    .name        = "edma",
    .id        = -1,
    .dev = {
        .platform_data = da850_edma_info,
    },
    .num_resources    = ARRAY_SIZE(da850_edma_resources),
    .resource    = da850_edma_resources,
};

int __init da830_register_edma(struct edma_rsv_info *rsv)
{
    da830_edma_cc0_info.rsv = rsv;

    return platform_device_register(&da830_edma_device);
}

int __init da850_register_edma(struct edma_rsv_info *rsv[2])
{
    if (rsv) {
        da850_edma_cc_info[0].rsv = rsv[0];
        da850_edma_cc_info[1].rsv = rsv[1];
    }

    return platform_device_register(&da850_edma_device);
}

static struct resource da8xx_i2c_resources0[] = {
    {
        .start    = DA8XX_I2C0_BASE,
        .end    = DA8XX_I2C0_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .start    = IRQ_DA8XX_I2CINT0,
        .end    = IRQ_DA8XX_I2CINT0,
        .flags    = IORESOURCE_IRQ,
    },
};

static struct platform_device da8xx_i2c_device0 = {
    .name        = "i2c_davinci",
    .id        = 1,
    .num_resources    = ARRAY_SIZE(da8xx_i2c_resources0),
    .resource    = da8xx_i2c_resources0,
};

static struct resource da8xx_i2c_resources1[] = {
    {
        .start    = DA8XX_I2C1_BASE,
        .end    = DA8XX_I2C1_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .start    = IRQ_DA8XX_I2CINT1,
        .end    = IRQ_DA8XX_I2CINT1,
        .flags    = IORESOURCE_IRQ,
    },
};

static struct platform_device da8xx_i2c_device1 = {
    .name        = "i2c_davinci",
    .id        = 2,
    .num_resources    = ARRAY_SIZE(da8xx_i2c_resources1),
    .resource    = da8xx_i2c_resources1,
};

int __init da8xx_register_i2c(int instance,
        struct davinci_i2c_platform_data *pdata)
{
    struct platform_device *pdev;

    if (instance == 0)
        pdev = &da8xx_i2c_device0;
    else if (instance == 1)
        pdev = &da8xx_i2c_device1;
    else
        return -EINVAL;

    pdev->dev.platform_data = pdata;
    return platform_device_register(pdev);
}

static struct resource da8xx_watchdog_resources[] = {
    {
        .start    = DA8XX_WDOG_BASE,
        .end    = DA8XX_WDOG_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
};

struct platform_device da8xx_wdt_device = {
    .name        = "watchdog",
    .id        = -1,
    .num_resources    = ARRAY_SIZE(da8xx_watchdog_resources),
    .resource    = da8xx_watchdog_resources,
};

int __init da8xx_register_watchdog(void)
{
    return platform_device_register(&da8xx_wdt_device);
}

static struct resource da8xx_emac_resources[] = {
    {
        .start    = DA8XX_EMAC_CPPI_PORT_BASE,
        .end    = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {
        .start    = IRQ_DA8XX_C0_RX_THRESH_PULSE,
        .end    = IRQ_DA8XX_C0_RX_THRESH_PULSE,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start    = IRQ_DA8XX_C0_RX_PULSE,
        .end    = IRQ_DA8XX_C0_RX_PULSE,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start    = IRQ_DA8XX_C0_TX_PULSE,
        .end    = IRQ_DA8XX_C0_TX_PULSE,
        .flags    = IORESOURCE_IRQ,
    },
    {
        .start    = IRQ_DA8XX_C0_MISC_PULSE,
        .end    = IRQ_DA8XX_C0_MISC_PULSE,
        .flags    = IORESOURCE_IRQ,
    },
};

struct emac_platform_data da8xx_emac_pdata = {
    .ctrl_reg_offset    = DA8XX_EMAC_CTRL_REG_OFFSET,
    .ctrl_mod_reg_offset    = DA8XX_EMAC_MOD_REG_OFFSET,
    .ctrl_ram_offset    = DA8XX_EMAC_RAM_OFFSET,
    .ctrl_ram_size        = DA8XX_EMAC_CTRL_RAM_SIZE,
    .version        = EMAC_VERSION_2,
};

static struct platform_device da8xx_emac_device = {
    .name        = "davinci_emac",
    .id        = 1,
    .dev = {
        .platform_data    = &da8xx_emac_pdata,
    },
    .num_resources    = ARRAY_SIZE(da8xx_emac_resources),
    .resource    = da8xx_emac_resources,
};

static struct resource da8xx_mdio_resources[] = {
    {
        .start    = DA8XX_EMAC_MDIO_BASE,
        .end    = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
};

static struct platform_device da8xx_mdio_device = {
    .name        = "davinci_mdio",
    .id        = 0,
    .num_resources    = ARRAY_SIZE(da8xx_mdio_resources),
    .resource    = da8xx_mdio_resources,
};

int __init da8xx_register_emac(void)
{
    int ret;

    ret = platform_device_register(&da8xx_mdio_device);
    if (ret < 0)
        return ret;
    ret = platform_device_register(&da8xx_emac_device);
    if (ret < 0)
        return ret;
    ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev),
                NULL, &da8xx_emac_device.dev);
    return ret;
}

static struct resource da830_mcasp1_resources[] = {
    {
        .name    = "mcasp1",
        .start    = DAVINCI_DA830_MCASP1_REG_BASE,
        .end    = DAVINCI_DA830_MCASP1_REG_BASE + (SZ_1K * 12) - 1,
        .flags    = IORESOURCE_MEM,
    },
    /* TX event */
    {
        .start    = DAVINCI_DA830_DMA_MCASP1_AXEVT,
        .end    = DAVINCI_DA830_DMA_MCASP1_AXEVT,
        .flags    = IORESOURCE_DMA,
    },
    /* RX event */
    {
        .start    = DAVINCI_DA830_DMA_MCASP1_AREVT,
        .end    = DAVINCI_DA830_DMA_MCASP1_AREVT,
        .flags    = IORESOURCE_DMA,
    },
};

static struct platform_device da830_mcasp1_device = {
    .name        = "davinci-mcasp",
    .id        = 1,
    .num_resources    = ARRAY_SIZE(da830_mcasp1_resources),
    .resource    = da830_mcasp1_resources,
};

static struct resource da850_mcasp_resources[] = {
    {
        .name    = "mcasp",
        .start    = DAVINCI_DA8XX_MCASP0_REG_BASE,
        .end    = DAVINCI_DA8XX_MCASP0_REG_BASE + (SZ_1K * 12) - 1,
        .flags    = IORESOURCE_MEM,
    },
    /* TX event */
    {
        .start    = DAVINCI_DA8XX_DMA_MCASP0_AXEVT,
        .end    = DAVINCI_DA8XX_DMA_MCASP0_AXEVT,
        .flags    = IORESOURCE_DMA,
    },
    /* RX event */
    {
        .start    = DAVINCI_DA8XX_DMA_MCASP0_AREVT,
        .end    = DAVINCI_DA8XX_DMA_MCASP0_AREVT,
        .flags    = IORESOURCE_DMA,
    },
};

static struct platform_device da850_mcasp_device = {
    .name        = "davinci-mcasp",
    .id        = 0,
    .num_resources    = ARRAY_SIZE(da850_mcasp_resources),
    .resource    = da850_mcasp_resources,
};

struct platform_device davinci_pcm_device = {
    .name    = "davinci-pcm-audio",
    .id    = -1,
};

void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
{
    platform_device_register(&davinci_pcm_device);

    /* DA830/OMAP-L137 has 3 instances of McASP */
    if (cpu_is_davinci_da830() && id == 1) {
        da830_mcasp1_device.dev.platform_data = pdata;
        platform_device_register(&da830_mcasp1_device);
    } else if (cpu_is_davinci_da850()) {
        da850_mcasp_device.dev.platform_data = pdata;
        platform_device_register(&da850_mcasp_device);
    }
}

static const struct display_panel disp_panel = {
    QVGA,
    16,
    16,
    COLOR_ACTIVE,
};

static struct lcd_ctrl_config lcd_cfg = {
    &disp_panel,
    .ac_bias        = 255,
    .ac_bias_intrpt        = 0,
    .dma_burst_sz        = 16,
    .bpp            = 16,
    .fdd            = 255,
    .tft_alt_mode        = 0,
    .stn_565_mode        = 0,
    .mono_8bit_mode        = 0,
    .invert_line_clock    = 1,
    .invert_frm_clock    = 1,
    .sync_edge        = 0,
    .sync_ctrl        = 1,
    .raster_order        = 0,
};

struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
    .manu_name        = "sharp",
    .controller_data    = &lcd_cfg,
    .type            = "Sharp_LCD035Q3DG01",
};

struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata = {
    .manu_name        = "sharp",
    .controller_data    = &lcd_cfg,
    .type            = "Sharp_LK043T1DG01",
};

static struct resource da8xx_lcdc_resources[] = {
    [0] = { /* registers */
        .start  = DA8XX_LCD_CNTRL_BASE,
        .end    = DA8XX_LCD_CNTRL_BASE + SZ_4K - 1,
        .flags  = IORESOURCE_MEM,
    },
    [1] = { /* interrupt */
        .start  = IRQ_DA8XX_LCDINT,
        .end    = IRQ_DA8XX_LCDINT,
        .flags  = IORESOURCE_IRQ,
    },
};

static struct platform_device da8xx_lcdc_device = {
    .name        = "da8xx_lcdc",
    .id        = 0,
    .num_resources    = ARRAY_SIZE(da8xx_lcdc_resources),
    .resource    = da8xx_lcdc_resources,
};

int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata)
{
    da8xx_lcdc_device.dev.platform_data = pdata;
    return platform_device_register(&da8xx_lcdc_device);
}

static struct resource da8xx_mmcsd0_resources[] = {
    {        /* registers */
        .start    = DA8XX_MMCSD0_BASE,
        .end    = DA8XX_MMCSD0_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {        /* interrupt */
        .start    = IRQ_DA8XX_MMCSDINT0,
        .end    = IRQ_DA8XX_MMCSDINT0,
        .flags    = IORESOURCE_IRQ,
    },
    {        /* DMA RX */
        .start    = DA8XX_DMA_MMCSD0_RX,
        .end    = DA8XX_DMA_MMCSD0_RX,
        .flags    = IORESOURCE_DMA,
    },
    {        /* DMA TX */
        .start    = DA8XX_DMA_MMCSD0_TX,
        .end    = DA8XX_DMA_MMCSD0_TX,
        .flags    = IORESOURCE_DMA,
    },
};

static struct platform_device da8xx_mmcsd0_device = {
    .name        = "davinci_mmc",
    .id        = 0,
    .num_resources    = ARRAY_SIZE(da8xx_mmcsd0_resources),
    .resource    = da8xx_mmcsd0_resources,
};

int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config)
{
    da8xx_mmcsd0_device.dev.platform_data = config;
    return platform_device_register(&da8xx_mmcsd0_device);
}

#ifdef CONFIG_ARCH_DAVINCI_DA850
static struct resource da850_mmcsd1_resources[] = {
    {        /* registers */
        .start    = DA850_MMCSD1_BASE,
        .end    = DA850_MMCSD1_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    {        /* interrupt */
        .start    = IRQ_DA850_MMCSDINT0_1,
        .end    = IRQ_DA850_MMCSDINT0_1,
        .flags    = IORESOURCE_IRQ,
    },
    {        /* DMA RX */
        .start    = DA850_DMA_MMCSD1_RX,
        .end    = DA850_DMA_MMCSD1_RX,
        .flags    = IORESOURCE_DMA,
    },
    {        /* DMA TX */
        .start    = DA850_DMA_MMCSD1_TX,
        .end    = DA850_DMA_MMCSD1_TX,
        .flags    = IORESOURCE_DMA,
    },
};

static struct platform_device da850_mmcsd1_device = {
    .name        = "davinci_mmc",
    .id        = 1,
    .num_resources    = ARRAY_SIZE(da850_mmcsd1_resources),
    .resource    = da850_mmcsd1_resources,
};

int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
{
    da850_mmcsd1_device.dev.platform_data = config;
    return platform_device_register(&da850_mmcsd1_device);
}
#endif

static struct resource da8xx_rtc_resources[] = {
    {
        .start        = DA8XX_RTC_BASE,
        .end        = DA8XX_RTC_BASE + SZ_4K - 1,
        .flags        = IORESOURCE_MEM,
    },
    { /* timer irq */
        .start        = IRQ_DA8XX_RTC,
        .end        = IRQ_DA8XX_RTC,
        .flags        = IORESOURCE_IRQ,
    },
    { /* alarm irq */
        .start        = IRQ_DA8XX_RTC,
        .end        = IRQ_DA8XX_RTC,
        .flags        = IORESOURCE_IRQ,
    },
};

static struct platform_device da8xx_rtc_device = {
    .name           = "omap_rtc",
    .id             = -1,
    .num_resources    = ARRAY_SIZE(da8xx_rtc_resources),
    .resource    = da8xx_rtc_resources,
};

int da8xx_register_rtc(void)
{
    int ret;
    void __iomem *base;

    base = ioremap(DA8XX_RTC_BASE, SZ_4K);
    if (WARN_ON(!base))
        return -ENOMEM;

    /* Unlock the rtc's registers */
    __raw_writel(0x83e70b13, base + 0x6c);
    __raw_writel(0x95a4f1e0, base + 0x70);

    iounmap(base);

    ret = platform_device_register(&da8xx_rtc_device);
    if (!ret)
        /* Atleast on DA850, RTC is a wakeup source */
        device_init_wakeup(&da8xx_rtc_device.dev, true);

    return ret;
}

static void __iomem *da8xx_ddr2_ctlr_base;
void __iomem * __init da8xx_get_mem_ctlr(void)
{
    if (da8xx_ddr2_ctlr_base)
        return da8xx_ddr2_ctlr_base;

    da8xx_ddr2_ctlr_base = ioremap(DA8XX_DDR2_CTL_BASE, SZ_32K);
    if (!da8xx_ddr2_ctlr_base)
        pr_warning("%s: Unable to map DDR2 controller",    __func__);

    return da8xx_ddr2_ctlr_base;
}

static struct resource da8xx_cpuidle_resources[] = {
    {
        .start        = DA8XX_DDR2_CTL_BASE,
        .end        = DA8XX_DDR2_CTL_BASE + SZ_32K - 1,
        .flags        = IORESOURCE_MEM,
    },
};

/* DA8XX devices support DDR2 power down */
static struct davinci_cpuidle_config da8xx_cpuidle_pdata = {
    .ddr2_pdown    = 1,
};


static struct platform_device da8xx_cpuidle_device = {
    .name            = "cpuidle-davinci",
    .num_resources        = ARRAY_SIZE(da8xx_cpuidle_resources),
    .resource        = da8xx_cpuidle_resources,
    .dev = {
        .platform_data    = &da8xx_cpuidle_pdata,
    },
};

int __init da8xx_register_cpuidle(void)
{
    da8xx_cpuidle_pdata.ddr2_ctlr_base = da8xx_get_mem_ctlr();

    return platform_device_register(&da8xx_cpuidle_device);
}

static struct resource da8xx_spi0_resources[] = {
    [0] = {
        .start    = DA8XX_SPI0_BASE,
        .end    = DA8XX_SPI0_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    [1] = {
        .start    = IRQ_DA8XX_SPINT0,
        .end    = IRQ_DA8XX_SPINT0,
        .flags    = IORESOURCE_IRQ,
    },
    [2] = {
        .start    = DA8XX_DMA_SPI0_RX,
        .end    = DA8XX_DMA_SPI0_RX,
        .flags    = IORESOURCE_DMA,
    },
    [3] = {
        .start    = DA8XX_DMA_SPI0_TX,
        .end    = DA8XX_DMA_SPI0_TX,
        .flags    = IORESOURCE_DMA,
    },
};

static struct resource da8xx_spi1_resources[] = {
    [0] = {
        .start    = DA830_SPI1_BASE,
        .end    = DA830_SPI1_BASE + SZ_4K - 1,
        .flags    = IORESOURCE_MEM,
    },
    [1] = {
        .start    = IRQ_DA8XX_SPINT1,
        .end    = IRQ_DA8XX_SPINT1,
        .flags    = IORESOURCE_IRQ,
    },
    [2] = {
        .start    = DA8XX_DMA_SPI1_RX,
        .end    = DA8XX_DMA_SPI1_RX,
        .flags    = IORESOURCE_DMA,
    },
    [3] = {
        .start    = DA8XX_DMA_SPI1_TX,
        .end    = DA8XX_DMA_SPI1_TX,
        .flags    = IORESOURCE_DMA,
    },
};

struct davinci_spi_platform_data da8xx_spi_pdata[] = {
    [0] = {
        .version    = SPI_VERSION_2,
        .intr_line    = 1,
        .dma_event_q    = EVENTQ_0,
    },
    [1] = {
        .version    = SPI_VERSION_2,
        .intr_line    = 1,
        .dma_event_q    = EVENTQ_0,
    },
};

static struct platform_device da8xx_spi_device[] = {
    [0] = {
        .name        = "spi_davinci",
        .id        = 0,
        .num_resources    = ARRAY_SIZE(da8xx_spi0_resources),
        .resource    = da8xx_spi0_resources,
        .dev        = {
            .platform_data = &da8xx_spi_pdata[0],
        },
    },
    [1] = {
        .name        = "spi_davinci",
        .id        = 1,
        .num_resources    = ARRAY_SIZE(da8xx_spi1_resources),
        .resource    = da8xx_spi1_resources,
        .dev        = {
            .platform_data = &da8xx_spi_pdata[1],
        },
    },
};

int __init da8xx_register_spi(int instance, struct spi_board_info *info,
                  unsigned len)
{
    int ret;

    if (instance < 0 || instance > 1)
        return -EINVAL;

    ret = spi_register_board_info(info, len);
    if (ret)
        pr_warning("%s: failed to register board info for spi %d :"
               " %d\n", __func__, instance, ret);

    da8xx_spi_pdata[instance].num_chipselect = len;

    if (instance == 1 && cpu_is_davinci_da850()) {
        da8xx_spi1_resources[0].start = DA850_SPI1_BASE;
        da8xx_spi1_resources[0].end = DA850_SPI1_BASE + SZ_4K - 1;
    }

    return platform_device_register(&da8xx_spi_device[instance]);
}