提交 70103814 编写于 作者: R Russell King 提交者: Russell King

Merge branch 'nomadik' into devel-stable

......@@ -338,6 +338,20 @@ config ARCH_H720X
help
This enables support for systems based on the Hynix HMS720x
config ARCH_NOMADIK
bool "STMicroelectronics Nomadik"
select ARM_AMBA
select ARM_VIC
select CPU_ARM926T
select HAVE_CLK
select COMMON_CLKDEV
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
Support for the Nomadik platform by ST-Ericsson
config ARCH_IOP13XX
bool "IOP13xx-based"
depends on MMU
......@@ -745,6 +759,8 @@ source "arch/arm/mach-at91/Kconfig"
source "arch/arm/plat-mxc/Kconfig"
source "arch/arm/mach-nomadik/Kconfig"
source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-ns9xxx/Kconfig"
......
......@@ -145,6 +145,7 @@ machine-$(CONFIG_ARCH_MX2) := mx2
machine-$(CONFIG_ARCH_MX25) := mx25
machine-$(CONFIG_ARCH_MX3) := mx3
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_NOMADIK) := nomadik
machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
machine-$(CONFIG_ARCH_OMAP1) := omap1
machine-$(CONFIG_ARCH_OMAP2) := omap2
......
......@@ -26,6 +26,15 @@
#include <asm/mach/irq.h>
#include <asm/hardware/vic.h>
static void vic_ack_irq(unsigned int irq)
{
void __iomem *base = get_irq_chip_data(irq);
irq &= 31;
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
/* moreover, clear the soft-triggered, in case it was the reason */
writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
}
static void vic_mask_irq(unsigned int irq)
{
void __iomem *base = get_irq_chip_data(irq);
......@@ -253,12 +262,21 @@ static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg
static struct irq_chip vic_chip = {
.name = "VIC",
.ack = vic_mask_irq,
.ack = vic_ack_irq,
.mask = vic_mask_irq,
.unmask = vic_unmask_irq,
.set_wake = vic_set_wake,
};
/* The PL190 cell from ARM has been modified by ST, so handle both here */
static void vik_init_st(void __iomem *base, unsigned int irq_start,
u32 vic_sources);
enum vic_vendor {
VENDOR_ARM = 0x41,
VENDOR_ST = 0x80,
};
/**
* vic_init - initialise a vectored interrupt controller
* @base: iomem base address
......@@ -270,6 +288,28 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
u32 vic_sources, u32 resume_sources)
{
unsigned int i;
u32 cellid = 0;
enum vic_vendor vendor;
/* Identify which VIC cell this one is, by reading the ID */
for (i = 0; i < 4; i++) {
u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
cellid |= (readl(addr) & 0xff) << (8 * i);
}
vendor = (cellid >> 12) & 0xff;
printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n",
base, cellid, vendor);
switch(vendor) {
case VENDOR_ST:
vik_init_st(base, irq_start, vic_sources);
return;
default:
printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
/* fall through */
case VENDOR_ARM:
break;
}
/* Disable all interrupts initially. */
......@@ -306,3 +346,60 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
vic_pm_register(base, irq_start, resume_sources);
}
/*
* The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
* The original cell has 32 interrupts, while the modified one has 64,
* replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case
* the probe function is called twice, with base set to offset 000
* and 020 within the page. We call this "second block".
*/
static void __init vik_init_st(void __iomem *base, unsigned int irq_start,
u32 vic_sources)
{
unsigned int i;
int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
/* Disable all interrupts initially. */
writel(0, base + VIC_INT_SELECT);
writel(0, base + VIC_INT_ENABLE);
writel(~0, base + VIC_INT_ENABLE_CLEAR);
writel(0, base + VIC_IRQ_STATUS);
writel(0, base + VIC_ITCR);
writel(~0, base + VIC_INT_SOFT_CLEAR);
/*
* Make sure we clear all existing interrupts. The vector registers
* in this cell are after the second block of general registers,
* so we can address them using standard offsets, but only from
* the second base address, which is 0x20 in the page
*/
if (vic_2nd_block) {
writel(0, base + VIC_PL190_VECT_ADDR);
for (i = 0; i < 19; i++) {
unsigned int value;
value = readl(base + VIC_PL190_VECT_ADDR);
writel(value, base + VIC_PL190_VECT_ADDR);
}
/* ST has 16 vectors as well, but we don't enable them by now */
for (i = 0; i < 16; i++) {
void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
writel(0, reg);
}
writel(32, base + VIC_PL190_DEF_VECT_ADDR);
}
for (i = 0; i < 32; i++) {
if (vic_sources & (1 << i)) {
unsigned int irq = irq_start + i;
set_irq_chip(irq, &vic_chip);
set_irq_chip_data(irq, base);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
}
此差异已折叠。
if ARCH_NOMADIK
menu "Nomadik boards"
config MACH_NOMADIK_8815NHK
bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
select NOMADIK_8815
endmenu
config NOMADIK_8815
bool
config I2C_BITBANG_8815NHK
tristate "Driver for bit-bang busses found on the 8815 NHK"
depends on I2C && MACH_NOMADIK_8815NHK
select I2C_ALGOBIT
default y
endif
#
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
# Object file lists.
obj-y += clock.o timer.o gpio.o
# Cpu revision
obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o
# Specific board support
obj-$(CONFIG_MACH_NOMADIK_8815NHK) += board-nhk8815.o
# Nomadik extra devices
obj-$(CONFIG_I2C_BITBANG_8815NHK) += i2c-8815nhk.o
zreladdr-y := 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
/*
* linux/arch/arm/mach-nomadik/board-8815nhk.c
*
* Copyright (C) STMicroelectronics
*
* 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.
*
* NHK15 board specifc driver definition
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <mach/setup.h>
#include "clock.h"
#define __MEM_4K_RESOURCE(x) \
.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
static struct amba_device uart0_device = {
.dev = { .init_name = "uart0" },
__MEM_4K_RESOURCE(NOMADIK_UART0_BASE),
.irq = {IRQ_UART0, NO_IRQ},
};
static struct amba_device uart1_device = {
.dev = { .init_name = "uart1" },
__MEM_4K_RESOURCE(NOMADIK_UART1_BASE),
.irq = {IRQ_UART1, NO_IRQ},
};
static struct amba_device *amba_devs[] __initdata = {
&uart0_device,
&uart1_device,
};
/* We have a fixed clock alone, by now */
static struct clk nhk8815_clk_48 = {
.rate = 48*1000*1000,
};
static struct resource nhk8815_eth_resources[] = {
{
.name = "smc91x-regs",
.start = 0x34000000 + 0x300,
.end = 0x34000000 + SZ_64K - 1,
.flags = IORESOURCE_MEM,
}, {
.start = NOMADIK_GPIO_TO_IRQ(115),
.end = NOMADIK_GPIO_TO_IRQ(115),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
}
};
static struct platform_device nhk8815_eth_device = {
.name = "smc91x",
.resource = nhk8815_eth_resources,
.num_resources = ARRAY_SIZE(nhk8815_eth_resources),
};
static int __init nhk8815_eth_init(void)
{
int gpio_nr = 115; /* hardwired in the board */
int err;
err = gpio_request(gpio_nr, "eth_irq");
if (!err) err = nmk_gpio_set_mode(gpio_nr, NMK_GPIO_ALT_GPIO);
if (!err) err = gpio_direction_input(gpio_nr);
if (err)
pr_err("Error %i in %s\n", err, __func__);
return err;
}
device_initcall(nhk8815_eth_init);
static struct platform_device *nhk8815_platform_devices[] __initdata = {
&nhk8815_eth_device,
/* will add more devices */
};
static void __init nhk8815_platform_init(void)
{
int i;
cpu8815_platform_init();
platform_add_devices(nhk8815_platform_devices,
ARRAY_SIZE(nhk8815_platform_devices));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
nmdk_clk_create(&nhk8815_clk_48, amba_devs[i]->dev.init_name);
amba_device_register(amba_devs[i], &iomem_resource);
}
}
MACHINE_START(NOMADIK, "NHK8815")
/* Maintainer: ST MicroElectronics */
.phys_io = NOMADIK_UART0_BASE,
.io_pg_offst = (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc,
.boot_params = 0x100,
.map_io = cpu8815_map_io,
.init_irq = cpu8815_init_irq,
.timer = &nomadik_timer,
.init_machine = nhk8815_platform_init,
MACHINE_END
/*
* linux/arch/arm/mach-nomadik/clock.c
*
* Copyright (C) 2009 Alessandro Rubini
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <asm/clkdev.h>
#include "clock.h"
/*
* The nomadik board uses generic clocks, but the serial pl011 file
* calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them
*/
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
/* enable and disable do nothing */
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);
/* Create a clock structure with the given name */
int nmdk_clk_create(struct clk *clk, const char *dev_id)
{
struct clk_lookup *clkdev;
clkdev = clkdev_alloc(clk, NULL, dev_id);
if (!clkdev)
return -ENOMEM;
clkdev_add(clkdev);
return 0;
}
/*
* linux/arch/arm/mach-nomadik/clock.h
*
* Copyright (C) 2009 Alessandro Rubini
*
* 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.
*/
struct clk {
unsigned long rate;
};
extern int nmdk_clk_create(struct clk *clk, const char *dev_id);
/*
* Copyright STMicroelectronics, 2007.
*
* 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
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/mach/map.h>
#include <asm/hardware/vic.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
/* The 8815 has 4 GPIO blocks, let's register them immediately */
static struct nmk_gpio_platform_data cpu8815_gpio[] = {
{
.name = "GPIO-0-31",
.first_gpio = 0,
.first_irq = NOMADIK_GPIO_TO_IRQ(0),
.parent_irq = IRQ_GPIO0,
}, {
.name = "GPIO-32-63",
.first_gpio = 32,
.first_irq = NOMADIK_GPIO_TO_IRQ(32),
.parent_irq = IRQ_GPIO1,
}, {
.name = "GPIO-64-95",
.first_gpio = 64,
.first_irq = NOMADIK_GPIO_TO_IRQ(64),
.parent_irq = IRQ_GPIO2,
}, {
.name = "GPIO-96-127", /* 124..127 not routed to pin */
.first_gpio = 96,
.first_irq = NOMADIK_GPIO_TO_IRQ(96),
.parent_irq = IRQ_GPIO3,
}
};
#define __MEM_4K_RESOURCE(x) \
.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
static struct amba_device cpu8815_amba_gpio[] = {
{
.dev = {
.init_name = "gpio0",
.platform_data = cpu8815_gpio + 0,
},
__MEM_4K_RESOURCE(NOMADIK_GPIO0_BASE),
}, {
.dev = {
.init_name = "gpio1",
.platform_data = cpu8815_gpio + 1,
},
__MEM_4K_RESOURCE(NOMADIK_GPIO1_BASE),
}, {
.dev = {
.init_name = "gpio2",
.platform_data = cpu8815_gpio + 2,
},
__MEM_4K_RESOURCE(NOMADIK_GPIO2_BASE),
}, {
.dev = {
.init_name = "gpio3",
.platform_data = cpu8815_gpio + 3,
},
__MEM_4K_RESOURCE(NOMADIK_GPIO3_BASE),
},
};
static struct amba_device *amba_devs[] __initdata = {
cpu8815_amba_gpio + 0,
cpu8815_amba_gpio + 1,
cpu8815_amba_gpio + 2,
cpu8815_amba_gpio + 3,
};
static int __init cpu8815_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
return 0;
}
arch_initcall(cpu8815_init);
/* All SoC devices live in the same area (see hardware.h) */
static struct map_desc nomadik_io_desc[] __initdata = {
{
.virtual = NOMADIK_IO_VIRTUAL,
.pfn = __phys_to_pfn(NOMADIK_IO_PHYSICAL),
.length = NOMADIK_IO_SIZE,
.type = MT_DEVICE,
}
/* static ram and secured ram may be added later */
};
void __init cpu8815_map_io(void)
{
iotable_init(nomadik_io_desc, ARRAY_SIZE(nomadik_io_desc));
}
void __init cpu8815_init_irq(void)
{
/* This modified VIC cell has two register blocks, at 0 and 0x20 */
vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START + 0, ~0, 0);
vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0);
}
/*
* This function is called from the board init ("init_machine").
*/
void __init cpu8815_platform_init(void)
{
#ifdef CONFIG_CACHE_L2X0
/* At full speed latency must be >=2, so 0x249 in low bits */
l2x0_init(io_p2v(NOMADIK_L2CC_BASE), 0x00730249, 0xfe000fff);
#endif
return;
}
/*
* Generic GPIO driver for logic cells found in the Nomadik SoC
*
* Copyright (C) 2008,2009 STMicroelectronics
* Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
* Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
*
* 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/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
/*
* The GPIO module in the Nomadik family of Systems-on-Chip is an
* AMBA device, managing 32 pins and alternate functions. The logic block
* is currently only used in the Nomadik.
*
* Symbols in this file are called "nmk_gpio" for "nomadik gpio"
*/
#define NMK_GPIO_PER_CHIP 32
struct nmk_gpio_chip {
struct gpio_chip chip;
void __iomem *addr;
unsigned int parent_irq;
spinlock_t *lock;
/* Keep track of configured edges */
u32 edge_rising;
u32 edge_falling;
};
/* Mode functions */
int nmk_gpio_set_mode(int gpio, int gpio_mode)
{
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 afunc, bfunc, bit;
nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
if (!nmk_chip)
return -EINVAL;
bit = 1 << (gpio - nmk_chip->chip.base);
spin_lock_irqsave(&nmk_chip->lock, flags);
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
if (gpio_mode & NMK_GPIO_ALT_A)
afunc |= bit;
if (gpio_mode & NMK_GPIO_ALT_B)
bfunc |= bit;
writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
return 0;
}
EXPORT_SYMBOL(nmk_gpio_set_mode);
int nmk_gpio_get_mode(int gpio)
{
struct nmk_gpio_chip *nmk_chip;
u32 afunc, bfunc, bit;
nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
if (!nmk_chip)
return -EINVAL;
bit = 1 << (gpio - nmk_chip->chip.base);
afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
}
EXPORT_SYMBOL(nmk_gpio_get_mode);
/* IRQ functions */
static inline int nmk_gpio_get_bitmask(int gpio)
{
return 1 << (gpio % 32);
}
static void nmk_gpio_irq_ack(unsigned int irq)
{
int gpio;
struct nmk_gpio_chip *nmk_chip;
gpio = NOMADIK_IRQ_TO_GPIO(irq);
nmk_chip = get_irq_chip_data(irq);
if (!nmk_chip)
return;
writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
}
static void nmk_gpio_irq_mask(unsigned int irq)
{
int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask, reg;
gpio = NOMADIK_IRQ_TO_GPIO(irq);
nmk_chip = get_irq_chip_data(irq);
bitmask = nmk_gpio_get_bitmask(gpio);
if (!nmk_chip)
return;
/* we must individually clear the two edges */
spin_lock_irqsave(&nmk_chip->lock, flags);
if (nmk_chip->edge_rising & bitmask) {
reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
reg &= ~bitmask;
writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC);
}
if (nmk_chip->edge_falling & bitmask) {
reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
reg &= ~bitmask;
writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC);
}
spin_unlock_irqrestore(&nmk_chip->lock, flags);
};
static void nmk_gpio_irq_unmask(unsigned int irq)
{
int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask, reg;
gpio = NOMADIK_IRQ_TO_GPIO(irq);
nmk_chip = get_irq_chip_data(irq);
bitmask = nmk_gpio_get_bitmask(gpio);
if (!nmk_chip)
return;
/* we must individually set the two edges */
spin_lock_irqsave(&nmk_chip->lock, flags);
if (nmk_chip->edge_rising & bitmask) {
reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
reg |= bitmask;
writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC);
}
if (nmk_chip->edge_falling & bitmask) {
reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
reg |= bitmask;
writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC);
}
spin_unlock_irqrestore(&nmk_chip->lock, flags);
}
static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type)
{
int gpio;
struct nmk_gpio_chip *nmk_chip;
unsigned long flags;
u32 bitmask;
gpio = NOMADIK_IRQ_TO_GPIO(irq);
nmk_chip = get_irq_chip_data(irq);
bitmask = nmk_gpio_get_bitmask(gpio);
if (!nmk_chip)
return -EINVAL;
if (type & IRQ_TYPE_LEVEL_HIGH)
return -EINVAL;
if (type & IRQ_TYPE_LEVEL_LOW)
return -EINVAL;
spin_lock_irqsave(&nmk_chip->lock, flags);
nmk_chip->edge_rising &= ~bitmask;
if (type & IRQ_TYPE_EDGE_RISING)
nmk_chip->edge_rising |= bitmask;
writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC);
nmk_chip->edge_falling &= ~bitmask;
if (type & IRQ_TYPE_EDGE_FALLING)
nmk_chip->edge_falling |= bitmask;
writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC);
spin_unlock_irqrestore(&nmk_chip->lock, flags);
nmk_gpio_irq_unmask(irq);
return 0;
}
static struct irq_chip nmk_gpio_irq_chip = {
.name = "Nomadik-GPIO",
.ack = nmk_gpio_irq_ack,
.mask = nmk_gpio_irq_mask,
.unmask = nmk_gpio_irq_unmask,
.set_type = nmk_gpio_irq_set_type,
};
static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct nmk_gpio_chip *nmk_chip;
struct irq_chip *host_chip;
unsigned int gpio_irq;
u32 pending;
unsigned int first_irq;
nmk_chip = get_irq_data(irq);
first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) {
gpio_irq = first_irq + __ffs(pending);
generic_handle_irq(gpio_irq);
}
if (0) {/* don't ack parent irq, as ack == disable */
host_chip = get_irq_chip(irq);
host_chip->ack(irq);
}
}
static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
{
unsigned int first_irq;
int i;
first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) {
set_irq_chip(i, &nmk_gpio_irq_chip);
set_irq_handler(i, handle_edge_irq);
set_irq_flags(i, IRQF_VALID);
set_irq_chip_data(i, nmk_chip);
}
set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
set_irq_data(nmk_chip->parent_irq, nmk_chip);
return 0;
}
/* I/O Functions */
static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
{
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
return 0;
}
static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
int val)
{
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
return 0;
}
static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
{
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
u32 bit = 1 << offset;
return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
}
static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
int val)
{
struct nmk_gpio_chip *nmk_chip =
container_of(chip, struct nmk_gpio_chip, chip);
u32 bit = 1 << offset;
if (val)
writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
else
writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
}
/* This structure is replicated for each GPIO block allocated at probe time */
static struct gpio_chip nmk_gpio_template = {
.direction_input = nmk_gpio_make_input,
.get = nmk_gpio_get_input,
.direction_output = nmk_gpio_make_output,
.set = nmk_gpio_set_output,
.ngpio = NMK_GPIO_PER_CHIP,
.can_sleep = 0,
};
static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id)
{
struct nmk_gpio_platform_data *pdata;
struct nmk_gpio_chip *nmk_chip;
struct gpio_chip *chip;
int ret;
pdata = dev->dev.platform_data;
ret = amba_request_regions(dev, pdata->name);
if (ret)
return ret;
nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
if (!nmk_chip) {
ret = -ENOMEM;
goto out_amba;
}
/*
* The virt address in nmk_chip->addr is in the nomadik register space,
* so we can simply convert the resource address, without remapping
*/
nmk_chip->addr = io_p2v(dev->res.start);
nmk_chip->chip = nmk_gpio_template;
nmk_chip->parent_irq = pdata->parent_irq;
chip = &nmk_chip->chip;
chip->base = pdata->first_gpio;
chip->label = pdata->name;
chip->dev = &dev->dev;
chip->owner = THIS_MODULE;
ret = gpiochip_add(&nmk_chip->chip);
if (ret)
goto out_free;
amba_set_drvdata(dev, nmk_chip);
nmk_gpio_init_irq(nmk_chip);
dev_info(&dev->dev, "Bits %i-%i at address %p\n",
nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr);
return 0;
out_free:
kfree(nmk_chip);
out_amba:
amba_release_regions(dev);
dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
pdata->first_gpio, pdata->first_gpio+31);
return ret;
}
static int nmk_gpio_remove(struct amba_device *dev)
{
struct nmk_gpio_chip *nmk_chip;
nmk_chip = amba_get_drvdata(dev);
gpiochip_remove(&nmk_chip->chip);
kfree(nmk_chip);
amba_release_regions(dev);
return 0;
}
/* We have 0x1f080060 and 0x1f180060, accept both using the mask */
static struct amba_id nmk_gpio_ids[] = {
{
.id = 0x1f080060,
.mask = 0xffefffff,
},
{0, 0},
};
static struct amba_driver nmk_gpio_driver = {
.drv = {
.owner = THIS_MODULE,
.name = "gpio",
},
.probe = nmk_gpio_probe,
.remove = nmk_gpio_remove,
.suspend = NULL, /* to be done */
.resume = NULL,
.id_table = nmk_gpio_ids,
};
static int __init nmk_gpio_init(void)
{
return amba_driver_register(&nmk_gpio_driver);
}
arch_initcall(nmk_gpio_init);
MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
MODULE_DESCRIPTION("Nomadik GPIO Driver");
MODULE_LICENSE("GPL");
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
/*
* There are two busses in the 8815NHK.
* They could, in theory, be driven by the hardware component, but we
* use bit-bang through GPIO by now, to keep things simple
*/
static struct i2c_gpio_platform_data nhk8815_i2c_data0 = {
/* keep defaults for timeouts; pins are push-pull bidirectional */
.scl_pin = 62,
.sda_pin = 63,
};
static struct i2c_gpio_platform_data nhk8815_i2c_data1 = {
/* keep defaults for timeouts; pins are push-pull bidirectional */
.scl_pin = 53,
.sda_pin = 54,
};
/* first bus: GPIO XX and YY */
static struct platform_device nhk8815_i2c_dev0 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &nhk8815_i2c_data0,
},
};
/* second bus: GPIO XX and YY */
static struct platform_device nhk8815_i2c_dev1 = {
.name = "i2c-gpio",
.id = 1,
.dev = {
.platform_data = &nhk8815_i2c_data1,
},
};
static int __init nhk8815_i2c_init(void)
{
nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO);
nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO);
platform_device_register(&nhk8815_i2c_dev0);
nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO);
nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO);
platform_device_register(&nhk8815_i2c_dev1);
return 0;
}
static void __exit nhk8815_i2c_exit(void)
{
platform_device_unregister(&nhk8815_i2c_dev0);
platform_device_unregister(&nhk8815_i2c_dev1);
return;
}
module_init(nhk8815_i2c_init);
module_exit(nhk8815_i2c_exit);
#ifndef __ASM_MACH_CLKDEV_H
#define __ASM_MACH_CLKDEV_H
#define __clk_get(clk) ({ 1; })
#define __clk_put(clk) do { } while (0)
#endif
/*
* 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?
moveq \rx, #0x10000000 @ physical base address
movne \rx, #0xf0000000 @ virtual base
add \rx, \rx, #0x00100000
add \rx, \rx, #0x000fb000
.endm
#include <asm/hardware/debug-pl01x.S>
/*
* Low-level IRQ helper macros for Nomadik platforms
*
* 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 <mach/hardware.h>
#include <mach/irqs.h>
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
ldr \base, =IO_ADDRESS(NOMADIK_IC_BASE)
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
/* This stanza gets the irq mask from one of two status registers */
mov \irqnr, #0
ldr \irqstat, [\base, #VIC_REG_IRQSR0] @ get masked status
cmp \irqstat, #0
bne 1001f
add \irqnr, \irqnr, #32
ldr \irqstat, [\base, #VIC_REG_IRQSR1] @ get masked status
1001: tst \irqstat, #15
bne 1002f
add \irqnr, \irqnr, #4
movs \irqstat, \irqstat, lsr #4
bne 1001b
1002: tst \irqstat, #1
bne 1003f
add \irqnr, \irqnr, #1
movs \irqstat, \irqstat, lsr #1
bne 1002b
1003: /* EQ will be set if no irqs pending */
.endm
/*
* Structures and registers for GPIO access in the Nomadik SoC
*
* Copyright (C) 2008 STMicroelectronics
* Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
* Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
*
* 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_GPIO_H
#define __ASM_ARCH_GPIO_H
#include <asm-generic/gpio.h>
/*
* These currently cause a function call to happen, they may be optimized
* if needed by adding cpu-specific defines to identify blocks
* (see mach-pxa/include/mach/gpio.h as an example using GPLR etc)
*/
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
/*
* "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
* the "gpio" namespace for generic and cross-machine functions
*/
/* Register in the logic block */
#define NMK_GPIO_DAT 0x00
#define NMK_GPIO_DATS 0x04
#define NMK_GPIO_DATC 0x08
#define NMK_GPIO_PDIS 0x0c
#define NMK_GPIO_DIR 0x10
#define NMK_GPIO_DIRS 0x14
#define NMK_GPIO_DIRC 0x18
#define NMK_GPIO_SLPC 0x1c
#define NMK_GPIO_AFSLA 0x20
#define NMK_GPIO_AFSLB 0x24
#define NMK_GPIO_RIMSC 0x40
#define NMK_GPIO_FIMSC 0x44
#define NMK_GPIO_IS 0x48
#define NMK_GPIO_IC 0x4c
#define NMK_GPIO_RWIMSC 0x50
#define NMK_GPIO_FWIMSC 0x54
#define NMK_GPIO_WKS 0x58
/* Alternate functions: function C is set in hw by setting both A and B */
#define NMK_GPIO_ALT_GPIO 0
#define NMK_GPIO_ALT_A 1
#define NMK_GPIO_ALT_B 2
#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
extern int nmk_gpio_get_mode(int gpio);
/*
* Platform data to register a block: only the initial gpio/irq number.
*/
struct nmk_gpio_platform_data {
char *name;
int first_gpio;
int first_irq;
int parent_irq;
};
#endif /* __ASM_ARCH_GPIO_H */
/*
* This file contains the hardware definitions of the Nomadik.
*
* 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
/* Nomadik registers live from 0x1000.0000 to 0x1023.0000 -- currently */
#define NOMADIK_IO_VIRTUAL 0xF0000000 /* VA of IO */
#define NOMADIK_IO_PHYSICAL 0x10000000 /* PA of IO */
#define NOMADIK_IO_SIZE 0x00300000 /* 3MB for all regs */
/* used in C code, so cast to proper type */
#define io_p2v(x) ((void __iomem *)(x) \
- NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL)
#define io_v2p(x) ((unsigned long)(x) \
- NOMADIK_IO_VIRTUAL + NOMADIK_IO_PHYSICAL)
/* used in asm code, so no casts */
#define IO_ADDRESS(x) ((x) - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL)
/*
* Base address defination for Nomadik Onchip Logic Block
*/
#define NOMADIK_FSMC_BASE 0x10100000 /* FSMC registers */
#define NOMADIK_SDRAMC_BASE 0x10110000 /* SDRAM Controller */
#define NOMADIK_CLCDC_BASE 0x10120000 /* CLCD Controller */
#define NOMADIK_MDIF_BASE 0x10120000 /* MDIF */
#define NOMADIK_DMA0_BASE 0x10130000 /* DMA0 Controller */
#define NOMADIK_IC_BASE 0x10140000 /* Vectored Irq Controller */
#define NOMADIK_DMA1_BASE 0x10150000 /* DMA1 Controller */
#define NOMADIK_USB_BASE 0x10170000 /* USB-OTG conf reg base */
#define NOMADIK_CRYP_BASE 0x10180000 /* Crypto processor */
#define NOMADIK_SHA1_BASE 0x10190000 /* SHA-1 Processor */
#define NOMADIK_XTI_BASE 0x101A0000 /* XTI */
#define NOMADIK_RNG_BASE 0x101B0000 /* Random number generator */
#define NOMADIK_SRC_BASE 0x101E0000 /* SRC base */
#define NOMADIK_WDOG_BASE 0x101E1000 /* Watchdog */
#define NOMADIK_MTU0_BASE 0x101E2000 /* Multiple Timer 0 */
#define NOMADIK_MTU1_BASE 0x101E3000 /* Multiple Timer 1 */
#define NOMADIK_GPIO0_BASE 0x101E4000 /* GPIO0 */
#define NOMADIK_GPIO1_BASE 0x101E5000 /* GPIO1 */
#define NOMADIK_GPIO2_BASE 0x101E6000 /* GPIO2 */
#define NOMADIK_GPIO3_BASE 0x101E7000 /* GPIO3 */
#define NOMADIK_RTC_BASE 0x101E8000 /* Real Time Clock base */
#define NOMADIK_PMU_BASE 0x101E9000 /* Power Management Unit */
#define NOMADIK_OWM_BASE 0x101EA000 /* One wire master */
#define NOMADIK_SCR_BASE 0x101EF000 /* Secure Control registers */
#define NOMADIK_MSP2_BASE 0x101F0000 /* MSP 2 interface */
#define NOMADIK_MSP1_BASE 0x101F1000 /* MSP 1 interface */
#define NOMADIK_UART2_BASE 0x101F2000 /* UART 2 interface */
#define NOMADIK_SSIRx_BASE 0x101F3000 /* SSI 8-ch rx interface */
#define NOMADIK_SSITx_BASE 0x101F4000 /* SSI 8-ch tx interface */
#define NOMADIK_MSHC_BASE 0x101F5000 /* Memory Stick(Pro) Host */
#define NOMADIK_SDI_BASE 0x101F6000 /* SD-card/MM-Card */
#define NOMADIK_I2C1_BASE 0x101F7000 /* I2C1 interface */
#define NOMADIK_I2C0_BASE 0x101F8000 /* I2C0 interface */
#define NOMADIK_MSP0_BASE 0x101F9000 /* MSP 0 interface */
#define NOMADIK_FIRDA_BASE 0x101FA000 /* FIrDA interface */
#define NOMADIK_UART1_BASE 0x101FB000 /* UART 1 interface */
#define NOMADIK_SSP_BASE 0x101FC000 /* SSP interface */
#define NOMADIK_UART0_BASE 0x101FD000 /* UART 0 interface */
#define NOMADIK_SGA_BASE 0x101FE000 /* SGA interface */
#define NOMADIK_L2CC_BASE 0x10210000 /* L2 Cache controller */
/* Other ranges, not for p2v/v2p */
#define NOMADIK_BACKUP_RAM 0x80010000
#define NOMADIK_EBROM 0x80000000 /* Embedded boot ROM */
#define NOMADIK_HAMACV_DMEM_BASE 0xA0100000 /* HAMACV Data Memory Start */
#define NOMADIK_HAMACV_DMEM_END 0xA01FFFFF /* HAMACV Data Memory End */
#define NOMADIK_HAMACA_DMEM 0xA0200000 /* HAMACA Data Memory Space */
#define NOMADIK_FSMC_VA IO_ADDRESS(NOMADIK_FSMC_BASE)
#define NOMADIK_MTU0_VA IO_ADDRESS(NOMADIK_MTU0_BASE)
#define NOMADIK_MTU1_VA IO_ADDRESS(NOMADIK_MTU1_BASE)
#endif /* __ASM_ARCH_HARDWARE_H */
/*
* arch/arm/mach-nomadik/include/mach/io.h (copied from mach-sa1100)
*
* Copyright (C) 1997-1999 Russell King
*
* Modifications:
* 06-12-1997 RMK Created.
* 07-04-1999 RMK Major cleanup
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
/*
* We don't actually have real ISA nor PCI buses, but there is so many
* drivers out there that might just work if we fake them...
*/
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
#endif
/*
* mach-nomadik/include/mach/irqs.h
*
* Copyright (C) ST Microelectronics
*
* 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_IRQS_H
#define __ASM_ARCH_IRQS_H
#include <mach/hardware.h>
#define IRQ_VIC_START 0 /* first VIC interrupt is 0 */
/*
* Interrupt numbers generic for all Nomadik Chip cuts
*/
#define IRQ_WATCHDOG 0
#define IRQ_SOFTINT 1
#define IRQ_CRYPTO 2
#define IRQ_OWM 3
#define IRQ_MTU0 4
#define IRQ_MTU1 5
#define IRQ_GPIO0 6
#define IRQ_GPIO1 7
#define IRQ_GPIO2 8
#define IRQ_GPIO3 9
#define IRQ_RTC_RTT 10
#define IRQ_SSP 11
#define IRQ_UART0 12
#define IRQ_DMA1 13
#define IRQ_CLCD_MDIF 14
#define IRQ_DMA0 15
#define IRQ_PWRFAIL 16
#define IRQ_UART1 17
#define IRQ_FIRDA 18
#define IRQ_MSP0 19
#define IRQ_I2C0 20
#define IRQ_I2C1 21
#define IRQ_SDMMC 22
#define IRQ_USBOTG 23
#define IRQ_SVA_IT0 24
#define IRQ_SVA_IT1 25
#define IRQ_SAA_IT0 26
#define IRQ_SAA_IT1 27
#define IRQ_UART2 28
#define IRQ_MSP2 31
#define IRQ_L2CC 48
#define IRQ_HPI 49
#define IRQ_SKE 50
#define IRQ_KP 51
#define IRQ_MEMST 54
#define IRQ_SGA_IT 58
#define IRQ_USBM 60
#define IRQ_MSP1 62
#define NOMADIK_SOC_NR_IRQS 64
/* After chip-specific IRQ numbers we have the GPIO ones */
#define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */
#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_SOC_NR_IRQS)
#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_SOC_NR_IRQS)
#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
/* Following two are used by entry_macro.S, to access our dual-vic */
#define VIC_REG_IRQSR0 0
#define VIC_REG_IRQSR1 0x20
#endif /* __ASM_ARCH_IRQS_H */
/*
* mach-nomadik/include/mach/memory.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
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
/*
* Physical DRAM offset.
*/
#define PHYS_OFFSET UL(0x00000000)
#endif
#ifndef __ASM_ARCH_MTU_H
#define __ASM_ARCH_MTU_H
/*
* The MTU device hosts four different counters, with 4 set of
* registers. These are register names.
*/
#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
#define MTU_RIS 0x04 /* Raw interrupt status */
#define MTU_MIS 0x08 /* Masked interrupt status */
#define MTU_ICR 0x0C /* Interrupt clear register */
/* per-timer registers take 0..3 as argument */
#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
/* bits for the control register */
#define MTU_CRn_ENA 0x80
#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
#define MTU_CRn_PRESCALE_MASK 0x0c
#define MTU_CRn_PRESCALE_1 0x00
#define MTU_CRn_PRESCALE_16 0x04
#define MTU_CRn_PRESCALE_256 0x08
#define MTU_CRn_32BITS 0x02
#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
/* Other registers are usual amba/primecell registers, currently not used */
#define MTU_ITCR 0xff0
#define MTU_ITOP 0xff4
#define MTU_PERIPH_ID0 0xfe0
#define MTU_PERIPH_ID1 0xfe4
#define MTU_PERIPH_ID2 0xfe8
#define MTU_PERIPH_ID3 0xfeC
#define MTU_PCELL0 0xff0
#define MTU_PCELL1 0xff4
#define MTU_PCELL2 0xff8
#define MTU_PCELL3 0xffC
#endif /* __ASM_ARCH_MTU_H */
/*
* These symbols are needed for board-specific files to call their
* own cpu-specific files
*/
#ifndef __ASM_ARCH_SETUP_H
#define __ASM_ARCH_SETUP_H
#include <asm/mach/time.h>
#include <linux/init.h>
#ifdef CONFIG_NOMADIK_8815
extern void cpu8815_map_io(void);
extern void cpu8815_platform_init(void);
extern void cpu8815_init_irq(void);
extern struct sys_timer nomadik_timer;
#endif /* NOMADIK_8815 */
#endif /* __ASM_ARCH_SETUP_H */
/*
* mach-nomadik/include/mach/system.h
*
* Copyright (C) 2008 STMicroelectronics
*
* 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>
static inline void arch_idle(void)
{
/*
* This should do all the clock switching
* and wait for interrupt tricks
*/
cpu_do_idle();
}
static inline void arch_reset(char mode, const char *cmd)
{
void __iomem *src_rstsr = io_p2v(NOMADIK_SRC_BASE + 0x18);
/* FIXME: use egpio when implemented */
/* Write anything to Reset status register */
writel(1, src_rstsr);
}
#endif
#ifndef __ASM_ARCH_TIMEX_H
#define __ASM_ARCH_TIMEX_H
#define CLOCK_TICK_RATE 2400000
#endif
/*
* Copyright (C) 2008 STMicroelectronics
*
* 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_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
#include <asm/setup.h>
#include <asm/io.h>
#include <mach/hardware.h>
/* we need the constants in amba/serial.h, but it refers to amba_device */
struct amba_device;
#include <linux/amba/serial.h>
#define NOMADIK_UART_DR 0x101FB000
#define NOMADIK_UART_LCRH 0x101FB02c
#define NOMADIK_UART_CR 0x101FB030
#define NOMADIK_UART_FR 0x101FB018
static void putc(const char c)
{
/* Do nothing if the UART is not enabled. */
if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN))
return;
if (c == '\n')
putc('\r');
while (readb(NOMADIK_UART_FR) & UART01x_FR_TXFF)
barrier();
writeb(c, NOMADIK_UART_DR);
}
static void flush(void)
{
if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN))
return;
while (readb(NOMADIK_UART_FR) & UART01x_FR_BUSY)
barrier();
}
static inline void arch_decomp_setup(void)
{
}
#define arch_decomp_wdog() /* nothing to do here */
#endif /* __ASM_ARCH_UNCOMPRESS_H */
/*
* linux/arch/arm/mach-nomadik/timer.c
*
* Copyright (C) 2008 STMicroelectronics
* Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x
*
* 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/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/clockchips.h>
#include <linux/jiffies.h>
#include <asm/mach/time.h>
#include <mach/mtu.h>
#define TIMER_CTRL 0x80 /* No divisor */
#define TIMER_PERIODIC 0x40
#define TIMER_SZ32BIT 0x02
/* Initial value for SRC control register: all timers use MXTAL/8 source */
#define SRC_CR_INIT_MASK 0x00007fff
#define SRC_CR_INIT_VAL 0x2aaa8000
static u32 nmdk_count; /* accumulated count */
static u32 nmdk_cycle; /* write-once */
static __iomem void *mtu_base;
/*
* clocksource: the MTU device is a decrementing counters, so we negate
* the value being read.
*/
static cycle_t nmdk_read_timer(struct clocksource *cs)
{
u32 count = readl(mtu_base + MTU_VAL(0));
return nmdk_count + nmdk_cycle - count;
}
static struct clocksource nmdk_clksrc = {
.name = "mtu_0",
.rating = 120,
.read = nmdk_read_timer,
.shift = 20,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/*
* Clockevent device: currently only periodic mode is supported
*/
static void nmdk_clkevt_mode(enum clock_event_mode mode,
struct clock_event_device *dev)
{
unsigned long flags;
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
/* enable interrupts -- and count current value? */
raw_local_irq_save(flags);
writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC);
raw_local_irq_restore(flags);
break;
case CLOCK_EVT_MODE_ONESHOT:
BUG(); /* Not supported, yet */
/* FALLTHROUGH */
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
/* disable irq */
raw_local_irq_save(flags);
writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC);
raw_local_irq_restore(flags);
break;
case CLOCK_EVT_MODE_RESUME:
break;
}
}
static struct clock_event_device nmdk_clkevt = {
.name = "mtu_0",
.features = CLOCK_EVT_FEAT_PERIODIC,
.shift = 32,
.rating = 100,
.set_mode = nmdk_clkevt_mode,
};
/*
* IRQ Handler for the timer 0 of the MTU block. The irq is not shared
* as we are the only users of mtu0 by now.
*/
static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
{
/* ack: "interrupt clear register" */
writel( 1 << 0, mtu_base + MTU_ICR);
/* we can't count lost ticks, unfortunately */
nmdk_count += nmdk_cycle;
nmdk_clkevt.event_handler(&nmdk_clkevt);
return IRQ_HANDLED;
}
/*
* Set up timer interrupt, and return the current time in seconds.
*/
static struct irqaction nmdk_timer_irq = {
.name = "Nomadik Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = nmdk_timer_interrupt,
};
static void nmdk_timer_reset(void)
{
u32 cr;
writel(0, mtu_base + MTU_CR(0)); /* off */
/* configure load and background-load, and fire it up */
writel(nmdk_cycle, mtu_base + MTU_LR(0));
writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
cr = MTU_CRn_PERIODIC | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS;
writel(cr, mtu_base + MTU_CR(0));
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
}
static void __init nmdk_timer_init(void)
{
u32 src_cr;
unsigned long rate;
int bits;
rate = CLOCK_TICK_RATE; /* 2.4MHz */
nmdk_cycle = (rate + HZ/2) / HZ;
/* Configure timer sources in "system reset controller" ctrl reg */
src_cr = readl(io_p2v(NOMADIK_SRC_BASE));
src_cr &= SRC_CR_INIT_MASK;
src_cr |= SRC_CR_INIT_VAL;
writel(src_cr, io_p2v(NOMADIK_SRC_BASE));
/* Save global pointer to mtu, used by functions above */
mtu_base = io_p2v(NOMADIK_MTU0_BASE);
/* Init the timer and register clocksource */
nmdk_timer_reset();
nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
bits = 8*sizeof(nmdk_count);
nmdk_clksrc.mask = CLOCKSOURCE_MASK(bits);
clocksource_register(&nmdk_clksrc);
/* Register irq and clockevents */
setup_irq(IRQ_MTU0, &nmdk_timer_irq);
nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift);
nmdk_clkevt.cpumask = cpumask_of(0);
clockevents_register_device(&nmdk_clkevt);
}
struct sys_timer nomadik_timer = {
.init = nmdk_timer_init,
};
......@@ -758,7 +758,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
config CACHE_L2X0
bool "Enable the L2x0 outer cache controller"
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX
REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK
default y
select OUTER_CACHE
help
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册