diff options
-rw-r--r-- | arch/arm/mach-mx2/clock_imx27.c | 29 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/mx27.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/mx2x.h | 60 | ||||
-rw-r--r-- | arch/arm/plat-mxc/system.c | 20 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 9 |
5 files changed, 106 insertions, 16 deletions
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index ff5e33298914..208dc83ff0c2 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -400,13 +400,26 @@ static unsigned long get_rate_ipg(struct clk *clk) { unsigned long rate, ipg_pdf; - if (mx27_revision() >= CHIP_REV_2_0) - return clk_get_rate(clk->parent); - else + rate = clk_get_rate(clk->parent); + + /* + * For i.MX27 TO2, IPG_CLK = MPLL / (3 * (AHB_DIV + 1)) + * as calculated in a Freescale provided version of + * RedBoot. + * Ref: packages/hal/arm/mx27/var/current/src/cmds.c:get_main_clock(...) + * in RedBoot. + */ + if (mx27_revision() >= CHIP_REV_2_0) { + + ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3; + rate = rate / (3 * (ipg_pdf + 1)); + } + else { ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1; + rate = rate / (ipg_pdf + 1); + } - rate = clk_get_rate(clk->parent); - return rate / (ipg_pdf + 1); + return rate; } static unsigned long get_rate_per(struct clk *clk) @@ -693,6 +706,12 @@ static void __init to2_adjust_clocks(void) if (!(cscr & CCM_CSCR_VPU)) vpu_clk.parent = &spll_clk; + + /* + * For TO2 and later, MPLL path 1 is the parent for + * IPG clock. MPLL path 1 has the same rate as MPLL. + */ + ipg_clk.parent = &mpll_main1_clk; } else { cpu_clk.parent = &mpll_clk; cpu_clk.set_parent = NULL; diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index dc3ad9aa952a..36206d5c9078 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -28,8 +28,8 @@ #define IRAM_BASE_ADDR 0xFFFF4C00 /* internal ram */ #define MSHC_BASE_ADDR (AIPI_BASE_ADDR + 0x18000) -#define GPT5_BASE_ADDR (AIPI_BASE_ADDR + 0x19000) -#define GPT4_BASE_ADDR (AIPI_BASE_ADDR + 0x1A000) +#define GPT4_BASE_ADDR (AIPI_BASE_ADDR + 0x19000) +#define GPT5_BASE_ADDR (AIPI_BASE_ADDR + 0x1A000) #define UART5_BASE_ADDR (AIPI_BASE_ADDR + 0x1B000) #define UART6_BASE_ADDR (AIPI_BASE_ADDR + 0x1C000) #define I2C2_BASE_ADDR (AIPI_BASE_ADDR + 0x1D000) diff --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h index db5d921e0fe6..18a89575c7f9 100644 --- a/arch/arm/plat-mxc/include/mach/mx2x.h +++ b/arch/arm/plat-mxc/include/mach/mx2x.h @@ -179,4 +179,64 @@ #define DMA_REQ_CSPI3_TX 2 #define DMA_REQ_CSPI3_RX 1 +/* + * GPT register address offsets & bit definitions. + */ +#define GPTX_TCTL_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x00) +#define GPTX_TPRER_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x04) +#define GPTX_TCMP_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x08) +#define GPTX_TCR_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x0C) +#define GPTX_TCN_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x10) +#define GPTX_TSTAT_ADDR(GPTX_BASE_ADDR) (IO_ADDRESS(GPTX_BASE_ADDR) + 0x14) + +/* TCTL bit definitions */ +#define GPT_TCTL_SWR (1 << 15) +#define GPT_TCTL_CLKSRC_BIT_SHIFT 1 +#define GPT_TCTL_CLKSRC_MASK (7 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CLKSRC_NOCLOCK (0 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CLKSRC_HIFREQ (1 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CLKSRC_HIFREQ_BY4 (2 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CLKSRC_CLKIN (3 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CLKSRC_CLK32K (4 << GPT_TCTL_CLKSRC_BIT_SHIFT) +#define GPT_TCTL_CC_ENABLE (1 << 10) +#define GPT_TCTL_OM_TOGGLE (1 << 9) +#define GPT_TCTL_COMP_INTR_EN (1 << 4) +#define GPT_TCTL_TEN (1 << 0) + +/* TSTAT bit definitions */ +#define GPT_TSTAT_COMP_EVNT (1 << 0) + +/* + * GPT calculations. + */ + +/* + * GPT MCLK: GPT_CLK_DIV is 1, except when PERCLK1 is the clock source, in + * which case it can be 1 or 4. + */ +#define GPT_MCLK(GPT_CLK_SRC_HZ, GPT_CLK_DIV) (GPT_CLK_SRC_HZ/GPT_CLK_DIV) + +/* + * GPT PCLK: GPT_PRESCALER is the prescaler divide value, which is one + * more than the PRER register value. + */ +#define GPT_PCLK(GPT_CLK_SRC_HZ, GPT_CLK_DIV, GPT_PRESCALER) \ + (GPT_MCLK(GPT_CLK_SRC_HZ, GPT_CLK_DIV)/GPT_PRESCALER) + +/* + * GPT Compare count: GPT_PCLK_HZ/FREQ_HZ, where FREQ_HZ is the + * frequency at which a compare event should occur. + * Division is performed as ((dividend + (divisor / 2)) / divisor) + * to reduce rounding errors. + */ +#define GPT_COMPARE(FREQ_HZ, GPT_PCLK_HZ) \ + ( (GPT_PCLK_HZ + (FREQ_HZ / 2)) / FREQ_HZ ) + +/* + * GPT Compare register value: GPT_COMPARE - 1 + */ +#define GPT_TCMP_VAL(FREQ_HZ, GPT_PCLK_HZ) \ + ( GPT_COMPARE(FREQ_HZ, GPT_PCLK_HZ) - 1 ) + + #endif /* __ASM_ARCH_MXC_MX2x_H__ */ diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c index 97f42799fa58..6d993a8eb355 100644 --- a/arch/arm/plat-mxc/system.c +++ b/arch/arm/plat-mxc/system.c @@ -39,6 +39,7 @@ static void __iomem *wdog_base; void arch_reset(char mode, const char *cmd) { unsigned int wcr_enable; + unsigned int wdog_clk_present = 1; #ifdef CONFIG_ARCH_MXC91231 if (cpu_is_mxc91231()) { @@ -48,22 +49,29 @@ void arch_reset(char mode, const char *cmd) #endif if (cpu_is_mx1()) { wcr_enable = (1 << 0); + wdog_clk_present = 1; } else { struct clk *clk; clk = clk_get_sys("imx-wdt.0", NULL); - if (!IS_ERR(clk)) + if (IS_ERR(clk)) + wdog_clk_present = 0; + else clk_enable(clk); wcr_enable = (1 << 2); } - /* Assert SRS signal */ - __raw_writew(wcr_enable, wdog_base); + if (wdog_clk_present) { + /* Assert SRS signal */ + __raw_writew(wcr_enable, wdog_base); - /* wait for reset to assert... */ - mdelay(500); + /* wait for reset to assert... */ + mdelay(500); - printk(KERN_ERR "Watchdog reset failed to assert reset\n"); + printk(KERN_ERR "Watchdog reset failed to assert reset\n"); + } else { + printk(KERN_ERR "Watchdog clock not available.\n"); + } /* delay to allow the serial port to show the message */ mdelay(50); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index e3654d683e15..5c3cf1a0fc08 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -160,7 +160,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) { int result; - result = wait_event_interruptible_timeout(i2c_imx->queue, + result = wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); if (unlikely(result < 0)) { @@ -228,6 +228,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) writeb(temp, i2c_imx->base + IMX_I2C_I2CR); i2c_imx->stopped = 1; } +#ifdef ENABLE_IMX_I2C_RESET_AFTER_STOP if (cpu_is_mx1()) { /* * This delay caused by an i.MXL hardware bug. @@ -235,12 +236,14 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) */ udelay(i2c_imx->disable_delay); } - +#endif if (!i2c_imx->stopped) i2c_imx_bus_busy(i2c_imx, 0); +#ifdef ENABLE_IMX_I2C_RESET_AFTER_STOP /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); +#endif clk_disable(i2c_imx->clk); } @@ -293,7 +296,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; writeb(temp, i2c_imx->base + IMX_I2C_I2SR); - wake_up_interruptible(&i2c_imx->queue); + wake_up(&i2c_imx->queue); return IRQ_HANDLED; } |