linux/arch/arm/mach-omap2/devices.c
sricharan a4dc616ae3 OMAP4: Initialise the l3 device with the hwmod data.
The l3 interconnect device is build with all the data required
to handle the error logging. The data is extracted from the
hwmod data base.

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: sricharan <r.sricharan@ti.com>
Acked-by: Benoit Cousson <b-cousson@ti.com>
2011-03-09 17:23:57 +05:30

720 lines
17 KiB
C

/*
* linux/arch/arm/mach-omap2/devices.c
*
* OMAP2 platform device setup/initialization
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/pmu.h>
#include <plat/tc.h>
#include <plat/board.h>
#include <plat/mcbsp.h>
#include <mach/gpio.h>
#include <plat/mmc.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
#include <plat/omap4-keypad.h>
#include "mux.h"
#include "control.h"
#define L3_MODULES_MAX_LEN 12
#define L3_MODULES 3
static int __init omap3_l3_init(void)
{
int l;
struct omap_hwmod *oh;
struct omap_device *od;
char oh_name[L3_MODULES_MAX_LEN];
/*
* To avoid code running on other OMAPs in
* multi-omap builds
*/
if (!(cpu_is_omap34xx()))
return -ENODEV;
l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
oh = omap_hwmod_lookup(oh_name);
if (!oh)
pr_err("could not look up %s\n", oh_name);
od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
NULL, 0, 0);
WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
return PTR_ERR(od);
}
postcore_initcall(omap3_l3_init);
static int __init omap4_l3_init(void)
{
int l, i;
struct omap_hwmod *oh[3];
struct omap_device *od;
char oh_name[L3_MODULES_MAX_LEN];
/*
* To avoid code running on other OMAPs in
* multi-omap builds
*/
if (!(cpu_is_omap44xx()))
return -ENODEV;
for (i = 0; i < L3_MODULES; i++) {
l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
oh[i] = omap_hwmod_lookup(oh_name);
if (!(oh[i]))
pr_err("could not look up %s\n", oh_name);
}
od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
0, NULL, 0, 0);
WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
return PTR_ERR(od);
}
postcore_initcall(omap4_l3_init);
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
static struct resource cam_resources[] = {
{
.start = OMAP24XX_CAMERA_BASE,
.end = OMAP24XX_CAMERA_BASE + 0xfff,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_CAM_IRQ,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device omap_cam_device = {
.name = "omap24xxcam",
.id = -1,
.num_resources = ARRAY_SIZE(cam_resources),
.resource = cam_resources,
};
static inline void omap_init_camera(void)
{
platform_device_register(&omap_cam_device);
}
#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
static struct resource omap3isp_resources[] = {
{
.start = OMAP3430_ISP_BASE,
.end = OMAP3430_ISP_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_CBUFF_BASE,
.end = OMAP3430_ISP_CBUFF_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_CCP2_BASE,
.end = OMAP3430_ISP_CCP2_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_CCDC_BASE,
.end = OMAP3430_ISP_CCDC_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_HIST_BASE,
.end = OMAP3430_ISP_HIST_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_H3A_BASE,
.end = OMAP3430_ISP_H3A_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_PREV_BASE,
.end = OMAP3430_ISP_PREV_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_RESZ_BASE,
.end = OMAP3430_ISP_RESZ_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_SBL_BASE,
.end = OMAP3430_ISP_SBL_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_CSI2A_BASE,
.end = OMAP3430_ISP_CSI2A_END,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3430_ISP_CSI2PHY_BASE,
.end = OMAP3430_ISP_CSI2PHY_END,
.flags = IORESOURCE_MEM,
},
{
.start = INT_34XX_CAM_IRQ,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device omap3isp_device = {
.name = "omap3isp",
.id = -1,
.num_resources = ARRAY_SIZE(omap3isp_resources),
.resource = omap3isp_resources,
};
static inline void omap_init_camera(void)
{
platform_device_register(&omap3isp_device);
}
#else
static inline void omap_init_camera(void)
{
}
#endif
struct omap_device_pm_latency omap_keyboard_latency[] = {
{
.deactivate_func = omap_device_idle_hwmods,
.activate_func = omap_device_enable_hwmods,
.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
};
int __init omap4_keyboard_init(struct omap4_keypad_platform_data
*sdp4430_keypad_data)
{
struct omap_device *od;
struct omap_hwmod *oh;
struct omap4_keypad_platform_data *keypad_data;
unsigned int id = -1;
char *oh_name = "kbd";
char *name = "omap4-keypad";
oh = omap_hwmod_lookup(oh_name);
if (!oh) {
pr_err("Could not look up %s\n", oh_name);
return -ENODEV;
}
keypad_data = sdp4430_keypad_data;
od = omap_device_build(name, id, oh, keypad_data,
sizeof(struct omap4_keypad_platform_data),
omap_keyboard_latency,
ARRAY_SIZE(omap_keyboard_latency), 0);
if (IS_ERR(od)) {
WARN(1, "Cant build omap_device for %s:%s.\n",
name, oh->name);
return PTR_ERR(od);
}
return 0;
}
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
static struct omap_device_pm_latency mbox_latencies[] = {
[0] = {
.activate_func = omap_device_enable_hwmods,
.deactivate_func = omap_device_idle_hwmods,
.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
};
static inline void omap_init_mbox(void)
{
struct omap_hwmod *oh;
struct omap_device *od;
oh = omap_hwmod_lookup("mailbox");
if (!oh) {
pr_err("%s: unable to find hwmod\n", __func__);
return;
}
od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
__func__, PTR_ERR(od));
}
#else
static inline void omap_init_mbox(void) { }
#endif /* CONFIG_OMAP_MBOX_FWK */
static inline void omap_init_sti(void) {}
#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
static struct platform_device omap_pcm = {
.name = "omap-pcm-audio",
.id = -1,
};
/*
* OMAP2420 has 2 McBSP ports
* OMAP2430 has 5 McBSP ports
* OMAP3 has 5 McBSP ports
* OMAP4 has 4 McBSP ports
*/
OMAP_MCBSP_PLATFORM_DEVICE(1);
OMAP_MCBSP_PLATFORM_DEVICE(2);
OMAP_MCBSP_PLATFORM_DEVICE(3);
OMAP_MCBSP_PLATFORM_DEVICE(4);
OMAP_MCBSP_PLATFORM_DEVICE(5);
static void omap_init_audio(void)
{
platform_device_register(&omap_mcbsp1);
platform_device_register(&omap_mcbsp2);
if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
platform_device_register(&omap_mcbsp3);
platform_device_register(&omap_mcbsp4);
}
if (cpu_is_omap243x() || cpu_is_omap34xx())
platform_device_register(&omap_mcbsp5);
platform_device_register(&omap_pcm);
}
#else
static inline void omap_init_audio(void) {}
#endif
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
#include <plat/mcspi.h>
struct omap_device_pm_latency omap_mcspi_latency[] = {
[0] = {
.deactivate_func = omap_device_idle_hwmods,
.activate_func = omap_device_enable_hwmods,
.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
};
static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
{
struct omap_device *od;
char *name = "omap2_mcspi";
struct omap2_mcspi_platform_config *pdata;
static int spi_num;
struct omap2_mcspi_dev_attr *mcspi_attrib = oh->dev_attr;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
pr_err("Memory allocation for McSPI device failed\n");
return -ENOMEM;
}
pdata->num_cs = mcspi_attrib->num_chipselect;
switch (oh->class->rev) {
case OMAP2_MCSPI_REV:
case OMAP3_MCSPI_REV:
pdata->regs_offset = 0;
break;
case OMAP4_MCSPI_REV:
pdata->regs_offset = OMAP4_MCSPI_REG_OFFSET;
break;
default:
pr_err("Invalid McSPI Revision value\n");
return -EINVAL;
}
spi_num++;
od = omap_device_build(name, spi_num, oh, pdata,
sizeof(*pdata), omap_mcspi_latency,
ARRAY_SIZE(omap_mcspi_latency), 0);
WARN(IS_ERR(od), "Cant build omap_device for %s:%s\n",
name, oh->name);
kfree(pdata);
return 0;
}
static void omap_init_mcspi(void)
{
omap_hwmod_for_each_by_class("mcspi", omap_mcspi_init, NULL);
}
#else
static inline void omap_init_mcspi(void) {}
#endif
static struct resource omap2_pmu_resource = {
.start = 3,
.end = 3,
.flags = IORESOURCE_IRQ,
};
static struct resource omap3_pmu_resource = {
.start = INT_34XX_BENCH_MPU_EMUL,
.end = INT_34XX_BENCH_MPU_EMUL,
.flags = IORESOURCE_IRQ,
};
static struct platform_device omap_pmu_device = {
.name = "arm-pmu",
.id = ARM_PMU_DEVICE_CPU,
.num_resources = 1,
};
static void omap_init_pmu(void)
{
if (cpu_is_omap24xx())
omap_pmu_device.resource = &omap2_pmu_resource;
else if (cpu_is_omap34xx())
omap_pmu_device.resource = &omap3_pmu_resource;
else
return;
platform_device_register(&omap_pmu_device);
}
#if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
#ifdef CONFIG_ARCH_OMAP2
static struct resource omap2_sham_resources[] = {
{
.start = OMAP24XX_SEC_SHA1MD5_BASE,
.end = OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_SHA1MD5,
.flags = IORESOURCE_IRQ,
}
};
static int omap2_sham_resources_sz = ARRAY_SIZE(omap2_sham_resources);
#else
#define omap2_sham_resources NULL
#define omap2_sham_resources_sz 0
#endif
#ifdef CONFIG_ARCH_OMAP3
static struct resource omap3_sham_resources[] = {
{
.start = OMAP34XX_SEC_SHA1MD5_BASE,
.end = OMAP34XX_SEC_SHA1MD5_BASE + 0x64,
.flags = IORESOURCE_MEM,
},
{
.start = INT_34XX_SHA1MD52_IRQ,
.flags = IORESOURCE_IRQ,
},
{
.start = OMAP34XX_DMA_SHA1MD5_RX,
.flags = IORESOURCE_DMA,
}
};
static int omap3_sham_resources_sz = ARRAY_SIZE(omap3_sham_resources);
#else
#define omap3_sham_resources NULL
#define omap3_sham_resources_sz 0
#endif
static struct platform_device sham_device = {
.name = "omap-sham",
.id = -1,
};
static void omap_init_sham(void)
{
if (cpu_is_omap24xx()) {
sham_device.resource = omap2_sham_resources;
sham_device.num_resources = omap2_sham_resources_sz;
} else if (cpu_is_omap34xx()) {
sham_device.resource = omap3_sham_resources;
sham_device.num_resources = omap3_sham_resources_sz;
} else {
pr_err("%s: platform not supported\n", __func__);
return;
}
platform_device_register(&sham_device);
}
#else
static inline void omap_init_sham(void) { }
#endif
#if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
#ifdef CONFIG_ARCH_OMAP2
static struct resource omap2_aes_resources[] = {
{
.start = OMAP24XX_SEC_AES_BASE,
.end = OMAP24XX_SEC_AES_BASE + 0x4C,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP24XX_DMA_AES_TX,
.flags = IORESOURCE_DMA,
},
{
.start = OMAP24XX_DMA_AES_RX,
.flags = IORESOURCE_DMA,
}
};
static int omap2_aes_resources_sz = ARRAY_SIZE(omap2_aes_resources);
#else
#define omap2_aes_resources NULL
#define omap2_aes_resources_sz 0
#endif
#ifdef CONFIG_ARCH_OMAP3
static struct resource omap3_aes_resources[] = {
{
.start = OMAP34XX_SEC_AES_BASE,
.end = OMAP34XX_SEC_AES_BASE + 0x4C,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP34XX_DMA_AES2_TX,
.flags = IORESOURCE_DMA,
},
{
.start = OMAP34XX_DMA_AES2_RX,
.flags = IORESOURCE_DMA,
}
};
static int omap3_aes_resources_sz = ARRAY_SIZE(omap3_aes_resources);
#else
#define omap3_aes_resources NULL
#define omap3_aes_resources_sz 0
#endif
static struct platform_device aes_device = {
.name = "omap-aes",
.id = -1,
};
static void omap_init_aes(void)
{
if (cpu_is_omap24xx()) {
aes_device.resource = omap2_aes_resources;
aes_device.num_resources = omap2_aes_resources_sz;
} else if (cpu_is_omap34xx()) {
aes_device.resource = omap3_aes_resources;
aes_device.num_resources = omap3_aes_resources_sz;
} else {
pr_err("%s: platform not supported\n", __func__);
return;
}
platform_device_register(&aes_device);
}
#else
static inline void omap_init_aes(void) { }
#endif
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
*mmc_controller)
{
if ((mmc_controller->slots[0].switch_pin > 0) && \
(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
OMAP_PIN_INPUT_PULLUP);
if ((mmc_controller->slots[0].gpio_wp > 0) && \
(mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("sdmmc_cmd", 0);
omap_mux_init_signal("sdmmc_clki", 0);
omap_mux_init_signal("sdmmc_clko", 0);
omap_mux_init_signal("sdmmc_dat0", 0);
omap_mux_init_signal("sdmmc_dat_dir0", 0);
omap_mux_init_signal("sdmmc_cmd_dir", 0);
if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
omap_mux_init_signal("sdmmc_dat1", 0);
omap_mux_init_signal("sdmmc_dat2", 0);
omap_mux_init_signal("sdmmc_dat3", 0);
omap_mux_init_signal("sdmmc_dat_dir1", 0);
omap_mux_init_signal("sdmmc_dat_dir2", 0);
omap_mux_init_signal("sdmmc_dat_dir3", 0);
}
/*
* Use internal loop-back in MMC/SDIO Module Input Clock
* selection
*/
if (mmc_controller->slots[0].internal_clock) {
u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
v |= (1 << 24);
omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
}
}
void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
{
char *name = "mmci-omap";
if (!mmc_data[0]) {
pr_err("%s fails: Incomplete platform data\n", __func__);
return;
}
omap242x_mmc_mux(mmc_data[0]);
omap_mmc_add(name, 0, OMAP2_MMC1_BASE, OMAP2420_MMC_SIZE,
INT_24XX_MMC_IRQ, mmc_data[0]);
}
#endif
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
#define OMAP_HDQ_BASE 0x480B2000
#endif
static struct resource omap_hdq_resources[] = {
{
.start = OMAP_HDQ_BASE,
.end = OMAP_HDQ_BASE + 0x1C,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_HDQ_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device omap_hdq_dev = {
.name = "omap_hdq",
.id = 0,
.dev = {
.platform_data = NULL,
},
.num_resources = ARRAY_SIZE(omap_hdq_resources),
.resource = omap_hdq_resources,
};
static inline void omap_hdq_init(void)
{
(void) platform_device_register(&omap_hdq_dev);
}
#else
static inline void omap_hdq_init(void) {}
#endif
/*---------------------------------------------------------------------------*/
#if defined(CONFIG_VIDEO_OMAP2_VOUT) || \
defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE)
#if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
static struct resource omap_vout_resource[3 - CONFIG_FB_OMAP2_NUM_FBS] = {
};
#else
static struct resource omap_vout_resource[2] = {
};
#endif
static struct platform_device omap_vout_device = {
.name = "omap_vout",
.num_resources = ARRAY_SIZE(omap_vout_resource),
.resource = &omap_vout_resource[0],
.id = -1,
};
static void omap_init_vout(void)
{
if (platform_device_register(&omap_vout_device) < 0)
printk(KERN_ERR "Unable to register OMAP-VOUT device\n");
}
#else
static inline void omap_init_vout(void) {}
#endif
/*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void)
{
/*
* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
omap_init_audio();
omap_init_camera();
omap_init_mbox();
omap_init_mcspi();
omap_init_pmu();
omap_hdq_init();
omap_init_sti();
omap_init_sham();
omap_init_aes();
omap_init_vout();
return 0;
}
arch_initcall(omap2_init_devices);
#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
static struct omap_device_pm_latency omap_wdt_latency[] = {
[0] = {
.deactivate_func = omap_device_idle_hwmods,
.activate_func = omap_device_enable_hwmods,
.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
},
};
static int __init omap_init_wdt(void)
{
int id = -1;
struct omap_device *od;
struct omap_hwmod *oh;
char *oh_name = "wd_timer2";
char *dev_name = "omap_wdt";
if (!cpu_class_is_omap2())
return 0;
oh = omap_hwmod_lookup(oh_name);
if (!oh) {
pr_err("Could not look up wd_timer%d hwmod\n", id);
return -EINVAL;
}
od = omap_device_build(dev_name, id, oh, NULL, 0,
omap_wdt_latency,
ARRAY_SIZE(omap_wdt_latency), 0);
WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n",
dev_name, oh->name);
return 0;
}
subsys_initcall(omap_init_wdt);
#endif