add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
#
# Makefile for the linux kernel.
#
obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
obj-m :=
obj-n :=
obj- :=
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o

View File

@@ -0,0 +1,4 @@
zreladdr-y := 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000

View File

@@ -0,0 +1,993 @@
/*
* arch/arm/mach-pnx4008/clock.c
*
* Clock control driver for PNX4008
*
* Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
* Generic clock management functions are partially based on:
* linux/arch/arm/mach-omap/clock.c
*
* 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/clock.h>
#include "clock.h"
/*forward declaration*/
static struct clk per_ck;
static struct clk hclk_ck;
static struct clk ck_1MHz;
static struct clk ck_13MHz;
static struct clk ck_pll1;
static int local_set_rate(struct clk *clk, u32 rate);
static inline void clock_lock(void)
{
local_irq_disable();
}
static inline void clock_unlock(void)
{
local_irq_enable();
}
static void propagate_rate(struct clk *clk)
{
struct clk *tmp_clk;
tmp_clk = clk;
while (tmp_clk->propagate_next) {
tmp_clk = tmp_clk->propagate_next;
local_set_rate(tmp_clk, tmp_clk->user_rate);
}
}
static inline void clk_reg_disable(struct clk *clk)
{
if (clk->enable_reg)
__raw_writel(__raw_readl(clk->enable_reg) &
~(1 << clk->enable_shift), clk->enable_reg);
}
static inline void clk_reg_enable(struct clk *clk)
{
if (clk->enable_reg)
__raw_writel(__raw_readl(clk->enable_reg) |
(1 << clk->enable_shift), clk->enable_reg);
}
static inline void clk_reg_disable1(struct clk *clk)
{
if (clk->enable_reg1)
__raw_writel(__raw_readl(clk->enable_reg1) &
~(1 << clk->enable_shift1), clk->enable_reg1);
}
static inline void clk_reg_enable1(struct clk *clk)
{
if (clk->enable_reg1)
__raw_writel(__raw_readl(clk->enable_reg1) |
(1 << clk->enable_shift1), clk->enable_reg1);
}
static int clk_wait_for_pll_lock(struct clk *clk)
{
int i;
i = 0;
while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ; /*wait for PLL to lock */
if (!(__raw_readl(clk->scale_reg) & 1)) {
printk(KERN_ERR
"%s ERROR: failed to lock, scale reg data: %x\n",
clk->name, __raw_readl(clk->scale_reg));
return -1;
}
return 0;
}
static int switch_to_dirty_13mhz(struct clk *clk)
{
int i;
int ret;
u32 tmp_reg;
ret = 0;
if (!clk->rate)
clk_reg_enable1(clk);
tmp_reg = __raw_readl(clk->parent_switch_reg);
/*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
if (!(tmp_reg & 1)) {
tmp_reg |= (1 << 1); /* Trigger switch to 13'MHz (dirty) clock */
__raw_writel(tmp_reg, clk->parent_switch_reg);
i = 0;
while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13'MHz selection status */
if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
printk(KERN_ERR
"%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
clk->name, __raw_readl(clk->parent_switch_reg));
ret = -1;
}
}
if (!clk->rate)
clk_reg_disable1(clk);
return ret;
}
static int switch_to_clean_13mhz(struct clk *clk)
{
int i;
int ret;
u32 tmp_reg;
ret = 0;
if (!clk->rate)
clk_reg_enable1(clk);
tmp_reg = __raw_readl(clk->parent_switch_reg);
/*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
if (tmp_reg & 1) {
tmp_reg &= ~(1 << 1); /* Trigger switch to 13MHz (clean) clock */
__raw_writel(tmp_reg, clk->parent_switch_reg);
i = 0;
while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13MHz selection status */
if (__raw_readl(clk->parent_switch_reg) & 1) {
printk(KERN_ERR
"%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
clk->name, __raw_readl(clk->parent_switch_reg));
ret = -1;
}
}
if (!clk->rate)
clk_reg_disable1(clk);
return ret;
}
static int set_13MHz_parent(struct clk *clk, struct clk *parent)
{
int ret = -EINVAL;
if (parent == &ck_13MHz)
ret = switch_to_clean_13mhz(clk);
else if (parent == &ck_pll1)
ret = switch_to_dirty_13mhz(clk);
return ret;
}
#define PLL160_MIN_FCCO 156000
#define PLL160_MAX_FCCO 320000
/*
* Calculate pll160 settings.
* Possible input: up to 320MHz with step of clk->parent->rate.
* In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
* Ignored paths: "feedback" (bit 13 set), "div-by-N".
* Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
* Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
* Please refer to PNX4008 IC manual for details.
*/
static int pll160_set_rate(struct clk *clk, u32 rate)
{
u32 tmp_reg, tmp_m, tmp_2p, i;
u32 parent_rate;
int ret = -EINVAL;
parent_rate = clk->parent->rate;
if (!parent_rate)
goto out;
/* set direct run for ARM or disable output for others */
clk_reg_disable(clk);
/* disable source input as well (ignored for ARM) */
clk_reg_disable1(clk);
tmp_reg = __raw_readl(clk->scale_reg);
tmp_reg &= ~0x1ffff; /*clear all settings, power down */
__raw_writel(tmp_reg, clk->scale_reg);
rate -= rate % parent_rate; /*round down the input */
if (rate > PLL160_MAX_FCCO)
rate = PLL160_MAX_FCCO;
if (!rate) {
clk->rate = 0;
ret = 0;
goto out;
}
clk_reg_enable1(clk);
tmp_reg = __raw_readl(clk->scale_reg);
if (rate == parent_rate) {
/*enter direct bypass mode */
tmp_reg |= ((1 << 14) | (1 << 15));
__raw_writel(tmp_reg, clk->scale_reg);
clk->rate = parent_rate;
clk_reg_enable(clk);
ret = 0;
goto out;
}
i = 0;
for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
if (rate * tmp_2p >= PLL160_MIN_FCCO)
break;
i++;
}
if (tmp_2p > 1)
tmp_reg |= ((i - 1) << 11);
else
tmp_reg |= (1 << 14); /*direct mode, no divide */
tmp_m = rate * tmp_2p;
tmp_m /= parent_rate;
tmp_reg |= (tmp_m - 1) << 1; /*calculate M */
tmp_reg |= (1 << 16); /*power up PLL */
__raw_writel(tmp_reg, clk->scale_reg);
if (clk_wait_for_pll_lock(clk) < 0) {
clk_reg_disable(clk);
clk_reg_disable1(clk);
tmp_reg = __raw_readl(clk->scale_reg);
tmp_reg &= ~0x1ffff; /*clear all settings, power down */
__raw_writel(tmp_reg, clk->scale_reg);
clk->rate = 0;
ret = -EFAULT;
goto out;
}
clk->rate = (tmp_m * parent_rate) / tmp_2p;
if (clk->flags & RATE_PROPAGATES)
propagate_rate(clk);
clk_reg_enable(clk);
ret = 0;
out:
return ret;
}
/*configure PER_CLK*/
static int per_clk_set_rate(struct clk *clk, u32 rate)
{
u32 tmp;
tmp = __raw_readl(clk->scale_reg);
tmp &= ~(0x1f << 2);
tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
__raw_writel(tmp, clk->scale_reg);
clk->rate = rate;
return 0;
}
/*configure HCLK*/
static int hclk_set_rate(struct clk *clk, u32 rate)
{
u32 tmp;
tmp = __raw_readl(clk->scale_reg);
tmp = tmp & ~0x3;
switch (rate) {
case 1:
break;
case 2:
tmp |= 1;
break;
case 4:
tmp |= 2;
break;
}
__raw_writel(tmp, clk->scale_reg);
clk->rate = rate;
return 0;
}
static u32 hclk_round_rate(struct clk *clk, u32 rate)
{
switch (rate) {
case 1:
case 4:
return rate;
}
return 2;
}
static u32 per_clk_round_rate(struct clk *clk, u32 rate)
{
return CLK_RATE_13MHZ;
}
static int on_off_set_rate(struct clk *clk, u32 rate)
{
if (rate) {
clk_reg_enable(clk);
clk->rate = 1;
} else {
clk_reg_disable(clk);
clk->rate = 0;
}
return 0;
}
static int on_off_inv_set_rate(struct clk *clk, u32 rate)
{
if (rate) {
clk_reg_disable(clk); /*enable bit is inverted */
clk->rate = 1;
} else {
clk_reg_enable(clk);
clk->rate = 0;
}
return 0;
}
static u32 on_off_round_rate(struct clk *clk, u32 rate)
{
return (rate ? 1 : 0);
}
static u32 pll4_round_rate(struct clk *clk, u32 rate)
{
if (rate > CLK_RATE_208MHZ)
rate = CLK_RATE_208MHZ;
if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
}
static u32 pll3_round_rate(struct clk *clk, u32 rate)
{
if (rate > CLK_RATE_208MHZ)
rate = CLK_RATE_208MHZ;
return (rate - rate % CLK_RATE_13MHZ);
}
static u32 pll5_round_rate(struct clk *clk, u32 rate)
{
return (rate ? CLK_RATE_48MHZ : 0);
}
static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
{
return (rate ? CLK_RATE_13MHZ : 0);
}
static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
{
if (rate) {
clk_reg_disable(clk); /*enable bit is inverted */
udelay(500);
clk->rate = CLK_RATE_13MHZ;
ck_1MHz.rate = CLK_RATE_1MHZ;
} else {
clk_reg_enable(clk);
clk->rate = 0;
ck_1MHz.rate = 0;
}
return 0;
}
static int pll1_set_rate(struct clk *clk, u32 rate)
{
#if 0 /* doesn't work on some boards, probably a HW BUG */
if (rate) {
clk_reg_disable(clk); /*enable bit is inverted */
if (!clk_wait_for_pll_lock(clk)) {
clk->rate = CLK_RATE_13MHZ;
} else {
clk_reg_enable(clk);
clk->rate = 0;
}
} else {
clk_reg_enable(clk);
clk->rate = 0;
}
#endif
return 0;
}
/* Clock sources */
static struct clk osc_13MHz = {
.name = "osc_13MHz",
.flags = FIXED_RATE,
.rate = CLK_RATE_13MHZ,
};
static struct clk ck_13MHz = {
.name = "ck_13MHz",
.parent = &osc_13MHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &ck_13MHz_round_rate,
.set_rate = &ck_13MHz_set_rate,
.enable_reg = OSC13CTRL_REG,
.enable_shift = 0,
.rate = CLK_RATE_13MHZ,
};
static struct clk osc_32KHz = {
.name = "osc_32KHz",
.flags = FIXED_RATE,
.rate = CLK_RATE_32KHZ,
};
/*attached to PLL5*/
static struct clk ck_1MHz = {
.name = "ck_1MHz",
.flags = FIXED_RATE | PARENT_SET_RATE,
.parent = &ck_13MHz,
};
/* PLL1 (397) - provides 13' MHz clock */
static struct clk ck_pll1 = {
.name = "ck_pll1",
.parent = &osc_32KHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &ck_13MHz_round_rate,
.set_rate = &pll1_set_rate,
.enable_reg = PLLCTRL_REG,
.enable_shift = 1,
.scale_reg = PLLCTRL_REG,
.rate = CLK_RATE_13MHZ,
};
/* CPU/Bus PLL */
static struct clk ck_pll4 = {
.name = "ck_pll4",
.parent = &ck_pll1,
.flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
.propagate_next = &per_ck,
.round_rate = &pll4_round_rate,
.set_rate = &pll160_set_rate,
.rate = CLK_RATE_208MHZ,
.scale_reg = HCLKPLLCTRL_REG,
.enable_reg = PWRCTRL_REG,
.enable_shift = 2,
.parent_switch_reg = SYSCLKCTRL_REG,
.set_parent = &set_13MHz_parent,
};
/* USB PLL */
static struct clk ck_pll5 = {
.name = "ck_pll5",
.parent = &ck_1MHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &pll5_round_rate,
.set_rate = &pll160_set_rate,
.scale_reg = USBCTRL_REG,
.enable_reg = USBCTRL_REG,
.enable_shift = 18,
.enable_reg1 = USBCTRL_REG,
.enable_shift1 = 17,
};
/* XPERTTeak DSP PLL */
static struct clk ck_pll3 = {
.name = "ck_pll3",
.parent = &ck_pll1,
.flags = NEEDS_INITIALIZATION,
.round_rate = &pll3_round_rate,
.set_rate = &pll160_set_rate,
.scale_reg = DSPPLLCTRL_REG,
.enable_reg = DSPCLKCTRL_REG,
.enable_shift = 3,
.enable_reg1 = DSPCLKCTRL_REG,
.enable_shift1 = 2,
.parent_switch_reg = DSPCLKCTRL_REG,
.set_parent = &set_13MHz_parent,
};
static struct clk hclk_ck = {
.name = "hclk_ck",
.parent = &ck_pll4,
.flags = PARENT_SET_RATE,
.set_rate = &hclk_set_rate,
.round_rate = &hclk_round_rate,
.scale_reg = HCLKDIVCTRL_REG,
.rate = 2,
.user_rate = 2,
};
static struct clk per_ck = {
.name = "per_ck",
.parent = &ck_pll4,
.flags = FIXED_RATE,
.propagate_next = &hclk_ck,
.set_rate = &per_clk_set_rate,
.round_rate = &per_clk_round_rate,
.scale_reg = HCLKDIVCTRL_REG,
.rate = CLK_RATE_13MHZ,
.user_rate = CLK_RATE_13MHZ,
};
static struct clk m2hclk_ck = {
.name = "m2hclk_ck",
.parent = &hclk_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_inv_set_rate,
.rate = 1,
.enable_shift = 6,
.enable_reg = PWRCTRL_REG,
};
static struct clk vfp9_ck = {
.name = "vfp9_ck",
.parent = &ck_pll4,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.rate = 1,
.enable_shift = 4,
.enable_reg = VFP9CLKCTRL_REG,
};
static struct clk keyscan_ck = {
.name = "keyscan_ck",
.parent = &osc_32KHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = KEYCLKCTRL_REG,
};
static struct clk touch_ck = {
.name = "touch_ck",
.parent = &osc_32KHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = TSCLKCTRL_REG,
};
static struct clk pwm1_ck = {
.name = "pwm1_ck",
.parent = &osc_32KHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = PWMCLKCTRL_REG,
};
static struct clk pwm2_ck = {
.name = "pwm2_ck",
.parent = &osc_32KHz,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 2,
.enable_reg = PWMCLKCTRL_REG,
};
static struct clk jpeg_ck = {
.name = "jpeg_ck",
.parent = &hclk_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = JPEGCLKCTRL_REG,
};
static struct clk ms_ck = {
.name = "ms_ck",
.parent = &ck_pll4,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 5,
.enable_reg = MSCTRL_REG,
};
static struct clk dum_ck = {
.name = "dum_ck",
.parent = &hclk_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = DUMCLKCTRL_REG,
};
static struct clk flash_ck = {
.name = "flash_ck",
.parent = &hclk_ck,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 1, /* Only MLC clock supported */
.enable_reg = FLASHCLKCTRL_REG,
};
static struct clk i2c0_ck = {
.name = "i2c0_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = I2CCLKCTRL_REG,
};
static struct clk i2c1_ck = {
.name = "i2c1_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 1,
.enable_reg = I2CCLKCTRL_REG,
};
static struct clk i2c2_ck = {
.name = "i2c2_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 2,
.enable_reg = USB_OTG_CLKCTRL_REG,
};
static struct clk spi0_ck = {
.name = "spi0_ck",
.parent = &hclk_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = SPICTRL_REG,
};
static struct clk spi1_ck = {
.name = "spi1_ck",
.parent = &hclk_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 4,
.enable_reg = SPICTRL_REG,
};
static struct clk dma_ck = {
.name = "dma_ck",
.parent = &hclk_ck,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = DMACLKCTRL_REG,
};
static struct clk uart3_ck = {
.name = "uart3_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.rate = 1,
.enable_shift = 0,
.enable_reg = UARTCLKCTRL_REG,
};
static struct clk uart4_ck = {
.name = "uart4_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 1,
.enable_reg = UARTCLKCTRL_REG,
};
static struct clk uart5_ck = {
.name = "uart5_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.rate = 1,
.enable_shift = 2,
.enable_reg = UARTCLKCTRL_REG,
};
static struct clk uart6_ck = {
.name = "uart6_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 3,
.enable_reg = UARTCLKCTRL_REG,
};
static struct clk wdt_ck = {
.name = "wdt_ck",
.parent = &per_ck,
.flags = NEEDS_INITIALIZATION,
.round_rate = &on_off_round_rate,
.set_rate = &on_off_set_rate,
.enable_shift = 0,
.enable_reg = TIMCLKCTRL_REG,
};
/* These clocks are visible outside this module
* and can be initialized
*/
static struct clk *onchip_clks[] = {
&ck_13MHz,
&ck_pll1,
&ck_pll4,
&ck_pll5,
&ck_pll3,
&vfp9_ck,
&m2hclk_ck,
&hclk_ck,
&dma_ck,
&flash_ck,
&dum_ck,
&keyscan_ck,
&pwm1_ck,
&pwm2_ck,
&jpeg_ck,
&ms_ck,
&touch_ck,
&i2c0_ck,
&i2c1_ck,
&i2c2_ck,
&spi0_ck,
&spi1_ck,
&uart3_ck,
&uart4_ck,
&uart5_ck,
&uart6_ck,
&wdt_ck,
};
static int local_clk_enable(struct clk *clk)
{
int ret = 0;
if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
&& clk->user_rate)
ret = clk->set_rate(clk, clk->user_rate);
return ret;
}
static void local_clk_disable(struct clk *clk)
{
if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
clk->set_rate(clk, 0);
}
static void local_clk_unuse(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
local_clk_disable(clk);
if (clk->parent)
local_clk_unuse(clk->parent);
}
}
static int local_clk_use(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (clk->parent)
ret = local_clk_use(clk->parent);
if (ret != 0) {
clk->usecount--;
goto out;
}
ret = local_clk_enable(clk);
if (ret != 0 && clk->parent) {
local_clk_unuse(clk->parent);
clk->usecount--;
}
}
out:
return ret;
}
static int local_set_rate(struct clk *clk, u32 rate)
{
int ret = -EINVAL;
if (clk->set_rate) {
if (clk->user_rate == clk->rate && clk->parent->rate) {
/* if clock enabled or rate not set */
clk->user_rate = clk->round_rate(clk, rate);
ret = clk->set_rate(clk, clk->user_rate);
} else
clk->user_rate = clk->round_rate(clk, rate);
ret = 0;
}
return ret;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EINVAL;
if (clk->flags & FIXED_RATE)
goto out;
clock_lock();
if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
clk->user_rate = clk->round_rate(clk, rate);
/* parent clock needs to be refreshed
for the setting to take effect */
} else {
ret = local_set_rate(clk, rate);
}
ret = 0;
clock_unlock();
out:
return ret;
}
EXPORT_SYMBOL(clk_set_rate);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *clk = ERR_PTR(-ENOENT);
struct clk **clkp;
clock_lock();
for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
clkp++) {
if (strcmp(id, (*clkp)->name) == 0
&& try_module_get((*clkp)->owner)) {
clk = (*clkp);
break;
}
}
clock_unlock();
return clk;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
clock_lock();
if (clk && !IS_ERR(clk))
module_put(clk->owner);
clock_unlock();
}
EXPORT_SYMBOL(clk_put);
unsigned long clk_get_rate(struct clk *clk)
{
unsigned long ret;
clock_lock();
ret = clk->rate;
clock_unlock();
return ret;
}
EXPORT_SYMBOL(clk_get_rate);
int clk_enable(struct clk *clk)
{
int ret = 0;
clock_lock();
ret = local_clk_use(clk);
clock_unlock();
return ret;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
clock_lock();
local_clk_unuse(clk);
clock_unlock();
}
EXPORT_SYMBOL(clk_disable);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
long ret;
clock_lock();
if (clk->round_rate)
ret = clk->round_rate(clk, rate);
else
ret = clk->rate;
clock_unlock();
return ret;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
int ret = -ENODEV;
if (!clk->set_parent)
goto out;
clock_lock();
ret = clk->set_parent(clk, parent);
if (!ret)
clk->parent = parent;
clock_unlock();
out:
return ret;
}
EXPORT_SYMBOL(clk_set_parent);
static int __init clk_init(void)
{
struct clk **clkp;
/* Disable autoclocking, as it doesn't seem to work */
__raw_writel(0xff, AUTOCLK_CTRL);
for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
clkp++) {
if (((*clkp)->flags & NEEDS_INITIALIZATION)
&& ((*clkp)->set_rate)) {
(*clkp)->user_rate = (*clkp)->rate;
local_set_rate((*clkp), (*clkp)->user_rate);
if ((*clkp)->set_parent)
(*clkp)->set_parent((*clkp), (*clkp)->parent);
}
pr_debug("%s: clock %s, rate %ld\n",
__func__, (*clkp)->name, (*clkp)->rate);
}
local_clk_use(&ck_pll4);
/* if ck_13MHz is not used, disable it. */
if (ck_13MHz.usecount == 0)
local_clk_disable(&ck_13MHz);
/* Disable autoclocking */
__raw_writeb(0xff, AUTOCLK_CTRL);
return 0;
}
arch_initcall(clk_init);

