Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

10
arch/arm/mach-imx/Kconfig Normal file
View File

@@ -0,0 +1,10 @@
menu "IMX Implementations"
depends on ARCH_IMX
config ARCH_MX1ADS
bool "mx1ads"
depends on ARCH_IMX
help
Say Y here if you are using the Motorola MX1ADS board
endmenu

View File

@@ -0,0 +1,19 @@
#
# 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 += irq.o time.o dma.o generic.o
# Specific board support
obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
# Support for blinky lights
led-y := leds.o
obj-$(CONFIG_LEDS) += $(led-y)
led-$(CONFIG_ARCH_MX1ADS) += leds-mx1ads.o

View File

@@ -0,0 +1,2 @@
zreladdr-$(CONFIG_ARCH_MX1ADS) := 0x08008000

203
arch/arm/mach-imx/dma.c Normal file
View File

@@ -0,0 +1,203 @@
/*
* linux/arch/arm/mach-imx/dma.c
*
* imx DMA registration and IRQ dispatching
*
* 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.
*
* 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
* initial version heavily inspired by
* linux/arch/arm/mach-pxa/dma.c
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
static struct dma_channel {
char *name;
void (*irq_handler) (int, void *, struct pt_regs *);
void (*err_handler) (int, void *, struct pt_regs *);
void *data;
} dma_channels[11];
/* set err_handler to NULL to have the standard info-only error handler */
int
imx_request_dma(char *name, imx_dma_prio prio,
void (*irq_handler) (int, void *, struct pt_regs *),
void (*err_handler) (int, void *, struct pt_regs *), void *data)
{
unsigned long flags;
int i, found = 0;
/* basic sanity checks */
if (!name || !irq_handler)
return -EINVAL;
local_irq_save(flags);
/* try grabbing a DMA channel with the requested priority */
for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
if (!found) {
/* requested prio group is full, try hier priorities */
for (i = prio - 1; i >= 0; i--) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
}
if (found) {
DIMR &= ~(1 << i);
dma_channels[i].name = name;
dma_channels[i].irq_handler = irq_handler;
dma_channels[i].err_handler = err_handler;
dma_channels[i].data = data;
} else {
printk(KERN_WARNING "No more available DMA channels for %s\n",
name);
i = -ENODEV;
}
local_irq_restore(flags);
return i;
}
void
imx_free_dma(int dma_ch)
{
unsigned long flags;
if (!dma_channels[dma_ch].name) {
printk(KERN_CRIT
"%s: trying to free channel %d which is already freed\n",
__FUNCTION__, dma_ch);
return;
}
local_irq_save(flags);
DIMR &= ~(1 << dma_ch);
dma_channels[dma_ch].name = NULL;
local_irq_restore(flags);
}
static irqreturn_t
dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
struct dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
DISR = disr;
for (i = 0; i < 11; i++) {
channel = &dma_channels[i];
if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue;
}
if (DBTOSR & (1 << i)) {
printk(KERN_WARNING
"Burst timeout on channel %d (%s)\n",
i, channel->name);
DBTOSR |= (1 << i);
}
if (DRTOSR & (1 << i)) {
printk(KERN_WARNING
"Request timeout on channel %d (%s)\n",
i, channel->name);
DRTOSR |= (1 << i);
}
if (DSESR & (1 << i)) {
printk(KERN_WARNING
"Transfer timeout on channel %d (%s)\n",
i, channel->name);
DSESR |= (1 << i);
}
if (DBOSR & (1 << i)) {
printk(KERN_WARNING
"Buffer overflow timeout on channel %d (%s)\n",
i, channel->name);
DBOSR |= (1 << i);
}
}
return IRQ_HANDLED;
}
static irqreturn_t
dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
DISR = disr;
for (i = 0; i < 11; i++) {
if (disr & (1 << i)) {
struct dma_channel *channel = &dma_channels[i];
if (channel->name && channel->irq_handler) {
channel->irq_handler(i, channel->data, regs);
} else {
/*
* IRQ for an unregistered DMA channel:
* let's clear the interrupts and disable it.
*/
printk(KERN_WARNING
"spurious IRQ for DMA channel %d\n", i);
}
}
}
return IRQ_HANDLED;
}
static int __init
imx_dma_init(void)
{
int ret;
/* reset DMA module */
DCR = DCR_DRST;
ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
if (ret) {
printk(KERN_CRIT "Wow! Can't register IRQ for DMA\n");
return ret;
}
ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
if (ret) {
printk(KERN_CRIT "Wow! Can't register ERRIRQ for DMA\n");
free_irq(DMA_INT, NULL);
}
/* enable DMA module */
DCR = DCR_DEN;
/* clear all interrupts */
DISR = 0x3ff;
/* enable interrupts */
DIMR = 0;
return ret;
}
arch_initcall(imx_dma_init);
EXPORT_SYMBOL(imx_request_dma);
EXPORT_SYMBOL(imx_free_dma);

