diff options
Diffstat (limited to 'arch/arm/mach-mx28')
-rw-r--r-- | arch/arm/mach-mx28/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/mach-mx28/bus_freq.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-mx28/clock.c | 82 | ||||
-rw-r--r-- | arch/arm/mach-mx28/device.c | 380 | ||||
-rw-r--r-- | arch/arm/mach-mx28/emi_settings.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-mx28/include/mach/mx28.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-mx28/mx28evk.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-mx28/mx28evk.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-mx28/mx28evk_pins.c | 287 | ||||
-rw-r--r-- | arch/arm/mach-mx28/pm.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-mx28/regs-clkctrl.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-mx28/sleep.S | 195 | ||||
-rw-r--r-- | arch/arm/mach-mx28/usb_dr.c | 24 |
13 files changed, 905 insertions, 224 deletions
diff --git a/arch/arm/mach-mx28/Kconfig b/arch/arm/mach-mx28/Kconfig index fdca0f6900ca..cbbf45230472 100644 --- a/arch/arm/mach-mx28/Kconfig +++ b/arch/arm/mach-mx28/Kconfig @@ -9,4 +9,14 @@ config MACH_MX28EVK config MXS_TIMER_WITH_MACH bool "Timer with architecture." +config MXS_TIMER_WITH_MACH + bool "System Timer support Compare Match interrupt" + endchoice + +config VECTORS_PHY_ADDR + int "vectors address" + default 0 + help + This config set vectors table is located which physical address + diff --git a/arch/arm/mach-mx28/bus_freq.c b/arch/arm/mach-mx28/bus_freq.c index a997eaa9a01f..ef01a41fc095 100644 --- a/arch/arm/mach-mx28/bus_freq.c +++ b/arch/arm/mach-mx28/bus_freq.c @@ -46,24 +46,19 @@ #define CLKCTRL_BASE_ADDR IO_ADDRESS(CLKCTRL_PHYS_ADDR) #define DIGCTRL_BASE_ADDR IO_ADDRESS(DIGCTL_PHYS_ADDR) -#define BP_CLKCTRL_HBUS_ASM_ENABLE 20 -#define CLKCTRL_PLL_PWD_BIT 17 -#define CLKCTRL_PLL_BYPASS 0x1ff #define BF(value, field) (((value) << BP_##field) & BM_##field) struct profile profiles[] = { - { 454736, 151580, 196360, 0, 1550000, - 1450000, 355000, 3300000, 1750000, 0 }, - { 392727, 130910, 160000, 0, 1475000, - 1375000, 225000, 3300000, 1750000, 0 }, - { 360000, 120000, 130910, 0, 1375000, - 1275000, 200000, 3300000, 1750000, 0 }, - { 261818, 130910, 130910, 0, 1275000, - 1175000, 173000, 3300000, 1750000, 0 }, - { 64000, 64000, 130910, 3, 1050000, - 975000, 150000, 3300000, 1750000, 0 }, + { 454736, 151570, 205710, 0, 1550000, + 1450000, 355000, 3300000, 1750000, 24000, 0 }, + { 360000, 120000, 130910, 0, 1350000, + 1250000, 200000, 3300000, 1750000, 24000, 0 }, + { 261818, 130910, 130910, 0, 1350000, + 1250000, 173000, 3300000, 1750000, 24000, 0 }, + { 64000, 64000, 130910, 3, 1350000, + 1250000, 150000, 3300000, 1750000, 24000, 0 }, { 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 }, + 0, 0, 0, 0, 0, 0 }, }; static struct device *busfreq_dev; @@ -82,58 +77,13 @@ int low_freq_used(void) return 0; } -void hbus_auto_slow_mode_enable(void) +int is_hclk_autoslow_ok(void) { - __raw_writel(BP_CLKCTRL_HBUS_ASM_ENABLE, - CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_SET); -} -EXPORT_SYMBOL(hbus_auto_slow_mode_enable); - -void hbus_auto_slow_mode_disable(void) -{ - __raw_writel(BP_CLKCTRL_HBUS_ASM_ENABLE, - CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR); -} -EXPORT_SYMBOL(hbus_auto_slow_mode_disable); - -int cpu_clk_set_pll_on(struct clk *clk, unsigned int freq) -{ - struct cpufreq_freqs freqs; - - freqs.old = clk_get_rate(clk); - freqs.cpu = 0; - freqs.new = freq; - - if (freqs.old == 24000 && freqs.new > 24000) { - /* turn pll on */ - __raw_writel(CLKCTRL_PLL_PWD_BIT, CLKCTRL_BASE_ADDR + - HW_CLKCTRL_PLL0CTRL0_SET); - udelay(10); - } else if (freqs.old > 24000 && freqs.new == 24000) - clkseq_setting = __raw_readl(CLKCTRL_BASE_ADDR + - HW_CLKCTRL_CLKSEQ); - return 0; -} - -int cpu_clk_set_pll_off(struct clk *clk, unsigned int freq) -{ - struct cpufreq_freqs freqs; - - freqs.old = clk_get_rate(clk); - freqs.cpu = 0; - freqs.new = freq; - - if (freqs.old > 24000 && freqs.new == 24000) { - /* turn pll off */ - __raw_writel(CLKCTRL_PLL_PWD_BIT, CLKCTRL_BASE_ADDR + - HW_CLKCTRL_PLL0CTRL0_CLR); - __raw_writel(CLKCTRL_PLL_BYPASS, CLKCTRL_BASE_ADDR + - HW_CLKCTRL_CLKSEQ); - } else if (freqs.old == 24000 && freqs.new > 24000) - __raw_writel(clkseq_setting, CLKCTRL_BASE_ADDR + - HW_CLKCTRL_CLKSEQ); - - return 0; + if ((clk_get_usecount(usb_clk0) == 0) + && (clk_get_usecount(usb_clk1) == 0)) + return 1; + else + return 0; } int timing_ctrl_rams(int ss) diff --git a/arch/arm/mach-mx28/clock.c b/arch/arm/mach-mx28/clock.c index 8e7adea7c09d..ae6f49d4ae41 100644 --- a/arch/arm/mach-mx28/clock.c +++ b/arch/arm/mach-mx28/clock.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/iram_alloc.h> #include <linux/platform_device.h> #include <mach/clock.h> @@ -47,6 +48,41 @@ static unsigned long xtal_clk_rate[3] = { 24000000, 24000000, 32000 }; static unsigned long enet_mii_phy_rate; +static inline int clk_is_busy(struct clk *clk) +{ + return __raw_readl(clk->busy_reg) & (1 << clk->busy_bits); +} + +static bool mx28_enable_h_autoslow(bool enable) +{ + bool currently_enabled; + + if (__raw_readl(CLKCTRL_BASE_ADDR+HW_CLKCTRL_HBUS) & + BM_CLKCTRL_HBUS_ASM_ENABLE) + currently_enabled = true; + else + currently_enabled = false; + + if (enable) + __raw_writel(BM_CLKCTRL_HBUS_ASM_ENABLE, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_SET); + else + __raw_writel(BM_CLKCTRL_HBUS_ASM_ENABLE, + CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS_CLR); + return currently_enabled; +} + + +static void mx28_set_hbus_autoslow_flags(u16 mask) +{ + u32 reg; + + reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); + reg &= 0xFFFF; + reg |= mask << 16; + __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); +} + static int mx28_raw_enable(struct clk *clk) { unsigned int reg; @@ -460,6 +496,7 @@ static unsigned long cpu_round_rate(struct clk *clk, unsigned long rate) return rate; } +static struct clk h_clk; static int cpu_set_rate(struct clk *clk, unsigned long rate) { unsigned long root_rate = @@ -469,7 +506,7 @@ static int cpu_set_rate(struct clk *clk, unsigned long rate) u32 c = clkctrl_cpu; u32 clkctrl_frac = 1; u32 val; - u32 reg_val; + u32 reg_val, hclk_reg; if (rate < 24000) return -EINVAL; @@ -500,7 +537,31 @@ static int cpu_set_rate(struct clk *clk, unsigned long rate) if ((abs(d) > 100) || (clkctrl_frac < 18) || (clkctrl_frac > 35)) return -EINVAL; - } + } + + /* Set safe hbus clock divider. A divider of 3 ensure that + * the Vddd voltage required for the cpuclk is sufficiently + * high for the hbus clock. + */ + hclk_reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS); + if ((hclk_reg & BP_CLKCTRL_HBUS_DIV) != 3) { + hclk_reg &= ~(BM_CLKCTRL_HBUS_DIV); + hclk_reg |= BF_CLKCTRL_HBUS_DIV(3); + + /* change hclk divider to safe value for any ref_cpu + * value. + */ + __raw_writel(hclk_reg, CLKCTRL_BASE_ADDR + + HW_CLKCTRL_HBUS); + } + + for (i = 10000; i; i--) + if (!clk_is_busy(&h_clk)) + break; + if (!i) { + printk(KERN_ERR "couldn't set up HCLK divisor\n"); + return -ETIMEDOUT; + } /* Set Frac div */ val = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); @@ -510,6 +571,7 @@ static int cpu_set_rate(struct clk *clk, unsigned long rate) /* Do not gate */ __raw_writel(BM_CLKCTRL_FRAC0_CLKGATECPU, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0_CLR); + /* write clkctrl_cpu */ reg_val = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); reg_val &= ~0x3F; @@ -824,8 +886,14 @@ static int emi_set_rate(struct clk *clk, unsigned long rate) { int i; struct mxs_emi_scaling_data emi; + unsigned long iram_phy; void (*f) (struct mxs_emi_scaling_data *, unsigned int *); - f = (void *)MX28_OCRAM_BASE; + f = iram_alloc((unsigned int)mxs_ram_freq_scale_end - + (unsigned int)mxs_ram_freq_scale, &iram_phy); + if (NULL == f) { + pr_err("%s Not enough iram\n", __func__); + return -ENOMEM; + } memcpy(f, mxs_ram_freq_scale, (unsigned int)mxs_ram_freq_scale_end - (unsigned int)mxs_ram_freq_scale); @@ -852,6 +920,9 @@ static int emi_set_rate(struct clk *clk, unsigned long rate) f(&emi, get_current_emidata()); local_fiq_enable(); local_irq_enable(); + iram_free(iram_phy, + (unsigned int)mxs_ram_freq_scale_end - + (unsigned int)mxs_ram_freq_scale); for (i = 10000; i; i--) if (!clk_is_busy(clk)) @@ -1681,6 +1752,8 @@ void mx28_enet_clk_hook(void) reg &= ~BM_CLKCTRL_ENET_SLEEP; reg |= BM_CLKCTRL_ENET_CLK_OUT_EN; + /* select clock for 1588 module */ + reg |= BM_CLKCTRL_ENET_1588_40MHZ; __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); } @@ -1695,4 +1768,7 @@ void __init mx28_clock_init(void) clk_enable(&cpu_clk); clk_enable(&emi_clk); + + clk_en_public_h_asm_ctrl(mx28_enable_h_autoslow, + mx28_set_hbus_autoslow_flags); } diff --git a/arch/arm/mach-mx28/device.c b/arch/arm/mach-mx28/device.c index 8e1d27fb1213..35e8f14a5568 100644 --- a/arch/arm/mach-mx28/device.c +++ b/arch/arm/mach-mx28/device.c @@ -27,13 +27,16 @@ #include <linux/platform_device.h> #include <linux/mmc/host.h> #include <linux/phy.h> +#include <linux/etherdevice.h> #include <linux/fec.h> +#include <linux/gpmi-nfc.h> #include <asm/mach/map.h> #include <mach/hardware.h> #include <mach/regs-timrot.h> #include <mach/regs-lradc.h> +#include <mach/regs-ocotp.h> #include <mach/device.h> #include <mach/dma.h> #include <mach/lradc.h> @@ -43,6 +46,7 @@ #include "regs-digctl.h" #include "device.h" +#include "mx28evk.h" #include "mx28_pins.h" #if defined(CONFIG_SERIAL_MXS_DUART) || \ @@ -328,76 +332,93 @@ static void __init mx28_init_i2c(void) } #endif - -#if defined(CONFIG_MTD_NAND_GPMI1) +#if defined(CONFIG_MTD_NAND_GPMI_NFC) extern int enable_gpmi; -static int gpmi_pinmux_handler(void) +static int gpmi_nfc_platform_init(unsigned int max_chip_count) { return !enable_gpmi; } -static const char *gpmi_partition_source_types[] = { "cmdlinepart", 0 }; +static void gpmi_nfc_platform_exit(unsigned int max_chip_count) +{ +} -static struct gpmi_platform_data gpmi_platform_data = { - .io_uA = 70000, +static const char *gpmi_nfc_partition_source_types[] = { "cmdlinepart", 0 }; + +static struct gpmi_nfc_platform_data gpmi_nfc_platform_data = { + .nfc_version = 1, + .boot_rom_version = 1, + .clock_name = "gpmi", + .platform_init = gpmi_nfc_platform_init, + .platform_exit = gpmi_nfc_platform_exit, .min_prop_delay_in_ns = 5, .max_prop_delay_in_ns = 9, - .pinmux_handler = gpmi_pinmux_handler, + .max_chip_count = 2, .boot_area_size_in_bytes = 20 * SZ_1M, + .partition_source_types = gpmi_nfc_partition_source_types, .partitions = 0, .partition_count = 0, - .partition_source_types = gpmi_partition_source_types, }; -static struct resource gpmi_resources[] = { +static struct resource gpmi_nfc_resources[] = { { + .name = GPMI_NFC_GPMI_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = GPMI_PHYS_ADDR, .end = GPMI_PHYS_ADDR + SZ_8K - 1, }, { + .name = GPMI_NFC_GPMI_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, - .start = IRQ_GPMI_DMA, - .end = IRQ_GPMI_DMA, - }, - { - .flags = IORESOURCE_DMA, - .start = MXS_DMA_CHANNEL_AHB_APBH_GPMI0, - .end = MXS_DMA_CHANNEL_AHB_APBH_GPMI7, - }, + .start = IRQ_GPMI, + .end = IRQ_GPMI, + }, { + .name = GPMI_NFC_BCH_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = BCH_PHYS_ADDR, .end = BCH_PHYS_ADDR + SZ_8K - 1, }, { + .name = GPMI_NFC_BCH_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = IRQ_BCH, .end = IRQ_BCH, }, + { + .name = GPMI_NFC_DMA_CHANNELS_RES_NAME, + .flags = IORESOURCE_DMA, + .start = MXS_DMA_CHANNEL_AHB_APBH_GPMI0, + .end = MXS_DMA_CHANNEL_AHB_APBH_GPMI7, + }, + { + .name = GPMI_NFC_DMA_INTERRUPT_RES_NAME, + .flags = IORESOURCE_IRQ, + .start = IRQ_GPMI_DMA, + .end = IRQ_GPMI_DMA, + }, }; -static void __init mx28_init_gpmi(void) +static void __init mx28_init_gpmi_nfc(void) { struct platform_device *pdev; - pdev = mxs_get_device("gpmi", 0); + pdev = mxs_get_device(GPMI_NFC_DRIVER_NAME, 0); if (pdev == NULL || IS_ERR(pdev)) return; - pdev->dev.platform_data = &gpmi_platform_data; - pdev->resource = gpmi_resources; - pdev->num_resources = ARRAY_SIZE(gpmi_resources); + pdev->dev.platform_data = &gpmi_nfc_platform_data; + pdev->resource = gpmi_nfc_resources; + pdev->num_resources = ARRAY_SIZE(gpmi_nfc_resources); mxs_add_device(pdev, 1); } #else -static void mx28_init_gpmi(void) +static void mx28_init_gpmi_nfc(void) { } #endif - #if defined(CONFIG_MMC_MXS) || defined(CONFIG_MMC_MXS_MODULE) #if defined(CONFIG_MACH_MX28EVK) #define MMC0_POWER MXS_PIN_TO_GPIO(PINID_PWM3) @@ -535,9 +556,10 @@ static struct mxs_mmc_platform_data mmc0_data = { .get_wp = mxs_mmc_get_wp_ssp0, .cmd_pullup = mxs_mmc_cmd_pullup_ssp0, .setclock = mxs_mmc_setclock_ssp0, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA + | MMC_CAP_DATA_DDR, .min_clk = 400000, - .max_clk = 52000000, + .max_clk = 48000000, .read_uA = 50000, .write_uA = 70000, .clock_mmc = "ssp.0", @@ -573,9 +595,10 @@ static struct mxs_mmc_platform_data mmc1_data = { .get_wp = mxs_mmc_get_wp_ssp1, .cmd_pullup = mxs_mmc_cmd_pullup_ssp1, .setclock = mxs_mmc_setclock_ssp1, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA + | MMC_CAP_DATA_DDR, .min_clk = 400000, - .max_clk = 52000000, + .max_clk = 48000000, .read_uA = 50000, .write_uA = 70000, .clock_mmc = "ssp.1", @@ -697,22 +720,25 @@ static void __init mx28_init_rtc(void) #endif #if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) -static struct resource fec_resources[] = { +static struct resource fec0_resource[] = { { .start = ENET_PHYS_ADDR, - .end = ENET_PHYS_ADDR + 0xffff, + .end = ENET_PHYS_ADDR + 0x3fff, .flags = IORESOURCE_MEM }, { - .start = IRQ_ENET_SWI, - .end = IRQ_ENET_SWI, - .flags = IORESOURCE_IRQ - }, - { .start = IRQ_ENET_MAC0, .end = IRQ_ENET_MAC0, .flags = IORESOURCE_IRQ }, +}; + +static struct resource fec1_resource[] = { + { + .start = ENET_PHYS_ADDR + 0x4000, + .end = ENET_PHYS_ADDR + 0x7fff, + .flags = IORESOURCE_MEM + }, { .start = IRQ_ENET_MAC1, .end = IRQ_ENET_MAC1, @@ -721,7 +747,12 @@ static struct resource fec_resources[] = { }; extern int mx28evk_enet_gpio_init(void); -static struct fec_platform_data fec_pdata = { +static struct fec_platform_data fec_pdata0 = { + .phy = PHY_INTERFACE_MODE_RMII, + .init = mx28evk_enet_gpio_init, +}; + +static struct fec_platform_data fec_pdata1 = { .phy = PHY_INTERFACE_MODE_RMII, .init = mx28evk_enet_gpio_init, }; @@ -729,22 +760,133 @@ static struct fec_platform_data fec_pdata = { static void __init mx28_init_fec(void) { struct platform_device *pdev; + struct mxs_dev_lookup *lookup; + struct fec_platform_data *pfec; + int i; + u32 val; + + __raw_writel(BM_OCOTP_CTRL_RD_BANK_OPEN, + IO_ADDRESS(OCOTP_PHYS_ADDR) + HW_OCOTP_CTRL_SET); + + while (BM_OCOTP_CTRL_BUSY & + __raw_readl(IO_ADDRESS(OCOTP_PHYS_ADDR) + HW_OCOTP_CTRL)) + udelay(10); + + lookup = mxs_get_devices("mxs-fec"); + if (lookup == NULL || IS_ERR(lookup)) + return; + + for (i = 0; i < lookup->size; i++) { + pdev = lookup->pdev + i; + val = __raw_readl(IO_ADDRESS(OCOTP_PHYS_ADDR) + + HW_OCOTP_CUSTn(pdev->id)); + switch (pdev->id) { + case 0: + pdev->resource = fec0_resource; + pdev->num_resources = ARRAY_SIZE(fec0_resource); + pdev->dev.platform_data = &fec_pdata0; + break; + case 1: + pdev->resource = fec1_resource; + pdev->num_resources = ARRAY_SIZE(fec1_resource); + pdev->dev.platform_data = &fec_pdata1; + break; + default: + return; + } + + pfec = (struct fec_platform_data *)pdev->dev.platform_data; + pfec->mac[0] = 0x00; + pfec->mac[1] = 0x04; + pfec->mac[2] = (val >> 24) & 0xFF; + pfec->mac[3] = (val >> 16) & 0xFF; + pfec->mac[4] = (val >> 8) & 0xFF; + pfec->mac[5] = (val >> 0) & 0xFF; + + mxs_add_device(pdev, 2); + } +} +#else +static void __init mx28_init_fec(void) +{ + ; +} +#endif + +#if defined(CONFIG_FEC_L2SWITCH) +static struct resource l2switch_resources[] = { + { + .start = ENET_PHYS_ADDR, + .end = ENET_PHYS_ADDR + 0x17FFC, + .flags = IORESOURCE_MEM + }, + { + .start = IRQ_ENET_SWI, + .end = IRQ_ENET_SWI, + .flags = IORESOURCE_IRQ + }, +}; + +/* Define the fixed address of the L2 Switch hardware. */ +static unsigned int switch_platform_hw[2] = { + (0x800F8000), + (0x800FC000), +}; + +static struct fec_platform_data fec_enet = { + .phy = PHY_INTERFACE_MODE_RMII, + .init = mx28evk_enet_gpio_init, +}; + +static struct switch_platform_data l2switch_data = { + .id = 0, + .fec_enet = &fec_enet, + .hash_table = 0, + .switch_hw = switch_platform_hw, +}; + +static void __init mx28_init_l2switch(void) +{ + struct platform_device *pdev; + struct switch_platform_data *pswitch; + struct fec_platform_data *pfec; + u32 val; - pdev = mxs_get_device("mxs-fec", 0); + __raw_writel(BM_OCOTP_CTRL_RD_BANK_OPEN, + IO_ADDRESS(OCOTP_PHYS_ADDR) + HW_OCOTP_CTRL_SET); + + while (BM_OCOTP_CTRL_BUSY & + __raw_readl(IO_ADDRESS(OCOTP_PHYS_ADDR) + HW_OCOTP_CTRL)) + udelay(10); + + pdev = mxs_get_device("mxs-l2switch", 0); if (pdev == NULL || IS_ERR(pdev)) return; - pdev->resource = fec_resources; - pdev->num_resources = ARRAY_SIZE(fec_resources); - pdev->dev.platform_data = &fec_pdata; + val = __raw_readl(IO_ADDRESS(OCOTP_PHYS_ADDR) + + HW_OCOTP_CUSTn(pdev->id)); + pdev->resource = l2switch_resources; + pdev->num_resources = ARRAY_SIZE(l2switch_resources); + pdev->dev.platform_data = &l2switch_data; + + pswitch = (struct switch_platform_data *)pdev->dev.platform_data; + pfec = pswitch->fec_enet; + pfec->mac[0] = 0x00; + pfec->mac[1] = 0x04; + pfec->mac[2] = (val >> 24) & 0xFF; + pfec->mac[3] = (val >> 16) & 0xFF; + pfec->mac[4] = (val >> 8) & 0xFF; + pfec->mac[5] = (val >> 0) & 0xFF; + mxs_add_device(pdev, 2); } #else -static void __init mx28_init_fec(void) +static void __init mx28_init_l2switch(void) { ; } #endif + #ifdef CONFIG_MXS_LRADC struct mxs_lradc_plat_data mx28_lradc_data = { .vddio_voltage = BV_LRADC_CTRL4_LRADC6SELECT__CHANNEL10, @@ -1211,6 +1353,156 @@ static inline mx28_init_spdif(void) } #endif +#if defined(CONFIG_MXS_PERSISTENT) +static const struct mxs_persistent_bit_config +mx28_persistent_bit_config[] = { + { .reg = 0, .start = 0, .width = 1, + .name = "CLOCKSOURCE" }, + { .reg = 0, .start = 1, .width = 1, + .name = "ALARM_WAKE_EN" }, + { .reg = 0, .start = 2, .width = 1, + .name = "ALARM_EN" }, + { .reg = 0, .start = 3, .width = 1, + .name = "CLK_SECS" }, + { .reg = 0, .start = 4, .width = 1, + .name = "XTAL24MHZ_PWRUP" }, + { .reg = 0, .start = 5, .width = 1, + .name = "XTAL32MHZ_PWRUP" }, + { .reg = 0, .start = 6, .width = 1, + .name = "XTAL32_FREQ" }, + { .reg = 0, .start = 7, .width = 1, + .name = "ALARM_WAKE" }, + { .reg = 0, .start = 8, .width = 5, + .name = "MSEC_RES" }, + { .reg = 0, .start = 13, .width = 1, + .name = "DISABLE_XTALOK" }, + { .reg = 0, .start = 14, .width = 2, + .name = "LOWERBIAS" }, + { .reg = 0, .start = 16, .width = 1, + .name = "DISABLE_PSWITCH" }, + { .reg = 0, .start = 17, .width = 1, + .name = "AUTO_RESTART" }, + { .reg = 0, .start = 18, .width = 1, + .name = "ENABLE_LRADC_PWRUP" }, + { .reg = 0, .start = 20, .width = 1, + .name = "THERMAL_RESET" }, + { .reg = 0, .start = 21, .width = 1, + .name = "EXTERNAL_RESET" }, + { .reg = 0, .start = 28, .width = 4, + .name = "ADJ_POSLIMITBUCK" }, + { .reg = 1, .start = 0, .width = 1, + .name = "FORCE_RECOVERY" }, + { .reg = 1, .start = 1, .width = 1, + .name = "ROM_REDUNDANT_BOOT" }, + { .reg = 1, .start = 2, .width = 1, + .name = "NAND_SDK_BLOCK_REWRITE" }, + { .reg = 1, .start = 3, .width = 1, + .name = "SD_SPEED_ENABLE" }, + { .reg = 1, .start = 4, .width = 1, + .name = "SD_INIT_SEQ_1_DISABLE" }, + { .reg = 1, .start = 5, .width = 1, + .name = "SD_CMD0_DISABLE" }, + { .reg = 1, .start = 6, .width = 1, + .name = "SD_INIT_SEQ_2_ENABLE" }, + { .reg = 1, .start = 7, .width = 1, + .name = "OTG_ATL_ROLE_BIT" }, + { .reg = 1, .start = 8, .width = 1, + .name = "OTG_HNP_BIT" }, + { .reg = 1, .start = 9, .width = 1, + .name = "USB_LOW_POWER_MODE" }, + { .reg = 1, .start = 10, .width = 1, + .name = "SKIP_CHECKDISK" }, + { .reg = 1, .start = 11, .width = 1, + .name = "USB_BOOT_PLAYER_MODE" }, + { .reg = 1, .start = 12, .width = 1, + .name = "ENUMERATE_500MA_TWICE" }, + { .reg = 1, .start = 13, .width = 19, + .name = "SPARE_GENERAL" }, + + { .reg = 2, .start = 0, .width = 32, + .name = "SPARE_2" }, + { .reg = 3, .start = 0, .width = 32, + .name = "SPARE_3" }, + { .reg = 4, .start = 0, .width = 32, + .name = "SPARE_4" }, + { .reg = 5, .start = 0, .width = 32, + .name = "SPARE_5" }, +}; + +static struct mxs_platform_persistent_data mx28_persistent_data = { + .bit_config_tab = mx28_persistent_bit_config, + .bit_config_cnt = ARRAY_SIZE(mx28_persistent_bit_config), +}; + +static struct resource mx28_persistent_res[] = { + { + .flags = IORESOURCE_MEM, + .start = RTC_PHYS_ADDR, + .end = RTC_PHYS_ADDR + 0x2000 - 1, + }, +}; + +static void mx28_init_persistent(void) +{ + struct platform_device *pdev; + pdev = mxs_get_device("mxs-persistent", 0); + if (pdev == NULL || IS_ERR(pdev)) + return; + pdev->dev.platform_data = &mx28_persistent_data; + pdev->resource = mx28_persistent_res, + pdev->num_resources = ARRAY_SIZE(mx28_persistent_res), + mxs_add_device(pdev, 3); +} +#else +static void mx28_init_persistent() +{ +} +#endif + +#if defined(CONFIG_FSL_OTP) +/* Building up eight registers's names of a bank */ +#define BANK(a, b, c, d, e, f, g, h) \ + {\ + ("HW_OCOTP_"#a), ("HW_OCOTP_"#b), ("HW_OCOTP_"#c), ("HW_OCOTP_"#d), \ + ("HW_OCOTP_"#e), ("HW_OCOTP_"#f), ("HW_OCOTP_"#g), ("HW_OCOTP_"#h) \ + } + +#define BANKS (5) +#define BANK_ITEMS (8) +static const char *bank_reg_desc[BANKS][BANK_ITEMS] = { + BANK(CUST0, CUST1, CUST2, CUST3, CRYPTO0, CRYPTO1, CRYPTO2, CRYPTO3), + BANK(HWCAP0, HWCAP1, HWCAP2, HWCAP3, HWCAP4, HWCAP5, SWCAP, CUSTCAP), + BANK(LOCK, OPS0, OPS1, OPS2, OPS3, UN0, UN1, UN2), + BANK(ROM0, ROM1, ROM2, ROM3, ROM4, ROM5, ROM6, ROM7), + BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7), +}; + +static struct fsl_otp_data otp_data = { + .fuse_name = (char **)bank_reg_desc, + .regulator_name = "vddio", + .fuse_num = BANKS * BANK_ITEMS, +}; +#undef BANK +#undef BANKS +#undef BANK_ITEMS + +static void __init mx28_init_otp(void) +{ + struct platform_device *pdev; + pdev = mxs_get_device("ocotp", 0); + if (pdev == NULL || IS_ERR(pdev)) + return; + pdev->dev.platform_data = &otp_data; + pdev->resource = NULL; + pdev->num_resources = 0; + mxs_add_device(pdev, 3); +} +#else +static void mx28_init_otp(void) +{ +} +#endif + int __init mx28_device_init(void) { mx28_init_dma(); @@ -1220,10 +1512,11 @@ int __init mx28_device_init(void) mx28_init_lradc(); mx28_init_auart(); mx28_init_mmc(); - mx28_init_gpmi(); + mx28_init_gpmi_nfc(); mx28_init_wdt(); mx28_init_rtc(); mx28_init_fec(); + mx28_init_l2switch(); mx28_init_flexcan(); mx28_init_kbd(); mx28_init_ts(); @@ -1233,7 +1526,8 @@ int __init mx28_device_init(void) mx28_init_pxp(); mx28_init_dcp(); mx28_init_battery(); - + mx28_init_persistent(); + mx28_init_otp(); return 0; } diff --git a/arch/arm/mach-mx28/emi_settings.c b/arch/arm/mach-mx28/emi_settings.c index 7dd62b9dd65a..56df6ad0c0d4 100644 --- a/arch/arm/mach-mx28/emi_settings.c +++ b/arch/arm/mach-mx28/emi_settings.c @@ -27,7 +27,6 @@ #include <linux/platform_device.h> #include <linux/mmc/host.h> #include <linux/phy.h> -#include <linux/fec.h> #include <asm/mach/map.h> diff --git a/arch/arm/mach-mx28/include/mach/mx28.h b/arch/arm/mach-mx28/include/mach/mx28.h index f74b8941fad2..097253266709 100644 --- a/arch/arm/mach-mx28/include/mach/mx28.h +++ b/arch/arm/mach-mx28/include/mach/mx28.h @@ -226,12 +226,17 @@ #define MX28_SOC_IO_ADDRESS(x) \ ((x) - MX28_SOC_IO_PHYS_BASE + MX28_SOC_IO_VIRT_BASE) +#ifdef __ASSEMBLER__ +#define IO_ADDRESS(x) \ + MX28_SOC_IO_ADDRESS(x) +#else #define IO_ADDRESS(x) \ (void __force __iomem *) \ (((x) >= (unsigned long)MX28_SOC_IO_PHYS_BASE) && \ ((x) < (unsigned long)MX28_SOC_IO_PHYS_BASE + \ MX28_SOC_IO_AREA_SIZE) ? \ MX28_SOC_IO_ADDRESS(x) : 0xDEADBEEF) +#endif #ifdef CONFIG_MXS_EARLY_CONSOLE #define MXS_DEBUG_CONSOLE_PHYS DUART_PHYS_ADDR diff --git a/arch/arm/mach-mx28/mx28evk.c b/arch/arm/mach-mx28/mx28evk.c index 650d16a4fb0a..37beb27f7065 100644 --- a/arch/arm/mach-mx28/mx28evk.c +++ b/arch/arm/mach-mx28/mx28evk.c @@ -39,7 +39,7 @@ static struct i2c_board_info __initdata mxs_i2c_device[] = { { I2C_BOARD_INFO("sgtl5000-i2c", 0x14), .flags = I2C_M_TEN } }; -static void i2c_device_init(void) +static void __init i2c_device_init(void) { i2c_register_board_info(0, mxs_i2c_device, ARRAY_SIZE(mxs_i2c_device)); } @@ -104,7 +104,12 @@ static void __init mx28evk_init_machine(void) { mx28_pinctrl_init(); /* Init iram allocate */ +#ifdef CONFIG_VECTORS_PHY_ADDR + /* reserve the first page for irq vector table*/ + iram_init(MX28_OCRAM_PHBASE + PAGE_SIZE, MX28_OCRAM_SIZE - PAGE_SIZE); +#else iram_init(MX28_OCRAM_PHBASE, MX28_OCRAM_SIZE); +#endif mx28_gpio_init(); mx28evk_pins_init(); diff --git a/arch/arm/mach-mx28/mx28evk.h b/arch/arm/mach-mx28/mx28evk.h index c141749cc183..d973c0f7ef19 100644 --- a/arch/arm/mach-mx28/mx28evk.h +++ b/arch/arm/mach-mx28/mx28evk.h @@ -20,4 +20,9 @@ #define __ASM_ARM_MACH_MX28EVK_H extern void __init mx28evk_pins_init(void); +extern int mx28evk_enet_gpio_init(void); +void mx28evk_enet_io_lowerpower_enter(void); +void mx28evk_enet_io_lowerpower_exit(void); + + #endif /* __ASM_ARM_MACH_MX28EVK_H */ diff --git a/arch/arm/mach-mx28/mx28evk_pins.c b/arch/arm/mach-mx28/mx28evk_pins.c index 8bb253607658..7d5b64328324 100644 --- a/arch/arm/mach-mx28/mx28evk_pins.c +++ b/arch/arm/mach-mx28/mx28evk_pins.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/gpio.h> +#include <linux/delay.h> #include <mach/pinctrl.h> @@ -530,15 +531,106 @@ static struct pin_desc mx28evk_fixed_pins[] = { .name = "SSP0_SCK", .id = PINID_SSP0_SCK, .fun = PIN_FUN1, - .strength = PAD_8MA, + .strength = PAD_12MA, .voltage = PAD_3_3V, .pullup = 0, - .drive = 1, + .drive = 2, .pull = 0, }, #endif +#if defined(CONFIG_LEDS_MXS) || defined(CONFIG_LEDS_MXS_MODULE) + { + .name = "LEDS_PWM0", + .id = PINID_AUART1_RX, + .fun = PIN_FUN3, + .strength = PAD_8MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, + { + .name = "LEDS_PWM1", + .id = PINID_AUART1_TX, + .fun = PIN_FUN3, + .strength = PAD_8MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, +#endif +#if defined(CONFIG_SND_MXS_SOC_DAI) || defined(CONFIG_SND_MXS_SOC_DAI_MODULE) + /* Configurations of SAIF0 port pins */ + { + .name = "SAIF0_MCLK", + .id = PINID_SAIF0_MCLK, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, + { + .name = "SAIF0_LRCLK", + .id = PINID_SAIF0_LRCLK, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, + { + .name = "SAIF0_BITCLK", + .id = PINID_SAIF0_BITCLK, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, + { + .name = "SAIF0_SDATA0", + .id = PINID_SAIF0_SDATA0, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, + { + .name = "SAIF1_SDATA0", + .id = PINID_SAIF1_SDATA0, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, +#endif +#if defined(CONFIG_SND_SOC_MXS_SPDIF) || \ + defined(CONFIG_SND_SOC_MXS_SPDIF_MODULE) + { + .name = "SPDIF", + .id = PINID_SPDIF, + .fun = PIN_FUN1, + .strength = PAD_12MA, + .voltage = PAD_3_3V, + .pullup = 1, + .drive = 1, + .pull = 1, + }, +#endif +}; -#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)\ + || defined(CONFIG_FEC_L2SWITCH) +static struct pin_desc mx28evk_eth_pins[] = { { .name = "ENET0_MDC", .id = PINID_ENET0_MDC, @@ -620,106 +712,77 @@ static struct pin_desc mx28evk_fixed_pins[] = { .drive = 1, }, { - .name = "ENET_CLK", - .id = PINID_ENET_CLK, - .fun = PIN_FUN1, + .name = "ENET1_RX_EN", + .id = PINID_ENET0_CRS, + .fun = PIN_FUN2, .strength = PAD_8MA, .pull = 1, .pullup = 1, .voltage = PAD_3_3V, - .drive = 1, - }, -#endif -#if defined(CONFIG_LEDS_MXS) || defined(CONFIG_LEDS_MXS_MODULE) - { - .name = "LEDS_PWM0", - .id = PINID_AUART1_RX, - .fun = PIN_FUN3, - .strength = PAD_8MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .drive = 1, }, { - .name = "LEDS_PWM1", - .id = PINID_AUART1_TX, - .fun = PIN_FUN3, - .strength = PAD_8MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET1_RXD0", + .id = PINID_ENET0_RXD2, + .fun = PIN_FUN2, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, -#endif -#if defined(CONFIG_SND_MXS_SOC_DAI) || defined(CONFIG_SND_MXS_SOC_DAI_MODULE) - /* Configurations of SAIF0 port pins */ { - .name = "SAIF0_MCLK", - .id = PINID_SAIF0_MCLK, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET1_RXD1", + .id = PINID_ENET0_RXD3, + .fun = PIN_FUN2, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, { - .name = "SAIF0_LRCLK", - .id = PINID_SAIF0_LRCLK, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET1_TX_EN", + .id = PINID_ENET0_COL, + .fun = PIN_FUN2, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, { - .name = "SAIF0_BITCLK", - .id = PINID_SAIF0_BITCLK, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET1_TXD0", + .id = PINID_ENET0_TXD2, + .fun = PIN_FUN2, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, { - .name = "SAIF0_SDATA0", - .id = PINID_SAIF0_SDATA0, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET1_TXD1", + .id = PINID_ENET0_TXD3, + .fun = PIN_FUN2, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, { - .name = "SAIF1_SDATA0", - .id = PINID_SAIF1_SDATA0, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, + .name = "ENET_CLK", + .id = PINID_ENET_CLK, + .fun = PIN_FUN1, + .strength = PAD_8MA, + .pull = 1, + .pullup = 1, + .voltage = PAD_3_3V, + .drive = 1, }, -#endif -#if defined(CONFIG_SND_SOC_MXS_SPDIF) || \ - defined(CONFIG_SND_SOC_MXS_SPDIF_MODULE) - { - .name = "SPDIF", - .id = PINID_SPDIF, - .fun = PIN_FUN1, - .strength = PAD_12MA, - .voltage = PAD_3_3V, - .pullup = 1, - .drive = 1, - .pull = 1, - }, -#endif }; - +#endif static int __initdata enable_ssp1 = { 0 }; static int __init ssp1_setup(char *__unused) @@ -835,16 +898,16 @@ static struct pin_desc mx28evk_ssp1_pins[] = { .name = "SSP1_SCK", .id = PINID_GPMI_WRN, .fun = PIN_FUN2, - .strength = PAD_8MA, + .strength = PAD_12MA, .voltage = PAD_3_3V, .pullup = 0, - .drive = 1, + .drive = 2, .pull = 0, }, }; -int __initdata enable_gpmi = { 0 }; +int enable_gpmi = { 0 }; static int __init gpmi_setup(char *__unused) { enable_gpmi = 1; @@ -1009,7 +1072,8 @@ static struct pin_desc mx28evk_gpmi_pins[] = { }, }; -#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)\ + || defined(CONFIG_FEC_L2SWITCH) int mx28evk_enet_gpio_init(void) { /* pwr */ @@ -1019,15 +1083,54 @@ int mx28evk_enet_gpio_init(void) /* reset phy */ gpio_request(MXS_PIN_TO_GPIO(PINID_ENET0_RX_CLK), "PHY_RESET"); gpio_direction_output(MXS_PIN_TO_GPIO(PINID_ENET0_RX_CLK), 0); + mdelay(10); gpio_direction_output(MXS_PIN_TO_GPIO(PINID_ENET0_RX_CLK), 1); return 0; } + +void mx28evk_enet_io_lowerpower_enter(void) +{ + int i; + gpio_direction_output(MXS_PIN_TO_GPIO(PINID_SSP1_DATA3), 1); + gpio_direction_output(MXS_PIN_TO_GPIO(PINID_ENET0_RX_CLK), 0); + gpio_request(MXS_PIN_TO_GPIO(PINID_ENET0_TX_CLK), "ETH_INT"); + gpio_direction_output(MXS_PIN_TO_GPIO(PINID_ENET0_TX_CLK), 0); + + for (i = 0; i < ARRAY_SIZE(mx28evk_eth_pins); i++) { + mxs_release_pin(mx28evk_eth_pins[i].id, + mx28evk_eth_pins[i].name); + gpio_request(MXS_PIN_TO_GPIO(mx28evk_eth_pins[i].id), + mx28evk_eth_pins[i].name); + gpio_direction_output( + MXS_PIN_TO_GPIO(mx28evk_eth_pins[i].id), 0); + } + +} + +void mx28evk_enet_io_lowerpower_exit(void) +{ + int i; + gpio_direction_output(MXS_PIN_TO_GPIO(PINID_SSP1_DATA3), 0); + gpio_direction_output(MXS_PIN_TO_GPIO(PINID_ENET0_RX_CLK), 1); + gpio_free(MXS_PIN_TO_GPIO(PINID_ENET0_TX_CLK)); + for (i = 0; i < ARRAY_SIZE(mx28evk_eth_pins); i++) { + gpio_free(MXS_PIN_TO_GPIO(mx28evk_eth_pins[i].id)); + mxs_request_pin(mx28evk_eth_pins[i].id, + mx28evk_eth_pins[i].fun, + mx28evk_eth_pins[i].name); + } +} + #else int mx28evk_enet_gpio_init(void) { return 0; } +void mx28evk_enet_io_lowerpower_enter(void) +{} +void mx28evk_enet_io_lowerpower_exit(void) +{} #endif void __init mx28evk_init_pin_group(struct pin_desc *pins, unsigned count) @@ -1071,5 +1174,9 @@ void __init mx28evk_pins_init(void) mx28evk_init_pin_group(mx28evk_gpmi_pins, ARRAY_SIZE(mx28evk_gpmi_pins)); } - +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)\ + || defined(CONFIG_FEC_L2SWITCH) + mx28evk_init_pin_group(mx28evk_eth_pins, + ARRAY_SIZE(mx28evk_eth_pins)); +#endif } diff --git a/arch/arm/mach-mx28/pm.c b/arch/arm/mach-mx28/pm.c index c26a495f59e2..4ac13bc3248c 100644 --- a/arch/arm/mach-mx28/pm.c +++ b/arch/arm/mach-mx28/pm.c @@ -36,12 +36,13 @@ #include <mach/dma.h> #include <mach/regs-rtc.h> #include "regs-clkctrl.h" -#include "regs-pinctrl.h" #include <mach/regs-power.h> #include <mach/regs-pwm.h> #include <mach/regs-rtc.h> #include <mach/../../regs-icoll.h> #include "regs-dram.h" +#include "mx28_pins.h" +#include "mx28evk.h" #include "sleep.h" @@ -79,7 +80,8 @@ static inline void do_standby(void) u32 reg_clkctrl_clkseq, reg_clkctrl_xtal; unsigned long iram_phy_addr; void *iram_virtual_addr; - + int wakeupirq; + mx28evk_enet_io_lowerpower_enter(); /* * 1) switch clock domains from PLL to 24MHz * 2) lower voltage (TODO) @@ -110,7 +112,8 @@ static inline void do_standby(void) cpu_parent = clk_get_parent(cpu_clk); hbus_rate = clk_get_rate(hbus_clk); clk_set_parent(cpu_clk, osc_clk); - } + } else + pr_err("fail to get cpu clk\n"); local_fiq_disable(); @@ -122,15 +125,18 @@ static inline void do_standby(void) reg_clkctrl_xtal = __raw_readl(REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL); + /* do suspend */ mx28_cpu_standby_ptr = iram_virtual_addr; mx28_cpu_standby_ptr(); + wakeupirq = __raw_readl(IO_ADDRESS(ICOLL_PHYS_ADDR) + HW_ICOLL_STAT); + + pr_info("wakeup irq = %d\n", wakeupirq); __raw_writel(reg_clkctrl_clkseq, REGS_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ); __raw_writel(reg_clkctrl_xtal, REGS_CLKCTRL_BASE + HW_CLKCTRL_XTAL); - saved_sleep_state = 0; /* waking from standby */ __raw_writel(BM_POWER_CTRL_PSWITCH_IRQ, REGS_POWER_BASE + HW_POWER_CTRL_CLR); @@ -149,6 +155,7 @@ static inline void do_standby(void) clk_put(cpu_clk); iram_free(iram_phy_addr, MAX_POWEROFF_CODE_SIZE); + mx28evk_enet_io_lowerpower_exit(); } static noinline void do_mem(void) @@ -255,38 +262,52 @@ static struct mx28_pswitch_state pswitch_state = { .dev_running = 0, }; -static irqreturn_t pswitch_interrupt(int irq, void *dev) +#define PSWITCH_POWER_DOWN_DELAY 30 +static struct delayed_work pswitch_work; +static void pswitch_check_work(struct work_struct *work) { int pin_value, i; - - /* check if irq by pswitch */ - if (!(__raw_readl(REGS_POWER_BASE + HW_POWER_CTRL) & - BM_POWER_CTRL_PSWITCH_IRQ)) - return IRQ_HANDLED; - for (i = 0; i < 3000; i++) { + for (i = 0; i < PSWITCH_POWER_DOWN_DELAY; i++) { pin_value = __raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BF_POWER_STS_PSWITCH(0x1); if (pin_value == 0) break; - mdelay(1); + msleep(100); } - if (i < 3000) { + if (i < PSWITCH_POWER_DOWN_DELAY) { pr_info("pswitch goto suspend\n"); complete(&suspend_request); } else { pr_info("release pswitch to power down\n"); - for (i = 0; i < 5000; i++) { + for (i = 0; i < 500; i++) { pin_value = __raw_readl(REGS_POWER_BASE + HW_POWER_STS) & BF_POWER_STS_PSWITCH(0x1); if (pin_value == 0) break; - mdelay(1); + msleep(10); } pr_info("pswitch power down\n"); mx28_pm_power_off(); } __raw_writel(BM_POWER_CTRL_PSWITCH_IRQ, REGS_POWER_BASE + HW_POWER_CTRL_CLR); + __raw_writel(BM_POWER_CTRL_ENIRQ_PSWITCH, + REGS_POWER_BASE + HW_POWER_CTRL_SET); + __raw_writel(BM_POWER_CTRL_PSWITCH_IRQ, + REGS_POWER_BASE + HW_POWER_CTRL_CLR); +} + + +static irqreturn_t pswitch_interrupt(int irq, void *dev) +{ + + /* check if irq by pswitch */ + if (!(__raw_readl(REGS_POWER_BASE + HW_POWER_CTRL) & + BM_POWER_CTRL_PSWITCH_IRQ)) + return IRQ_HANDLED; + __raw_writel(BM_POWER_CTRL_ENIRQ_PSWITCH, + REGS_POWER_BASE + HW_POWER_CTRL_CLR); + schedule_delayed_work(&pswitch_work, 1); return IRQ_HANDLED; } @@ -299,6 +320,7 @@ static struct irqaction pswitch_irq = { static void init_pswitch(void) { + INIT_DELAYED_WORK(&pswitch_work, pswitch_check_work); kthread_run(suspend_thread_fn, NULL, "pswitch"); __raw_writel(BM_POWER_CTRL_PSWITCH_IRQ, REGS_POWER_BASE + HW_POWER_CTRL_CLR); diff --git a/arch/arm/mach-mx28/regs-clkctrl.h b/arch/arm/mach-mx28/regs-clkctrl.h index 161860c2fcf0..9de19275fa91 100644 --- a/arch/arm/mach-mx28/regs-clkctrl.h +++ b/arch/arm/mach-mx28/regs-clkctrl.h @@ -478,6 +478,7 @@ #define BM_CLKCTRL_ENET_RSRVD0 0x0000FFFF #define BF_CLKCTRL_ENET_RSRVD0(v) \ (((v) << 0) & BM_CLKCTRL_ENET_RSRVD0) +#define BM_CLKCTRL_ENET_1588_40MHZ 0x01880000 #define HW_CLKCTRL_HSADC (0x00000150) diff --git a/arch/arm/mach-mx28/sleep.S b/arch/arm/mach-mx28/sleep.S index 438f588f85d3..54e86bd4f717 100644 --- a/arch/arm/mach-mx28/sleep.S +++ b/arch/arm/mach-mx28/sleep.S @@ -25,6 +25,7 @@ #include <mach/hardware.h> #include <mach/regs-power.h> #include <mach/regs-rtc.h> +#include "regs-pinctrl.h" #include "regs-clkctrl.h" #include "regs-dram.h" #include "sleep.h" @@ -39,11 +40,104 @@ #define HW_DRAM_CTL17_ADDR \ (MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL17) +#define HW_DRAM_CTL22_ADDR \ + (MX28_SOC_IO_ADDRESS(DRAM_PHYS_ADDR) + HW_DRAM_CTL22) + #define HW_RTC_PERSISTENT0_ADDR \ (MX28_SOC_IO_ADDRESS(RTC_PHYS_ADDR) + HW_RTC_PERSISTENT0) +#define HW_CLKCTRL_EMI_ADDR \ + (MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) + HW_CLKCTRL_EMI) +#define HW_CLKCTRL_PLL0CTRL0_ADDR \ + (MX28_SOC_IO_ADDRESS(CLKCTRL_PHYS_ADDR) + HW_CLKCTRL_PLL0CTRL0) +#define HW_POWER_VDDIOCTRL_ADDR \ + (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDIOCTRL) +#define HW_POWER_VDDDCTRL_ADDR \ + (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDDCTRL) +#define HW_POWER_VDDACTRL_ADDR \ + (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_VDDACTRL) +#define HW_PINCTRL_EMI_DS_CTRL_ADDR \ + (MX28_SOC_IO_ADDRESS(PINCTRL_PHYS_ADDR) + HW_PINCTRL_EMI_DS_CTRL) + +#define HW_POWER_LOOPCTRL_ADDR \ + (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_LOOPCTRL) + +#define HW_POWER_MINPWR_ADDR \ + (MX28_SOC_IO_ADDRESS(POWER_PHYS_ADDR) + HW_POWER_MINPWR) #define PHYS_RAM_START 0x40000000 +#define LOWER_VDDIO 6 +#define LOWER_VDDA 9 +#define LOWER_VDDD 0x16 + +#define VDDIOCTRL_BACKUP 0 +#define VDDACTRL_BACKUP 1 +#define VDDDCTRL_BACKUP 2 +#define POWER_LOOPCTRL_BACKUP 3 +#define POWER_MINPWR_BACKUP 4 + +.macro PM_BITS_SET, addr, val + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, [r0] + orr r1, r1, #(\val) + str r1, [r0] +.endm + +.macro PM_BITS_CLR, addr, val + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, [r0] + bic r1, r1, #(\val) + str r1, [r0] +.endm + +.macro PM_BACKUP_REG, addr, num + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, [r0] + str r1, __mx28_temp_stack + \num * 4 +.endm + +.macro PM_WRITE_REG_MASK, addr, bitmask, val + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, [r0] + bic r1, r1, #(\bitmask) + orr r1, r1, #(\val) + str r1, [r0] +.endm + +.macro PM_SET_AND_BACKUP_REG, addr, bitmask, val, num + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, [r0] + str r1, __mx28_temp_stack + \num * 4 + bic r1, r1, #(\bitmask) + orr r1, r1, #(\val) + str r1, [r0] +.endm + +.macro PM_SET_RESTORE_REG, addr, num + mov r0, #(\addr & 0x000000FF) + orr r0, r0, #(\addr & 0x0000FF00) + orr r0, r0, #(\addr & 0x00FF0000) + orr r0, r0, #(\addr & 0xFF000000) + ldr r1, __mx28_temp_stack + \num * 4 + str r1, [r0] +.endm + + .global cpu_arm926_switch_mm .text @@ -59,7 +153,6 @@ ENTRY(mx28_cpu_standby) ldr r1, __mx28_flush_cache_addr mov lr, pc mov pc, r1 - @ put DRAM into self refresh mov r0, #(HW_DRAM_CTL17_ADDR & 0x000000FF) orr r0, r0, #(HW_DRAM_CTL17_ADDR & 0x0000FF00) @@ -69,6 +162,67 @@ ENTRY(mx28_cpu_standby) orr r1, r1, #(BM_DRAM_CTL17_SREFRESH) str r1, [r0] @ wait for it to actually happen + mov r0, #24 << 5 +11: sub r0, r0, #1 + cmp r0, #0 + bne 11b + + @ gate clk + mov r0, #(HW_CLKCTRL_EMI_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0xFF000000) + ldr r1, [r0] + orr r1, r1, #(BM_CLKCTRL_EMI_CLKGATE) + str r1, [r0] + +// PM_SET_AND_BACKUP_REG HW_PINCTRL_EMI_DS_CTRL_ADDR,\ +// BM_PINCTRL_EMI_DS_CTRL_DDR_MODE,\ +// BF_PINCTRL_EMI_DS_CTRL_DDR_MODE(0x1), 4 + + // vddio + PM_SET_AND_BACKUP_REG HW_POWER_VDDIOCTRL_ADDR,\ + BM_POWER_VDDIOCTRL_TRG, LOWER_VDDIO, VDDIOCTRL_BACKUP + mov r0, #24 << 10 +1: sub r0, r0, #1 + cmp r0, #0 + bne 1b + + PM_SET_AND_BACKUP_REG HW_POWER_VDDACTRL_ADDR,\ + BM_POWER_VDDACTRL_TRG, LOWER_VDDA, VDDACTRL_BACKUP + mov r0, #24 << 10 +2: sub r0, r0, #1 + cmp r0, #0 + bne 2b + + PM_SET_AND_BACKUP_REG HW_POWER_VDDDCTRL_ADDR,\ + BM_POWER_VDDDCTRL_TRG, LOWER_VDDD, VDDDCTRL_BACKUP + mov r0, #24 << 10 +3: sub r0, r0, #1 + cmp r0, #0 + bne 3b + + PM_BACKUP_REG HW_POWER_LOOPCTRL_ADDR, POWER_LOOPCTRL_BACKUP + PM_BACKUP_REG HW_POWER_MINPWR_ADDR, POWER_MINPWR_BACKUP + +// PM_BITS_CLR HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_EN_RCSCALE +// PM_WRITE_REG_MASK HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_DC_R,\ +// (2<<BP_POWER_LOOPCTRL_DC_R) + + // half fets + PM_BITS_SET HW_POWER_MINPWR_ADDR, BM_POWER_MINPWR_HALF_FETS + + PM_BITS_CLR HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_CM_HYST_THRESH + PM_BITS_CLR HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_EN_CM_HYST + PM_BITS_CLR HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_EN_DF_HYST + + // enable PFM + PM_BITS_SET HW_POWER_LOOPCTRL_ADDR, BM_POWER_LOOPCTRL_HYST_SIGN + PM_BITS_SET HW_POWER_MINPWR_ADDR, BM_POWER_MINPWR_EN_DC_PFM + + + //Gated PLL0 + PM_BITS_CLR HW_CLKCTRL_PLL0CTRL0_ADDR, BM_CLKCTRL_PLL0CTRL0_POWER @ do enter standby mov r0, #(HW_CLKCTRL_CPU_ADDR & 0x000000FF) @@ -89,6 +243,39 @@ ENTRY(mx28_cpu_standby) nop nop + PM_BITS_SET HW_CLKCTRL_PLL0CTRL0_ADDR, BM_CLKCTRL_PLL0CTRL0_POWER + + PM_SET_RESTORE_REG HW_POWER_MINPWR_ADDR, POWER_MINPWR_BACKUP + + PM_SET_RESTORE_REG HW_POWER_LOOPCTRL_ADDR, POWER_LOOPCTRL_BACKUP + + // vddio + PM_SET_RESTORE_REG HW_POWER_VDDIOCTRL_ADDR, VDDIOCTRL_BACKUP + mov r0, #24 << 10 +10: sub r0, r0, #1 + cmp r0, #0 + bne 10b + PM_SET_RESTORE_REG HW_POWER_VDDACTRL_ADDR, VDDACTRL_BACKUP + mov r0, #24 << 10 +20: sub r0, r0, #1 + cmp r0, #0 + bne 20b + PM_SET_RESTORE_REG HW_POWER_VDDDCTRL_ADDR, VDDDCTRL_BACKUP + mov r0, #24 << 10 +30: sub r0, r0, #1 + cmp r0, #0 + bne 30b + + @ ungate clk + mov r0, #(HW_CLKCTRL_EMI_ADDR & 0x000000FF) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x0000FF00) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0x00FF0000) + orr r0, r0, #(HW_CLKCTRL_EMI_ADDR & 0xFF000000) + ldr r1, [r0] + bic r1, r1, #(BM_CLKCTRL_EMI_CLKGATE) + str r1, [r0] + +// PM_SET_RESTORE_REG HW_PINCTRL_EMI_DS_CTRL_ADDR, 4 @ restore normal DRAM mode mov r0, #(HW_DRAM_CTL17_ADDR & 0x000000FF) orr r0, r0, #(HW_DRAM_CTL17_ADDR & 0x0000FF00) @@ -98,6 +285,10 @@ ENTRY(mx28_cpu_standby) bic r1, r1, #BM_DRAM_CTL17_SREFRESH str r1, [r0] @ wait for it to actually happen + mov r0, #24 << 5 +12: sub r0, r0, #1 + cmp r0, #0 + bne 12b nop nop @@ -108,7 +299,7 @@ ENTRY(mx28_cpu_standby) .space 0x100 __mx28_temp_stack: - .word 0 + .space 128 #ifdef CONFIG_STMP378X_RAM_FREQ_SCALING #include "emi.inc" diff --git a/arch/arm/mach-mx28/usb_dr.c b/arch/arm/mach-mx28/usb_dr.c index 13344ef0e26f..50a2f8b381af 100644 --- a/arch/arm/mach-mx28/usb_dr.c +++ b/arch/arm/mach-mx28/usb_dr.c @@ -63,7 +63,7 @@ static struct fsl_usb2_platform_data __maybe_unused dr_utmi_config = { }; /* - * resources + * OTG resources */ static struct resource otg_resources[] = { [0] = { @@ -78,6 +78,22 @@ static struct resource otg_resources[] = { }, }; +/* + * UDC resources (same as OTG resource) + */ +static struct resource udc_resources[] = { + [0] = { + .start = (u32)USBCTRL0_PHYS_ADDR, + .end = (u32)(USBCTRL0_PHYS_ADDR + 0x1ff), + .flags = IORESOURCE_MEM, + }, + + [1] = { + .start = IRQ_USB0, + .flags = IORESOURCE_IRQ, + }, +}; + static u64 dr_udc_dmamask = ~(u32) 0; static void dr_udc_release(struct device *dev) { @@ -111,8 +127,8 @@ static struct platform_device __maybe_unused dr_otg_device = { .dma_mask = &dr_otg_dmamask, .coherent_dma_mask = 0xffffffff, }, - .resource = otg_resources, - .num_resources = ARRAY_SIZE(otg_resources), + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), }; @@ -156,5 +172,5 @@ void fsl_phy_set_power(struct fsl_xcvr_ops *this, #ifdef CONFIG_MXS_VBUS_CURRENT_DRAW fs_initcall(usb_dr_init); #else - module_init(usb_dr_init); + subsys_initcall(usb_dr_init); #endif |