Commit a85be436 authored by Ralf Bächle's avatar Ralf Bächle Committed by Linus Torvalds

[PATCH] Alchemy update

This is an update of the AMD Alchemy support for 2.5.

(This is way behind what we have for 2.4 but forward porting is non-trivial
and work in progress.)
parent 9451f92d
......@@ -5,14 +5,14 @@
#
# Makefile for the Alchemy Au1000 CPU, generic files.
#
# 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).
#
obj-y := prom.o dbg_io.o int-handler.o irq.o puts.o time.o reset.o
obj-$(CONFIG_AU1000_UART) += serial.o
obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o
EXTRA_AFLAGS := $(CFLAGS)
obj-y += prom.o int-handler.o dma.o irq.o puts.o \
time.o reset.o clocks.o power.o
ramdisk.o:
mkramobj ramdisk ramdisk.o
obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o
obj-$(CONFIG_KGDB) += dbg_io.o
obj-$(CONFIG_RTC) += rtc.o
/*
* BRIEF MODULE DESCRIPTION
* Simple Au1000 clocks routines.
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <asm/au1000.h>
static unsigned int au1x00_clock; // Hz
static unsigned int lcd_clock; // KHz
static unsigned long uart_baud_base;
/*
* Set the au1000_clock
*/
void set_au1x00_speed(unsigned int new_freq)
{
au1x00_clock = new_freq;
}
unsigned int get_au1x00_speed(void)
{
return au1x00_clock;
}
/*
* The UART baud base is not known at compile time ... if
* we want to be able to use the same code on different
* speed CPUs.
*/
unsigned long get_au1x00_uart_baud_base(void)
{
return uart_baud_base;
}
void set_au1x00_uart_baud_base(unsigned long new_baud_base)
{
uart_baud_base = new_baud_base;
}
/*
* Calculate the Au1x00's LCD clock based on the current
* cpu clock and the system bus clock, and try to keep it
* below 40 MHz (the Pb1000 board can lock-up if the LCD
* clock is over 40 MHz).
*/
void set_au1x00_lcd_clock(void)
{
unsigned int static_cfg0;
unsigned int sys_busclk =
(get_au1x00_speed()/1000) /
((int)(au_readl(SYS_POWERCTRL)&0x03) + 2);
static_cfg0 = au_readl(MEM_STCFG0);
if (static_cfg0 & (1<<11))
lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
else
lcd_clock = sys_busclk / 4;
if (lcd_clock > 50000) /* Epson MAX */
printk("%s: warning: LCD clock too high (%d KHz)\n",
__FUNCTION__, lcd_clock);
}
unsigned int get_au1x00_lcd_clock(void)
{
return lcd_clock;
}
EXPORT_SYMBOL(get_au1x00_lcd_clock);
......@@ -3,13 +3,13 @@
#include <asm/io.h>
#include <asm/au1000.h>
#ifdef CONFIG_REMOTE_DEBUG
#ifdef CONFIG_KGDB
/*
* FIXME the user should be able to select the
* uart to be used for debugging.
*/
#define DEBUG_BASE UART2_ADDR
#define DEBUG_BASE UART_DEBUG_BASE
/**/
/* we need uint32 uint8 */
......@@ -53,8 +53,11 @@ typedef unsigned int uint32;
#define UART_MOD_CNTRL 0x100 /* Module Control */
/* memory-mapped read/write of the port */
#define UART16550_READ(y) (inl(DEBUG_BASE + y) & 0xff)
#define UART16550_WRITE(y,z) (outl(z&0xff, DEBUG_BASE + y))
#define UART16550_READ(y) (au_readl(DEBUG_BASE + y) & 0xff)
#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y))
extern unsigned long get_au1x00_uart_baud_base(void);
extern unsigned long cal_r4koff(void);
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
{
......@@ -68,16 +71,16 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
UART16550_WRITE(UART_IER, 0);
/* set up baud rate */
{
{
uint32 divisor;
/* set divisor */
divisor = get_au1000_uart_baud() / baud;
divisor = get_au1x00_uart_baud_base() / baud;
UART16550_WRITE(UART_CLK, divisor & 0xffff);
}
/* set data format */
UART16550_WRITE(UART_LCR, data | parity | stop);
UART16550_WRITE(UART_LCR, (data | parity | stop));
}
static int remoteDebugInitialized = 0;
......@@ -99,7 +102,8 @@ uint8 getDebugChar(void)
int putDebugChar(uint8 byte)
{
int i;
// int i;
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(UART16550_BAUD_115200,
......
/*
*
* BRIEF MODULE DESCRIPTION
* A DMA channel allocator for Au1000. API is modeled loosely off of
* linux/kernel/dma.c.
*
* Copyright 2000 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* stevel@mvista.com or source@mvista.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <asm/au1000.h>
#include <asm/au1000_dma.h>
#include <asm/system.h>
/*
* A note on resource allocation:
*
* All drivers needing DMA channels, should allocate and release them
* through the public routines `request_dma()' and `free_dma()'.
*
* In order to avoid problems, all processes should allocate resources in
* the same sequence and release them in the reverse order.
*
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
* When releasing them, first release the IRQ, then release the DMA. The
* main reason for this order is that, if you are requesting the DMA buffer
* done interrupt, you won't know the irq number until the DMA channel is
* returned from request_dma.
*/
spinlock_t au1000_dma_spin_lock = SPIN_LOCK_UNLOCKED;
struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = {
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,},
{dev_id:-1,}
};
// Device FIFO addresses and default DMA modes
static const struct {
unsigned int fifo_addr;
unsigned int dma_mode;
} dma_dev_table[DMA_NUM_DEV] = {
{UART0_ADDR + UART_TX, 0},
{UART0_ADDR + UART_RX, 0},
{0, 0},
{0, 0},
{AC97C_DATA, DMA_DW16 }, // coherent
{AC97C_DATA, DMA_DR | DMA_DW16 }, // coherent
{UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC},
{UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC},
{USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC},
{USBD_EP0WR, DMA_DW8 | DMA_NC},
{USBD_EP2WR, DMA_DW8 | DMA_NC},
{USBD_EP3WR, DMA_DW8 | DMA_NC},
{USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC},
{USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC},
{I2S_DATA, DMA_DW32 | DMA_NC},
{I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC}
};
int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
int length, int *eof, void *data)
{
int i, len = 0;
struct dma_chan *chan;
for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
if ((chan = get_dma_chan(i)) != NULL) {
len += sprintf(buf + len, "%2d: %s\n",
i, chan->dev_str);
}
}
if (fpos >= len) {
*start = buf;
*eof = 1;
return 0;
}
*start = buf + fpos;
if ((len -= fpos) > length)
return length;
*eof = 1;
return len;
}
void dump_au1000_dma_channel(unsigned int dmanr)
{
struct dma_chan *chan;
if (dmanr > NUM_AU1000_DMA_CHANNELS)
return;
chan = &au1000_dma_table[dmanr];
printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
printk(KERN_INFO " mode = 0x%08x\n",
au_readl(chan->io + DMA_MODE_SET));
printk(KERN_INFO " addr = 0x%08x\n",
au_readl(chan->io + DMA_PERIPHERAL_ADDR));
printk(KERN_INFO " start0 = 0x%08x\n",
au_readl(chan->io + DMA_BUFFER0_START));
printk(KERN_INFO " start1 = 0x%08x\n",
au_readl(chan->io + DMA_BUFFER1_START));
printk(KERN_INFO " count0 = 0x%08x\n",
au_readl(chan->io + DMA_BUFFER0_COUNT));
printk(KERN_INFO " count1 = 0x%08x\n",
au_readl(chan->io + DMA_BUFFER1_COUNT));
}
/*
* Finds a free channel, and binds the requested device to it.
* Returns the allocated channel number, or negative on error.
* Requests the DMA done IRQ if irqhandler != NULL.
*/
int request_au1000_dma(int dev_id, const char *dev_str,
void (*irqhandler)(int, void *, struct pt_regs *),
unsigned long irqflags,
void *irq_dev_id)
{
struct dma_chan *chan;
int i, ret;
if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
return -EINVAL;
for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
if (au1000_dma_table[i].dev_id < 0)
break;
}
if (i == NUM_AU1000_DMA_CHANNELS)
return -ENODEV;
chan = &au1000_dma_table[i];
if (irqhandler) {
chan->irq = AU1000_DMA_INT_BASE + i;
chan->irq_dev = irq_dev_id;
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
dev_str, chan->irq_dev))) {
chan->irq = 0;
chan->irq_dev = NULL;
return ret;
}
} else {
chan->irq = 0;
chan->irq_dev = NULL;
}
// fill it in
chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN;
chan->dev_id = dev_id;
chan->dev_str = dev_str;
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
chan->mode = dma_dev_table[dev_id].dma_mode;
/* initialize the channel before returning */
init_dma(i);
return i;
}
void free_au1000_dma(unsigned int dmanr)
{
struct dma_chan *chan = get_dma_chan(dmanr);
if (!chan) {
printk("Trying to free DMA%d\n", dmanr);
return;
}
disable_dma(dmanr);
if (chan->irq)
free_irq(chan->irq, chan->irq_dev);
chan->irq = 0;
chan->irq_dev = NULL;
chan->dev_id = -1;
}
......@@ -9,7 +9,6 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/config.h>
#include <asm/asm.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
......@@ -40,32 +39,30 @@ NESTED(au1000_IRQ, PT_SIZE, sp)
1:
andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
beq a0, zero, 2f
move a0,sp
beq a0, zero, 2f
move a0,sp
jal intc0_req0_irqdispatch
j ret_from_irq
2:
andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
beq a0, zero, 3f
move a0,sp
beq a0, zero, 3f
move a0,sp
jal intc0_req1_irqdispatch
j ret_from_irq
3:
andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
beq a0, zero, 4f
move a0,sp
beq a0, zero, 4f
move a0,sp
jal intc1_req0_irqdispatch
j ret_from_irq
4:
andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
beq a0, zero, 5f
move a0, sp
beq a0, zero, 5f
move a0, sp
jal intc1_req1_irqdispatch
j ret_from_irq
5:
5:
move a0, sp
jal mips_spurious_interrupt
done:
j ret_from_irq
j spurious_interrupt
END(au1000_IRQ)
This diff is collapsed.
/*
* BRIEF MODULE DESCRIPTION
* Au1000 Power Management routines.
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* Some of the routines are right out of init/main.c, whose
* copyrights apply here.
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/au1000.h>
#define DEBUG 1
#ifdef DEBUG
# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
#else
# define DPRINTK(fmt, args...)
#endif
extern void au1k_wait(void);
static void calibrate_delay(void);
extern void set_au1000_speed(unsigned int new_freq);
extern unsigned int get_au1000_speed(void);
extern unsigned long get_au1000_uart_baud_base(void);
extern void set_au1000_uart_baud_base(unsigned long new_baud_base);
extern unsigned long save_local_and_disable(int controller);
extern void restore_local_and_enable(int controller, unsigned long mask);
extern void local_enable_irq(unsigned int irq_nr);
/* Quick acpi hack. This will have to change! */
#define CTL_ACPI 9999
#define ACPI_S1_SLP_TYP 19
#define ACPI_SLEEP 21
#ifdef CONFIG_PM
static spinlock_t pm_lock = SPIN_LOCK_UNLOCKED;
unsigned long suspend_mode;
void wakeup_from_suspend(void)
{
suspend_mode = 0;
}
int au_sleep(void)
{
unsigned long wakeup, flags;
spin_lock_irqsave(&pm_lock,flags);
flush_cache_all();
/* pin 6 is gpio */
au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
/* gpio 6 can cause a wake up event */
wakeup = au_readl(SYS_WAKEMSK);
wakeup &= ~(1 << 8); /* turn off match20 wakeup */
wakeup |= 1 << 6; /* turn on gpio 6 wakeup */
au_writel(wakeup, SYS_WAKEMSK);
au_writel(1, SYS_WAKESRC); /* clear cause */
au_writel(1, SYS_SLPPWR); /* prepare to sleep */
__asm__("la $4, 1f\n\t"
"lui $5, 0xb190\n\t"
"ori $5, 0x18\n\t"
"sw $4, 0($5)\n\t"
"li $4, 1\n\t"
"lui $5, 0xb190\n\t"
"ori $5, 0x7c\n\t"
"sw $4, 0($5)\n\t" "sync\n\t" "1:\t\n\t" "nop\n\t");
/* after a wakeup, the cpu vectors back to 0x1fc00000 so
* it's up to the boot code to get us back here.
*/
spin_unlock_irqrestore(&pm_lock, flags);
return 0;
}
static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
void *buffer, size_t * len)
{
int retval = 0;
if (!write) {
*len = 0;
} else {
retval = pm_send_all(PM_SUSPEND, (void *) 2);
if (retval)
return retval;
au_sleep();
retval = pm_send_all(PM_RESUME, (void *) 0);
}
return retval;
}
static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
void *buffer, size_t * len)
{
int retval = 0;
if (!write) {
*len = 0;
} else {
retval = pm_send_all(PM_SUSPEND, (void *) 2);
if (retval)
return retval;
suspend_mode = 1;
au1k_wait();
retval = pm_send_all(PM_RESUME, (void *) 0);
}
return retval;
}
static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
void *buffer, size_t * len)
{
int retval = 0, i;
unsigned long val, pll;
#define TMPBUFLEN 64
#define MAX_CPU_FREQ 396
char buf[8], *p;
unsigned long flags, intc0_mask, intc1_mask;
unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
old_refresh;
unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
spin_lock_irqsave(&pm_lock, flags);
if (!write) {
*len = 0;
} else {
/* Parse the new frequency */
if (*len > TMPBUFLEN - 1) {
spin_unlock_irqrestore(&pm_lock, flags);
return -EFAULT;
}
if (copy_from_user(buf, buffer, *len)) {
spin_unlock_irqrestore(&pm_lock, flags);
return -EFAULT;
}
buf[*len] = 0;
p = buf;
val = simple_strtoul(p, &p, 0);
if (val > MAX_CPU_FREQ) {
spin_unlock_irqrestore(&pm_lock, flags);
return -EFAULT;
}
pll = val / 12;
if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
/* revisit this for higher speed cpus */
spin_unlock_irqrestore(&pm_lock, flags);
return -EFAULT;
}
old_baud_base = get_au1000_uart_baud_base();
old_cpu_freq = get_au1000_speed();
new_cpu_freq = pll * 12 * 1000000;
new_baud_base = (new_cpu_freq / 4) / 16;
set_au1000_speed(new_cpu_freq);
set_au1000_uart_baud_base(new_baud_base);
old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
new_refresh =
((old_refresh * new_cpu_freq) /
old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
au_writel(pll, SYS_CPUPLL);
au_sync_delay(1);
au_writel(new_refresh, MEM_SDREFCFG);
au_sync_delay(1);
for (i = 0; i < 4; i++) {
if (au_readl
(UART_BASE + UART_MOD_CNTRL +
i * 0x00100000) == 3) {
old_clk =
au_readl(UART_BASE + UART_CLK +
i * 0x00100000);
// baud_rate = baud_base/clk
baud_rate = old_baud_base / old_clk;
/* we won't get an exact baud rate and the error
* could be significant enough that our new
* calculation will result in a clock that will
* give us a baud rate that's too far off from
* what we really want.
*/
if (baud_rate > 100000)
baud_rate = 115200;
else if (baud_rate > 50000)
baud_rate = 57600;
else if (baud_rate > 30000)
baud_rate = 38400;
else if (baud_rate > 17000)
baud_rate = 19200;
else
(baud_rate = 9600);
// new_clk = new_baud_base/baud_rate
new_clk = new_baud_base / baud_rate;
au_writel(new_clk,
UART_BASE + UART_CLK +
i * 0x00100000);
au_sync_delay(10);
}
}
}
/* We don't want _any_ interrupts other than
* match20. Otherwise our calibrate_delay()
* calculation will be off, potentially a lot.
*/
intc0_mask = save_local_and_disable(0);
intc1_mask = save_local_and_disable(1);
local_enable_irq(AU1000_TOY_MATCH2_INT);
spin_unlock_irqrestore(&pm_lock, flags);
calibrate_delay();
restore_local_and_enable(0, intc0_mask);
restore_local_and_enable(1, intc1_mask);
return retval;
}
static struct ctl_table pm_table[] = {
{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
{CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
{0}
};
static struct ctl_table pm_dir_table[] = {
{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
{0}
};
/*
* Initialize power interface
*/
static int __init pm_init(void)
{
register_sysctl_table(pm_dir_table, 1);
return 0;
}
__initcall(pm_init);
/*
* This is right out of init/main.c
*/
/* This is the number of bits of precision for the loops_per_jiffy. Each
bit takes on average 1.5/HZ seconds. This (like the original) is a little
better than 1% */
#define LPS_PREC 8
static void calibrate_delay(void)
{
unsigned long ticks, loopbit;
int lps_precision = LPS_PREC;
loops_per_jiffy = (1 << 12);
while (loops_per_jiffy <<= 1) {
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */ ;
/* Go .. */
ticks = jiffies;
__delay(loops_per_jiffy);
ticks = jiffies - ticks;
if (ticks)
break;
}
/* Do a binary approximation to get loops_per_jiffy set to equal one clock
(up to lps_precision bits) */
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit;
ticks = jiffies;
while (ticks == jiffies);
ticks = jiffies;
__delay(loops_per_jiffy);
if (jiffies != ticks) /* longer than 1 tick */
loops_per_jiffy &= ~loopbit;
}
}
void au1k_wait(void)
{
__asm__("nop\n\t" "nop\n\t");
}
#endif /* CONFIG_PM */
......@@ -4,11 +4,11 @@
* PROM library initialisation code, assuming a version of
* pmon is the boot code.
*
* Copyright 2000 MontaVista Software Inc.
* Copyright 2000,2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This file was derived from Carsten Langgaard's
* This file was derived from Carsten Langgaard's
* arch/mips/mips-boards/xx files.
*
* Carsten Langgaard, carstenl@mips.com
......@@ -35,7 +35,7 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
......@@ -44,22 +44,23 @@
/* #define DEBUG_CMDLINE */
char arcs_cmdline[COMMAND_LINE_SIZE];
int prom_argc;
char **prom_argv, **prom_envp;
char arcs_cmdline[CL_SIZE];
extern int prom_argc;
extern char **prom_argv, **prom_envp;
typedef struct {
char *name;
/* char *val; */
} t_env_var;
typedef struct
{
char *name;
/* char *val; */
}t_env_var;
char * __init prom_getcmdline(void)
char * prom_getcmdline(void)
{
return &(arcs_cmdline[0]);
}
void __init prom_init_cmdline(void)
void prom_init_cmdline(void)
{
char *cp;
int actr;
......@@ -101,20 +102,57 @@ char *prom_getenv(char *envname)
return(NULL);
}
static inline unsigned char str2hexnum(unsigned char c)
inline unsigned char str2hexnum(unsigned char c)
{
if(c >= '0' && c <= '9')
return c - '0';
return c - '0';
if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
return c - 'a' + 10;
if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0; /* foo */
}
int __init page_is_ram(unsigned long pagenr)
inline void str2eaddr(unsigned char *ea, unsigned char *str)
{
return 1;
int i;
for(i = 0; i < 6; i++) {
unsigned char num;
if((*str == '.') || (*str == ':'))
str++;
num = str2hexnum(*str++) << 4;
num |= (str2hexnum(*str++));
ea[i] = num;
}
}
void prom_free_prom_memory (void)
int get_ethernet_addr(char *ethernet_addr)
{
char *ethaddr_str;
ethaddr_str = prom_getenv("ethaddr");
if (!ethaddr_str) {
printk("ethaddr not set in boot prom\n");
return -1;
}
str2eaddr(ethernet_addr, ethaddr_str);
#if 0
{
int i;
printk("get_ethernet_addr: ");
for (i=0; i<5; i++)
printk("%02x:", (unsigned char)*(ethernet_addr+i));
printk("%02x\n", *(ethernet_addr+i));
}
#endif
return 0;
}
void prom_free_prom_memory (void) {}
EXPORT_SYMBOL(prom_getcmdline);
EXPORT_SYMBOL(get_ethernet_addr);
......@@ -29,8 +29,9 @@
*/
#include <linux/types.h>
#include <asm/au1000.h>
#define SERIAL_BASE 0xB1100000 /* au1000, uart 0 */
#define SERIAL_BASE UART_BASE
#define SER_CMD 0x7
#define SER_DATA 0x1
#define TX_BUSY 0x20
......
......@@ -27,7 +27,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
......@@ -35,23 +35,107 @@
#include <asm/processor.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <asm/au1000.h>
extern int au_sleep(void);
void au1000_restart(char *command)
{
set_cp0_status(ST0_BEV | ST0_ERL);
set_cp0_config(CONF_CM_UNCACHED);
/* Set all integrated peripherals to disabled states */
u32 prid = read_c0_prid();
printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n");
switch (prid & 0xFF000000)
{
case 0x00000000: /* Au1000 */
au_writel(0x02, 0xb0000010); /* ac97_enable */
au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
asm("sync");
au_writel(0x00, 0xb017fffc); /* usbh_enable */
au_writel(0x00, 0xb0200058); /* usbd_enable */
au_writel(0x00, 0xb0300040); /* ir_enable */
au_writel(0x00, 0xb0520000); /* macen0 */
au_writel(0x00, 0xb0520004); /* macen1 */
au_writel(0x00, 0xb1000008); /* i2s_enable */
au_writel(0x00, 0xb1100100); /* uart0_enable */
au_writel(0x00, 0xb1200100); /* uart1_enable */
au_writel(0x00, 0xb1300100); /* uart2_enable */
au_writel(0x00, 0xb1400100); /* uart3_enable */
au_writel(0x02, 0xb1600100); /* ssi0_enable */
au_writel(0x02, 0xb1680100); /* ssi1_enable */
au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
au_writel(0x00, 0xb1900028); /* sys_clksrc */
au_writel(0x00, 0xb1900100); /* sys_pininputen */
break;
case 0x01000000: /* Au1500 */
au_writel(0x02, 0xb0000010); /* ac97_enable */
au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
asm("sync");
au_writel(0x00, 0xb017fffc); /* usbh_enable */
au_writel(0x00, 0xb0200058); /* usbd_enable */
au_writel(0x00, 0xb1520000); /* macen0 */
au_writel(0x00, 0xb1520004); /* macen1 */
au_writel(0x00, 0xb1100100); /* uart0_enable */
au_writel(0x00, 0xb1400100); /* uart3_enable */
au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
au_writel(0x00, 0xb1900028); /* sys_clksrc */
au_writel(0x00, 0xb1900100); /* sys_pininputen */
break;
case 0x02000000: /* Au1100 */
au_writel(0x02, 0xb0000010); /* ac97_enable */
au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
asm("sync");
au_writel(0x00, 0xb017fffc); /* usbh_enable */
au_writel(0x00, 0xb0200058); /* usbd_enable */
au_writel(0x00, 0xb0300040); /* ir_enable */
au_writel(0x00, 0xb0520000); /* macen0 */
au_writel(0x00, 0xb1000008); /* i2s_enable */
au_writel(0x00, 0xb1100100); /* uart0_enable */
au_writel(0x00, 0xb1200100); /* uart1_enable */
au_writel(0x00, 0xb1400100); /* uart3_enable */
au_writel(0x02, 0xb1600100); /* ssi0_enable */
au_writel(0x02, 0xb1680100); /* ssi1_enable */
au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
au_writel(0x00, 0xb1900028); /* sys_clksrc */
au_writel(0x00, 0xb1900100); /* sys_pininputen */
break;
default:
break;
}
set_c0_status(ST0_BEV | ST0_ERL);
set_c0_config(CONF_CM_UNCACHED);
flush_cache_all();
write_32bit_cp0_register(CP0_WIRED, 0);
write_c0_wired(0);
#if defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500)
/* Do a HW reset if the board can do it */
au_writel(0x00000000, 0xAE00001C);
#endif
__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
void au1000_halt(void)
{
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
#ifdef CONFIG_PM
au_sleep();
/* should not get here */
printk(KERN_ERR "Unable to put cpu in sleep mode\n");
while(1);
#else
while (1)
__asm__(".set\tmips3\n\t"
"wait\n\t"
".set\tmips0");
#endif
}
void au1000_power_off(void)
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* RTC routines for PC style attached Dallas chip.
*
* Copyright (C) 1998, 2001 by Ralf Baechle
*/
#include <linux/mc146818rtc.h>
#include <asm/io.h>
#include <asm/au1000.h>
#define PB1500_RTC_ADDR 0xAC000000
unsigned char std_rtc_read_data(unsigned long offset)
{
offset <<= 2;
return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff);
}
static void std_rtc_write_data(unsigned char data, unsigned long offset)
{
offset <<= 2;
au_writel(data, offset + PB1500_RTC_ADDR);
}
static int std_rtc_bcd_mode(void)
{
return 1;
}
struct rtc_ops pb1500_rtc_ops = {
&std_rtc_read_data,
&std_rtc_write_data,
&std_rtc_bcd_mode
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# Copyright 2000 MontaVista Software Inc.
# Author: MontaVista Software, Inc.
# ppopov@mvista.com or source@mvista.com
#
# Makefile for the Alchemy Semiconductor PB1000 board.
#
# 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).
#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET := db1x00.o
obj-y := init.o setup.o
/*
*
* BRIEF MODULE DESCRIPTION
* PB1000 board setup
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
int prom_argc;
char **prom_argv, **prom_envp;
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname);
const char *get_system_type(void)
{
return "Alchemy Db1000";
}
int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = argc;
prom_argv = argv;
prom_envp = envp;
mips_machgroup = MACH_GROUP_ALCHEMY;
mips_machtype = MACH_DB1000; /* set the platform # */
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str) {
memsize = 0x04000000;
} else {
memsize = simple_strtol(memsize_str, NULL, 0);
}
add_memory_region(0, memsize, BOOT_MEM_RAM);
return 0;
}
This diff is collapsed.
......@@ -5,5 +5,13 @@
#
# Makefile for the Alchemy Semiconductor PB1000 board.
#
# 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 := pb1000.o
obj-y := init.o setup.o
......@@ -33,27 +33,39 @@
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
extern int prom_argc;
extern char **prom_argv, **prom_envp;
int prom_argc;
char **prom_argv, **prom_envp;
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname);
const char *get_system_type(void)
{
return "Alchemy Pb1000";
}
int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = argc;
prom_argv = argv;
prom_envp = envp;
mips_machgroup = MACH_GROUP_ALCHEMY;
mips_machtype = MACH_PB1000;
mips_machtype = MACH_PB1000;
prom_init_cmdline();
add_memory_region(1, 64 << 20, BOOT_MEM_RAM);
memsize_str = prom_getenv("memsize");
if (!memsize_str) {
memsize = 0x04000000;
} else {
memsize = simple_strtol(memsize_str, NULL, 0);
}
add_memory_region(0, memsize, BOOT_MEM_RAM);
return 0;
}
This diff is collapsed.
#
# Copyright 2000,2001 MontaVista Software Inc.
# Author: MontaVista Software, Inc.
# ppopov@mvista.com or source@mvista.com
#
# Makefile for the Alchemy Semiconductor Pb1100 board.
#
# 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 := pb1100.o
obj-y := init.o setup.o
/*
*
* BRIEF MODULE DESCRIPTION
* Pb1100 board setup
*
* Copyright 2002 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
int prom_argc;
char **prom_argv, **prom_envp;
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname);
const char *get_system_type(void)
{
return "Alchemy Pb1100";
}
int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = argc;
prom_argv = argv;
prom_envp = envp;
mips_machgroup = MACH_GROUP_ALCHEMY;
mips_machtype = MACH_PB1100;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str) {
memsize = 0x04000000;
} else {
memsize = simple_strtol(memsize_str, NULL, 0);
}
add_memory_region(0, memsize, BOOT_MEM_RAM);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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