274
arch/arm/mach-imx/generic.c Normal file
View File

@@ -0,0 +1,274 @@
/*
* arch/arm/mach-imx/generic.c
*
* author: Sascha Hauer
* Created: april 20th, 2004
* Copyright: Synertronixx GmbH
*
* Common code for i.MX machines
*
* 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/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hardware.h>
#include <asm/mach/map.h>
void imx_gpio_mode(int gpio_mode)
{
unsigned int pin = gpio_mode & GPIO_PIN_MASK;
unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
unsigned int tmp;
/* Pullup enable */
if(gpio_mode & GPIO_PUEN)
PUEN(port) |= (1<<pin);
else
PUEN(port) &= ~(1<<pin);
/* Data direction */
if(gpio_mode & GPIO_OUT)
DDIR(port) |= 1<<pin;
else
DDIR(port) &= ~(1<<pin);
/* Primary / alternate function */
if(gpio_mode & GPIO_AF)
GPR(port) |= (1<<pin);
else
GPR(port) &= ~(1<<pin);
/* use as gpio? */
if( ocr == 3 )
GIUS(port) |= (1<<pin);
else
GIUS(port) &= ~(1<<pin);
/* Output / input configuration */
/* FIXME: I'm not very sure about OCR and ICONF, someone
* should have a look over it
*/
if(pin<16) {
tmp = OCR1(port);
tmp &= ~( 3<<(pin*2));
tmp |= (ocr << (pin*2));
OCR1(port) = tmp;
if( gpio_mode & GPIO_AOUT )
ICONFA1(port) &= ~( 3<<(pin*2));
if( gpio_mode & GPIO_BOUT )
ICONFB1(port) &= ~( 3<<(pin*2));
} else {
tmp = OCR2(port);
tmp &= ~( 3<<((pin-16)*2));
tmp |= (ocr << ((pin-16)*2));
OCR2(port) = tmp;
if( gpio_mode & GPIO_AOUT )
ICONFA2(port) &= ~( 3<<((pin-16)*2));
if( gpio_mode & GPIO_BOUT )
ICONFB2(port) &= ~( 3<<((pin-16)*2));
}
}
EXPORT_SYMBOL(imx_gpio_mode);
/*
* get the system pll clock in Hz
*
* mfi + mfn / (mfd +1)
* f = 2 * f_ref * --------------------
* pd + 1
*/
static unsigned int imx_decode_pll(unsigned int pll)
{
u32 mfi = (pll >> 10) & 0xf;
u32 mfn = pll & 0x3ff;
u32 mfd = (pll >> 16) & 0x3ff;
u32 pd = (pll >> 26) & 0xf;
u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
mfi = mfi <= 5 ? 5 : mfi;
return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
}
unsigned int imx_get_system_clk(void)
{
return imx_decode_pll(SPCTL0);
}
EXPORT_SYMBOL(imx_get_system_clk);
unsigned int imx_get_mcu_clk(void)
{
return imx_decode_pll(MPCTL0);
}
EXPORT_SYMBOL(imx_get_mcu_clk);
/*
* get peripheral clock 1 ( UART[12], Timer[12], PWM )
*/
unsigned int imx_get_perclk1(void)
{
return imx_get_system_clk() / (((PCDR) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_perclk1);
/*
* get peripheral clock 2 ( LCD, SD, SPI[12] )
*/
unsigned int imx_get_perclk2(void)
{
return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_perclk2);
/*
* get peripheral clock 3 ( SSI )
*/
unsigned int imx_get_perclk3(void)
{
return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
}
EXPORT_SYMBOL(imx_get_perclk3);
/*
* get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
*/
unsigned int imx_get_hclk(void)
{
return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
}
EXPORT_SYMBOL(imx_get_hclk);
static struct resource imx_mmc_resources[] = {
[0] = {
.start = 0x00214000,
.end = 0x002140FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (SDHC_INT),
.end = (SDHC_INT),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_mmc_device = {
.name = "imx-mmc",
.id = 0,
.num_resources = ARRAY_SIZE(imx_mmc_resources),
.resource = imx_mmc_resources,
};
static struct resource imx_uart1_resources[] = {
[0] = {
.start = 0x00206000,
.end = 0x002060FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (UART1_MINT_RX),
.end = (UART1_MINT_RX),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = (UART1_MINT_TX),
.end = (UART1_MINT_TX),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_uart1_device = {
.name = "imx-uart",
.id = 0,
.num_resources = ARRAY_SIZE(imx_uart1_resources),
.resource = imx_uart1_resources,
};
static struct resource imx_uart2_resources[] = {
[0] = {
.start = 0x00207000,
.end = 0x002070FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = (UART2_MINT_RX),
.end = (UART2_MINT_RX),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = (UART2_MINT_TX),
.end = (UART2_MINT_TX),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imx_uart2_device = {
.name = "imx-uart",
.id = 1,
.num_resources = ARRAY_SIZE(imx_uart2_resources),
.resource = imx_uart2_resources,
};
static struct resource imxfb_resources[] = {
[0] = {
.start = 0x00205000,
.end = 0x002050FF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = LCDC_INT,
.end = LCDC_INT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device imxfb_device = {
.name = "imx-fb",
.id = 0,
.num_resources = ARRAY_SIZE(imxfb_resources),
.resource = imxfb_resources,
};
static struct platform_device *devices[] __initdata = {
&imx_mmc_device,
&imxfb_device,
&imx_uart1_device,
&imx_uart2_device,
};
static struct map_desc imx_io_desc[] __initdata = {
/* virtual physical length type */
{IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
};
void __init
imx_map_io(void)
{
iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
}
static int __init imx_init(void)
{
return platform_add_devices(devices, ARRAY_SIZE(devices));
}
subsys_initcall(imx_init);

View File

@@ -0,0 +1,16 @@
/*
* linux/arch/arm/mach-imx/generic.h
*
* Author: Sascha Hauer <sascha@saschahauer.de>
* Copyright: Synertronixx GmbH
*
* 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.
*/
extern void __init imx_map_io(void);
extern void __init imx_init_irq(void);
struct sys_timer;
extern struct sys_timer imx_timer;

252
arch/arm/mach-imx/irq.c Normal file
View File

@@ -0,0 +1,252 @@
/*
* linux/arch/arm/mach-imx/irq.c
*
* Copyright (C) 1999 ARM Limited
* Copyright (C) 2002 Shane Nay (shane@minirl.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
*
* 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
* Copied from the motorola bsp package and added gpio demux
* interrupt handler
*/
#include <linux/init.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
/*
*
* We simply use the ENABLE DISABLE registers inside of the IMX
* to turn on/off specific interrupts. FIXME- We should
* also add support for the accelerated interrupt controller
* by putting offets to irq jump code in the appropriate
* places.
*
*/
#define INTENNUM_OFF 0x8
#define INTDISNUM_OFF 0xC
#define VA_AITC_BASE IO_ADDRESS(IMX_AITC_BASE)
#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF)
#define IMX_AITC_INTENNUM (VA_AITC_BASE + INTENNUM_OFF)
#if 0
#define DEBUG_IRQ(fmt...) printk(fmt)
#else
#define DEBUG_IRQ(fmt...) do { } while (0)
#endif
static void
imx_mask_irq(unsigned int irq)
{
__raw_writel(irq, IMX_AITC_INTDISNUM);
}
static void
imx_unmask_irq(unsigned int irq)
{
__raw_writel(irq, IMX_AITC_INTENNUM);
}
static int
imx_gpio_irq_type(unsigned int _irq, unsigned int type)
{
unsigned int irq_type = 0, irq, reg, bit;
irq = _irq - IRQ_GPIOA(0);
reg = irq >> 5;
bit = 1 << (irq % 32);
if (type == IRQT_PROBE) {
/* Don't mess with enabled GPIOs using preconfigured edges or
GPIOs set to alternate function during probe */
/* TODO: support probe */
// if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
// GPIO_bit(gpio))
// return 0;
// if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
// return 0;
// type = __IRQT_RISEDGE | __IRQT_FALEDGE;
}
GIUS(reg) |= bit;
DDIR(reg) &= ~(bit);
DEBUG_IRQ("setting type of irq %d to ", _irq);
if (type & __IRQT_RISEDGE) {
DEBUG_IRQ("rising edges\n");
irq_type = 0x0;
}
if (type & __IRQT_FALEDGE) {
DEBUG_IRQ("falling edges\n");
irq_type = 0x1;
}
if (type & __IRQT_LOWLVL) {
DEBUG_IRQ("low level\n");
irq_type = 0x3;
}
if (type & __IRQT_HIGHLVL) {
DEBUG_IRQ("high level\n");
irq_type = 0x2;
}
if (irq % 32 < 16) {
ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) |
(irq_type << ((irq % 16) * 2));
} else {
ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) |
(irq_type << ((irq % 16) * 2));
}
return 0;
}
static void
imx_gpio_ack_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
}
static void
imx_gpio_mask_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32));
}
static void
imx_gpio_unmask_irq(unsigned int irq)
{
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
}
static void
imx_gpio_handler(unsigned int mask, unsigned int irq,
struct irqdesc *desc, struct pt_regs *regs)
{
desc = irq_desc + irq;
while (mask) {
if (mask & 1) {
DEBUG_IRQ("handling irq %d\n", irq);
desc->handle(irq, desc, regs);
}
irq++;
desc++;
mask >>= 1;
}
}
static void
imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(0);
irq = IRQ_GPIOA(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(1);
irq = IRQ_GPIOB(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(2);
irq = IRQ_GPIOC(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static void
imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask, irq;
mask = ISR(3);
irq = IRQ_GPIOD(0);
imx_gpio_handler(mask, irq, desc, regs);
}
static struct irqchip imx_internal_chip = {
.ack = imx_mask_irq,
.mask = imx_mask_irq,
.unmask = imx_unmask_irq,
};
static struct irqchip imx_gpio_chip = {
.ack = imx_gpio_ack_irq,
.mask = imx_gpio_mask_irq,
.unmask = imx_gpio_unmask_irq,
.type = imx_gpio_irq_type,
};
void __init
imx_init_irq(void)
{
unsigned int irq;
DEBUG_IRQ("Initializing imx interrupts\n");
/* Mask all interrupts initially */
IMR(0) = 0;
IMR(1) = 0;
IMR(2) = 0;
IMR(3) = 0;
for (irq = 0; irq < IMX_IRQS; irq++) {
set_irq_chip(irq, &imx_internal_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
set_irq_chip(irq, &imx_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler);
set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler);
/* Disable all interrupts initially. */
/* In IMX this is done in the bootloader. */
}

View File

@@ -0,0 +1,54 @@
/*
* linux/arch/arm/mach-imx/leds-mx1ads.c
*
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* Original (leds-footbridge.c) by Russell King
*
* 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/init.h>
#include <asm/hardware.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include "leds.h"
/*
* The MX1ADS Board has only one usable LED,
* so select only the timer led or the
* cpu usage led
*/
void
mx1ads_leds_event(led_event_t ledevt)
{
unsigned long flags;
local_irq_save(flags);
switch (ledevt) {
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
DR(0) &= ~(1<<2);
break;
case led_idle_end:
DR(0) |= 1<<2;
break;
#endif
#ifdef CONFIG_LEDS_TIMER
case led_timer:
DR(0) ^= 1<<2;
#endif
default:
break;
}
local_irq_restore(flags);
}

31
arch/arm/mach-imx/leds.c Normal file
View File

@@ -0,0 +1,31 @@
/*
* linux/arch/arm/mach-imx/leds.h
*
* Copyright (C) 2004 Sascha Hauer <sascha@saschahauer.de>
*
*
* 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/init.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include "leds.h"
static int __init
leds_init(void)
{
if (machine_is_mx1ads()) {
leds_event = mx1ads_leds_event;
}
return 0;
}
__initcall(leds_init);

9
arch/arm/mach-imx/leds.h Normal file
View File

@@ -0,0 +1,9 @@
/*
* include/asm-arm/arch-imx/leds.h
*
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* blinky lights for IMX-based systems
*
*/
extern void mx1ads_leds_event(led_event_t evt);

View File

@@ -0,0 +1,88 @@
/*
* arch/arm/mach-imx/mx1ads.c
*
* Initially based on:
* linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
* Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
*
* 2004 (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/device.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <linux/interrupt.h>
#include "generic.h"
#include <asm/serial.h>
static struct resource mx1ads_resources[] = {
[0] = {
.start = IMX_CS4_VIRT,
.end = IMX_CS4_VIRT + 16,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 13,
.end = 13,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device mx1ads_device = {
.name = "mx1ads",
.num_resources = ARRAY_SIZE(mx1ads_resources),
.resource = mx1ads_resources,
};
static struct platform_device *devices[] __initdata = {
&mx1ads_device,
};
static void __init
mx1ads_init(void)
{
#ifdef CONFIG_LEDS
imx_gpio_mode(GPIO_PORTA | GPIO_OUT | GPIO_GPIO | 2);
#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
}
static struct map_desc mx1ads_io_desc[] __initdata = {
/* virtual physical length type */
{IMX_CS0_VIRT, IMX_CS0_PHYS, IMX_CS0_SIZE, MT_DEVICE},
{IMX_CS1_VIRT, IMX_CS1_PHYS, IMX_CS1_SIZE, MT_DEVICE},
{IMX_CS2_VIRT, IMX_CS2_PHYS, IMX_CS2_SIZE, MT_DEVICE},
{IMX_CS3_VIRT, IMX_CS3_PHYS, IMX_CS3_SIZE, MT_DEVICE},
{IMX_CS4_VIRT, IMX_CS4_PHYS, IMX_CS4_SIZE, MT_DEVICE},
{IMX_CS5_VIRT, IMX_CS5_PHYS, IMX_CS5_SIZE, MT_DEVICE},
};
static void __init
mx1ads_map_io(void)
{
imx_map_io();
iotable_init(mx1ads_io_desc, ARRAY_SIZE(mx1ads_io_desc));
}
MACHINE_START(MX1ADS, "Motorola MX1ADS")
MAINTAINER("Sascha Hauer, Pengutronix")
BOOT_MEM(0x08000000, 0x00200000, 0xe0200000)
BOOT_PARAMS(0x08000100)
MAPIO(mx1ads_map_io)
INITIRQ(imx_init_irq)
.timer = &imx_timer,
INIT_MACHINE(mx1ads_init)
MACHINE_END

101
arch/arm/mach-imx/time.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* linux/arch/arm/mach-imx/time.c
*
* Copyright (C) 2000-2001 Deep Blue Solutions
* Copyright (C) 2002 Shane Nay (shane@minirl.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/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/leds.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
/* Use timer 1 as system timer */
#define TIMER_BASE IMX_TIM1_BASE
/*
* Returns number of us since last clock interrupt. Note that interrupts
* will have been disabled by do_gettimeoffset()
*/
static unsigned long imx_gettimeoffset(void)
{
unsigned long ticks;
/*
* Get the current number of ticks. Note that there is a race
* condition between us reading the timer and checking for
* an interrupt. We get around this by ensuring that the
* counter has not reloaded between our two reads.
*/
ticks = IMX_TCN(TIMER_BASE);
/*
* Interrupt pending? If so, we've reloaded once already.
*/
if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
ticks += LATCH;
/*
* Convert the ticks to usecs
*/
return (1000000 / CLK32) * ticks;
}
/*
* IRQ handler for the timer
*/
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
write_seqlock(&xtime_lock);
/* clear the interrupt */
if (IMX_TSTAT(TIMER_BASE))
IMX_TSTAT(TIMER_BASE) = 0;
timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction imx_timer_irq = {
.name = "i.MX Timer Tick",
.flags = SA_INTERRUPT,
.handler = imx_timer_interrupt
};
/*
* Set up timer interrupt, and return the current time in seconds.
*/
static void __init imx_timer_init(void)
{
/*
* Initialise to a known state (all timers off, and timing reset)
*/
IMX_TCTL(TIMER_BASE) = 0;
IMX_TPRER(TIMER_BASE) = 0;
IMX_TCMP(TIMER_BASE) = LATCH - 1;
IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN;
/*
* Make irqs happen for the system timer
*/
setup_irq(TIM1_INT, &imx_timer_irq);
}
struct sys_timer imx_timer = {
.init = imx_timer_init,
.offset = imx_gettimeoffset,
};