View File

@@ -0,0 +1,43 @@
/*
* arch/arm/mach-pnx4008/clock.h
*
* Clock control driver for PNX4008 - internal header file
*
* Author: Vitaly Wool <source@mvista.com>
*
* 2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
#define __ARCH_ARM_PNX4008_CLOCK_H__
struct clk {
struct list_head node;
struct module *owner;
const char *name;
struct clk *parent;
struct clk *propagate_next;
u32 rate;
u32 user_rate;
s8 usecount;
u32 flags;
u32 scale_reg;
u8 enable_shift;
u32 enable_reg;
u8 enable_shift1;
u32 enable_reg1;
u32 parent_switch_reg;
u32(*round_rate) (struct clk *, u32);
int (*set_rate) (struct clk *, u32);
int (*set_parent) (struct clk * clk, struct clk * parent);
};
/* Flags */
#define RATE_PROPAGATES (1<<0)
#define NEEDS_INITIALIZATION (1<<1)
#define PARENT_SET_RATE (1<<2)
#define FIXED_RATE (1<<3)
#endif

View File

@@ -0,0 +1,274 @@
/*
* arch/arm/mach-pnx4008/core.c
*
* PNX4008 core startup code
*
* Authors: Vitaly Wool, Dmitry Chigirev,
* Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
*
* Based on reference code received from Philips:
* Copyright (C) 2003 Philips Semiconductors
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/serial_8250.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <mach/irq.h>
#include <mach/clock.h>
#include <mach/dma.h>
struct resource spipnx_0_resources[] = {
{
.start = PNX4008_SPI1_BASE,
.end = PNX4008_SPI1_BASE + SZ_4K,
.flags = IORESOURCE_MEM,
}, {
.start = PER_SPI1_REC_XMIT,
.flags = IORESOURCE_DMA,
}, {
.start = SPI1_INT,
.flags = IORESOURCE_IRQ,
}, {
.flags = 0,
},
};
struct resource spipnx_1_resources[] = {
{
.start = PNX4008_SPI2_BASE,
.end = PNX4008_SPI2_BASE + SZ_4K,
.flags = IORESOURCE_MEM,
}, {
.start = PER_SPI2_REC_XMIT,
.flags = IORESOURCE_DMA,
}, {
.start = SPI2_INT,
.flags = IORESOURCE_IRQ,
}, {
.flags = 0,
}
};
static struct spi_board_info spi_board_info[] __initdata = {
{
.modalias = "m25p80",
.max_speed_hz = 1000000,
.bus_num = 1,
.chip_select = 0,
},
};
static struct platform_device spipnx_1 = {
.name = "spipnx",
.id = 1,
.num_resources = ARRAY_SIZE(spipnx_0_resources),
.resource = spipnx_0_resources,
.dev = {
.coherent_dma_mask = 0xFFFFFFFF,
},
};
static struct platform_device spipnx_2 = {
.name = "spipnx",
.id = 2,
.num_resources = ARRAY_SIZE(spipnx_1_resources),
.resource = spipnx_1_resources,
.dev = {
.coherent_dma_mask = 0xFFFFFFFF,
},
};
static struct plat_serial8250_port platform_serial_ports[] = {
{
.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
.mapbase = (unsigned long)PNX4008_UART5_BASE,
.irq = IIR5_INT,
.uartclk = PNX4008_UART_CLK,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
},
{
.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
.mapbase = (unsigned long)PNX4008_UART3_BASE,
.irq = IIR3_INT,
.uartclk = PNX4008_UART_CLK,
.regshift = 2,
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
},
{}
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = &platform_serial_ports,
},
};
static struct platform_device nand_flash_device = {
.name = "pnx4008-flash",
.id = -1,
.dev = {
.coherent_dma_mask = 0xFFFFFFFF,
},
};
/* The dmamask must be set for OHCI to work */
static u64 ohci_dmamask = ~(u32) 0;
static struct resource ohci_resources[] = {
{
.start = IO_ADDRESS(PNX4008_USB_CONFIG_BASE),
.end = IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x100),
.flags = IORESOURCE_MEM,
}, {
.start = USB_HOST_INT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device ohci_device = {
.name = "pnx4008-usb-ohci",
.id = -1,
.dev = {
.dma_mask = &ohci_dmamask,
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(ohci_resources),
.resource = ohci_resources,
};
static struct platform_device sdum_device = {
.name = "pnx4008-sdum",
.id = 0,
.dev = {
.coherent_dma_mask = 0xffffffff,
},
};
static struct platform_device rgbfb_device = {
.name = "pnx4008-rgbfb",
.id = 0,
.dev = {
.coherent_dma_mask = 0xffffffff,
}
};
struct resource watchdog_resources[] = {
{
.start = PNX4008_WDOG_BASE,
.end = PNX4008_WDOG_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device watchdog_device = {
.name = "pnx4008-watchdog",
.id = -1,
.num_resources = ARRAY_SIZE(watchdog_resources),
.resource = watchdog_resources,
};
static struct platform_device *devices[] __initdata = {
&spipnx_1,
&spipnx_2,
&serial_device,
&ohci_device,
&nand_flash_device,
&sdum_device,
&rgbfb_device,
&watchdog_device,
};
extern void pnx4008_uart_init(void);
static void __init pnx4008_init(void)
{
/*disable all START interrupt sources,
and clear all START interrupt flags */
__raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
__raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
platform_add_devices(devices, ARRAY_SIZE(devices));
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
/* Switch on the UART clocks */
pnx4008_uart_init();
}
static struct map_desc pnx4008_io_desc[] __initdata = {
{
.virtual = IO_ADDRESS(PNX4008_IRAM_BASE),
.pfn = __phys_to_pfn(PNX4008_IRAM_BASE),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
.pfn = __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
.length = SZ_1M - SZ_128K,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
.pfn = __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
.length = SZ_128K * 3,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
.pfn = __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
.length = SZ_1M,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(PNX4008_AHB2FAB_BASE),
.pfn = __phys_to_pfn(PNX4008_AHB2FAB_BASE),
.length = SZ_1M,
.type = MT_DEVICE,
},
};
void __init pnx4008_map_io(void)
{
iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
}
extern struct sys_timer pnx4008_timer;
MACHINE_START(PNX4008, "Philips PNX4008")
/* Maintainer: MontaVista Software Inc. */
.phys_io = 0x40090000,
.io_pg_offst = (0xf4090000 >> 18) & 0xfffc,
.boot_params = 0x80000100,
.map_io = pnx4008_map_io,
.init_irq = pnx4008_init_irq,
.init_machine = pnx4008_init,
.timer = &pnx4008_timer,
MACHINE_END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,329 @@
/*
* arch/arm/mach-pnx4008/gpio.c
*
* PNX4008 GPIO driver
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
#include <mach/gpio.h>
/* register definitions */
#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE)
#define PIO_INP_STATE (0x00U)
#define PIO_OUTP_SET (0x04U)
#define PIO_OUTP_CLR (0x08U)
#define PIO_OUTP_STATE (0x0CU)
#define PIO_DRV_SET (0x10U)
#define PIO_DRV_CLR (0x14U)
#define PIO_DRV_STATE (0x18U)
#define PIO_SDINP_STATE (0x1CU)
#define PIO_SDOUTP_SET (0x20U)
#define PIO_SDOUTP_CLR (0x24U)
#define PIO_MUX_SET (0x28U)
#define PIO_MUX_CLR (0x2CU)
#define PIO_MUX_STATE (0x30U)
static inline void gpio_lock(void)
{
local_irq_disable();
}
static inline void gpio_unlock(void)
{
local_irq_enable();
}
/* Inline functions */
static inline int gpio_read_bit(u32 reg, int gpio)
{
u32 bit, val;
int ret = -EFAULT;
if (gpio < 0)
goto out;
bit = GPIO_BIT(gpio);
if (bit) {
val = __raw_readl(PIO_VA_BASE + reg);
ret = (val & bit) ? 1 : 0;
}
out:
return ret;
}
static inline int gpio_set_bit(u32 reg, int gpio)
{
u32 bit, val;
int ret = -EFAULT;
if (gpio < 0)
goto out;
bit = GPIO_BIT(gpio);
if (bit) {
val = __raw_readl(PIO_VA_BASE + reg);
val |= bit;
__raw_writel(val, PIO_VA_BASE + reg);
ret = 0;
}
out:
return ret;
}
/* Very simple access control, bitmap for allocated/free */
static unsigned long access_map[4];
#define INP_INDEX 0
#define OUTP_INDEX 1
#define GPIO_INDEX 2
#define MUX_INDEX 3
/*GPIO to Input Mapping */
static short gpio_to_inp_map[32] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 24, -1
};
/*GPIO to Mux Mapping */
static short gpio_to_mux_map[32] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 0, 1, 4, 5, -1
};
/*Output to Mux Mapping */
static short outp_to_mux_map[32] = {
-1, -1, -1, 6, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 2, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
};
int pnx4008_gpio_register_pin(unsigned short pin)
{
unsigned long bit = GPIO_BIT(pin);
int ret = -EBUSY; /* Already in use */
gpio_lock();
if (GPIO_ISBID(pin)) {
if (access_map[GPIO_INDEX] & bit)
goto out;
access_map[GPIO_INDEX] |= bit;
} else if (GPIO_ISRAM(pin)) {
if (access_map[GPIO_INDEX] & bit)
goto out;
access_map[GPIO_INDEX] |= bit;
} else if (GPIO_ISMUX(pin)) {
if (access_map[MUX_INDEX] & bit)
goto out;
access_map[MUX_INDEX] |= bit;
} else if (GPIO_ISOUT(pin)) {
if (access_map[OUTP_INDEX] & bit)
goto out;
access_map[OUTP_INDEX] |= bit;
} else if (GPIO_ISIN(pin)) {
if (access_map[INP_INDEX] & bit)
goto out;
access_map[INP_INDEX] |= bit;
} else
goto out;
ret = 0;
out:
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_register_pin);
int pnx4008_gpio_unregister_pin(unsigned short pin)
{
unsigned long bit = GPIO_BIT(pin);
int ret = -EFAULT; /* Not registered */
gpio_lock();
if (GPIO_ISBID(pin)) {
if (~access_map[GPIO_INDEX] & bit)
goto out;
access_map[GPIO_INDEX] &= ~bit;
} else if (GPIO_ISRAM(pin)) {
if (~access_map[GPIO_INDEX] & bit)
goto out;
access_map[GPIO_INDEX] &= ~bit;
} else if (GPIO_ISMUX(pin)) {
if (~access_map[MUX_INDEX] & bit)
goto out;
access_map[MUX_INDEX] &= ~bit;
} else if (GPIO_ISOUT(pin)) {
if (~access_map[OUTP_INDEX] & bit)
goto out;
access_map[OUTP_INDEX] &= ~bit;
} else if (GPIO_ISIN(pin)) {
if (~access_map[INP_INDEX] & bit)
goto out;
access_map[INP_INDEX] &= ~bit;
} else
goto out;
ret = 0;
out:
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
unsigned long pnx4008_gpio_read_pin(unsigned short pin)
{
unsigned long ret = -EFAULT;
int gpio = GPIO_BIT_MASK(pin);
gpio_lock();
if (GPIO_ISOUT(pin)) {
ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
} else if (GPIO_ISRAM(pin)) {
if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
}
} else if (GPIO_ISBID(pin)) {
ret = gpio_read_bit(PIO_DRV_STATE, gpio);
if (ret > 0)
ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
else if (ret == 0)
ret =
gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
} else if (GPIO_ISIN(pin)) {
ret = gpio_read_bit(PIO_INP_STATE, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_read_pin);
/* Write Value to output */
int pnx4008_gpio_write_pin(unsigned short pin, int output)
{
int gpio = GPIO_BIT_MASK(pin);
int ret = -EFAULT;
gpio_lock();
if (GPIO_ISOUT(pin)) {
printk( "writing '%x' to '%x'\n",
gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
} else if (GPIO_ISRAM(pin)) {
if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
PIO_SDOUTP_CLR, gpio);
} else if (GPIO_ISBID(pin)) {
if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
ret = gpio_set_bit(output ? PIO_OUTP_SET :
PIO_OUTP_CLR, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_write_pin);
/* Value = 1 : Set GPIO pin as output */
/* Value = 0 : Set GPIO pin as input */
int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
{
int gpio = GPIO_BIT_MASK(pin);
int ret = -EFAULT;
gpio_lock();
if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
int pnx4008_gpio_read_pin_direction(unsigned short pin)
{
int gpio = GPIO_BIT_MASK(pin);
int ret = -EFAULT;
gpio_lock();
if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
ret = gpio_read_bit(PIO_DRV_STATE, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
/* Value = 1 : Set pin to muxed function */
/* Value = 0 : Set pin as GPIO */
int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
{
int gpio = GPIO_BIT_MASK(pin);
int ret = -EFAULT;
gpio_lock();
if (GPIO_ISBID(pin)) {
ret =
gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
gpio_to_mux_map[gpio]);
} else if (GPIO_ISOUT(pin)) {
ret =
gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
outp_to_mux_map[gpio]);
} else if (GPIO_ISMUX(pin)) {
ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
int pnx4008_gpio_read_pin_mux(unsigned short pin)
{
int gpio = GPIO_BIT_MASK(pin);
int ret = -EFAULT;
gpio_lock();
if (GPIO_ISBID(pin)) {
ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
} else if (GPIO_ISOUT(pin)) {
ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
} else if (GPIO_ISMUX(pin)) {
ret = gpio_read_bit(PIO_MUX_STATE, gpio);
}
gpio_unlock();
return ret;
}
EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);

View File

@@ -0,0 +1,168 @@
/*
* I2C initialization for PNX4008.
*
* Author: Vitaly Wool <vitalywool@gmail.com>
*
* 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/i2c-pnx.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <mach/platform.h>
#include <mach/irqs.h>
#include <mach/i2c.h>
static int set_clock_run(struct platform_device *pdev)
{
struct clk *clk;
char name[10];
int retval = 0;
snprintf(name, 10, "i2c%d_ck", pdev->id);
clk = clk_get(&pdev->dev, name);
if (!IS_ERR(clk)) {
clk_set_rate(clk, 1);
clk_put(clk);
} else
retval = -ENOENT;
return retval;
}
static int set_clock_stop(struct platform_device *pdev)
{
struct clk *clk;
char name[10];
int retval = 0;
snprintf(name, 10, "i2c%d_ck", pdev->id);
clk = clk_get(&pdev->dev, name);
if (!IS_ERR(clk)) {
clk_set_rate(clk, 0);
clk_put(clk);
} else
retval = -ENOENT;
return retval;
}
static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
{
int retval = 0;
#ifdef CONFIG_PM
retval = set_clock_run(pdev);
#endif
return retval;
}
static int i2c_pnx_resume(struct platform_device *pdev)
{
int retval = 0;
#ifdef CONFIG_PM
retval = set_clock_run(pdev);
#endif
return retval;
}
static u32 calculate_input_freq(struct platform_device *pdev)
{
return HCLK_MHZ;
}
static struct i2c_pnx_algo_data pnx_algo_data0 = {
.base = PNX4008_I2C1_BASE,
.irq = I2C_1_INT,
};
static struct i2c_pnx_algo_data pnx_algo_data1 = {
.base = PNX4008_I2C2_BASE,
.irq = I2C_2_INT,
};
static struct i2c_pnx_algo_data pnx_algo_data2 = {
.base = (PNX4008_USB_CONFIG_BASE + 0x300),
.irq = USB_I2C_INT,
};
static struct i2c_adapter pnx_adapter0 = {
.name = I2C_CHIP_NAME "0",
.algo_data = &pnx_algo_data0,
};
static struct i2c_adapter pnx_adapter1 = {
.name = I2C_CHIP_NAME "1",
.algo_data = &pnx_algo_data1,
};
static struct i2c_adapter pnx_adapter2 = {
.name = "USB-I2C",
.algo_data = &pnx_algo_data2,
};
static struct i2c_pnx_data i2c0_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter0,
};
static struct i2c_pnx_data i2c1_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter1,
};
static struct i2c_pnx_data i2c2_data = {
.suspend = i2c_pnx_suspend,
.resume = i2c_pnx_resume,
.calculate_input_freq = calculate_input_freq,
.set_clock_run = set_clock_run,
.set_clock_stop = set_clock_stop,
.adapter = &pnx_adapter2,
};
static struct platform_device i2c0_device = {
.name = "pnx-i2c",
.id = 0,
.dev = {
.platform_data = &i2c0_data,
},
};
static struct platform_device i2c1_device = {
.name = "pnx-i2c",
.id = 1,
.dev = {
.platform_data = &i2c1_data,
},
};
static struct platform_device i2c2_device = {
.name = "pnx-i2c",
.id = 2,
.dev = {
.platform_data = &i2c2_data,
},
};
static struct platform_device *devices[] __initdata = {
&i2c0_device,
&i2c1_device,
&i2c2_device,
};
void __init pnx4008_register_i2c_devices(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
}

View File

@@ -0,0 +1,62 @@
/*
* arch/arm/mach-pnx4008/include/mach/clock.h
*
* Clock control driver for PNX4008 - header file
*
* Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __PNX4008_CLOCK_H__
#define __PNX4008_CLOCK_H__
struct module;
struct clk;
#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
#define HCLKDIVCTRL_REG (PWRMAN_VA_BASE + 0x40)
#define PWRCTRL_REG (PWRMAN_VA_BASE + 0x44)
#define PLLCTRL_REG (PWRMAN_VA_BASE + 0x48)
#define OSC13CTRL_REG (PWRMAN_VA_BASE + 0x4c)
#define SYSCLKCTRL_REG (PWRMAN_VA_BASE + 0x50)
#define HCLKPLLCTRL_REG (PWRMAN_VA_BASE + 0x58)
#define USBCTRL_REG (PWRMAN_VA_BASE + 0x64)
#define SDRAMCLKCTRL_REG (PWRMAN_VA_BASE + 0x68)
#define MSCTRL_REG (PWRMAN_VA_BASE + 0x80)
#define BTCLKCTRL (PWRMAN_VA_BASE + 0x84)
#define DUMCLKCTRL_REG (PWRMAN_VA_BASE + 0x90)
#define I2CCLKCTRL_REG (PWRMAN_VA_BASE + 0xac)
#define KEYCLKCTRL_REG (PWRMAN_VA_BASE + 0xb0)
#define TSCLKCTRL_REG (PWRMAN_VA_BASE + 0xb4)
#define PWMCLKCTRL_REG (PWRMAN_VA_BASE + 0xb8)
#define TIMCLKCTRL_REG (PWRMAN_VA_BASE + 0xbc)
#define SPICTRL_REG (PWRMAN_VA_BASE + 0xc4)
#define FLASHCLKCTRL_REG (PWRMAN_VA_BASE + 0xc8)
#define UART3CLK_REG (PWRMAN_VA_BASE + 0xd0)
#define UARTCLKCTRL_REG (PWRMAN_VA_BASE + 0xe4)
#define DMACLKCTRL_REG (PWRMAN_VA_BASE + 0xe8)
#define AUTOCLK_CTRL (PWRMAN_VA_BASE + 0xec)
#define JPEGCLKCTRL_REG (PWRMAN_VA_BASE + 0xfc)
#define AUDIOCONFIG_VA_BASE IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE)
#define DSPPLLCTRL_REG (AUDIOCONFIG_VA_BASE + 0x60)
#define DSPCLKCTRL_REG (AUDIOCONFIG_VA_BASE + 0x64)
#define AUDIOCLKCTRL_REG (AUDIOCONFIG_VA_BASE + 0x68)
#define AUDIOPLLCTRL_REG (AUDIOCONFIG_VA_BASE + 0x6C)
#define USB_OTG_CLKCTRL_REG IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4)
#define VFP9CLKCTRL_REG IO_ADDRESS(PNX4008_DEBUG_BASE)
#define CLK_RATE_13MHZ 13000
#define CLK_RATE_1MHZ 1000
#define CLK_RATE_208MHZ 208000
#define CLK_RATE_48MHZ 48000
#define CLK_RATE_32KHZ 32
#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */
#endif

View File

@@ -0,0 +1,23 @@
/* arch/arm/mach-pnx4008/include/mach/debug-macro.S
*
* Debugging macro include header
*
* Copyright (C) 1994-1999 Russell King
* Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
mov \rx, #0x00090000
addeq \rx, \rx, #0x40000000
addne \rx, \rx, #0xf4000000
.endm
#define UART_SHIFT 2
#include <asm/hardware/debug-8250.S>

View File

@@ -0,0 +1,160 @@
/*
* arch/arm/mach-pnx4008/include/mach/dma.h
*
* PNX4008 DMA header file
*
* Author: Vitaly Wool
* Copyright: MontaVista Software Inc. (c) 2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#include "platform.h"
#define MAX_DMA_CHANNELS 8
#define DMAC_BASE IO_ADDRESS(PNX4008_DMA_CONFIG_BASE)
#define DMAC_INT_STAT (DMAC_BASE + 0x0000)
#define DMAC_INT_TC_STAT (DMAC_BASE + 0x0004)
#define DMAC_INT_TC_CLEAR (DMAC_BASE + 0x0008)
#define DMAC_INT_ERR_STAT (DMAC_BASE + 0x000c)
#define DMAC_INT_ERR_CLEAR (DMAC_BASE + 0x0010)
#define DMAC_SOFT_SREQ (DMAC_BASE + 0x0024)
#define DMAC_CONFIG (DMAC_BASE + 0x0030)
#define DMAC_Cx_SRC_ADDR(c) (DMAC_BASE + 0x0100 + (c) * 0x20)
#define DMAC_Cx_DEST_ADDR(c) (DMAC_BASE + 0x0104 + (c) * 0x20)
#define DMAC_Cx_LLI(c) (DMAC_BASE + 0x0108 + (c) * 0x20)
#define DMAC_Cx_CONTROL(c) (DMAC_BASE + 0x010c + (c) * 0x20)
#define DMAC_Cx_CONFIG(c) (DMAC_BASE + 0x0110 + (c) * 0x20)
enum {
WIDTH_BYTE = 0,
WIDTH_HWORD,
WIDTH_WORD
};
enum {
FC_MEM2MEM_DMA,
FC_MEM2PER_DMA,
FC_PER2MEM_DMA,
FC_PER2PER_DMA,
FC_PER2PER_DPER,
FC_MEM2PER_PER,
FC_PER2MEM_PER,
FC_PER2PER_SPER
};
enum {
DMA_INT_UNKNOWN = 0,
DMA_ERR_INT = 1,
DMA_TC_INT = 2,
};
enum {
DMA_BUFFER_ALLOCATED = 1,
DMA_HAS_LL = 2,
};
enum {
PER_CAM_DMA_1 = 0,
PER_NDF_FLASH = 1,
PER_MBX_SLAVE_FIFO = 2,
PER_SPI2_REC_XMIT = 3,
PER_MS_SD_RX_XMIT = 4,
PER_HS_UART_1_XMIT = 5,
PER_HS_UART_1_RX = 6,
PER_HS_UART_2_XMIT = 7,
PER_HS_UART_2_RX = 8,
PER_HS_UART_7_XMIT = 9,
PER_HS_UART_7_RX = 10,
PER_SPI1_REC_XMIT = 11,
PER_MLC_NDF_SREC = 12,
PER_CAM_DMA_2 = 13,
PER_PRNG_INFIFO = 14,
PER_PRNG_OUTFIFO = 15,
};
struct pnx4008_dma_ch_ctrl {
int tc_mask;
int cacheable;
int bufferable;
int priv_mode;
int di;
int si;
int dest_ahb1;
int src_ahb1;
int dwidth;
int swidth;
int dbsize;
int sbsize;
int tr_size;
};
struct pnx4008_dma_ch_config {
int halt;
int active;
int lock;
int itc;
int ie;
int flow_cntrl;
int dest_per;
int src_per;
};
struct pnx4008_dma_ll {
unsigned long src_addr;
unsigned long dest_addr;
u32 next_dma;
unsigned long ch_ctrl;
struct pnx4008_dma_ll *next;
int flags;
void *alloc_data;
int (*free) (void *);
};
struct pnx4008_dma_config {
int is_ll;
unsigned long src_addr;
unsigned long dest_addr;
unsigned long ch_ctrl;
unsigned long ch_cfg;
struct pnx4008_dma_ll *ll;
u32 ll_dma;
int flags;
void *alloc_data;
int (*free) (void *);
};
extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *);
extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t);
extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
extern int pnx4008_request_channel(char *, int,
void (*)(int, int, void *),
void *);
extern void pnx4008_free_channel(int);
extern int pnx4008_config_dma(int, int, int);
extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *,
unsigned long *);
extern int pnx4008_dma_parse_control(unsigned long,
struct pnx4008_dma_ch_ctrl *);
extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *,
unsigned long *);
extern int pnx4008_dma_parse_config(unsigned long,
struct pnx4008_dma_ch_config *);
extern int pnx4008_config_channel(int, struct pnx4008_dma_config *);
extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *);
extern int pnx4008_dma_ch_enable(int);
extern int pnx4008_dma_ch_disable(int);
extern int pnx4008_dma_ch_enabled(int);
extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *,
struct pnx4008_dma_ch_ctrl *);
extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *,
struct pnx4008_dma_ch_ctrl *);
#endif /* _ASM_ARCH_DMA_H */

View File

@@ -0,0 +1,127 @@
/*
* arch/arm/mach-pnx4008/include/mach/entry-macro.S
*
* Low-level IRQ helper macros for PNX4008-based platforms
*
* 2005-2006 (c) MontaVista Software, Inc.
* Author: Vitaly Wool <vwool@ru.mvista.com>
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include "platform.h"
#define IO_BASE 0xF0000000
#define IO_ADDRESS(x) (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
#define INTRC_MASK 0x00
#define INTRC_RAW_STAT 0x04
#define INTRC_STAT 0x08
#define INTRC_POLAR 0x0C
#define INTRC_ACT_TYPE 0x10
#define INTRC_TYPE 0x14
#define SIC1_BASE_INT 32
#define SIC2_BASE_INT 64
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
/* decode the MIC interrupt numbers */
ldr \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
ldr \irqstat, [\base, #INTRC_STAT]
cmp \irqstat,#1<<16
movhs \irqnr,#16
movlo \irqnr,#0
movhs \irqstat,\irqstat,lsr#16
cmp \irqstat,#1<<8
addhs \irqnr,\irqnr,#8
movhs \irqstat,\irqstat,lsr#8
cmp \irqstat,#1<<4
addhs \irqnr,\irqnr,#4
movhs \irqstat,\irqstat,lsr#4
cmp \irqstat,#1<<2
addhs \irqnr,\irqnr,#2
movhs \irqstat,\irqstat,lsr#2
cmp \irqstat,#1<<1
addhs \irqnr,\irqnr,#1
/* was there an interrupt ? if not then drop out with EQ status */
teq \irqstat,#0
beq 1003f
/* and now check for extended IRQ reasons */
cmp \irqnr,#1
bls 1003f
cmp \irqnr,#30
blo 1002f
/* IRQ 31,30 : High priority cascade IRQ handle */
/* read the correct SIC */
/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */
/* set the base IRQ number */
ldreq \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
moveq \irqnr,#SIC1_BASE_INT
ldrne \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
movne \irqnr,#SIC2_BASE_INT
ldr \irqstat, [\base, #INTRC_STAT]
ldr \tmp, [\base, #INTRC_TYPE]
/* and with inverted mask : low priority interrupts */
and \irqstat,\irqstat,\tmp
b 1004f
1003:
/* IRQ 1,0 : Low priority cascade IRQ handle */
/* read the correct SIC */
/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/
/* read the correct SIC */
/* set the base IRQ number */
ldrne \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
movne \irqnr,#SIC1_BASE_INT
ldreq \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
moveq \irqnr,#SIC2_BASE_INT
ldr \irqstat, [\base, #INTRC_STAT]
ldr \tmp, [\base, #INTRC_TYPE]
/* and with inverted mask : low priority interrupts */
bic \irqstat,\irqstat,\tmp
1004:
cmp \irqstat,#1<<16
addhs \irqnr,\irqnr,#16
movhs \irqstat,\irqstat,lsr#16
cmp \irqstat,#1<<8
addhs \irqnr,\irqnr,#8
movhs \irqstat,\irqstat,lsr#8
cmp \irqstat,#1<<4
addhs \irqnr,\irqnr,#4
movhs \irqstat,\irqstat,lsr#4
cmp \irqstat,#1<<2
addhs \irqnr,\irqnr,#2
movhs \irqstat,\irqstat,lsr#2
cmp \irqstat,#1<<1
addhs \irqnr,\irqnr,#1
/* is irqstat not zero */
1002:
/* we assert that irqstat is not equal to zero and return ne status if true*/
teq \irqstat,#0
1003:
.endm
.macro irq_prio_table
.endm

View File

@@ -0,0 +1,241 @@
/*
* arch/arm/mach-pnx4008/include/mach/gpio.h
*
* PNX4008 GPIO driver - header file
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef _PNX4008_GPIO_H_
#define _PNX4008_GPIO_H_
/* Block numbers */
#define GPIO_IN (0)
#define GPIO_OUT (0x100)
#define GPIO_BID (0x200)
#define GPIO_RAM (0x300)
#define GPIO_MUX (0x400)
#define GPIO_TYPE_MASK(K) ((K) & 0x700)
/* INPUT GPIOs */
/* GPI */
#define GPI_00 (GPIO_IN | 0)
#define GPI_01 (GPIO_IN | 1)
#define GPI_02 (GPIO_IN | 2)
#define GPI_03 (GPIO_IN | 3)
#define GPI_04 (GPIO_IN | 4)
#define GPI_05 (GPIO_IN | 5)
#define GPI_06 (GPIO_IN | 6)
#define GPI_07 (GPIO_IN | 7)
#define GPI_08 (GPIO_IN | 8)
#define GPI_09 (GPIO_IN | 9)
#define U1_RX (GPIO_IN | 15)
#define U2_HTCS (GPIO_IN | 16)
#define U2_RX (GPIO_IN | 17)
#define U3_RX (GPIO_IN | 18)
#define U4_RX (GPIO_IN | 19)
#define U5_RX (GPIO_IN | 20)
#define U6_IRRX (GPIO_IN | 21)
#define U7_HCTS (GPIO_IN | 22)
#define U7_RX (GPIO_IN | 23)
/* MISC IN */
#define SPI1_DATIN (GPIO_IN | 25)
#define DISP_SYNC (GPIO_IN | 26)
#define SPI2_DATIN (GPIO_IN | 27)
#define GPI_11 (GPIO_IN | 28)
#define GPIO_IN_MASK 0x1eff83ff
/* OUTPUT GPIOs */
/* GPO */
#define GPO_00 (GPIO_OUT | 0)
#define GPO_01 (GPIO_OUT | 1)
#define GPO_02 (GPIO_OUT | 2)
#define GPO_03 (GPIO_OUT | 3)
#define GPO_04 (GPIO_OUT | 4)
#define GPO_05 (GPIO_OUT | 5)
#define GPO_06 (GPIO_OUT | 6)
#define GPO_07 (GPIO_OUT | 7)
#define GPO_08 (GPIO_OUT | 8)
#define GPO_09 (GPIO_OUT | 9)
#define GPO_10 (GPIO_OUT | 10)
#define GPO_11 (GPIO_OUT | 11)
#define GPO_12 (GPIO_OUT | 12)
#define GPO_13 (GPIO_OUT | 13)
#define GPO_14 (GPIO_OUT | 14)
#define GPO_15 (GPIO_OUT | 15)
#define GPO_16 (GPIO_OUT | 16)
#define GPO_17 (GPIO_OUT | 17)
#define GPO_18 (GPIO_OUT | 18)
#define GPO_19 (GPIO_OUT | 19)
#define GPO_20 (GPIO_OUT | 20)
#define GPO_21 (GPIO_OUT | 21)
#define GPO_22 (GPIO_OUT | 22)
#define GPO_23 (GPIO_OUT | 23)
#define GPIO_OUT_MASK 0xffffff
/* BIDIRECTIONAL GPIOs */
/* RAM pins */
#define RAM_D19 (GPIO_RAM | 0)
#define RAM_D20 (GPIO_RAM | 1)
#define RAM_D21 (GPIO_RAM | 2)
#define RAM_D22 (GPIO_RAM | 3)
#define RAM_D23 (GPIO_RAM | 4)
#define RAM_D24 (GPIO_RAM | 5)
#define RAM_D25 (GPIO_RAM | 6)
#define RAM_D26 (GPIO_RAM | 7)
#define RAM_D27 (GPIO_RAM | 8)
#define RAM_D28 (GPIO_RAM | 9)
#define RAM_D29 (GPIO_RAM | 10)
#define RAM_D30 (GPIO_RAM | 11)
#define RAM_D31 (GPIO_RAM | 12)
#define GPIO_RAM_MASK 0x1fff
/* I/O pins */
#define GPIO_00 (GPIO_BID | 25)
#define GPIO_01 (GPIO_BID | 26)
#define GPIO_02 (GPIO_BID | 27)
#define GPIO_03 (GPIO_BID | 28)
#define GPIO_04 (GPIO_BID | 29)
#define GPIO_05 (GPIO_BID | 30)
#define GPIO_BID_MASK 0x7e000000
/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
#define GPIO_SDRAM_SEL (GPIO_MUX | 3)
#define GPIO_MUX_MASK 0x8
/* Extraction/assembly macros */
#define GPIO_BIT_MASK(K) ((K) & 0x1F)
#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
#define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
/* Start Enable Pin Interrupts - table 58 page 66 */
#define SE_PIN_BASE_INT 32
#define SE_U7_RX_INT 63
#define SE_U7_HCTS_INT 62
#define SE_BT_CLKREQ_INT 61
#define SE_U6_IRRX_INT 60
/*59 unused*/
#define SE_U5_RX_INT 58
#define SE_GPI_11_INT 57
#define SE_U3_RX_INT 56
#define SE_U2_HCTS_INT 55
#define SE_U2_RX_INT 54
#define SE_U1_RX_INT 53
#define SE_DISP_SYNC_INT 52
/*51 unused*/
#define SE_SDIO_INT_N 50
#define SE_MSDIO_START_INT 49
#define SE_GPI_06_INT 48
#define SE_GPI_05_INT 47
#define SE_GPI_04_INT 46
#define SE_GPI_03_INT 45
#define SE_GPI_02_INT 44
#define SE_GPI_01_INT 43
#define SE_GPI_00_INT 42
#define SE_SYSCLKEN_PIN_INT 41
#define SE_SPI1_DATAIN_INT 40
#define SE_GPI_07_INT 39
#define SE_SPI2_DATAIN_INT 38
#define SE_GPI_10_INT 37
#define SE_GPI_09_INT 36
#define SE_GPI_08_INT 35
/*34-32 unused*/
/* Start Enable Internal Interrupts - table 57 page 65 */
#define SE_INT_BASE_INT 0
#define SE_TS_IRQ 31
#define SE_TS_P_INT 30
#define SE_TS_AUX_INT 29
/*27-28 unused*/
#define SE_USB_AHB_NEED_CLK_INT 26
#define SE_MSTIMER_INT 25
#define SE_RTC_INT 24
#define SE_USB_NEED_CLK_INT 23
#define SE_USB_INT 22
#define SE_USB_I2C_INT 21
#define SE_USB_OTG_TIMER_INT 20
#define SE_USB_OTG_ATX_INT_N 19
/*18 unused*/
#define SE_DSP_GPIO4_INT 17
#define SE_KEY_IRQ 16
#define SE_DSP_SLAVEPORT_INT 15
#define SE_DSP_GPIO1_INT 14
#define SE_DSP_GPIO0_INT 13
#define SE_DSP_AHB_INT 12
/*11-6 unused*/
#define SE_GPIO_05_INT 5
#define SE_GPIO_04_INT 4
#define SE_GPIO_03_INT 3
#define SE_GPIO_02_INT 2
#define SE_GPIO_01_INT 1
#define SE_GPIO_00_INT 0
#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
extern int pnx4008_gpio_register_pin(unsigned short pin);
extern int pnx4008_gpio_unregister_pin(unsigned short pin);
extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
static inline void start_int_umask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_mask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_ack(u8 irq)
{
__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
}
static inline void start_int_set_falling_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
static inline void start_int_set_rising_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
#endif /* _PNX4008_GPIO_H_ */

View File

@@ -0,0 +1,32 @@
/*
* arch/arm/mach-pnx4008/include/mach/hardware.h
*
* Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <asm/sizes.h>
#include <mach/platform.h>
/* Start of virtual addresses for IO devices */
#define IO_BASE 0xF0000000
/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */
#define IO_ADDRESS(x) (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
#endif

View File

@@ -0,0 +1,64 @@
/*
* PNX4008-specific tweaks for I2C IP3204 block
*
* Author: Vitaly Wool <vwool@ru.mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_I2C_H__
#define __ASM_ARCH_I2C_H__
enum {
mstatus_tdi = 0x00000001,
mstatus_afi = 0x00000002,
mstatus_nai = 0x00000004,
mstatus_drmi = 0x00000008,
mstatus_active = 0x00000020,
mstatus_scl = 0x00000040,
mstatus_sda = 0x00000080,
mstatus_rff = 0x00000100,
mstatus_rfe = 0x00000200,
mstatus_tff = 0x00000400,
mstatus_tfe = 0x00000800,
};
enum {
mcntrl_tdie = 0x00000001,
mcntrl_afie = 0x00000002,
mcntrl_naie = 0x00000004,
mcntrl_drmie = 0x00000008,
mcntrl_daie = 0x00000020,
mcntrl_rffie = 0x00000040,
mcntrl_tffie = 0x00000080,
mcntrl_reset = 0x00000100,
mcntrl_cdbmode = 0x00000400,
};
enum {
rw_bit = 1 << 0,
start_bit = 1 << 8,
stop_bit = 1 << 9,
};
#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
#define HCLK_MHZ 13
#define I2C_CHIP_NAME "PNX4008-I2C"
#endif /* __ASM_ARCH_I2C_H___ */

View File

@@ -0,0 +1,21 @@
/*
* arch/arm/mach-pnx4008/include/mach/io.h
*
* Author: Dmitry Chigirev <chigirev@ru.mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
#endif

View File

@@ -0,0 +1,42 @@
/*
* arch/arm/mach-pnx4008/include/mach/irq.h
*
* PNX4008 IRQ controller driver - header file
* this one is used in entry-arnv.S as well so it cannot contain C code
*
* Copyright (c) 2005 Philips Semiconductors
* Copyright (c) 2005 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __PNX4008_IRQ_H__
#define __PNX4008_IRQ_H__
#define MIC_VA_BASE IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
#define SIC1_VA_BASE IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
#define SIC2_VA_BASE IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
/* Manual: Chapter 20, page 195 */
#define INTC_BIT(irq) (1<< ((irq) & 0x1F))
#define INTC_ER(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9)))
#define INTC_RSR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9)))
#define INTC_SR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9)))
#define INTC_APR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9)))
#define INTC_ATR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9)))
#define INTC_ITR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9)))
#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
extern void __init pnx4008_init_irq(void);
#endif /* __PNX4008_IRQ_H__ */

View File

@@ -0,0 +1,215 @@
/*
* arch/arm/mach-pnx4008/include/mach/irqs.h
*
* PNX4008 IRQ controller driver - header file
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __PNX4008_IRQS_h__
#define __PNX4008_IRQS_h__
#define NR_IRQS 96
/*Manual: table 259, page 199*/
/*SUB2 Interrupt Routing (SIC2)*/
#define SIC2_BASE_INT 64
#define CLK_SWITCH_ARM_INT 95 /*manual: Clkswitch ARM */
#define CLK_SWITCH_DSP_INT 94 /*manual: ClkSwitch DSP */
#define CLK_SWITCH_AUD_INT 93 /*manual: Clkswitch AUD */
#define GPI_06_INT 92
#define GPI_05_INT 91
#define GPI_04_INT 90
#define GPI_03_INT 89
#define GPI_02_INT 88
#define GPI_01_INT 87
#define GPI_00_INT 86
#define BT_CLKREQ_INT 85
#define SPI1_DATIN_INT 84
#define U5_RX_INT 83
#define SDIO_INT_N 82
#define CAM_HS_INT 81
#define CAM_VS_INT 80
#define GPI_07_INT 79
#define DISP_SYNC_INT 78
#define DSP_INT8 77
#define U7_HCTS_INT 76
#define GPI_10_INT 75
#define GPI_09_INT 74
#define GPI_08_INT 73
#define DSP_INT7 72
#define U2_HCTS_INT 71
#define SPI2_DATIN_INT 70
#define GPIO_05_INT 69
#define GPIO_04_INT 68
#define GPIO_03_INT 67
#define GPIO_02_INT 66
#define GPIO_01_INT 65
#define GPIO_00_INT 64
/*Manual: table 258, page 198*/
/*SUB1 Interrupt Routing (SIC1)*/
#define SIC1_BASE_INT 32
#define USB_I2C_INT 63
#define USB_DEV_HP_INT 62
#define USB_DEV_LP_INT 61
#define USB_DEV_DMA_INT 60
#define USB_HOST_INT 59
#define USB_OTG_ATX_INT_N 58
#define USB_OTG_TIMER_INT 57
#define SW_INT 56
#define SPI1_INT 55
#define KEY_IRQ 54
#define DSP_M_INT 53
#define RTC_INT 52
#define I2C_1_INT 51
#define I2C_2_INT 50
#define PLL1_LOCK_INT 49
#define PLL2_LOCK_INT 48
#define PLL3_LOCK_INT 47
#define PLL4_LOCK_INT 46
#define PLL5_LOCK_INT 45
#define SPI2_INT 44
#define DSP_INT1 43
#define DSP_INT2 42
#define DSP_TDM_INT2 41
#define TS_AUX_INT 40
#define TS_IRQ 39
#define TS_P_INT 38
#define UOUT1_TO_PAD_INT 37
#define GPI_11_INT 36
#define DSP_INT4 35
#define JTAG_COMM_RX_INT 34
#define JTAG_COMM_TX_INT 33
#define DSP_INT3 32
/*Manual: table 257, page 197*/
/*MAIN Interrupt Routing*/
#define MAIN_BASE_INT 0
#define SUB2_FIQ_N 31 /*active low */
#define SUB1_FIQ_N 30 /*active low */
#define JPEG_INT 29
#define DMA_INT 28
#define MSTIMER_INT 27
#define IIR1_INT 26
#define IIR2_INT 25
#define IIR7_INT 24
#define DSP_TDM_INT0 23
#define DSP_TDM_INT1 22
#define DSP_P_INT 21
#define DSP_INT0 20
#define DUM_INT 19
#define UOUT0_TO_PAD_INT 18
#define MP4_ENC_INT 17
#define MP4_DEC_INT 16
#define SD0_INT 15
#define MBX_INT 14
#define SD1_INT 13
#define MS_INT_N 12
#define FLASH_INT 11 /*NAND*/
#define IIR6_INT 10
#define IIR5_INT 9
#define IIR4_INT 8
#define IIR3_INT 7
#define WATCH_INT 6
#define HSTIMER_INT 5
#define ARCH_TIMER_IRQ HSTIMER_INT
#define CAM_INT 4
#define PRNG_INT 3
#define CRYPTO_INT 2
#define SUB2_IRQ_N 1 /*active low */
#define SUB1_IRQ_N 0 /*active low */
#define PNX4008_IRQ_TYPES \
{ /*IRQ #'s: */ \
IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH, /* 0, 1, 2, 3 */ \
IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 4, 5, 6, 7 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 8, 9,10,11 */ \
IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 12,13,14,15 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 16,17,18,19 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 20,21,22,23 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 24,25,26,27 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_LOW, /* 28,29,30,31 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 32,33,34,35 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH, /* 36,37,38,39 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 40,41,42,43 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 44,45,46,47 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_LOW, /* 48,49,50,51 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 52,53,54,55 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH, /* 56,57,58,59 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 60,61,62,63 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 64,65,66,67 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 68,69,70,71 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 72,73,74,75 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 76,77,78,79 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 80,81,82,83 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 84,85,86,87 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 88,89,90,91 */ \
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 92,93,94,95 */ \
}
/* Start Enable Pin Interrupts - table 58 page 66 */
#define SE_PIN_BASE_INT 32
#define SE_U7_RX_INT 63
#define SE_U7_HCTS_INT 62
#define SE_BT_CLKREQ_INT 61
#define SE_U6_IRRX_INT 60
/*59 unused*/
#define SE_U5_RX_INT 58
#define SE_GPI_11_INT 57
#define SE_U3_RX_INT 56
#define SE_U2_HCTS_INT 55
#define SE_U2_RX_INT 54
#define SE_U1_RX_INT 53
#define SE_DISP_SYNC_INT 52
/*51 unused*/
#define SE_SDIO_INT_N 50
#define SE_MSDIO_START_INT 49
#define SE_GPI_06_INT 48
#define SE_GPI_05_INT 47
#define SE_GPI_04_INT 46
#define SE_GPI_03_INT 45
#define SE_GPI_02_INT 44
#define SE_GPI_01_INT 43
#define SE_GPI_00_INT 42
#define SE_SYSCLKEN_PIN_INT 41
#define SE_SPI1_DATAIN_INT 40
#define SE_GPI_07_INT 39
#define SE_SPI2_DATAIN_INT 38
#define SE_GPI_10_INT 37
#define SE_GPI_09_INT 36
#define SE_GPI_08_INT 35
/*34-32 unused*/
/* Start Enable Internal Interrupts - table 57 page 65 */
#define SE_INT_BASE_INT 0
#define SE_TS_IRQ 31
#define SE_TS_P_INT 30
#define SE_TS_AUX_INT 29
/*27-28 unused*/
#define SE_USB_AHB_NEED_CLK_INT 26
#define SE_MSTIMER_INT 25
#define SE_RTC_INT 24
#define SE_USB_NEED_CLK_INT 23
#define SE_USB_INT 22
#define SE_USB_I2C_INT 21
#define SE_USB_OTG_TIMER_INT 20
#endif /* __PNX4008_IRQS_h__ */

View File

@@ -0,0 +1,21 @@
/*
* arch/arm/mach-pnx4008/include/mach/memory.h
*
* Copyright (c) 2005 Philips Semiconductors
* Copyright (c) 2005 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
/*
* Physical DRAM offset.
*/
#define PHYS_OFFSET UL(0x80000000)
#endif

View File

@@ -0,0 +1,21 @@
/*
* arch/arm/mach-pnx4008/include/mach/param.h
*
* Copyright (C) 1999 ARM Limited
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define HZ 100

View File

@@ -0,0 +1,69 @@
/*
* arch/arm/mach-pnx4008/include/mach/platform.h
*
* PNX4008 Base addresses - header file
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* Based on reference code received from Philips:
* Copyright (C) 2003 Philips Semiconductors
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_PLATFORM_H__
#define __ASM_ARCH_PLATFORM_H__
#define PNX4008_IRAM_BASE 0x08000000
#define PNX4008_IRAM_SIZE 0x00010000
#define PNX4008_YUV_SLAVE_BASE 0x10000000
#define PNX4008_DUM_SLAVE_BASE 0x18000000
#define PNX4008_NDF_FLASH_BASE 0x20020000
#define PNX4008_SPI1_BASE 0x20088000
#define PNX4008_SPI2_BASE 0x20090000
#define PNX4008_SD_CONFIG_BASE 0x20098000
#define PNX4008_FLASH_DATA 0x200B0000
#define PNX4008_MLC_FLASH_BASE 0x200B8000
#define PNX4008_JPEG_CONFIG_BASE 0x300A0000
#define PNX4008_DMA_CONFIG_BASE 0x31000000
#define PNX4008_USB_CONFIG_BASE 0x31020000
#define PNX4008_SDRAM_CFG_BASE 0x31080000
#define PNX4008_AHB2FAB_BASE 0x40000000
#define PNX4008_PWRMAN_BASE 0x40004000
#define PNX4008_INTCTRLMIC_BASE 0x40008000
#define PNX4008_INTCTRLSIC1_BASE 0x4000C000
#define PNX4008_INTCTRLSIC2_BASE 0x40010000
#define PNX4008_HSUART1_BASE 0x40014000
#define PNX4008_HSUART2_BASE 0x40018000
#define PNX4008_HSUART7_BASE 0x4001C000
#define PNX4008_RTC_BASE 0x40024000
#define PNX4008_PIO_BASE 0x40028000
#define PNX4008_MSTIMER_BASE 0x40034000
#define PNX4008_HSTIMER_BASE 0x40038000
#define PNX4008_WDOG_BASE 0x4003C000
#define PNX4008_DEBUG_BASE 0x40040000
#define PNX4008_TOUCH1_BASE 0x40048000
#define PNX4008_KEYSCAN_BASE 0x40050000
#define PNX4008_UARTCTRL_BASE 0x40054000
#define PNX4008_PWM_BASE 0x4005C000
#define PNX4008_UART3_BASE 0x40080000
#define PNX4008_UART4_BASE 0x40088000
#define PNX4008_UART5_BASE 0x40090000
#define PNX4008_UART6_BASE 0x40098000
#define PNX4008_I2C1_BASE 0x400A0000
#define PNX4008_I2C2_BASE 0x400A8000
#define PNX4008_MAGICGATE_BASE 0x400B0000
#define PNX4008_DUMCONF_BASE 0x400B8000
#define PNX4008_DUM_MAINCFG_BASE 0x400BC000
#define PNX4008_DSP_BASE 0x400C0000
#define PNX4008_PROFCOUNTER_BASE 0x400C8000
#define PNX4008_CRYPTO_BASE 0x400D0000
#define PNX4008_CAMIFCONF_BASE 0x400D8000
#define PNX4008_YUV2RGB_BASE 0x400E0000
#define PNX4008_AUDIOCONFIG_BASE 0x400E8000
#endif

View File

@@ -0,0 +1,33 @@
/*
* arch/arm/mach-pnx4008/include/mach/pm.h
*
* PNX4008 Power Management Routiness - header file
*
* Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_PNX4008_PM_H
#define __ASM_ARCH_PNX4008_PM_H
#ifndef __ASSEMBLER__
#include "irq.h"
#include "irqs.h"
#include "clock.h"
extern void pnx4008_pm_idle(void);
extern void pnx4008_pm_suspend(void);
extern unsigned int pnx4008_cpu_suspend_sz;
extern void pnx4008_cpu_suspend(void);
extern unsigned int pnx4008_cpu_standby_sz;
extern void pnx4008_cpu_standby(void);
extern int pnx4008_startup_pll(struct clk *);
extern int pnx4008_shutdown_pll(struct clk *);
#endif /* ASSEMBLER */
#endif /* __ASM_ARCH_PNX4008_PM_H */

View File

@@ -0,0 +1,38 @@
/*
* arch/arm/mach-pnx4008/include/mach/system.h
*
* Copyright (C) 2003 Philips Semiconductors
* Copyright (C) 2005 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
static void arch_idle(void)
{
cpu_do_idle();
}
static inline void arch_reset(char mode, const char *cmd)
{
cpu_reset(0);
}
#endif

View File

@@ -0,0 +1,73 @@
/*
* arch/arm/mach-pnx4008/include/mach/timex.h
*
* PNX4008 timers header file
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __PNX4008_TIMEX_H
#define __PNX4008_TIMEX_H
#include <linux/io.h>
#include <mach/hardware.h>
#define CLOCK_TICK_RATE 1000000
#define TICKS2USECS(x) (x)
/* MilliSecond Timer - Chapter 21 Page 202 */
#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
/* High Speed Timer - Chpater 22, Page 205 */
#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
/* IMPORTANT: both timers are UPCOUNTING */
/* xSTIM_MCTRL bit definitions */
#define MR0_INT 1
#define RESET_COUNT0 (1<<1)
#define STOP_COUNT0 (1<<2)
#define MR1_INT (1<<3)
#define RESET_COUNT1 (1<<4)
#define STOP_COUNT1 (1<<5)
#define MR2_INT (1<<6)
#define RESET_COUNT2 (1<<7)
#define STOP_COUNT2 (1<<8)
/* xSTIM_CTRL bit definitions */
#define COUNT_ENAB 1
#define RESET_COUNT (1<<1)
#define DEBUG_EN (1<<2)
/* xSTIM_INT bit definitions */
#define MATCH0_INT 1
#define MATCH1_INT (1<<1)
#define MATCH2_INT (1<<2)
#define RTC_TICK0 (1<<4)
#define RTC_TICK1 (1<<5)
#endif

View File

@@ -0,0 +1,46 @@
/*
* arch/arm/mach-pnx4008/include/mach/uncompress.h
*
* Copyright (C) 1999 ARM Limited
* Copyright (C) 2006 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define UART5_BASE 0x40090000
#define UART5_DR (*(volatile unsigned char *) (UART5_BASE))
#define UART5_FR (*(volatile unsigned char *) (UART5_BASE + 18))
static __inline__ void putc(char c)
{
while (UART5_FR & (1 << 5))
barrier();
UART5_DR = c;
}
/*
* This does not append a newline
*/
static inline void flush(void)
{
}
/*
* nothing to do
*/
#define arch_decomp_setup()
#define arch_decomp_wdog()

View File

@@ -0,0 +1,20 @@
/*
* arch/arm/mach-pnx4008/include/mach/vmalloc.h
*
* Author: Vitaly Wool <source@mvista.com>
*
* 2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
* physical memory until the kernel virtual memory starts. That means that
* any out-of-bounds memory accesses will hopefully be caught.
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;)
*/
#define VMALLOC_END (PAGE_OFFSET + 0x10000000)

View File

@@ -0,0 +1,118 @@
/*
* arch/arm/mach-pnx4008/irq.c
*
* PNX4008 IRQ controller driver
*
* Author: Dmitry Chigirev <source@mvista.com>
*
* Based on reference code received from Philips:
* Copyright (C) 2003 Philips Semiconductors
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <mach/irq.h>
static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
static void pnx4008_mask_irq(unsigned int irq)
{
__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
}
static void pnx4008_unmask_irq(unsigned int irq)
{
__raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq)); /* unmask interrupt */
}
static void pnx4008_mask_ack_irq(unsigned int irq)
{
__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
__raw_writel(INTC_BIT(irq), INTC_SR(irq)); /* clear interrupt status */
}
static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
{
switch (type) {
case IRQ_TYPE_EDGE_RISING:
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */
set_irq_handler(irq, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_FALLING:
__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */
set_irq_handler(irq, handle_edge_irq);
break;
case IRQ_TYPE_LEVEL_LOW:
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */
set_irq_handler(irq, handle_level_irq);
break;
case IRQ_TYPE_LEVEL_HIGH:
__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */
__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */
set_irq_handler(irq, handle_level_irq);
break;
/* IRQ_TYPE_EDGE_BOTH is not supported */
default:
printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
return -1;
}
return 0;
}
static struct irq_chip pnx4008_irq_chip = {
.ack = pnx4008_mask_ack_irq,
.mask = pnx4008_mask_irq,
.unmask = pnx4008_unmask_irq,
.set_type = pnx4008_set_irq_type,
};
void __init pnx4008_init_irq(void)
{
unsigned int i;
/* configure IRQ's */
for (i = 0; i < NR_IRQS; i++) {
set_irq_flags(i, IRQF_VALID);
set_irq_chip(i, &pnx4008_irq_chip);
pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
}
/* configure and enable IRQ 0,1,30,31 (cascade interrupts) */
pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
/* mask all others */
__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
(1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
INTC_ER(MAIN_BASE_INT));
__raw_writel(0, INTC_ER(SIC1_BASE_INT));
__raw_writel(0, INTC_ER(SIC2_BASE_INT));
}

View File

@@ -0,0 +1,152 @@
/*
* arch/arm/mach-pnx4008/pm.c
*
* Power Management driver for PNX4008
*
* Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/pm.h>
#include <linux/rtc.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <mach/pm.h>
#include <mach/clock.h>
#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
static void *saved_sram;
static struct clk *pll4_clk;
static inline void pnx4008_standby(void)
{
void (*pnx4008_cpu_standby_ptr) (void);
local_irq_disable();
local_fiq_disable();
clk_disable(pll4_clk);
/*saving portion of SRAM to be used by suspend function. */
memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
/*make sure SRAM copy gets physically written into SDRAM.
SDRAM will be placed into self-refresh during power down */
flush_cache_all();
/*copy suspend function into SRAM */
memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
/*do suspend */
pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
pnx4008_cpu_standby_ptr();
/*restoring portion of SRAM that was used by suspend function */
memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
clk_enable(pll4_clk);
local_fiq_enable();
local_irq_enable();
}
static inline void pnx4008_suspend(void)
{
void (*pnx4008_cpu_suspend_ptr) (void);
local_irq_disable();
local_fiq_disable();
clk_disable(pll4_clk);
__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
/*saving portion of SRAM to be used by suspend function. */
memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
/*make sure SRAM copy gets physically written into SDRAM.
SDRAM will be placed into self-refresh during power down */
flush_cache_all();
/*copy suspend function into SRAM */
memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
/*do suspend */
pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
pnx4008_cpu_suspend_ptr();
/*restoring portion of SRAM that was used by suspend function */
memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
clk_enable(pll4_clk);
local_fiq_enable();
local_irq_enable();
}
static int pnx4008_pm_enter(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_STANDBY:
pnx4008_standby();
break;
case PM_SUSPEND_MEM:
pnx4008_suspend();
break;
}
return 0;
}
static int pnx4008_pm_valid(suspend_state_t state)
{
return (state == PM_SUSPEND_STANDBY) ||
(state == PM_SUSPEND_MEM);
}
static struct platform_suspend_ops pnx4008_pm_ops = {
.enter = pnx4008_pm_enter,
.valid = pnx4008_pm_valid,
};
static int __init pnx4008_pm_init(void)
{
u32 sram_size_to_allocate;
pll4_clk = clk_get(0, "ck_pll4");
if (IS_ERR(pll4_clk)) {
printk(KERN_ERR
"PM Suspend cannot acquire ARM(PLL4) clock control\n");
return PTR_ERR(pll4_clk);
}
if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
sram_size_to_allocate = pnx4008_cpu_standby_sz;
else
sram_size_to_allocate = pnx4008_cpu_suspend_sz;
saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
if (!saved_sram) {
printk(KERN_ERR
"PM Suspend: cannot allocate memory to save portion of SRAM\n");
clk_put(pll4_clk);
return -ENOMEM;
}
suspend_set_ops(&pnx4008_pm_ops);
return 0;
}
late_initcall(pnx4008_pm_init);

View File

@@ -0,0 +1,68 @@
/*
* linux/arch/arm/mach-pnx4008/serial.c
*
* PNX4008 UART initialization
*
* Copyright: MontaVista Software Inc. (c) 2005
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/io.h>
#include <mach/platform.h>
#include <mach/hardware.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <mach/gpio.h>
#include <mach/clock.h>
#define UART_3 0
#define UART_4 1
#define UART_5 2
#define UART_6 3
#define UART_UNKNOWN (-1)
#define UART3_BASE_VA IO_ADDRESS(PNX4008_UART3_BASE)
#define UART4_BASE_VA IO_ADDRESS(PNX4008_UART4_BASE)
#define UART5_BASE_VA IO_ADDRESS(PNX4008_UART5_BASE)
#define UART6_BASE_VA IO_ADDRESS(PNX4008_UART6_BASE)
#define UART_FCR_OFFSET 8
#define UART_FIFO_SIZE 64
void pnx4008_uart_init(void)
{
u32 tmp;
int i = UART_FIFO_SIZE;
__raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
__raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
/* Send a NULL to fix the UART HW bug */
__raw_writel(0x00, UART5_BASE_VA);
__raw_writel(0x00, UART3_BASE_VA);
while (i--) {
tmp = __raw_readl(UART5_BASE_VA);
tmp = __raw_readl(UART3_BASE_VA);
}
__raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
__raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
/* setup wakeup interrupt */
start_int_set_rising_edge(SE_U3_RX_INT);
start_int_ack(SE_U3_RX_INT);
start_int_umask(SE_U3_RX_INT);
start_int_set_rising_edge(SE_U5_RX_INT);
start_int_ack(SE_U5_RX_INT);
start_int_umask(SE_U5_RX_INT);
}

View File

@@ -0,0 +1,195 @@
/*
* linux/arch/arm/mach-pnx4008/sleep.S
*
* PNX4008 support for STOP mode and SDRAM self-refresh
*
* Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/hardware.h>
#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
#define PWR_CTRL_REG_OFFS 0x44
#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
#define MPMC_STATUS_REG_OFFS 0x4
.text
ENTRY(pnx4008_cpu_suspend)
@this function should be entered in Direct run mode.
@ save registers on stack
stmfd sp!, {r0 - r6, lr}
@ setup Power Manager base address in r4
@ and put it's value in r5
mov r4, #(PWRMAN_VA_BASE & 0xff000000)
orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
ldr r5, [r4, #PWR_CTRL_REG_OFFS]
@ setup SDRAM controller base address in r2
@ and put it's value in r3
mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
@ clear SDRAM self-refresh bit latch
and r5, r5, #(~(1 << 8))
@ clear SDRAM self-refresh bit
and r5, r5, #(~(1 << 9))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ do save current bit settings in r1
mov r1, r5
@ set SDRAM self-refresh bit
orr r5, r5, #(1 << 9)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ set SDRAM self-refresh bit latch
orr r5, r5, #(1 << 8)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ clear SDRAM self-refresh bit latch
and r5, r5, #(~(1 << 8))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ clear SDRAM self-refresh bit
and r5, r5, #(~(1 << 9))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ wait for SDRAM to get into self-refresh mode
2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS]
tst r3, #(1 << 2)
beq 2b
@ to prepare SDRAM to get out of self-refresh mode after wakeup
orr r5, r5, #(1 << 7)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ do enter stop mode
orr r5, r5, #(1 << 0)
str r5, [r4, #PWR_CTRL_REG_OFFS]
nop
nop
nop
nop
nop
nop
nop
nop
nop
@ sleeping now...
@ coming out of STOP mode into Direct Run mode
@ clear STOP mode and SDRAM self-refresh bits
str r1, [r4, #PWR_CTRL_REG_OFFS]
@ wait for SDRAM to get out self-refresh mode
3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS]
tst r3, #5
bne 3b
@ restore regs and return
ldmfd sp!, {r0 - r6, pc}
ENTRY(pnx4008_cpu_suspend_sz)
.word . - pnx4008_cpu_suspend
ENTRY(pnx4008_cpu_standby)
@ save registers on stack
stmfd sp!, {r0 - r6, lr}
@ setup Power Manager base address in r4
@ and put it's value in r5
mov r4, #(PWRMAN_VA_BASE & 0xff000000)
orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
ldr r5, [r4, #PWR_CTRL_REG_OFFS]
@ setup SDRAM controller base address in r2
@ and put it's value in r3
mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
@ clear SDRAM self-refresh bit latch
and r5, r5, #(~(1 << 8))
@ clear SDRAM self-refresh bit
and r5, r5, #(~(1 << 9))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ do save current bit settings in r1
mov r1, r5
@ set SDRAM self-refresh bit
orr r5, r5, #(1 << 9)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ set SDRAM self-refresh bit latch
orr r5, r5, #(1 << 8)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ clear SDRAM self-refresh bit latch
and r5, r5, #(~(1 << 8))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ clear SDRAM self-refresh bit
and r5, r5, #(~(1 << 9))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ wait for SDRAM to get into self-refresh mode
2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS]
tst r3, #(1 << 2)
beq 2b
@ set 'get out of self-refresh mode after wakeup' bit
orr r5, r5, #(1 << 7)
str r5, [r4, #PWR_CTRL_REG_OFFS]
mcr p15, 0, r0, c7, c0, 4 @ kinda sleeping now...
@ set SDRAM self-refresh bit latch
orr r5, r5, #(1 << 8)
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ clear SDRAM self-refresh bit latch
and r5, r5, #(~(1 << 8))
str r5, [r4, #PWR_CTRL_REG_OFFS]
@ wait for SDRAM to get out self-refresh mode
3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS]
tst r3, #5
bne 3b
@ restore regs and return
ldmfd sp!, {r0 - r6, pc}
ENTRY(pnx4008_cpu_standby_sz)
.word . - pnx4008_cpu_standby
ENTRY(pnx4008_cache_clean_invalidate)
stmfd sp!, {r0 - r6, lr}
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
#else
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
bne 1b
#endif
ldmfd sp!, {r0 - r6, pc}

View File

@@ -0,0 +1,133 @@
/*
* arch/arm/mach-pnx4008/time.c
*
* PNX4008 Timers
*
* Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/system.h>
#include <mach/hardware.h>
#include <asm/leds.h>
#include <asm/mach/time.h>
#include <asm/errno.h>
/*! Note: all timers are UPCOUNTING */
/*!
* Returns number of us since last clock interrupt. Note that interrupts
* will have been disabled by do_gettimeoffset()
*/
static unsigned long pnx4008_gettimeoffset(void)
{
u32 ticks_to_match =
__raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
u32 elapsed = LATCH - ticks_to_match;
return (elapsed * (tick_nsec / 1000)) / LATCH;
}
/*!
* IRQ handler for the timer
*/
static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id)
{
if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
do {
timer_tick();
/*
* this algorithm takes care of possible delay
* for this interrupt handling longer than a normal
* timer period
*/
__raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
HSTIM_MATCH0);
__raw_writel(MATCH0_INT, HSTIM_INT); /* clear interrupt */
/*
* The goal is to keep incrementing HSTIM_MATCH0
* register until HSTIM_MATCH0 indicates time after
* what HSTIM_COUNTER indicates.
*/
} while ((signed)
(__raw_readl(HSTIM_MATCH0) -
__raw_readl(HSTIM_COUNTER)) < 0);
}
return IRQ_HANDLED;
}
static struct irqaction pnx4008_timer_irq = {
.name = "PNX4008 Tick Timer",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = pnx4008_timer_interrupt
};
/*!
* Set up timer and timer interrupt.
*/
static __init void pnx4008_setup_timer(void)
{
__raw_writel(RESET_COUNT, MSTIM_CTRL);
while (__raw_readl(MSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */
__raw_writel(0, MSTIM_CTRL); /* stop the timer */
__raw_writel(0, MSTIM_MCTRL);
__raw_writel(RESET_COUNT, HSTIM_CTRL);
while (__raw_readl(HSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */
__raw_writel(0, HSTIM_CTRL);
__raw_writel(0, HSTIM_MCTRL);
__raw_writel(0, HSTIM_CCR);
__raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */
__raw_writel(LATCH, HSTIM_MATCH0);
__raw_writel(MR0_INT, HSTIM_MCTRL);
setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
__raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL); /*start timer, stop when JTAG active */
}
/* Timer Clock Control in PM register */
#define TIMCLK_CTRL_REG IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
#define WATCHDOG_CLK_EN 1
#define TIMER_CLK_EN 2 /* HS and MS timers? */
static u32 timclk_ctrl_reg_save;
void pnx4008_timer_suspend(void)
{
timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
__raw_writel(0, TIMCLK_CTRL_REG); /* disable timers */
}
void pnx4008_timer_resume(void)
{
__raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG); /* enable timers */
}
struct sys_timer pnx4008_timer = {
.init = pnx4008_setup_timer,
.offset = pnx4008_gettimeoffset,
.suspend = pnx4008_timer_suspend,
.resume = pnx4008_timer_resume,
};