forked from Minki/linux
e08016d0f4
The MMC controller on the OMAP2420 is different from those on the OMAP2430, OMAP3 and OMAP4 families - all of the latter are identical. The one on the OMAP2420 is closer to that on OMAP1 chips. Currently, the n8x0 is the only OMAP2420 platform supported in mainline which registers the MMC controller. Upcoming changes to register the controllers using hwmod data are potentially invasive. To reduce the risk, separate out the 2420 controller registration from the common init function and update its only user. Also seperating out mux settings for OMAP2420. Signed-off-by: Anand Gadiyar <gadiyar@ti.com> Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com> Cc: Tony Lindgren <tony@atomide.com> Cc: Madhusudhan Chikkature <madhu.cr@ti.com> Cc: Chris Ball <cjb@laptop.org> Signed-off-by: Tony Lindgren <tony@atomide.com>
973 lines
23 KiB
C
973 lines
23 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"
|
|
|
|
#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)
|
|
|
|
#define MBOX_REG_SIZE 0x120
|
|
|
|
#ifdef CONFIG_ARCH_OMAP2
|
|
static struct resource omap2_mbox_resources[] = {
|
|
{
|
|
.start = OMAP24XX_MAILBOX_BASE,
|
|
.end = OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
{
|
|
.start = INT_24XX_MAIL_U0_MPU,
|
|
.flags = IORESOURCE_IRQ,
|
|
.name = "dsp",
|
|
},
|
|
{
|
|
.start = INT_24XX_MAIL_U3_MPU,
|
|
.flags = IORESOURCE_IRQ,
|
|
.name = "iva",
|
|
},
|
|
};
|
|
static int omap2_mbox_resources_sz = ARRAY_SIZE(omap2_mbox_resources);
|
|
#else
|
|
#define omap2_mbox_resources NULL
|
|
#define omap2_mbox_resources_sz 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARCH_OMAP3
|
|
static struct resource omap3_mbox_resources[] = {
|
|
{
|
|
.start = OMAP34XX_MAILBOX_BASE,
|
|
.end = OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
{
|
|
.start = INT_24XX_MAIL_U0_MPU,
|
|
.flags = IORESOURCE_IRQ,
|
|
.name = "dsp",
|
|
},
|
|
};
|
|
static int omap3_mbox_resources_sz = ARRAY_SIZE(omap3_mbox_resources);
|
|
#else
|
|
#define omap3_mbox_resources NULL
|
|
#define omap3_mbox_resources_sz 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARCH_OMAP4
|
|
|
|
#define OMAP4_MBOX_REG_SIZE 0x130
|
|
static struct resource omap4_mbox_resources[] = {
|
|
{
|
|
.start = OMAP44XX_MAILBOX_BASE,
|
|
.end = OMAP44XX_MAILBOX_BASE +
|
|
OMAP4_MBOX_REG_SIZE - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
{
|
|
.start = OMAP44XX_IRQ_MAIL_U0,
|
|
.flags = IORESOURCE_IRQ,
|
|
.name = "mbox",
|
|
},
|
|
};
|
|
static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources);
|
|
#else
|
|
#define omap4_mbox_resources NULL
|
|
#define omap4_mbox_resources_sz 0
|
|
#endif
|
|
|
|
static struct platform_device mbox_device = {
|
|
.name = "omap-mailbox",
|
|
.id = -1,
|
|
};
|
|
|
|
static inline void omap_init_mbox(void)
|
|
{
|
|
if (cpu_is_omap24xx()) {
|
|
mbox_device.resource = omap2_mbox_resources;
|
|
mbox_device.num_resources = omap2_mbox_resources_sz;
|
|
} else if (cpu_is_omap34xx()) {
|
|
mbox_device.resource = omap3_mbox_resources;
|
|
mbox_device.num_resources = omap3_mbox_resources_sz;
|
|
} else if (cpu_is_omap44xx()) {
|
|
mbox_device.resource = omap4_mbox_resources;
|
|
mbox_device.num_resources = omap4_mbox_resources_sz;
|
|
} else {
|
|
pr_err("%s: platform not supported\n", __func__);
|
|
return;
|
|
}
|
|
platform_device_register(&mbox_device);
|
|
}
|
|
#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_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
|
|
|
|
#define MMCHS_SYSCONFIG 0x0010
|
|
#define MMCHS_SYSCONFIG_SWRESET (1 << 1)
|
|
#define MMCHS_SYSSTATUS 0x0014
|
|
#define MMCHS_SYSSTATUS_RESETDONE (1 << 0)
|
|
|
|
static struct platform_device dummy_pdev = {
|
|
.dev = {
|
|
.bus = &platform_bus_type,
|
|
},
|
|
};
|
|
|
|
/**
|
|
* omap_hsmmc_reset() - Full reset of each HS-MMC controller
|
|
*
|
|
* Ensure that each MMC controller is fully reset. Controllers
|
|
* left in an unknown state (by bootloader) may prevent retention
|
|
* or OFF-mode. This is especially important in cases where the
|
|
* MMC driver is not enabled, _or_ built as a module.
|
|
*
|
|
* In order for reset to work, interface, functional and debounce
|
|
* clocks must be enabled. The debounce clock comes from func_32k_clk
|
|
* and is not under SW control, so we only enable i- and f-clocks.
|
|
**/
|
|
static void __init omap_hsmmc_reset(void)
|
|
{
|
|
u32 i, nr_controllers;
|
|
struct clk *iclk, *fclk;
|
|
|
|
if (cpu_is_omap242x())
|
|
return;
|
|
|
|
nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC :
|
|
(cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC);
|
|
|
|
for (i = 0; i < nr_controllers; i++) {
|
|
u32 v, base = 0;
|
|
struct device *dev = &dummy_pdev.dev;
|
|
|
|
switch (i) {
|
|
case 0:
|
|
base = OMAP2_MMC1_BASE;
|
|
break;
|
|
case 1:
|
|
base = OMAP2_MMC2_BASE;
|
|
break;
|
|
case 2:
|
|
base = OMAP3_MMC3_BASE;
|
|
break;
|
|
case 3:
|
|
if (!cpu_is_omap44xx())
|
|
return;
|
|
base = OMAP4_MMC4_BASE;
|
|
break;
|
|
case 4:
|
|
if (!cpu_is_omap44xx())
|
|
return;
|
|
base = OMAP4_MMC5_BASE;
|
|
break;
|
|
}
|
|
|
|
if (cpu_is_omap44xx())
|
|
base += OMAP4_MMC_REG_OFFSET;
|
|
|
|
dummy_pdev.id = i;
|
|
dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
|
|
iclk = clk_get(dev, "ick");
|
|
if (IS_ERR(iclk))
|
|
goto err1;
|
|
if (clk_enable(iclk))
|
|
goto err2;
|
|
|
|
fclk = clk_get(dev, "fck");
|
|
if (IS_ERR(fclk))
|
|
goto err3;
|
|
if (clk_enable(fclk))
|
|
goto err4;
|
|
|
|
omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
|
|
v = omap_readl(base + MMCHS_SYSSTATUS);
|
|
while (!(omap_readl(base + MMCHS_SYSSTATUS) &
|
|
MMCHS_SYSSTATUS_RESETDONE))
|
|
cpu_relax();
|
|
|
|
clk_disable(fclk);
|
|
clk_put(fclk);
|
|
clk_disable(iclk);
|
|
clk_put(iclk);
|
|
}
|
|
return;
|
|
|
|
err4:
|
|
clk_put(fclk);
|
|
err3:
|
|
clk_disable(iclk);
|
|
err2:
|
|
clk_put(iclk);
|
|
err1:
|
|
printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, "
|
|
"cannot reset.\n", __func__, i);
|
|
}
|
|
#else
|
|
static inline void omap_hsmmc_reset(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_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
|
|
|
|
static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
|
|
int controller_nr)
|
|
{
|
|
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);
|
|
if (cpu_is_omap34xx()) {
|
|
if (controller_nr == 0) {
|
|
omap_mux_init_signal("sdmmc1_clk",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_cmd",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat0",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
if (mmc_controller->slots[0].caps &
|
|
(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
|
|
omap_mux_init_signal("sdmmc1_dat1",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat2",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat3",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
}
|
|
if (mmc_controller->slots[0].caps &
|
|
MMC_CAP_8_BIT_DATA) {
|
|
omap_mux_init_signal("sdmmc1_dat4",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat5",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat6",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc1_dat7",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
}
|
|
}
|
|
if (controller_nr == 1) {
|
|
/* MMC2 */
|
|
omap_mux_init_signal("sdmmc2_clk",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_cmd",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat0",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
|
|
/*
|
|
* For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
|
|
* in the board-*.c files
|
|
*/
|
|
if (mmc_controller->slots[0].caps &
|
|
(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
|
|
omap_mux_init_signal("sdmmc2_dat1",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat2",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat3",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
}
|
|
if (mmc_controller->slots[0].caps &
|
|
MMC_CAP_8_BIT_DATA) {
|
|
omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
|
|
OMAP_PIN_INPUT_PULLUP);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* For MMC3 the pins need to be muxed in the board-*.c files
|
|
*/
|
|
}
|
|
}
|
|
|
|
void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
|
|
int nr_controllers)
|
|
{
|
|
int i;
|
|
char *name;
|
|
|
|
for (i = 0; i < nr_controllers; i++) {
|
|
unsigned long base, size;
|
|
unsigned int irq = 0;
|
|
|
|
if (!mmc_data[i])
|
|
continue;
|
|
|
|
omap2_mmc_mux(mmc_data[i], i);
|
|
|
|
switch (i) {
|
|
case 0:
|
|
base = OMAP2_MMC1_BASE;
|
|
irq = INT_24XX_MMC_IRQ;
|
|
break;
|
|
case 1:
|
|
base = OMAP2_MMC2_BASE;
|
|
irq = INT_24XX_MMC2_IRQ;
|
|
break;
|
|
case 2:
|
|
if (!cpu_is_omap44xx() && !cpu_is_omap34xx())
|
|
return;
|
|
base = OMAP3_MMC3_BASE;
|
|
irq = INT_34XX_MMC3_IRQ;
|
|
break;
|
|
case 3:
|
|
if (!cpu_is_omap44xx())
|
|
return;
|
|
base = OMAP4_MMC4_BASE;
|
|
irq = OMAP44XX_IRQ_MMC4;
|
|
break;
|
|
case 4:
|
|
if (!cpu_is_omap44xx())
|
|
return;
|
|
base = OMAP4_MMC5_BASE;
|
|
irq = OMAP44XX_IRQ_MMC5;
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
if (cpu_is_omap44xx()) {
|
|
if (i < 3)
|
|
irq += OMAP44XX_IRQ_GIC_START;
|
|
size = OMAP4_HSMMC_SIZE;
|
|
name = "mmci-omap-hs";
|
|
} else {
|
|
size = OMAP3_HSMMC_SIZE;
|
|
name = "mmci-omap-hs";
|
|
}
|
|
omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
|
|
};
|
|
}
|
|
|
|
#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_hsmmc_reset();
|
|
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
|