#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/clk.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
}
#endif
-#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
-#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
+#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-static struct resource mbox_resources[] = {
+#define MBOX_REG_SIZE 0x120
+
+static struct resource omap2_mbox_resources[] = {
{
- .start = OMAP2_MBOX_BASE,
- .end = OMAP2_MBOX_BASE + 0x11f,
+ .start = OMAP24XX_MAILBOX_BASE,
+ .end = OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
},
};
+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,
+ },
+};
+
static struct platform_device mbox_device = {
- .name = "mailbox",
+ .name = "omap2-mailbox",
.id = -1,
- .num_resources = ARRAY_SIZE(mbox_resources),
- .resource = mbox_resources,
};
static inline void omap_init_mbox(void)
{
+ if (cpu_is_omap2420()) {
+ mbox_device.num_resources = ARRAY_SIZE(omap2_mbox_resources);
+ mbox_device.resource = omap2_mbox_resources;
+ } else if (cpu_is_omap3430()) {
+ mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
+ mbox_device.resource = omap3_mbox_resources;
+ } else {
+ return;
+ }
platform_device_register(&mbox_device);
}
#else
static inline void omap_init_mbox(void) { }
-#endif
+#endif /* CONFIG_OMAP_MBOX_FWK */
#if defined(CONFIG_OMAP_STI)
/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_ARCH_OMAP3
+
+#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 = cpu_is_omap34xx() ? OMAP34XX_NR_MMC :
+ OMAP24XX_NR_MMC;
+
+ for (i = 0; i < nr_controllers; i++) {
+ u32 v, base = 0;
+ struct clk *iclk, *fclk;
+ 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;
+ }
+
+ dummy_pdev.id = i;
+ iclk = clk_get(dev, "mmchs_ick");
+ if (iclk && clk_enable(iclk))
+ iclk = NULL;
+
+ fclk = clk_get(dev, "mmchs_fck");
+ if (fclk && clk_enable(fclk))
+ fclk = NULL;
+
+ if (!iclk || !fclk) {
+ printk(KERN_WARNING
+ "%s: Unable to enable clocks for MMC%d, "
+ "cannot reset.\n", __func__, i);
+ break;
+ }
+
+ 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();
+
+ if (fclk) {
+ clk_disable(fclk);
+ clk_put(fclk);
+ }
+ if (iclk) {
+ clk_disable(iclk);
+ clk_put(iclk);
+ }
+ }
+}
+#else
+static inline void omap_hsmmc_reset(void) {}
+#endif
+
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
+ omap_hsmmc_reset();
omap_init_camera();
omap_init_mbox();
omap_init_mcspi();