mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-24 07:34:24 +00:00
1 correct the pata platform device resource check codes 2 Change the end statment of the sdhc1 det pin iomux definition on mx51 board from ',' to ';'. 3 sdhc driver max blk count on MX31, sinc customer report that the emmc would be failed when the blk count is more than 32. Signed-off-by: Richard Zhu <r65037@freescale.com>
1023 lines
23 KiB
C
1023 lines
23 KiB
C
/*
|
|
* Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
*/
|
|
|
|
/*
|
|
* The code contained herein is licensed under the GNU General Public
|
|
* License. You may obtain a copy of the GNU General Public License
|
|
* Version 2 or later at the following locations:
|
|
*
|
|
* http://www.opensource.org/licenses/gpl-license.html
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/init.h>
|
|
#include <linux/input.h>
|
|
#include <linux/nodemask.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/fsl_devices.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/ata.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/pmic_external.h>
|
|
#include <linux/smsc911x.h>
|
|
#include <linux/i2c/tsc2007.h>
|
|
#include <linux/ipu.h>
|
|
#include <linux/mxcfb.h>
|
|
#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/map.h>
|
|
#include <linux/mtd/partitions.h>
|
|
|
|
#include <asm/mach/flash.h>
|
|
#endif
|
|
|
|
#include <mach/hardware.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/setup.h>
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/mach/time.h>
|
|
#include <mach/common.h>
|
|
#include <mach/memory.h>
|
|
#include <mach/gpio.h>
|
|
#include <mach/mmc.h>
|
|
#include <mach/mxc_dvfs.h>
|
|
#include "board-mx37_3stack.h"
|
|
#include "iomux.h"
|
|
#include "crm_regs.h"
|
|
|
|
/*!
|
|
* @file mach-mx37/mx37_3stack.c
|
|
*
|
|
* @brief This file contains the board specific initialization routines.
|
|
*
|
|
* @ingroup MSL_MX37
|
|
*/
|
|
extern void gpio_lcd_active(void);
|
|
extern void mxc_init_srpgconfig(void);
|
|
|
|
/* working point(wp): 0 - 532MHz; 1 - 200MHz; */
|
|
static struct cpu_wp cpu_wp_auto[] = {
|
|
{
|
|
.pll_rate = 532000000,
|
|
.cpu_rate = 532000000,
|
|
.pdf = 0,
|
|
.mfi = 5,
|
|
.mfd = 23,
|
|
.mfn = 13,
|
|
.cpu_voltage = 1050000,},
|
|
{
|
|
.pll_rate = 200000000,
|
|
.cpu_rate = 200000000,
|
|
.pdf = 3,
|
|
.mfi = 8,
|
|
.mfd = 2,
|
|
.mfn = 1,
|
|
.cpu_voltage = 850000,},
|
|
};
|
|
|
|
struct cpu_wp *get_cpu_wp(int *wp)
|
|
{
|
|
*wp = 2;
|
|
return cpu_wp_auto;
|
|
}
|
|
|
|
#if defined(CONFIG_REGULATOR_MC13892) \
|
|
|| defined(CONFIG_REGULATOR_MC13892_MODULE)
|
|
static int mc13892_reg_int(void)
|
|
{
|
|
int i = 0;
|
|
unsigned int value;
|
|
struct regulator *regulator;
|
|
struct cpu_wp *cpu_wp_tbl1;
|
|
int cpu_wp_nr1;
|
|
char *reg_name[] = {
|
|
"SW1",
|
|
"SW2",
|
|
"SW3",
|
|
"SW4",
|
|
"SW1_STBY",
|
|
"SW2_STBY",
|
|
"SW3_STBY",
|
|
"SW4_STBY",
|
|
"SW1_DVS",
|
|
"SW2_DVS",
|
|
"SWBST",
|
|
"VIOHI",
|
|
"VPLL",
|
|
"VDIG",
|
|
"VSD",
|
|
"VUSB2",
|
|
"VVIDEO",
|
|
"VAUDIO",
|
|
"VCAM",
|
|
"VGEN1",
|
|
"VGEN2",
|
|
"VGEN3",
|
|
"USB",
|
|
"GPO1",
|
|
"GPO2",
|
|
"GPO3",
|
|
"GPO4",
|
|
};
|
|
|
|
/* for board v1.1 do nothing */
|
|
if (!board_is_rev(BOARD_REV_2))
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(reg_name); i++) {
|
|
regulator = regulator_get(NULL, reg_name[i]);
|
|
if (regulator != ERR_PTR(-ENOENT)) {
|
|
regulator_enable(regulator);
|
|
regulator_put(regulator);
|
|
}
|
|
}
|
|
for (i = 0; i < ARRAY_SIZE(reg_name); i++) {
|
|
if ((strcmp(reg_name[i], "VIOHI") == 0) ||
|
|
(strcmp(reg_name[i], "VPLL") == 0) ||
|
|
(strcmp(reg_name[i], "VDIG") == 0) ||
|
|
(strcmp(reg_name[i], "VGEN2") == 0))
|
|
continue;
|
|
regulator = regulator_get(NULL, reg_name[i]);
|
|
if (regulator != ERR_PTR(-ENOENT)) {
|
|
regulator_disable(regulator);
|
|
regulator_put(regulator);
|
|
}
|
|
}
|
|
|
|
/* Set the current working point. */
|
|
cpu_wp_tbl1 = get_cpu_wp(&cpu_wp_nr1);
|
|
for (i = 0; i < cpu_wp_nr1; i++)
|
|
cpu_wp_tbl1[i].cpu_voltage += 50000;
|
|
|
|
/* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */
|
|
pmic_read_reg(REG_POWER_CTL0, &value, 0xffffff);
|
|
value |= 0x000010;
|
|
pmic_write_reg(REG_POWER_CTL0, value, 0xffffff);
|
|
|
|
return 0;
|
|
}
|
|
|
|
late_initcall(mc13892_reg_int);
|
|
#endif
|
|
|
|
static void mxc_nop_release(struct device *dev)
|
|
{
|
|
/* Nothing */
|
|
}
|
|
|
|
/* MTD NAND flash */
|
|
#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE) \
|
|
|| defined(CONFIG_MTD_NAND_MXC_V2) || defined(CONFIG_MTD_NAND_MXC_V2_MODULE) \
|
|
|| defined(CONFIG_MTD_NAND_MXC_V3)
|
|
|
|
static struct mtd_partition mxc_nand_partitions[] = {
|
|
{
|
|
.name = "nand.bootloader",
|
|
.offset = 0,
|
|
.size = 2 * 1024 * 1024},
|
|
{
|
|
.name = "nand.kernel",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 4 * 1024 * 1024},
|
|
{
|
|
.name = "nand.rootfs",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 256 * 1024 * 1024},
|
|
{
|
|
.name = "nand.userfs1",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 256 * 1024 * 1024},
|
|
{
|
|
.name = "nand.userfs2",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = 512 * 1024 * 1024},
|
|
{
|
|
.name = "nand.userfs3",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = MTDPART_SIZ_FULL},
|
|
};
|
|
|
|
static struct resource mxc_nand_resources[] = {
|
|
{
|
|
.flags = IORESOURCE_MEM,
|
|
.name = "NFC_AXI_BASE",
|
|
.start = NFC_BASE_ADDR_AXI,
|
|
.end = NFC_BASE_ADDR_AXI + SZ_8K - 1,
|
|
},
|
|
{
|
|
.flags = IORESOURCE_MEM,
|
|
.name = "NFC_IP_BASE",
|
|
.start = NFC_BASE_ADDR + 0x00,
|
|
.end = NFC_BASE_ADDR + 0x34 - 1,
|
|
},
|
|
{
|
|
.flags = IORESOURCE_IRQ,
|
|
.start = MXC_INT_EMI,
|
|
.end = MXC_INT_EMI,
|
|
},
|
|
};
|
|
|
|
static struct flash_platform_data mxc_nand_data = {
|
|
.parts = mxc_nand_partitions,
|
|
.nr_parts = ARRAY_SIZE(mxc_nand_partitions),
|
|
.width = 1,
|
|
};
|
|
|
|
static struct platform_device mxc_nandv2_mtd_device = {
|
|
.name = "mxc_nandv2_flash",
|
|
.id = 0,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &mxc_nand_data,
|
|
},
|
|
.resource = mxc_nand_resources,
|
|
.num_resources = ARRAY_SIZE(mxc_nand_resources),
|
|
|
|
};
|
|
|
|
static void mxc_init_nand_mtd(void)
|
|
{
|
|
// if (__raw_readl(MXC_CCM_RCSR) & MXC_CCM_RCSR_NF16B) {
|
|
// mxc_nand_data.width = 2;
|
|
// }
|
|
(void)platform_device_register(&mxc_nandv2_mtd_device);
|
|
}
|
|
#else
|
|
static inline void mxc_init_nand_mtd(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
static void lcd_reset(void)
|
|
{
|
|
static int first;
|
|
|
|
/* ensure that LCDIO(1.8V) has been turn on */
|
|
/* active reset line GPIO */
|
|
if (!first) {
|
|
mxc_request_iomux(MX37_PIN_GPIO1_5, IOMUX_CONFIG_GPIO);
|
|
gpio_request(IOMUX_TO_GPIO(MX37_PIN_GPIO1_5), "gpio1_5");
|
|
first = 1;
|
|
}
|
|
gpio_set_value(IOMUX_TO_GPIO(MX37_PIN_GPIO1_5), 0);
|
|
gpio_direction_output(IOMUX_TO_GPIO(MX37_PIN_GPIO1_5), 0);
|
|
/* do reset */
|
|
msleep(10); /* tRES >= 100us */
|
|
gpio_set_value(IOMUX_TO_GPIO(MX37_PIN_GPIO1_5), 1);
|
|
msleep(60);
|
|
}
|
|
|
|
static struct mxc_lcd_platform_data lcd_data = {
|
|
.core_reg = "VVIDEO",
|
|
.io_reg = "SW4",
|
|
.reset = lcd_reset,
|
|
};
|
|
|
|
#if defined(CONFIG_KEYBOARD_MPR084) || defined(CONFIG_KEYBOARD_MPR084_MODULE)
|
|
/*!
|
|
* These functions are used to configure and the GPIO pins for keypad to
|
|
* activate and deactivate it.
|
|
*/
|
|
extern void gpio_keypad_active(void);
|
|
|
|
extern void gpio_keypad_inactive(void);
|
|
|
|
static u16 keymap[] = {
|
|
KEY_DOWN, KEY_LEFT, KEY_ENTER,
|
|
KEY_RIGHT, KEY_UP, KEY_LEFTALT,
|
|
KEY_TAB, KEY_ESC,
|
|
};
|
|
|
|
static struct mxc_keyp_platform_data keypad_data = {
|
|
.matrix = keymap,
|
|
.active = gpio_keypad_active,
|
|
.inactive = gpio_keypad_inactive,
|
|
.vdd_reg = "VGEN2",
|
|
};
|
|
#else
|
|
|
|
static struct mxc_keyp_platform_data keypad_data = {};
|
|
|
|
#endif
|
|
|
|
static struct mxc_lightsensor_platform_data ls_data = {
|
|
.vdd_reg = "VGEN2",
|
|
.rext = 100,
|
|
};
|
|
|
|
#if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
|
|
static int tsc2007_get_pendown_state(void)
|
|
{
|
|
return !gpio_get_value(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXFS));
|
|
}
|
|
|
|
static int tsc2007_init(void)
|
|
{
|
|
int pad_val;
|
|
|
|
mxc_request_iomux(MX37_PIN_AUD5_RXFS, IOMUX_CONFIG_GPIO);
|
|
pad_val = PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU;
|
|
mxc_iomux_set_pad(MX37_PIN_AUD5_RXFS, pad_val);
|
|
gpio_request(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXFS), "aud5_rxfs");
|
|
gpio_direction_input(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXFS));
|
|
return 0;
|
|
}
|
|
|
|
static void tsc2007_exit(void)
|
|
{
|
|
}
|
|
|
|
struct tsc2007_platform_data tsc2007_data = {
|
|
.model = 2007,
|
|
.x_plate_ohms = 400,
|
|
.get_pendown_state = tsc2007_get_pendown_state,
|
|
.init_platform_hw = tsc2007_init,
|
|
.exit_platform_hw = tsc2007_exit,
|
|
};
|
|
#else
|
|
struct tsc2007_platform_data tsc2007_data;
|
|
#endif
|
|
|
|
static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
|
|
{
|
|
.type = "tsc2007",
|
|
.addr = 0x48,
|
|
.irq = IOMUX_TO_IRQ(MX37_PIN_AUD5_RXFS),
|
|
.platform_data = &tsc2007_data,
|
|
},
|
|
{
|
|
.type = "mpr084",
|
|
.addr = 0x5D,
|
|
.platform_data = &keypad_data,
|
|
.irq = IOMUX_TO_IRQ(MX37_PIN_GPIO1_3),
|
|
},
|
|
{
|
|
.type = "isl29003",
|
|
.addr = 0x44,
|
|
.platform_data = &ls_data,
|
|
},
|
|
};
|
|
|
|
static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
|
|
{
|
|
.type = "mc13892",
|
|
.addr = 0x08,
|
|
.platform_data = (void *)MX37_PIN_OWIRE_LINE,
|
|
},
|
|
{
|
|
.type = "sgtl5000-i2c",
|
|
.addr = 0x0a,
|
|
},
|
|
};
|
|
|
|
static struct spi_board_info mxc_spi_board_info[] __initdata = {
|
|
{
|
|
.modalias = "cpld_spi",
|
|
.max_speed_hz = 27000000,
|
|
.bus_num = 2,
|
|
.chip_select = 0,
|
|
},
|
|
{
|
|
.modalias = "lcd_spi",
|
|
.max_speed_hz = 5000000,
|
|
.bus_num = 2,
|
|
.platform_data = &lcd_data,
|
|
.chip_select = 1,},
|
|
};
|
|
|
|
#if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
|
|
static int __initdata enable_tv = { 0 };
|
|
static int __init tv_setup(char *s)
|
|
{
|
|
enable_tv = 1;
|
|
return 1;
|
|
}
|
|
__setup("tv", tv_setup);
|
|
|
|
static struct fb_videomode tv_mode = {
|
|
/* NTSC TV output */
|
|
"TV-NTSC", 60, 720, 480, 74074,
|
|
121, 16,
|
|
17, 5,
|
|
1, 1,
|
|
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_EXT,
|
|
FB_VMODE_INTERLACED,
|
|
0,
|
|
};
|
|
|
|
static struct platform_device mxc_fb_device[] = {
|
|
{
|
|
.name = "mxc_sdc_fb",
|
|
.id = 0,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.coherent_dma_mask = 0xFFFFFFFF,
|
|
},
|
|
},
|
|
{
|
|
.name = "mxc_sdc_fb",
|
|
.id = 1,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.coherent_dma_mask = 0xFFFFFFFF,
|
|
},
|
|
},
|
|
{
|
|
.name = "mxc_sdc_fb",
|
|
.id = 2,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.coherent_dma_mask = 0xFFFFFFFF,
|
|
},
|
|
},
|
|
};
|
|
|
|
static struct mxc_fb_platform_data fb_data;
|
|
static void mxc_init_fb(void)
|
|
{
|
|
if (enable_tv) {
|
|
printk(KERN_INFO "TV is primary display\n");
|
|
fb_data.interface_pix_fmt = IPU_PIX_FMT_YUV444;
|
|
fb_data.mode = &tv_mode;
|
|
fb_data.num_modes = 1;
|
|
mxc_fb_device[1].dev.platform_data = &fb_data;
|
|
(void)platform_device_register(&mxc_fb_device[1]);
|
|
(void)platform_device_register(&mxc_fb_device[0]);
|
|
} else {
|
|
(void)platform_device_register(&mxc_fb_device[0]);
|
|
(void)platform_device_register(&mxc_fb_device[1]);
|
|
}
|
|
(void)platform_device_register(&mxc_fb_device[2]);
|
|
gpio_lcd_active();
|
|
}
|
|
#else
|
|
static inline void mxc_init_fb(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
static struct platform_device mxcbl_device = {
|
|
.name = "mxc_mc13892_bl",
|
|
};
|
|
|
|
static inline void mxc_init_bl(void)
|
|
{
|
|
platform_device_register(&mxcbl_device);
|
|
}
|
|
|
|
/*lan9217 device*/
|
|
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
|
|
static struct resource smsc911x_resources[] = {
|
|
{
|
|
.start = LAN9217_BASE_ADDR,
|
|
.end = LAN9217_BASE_ADDR + 255,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
{
|
|
.start = MXC_BOARD_IRQ_START,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
struct smsc911x_platform_config smsc911x_config = {
|
|
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
|
|
.flags = 0x8000 | SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
|
|
};
|
|
|
|
static struct platform_device smsc_lan9217_device = {
|
|
.name = "smsc911x",
|
|
.id = 0,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &smsc911x_config,
|
|
},
|
|
.num_resources = ARRAY_SIZE(smsc911x_resources),
|
|
.resource = smsc911x_resources,
|
|
};
|
|
|
|
static int __init mxc_init_enet(void)
|
|
{
|
|
(void)platform_device_register(&smsc_lan9217_device);
|
|
return 0;
|
|
}
|
|
#else
|
|
static int __init mxc_init_enet(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
late_initcall(mxc_init_enet);
|
|
|
|
#if defined(CONFIG_PATA_FSL) || defined(CONFIG_PATA_FSL_MODULE)
|
|
extern void gpio_ata_active(void);
|
|
extern void gpio_ata_inactive(void);
|
|
|
|
static int ata_init(struct platform_device *pdev)
|
|
{
|
|
/* Configure the pins */
|
|
gpio_ata_active();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ata_exit(void)
|
|
{
|
|
/* Free the pins */
|
|
gpio_ata_inactive();
|
|
}
|
|
|
|
static struct fsl_ata_platform_data ata_data = {
|
|
.udma_mask = ATA_UDMA3, /* board can handle up to UDMA3 */
|
|
.mwdma_mask = ATA_MWDMA2,
|
|
.pio_mask = ATA_PIO4,
|
|
.fifo_alarm = MXC_IDE_DMA_WATERMARK / 2,
|
|
.max_sg = MXC_IDE_DMA_BD_NR,
|
|
.init = ata_init,
|
|
.exit = ata_exit,
|
|
.core_reg = NULL, /*"LDO2", */
|
|
.io_reg = NULL, /*"LDO3", */
|
|
};
|
|
|
|
static struct resource pata_fsl_resources[] = {
|
|
{
|
|
.start = ATA_BASE_ADDR,
|
|
.end = ATA_BASE_ADDR + 0x000000C8,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
{
|
|
.start = MXC_INT_ATA,
|
|
.end = MXC_INT_ATA,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device pata_fsl_device = {
|
|
.name = "pata_fsl",
|
|
.id = -1,
|
|
.num_resources = ARRAY_SIZE(pata_fsl_resources),
|
|
.resource = pata_fsl_resources,
|
|
.dev = {
|
|
.platform_data = &ata_data,
|
|
.coherent_dma_mask = ~0,
|
|
},
|
|
};
|
|
|
|
static void __init mxc_init_pata(void)
|
|
{
|
|
(void)platform_device_register(&pata_fsl_device);
|
|
}
|
|
#else /* CONFIG_PATA_FSL */
|
|
static void __init mxc_init_pata(void)
|
|
{
|
|
}
|
|
#endif /* CONFIG_PATA_FSL */
|
|
|
|
/*!
|
|
* 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
|
|
* statically fill in the proper values for the passed-in parameters. None of
|
|
* the parameters is used currently.
|
|
*
|
|
* @param desc pointer to \b struct \b machine_desc
|
|
* @param tags pointer to \b struct \b tag
|
|
* @param cmdline pointer to the command line
|
|
* @param mi pointer to \b struct \b meminfo
|
|
*/
|
|
static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
|
|
char **cmdline, struct meminfo *mi)
|
|
{
|
|
mxc_cpu_init();
|
|
|
|
#ifdef CONFIG_DISCONTIGMEM
|
|
do {
|
|
int nid;
|
|
mi->nr_banks = MXC_NUMNODES;
|
|
for (nid = 0; nid < mi->nr_banks; nid++) {
|
|
SET_NODE(mi, nid);
|
|
}
|
|
} while (0);
|
|
#endif
|
|
}
|
|
|
|
static void mxc_unifi_hardreset(int pin_level)
|
|
{
|
|
struct regulator *gpo4;
|
|
|
|
if (board_is_rev(BOARD_REV_2)) {
|
|
gpo4 = regulator_get(NULL, "GPO4");
|
|
if (!IS_ERR(gpo4)) {
|
|
if (pin_level & 0x01)
|
|
regulator_enable(gpo4);
|
|
else
|
|
regulator_disable(gpo4);
|
|
}
|
|
regulator_put(gpo4);
|
|
} else {
|
|
mxc_request_iomux(MX37_PIN_AUD5_RXC, IOMUX_CONFIG_GPIO);
|
|
gpio_request(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC), "aud5_rxc");
|
|
gpio_set_value(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC),
|
|
pin_level & 0x01);
|
|
gpio_direction_output(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC), 0);
|
|
mxc_free_iomux(MX37_PIN_AUD5_RXC, IOMUX_CONFIG_GPIO);
|
|
}
|
|
}
|
|
|
|
static struct mxc_unifi_platform_data unifi_data = {
|
|
.hardreset = mxc_unifi_hardreset,
|
|
.enable = NULL,
|
|
.reg_1v5_ana_bb = "VGEN1",
|
|
.reg_vdd_vpa = "VCAM",
|
|
.reg_1v5_dd = "VGEN1",
|
|
.host_id = 1,
|
|
};
|
|
|
|
struct mxc_unifi_platform_data *get_unifi_plat_data(void)
|
|
{
|
|
return &unifi_data;
|
|
}
|
|
|
|
EXPORT_SYMBOL(get_unifi_plat_data);
|
|
|
|
#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE)
|
|
static struct mxc_mmc_platform_data mmc1_data = {
|
|
.ocr_mask = MMC_VDD_32_33,
|
|
.caps = MMC_CAP_4_BIT_DATA,
|
|
.min_clk = 150000,
|
|
.max_clk = 52000000,
|
|
.card_inserted_state = 0,
|
|
.status = sdhc_get_card_det_status,
|
|
.wp_status = sdhc_write_protect,
|
|
.clock_mmc = "esdhc_clk",
|
|
};
|
|
|
|
/*!
|
|
* Resource definition for the SDHC1
|
|
*/
|
|
static struct resource mxcsdhc1_resources[] = {
|
|
[0] = {
|
|
.start = MMC_SDHC1_BASE_ADDR,
|
|
.end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = MXC_INT_MMC_SDHC1,
|
|
.end = MXC_INT_MMC_SDHC1,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
.start = 0,
|
|
.end = 0,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
/*! Device Definition for MXC SDHC1 */
|
|
static struct platform_device mxcsdhc1_device = {
|
|
.name = "mxsdhci",
|
|
.id = 0,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &mmc1_data,
|
|
},
|
|
.num_resources = ARRAY_SIZE(mxcsdhc1_resources),
|
|
.resource = mxcsdhc1_resources,
|
|
};
|
|
|
|
static struct mxc_mmc_platform_data mmc2_data = {
|
|
.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
|
|
MMC_VDD_31_32,
|
|
.caps = MMC_CAP_4_BIT_DATA,
|
|
.min_clk = 150000,
|
|
.max_clk = 50000000,
|
|
.card_inserted_state = 0,
|
|
.status = sdhc_get_card_det_status,
|
|
.wp_status = sdhc_write_protect,
|
|
.clock_mmc = "esdhc_clk",
|
|
};
|
|
|
|
static struct resource mxcsdhc2_resources[] = {
|
|
[0] = {
|
|
.start = MMC_SDHC2_BASE_ADDR,
|
|
.end = MMC_SDHC2_BASE_ADDR + SZ_4K - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = MXC_INT_MMC_SDHC2,
|
|
.end = MXC_INT_MMC_SDHC2,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
[2] = {
|
|
.start = 0,
|
|
.end = 0,
|
|
.flags = IORESOURCE_IRQ,
|
|
},
|
|
};
|
|
|
|
static struct platform_device mxcsdhc2_device = {
|
|
.name = "mxsdhci",
|
|
.id = 1,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &mmc2_data,
|
|
},
|
|
.num_resources = ARRAY_SIZE(mxcsdhc2_resources),
|
|
.resource = mxcsdhc2_resources,
|
|
};
|
|
|
|
static inline void mxc_init_mmc(void)
|
|
{
|
|
int cd_irq;
|
|
|
|
cd_irq = sdhc_init_card_det(0);
|
|
if (cd_irq) {
|
|
mxcsdhc1_device.resource[2].start = cd_irq;
|
|
mxcsdhc1_device.resource[2].end = cd_irq;
|
|
}
|
|
|
|
(void)platform_device_register(&mxcsdhc1_device);
|
|
cd_irq = sdhc_init_card_det(1);
|
|
if (cd_irq) {
|
|
mxcsdhc2_device.resource[2].start = cd_irq;
|
|
mxcsdhc2_device.resource[2].end = cd_irq;
|
|
}
|
|
(void)platform_device_register(&mxcsdhc2_device);
|
|
}
|
|
#else
|
|
static inline void mxc_init_mmc(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
static void bt_reset(void)
|
|
{
|
|
struct regulator *gpo4;
|
|
if (board_is_rev(BOARD_REV_2)) {
|
|
gpo4 = regulator_get(NULL, "GPO4");
|
|
if (!IS_ERR(gpo4))
|
|
regulator_enable(gpo4);
|
|
regulator_put(gpo4);
|
|
} else {
|
|
mxc_request_iomux(MX37_PIN_AUD5_RXC, IOMUX_CONFIG_GPIO);
|
|
gpio_request(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC), "aud5_rxc");
|
|
gpio_set_value(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC), 1);
|
|
gpio_direction_output(IOMUX_TO_GPIO(MX37_PIN_AUD5_RXC), 0);
|
|
}
|
|
}
|
|
|
|
static struct mxc_bt_platform_data mxc_bt_data = {
|
|
.bt_vdd = "VGEN2",
|
|
.bt_vdd_parent = NULL,
|
|
.bt_vusb = "SW4",
|
|
.bt_vusb_parent = NULL,
|
|
.bt_reset = bt_reset,
|
|
};
|
|
|
|
static struct platform_device mxc_bt_device = {
|
|
.name = "mxc_bt",
|
|
.id = 0,
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &mxc_bt_data,
|
|
},
|
|
};
|
|
|
|
static void mxc_init_bluetooth(void)
|
|
{
|
|
(void)platform_device_register(&mxc_bt_device);
|
|
}
|
|
|
|
#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) \
|
|
|| defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE)
|
|
static int mxc_sgtl5000_plat_init(void);
|
|
static int mxc_sgtl5000_plat_finit(void);
|
|
static int mxc_sgtl5000_amp_enable(int enable);
|
|
|
|
static struct mxc_audio_platform_data sgtl5000_data = {
|
|
.ssi_num = 1,
|
|
.src_port = 2,
|
|
.ext_port = 5,
|
|
.hp_irq = IOMUX_TO_IRQ(MX37_PIN_AUD5_RXFS),
|
|
.hp_status = headphone_det_status,
|
|
.amp_enable = mxc_sgtl5000_amp_enable,
|
|
.init = mxc_sgtl5000_plat_init,
|
|
.finit = mxc_sgtl5000_plat_finit,
|
|
};
|
|
|
|
static struct platform_device mxc_sgtl5000_device = {
|
|
.name = "imx-3stack-sgtl5000",
|
|
.dev = {
|
|
.release = mxc_nop_release,
|
|
.platform_data = &sgtl5000_data,
|
|
},
|
|
};
|
|
|
|
static int mxc_sgtl5000_plat_init(void)
|
|
{
|
|
struct regulator *reg;
|
|
reg = regulator_get(&mxc_sgtl5000_device.dev, "GPO2");
|
|
if (IS_ERR(reg))
|
|
return -EINVAL;
|
|
sgtl5000_data.priv = reg;
|
|
return 0;
|
|
}
|
|
|
|
static int mxc_sgtl5000_plat_finit(void)
|
|
{
|
|
struct regulator *reg;
|
|
reg = sgtl5000_data.priv;
|
|
if (reg) {
|
|
regulator_put(reg);
|
|
sgtl5000_data.priv = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int mxc_sgtl5000_amp_enable(int enable)
|
|
{
|
|
struct regulator *reg;
|
|
reg = sgtl5000_data.priv;
|
|
|
|
if (!reg)
|
|
return -EINVAL;
|
|
if (enable)
|
|
regulator_enable(reg);
|
|
else
|
|
regulator_disable(reg);
|
|
return 0;
|
|
}
|
|
|
|
static void mxc_init_sgtl5000(void)
|
|
{
|
|
int err, pin;
|
|
struct clk *cko1, *parent;
|
|
unsigned long rate;
|
|
|
|
/* for board v1.1 do nothing */
|
|
if (!board_is_rev(BOARD_REV_2))
|
|
return;
|
|
|
|
pin = MX37_PIN_AUD5_RXFS;
|
|
err = mxc_request_iomux(pin, IOMUX_CONFIG_GPIO);
|
|
if (err) {
|
|
sgtl5000_data.hp_irq = -1;
|
|
printk(KERN_ERR "Error: sgtl5000_init request gpio failed!\n");
|
|
return;
|
|
}
|
|
mxc_iomux_set_pad(pin, PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU);
|
|
gpio_request(IOMUX_TO_GPIO(pin), "aud5_rxfs");
|
|
gpio_direction_input(IOMUX_TO_GPIO(pin));
|
|
|
|
/* cko1 clock */
|
|
mxc_request_iomux(MX37_PIN_GPIO1_6, IOMUX_CONFIG_ALT2);
|
|
|
|
cko1 = clk_get(NULL, "cko1_clk");
|
|
if (IS_ERR(cko1))
|
|
return;
|
|
parent = clk_get(NULL, "ipg_perclk");
|
|
if (IS_ERR(parent))
|
|
return;
|
|
clk_set_parent(cko1, parent);
|
|
rate = clk_round_rate(cko1, 13000000);
|
|
if (rate < 8000000 || rate > 27000000) {
|
|
printk(KERN_ERR "Error: SGTL5000 mclk freq %d out of range!\n",
|
|
rate);
|
|
clk_put(parent);
|
|
clk_put(cko1);
|
|
return;
|
|
}
|
|
clk_set_rate(cko1, rate);
|
|
clk_enable(cko1);
|
|
sgtl5000_data.sysclk = rate;
|
|
platform_device_register(&mxc_sgtl5000_device);
|
|
}
|
|
#else
|
|
static inline void mxc_init_sgtl5000(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* fixup for mx37 3stack board v1.1(wm8350)
|
|
*/
|
|
static void mx37_3stack_fixup_for_board_v1(void)
|
|
{
|
|
dptc_gp_data.reg_id = "DCDC1";
|
|
dptc_lp_data.reg_id = "DCDC4";
|
|
gp_reg_id = "DCDC1";
|
|
lp_reg_id = "DCDC4";
|
|
tve_data.dac_reg = "LDO2";
|
|
tve_data.dig_reg = "LDO3";
|
|
lcd_data.core_reg = "LDO1";
|
|
lcd_data.io_reg = "DCDC6";
|
|
dvfs_core_data.reg_id = "DCDC1";
|
|
dvfs_per_data.reg_id = "DCDC4";
|
|
ls_data.vdd_reg = "DCDC3";
|
|
mxc_bt_data.bt_vdd = "DCDC3";
|
|
mxc_bt_data.bt_vusb = "DCDC6";
|
|
|
|
unifi_data.reg_1v5_ana_bb = NULL; /* VMAIN is used on v1 board */
|
|
unifi_data.reg_vdd_vpa = NULL;
|
|
unifi_data.reg_1v5_dd = NULL;
|
|
/*Set the CPU voltage to be higher for the lower setpoint
|
|
* When set to 0.85V, under certain situations, the voltage drops
|
|
* below 0.85V and the system hangs.
|
|
*/
|
|
cpu_wp_auto[1].cpu_voltage = 925000;
|
|
|
|
#if defined(CONFIG_KEYBOARD_MPR084) || defined(CONFIG_KEYBOARD_MPR084_MODULE)
|
|
keypad_data.vdd_reg = "DCDC3";
|
|
#endif
|
|
}
|
|
|
|
#if defined(CONFIG_GPS_IOCTRL) || defined(CONFIG_GPS_IOCTRL_MODULE)
|
|
static struct mxc_gps_platform_data gps_data = {
|
|
.core_reg = "VIOHI",
|
|
.analog_reg = "SW3",
|
|
};
|
|
|
|
static struct platform_device mxc_gps_device = {
|
|
.name = "gps_ioctrl",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &gps_data,
|
|
},
|
|
};
|
|
|
|
static void __init mxc_init_gps(void)
|
|
{
|
|
(void)platform_device_register(&mxc_gps_device);
|
|
}
|
|
#else
|
|
static void __init mxc_init_gps(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* Board specific initialization.
|
|
*/
|
|
static void __init mxc_board_init(void)
|
|
{
|
|
mxc_cpu_common_init();
|
|
mxc_init_srpgconfig();
|
|
mxc_register_gpios();
|
|
mxc_init_devices();
|
|
if (!board_is_rev(BOARD_REV_2))
|
|
mx37_3stack_fixup_for_board_v1();
|
|
i2c_register_board_info(0, mxc_i2c0_board_info,
|
|
ARRAY_SIZE(mxc_i2c0_board_info));
|
|
i2c_register_board_info(1, mxc_i2c1_board_info,
|
|
ARRAY_SIZE(mxc_i2c1_board_info));
|
|
|
|
spi_register_board_info(mxc_spi_board_info,
|
|
ARRAY_SIZE(mxc_spi_board_info));
|
|
mxc_init_nand_mtd();
|
|
mxc_init_mmc();
|
|
mxc_init_pata();
|
|
mxc_init_fb();
|
|
mxc_init_bl();
|
|
mxc_init_bluetooth();
|
|
mxc_init_gps();
|
|
mxc_init_sgtl5000();
|
|
}
|
|
|
|
static void __init mx37_3stack_timer_init(void)
|
|
{
|
|
struct clk *uart_clk;
|
|
|
|
mx37_clocks_init(32768, 24000000, 22579200, 0);
|
|
uart_clk = clk_get(NULL, "uart_clk.0");
|
|
early_console_setup(UART1_BASE_ADDR, uart_clk);
|
|
}
|
|
|
|
static struct sys_timer mxc_timer = {
|
|
.init = mx37_3stack_timer_init,
|
|
};
|
|
|
|
/*
|
|
* The following uses standard kernel macros define in arch.h in order to
|
|
* initialize __mach_desc_MX37_3STACK data structure.
|
|
*/
|
|
/* *INDENT-OFF* */
|
|
MACHINE_START(MX37_3DS, "Freescale MX37 3-Stack Board")
|
|
/* Maintainer: Freescale Semiconductor, Inc. */
|
|
.phys_io = AIPS1_BASE_ADDR,
|
|
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
|
|
.boot_params = PHYS_OFFSET + 0x100,
|
|
.fixup = fixup_mxc_board,
|
|
.map_io = mx37_map_io,
|
|
.init_irq = mx37_init_irq,
|
|
.init_machine = mxc_board_init,
|
|
.timer = &mxc_timer,
|
|
MACHINE_END
|