Commit 34993337 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Russell King

[PATCH] 1080/1: Addition of new files for the Intel PXA250/210 architecture

This only populates the linux/arch/arm/mach-pxa directory.
parent 6094ecbd
#
# 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).
USE_STANDARD_AS_RULE := true
O_TARGET := pxa.o
obj-y :=
obj-m :=
obj-n :=
obj- :=
export-objs := generic.o irq.o dma.o sa1111.o
# Common support (must be linked before board specific support)
obj-y += generic.o irq.o dma.o
obj-$(CONFIG_SA1111) += sa1111.o
# Specific board support
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
# Support for blinky lights
leds-y := leds.o
leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
obj-$(CONFIG_LEDS) += $(leds-y)
include $(TOPDIR)/Rules.make
/*
* linux/arch/arm/mach-pxa/dma.c
*
* PXA DMA registration and IRQ dispatching
*
* Author: Nicolas Pitre
* Created: Nov 15, 2001
* Copyright: 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.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 *data;
} dma_channels[16];
int pxa_request_dma (char *name, pxa_dma_prio prio,
void (*irq_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) {
DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
dma_channels[i].name = name;
dma_channels[i].irq_handler = irq_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 pxa_free_dma (int dma_ch)
{
unsigned long flags;
if (!dma_channels[dma_ch].name) {
printk (KERN_CRIT __FUNCTION__
": trying to free channel %d which is already freed\n",
dma_ch);
return;
}
local_irq_save(flags);
DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
dma_channels[dma_ch].name = NULL;
local_irq_restore(flags);
}
static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, dint = DINT;
for (i = 0; i < 16; i++) {
if (dint & (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);
DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
}
}
}
}
static int __init pxa_dma_init (void)
{
int ret;
ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
if (ret)
printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
return ret;
}
__initcall(pxa_dma_init);
EXPORT_SYMBOL(pxa_request_dma);
EXPORT_SYMBOL(pxa_free_dma);
/*
* linux/arch/arm/mach-pxa/generic.c
*
* Author: Nicolas Pitre
* Created: Jun 15, 2001
* Copyright: MontaVista Software Inc.
*
* Code common to all PXA machines.
*
* 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.
*
* Since this file should be linked before any other machine specific file,
* the __initcall() here will be executed first. This serves as default
* initialization stuff for PXA machines which can be overriden later if
* need be.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <asm/hardware.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include "generic.h"
/*
* Return the current lclk requency in units of 10kHz
*/
unsigned int get_lclk_frequency_10khz(void)
{
unsigned int l;
l = CCCR & 0x1f;
switch(l)
{
case 1:
return 9953;
case 2:
return 11796;
case 3:
return 13271;
case 4:
return 14746;
case 5:
return 16589;
case 0xf:
return 3320;
default:
return 0;
}
}
EXPORT_SYMBOL(get_lclk_frequency_10khz);
/*
* Handy function to set GPIO alternate functions
*/
void pxa_gpio_mode(int gpio_mode)
{
long flags;
int gpio = gpio_mode & GPIO_MD_MASK_NR;
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
int gafr;
local_irq_save(flags);
if (gpio_mode & GPIO_MD_MASK_DIR)
GPDR(gpio) |= GPIO_bit(gpio);
else
GPDR(gpio) &= ~GPIO_bit(gpio);
gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
local_irq_restore(flags);
}
EXPORT_SYMBOL(pxa_gpio_mode);
/*
* Note that 0xfffe0000-0xffffffff is reserved for the vector table and
* cache flush area.
*/
static struct map_desc standard_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
{ 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
{ 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
{ 0xfc000000, 0x40000000, 0x01400000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */
{ 0xfe000000, 0x44000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
{ 0xff000000, 0x48000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */
LAST_DESC
};
void __init pxa_map_io(void)
{
iotable_init(standard_io_desc);
}
/*
* linux/arch/arm/mach-pxa/generic.h
*
* Author: Nicolas Pitre
* Copyright: 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 version 2 as
* published by the Free Software Foundation.
*/
extern void __init pxa_map_io(void);
extern void __init pxa_init_irq(void);
#define SET_BANK(__nr,__start,__size) \
mi->bank[__nr].start = (__start), \
mi->bank[__nr].size = (__size), \
mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
/*
* linux/arch/arm/mach-pxa/idp.c
*
* 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.
*
* Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
*
* 2001-09-13: Cliff Brake <cbrake@accelent.com>
* Initial code
*/
#include <linux/init.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/types.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "generic.h"
#define PXA_IDP_REV02
#ifndef PXA_IDP_REV02
/* shadow registers for write only registers */
unsigned int idp_cpld_led_control_shadow = 0x1;
unsigned int idp_cpld_periph_pwr_shadow = 0xd;
unsigned int ipd_cpld_cir_shadow = 0;
unsigned int idp_cpld_kb_col_high_shadow = 0;
unsigned int idp_cpld_kb_col_low_shadow = 0;
unsigned int idp_cpld_pccard_en_shadow = 0xC3;
unsigned int idp_cpld_gpioh_dir_shadow = 0;
unsigned int idp_cpld_gpioh_value_shadow = 0;
unsigned int idp_cpld_gpiol_dir_shadow = 0;
unsigned int idp_cpld_gpiol_value_shadow = 0;
/*
* enable all LCD signals -- they should still be on
* write protect flash
* enable all serial port transceivers
*/
unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */
(0x1 << 19) | /* disable flash write enable */
(0x7 << 9)); /* enable serial port transeivers */
#endif
static int __init idp_init(void)
{
printk("idp_init()\n");
return 0;
}
__initcall(idp_init);
static void __init idp_init_irq(void)
{
pxa_init_irq();
}
static void __init
fixup_idp(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
{
#ifdef PXA_IDP_REV02
SET_BANK (0, 0xa0000000, 64*1024*1024);
#else
SET_BANK (0, 0xa0000000, 32*1024*1024);
#endif
mi->nr_banks = 1;
#if 0
setup_ramdisk (1, 0, 0, 8192);
setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
#endif
}
static struct map_desc idp_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
#ifndef PXA_IDP_REV02
{ IDP_CTRL_PORT_BASE,
IDP_CTRL_PORT_PHYS,
IDP_CTRL_PORT_SIZE,
DOMAIN_IO,
0, 1, 0, 0 },
#endif
{ IDP_IDE_BASE,
IDP_IDE_PHYS,
IDP_IDE_SIZE,
DOMAIN_IO,
0, 1, 0, 0 },
{ IDP_ETH_BASE,
IDP_ETH_PHYS,
IDP_ETH_SIZE,
DOMAIN_IO,
0, 1, 0, 0 },
{ IDP_COREVOLT_BASE,
IDP_COREVOLT_PHYS,
IDP_COREVOLT_SIZE,
DOMAIN_IO,
0, 1, 0, 0 },
{ IDP_CPLD_BASE,
IDP_CPLD_PHYS,
IDP_CPLD_SIZE,
DOMAIN_IO,
0, 1, 0, 0 },
LAST_DESC
};
static void __init idp_map_io(void)
{
pxa_map_io();
iotable_init(idp_io_desc);
set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
}
MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
MAINTAINER("Accelent Systems Inc.")
BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
FIXUP(fixup_idp)
MAPIO(idp_map_io)
INITIRQ(idp_init_irq)
MACHINE_END
/*
* linux/arch/arm/mach-pxa/irq.c
*
* Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
*
* Author: Nicolas Pitre
* Created: Jun 15, 2001
* Copyright: 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include "generic.h"
/*
* This is for IRQs known as PXA_IRQ([8...31]).
*/
static void pxa_mask_irq(unsigned int irq)
{
ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
}
static void pxa_unmask_irq(unsigned int irq)
{
ICMR |= (1 << (irq + PXA_IRQ_SKIP));
}
static struct irqchip pxa_internal_chip = {
ack: pxa_mask_irq,
mask: pxa_mask_irq,
unmask: pxa_unmask_irq,
};
/*
* PXA GPIO edge detection for IRQs:
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
* Use this instead of directly setting GRER/GFER.
*/
static int GPIO_IRQ_rising_edge[3];
static int GPIO_IRQ_falling_edge[3];
static int GPIO_IRQ_mask[3];
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
int gpio, idx;
gpio = irq - ((irq >= IRQ_GPIO(2)) ? IRQ_GPIO(2) + 2 : IRQ_GPIO(0));
printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio);
pxa_gpio_mode(gpio | GPIO_IN);
if (type & __IRQT_RISEDGE) {
printk("rising ");
__set_bit (gpio, GPIO_IRQ_rising_edge);
} else
__clear_bit (gpio, GPIO_IRQ_rising_edge);
if (type & __IRQT_FALEDGE) {
printk("falling ");
__set_bit (gpio, GPIO_IRQ_falling_edge);
} else
__clear_bit (gpio, GPIO_IRQ_falling_edge);
printk("edges\n");
idx = gpio >> 5;
GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
return 0;
}
/*
* Since we can't actually physically mask edge triggered interrupts
* without the risk of missing transitions, we therefore logically mask
* them and defer their processing through tis function.
*/
static void pxa_manual_rerun(unsigned int irq)
{
struct pt_regs regs;
memset(&regs, 0, sizeof(regs));
irq_desc[irq].handle(irq, &irq_desc[irq], &regs);
}
/*
* GPIO IRQs must be acknoledged. This is for GPIO 0 and 1.
*/
static void pxa_ack_low_gpio(unsigned int irq)
{
GEDR0 = (1 << (irq - IRQ_GPIO0));
}
static struct irqchip pxa_low_gpio_chip = {
ack: pxa_ack_low_gpio,
mask: pxa_mask_irq,
unmask: pxa_unmask_irq,
rerun: pxa_manual_rerun,
type: pxa_gpio_irq_type,
};
/*
* Demux handler for GPIO 2-80 edge detect interrupts
*/
static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask;
int loop;
do {
loop = 0;
mask = GEDR0 & ~3;
if (mask) {
GEDR0 = mask;
irq = IRQ_GPIO(2);
desc = irq_desc + irq;
mask >>= 2;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
} while (mask);
loop = 1;
}
mask = GEDR1;
if (mask) {
GEDR1 = mask;
irq = IRQ_GPIO(32);
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
} while (mask);
loop = 1;
}
mask = GEDR2;
if (mask) {
GEDR2 = mask;
irq = IRQ_GPIO(64);
desc = irq_desc + irq;
do {
if (mask & 1)
desc->handle(irq, desc, regs);
irq++;
desc++;
mask >>= 1;
} while (mask);
loop = 1;
}
} while (loop);
}
static void pxa_ack_muxed_gpio(unsigned int irq)
{
int gpio = irq - IRQ_GPIO(2) + 2;
GEDR(gpio) = GPIO_bit(gpio);
}
static void pxa_mask_muxed_gpio(unsigned int irq)
{
int gpio = irq - IRQ_GPIO(2) + 2;
__clear_bit(gpio, GPIO_IRQ_mask);
GRER(gpio) &= ~GPIO_bit(gpio);
GFER(gpio) &= ~GPIO_bit(gpio);
}
static void pxa_unmask_muxed_gpio(unsigned int irq)
{
int gpio = irq - IRQ_GPIO(2) + 2;
int idx = gpio >> 5;
__set_bit(gpio, GPIO_IRQ_mask);
GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
}
static struct irqchip pxa_muxed_gpio_chip = {
ack: pxa_ack_muxed_gpio,
mask: pxa_mask_muxed_gpio,
unmask: pxa_unmask_muxed_gpio,
rerun: pxa_manual_rerun,
type: pxa_gpio_irq_type,
};
void __init pxa_init_irq(void)
{
int irq;
/* disable all IRQs */
ICMR = 0;
/* all IRQs are IRQ, not FIQ */
ICLR = 0;
/* clear all GPIO edge detects */
GFER0 = GFER1 = GFER2 = 0;
GRER0 = GRER1 = GRER2 = 0;
GEDR0 = GEDR0;
GEDR1 = GEDR1;
GEDR2 = GEDR2;
/* only unmasked interrupts kick us out of idle */
ICCR = 1;
/* GPIO 0 and 1 must have their mask bit always set */
GPIO_IRQ_mask[0] = 3;
for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = PXA_IRQ(11); irq <= PXA_IRQ(31); irq++) {
set_irq_chip(irq, &pxa_internal_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
}
/* Those are reserved */
set_irq_flags(PXA_IRQ(15), 0);
set_irq_flags(PXA_IRQ(16), 0);
for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
set_irq_chip(irq, &pxa_muxed_gpio_chip);
set_irq_handler(irq, do_edge_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
/* Install handler for GPIO 2-80 edge detect interrupts */
set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip);
set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler);
/*
* We generally don't want the LCD IRQ being
* enabled as soon as we request it.
*/
set_irq_flags(IRQ_LCD, IRQF_VALID | IRQF_NOAUTOEN);
}
/*
* linux/arch/arm/mach-pxa/leds-idp.c
*
* Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
*
* Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
*
* Original (leds-footbridge.c) by Russell King
*
* Macros for actual LED manipulation should be in machine specific
* files in this 'mach' directory.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
#include "leds.h"
#define LED_STATE_ENABLED 1
#define LED_STATE_CLAIMED 2
static unsigned int led_state;
static unsigned int hw_led_state;
void idp_leds_event(led_event_t evt)
{
unsigned long flags;
local_irq_save(flags);
switch (evt) {
case led_start:
hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
led_state = LED_STATE_ENABLED;
break;
case led_stop:
led_state &= ~LED_STATE_ENABLED;
break;
case led_claim:
led_state |= LED_STATE_CLAIMED;
hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
break;
case led_release:
led_state &= ~LED_STATE_CLAIMED;
hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
break;
#ifdef CONFIG_LEDS_TIMER
case led_timer:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state ^= IDP_HB_LED;
break;
#endif
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state |= IDP_BUSY_LED;
break;
case led_idle_end:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state &= ~IDP_BUSY_LED;
break;
#endif
case led_halted:
break;
case led_green_on:
if (led_state & LED_STATE_CLAIMED)
hw_led_state &= ~IDP_HB_LED;
break;
case led_green_off:
if (led_state & LED_STATE_CLAIMED)
hw_led_state |= IDP_HB_LED;
break;
case led_amber_on:
break;
case led_amber_off:
break;
case led_red_on:
if (led_state & LED_STATE_CLAIMED)
hw_led_state &= ~IDP_BUSY_LED;
break;
case led_red_off:
if (led_state & LED_STATE_CLAIMED)
hw_led_state |= IDP_BUSY_LED;
break;
default:
break;
}
if (led_state & LED_STATE_ENABLED)
IDP_WRITE_LEDS(hw_led_state);
local_irq_restore(flags);
}
/*
* linux/arch/arm/mach-pxa/leds-lubbock.c
*
* Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
*
* Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
*
* Original (leds-footbridge.c) by Russell King
*
* See leds.h for bit definitions. The first version defines D28 on the
* Lubbock dev board as the heartbeat, and D27 as the Sys_busy led.
* There's plenty more if you're interested in adding them :)
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
#include "leds.h"
#define LED_STATE_ENABLED 1
#define LED_STATE_CLAIMED 2
static unsigned int led_state;
static unsigned int hw_led_state;
void lubbock_leds_event(led_event_t evt)
{
unsigned long flags;
local_irq_save(flags);
switch (evt) {
case led_start:
hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
led_state = LED_STATE_ENABLED;
break;
case led_stop:
led_state &= ~LED_STATE_ENABLED;
break;
case led_claim:
led_state |= LED_STATE_CLAIMED;
hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
break;
case led_release:
led_state &= ~LED_STATE_CLAIMED;
hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
break;
#ifdef CONFIG_LEDS_TIMER
case led_timer:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state ^= HEARTBEAT_LED;
break;
#endif
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state |= SYS_BUSY_LED;
break;
case led_idle_end:
if (!(led_state & LED_STATE_CLAIMED))
hw_led_state &= ~SYS_BUSY_LED;
break;
#endif
case led_halted:
break;
case led_green_on:
if (led_state & LED_STATE_CLAIMED)
hw_led_state &= ~HEARTBEAT_LED;
break;
case led_green_off:
if (led_state & LED_STATE_CLAIMED)
hw_led_state |= HEARTBEAT_LED;
break;
case led_amber_on:
break;
case led_amber_off:
break;
case led_red_on:
if (led_state & LED_STATE_CLAIMED)
hw_led_state &= ~SYS_BUSY_LED;
break;
case led_red_off:
if (led_state & LED_STATE_CLAIMED)
hw_led_state |= SYS_BUSY_LED;
break;
default:
break;
}
if (led_state & LED_STATE_ENABLED)
{
switch (hw_led_state) {
case 0: // all on
HEARTBEAT_LED_ON;
SYS_BUSY_LED_ON;
break;
case 1: // turn off heartbeat, status on:
HEARTBEAT_LED_OFF;
SYS_BUSY_LED_ON;
break;
case 2: // status off, heartbeat on:
HEARTBEAT_LED_ON;
SYS_BUSY_LED_OFF;
break;
case 3: // turn them both off...
HEARTBEAT_LED_OFF;
SYS_BUSY_LED_OFF;
break;
default:
break;
}
}
local_irq_restore(flags);
}
/*
* linux/arch/arm/mach-pxa/leds.c
*
* xscale LEDs dispatcher
*
* Copyright (C) 2001 Nicolas Pitre
*
* Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include "leds.h"
static int __init
pxa_leds_init(void)
{
if (machine_is_lubbock())
leds_event = lubbock_leds_event;
if (machine_is_pxa_idp())
leds_event = idp_leds_event;
leds_event(led_start);
return 0;
}
__initcall(pxa_leds_init);
/*
* include/asm-arm/arch-pxa/leds.h
*
* Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
*
* blinky lights for various PXA-based systems:
*
*/
extern void lubbock_leds_event(led_event_t evt);
extern void idp_leds_event(led_event_t evt);
/*
* linux/arch/arm/mach-pxa/lubbock.c
*
* Support for the Intel DBPXA250 Development Platform.
*
* Author: Nicolas Pitre
* Created: Jun 15, 2001
* Copyright: 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/types.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
#include <asm/hardware/sa1111.h>
#include "generic.h"
#include "sa1111.h"
static void lubbock_ack_irq(unsigned int irq)
{
int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
}
static void lubbock_mask_irq(unsigned int irq)
{
int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_MASK_EN &= ~(1 << lubbock_irq);
}
static void lubbock_unmask_irq(unsigned int irq)
{
int lubbock_irq = (irq - LUBBOCK_IRQ(0));
LUB_IRQ_MASK_EN |= (1 << lubbock_irq);
}
static struct irqchip lubbock_irq_chip = {
ack: lubbock_ack_irq,
mask: lubbock_mask_irq,
unmask: lubbock_unmask_irq,
};
void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int enabled, pending;
/* get active pending irq mask */
enabled = LUB_IRQ_MASK_EN & 0x003f;
pending = LUB_IRQ_SET_CLR & enabled;
do {
//printk("%s a: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 );
/* clear our parent irq */
GEDR(0) = GPIO_bit(0);
/* process them */
irq = LUBBOCK_IRQ(0);
desc = irq_desc + irq;
do {
if (pending & 1)
desc->handle(irq, desc, regs);
irq++;
desc++;
pending >>= 1;
} while (pending);
//printk("%s b: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 );
enabled = LUB_IRQ_MASK_EN & 0x003f;
pending = LUB_IRQ_SET_CLR & enabled;
} while (pending);
}
static void __init lubbock_init_irq(void)
{
int irq;
pxa_init_irq();
/* setup extra lubbock irqs */
for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_IRQ(5); irq++) {
set_irq_chip(irq, &lubbock_irq_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
}
static int __init lubbock_init(void)
{
int ret;
ret = sa1111_probe(LUBBOCK_SA1111_BASE);
if (ret)
return ret;
sa1111_wake();
sa1111_init_irq(LUBBOCK_SA1111_IRQ);
return 0;
}
__initcall(lubbock_init);
static void __init
fixup_lubbock(struct machine_desc *desc, struct param_struct *params,
char **cmdline, struct meminfo *mi)
{
SET_BANK (0, 0xa0000000, 64*1024*1024);
mi->nr_banks = 1;
#if 0
setup_ramdisk (1, 0, 0, 8192);
setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
#endif
}
static struct map_desc lubbock_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
{ 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
{ 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
{ 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
{ 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
LAST_DESC
};
static void __init lubbock_map_io(void)
{
pxa_map_io();
iotable_init(lubbock_io_desc);
/* This enables the BTUART */
CKEN |= CKEN7_BTUART;
pxa_gpio_mode(GPIO42_BTRXD_MD);
pxa_gpio_mode(GPIO43_BTTXD_MD);
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
/* This is for the SMC chip select */
pxa_gpio_mode(GPIO79_nCS_3_MD);
}
MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform")
MAINTAINER("MontaVista Software Inc.")
BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
FIXUP(fixup_lubbock)
MAPIO(lubbock_map_io)
INITIRQ(lubbock_init_irq)
MACHINE_END
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment