summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx2/clock_imx27.c29
-rw-r--r--arch/arm/plat-mxc/include/mach/mx27.h4
-rw-r--r--arch/arm/plat-mxc/include/mach/mx2x.h60
-rw-r--r--arch/arm/plat-mxc/system.c20
-rw-r--r--drivers/i2c/busses/i2c-imx.c9
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;
}