parent
1f8f2aaa37
commit
d9a42c5436
@ -0,0 +1,25 @@ |
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk |
||||
|
||||
ARCH:=mipsel
|
||||
BOARD:=adm8668
|
||||
BOARDNAME:=Infineon WildPass ADM8668
|
||||
FEATURES:=squashfs
|
||||
|
||||
LINUX_VERSION:=2.6.36
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk |
||||
DEFAULT_PACKAGES += wpad-mini kmod-rt61-pci
|
||||
# kmod-switch kmod-diag nvram
|
||||
|
||||
define Target/Description |
||||
Build firmware images for Infineon WildPass (ADM8668) based routers
|
||||
(e.g. T-Mobile branded Linksys WRTU54G-TM)
|
||||
endef |
||||
|
||||
$(eval $(call BuildTarget)) |
@ -0,0 +1,3 @@ |
||||
#define Package/base-files/install-target
|
||||
# rm -f $(1)/etc/config/network
|
||||
#endef
|
@ -0,0 +1,16 @@ |
||||
config interface loopback |
||||
option ifname lo |
||||
option proto static |
||||
option ipaddr 127.0.0.1 |
||||
option netmask 255.0.0.0 |
||||
|
||||
config interface lan |
||||
option ifname eth0 |
||||
option type bridge |
||||
option proto static |
||||
option ipaddr 192.168.1.1 |
||||
option netmask 255.255.255.0 |
||||
|
||||
config interface wan |
||||
option ifname eth1 |
||||
option proto dhcp |
@ -0,0 +1,21 @@ |
||||
#!/bin/sh |
||||
# Copyright (C) 2010 OpenWrt.org |
||||
|
||||
set_led() { |
||||
local state="$1" |
||||
[ -f "/proc/adm8668/sesled" ] && echo "$state" > "/proc/adm8668/sesled" |
||||
} |
||||
|
||||
set_state() { |
||||
case "$1" in |
||||
preinit) |
||||
set_led 1 |
||||
;; |
||||
failsafe) |
||||
set_led 2 |
||||
;; |
||||
done) |
||||
set_led 0 |
||||
;; |
||||
esac |
||||
} |
@ -0,0 +1,9 @@ |
||||
#!/bin/sh |
||||
|
||||
init_hotplug_failsafe() { |
||||
echo '/sbin/hotplug.failsafe' > /proc/sys/kernel/hotplug |
||||
} |
||||
|
||||
boot_hook_add preinit_main init_hotplug_failsafe |
||||
|
||||
|
@ -0,0 +1,9 @@ |
||||
#!/bin/sh |
||||
|
||||
set_preinit_ifname() { |
||||
ifname=eth0 |
||||
} |
||||
|
||||
boot_hook_add preinit_main set_preinit_ifname |
||||
|
||||
|
@ -0,0 +1,11 @@ |
||||
#!/bin/sh |
||||
|
||||
failsafe_wait() { |
||||
FAILSAFE= |
||||
grep -q 'SES: UP FLIP' /proc/adm8668/buttons && FAILSAFE=true && export FAILSAFE |
||||
grep -q 'SES: DOWN' /proc/adm8668/buttons && FAILSAFE=true && export FAILSAFE |
||||
if [ "$FAILSAFE" != "true" ]; then |
||||
preinit_net_echo "Please press button now to enter failsafe" |
||||
fs_wait_for_key f 'to enter failsafe mode' $fs_failsafe_wait_timeout && FAILSAFE=true && export FAILSAFE |
||||
fi |
||||
} |
@ -0,0 +1,15 @@ |
||||
PART_NAME=linux |
||||
platform_check_image() { |
||||
[ "$ARGC" -gt 1 ] && return 1 |
||||
|
||||
case "$(get_magic_word "$1")" in |
||||
# u-boot |
||||
2705) return 0;; |
||||
*) |
||||
echo "Invalid image type. Please use only u-boot files" |
||||
return 1 |
||||
;; |
||||
esac |
||||
} |
||||
|
||||
# use default for platform_do_upgrade() |
@ -0,0 +1,4 @@ |
||||
#!/bin/sh |
||||
case "$1" in |
||||
button) kill -USR1 1;; |
||||
esac |
@ -0,0 +1,36 @@ |
||||
CONFIG_ADM8668=y |
||||
CONFIG_CEVT_R4K=y |
||||
CONFIG_CEVT_R4K_LIB=y |
||||
CONFIG_CPU_HAS_PREFETCH=y |
||||
CONFIG_CPU_HAS_SYNC=y |
||||
CONFIG_CPU_LITTLE_ENDIAN=y |
||||
CONFIG_CPU_MIPS32=y |
||||
CONFIG_CPU_MIPS32_R1=y |
||||
CONFIG_CPU_MIPSR1=y |
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y |
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y |
||||
CONFIG_CSRC_R4K=y |
||||
CONFIG_CSRC_R4K_LIB=y |
||||
CONFIG_DECOMPRESS_LZMA=y |
||||
CONFIG_DMA_NONCOHERENT=y |
||||
CONFIG_EEPROM_93CX6=m |
||||
CONFIG_HAS_DMA=y |
||||
CONFIG_HAS_IOMEM=y |
||||
CONFIG_HAS_IOPORT=y |
||||
CONFIG_HW_HAS_PCI=y |
||||
CONFIG_IRQ_CPU=y |
||||
CONFIG_MIPS=y |
||||
CONFIG_MIPS_L1_CACHE_SHIFT=5 |
||||
CONFIG_MIPS_MT_DISABLED=y |
||||
CONFIG_MTD_ADM8668_NOR=y |
||||
CONFIG_NEED_DMA_MAP_STATE=y |
||||
CONFIG_PCI=y |
||||
CONFIG_PCI_DOMAINS=y |
||||
CONFIG_SERIAL_ADM8668=y |
||||
CONFIG_SERIAL_ADM8668_CONSOLE=y |
||||
CONFIG_SWAP_IO_SPACE=y |
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y |
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y |
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y |
||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y |
||||
CONFIG_ZONE_DMA_FLAG=0 |
@ -0,0 +1,5 @@ |
||||
#
|
||||
# something witty --neutronscott
|
||||
#
|
||||
|
||||
obj-y := irq.o pci.o prom.o platform.o serial.o proc.o net_core.o net_intr.o
|
@ -0,0 +1,6 @@ |
||||
# |
||||
# Infineon ADM8668 WildPass |
||||
# |
||||
platform-$(CONFIG_ADM8668) += adm8668/ |
||||
cflags-$(CONFIG_ADM8668) += -I$(srctree)/arch/mips/include/asm/mach-adm8668 |
||||
load-$(CONFIG_ADM8668) += 0xffffffff80002000 |
@ -0,0 +1,134 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/init.h> |
||||
#include <linux/kernel_stat.h> |
||||
#include <linux/signal.h> |
||||
#include <linux/sched.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/random.h> |
||||
#include <linux/pm.h> |
||||
#include <linux/irq.h> |
||||
#include <asm/mipsregs.h> |
||||
#include <asm/irq_cpu.h> |
||||
#include <asm/irq.h> |
||||
#include <adm8668.h> |
||||
|
||||
|
||||
void enable_adm8668_irq(unsigned int irq); |
||||
void disable_adm8668_irq(unsigned int irq); |
||||
void adm8668_irq_cascade(void); |
||||
|
||||
void plat_irq_dispatch(void) |
||||
{ |
||||
unsigned int pending; |
||||
|
||||
pending = read_c0_cause() & read_c0_status() & ST0_IM; |
||||
|
||||
/* timer interrupt, that we renumbered */ |
||||
if (pending & STATUSF_IP7) |
||||
do_IRQ(MIPS_CPU_IRQ_BASE + 7); |
||||
if (pending & STATUSF_IP2) |
||||
adm8668_irq_cascade(); |
||||
} |
||||
|
||||
/*
|
||||
* System irq dispatch |
||||
*/ |
||||
void adm8668_irq_cascade() |
||||
{ |
||||
int i; |
||||
unsigned long intsrc; |
||||
|
||||
intsrc = ADM8668_INTC_REG(IRQ_STATUS_REG) & IRQ_MASK; |
||||
for (i = 0; intsrc; intsrc >>= 1, i++) |
||||
if (intsrc & 0x1) |
||||
do_IRQ(i); |
||||
} |
||||
|
||||
/*
|
||||
* irq enable |
||||
*/ |
||||
static __inline void _irq_enable(int irql) |
||||
{ |
||||
ADM8668_INTC_REG(IRQ_ENABLE_REG) = (1 << irql); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* irq disable |
||||
*/ |
||||
static __inline void _irq_disable(int irql) |
||||
{ |
||||
ADM8668_INTC_REG(IRQ_DISABLE_REG) = (1 << irql); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* enable 8668 irq |
||||
*/ |
||||
void enable_adm8668_irq(unsigned int irq) |
||||
{ |
||||
if ((irq < 0) || (irq > NR_IRQS)) |
||||
return; |
||||
|
||||
_irq_enable(irq); |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* disable 8668 irq |
||||
*/ |
||||
void disable_adm8668_irq(unsigned int irq) |
||||
{ |
||||
if ((irq < 0) || (irq > NR_IRQS)) |
||||
return; |
||||
|
||||
_irq_disable(irq); |
||||
} |
||||
|
||||
static inline void ack_adm8668_irq(unsigned int irq_nr) |
||||
{ |
||||
ADM8668_INTC_REG(IRQ_DISABLE_REG) = (1 << irq_nr); |
||||
} |
||||
|
||||
/*
|
||||
* system irq type |
||||
*/ |
||||
|
||||
static struct irq_chip adm8668_irq_type = { |
||||
.name = "adm8668", |
||||
.ack = ack_adm8668_irq, |
||||
.mask = disable_adm8668_irq, |
||||
.unmask = enable_adm8668_irq |
||||
}; |
||||
|
||||
/*
|
||||
* irq init |
||||
*/ |
||||
void __init init_adm8668_irqs(void) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i <= INT_LVL_MAX; i++) |
||||
set_irq_chip_and_handler(i, &adm8668_irq_type, |
||||
handle_level_irq); |
||||
|
||||
/* hw0 is where our interrupts are uh.. interrupted at. */ |
||||
set_c0_status(IE_IRQ0); |
||||
} |
||||
|
||||
/*
|
||||
* system init |
||||
*/ |
||||
void __init arch_init_irq(void) |
||||
{ |
||||
mips_cpu_irq_init(); |
||||
init_adm8668_irqs(); |
||||
} |
@ -0,0 +1,276 @@ |
||||
/*
|
||||
* originally drivers/net/tulip/tulip.h |
||||
* Copyright 2000,2001 The Linux Kernel Team |
||||
* Written/copyright 1994-2001 by Donald Becker. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef __NET_TULIP_H__ |
||||
#define __NET_TULIP_H__ |
||||
|
||||
#include <linux/module.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/init.h> |
||||
#include <linux/mii.h> |
||||
#include <linux/crc32.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/types.h> |
||||
#include <linux/spinlock.h> |
||||
#include <linux/netdevice.h> |
||||
#include <linux/ethtool.h> |
||||
#include <linux/timer.h> |
||||
#include <linux/delay.h> |
||||
#include <linux/etherdevice.h> |
||||
#include <linux/platform_device.h> |
||||
#include <asm/unaligned.h> |
||||
#include <asm/uaccess.h> |
||||
#include <asm/io.h> |
||||
#include <asm/irq.h> |
||||
|
||||
/* undefine, or define to various debugging levels (>4 == obscene levels) */ |
||||
#define TULIP_DEBUG 1 |
||||
#define VALID_INTR 0x0001a451 |
||||
#define ADM8668_WAN_IRQ 8 |
||||
#define ADM8668_LAN_IRQ 7 |
||||
#define ADM8668_WAN_MACADDR 0xb00205ac |
||||
#define ADM8668_LAN_MACADDR 0xb0020404 |
||||
|
||||
/* Offsets to the Command and Status Registers, "CSRs". All accesses
|
||||
must be longword instructions and quadword aligned. */ |
||||
enum tulip_offsets { |
||||
CSR0 = 0, |
||||
CSR1 = 0x08, |
||||
CSR2 = 0x10, |
||||
CSR3 = 0x18, |
||||
CSR4 = 0x20, |
||||
CSR5 = 0x28, |
||||
CSR6 = 0x30, |
||||
CSR7 = 0x38, |
||||
CSR8 = 0x40, |
||||
CSR9 = 0x48, |
||||
CSR10 = 0x50, |
||||
CSR11 = 0x58, |
||||
CSR12 = 0x60, |
||||
CSR13 = 0x68, |
||||
CSR14 = 0x70, |
||||
CSR15 = 0x78, |
||||
CSR18 = 0x88, |
||||
CSR19 = 0x8c, |
||||
CSR20 = 0x90, |
||||
CSR27 = 0xAC, |
||||
CSR28 = 0xB0, |
||||
}; |
||||
|
||||
#define RxPollInt (RxIntr|RxNoBuf|RxDied|RxJabber) |
||||
|
||||
/* The bits in the CSR5 status registers, mostly interrupt sources. */ |
||||
enum status_bits { |
||||
TimerInt = 0x800, |
||||
SystemError = 0x2000, |
||||
TPLnkFail = 0x1000, |
||||
TPLnkPass = 0x10, |
||||
NormalIntr = 0x10000, |
||||
AbnormalIntr = 0x8000, |
||||
RxJabber = 0x200, |
||||
RxDied = 0x100, |
||||
RxNoBuf = 0x80, |
||||
RxIntr = 0x40, |
||||
TxFIFOUnderflow = 0x20, |
||||
RxErrIntr = 0x10, |
||||
TxJabber = 0x08, |
||||
TxNoBuf = 0x04, |
||||
TxDied = 0x02, |
||||
TxIntr = 0x01, |
||||
}; |
||||
|
||||
/* bit mask for CSR5 TX/RX process state */ |
||||
#define CSR5_TS 0x00700000 |
||||
#define CSR5_RS 0x000e0000 |
||||
|
||||
enum tulip_mode_bits { |
||||
TxThreshold = (1 << 22), |
||||
FullDuplex = (1 << 9), |
||||
TxOn = 0x2000, |
||||
AcceptBroadcast = 0x0100, |
||||
AcceptAllMulticast = 0x0080, |
||||
AcceptAllPhys = 0x0040, |
||||
AcceptRunt = 0x0008, |
||||
RxOn = 0x0002, |
||||
RxTx = (TxOn | RxOn), |
||||
}; |
||||
|
||||
/* The Tulip Rx and Tx buffer descriptors. */ |
||||
struct tulip_rx_desc { |
||||
__le32 status; |
||||
__le32 length; |
||||
__le32 buffer1; |
||||
__le32 buffer2; |
||||
}; |
||||
|
||||
struct tulip_tx_desc { |
||||
__le32 status; |
||||
__le32 length; |
||||
__le32 buffer1; |
||||
__le32 buffer2; /* We use only buffer 1. */ |
||||
}; |
||||
|
||||
enum desc_status_bits { |
||||
DescOwned = 0x80000000, |
||||
DescWholePkt = 0x60000000, |
||||
DescEndPkt = 0x40000000, |
||||
DescStartPkt = 0x20000000, |
||||
DescEndRing = 0x02000000, |
||||
DescUseLink = 0x01000000, |
||||
|
||||
/*
|
||||
* Error summary flag is logical or of 'CRC Error', 'Collision Seen', |
||||
* 'Frame Too Long', 'Runt' and 'Descriptor Error' flags generated |
||||
* within tulip chip. |
||||
*/ |
||||
RxDescErrorSummary = 0x8000, |
||||
RxDescCRCError = 0x0002, |
||||
RxDescCollisionSeen = 0x0040, |
||||
|
||||
/*
|
||||
* 'Frame Too Long' flag is set if packet length including CRC exceeds |
||||
* 1518. However, a full sized VLAN tagged frame is 1522 bytes |
||||
* including CRC. |
||||
* |
||||
* The tulip chip does not block oversized frames, and if this flag is |
||||
* set on a receive descriptor it does not indicate the frame has been |
||||
* truncated. The receive descriptor also includes the actual length. |
||||
* Therefore we can safety ignore this flag and check the length |
||||
* ourselves. |
||||
*/ |
||||
RxDescFrameTooLong = 0x0080, |
||||
RxDescRunt = 0x0800, |
||||
RxDescDescErr = 0x4000, |
||||
RxWholePkt = 0x00000300, |
||||
/*
|
||||
* Top three bits of 14 bit frame length (status bits 27-29) should |
||||
* never be set as that would make frame over 2047 bytes. The Receive |
||||
* Watchdog flag (bit 4) may indicate the length is over 2048 and the |
||||
* length field is invalid. |
||||
*/ |
||||
RxLengthOver2047 = 0x38000010 |
||||
}; |
||||
|
||||
/* Keep the ring sizes a power of two for efficiency.
|
||||
Making the Tx ring too large decreases the effectiveness of channel |
||||
bonding and packet priority. |
||||
There are no ill effects from too-large receive rings. */ |
||||
|
||||
#define TX_RING_SIZE 32 |
||||
#define RX_RING_SIZE 128 |
||||
|
||||
/* The receiver on the DC21143 rev 65 can fail to close the last
|
||||
* receive descriptor in certain circumstances (see errata) when |
||||
* using MWI. This can only occur if the receive buffer ends on |
||||
* a cache line boundary, so the "+ 4" below ensures it doesn't. |
||||
*/ |
||||
#define PKT_BUF_SZ (1536 + 4) /* Size of each temporary Rx buffer. */ |
||||
|
||||
/* Ring-wrap flag in length field, use for last ring entry.
|
||||
0x01000000 means chain on buffer2 address, |
||||
0x02000000 means use the ring start address in CSR2/3. |
||||
Note: Some work-alike chips do not function correctly in chained mode. |
||||
The ASIX chip works only in chained mode. |
||||
Thus we indicates ring mode, but always write the 'next' field for |
||||
chained mode as well. |
||||
*/ |
||||
#define DESC_RING_WRAP 0x02000000 |
||||
|
||||
struct ring_info { |
||||
struct sk_buff *skb; |
||||
dma_addr_t mapping; |
||||
}; |
||||
|
||||
struct tulip_private { |
||||
struct tulip_rx_desc *rx_ring; |
||||
struct tulip_tx_desc *tx_ring; |
||||
dma_addr_t rx_ring_dma; |
||||
dma_addr_t tx_ring_dma; |
||||
/* The saved address of a sent-in-place packet/buffer, for skfree(). */ |
||||
struct ring_info tx_buffers[TX_RING_SIZE]; |
||||
/* The addresses of receive-in-place skbuffs. */ |
||||
struct ring_info rx_buffers[RX_RING_SIZE]; |
||||
struct napi_struct napi; |
||||
struct net_device_stats stats; |
||||
struct timer_list oom_timer; /* Out of memory timer. */ |
||||
u32 mc_filter[2]; |
||||
spinlock_t lock; |
||||
unsigned int cur_rx, cur_tx; /* The next free ring entry */ |
||||
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ |
||||
unsigned int csr0; /* CSR0 setting. */ |
||||
unsigned int csr6; /* Current CSR6 control settings. */ |
||||
void (*link_change) (struct net_device * dev, int csr5); |
||||
struct platform_device *pdev; |
||||
unsigned long nir; |
||||
void __iomem *base_addr; |
||||
int pad0; /* Used for 8-byte alignment */ |
||||
struct net_device *dev; |
||||
}; |
||||
|
||||
|
||||
/* interrupt.c */ |
||||
irqreturn_t tulip_interrupt(int irq, void *dev_instance); |
||||
int tulip_refill_rx(struct net_device *dev); |
||||
int tulip_poll(struct napi_struct *napi, int budget); |
||||
|
||||
/* tulip_core.c */ |
||||
extern int tulip_debug; |
||||
void oom_timer(unsigned long data); |
||||
|
||||
static inline void tulip_start_rxtx(struct tulip_private *tp) |
||||
{ |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
iowrite32(tp->csr6 | RxTx, ioaddr + CSR6); |
||||
barrier(); |
||||
(void) ioread32(ioaddr + CSR6); /* mmio sync */ |
||||
} |
||||
|
||||
static inline void tulip_stop_rxtx(struct tulip_private *tp) |
||||
{ |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
u32 csr6 = ioread32(ioaddr + CSR6); |
||||
|
||||
if (csr6 & RxTx) { |
||||
unsigned i=1300/10; |
||||
iowrite32(csr6 & ~RxTx, ioaddr + CSR6); |
||||
barrier(); |
||||
/* wait until in-flight frame completes.
|
||||
* Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) |
||||
* Typically expect this loop to end in < 50 us on 100BT. |
||||
*/ |
||||
while (--i && (ioread32(ioaddr + CSR5) & (CSR5_TS|CSR5_RS))) |
||||
udelay(10); |
||||
|
||||
if (!i) |
||||
printk(KERN_DEBUG "fixme: tulip_stop_rxtx() failed" |
||||
" (CSR5 0x%x CSR6 0x%x)\n", |
||||
ioread32(ioaddr + CSR5), |
||||
ioread32(ioaddr + CSR6)); |
||||
} |
||||
} |
||||
|
||||
static inline void tulip_restart_rxtx(struct tulip_private *tp) |
||||
{ |
||||
tulip_stop_rxtx(tp); |
||||
udelay(5); |
||||
tulip_start_rxtx(tp); |
||||
} |
||||
|
||||
static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __iomem *ioaddr) |
||||
{ |
||||
/* Stop and restart the chip's Tx processes. */ |
||||
tulip_restart_rxtx(tp); |
||||
/* Trigger an immediate transmit demand. */ |
||||
iowrite32(0, ioaddr + CSR1); |
||||
|
||||
tp->stats.tx_errors++; |
||||
} |
||||
|
||||
#endif /* __NET_TULIP_H__ */ |
@ -0,0 +1,617 @@ |
||||
/*
|
||||
* originally drivers/net/tulip_core.c |
||||
* Copyright 2000,2001 The Linux Kernel Team |
||||
* Written/copyright 1994-2001 by Donald Becker. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#define DRV_NAME "tulip" |
||||
#define DRV_VERSION "1.1.15-NAPI" /* Keep at least for test */ |
||||
#define DRV_RELDATE "Feb 27, 2007" |
||||
|
||||
#include "net.h" |
||||
|
||||
static char version[] __devinitdata = |
||||
"ADM8668net driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; |
||||
|
||||
#define MAX_UNITS 2 |
||||
|
||||
/*
|
||||
Set the bus performance register. |
||||
Typical: Set 16 longword cache alignment, no burst limit. |
||||
Cache alignment bits 15:14 Burst length 13:8 |
||||
0000 No alignment 0x00000000 unlimited 0800 8 longwords |
||||
4000 8 longwords 0100 1 longword 1000 16 longwords |
||||
8000 16 longwords 0200 2 longwords 2000 32 longwords |
||||
C000 32 longwords 0400 4 longwords |
||||
Warning: many older 486 systems are broken and require setting 0x00A04800 |
||||
8 longword cache alignment, 8 longword burst. |
||||
ToDo: Non-Intel setting could be better. |
||||
*/ |
||||
|
||||
//static int csr0 = 0x00200000 | 0x4000;
|
||||
static int csr0 = 0; |
||||
|
||||
/* Operational parameters that usually are not changed. */ |
||||
/* Time in jiffies before concluding the transmitter is hung. */ |
||||
#define TX_TIMEOUT (4*HZ) |
||||
|
||||
MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>"); |
||||
MODULE_DESCRIPTION("ADM8668 new ethernet driver."); |
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_VERSION(DRV_VERSION); |
||||
|
||||
#ifdef TULIP_DEBUG |
||||
int tulip_debug = TULIP_DEBUG; |
||||
#else |
||||
int tulip_debug = 1; |
||||
#endif |
||||
|
||||
static void tulip_tx_timeout(struct net_device *dev); |
||||
static void tulip_init_ring(struct net_device *dev); |
||||
static void tulip_free_ring(struct net_device *dev); |
||||
static netdev_tx_t tulip_start_xmit(struct sk_buff *skb, |
||||
struct net_device *dev); |
||||
static int tulip_open(struct net_device *dev); |
||||
static int tulip_close(struct net_device *dev); |
||||
static void tulip_up(struct net_device *dev); |
||||
static void tulip_down(struct net_device *dev); |
||||
static struct net_device_stats *tulip_get_stats(struct net_device *dev); |
||||
//static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
static void set_rx_mode(struct net_device *dev); |
||||
#ifdef CONFIG_NET_POLL_CONTROLLER |
||||
static void poll_tulip(struct net_device *dev); |
||||
#endif |
||||
|
||||
static void tulip_up(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
|
||||
napi_enable(&tp->napi); |
||||
|
||||
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ |
||||
iowrite32(0x00000001, ioaddr + CSR0); |
||||
|
||||
/* Deassert reset.
|
||||
Wait the specified 50 PCI cycles after a reset by initializing |
||||
Tx and Rx queues and the address filter list. */ |
||||
iowrite32(tp->csr0, ioaddr + CSR0); |
||||
|
||||
if (tulip_debug > 1) |
||||
printk(KERN_DEBUG "%s: tulip_up(), irq==%d\n", |
||||
dev->name, dev->irq); |
||||
|
||||
iowrite32(tp->rx_ring_dma, ioaddr + CSR3); |
||||
iowrite32(tp->tx_ring_dma, ioaddr + CSR4); |
||||
tp->cur_rx = tp->cur_tx = 0; |
||||
tp->dirty_rx = tp->dirty_tx = 0; |
||||
|
||||
/* set mac address */ |
||||
iowrite32(get_unaligned_le32(dev->dev_addr), ioaddr + 0xA4); |
||||
iowrite32(get_unaligned_le16(dev->dev_addr + 4), ioaddr + 0xA8); |
||||
iowrite32(0, ioaddr + CSR27); |
||||
iowrite32(0, ioaddr + CSR28); |
||||
|
||||
tp->csr6 = 0; |
||||
|
||||
/* Enable automatic Tx underrun recovery. */ |
||||
iowrite32(ioread32(ioaddr + CSR18) | 1, ioaddr + CSR18); |
||||
tp->csr6 = 0x00040000; |
||||
|
||||
/* Start the chip's Tx to process setup frame. */ |
||||
tulip_stop_rxtx(tp); |
||||
barrier(); |
||||
udelay(5); |
||||
iowrite32(tp->csr6 | TxOn, ioaddr + CSR6); |
||||
|
||||
/* Enable interrupts by setting the interrupt mask. */ |
||||
iowrite32(VALID_INTR, ioaddr + CSR5); |
||||
iowrite32(VALID_INTR, ioaddr + CSR7); |
||||
tulip_start_rxtx(tp); |
||||
iowrite32(0, ioaddr + CSR2); /* Rx poll demand */ |
||||
|
||||
if (tulip_debug > 2) { |
||||
printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n", |
||||
dev->name, ioread32(ioaddr + CSR0), |
||||
ioread32(ioaddr + CSR5), |
||||
ioread32(ioaddr + CSR6)); |
||||
} |
||||
|
||||
init_timer(&tp->oom_timer); |
||||
tp->oom_timer.data = (unsigned long)dev; |
||||
tp->oom_timer.function = oom_timer; |
||||
} |
||||
|
||||
static int |
||||
tulip_open(struct net_device *dev) |
||||
{ |
||||
int retval; |
||||
|
||||
tulip_init_ring (dev); |
||||
|
||||
retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev); |
||||
if (retval) |
||||
goto free_ring; |
||||
|
||||
tulip_up (dev); |
||||
|
||||
netif_start_queue (dev); |
||||
|
||||
return 0; |
||||
|
||||
free_ring: |
||||
tulip_free_ring (dev); |
||||
return retval; |
||||
} |
||||
|
||||
|
||||
static void tulip_tx_timeout(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave (&tp->lock, flags); |
||||
|
||||
dev_warn(&dev->dev, |
||||
"Transmit timed out, status %08x, CSR12 %08x, resetting...\n", |
||||
ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12)); |
||||
|
||||
tulip_tx_timeout_complete(tp, ioaddr); |
||||
|
||||
spin_unlock_irqrestore (&tp->lock, flags); |
||||
dev->trans_start = jiffies; /* prevent tx timeout */ |
||||
netif_wake_queue (dev); |
||||
} |
||||
|
||||
|
||||
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ |
||||
static void tulip_init_ring(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
int i; |
||||
|
||||
tp->nir = 0; |
||||
|
||||
for (i = 0; i < RX_RING_SIZE; i++) { |
||||
tp->rx_ring[i].status = 0x00000000; |
||||
tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ); |
||||
tp->rx_ring[i].buffer2 = cpu_to_le32(tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * (i + 1)); |
||||
tp->rx_buffers[i].skb = NULL; |
||||
tp->rx_buffers[i].mapping = 0; |
||||
} |
||||
/* Mark the last entry as wrapping the ring. */ |
||||
tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP); |
||||
tp->rx_ring[i-1].buffer2 = cpu_to_le32(tp->rx_ring_dma); |
||||
|
||||
for (i = 0; i < RX_RING_SIZE; i++) { |
||||
dma_addr_t mapping; |
||||
/* Note the receive buffer must be longword aligned.
|
||||
dev_alloc_skb() provides 16 byte alignment. But do *not* |
||||
use skb_reserve() to align the IP header! */ |
||||
struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); |
||||
tp->rx_buffers[i].skb = skb; |
||||
if (skb == NULL) |
||||
break; |
||||
mapping = dma_map_single(&dev->dev, skb->data, |
||||
PKT_BUF_SZ, DMA_FROM_DEVICE); |
||||
tp->rx_buffers[i].mapping = mapping; |
||||
skb->dev = dev; /* Mark as being used by this device. */ |
||||
tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */ |
||||
tp->rx_ring[i].buffer1 = cpu_to_le32(mapping); |
||||
} |
||||
tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); |
||||
|
||||
/* The Tx buffer descriptor is filled in as needed, but we
|
||||
do need to clear the ownership bit. */ |
||||
for (i = 0; i < TX_RING_SIZE; i++) { |
||||
tp->tx_buffers[i].skb = NULL; |
||||
tp->tx_buffers[i].mapping = 0; |
||||
tp->tx_ring[i].status = 0x00000000; |
||||
tp->tx_ring[i].buffer2 = cpu_to_le32(tp->tx_ring_dma + sizeof(struct tulip_tx_desc) * (i + 1)); |
||||
} |
||||
tp->tx_ring[i-1].buffer2 = cpu_to_le32(tp->tx_ring_dma); |
||||
} |
||||
|
||||
static netdev_tx_t |
||||
tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
int entry; |
||||
u32 flag; |
||||
dma_addr_t mapping; |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&tp->lock, flags); |
||||
|
||||
/* Calculate the next Tx descriptor entry. */ |
||||
entry = tp->cur_tx % TX_RING_SIZE; |
||||
|
||||
tp->tx_buffers[entry].skb = skb; |
||||
mapping = dma_map_single(&tp->pdev->dev, skb->data, skb->len, |
||||
DMA_TO_DEVICE); |
||||
tp->tx_buffers[entry].mapping = mapping; |
||||
tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping); |
||||
|
||||
if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ |
||||
flag = 0x60000000; /* No interrupt */ |
||||
} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) { |
||||
flag = 0xe0000000; /* Tx-done intr. */ |
||||
} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { |
||||
flag = 0x60000000; /* No Tx-done intr. */ |
||||
} else { /* Leave room for set_rx_mode() to fill entries. */ |
||||
flag = 0xe0000000; /* Tx-done intr. */ |
||||
netif_stop_queue(dev); |
||||
} |
||||
if (entry == TX_RING_SIZE-1) |
||||
flag = 0xe0000000 | DESC_RING_WRAP; |
||||
|
||||
tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); |
||||
/* if we were using Transmit Automatic Polling, we would need a
|
||||
* wmb() here. */ |
||||
tp->tx_ring[entry].status = cpu_to_le32(DescOwned); |
||||
wmb(); |
||||
|
||||
tp->cur_tx++; |
||||
|
||||
/* Trigger an immediate transmit demand. */ |
||||
iowrite32(0, tp->base_addr + CSR1); |
||||
|
||||
spin_unlock_irqrestore(&tp->lock, flags); |
||||
|
||||
return NETDEV_TX_OK; |
||||
} |
||||
|
||||
static void tulip_clean_tx_ring(struct tulip_private *tp) |
||||
{ |
||||
unsigned int dirty_tx; |
||||
|
||||
for (dirty_tx = tp->dirty_tx ; tp->cur_tx - dirty_tx > 0; |
||||
dirty_tx++) { |
||||
int entry = dirty_tx % TX_RING_SIZE; |
||||
int status = le32_to_cpu(tp->tx_ring[entry].status); |
||||
|
||||
if (status < 0) { |
||||
tp->stats.tx_errors++; /* It wasn't Txed */ |
||||
tp->tx_ring[entry].status = 0; |
||||
} |
||||
|
||||
dma_unmap_single(&tp->pdev->dev, tp->tx_buffers[entry].mapping, |
||||
tp->tx_buffers[entry].skb->len, |
||||
DMA_TO_DEVICE); |
||||
|
||||
/* Free the original skb. */ |
||||
dev_kfree_skb_irq(tp->tx_buffers[entry].skb); |
||||
tp->tx_buffers[entry].skb = NULL; |
||||
tp->tx_buffers[entry].mapping = 0; |
||||
} |
||||
} |
||||
|
||||
static void tulip_down (struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
unsigned long flags; |
||||
|
||||
napi_disable(&tp->napi); |
||||
del_timer_sync (&tp->oom_timer); |
||||
spin_lock_irqsave (&tp->lock, flags); |
||||
|
||||
/* Disable interrupts by clearing the interrupt mask. */ |
||||
iowrite32 (0x00000000, ioaddr + CSR7); |
||||
|
||||
/* Stop the Tx and Rx processes. */ |
||||
tulip_stop_rxtx(tp); |
||||
|
||||
/* prepare receive buffers */ |
||||
tulip_refill_rx(dev); |
||||
|
||||
/* release any unconsumed transmit buffers */ |
||||
tulip_clean_tx_ring(tp); |
||||
|
||||
if (ioread32 (ioaddr + CSR6) != 0xffffffff) |
||||
tp->stats.rx_missed_errors += ioread32 (ioaddr + CSR8) & 0xffff; |
||||
|
||||
spin_unlock_irqrestore (&tp->lock, flags); |
||||
} |
||||
|
||||
static void tulip_free_ring (struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
int i; |
||||
|
||||
/* Free all the skbuffs in the Rx queue. */ |
||||
for (i = 0; i < RX_RING_SIZE; i++) { |
||||
struct sk_buff *skb = tp->rx_buffers[i].skb; |
||||
dma_addr_t mapping = tp->rx_buffers[i].mapping; |
||||
|
||||
tp->rx_buffers[i].skb = NULL; |
||||
tp->rx_buffers[i].mapping = 0; |
||||
|
||||
tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */ |
||||
tp->rx_ring[i].length = 0; |
||||
/* An invalid address. */ |
||||
tp->rx_ring[i].buffer1 = cpu_to_le32(0xBADF00D0); |
||||
if (skb) { |
||||
dma_unmap_single(&tp->pdev->dev, mapping, PKT_BUF_SZ, |
||||
DMA_FROM_DEVICE); |
||||
dev_kfree_skb (skb); |
||||
} |
||||
} |
||||
|
||||
for (i = 0; i < TX_RING_SIZE; i++) { |
||||
struct sk_buff *skb = tp->tx_buffers[i].skb; |
||||
|
||||
if (skb != NULL) { |
||||
dma_unmap_single(&tp->pdev->dev, |
||||
tp->tx_buffers[i].mapping, skb->len, DMA_TO_DEVICE); |
||||
dev_kfree_skb (skb); |
||||
} |
||||
tp->tx_buffers[i].skb = NULL; |
||||
tp->tx_buffers[i].mapping = 0; |
||||
} |
||||
} |
||||
|
||||
static int tulip_close (struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
|
||||
netif_stop_queue (dev); |
||||
|
||||
tulip_down (dev); |
||||
|
||||
if (tulip_debug > 1) |
||||
dev_printk(KERN_DEBUG, &dev->dev, |
||||
"Shutting down ethercard, status was %02x\n", |
||||
ioread32 (ioaddr + CSR5)); |
||||
|
||||
free_irq (dev->irq, dev); |
||||
|
||||
tulip_free_ring (dev); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static struct net_device_stats *tulip_get_stats(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
|
||||
if (netif_running(dev)) { |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave (&tp->lock, flags); |
||||
|
||||
tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; |
||||
|
||||
spin_unlock_irqrestore(&tp->lock, flags); |
||||
} |
||||
|
||||
return &tp->stats; |
||||
} |
||||
|
||||
|
||||
static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
||||
{ |
||||
strcpy(info->driver, DRV_NAME); |
||||
strcpy(info->version, DRV_VERSION); |
||||
strcpy(info->bus_info, "mmio"); |
||||
} |
||||
|
||||
static const struct ethtool_ops ops = { |
||||
.get_drvinfo = tulip_get_drvinfo |
||||
}; |
||||
|
||||
static void set_rx_mode(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
int csr6; |
||||
|
||||
csr6 = ioread32(ioaddr + CSR6) & ~0x00D5; |
||||
|
||||
tp->csr6 &= ~0x00D5; |
||||
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ |
||||
tp->csr6 |= AcceptAllMulticast | AcceptAllPhys; |
||||
csr6 |= AcceptAllMulticast | AcceptAllPhys; |
||||
} else if ((netdev_mc_count(dev) > 1000) || |
||||
(dev->flags & IFF_ALLMULTI)) { |
||||
/* Too many to filter well -- accept all multicasts. */ |
||||
tp->csr6 |= AcceptAllMulticast; |
||||
csr6 |= AcceptAllMulticast; |
||||
} else { |
||||
/* Some work-alikes have only a 64-entry hash filter table. */ |
||||
/* Should verify correctness on big-endian/__powerpc__ */ |
||||
struct netdev_hw_addr *ha; |
||||
if (netdev_mc_count(dev) > 64) { |
||||
/* Arbitrary non-effective limit. */ |
||||
tp->csr6 |= AcceptAllMulticast; |
||||
csr6 |= AcceptAllMulticast; |
||||
} else { |
||||
u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ |
||||
int filterbit; |
||||
netdev_for_each_mc_addr(ha, dev) { |
||||
filterbit = ether_crc_le(ETH_ALEN, ha->addr); |
||||
filterbit &= 0x3f; |
||||
mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); |
||||
if (tulip_debug > 2) |
||||
dev_info(&dev->dev, |
||||
"Added filter for %pM %08x bit %d\n", |
||||
ha->addr, |
||||
ether_crc(ETH_ALEN, ha->addr), |
||||
filterbit); |
||||
} |
||||
if (mc_filter[0] == tp->mc_filter[0] && |
||||
mc_filter[1] == tp->mc_filter[1]) |
||||
; /* No change. */ |
||||
iowrite32(mc_filter[0], ioaddr + CSR27); |
||||
iowrite32(mc_filter[1], ioaddr + CSR28); |
||||
tp->mc_filter[0] = mc_filter[0]; |
||||
tp->mc_filter[1] = mc_filter[1]; |
||||
} |
||||
} |
||||
|
||||
if (dev->irq == ADM8668_LAN_IRQ) |
||||
csr6 |= (1 << 9); /* force 100Mbps full duplex */ |
||||
// csr6 |= 1; /* pad 2 bytes. vlan? */
|
||||
|
||||
iowrite32(csr6, ioaddr + CSR6); |
||||
} |
||||
|
||||
static const struct net_device_ops tulip_netdev_ops = { |
||||
.ndo_open = tulip_open, |
||||
.ndo_start_xmit = tulip_start_xmit, |
||||
.ndo_tx_timeout = tulip_tx_timeout, |
||||
.ndo_stop = tulip_close, |
||||
.ndo_get_stats = tulip_get_stats, |
||||
.ndo_set_multicast_list = set_rx_mode, |
||||
.ndo_change_mtu = eth_change_mtu, |
||||
.ndo_set_mac_address = eth_mac_addr, |
||||
.ndo_validate_addr = eth_validate_addr, |
||||
#ifdef CONFIG_NET_POLL_CONTROLLER |
||||
.ndo_poll_controller = poll_tulip, |
||||
#endif |
||||
}; |
||||
|
||||
static int __devinit adm8668net_probe(struct platform_device *pdev) |
||||
{ |
||||
struct tulip_private *tp; |
||||
struct net_device *dev; |
||||
struct resource *res; |
||||
void __iomem *ioaddr; |
||||
int irq; |
||||
|
||||
if (pdev->id < 0 || pdev->id >= MAX_UNITS) |
||||
return -EINVAL; |
||||
|
||||
if (!(res = platform_get_resource(pdev, IORESOURCE_IRQ, 0))) |
||||
return -ENODEV; |
||||
irq = res->start; |
||||
if (!(res = platform_get_resource(pdev, IORESOURCE_MEM, 0))) |
||||
return -ENODEV; |
||||
if (!(ioaddr = ioremap(res->start, res->end - res->start))) |
||||
return -ENODEV; |
||||
if (!(dev = alloc_etherdev(sizeof (*tp)))) |
||||
return -ENOMEM; |
||||
|
||||
/* setup net dev */ |
||||
dev->base_addr = (unsigned long)res->start; |
||||
dev->irq = irq; |
||||
SET_NETDEV_DEV(dev, &pdev->dev); |
||||
|
||||
/* tulip private struct */ |
||||
tp = netdev_priv(dev); |
||||
tp->dev = dev; |
||||
tp->base_addr = ioaddr; |
||||
tp->csr0 = csr0; |
||||
tp->rx_ring = dma_alloc_coherent(&pdev->dev, |
||||
sizeof(struct tulip_rx_desc) * RX_RING_SIZE + |
||||
sizeof(struct tulip_tx_desc) * TX_RING_SIZE, |
||||
&tp->rx_ring_dma, GFP_KERNEL); |
||||
if (!tp->rx_ring) |
||||
return -ENODEV; |
||||
tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); |
||||
tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; |
||||
|
||||
spin_lock_init(&tp->lock); |
||||
|
||||
/* Stop the chip's Tx and Rx processes. */ |
||||
tulip_stop_rxtx(tp); |
||||
|
||||
/* Clear the missed-packet counter. */ |
||||
ioread32(ioaddr + CSR8); |
||||
|
||||
/* Addresses are stored in BSP area of NOR flash */ |
||||
if (irq == ADM8668_WAN_IRQ) |
||||
memcpy(dev->dev_addr, (char *)ADM8668_WAN_MACADDR, 6); |
||||
else |
||||
memcpy(dev->dev_addr, (char *)ADM8668_LAN_MACADDR, 6); |
||||
|
||||
/* The Tulip-specific entries in the device structure. */ |
||||
dev->netdev_ops = &tulip_netdev_ops; |
||||
dev->watchdog_timeo = TX_TIMEOUT; |
||||
netif_napi_add(dev, &tp->napi, tulip_poll, 16); |
||||
SET_ETHTOOL_OPS(dev, &ops); |
||||
|
||||
if (register_netdev(dev)) |
||||
goto err_out_free_ring; |
||||
|
||||
dev_info(&dev->dev, |
||||
"ADM8668net at MMIO %#lx %pM, IRQ %d\n", |
||||
(unsigned long)dev->base_addr, dev->dev_addr, irq); |
||||
|
||||
platform_set_drvdata(pdev, dev); |
||||
return 0; |
||||
|
||||
err_out_free_ring: |
||||
dma_free_coherent(&pdev->dev, |
||||
sizeof (struct tulip_rx_desc) * RX_RING_SIZE + |
||||
sizeof (struct tulip_tx_desc) * TX_RING_SIZE, |
||||
tp->rx_ring, tp->rx_ring_dma); |
||||
return -ENODEV; |
||||
} |
||||
|
||||
static int __devexit adm8668net_remove(struct platform_device *pdev) |
||||
{ |
||||
struct net_device *dev = platform_get_drvdata (pdev); |
||||
struct tulip_private *tp; |
||||
|
||||
if (!dev) |
||||
return -ENODEV; |
||||
|
||||
tp = netdev_priv(dev); |
||||
unregister_netdev(dev); |
||||
dma_free_coherent(&pdev->dev, |
||||
sizeof (struct tulip_rx_desc) * RX_RING_SIZE + |
||||
sizeof (struct tulip_tx_desc) * TX_RING_SIZE, |
||||
tp->rx_ring, tp->rx_ring_dma); |
||||
iounmap(tp->base_addr); |
||||
free_netdev(dev); |
||||
platform_set_drvdata(pdev, NULL); |
||||
return 0; |
||||
} |
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER |
||||
/*
|
||||
* Polling 'interrupt' - used by things like netconsole to send skbs |
||||
* without having to re-enable interrupts. It's not called while |
||||
* the interrupt routine is executing. |
||||
*/ |
||||
|
||||
static void poll_tulip (struct net_device *dev) |
||||
{ |
||||
/* disable_irq here is not very nice, but with the lockless
|
||||
interrupt handler we have no other choice. */ |
||||
disable_irq(dev->irq); |
||||
tulip_interrupt(dev->irq, dev); |
||||
enable_irq(dev->irq); |
||||
} |
||||
#endif |
||||
|
||||
static struct platform_driver adm8668net_platform_driver = { |
||||
.probe = adm8668net_probe, |
||||
.remove = __devexit_p(adm8668net_remove), |
||||
.driver = { |
||||
.owner = THIS_MODULE, |
||||
.name = "adm8668_eth" |
||||
}, |
||||
}; |
||||
|
||||
static int __init adm8668net_init(void) |
||||
{ |
||||
pr_info("%s", version); |
||||
return platform_driver_register(&adm8668net_platform_driver); |
||||
} |
||||
|
||||
static void __exit adm8668net_exit(void) |
||||
{ |
||||
platform_driver_unregister(&adm8668net_platform_driver); |
||||
} |
||||
|
||||
module_init(adm8668net_init); |
||||
module_exit(adm8668net_exit); |
@ -0,0 +1,446 @@ |
||||
/*
|
||||
* originally drivers/net/tulip/interrupt.c |
||||
* Copyright 2000,2001 The Linux Kernel Team |
||||
* Written/copyright 1994-2001 by Donald Becker. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include "net.h" |
||||
|
||||
int tulip_refill_rx(struct net_device *dev) |
||||
{ |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
int entry; |
||||
int refilled = 0; |
||||
|
||||
/* Refill the Rx ring buffers. */ |
||||
for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) { |
||||
entry = tp->dirty_rx % RX_RING_SIZE; |
||||
if (tp->rx_buffers[entry].skb == NULL) { |
||||
struct sk_buff *skb; |
||||
dma_addr_t mapping; |
||||
|
||||
skb = tp->rx_buffers[entry].skb = dev_alloc_skb(PKT_BUF_SZ); |
||||
if (skb == NULL) |
||||
break; |
||||
|
||||
mapping = dma_map_single(&dev->dev, skb->data, |
||||
PKT_BUF_SZ, DMA_FROM_DEVICE); |
||||
tp->rx_buffers[entry].mapping = mapping; |
||||
|
||||
skb->dev = dev; /* Mark as being used by this device. */ |
||||
tp->rx_ring[entry].buffer1 = cpu_to_le32(mapping); |
||||
refilled++; |
||||
} |
||||
tp->rx_ring[entry].status = cpu_to_le32(DescOwned); |
||||
} |
||||
return refilled; |
||||
} |
||||
|
||||
void oom_timer(unsigned long data) |
||||
{ |
||||
struct net_device *dev = (struct net_device *)data; |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
napi_schedule(&tp->napi); |
||||
} |
||||
|
||||
int tulip_poll(struct napi_struct *napi, int budget) |
||||
{ |
||||
struct tulip_private *tp = container_of(napi, struct tulip_private, napi); |
||||
struct net_device *dev = tp->dev; |
||||
int entry = tp->cur_rx % RX_RING_SIZE; |
||||
int work_done = 0; |
||||
|
||||
if (tulip_debug > 4) |
||||
printk(KERN_DEBUG " In tulip_rx(), entry %d %08x\n", |
||||
entry, tp->rx_ring[entry].status); |
||||
|
||||
do { |
||||
if (ioread32(tp->base_addr + CSR5) == 0xffffffff) { |
||||
printk(KERN_DEBUG " In tulip_poll(), hardware disappeared\n"); |
||||
break; |
||||
} |
||||
/* Acknowledge current RX interrupt sources. */ |
||||
iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5); |
||||
|
||||
|
||||
/* If we own the next entry, it is a new packet. Send it up. */ |
||||
while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { |
||||
s32 status = le32_to_cpu(tp->rx_ring[entry].status); |
||||
short pkt_len; |
||||
|
||||
if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) |
||||
break; |
||||
|
||||
if (tulip_debug > 5) |
||||
printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %08x\n", |
||||
dev->name, entry, status); |
||||
|
||||
if (++work_done >= budget) |
||||
goto not_done; |
||||
|
||||
/*
|
||||
* Omit the four octet CRC from the length. |
||||
* (May not be considered valid until we have |
||||
* checked status for RxLengthOver2047 bits) |
||||
*/ |
||||
pkt_len = ((status >> 16) & 0x7ff) - 4; |
||||
|
||||
#if 0 |
||||
csr6 = ioread32(tp->base_addr + CSR6); |
||||
if (csr6 & 0x1) |
||||
pkt_len += 2; |
||||
|
||||
#endif |
||||
/*
|
||||
* Maximum pkt_len is 1518 (1514 + vlan header) |
||||
* Anything higher than this is always invalid |
||||
* regardless of RxLengthOver2047 bits |
||||
*/ |
||||
|
||||
if ((status & (RxLengthOver2047 | |
||||
RxDescCRCError | |
||||
RxDescCollisionSeen | |
||||
RxDescRunt | |
||||
RxDescDescErr | |
||||
RxWholePkt)) != RxWholePkt || |
||||
pkt_len > 1518) { |
||||
if ((status & (RxLengthOver2047 | |
||||
RxWholePkt)) != RxWholePkt) { |
||||
/* Ingore earlier buffers. */ |
||||
if ((status & 0xffff) != 0x7fff) { |
||||
if (tulip_debug > 1) |
||||
dev_warn(&dev->dev, |
||||
"Oversized Ethernet frame spanned multiple buffers, status %08x!\n", |
||||
status); |
||||
tp->stats.rx_length_errors++; |
||||
} |
||||
} else { |
||||
/* There was a fatal error. */ |
||||
if (tulip_debug > 2) |
||||
printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", |
||||
dev->name, status); |
||||
tp->stats.rx_errors++; /* end of a packet.*/ |
||||
if (pkt_len > 1518 || |
||||
(status & RxDescRunt)) |
||||
tp->stats.rx_length_errors++; |
||||
|
||||
if (status & 0x0004) tp->stats.rx_frame_errors++; |
||||
if (status & 0x0002) tp->stats.rx_crc_errors++; |
||||
if (status & 0x0001) tp->stats.rx_fifo_errors++; |
||||
} |
||||
} else { |
||||
struct sk_buff *skb = tp->rx_buffers[entry].skb; |
||||
char *temp = skb_put(skb, pkt_len); |
||||
|
||||
#if 0 |
||||
if (csr6 & 1) |
||||
skb_pull(skb, 2); |
||||
#endif |
||||
#ifndef final_version |
||||
if (tp->rx_buffers[entry].mapping != |
||||
le32_to_cpu(tp->rx_ring[entry].buffer1)) { |
||||
dev_err(&dev->dev, |
||||
"Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %08llx %p / %p\n", |
||||
le32_to_cpu(tp->rx_ring[entry].buffer1), |
||||
(unsigned long long)tp->rx_buffers[entry].mapping, |
||||
skb->head, temp); |
||||
} |
||||
#endif |
||||
|
||||
tp->rx_buffers[entry].skb = NULL; |
||||
tp->rx_buffers[entry].mapping = 0; |
||||
skb->protocol = eth_type_trans(skb, dev); |
||||
|
||||
netif_receive_skb(skb); |
||||
|
||||
tp->stats.rx_packets++; |
||||
tp->stats.rx_bytes += pkt_len; |
||||
} |
||||
entry = (++tp->cur_rx) % RX_RING_SIZE; |
||||
if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) |
||||
tulip_refill_rx(dev); |
||||
|
||||
} |
||||
|
||||
/* New ack strategy... irq does not ack Rx any longer
|
||||
hopefully this helps */ |
||||
|
||||
/* Really bad things can happen here... If new packet arrives
|
||||
* and an irq arrives (tx or just due to occasionally unset |
||||
* mask), it will be acked by irq handler, but new thread |
||||
* is not scheduled. It is major hole in design. |
||||
* No idea how to fix this if "playing with fire" will fail |
||||
* tomorrow (night 011029). If it will not fail, we won |
||||
* finally: amount of IO did not increase at all. */ |
||||
} while ((ioread32(tp->base_addr + CSR5) & RxIntr)); |
||||
|
||||
tulip_refill_rx(dev); |
||||
|
||||
/* If RX ring is not full we are out of memory. */ |
||||
if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
||||
goto oom; |
||||
|
||||
/* Remove us from polling list and enable RX intr. */ |
||||
napi_complete(napi); |
||||
iowrite32(VALID_INTR, tp->base_addr+CSR7); |
||||
|
||||
/* The last op happens after poll completion. Which means the following:
|
||||
* 1. it can race with disabling irqs in irq handler |
||||
* 2. it can race with dise/enabling irqs in other poll threads |
||||
* 3. if an irq raised after beginning loop, it will be immediately |
||||
* triggered here. |
||||
* |
||||
* Summarizing: the logic results in some redundant irqs both |
||||
* due to races in masking and due to too late acking of already |
||||
* processed irqs. But it must not result in losing events. |
||||
*/ |
||||
|
||||
return work_done; |
||||
|
||||
not_done: |
||||
if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 || |
||||
tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
||||
tulip_refill_rx(dev); |
||||
|
||||
if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) |
||||
goto oom; |
||||
|
||||
return work_done; |
||||
|
||||
oom: /* Executed with RX ints disabled */ |
||||
|
||||
/* Start timer, stop polling, but do not enable rx interrupts. */ |
||||
mod_timer(&tp->oom_timer, jiffies+1); |
||||
|
||||
/* Think: timer_pending() was an explicit signature of bug.
|
||||
* Timer can be pending now but fired and completed |
||||
* before we did napi_complete(). See? We would lose it. */ |
||||
|
||||
/* remove ourselves from the polling list */ |
||||
napi_complete(napi); |
||||
|
||||
return work_done; |
||||
} |
||||
|
||||
/* The interrupt handler does all of the Rx thread work and cleans up
|
||||
after the Tx thread. */ |
||||
irqreturn_t tulip_interrupt(int irq, void *dev_instance) |
||||
{ |
||||
struct net_device *dev = (struct net_device *)dev_instance; |
||||
struct tulip_private *tp = netdev_priv(dev); |
||||
void __iomem *ioaddr = tp->base_addr; |
||||
int csr5; |
||||
int missed; |
||||
int rx = 0; |
||||
int tx = 0; |
||||
int oi = 0; |
||||
int maxrx = RX_RING_SIZE; |
||||
int maxtx = TX_RING_SIZE; |
||||
int maxoi = TX_RING_SIZE; |
||||
int rxd = 0; |
||||
unsigned int work_count = 25; |
||||
unsigned int handled = 0; |
||||
|
||||
/* Let's see whether the interrupt really is for us */ |
||||
csr5 = ioread32(ioaddr + CSR5); |
||||
|
||||
if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) |
||||
return IRQ_RETVAL(handled); |
||||
|
||||
tp->nir++; |
||||
|
||||
do { |
||||
|
||||
if (!rxd && (csr5 & (RxIntr | RxNoBuf))) { |
||||
rxd++; |
||||
/* Mask RX intrs and add the device to poll list. */ |
||||
iowrite32(VALID_INTR&~RxPollInt, ioaddr + CSR7); |
||||
napi_schedule(&tp->napi); |
||||
|
||||
if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) |
||||
break; |
||||
} |
||||
|
||||
/* Acknowledge the interrupt sources we handle here ASAP
|
||||
the poll function does Rx and RxNoBuf acking */ |
||||
|
||||
iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5); |
||||
|
||||
if (tulip_debug > 4) |
||||
printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x\n", |
||||
dev->name, csr5, ioread32(ioaddr + CSR5)); |
||||
|
||||
|
||||
if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { |
||||
unsigned int dirty_tx; |
||||
|
||||
spin_lock(&tp->lock); |
||||
|
||||
for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; |
||||
dirty_tx++) { |
||||
int entry = dirty_tx % TX_RING_SIZE; |
||||
int status = le32_to_cpu(tp->tx_ring[entry].status); |
||||
|
||||
if (status < 0) |
||||
break; /* It still has not been Txed */ |
||||
|
||||
if (status & 0x8000) { |
||||
/* There was an major error, log it. */ |
||||
#ifndef final_version |
||||
if (tulip_debug > 1) |
||||
printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n", |
||||
dev->name, status); |
||||
#endif |
||||
tp->stats.tx_errors++; |
||||
if (status & 0x4104) tp->stats.tx_aborted_errors++; |
||||
if (status & 0x0C00) tp->stats.tx_carrier_errors++; |
||||
if (status & 0x0200) tp->stats.tx_window_errors++; |
||||
if (status & 0x0002) tp->stats.tx_fifo_errors++; |
||||
if (status & 0x0080) tp->stats.tx_heartbeat_errors++; |
||||
} else { |
||||
tp->stats.tx_bytes += |
||||
tp->tx_buffers[entry].skb->len; |
||||
tp->stats.collisions += (status >> 3) & 15; |
||||
tp->stats.tx_packets++; |
||||
} |
||||
|
||||
dma_unmap_single(&tp->pdev->dev, tp->tx_buffers[entry].mapping, |
||||
tp->tx_buffers[entry].skb->len, DMA_TO_DEVICE); |
||||
/* Free the original skb. */ |
||||
dev_kfree_skb_irq(tp->tx_buffers[entry].skb); |
||||
tp->tx_buffers[entry].skb = NULL; |
||||
tp->tx_buffers[entry].mapping = 0; |
||||
tx++; |
||||
} |
||||
|
||||
#ifndef final_version |
||||
if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { |
||||
dev_err(&dev->dev, |
||||
"Out-of-sync dirty pointer, %d vs. %d\n", |
||||
dirty_tx, tp->cur_tx); |
||||
dirty_tx += TX_RING_SIZE; |
||||
} |
||||
#endif |
||||
|
||||
if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) |
||||
netif_wake_queue(dev); |
||||
|
||||
tp->dirty_tx = dirty_tx; |
||||
if (csr5 & TxDied) { |
||||
if (tulip_debug > 2) |
||||
dev_warn(&dev->dev, |
||||
"The transmitter stopped. CSR5 is %x, CSR6 %x, new CSR6 %x\n", |
||||
csr5, ioread32(ioaddr + CSR6), |
||||
tp->csr6); |
||||
tulip_restart_rxtx(tp); |
||||
} |
||||
spin_unlock(&tp->lock); |
||||
} |
||||
|
||||
/* Log errors. */ |
||||
if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ |
||||
if (csr5 == 0xffffffff) |
||||
break; |
||||
if (csr5 & TxJabber) tp->stats.tx_errors++; |
||||
if (csr5 & TxFIFOUnderflow) { |
||||
if ((tp->csr6 & 0xC000) != 0xC000) |
||||
tp->csr6 += 0x4000; /* Bump up the Tx threshold */ |
||||
else |
||||
tp->csr6 |= 0x00200000; /* Store-n-forward. */ |
||||
/* Restart the transmit process. */ |
||||
tulip_restart_rxtx(tp); |
||||
iowrite32(0, ioaddr + CSR1); |
||||
} |
||||
if (csr5 & (RxDied | RxNoBuf)) { |
||||
iowrite32(tp->mc_filter[0], ioaddr + CSR27); |
||||
iowrite32(tp->mc_filter[1], ioaddr + CSR28); |
||||
} |
||||
if (csr5 & RxDied) { /* Missed a Rx frame. */ |
||||
tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; |
||||
tp->stats.rx_errors++; |
||||
tulip_start_rxtx(tp); |
||||
} |
||||
/*
|
||||
* NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this |
||||
* call is ever done under the spinlock |
||||
*/ |
||||
if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { |
||||
if (tp->link_change) |
||||
(tp->link_change)(dev, csr5); |
||||
} |
||||
if (csr5 & SystemError) { |
||||
int error = (csr5 >> 23) & 7; |
||||
/* oops, we hit a PCI error. The code produced corresponds
|
||||
* to the reason: |
||||
* 0 - parity error |
||||
* 1 - master abort |
||||
* 2 - target abort |
||||
* Note that on parity error, we should do a software reset |
||||
* of the chip to get it back into a sane state (according |
||||
* to the 21142/3 docs that is). |
||||
* -- rmk |
||||
*/ |
||||
dev_err(&dev->dev, |
||||
"(%lu) System Error occurred (%d)\n", |
||||
tp->nir, error); |
||||
} |
||||
/* Clear all error sources, included undocumented ones! */ |
||||
iowrite32(0x0800f7ba, ioaddr + CSR5); |
||||
oi++; |
||||
} |
||||
if (csr5 & TimerInt) { |
||||
|
||||
if (tulip_debug > 2) |
||||
dev_err(&dev->dev, |
||||
"Re-enabling interrupts, %08x\n", |
||||
csr5); |
||||
iowrite32(VALID_INTR, ioaddr + CSR7); |
||||
oi++; |
||||
} |
||||
if (tx > maxtx || rx > maxrx || oi > maxoi) { |
||||
if (tulip_debug > 1) |
||||
dev_warn(&dev->dev, "Too much work during an interrupt, csr5=0x%08x. (%lu) (%d,%d,%d)\n", |
||||
csr5, tp->nir, tx, rx, oi); |
||||
|
||||
/* Acknowledge all interrupt sources. */ |
||||
iowrite32(0x8001ffff, ioaddr + CSR5); |
||||
/* Mask all interrupting sources, set timer to
|
||||
re-enable. */ |
||||
iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); |
||||
iowrite32(0x0012, ioaddr + CSR11); |
||||
break; |
||||
} |
||||
|
||||
work_count--; |
||||
if (work_count == 0) |
||||
break; |
||||
|
||||
csr5 = ioread32(ioaddr + CSR5); |
||||
|
||||
if (rxd) |
||||
csr5 &= ~RxPollInt; |
||||
} while ((csr5 & (TxNoBuf | |
||||
TxDied | |
||||
TxIntr | |
||||
TimerInt | |
||||
/* Abnormal intr. */ |
||||
RxDied | |
||||
TxFIFOUnderflow | |
||||
TxJabber | |
||||
TPLnkFail | |
||||
SystemError )) != 0); |
||||
|
||||
if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) { |
||||
tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; |
||||
} |
||||
|
||||
if (tulip_debug > 4) |
||||
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#04x\n", |
||||
dev->name, ioread32(ioaddr + CSR5)); |
||||
|
||||
return IRQ_HANDLED; |
||||
} |
@ -0,0 +1,171 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/init.h> |
||||
#include <linux/pci.h> |
||||
#include <linux/types.h> |
||||
#include <asm/byteorder.h> |
||||
#include <asm/pci.h> |
||||
#include <adm8668.h> |
||||
|
||||
volatile u32* pci_config_address_reg = (volatile u32*)KSEG1ADDR(PCICFG_BASE); |
||||
volatile u32* pci_config_data_reg = (volatile u32*)KSEG1ADDR(PCIDAT_BASE); |
||||
|
||||
#define PCI_ENABLE 0x80000000 |
||||
#define ADMPCI_IO_BASE 0x12600000 |
||||
#define ADMPCI_IO_SIZE 0x1fffff |
||||
#define ADMPCI_MEM_BASE 0x16000000 |
||||
#define ADMPCI_MEM_SIZE 0x7ffffff |
||||
#define PCI_CMM_IOACC_EN 0x1 |
||||
#define PCI_CMM_MEMACC_EN 0x2 |
||||
#define PCI_CMM_MASTER_EN 0x4 |
||||
#define PCI_CMM_DEF (PCI_CMM_IOACC_EN | PCI_CMM_MEMACC_EN | PCI_CMM_MASTER_EN) |
||||
|
||||
#define PCI_DEF_CACHE_LINE_SZ 0 |
||||
#define PCI_DEF_LATENCY_TIMER 0x20 |
||||
#define PCI_DEF_CACHE_LATENCY ((PCI_DEF_LATENCY_TIMER << 8) | PCI_DEF_CACHE_LINE_SZ) |
||||
|
||||
|
||||
#define cfgaddr(bus, devfn, where) ( \ |
||||
(bus ? ((bus->number & 0xff) << 0x10) : 0) | \
|
||||
((devfn & 0xff) << 0x08) | \
|
||||
(where & 0xfc)) | PCI_ENABLE |
||||
|
||||
/* assumed little endian */ |
||||
static int adm8668_read_config(struct pci_bus *bus, unsigned int devfn, |
||||
int where, int size, u32 *val) |
||||
{ |
||||
switch (size) |
||||
{ |
||||
case 1: |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xff; |
||||
break; |
||||
case 2: |
||||
if (where & 1) |
||||
return PCIBIOS_BAD_REGISTER_NUMBER; |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xffff; |
||||
break; |
||||
case 4: |
||||
if (where & 3) |
||||
return PCIBIOS_BAD_REGISTER_NUMBER; |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*val = le32_to_cpu(*pci_config_data_reg); |
||||
break; |
||||
} |
||||
|
||||
return PCIBIOS_SUCCESSFUL; |
||||
} |
||||
|
||||
static int adm8668_write_config(struct pci_bus *bus, unsigned int devfn, |
||||
int where, int size, u32 val) |
||||
{ |
||||
switch (size) |
||||
{ |
||||
case 1: |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*(volatile u8 *)(((int)pci_config_data_reg) + (where & 3)) = val; |
||||
break; |
||||
case 2: |
||||
if (where & 1) |
||||
return PCIBIOS_BAD_REGISTER_NUMBER; |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*(volatile u16 *)(((int)pci_config_data_reg) + (where & 2)) = val; |
||||
break; |
||||
case 4: |
||||
if (where & 3) |
||||
return PCIBIOS_BAD_REGISTER_NUMBER; |
||||
*pci_config_address_reg = cfgaddr(bus, devfn, where); |
||||
*pci_config_data_reg = (val); |
||||
} |
||||
|
||||
return PCIBIOS_SUCCESSFUL; |
||||
} |
||||
|
||||
|
||||
struct pci_ops adm8668_pci_ops = { |
||||
.read = adm8668_read_config, |
||||
.write = adm8668_write_config |
||||
}; |
||||
|
||||
|
||||
struct resource pciioport_resource = { |
||||
.name = "adm8668_pci", |
||||
.start = ADMPCI_IO_BASE, |
||||
.end = ADMPCI_IO_BASE + ADMPCI_IO_SIZE, |
||||
.flags = IORESOURCE_IO |
||||
}; |
||||
|
||||
|
||||
struct resource pciiomem_resource = { |
||||
.name = "adm8668_pci", |
||||
.start = ADMPCI_MEM_BASE, |
||||
.end = ADMPCI_MEM_BASE + ADMPCI_MEM_SIZE, |
||||
.flags = IORESOURCE_MEM |
||||
}; |
||||
|
||||
#ifdef CONFIG_ADM8668_DISABLE_PCI |
||||
struct pci_controller mips_pci_channels[] = { |
||||
{ NULL, NULL, NULL , NULL , NULL} |
||||
}; |
||||
#else |
||||
struct pci_controller mips_pci_channels = { |
||||
.pci_ops = &adm8668_pci_ops, |
||||
.io_resource = &pciioport_resource, |
||||
.mem_resource = &pciiomem_resource, |
||||
}; |
||||
#endif |
||||
|
||||
int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
||||
{ |
||||
switch (slot) |
||||
{ |
||||
case 1: |
||||
return 14; |
||||
case 2: |
||||
return 13; |
||||
case 3: |
||||
return 12; |
||||
default: |
||||
return dev->irq; |
||||
} |
||||
} |
||||
|
||||
int pcibios_plat_dev_init(struct pci_dev *dev) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
static int __init adm8668_pci_init(void) |
||||
{ |
||||
void __iomem *io_map_base; |
||||
|
||||
printk("adm8668_pci_init()\n"); |
||||
|
||||
/* what's an io port? this is MIPS... *shrug* */ |
||||
ioport_resource.start = ADMPCI_IO_BASE; |
||||
ioport_resource.end = ADMPCI_IO_BASE + ADMPCI_IO_SIZE; |
||||
|
||||
io_map_base = ioremap(ADMPCI_IO_BASE, ADMPCI_IO_SIZE); |
||||
if (!io_map_base) |
||||
printk("io_map_base didn't work.\n"); |
||||
mips_pci_channels.io_map_base = (unsigned long)io_map_base; |
||||
register_pci_controller(&mips_pci_channels); |
||||
|
||||
/* this needed? linksys' gpl 2.4 did it... */ |
||||
adm8668_write_config(NULL, 0, PCI_CACHE_LINE_SIZE, 2, 0); |
||||
adm8668_write_config(NULL, 0, PCI_BASE_ADDRESS_0, 4, 0); |
||||
adm8668_write_config(NULL, 0, PCI_BASE_ADDRESS_1, 4, 0); |
||||
adm8668_write_config(NULL, 0, PCI_COMMAND, 4, PCI_CMM_DEF); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
arch_initcall(adm8668_pci_init); |
@ -0,0 +1,154 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/init.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/mtd/physmap.h> |
||||
#include <linux/pci.h> |
||||
#include <linux/slab.h> |
||||
#include <linux/ioport.h> |
||||
#include <asm/reboot.h> |
||||
#include <asm/time.h> |
||||
#include <asm/addrspace.h> |
||||
#include <asm/bootinfo.h> |
||||
#include <asm/io.h> |
||||
#include <adm8668.h> |
||||
|
||||
extern char _end; |
||||
#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) |
||||
|
||||
static struct resource uart_resources[] = { |
||||
{ |
||||
.start = ADM8668_UART0_BASE, |
||||
.end = ADM8668_UART0_BASE + 0xF, |
||||
.flags = IORESOURCE_MEM, |
||||
}, |
||||
{ |
||||
.start = INT_LVL_UART0, |
||||
.flags = IORESOURCE_IRQ, |
||||
}, |
||||
}; |
||||
|
||||
static struct platform_device adm8668_uart_device = { |
||||
.name = "adm8668_uart", |
||||
.id = 0, |
||||
.resource = uart_resources, |
||||
.num_resources = ARRAY_SIZE(uart_resources), |
||||
}; |
||||
|
||||
static struct resource eth0_resources[] = { |
||||
{ |
||||
.start = ADM8668_LAN_BASE, |
||||
.end = ADM8668_LAN_BASE + 256, |
||||
.flags = IORESOURCE_MEM, |
||||
}, |
||||
{ |
||||
.start = INT_LVL_LAN, |
||||
.flags = IORESOURCE_IRQ, |
||||
}, |
||||
}; |
||||
|
||||
static struct platform_device adm8668_eth0_device = { |
||||
.name = "adm8668_eth", |
||||
.id = 0, |
||||
.resource = eth0_resources, |
||||
.num_resources = ARRAY_SIZE(eth0_resources), |
||||
}; |
||||
|
||||
static struct resource eth1_resources[] = { |
||||
{ |
||||
.start = ADM8668_WAN_BASE, |
||||
.end = ADM8668_WAN_BASE + 256, |
||||
.flags = IORESOURCE_MEM, |
||||
}, |
||||
{ |
||||
.start = INT_LVL_WAN, |
||||
.flags = IORESOURCE_IRQ, |
||||
}, |
||||
}; |
||||
|
||||
static struct platform_device adm8668_eth1_device = { |
||||
.name = "adm8668_eth", |
||||
.id = 1, |
||||
.resource = eth1_resources, |
||||
.num_resources = ARRAY_SIZE(eth1_resources), |
||||
}; |
||||
|
||||
static void adm8668_restart(char *cmd) |
||||
{ |
||||
int i; |
||||
|
||||
/* stop eth0 and eth1 */ |
||||
ADM8668_LAN_REG(NETCSR6) = BIT_1|BIT_13; |
||||
ADM8668_LAN_REG(NETCSR7) = 0; |
||||
ADM8668_WAN_REG(NETCSR6) = BIT_1|BIT_13; |
||||
ADM8668_WAN_REG(NETCSR7) = 0; |
||||
|
||||
/* reset PHY */ |
||||
ADM8668_WAN_REG(NETCSR37) = 0x20; |
||||
for (i = 0; i < 10000; i++) |
||||
; |
||||
ADM8668_WAN_REG(NETCSR37) = 0; |
||||
for (i = 0; i < 10000; i++) |
||||
; |
||||
|
||||
*(volatile unsigned int *)0xB1600000 = 1; /* reset eth0 mac */ |
||||
*(volatile unsigned int *)0xB1A00000 = 1; /* reset eth1 mac */ |
||||
*(volatile unsigned int *)0xB1800000 = 1; /* reset wlan0 mac */ |
||||
|
||||
/* the real deal */ |
||||
for (i = 0; i < 1000; i++) |
||||
; |
||||
ADM8668_CONFIG_REG(ADM8668_CR1) = BIT_0; |
||||
} |
||||
|
||||
int __devinit adm8668_devs_register(void) |
||||
{ |
||||
_machine_restart = adm8668_restart; |
||||
platform_device_register(&adm8668_uart_device); |
||||
platform_device_register(&adm8668_eth0_device); |
||||
platform_device_register(&adm8668_eth1_device); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void __init plat_time_init(void) |
||||
{ |
||||
int adj = (ADM8668_CONFIG_REG(ADM8668_CR3) >> 11) & 0xf; |
||||
|
||||
/* adjustable clock selection
|
||||
CR3 bit 14~11, 0000 -> 175MHz, 0001 -> 180MHz, etc... */ |
||||
|
||||
mips_hpt_frequency = (SYS_CLOCK + adj * 5000000) / 2; |
||||
printk("ADM8668 CPU clock: %d MHz\n", 2*mips_hpt_frequency / 1000000); |
||||
} |
||||
|
||||
void __init plat_mem_setup(void) |
||||
{ |
||||
/* prom_init seemed like easier place for this. it's tooo simple */ |
||||
} |
||||
|
||||
const char *get_system_type(void) |
||||
{ |
||||
unsigned long chipid = ADM8668_CONFIG_REG(ADM8668_CR0); |
||||
int adj = (ADM8668_CONFIG_REG(ADM8668_CR3) >> 11) & 0xf; |
||||
int product, revision, mhz; |
||||
static char ret[32]; |
||||
|
||||
product = chipid >> 16; |
||||
revision = chipid & 0xffff; |
||||
mhz = (SYS_CLOCK/1000000) + (adj * 5); |
||||
|
||||
/* i getting fancy :\ */ |
||||
snprintf(ret, sizeof(ret), "ADM%xr%x %dMHz", product, revision, mhz); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
arch_initcall(adm8668_devs_register); |
@ -0,0 +1,114 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/module.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/init.h> |
||||
#include <linux/proc_fs.h> |
||||
#include <asm/uaccess.h> |
||||
#include <adm8668.h> |
||||
|
||||
int adm8668_sesled_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) |
||||
{ |
||||
char buf[8]; |
||||
int num; |
||||
|
||||
num = (count < 8) ? count : 8; |
||||
|
||||
if (copy_from_user(buf, buffer, num)) |
||||
{ |
||||
printk("copy_from_user failed"); |
||||
return -EFAULT; |
||||
} |
||||
num = simple_strtoul(buf, NULL, 16); |
||||
switch (num) |
||||
{ |
||||
case 0: |
||||
GPIO_SET_LOW(0); |
||||
CRGPIO_SET_LOW(2); |
||||
break; |
||||
case 1: |
||||
GPIO_SET_LOW(0); |
||||
CRGPIO_SET_HI(2); |
||||
break; |
||||
case 2: |
||||
GPIO_SET_HI(0); |
||||
CRGPIO_SET_HI(2); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
return count; |
||||
} |
||||
|
||||
int adm8668_sesled_read_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data) |
||||
{ |
||||
int len = 0; |
||||
int led_state = 0; |
||||
|
||||
led_state = (ADM8668_CONFIG_REG(CRGPIO_REG) & 0x100) ? 1 : 0; |
||||
led_state += (ADM8668_WLAN_REG(GPIO_REG) & 0x40) ? 2 : 0; |
||||
len += sprintf(buf+len, "%s\n", |
||||
(led_state&1) ? |
||||
((led_state&2) ? "ORANGE" : "GREEN") : "OFF"); |
||||
|
||||
return len; |
||||
} |
||||
|
||||
int adm8668_button_read_proc(char *buf, char **start, off_t offset, |
||||
int count, int *eof, void *data) |
||||
{ |
||||
int len = 0; |
||||
int read_once = ADM8668_CONFIG_REG(CRGPIO_REG); |
||||
int button_flip = (read_once >> 20) & 0x3; |
||||
int button_state = read_once & 0x3; |
||||
|
||||
len += sprintf(buf+len, "SES: %s %s\nRESET: %s %s\n", |
||||
(button_state&2) ? "UP" : "DOWN", |
||||
(button_flip&2) ? "FLIP" : "", |
||||
(button_state&1) ? "UP" : "DOWN", |
||||
(button_flip&1) ? "FLIP" : ""); |
||||
|
||||
return len; |
||||
} |
||||
|
||||
int __init adm8668_init_proc(void) |
||||
{ |
||||
struct proc_dir_entry *adm8668_proc_dir = NULL; |
||||
struct proc_dir_entry *sesled = NULL; |
||||
int bogus; |
||||
|
||||
/* these are known to be lights. rest are input...? */ |
||||
ADM8668_CONFIG_REG(CRGPIO_REG) = GPIO2_OUTPUT_ENABLE; |
||||
ADM8668_WLAN_REG(GPIO_REG) = GPIO0_OUTPUT_ENABLE; |
||||
|
||||
/* inital read off of the flipper switcher on the button thingie */ |
||||
bogus = ADM8668_CONFIG_REG(CRGPIO_REG); |
||||
|
||||
adm8668_proc_dir = proc_mkdir("adm8668", 0); |
||||
if (adm8668_proc_dir == NULL) { |
||||
printk(KERN_ERR "ADM8668 proc: unable to create proc dir.\n"); |
||||
return 0; |
||||
} |
||||
create_proc_read_entry("buttons", 0444, adm8668_proc_dir, |
||||
adm8668_button_read_proc, NULL); |
||||
sesled = create_proc_entry("sesled", S_IRUGO|S_IWUGO, adm8668_proc_dir); |
||||
if (sesled) { |
||||
sesled->read_proc = adm8668_sesled_read_proc; |
||||
sesled->write_proc = adm8668_sesled_write_proc; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
module_init(adm8668_init_proc); |
||||
|
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>"); |
||||
MODULE_DESCRIPTION("ADM8668 ghetto button driver"); |
@ -0,0 +1,138 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* based on work of rb532 prom.c |
||||
* Copyright (C) 2003, Peter Sadik <peter.sadik@idt.com> |
||||
* Copyright (C) 2005-2006, P.Christeas <p_christ@hol.gr> |
||||
* Copyright (C) 2007, Gabor Juhos <juhosg@openwrt.org> |
||||
* Felix Fietkau <nbd@openwrt.org> |
||||
* Florian Fainelli <florian@openwrt.org> |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <linux/init.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/types.h> |
||||
#include <linux/console.h> |
||||
#include <linux/string.h> |
||||
#include <linux/serial_core.h> |
||||
#include <asm/bootinfo.h> |
||||
#include <adm8668.h> |
||||
#include "u-boot.h" |
||||
|
||||
register volatile struct global_data *gd asm ("k0"); |
||||
|
||||
#ifdef CONFIG_SERIAL_ADM8668_CONSOLE |
||||
static inline unsigned int adm_uart_readl(unsigned int offset) |
||||
{ |
||||
return (*(volatile unsigned int *)(0xbe400000 + offset)); |
||||
} |
||||
|
||||
static inline void adm_uart_writel(unsigned int value, unsigned int offset) |
||||
{ |
||||
(*((volatile unsigned int *)(0xbe400000 + offset))) = value; |
||||
} |
||||
|
||||
static void prom_putchar(char c) |
||||
{ |
||||
adm_uart_writel(c, UART_DR_REG); |
||||
while ((adm_uart_readl(UART_FR_REG) & UART_TX_FIFO_FULL) != 0) |
||||
; |
||||
} |
||||
|
||||
static void __init |
||||
early_console_write(struct console *con, const char *s, unsigned n) |
||||
{ |
||||
while (n-- && *s) { |
||||
if (*s == '\n') |
||||
prom_putchar('\r'); |
||||
prom_putchar(*s); |
||||
s++; |
||||
} |
||||
} |
||||
|
||||
static struct console early_console __initdata = { |
||||
.name = "early", |
||||
.write = early_console_write, |
||||
.flags = CON_BOOT, |
||||
.index = -1 |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
void __init prom_free_prom_memory(void) |
||||
{ |
||||
/* No prom memory to free */ |
||||
} |
||||
|
||||
static inline int match_tag(char *arg, const char *tag) |
||||
{ |
||||
return strncmp(arg, tag, strlen(tag)) == 0; |
||||
} |
||||
|
||||
static inline unsigned long tag2ul(char *arg, const char *tag) |
||||
{ |
||||
char *num; |
||||
|
||||
num = arg + strlen(tag); |
||||
return simple_strtoul(num, 0, 10); |
||||
} |
||||
|
||||
void __init prom_setup_cmdline(void) |
||||
{ |
||||
char *cp; |
||||
int prom_argc; |
||||
char **prom_argv; |
||||
int i; |
||||
|
||||
prom_argc = fw_arg0; |
||||
prom_argv = (char **)KSEG0ADDR(fw_arg1); |
||||
|
||||
cp = &(arcs_cmdline[0]); |
||||
for (i = 1; i < prom_argc; i++) { |
||||
prom_argv[i] = (char *)KSEG0ADDR(prom_argv[i]); |
||||
|
||||
/* default bootargs has "console=/dev/ttyS0" yet console won't
|
||||
* show up at all if you do this ... */ |
||||
if (match_tag(prom_argv[i], "console=/dev/")) { |
||||
char *ptr = prom_argv[i] + strlen("console=/dev/"); |
||||
|
||||
strcpy(cp, "console="); |
||||
cp += strlen("console="); |
||||
strcpy(cp, ptr); |
||||
cp += strlen(ptr); |
||||
*cp++ = ' '; |
||||
continue; |
||||
} |
||||
strcpy(cp, prom_argv[i]); |
||||
cp += strlen(prom_argv[i]); |
||||
*cp++ = ' '; |
||||
} |
||||
if (prom_argc > 1) |
||||
--cp; /* trailing space */ |
||||
|
||||
*cp = '\0'; |
||||
} |
||||
|
||||
void __init prom_init(void) |
||||
{ |
||||
bd_t *bd = gd->bd; |
||||
int memsize; |
||||
|
||||
#ifdef CONFIG_SERIAL_ADM8668_CONSOLE |
||||
register_console(&early_console); |
||||
#endif |
||||
|
||||
memsize = bd->bi_memsize; |
||||
printk("Board info:\n"); |
||||
printk(" Board ID: %#lx\n", bd->bi_arch_number); |
||||
printk(" RAM size: %d MB\n", (int)memsize/(1024*1024)); |
||||
printk(" NOR start: %#lx\n", bd->bi_flashstart); |
||||
printk(" NOR size: %#lx\n", bd->bi_flashsize); |
||||
|
||||
prom_setup_cmdline(); |
||||
add_memory_region(0, memsize, BOOT_MEM_RAM); |
||||
} |
@ -0,0 +1,638 @@ |
||||
/*
|
||||
* 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. |
||||
* |
||||
* ADM8668 serial driver, totally ripped the source from BCM63xx and changed |
||||
* all the registers to fit our hardware, and removed all the features that |
||||
* I didn't know because our GPL'd serial driver was way lame. |
||||
* |
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* Derived directly from bcm63xx_uart |
||||
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> |
||||
* |
||||
*/ |
||||
|
||||
#if defined(CONFIG_SERIAL_ADM8668_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
||||
#define SUPPORT_SYSRQ |
||||
#endif |
||||
|
||||
#include <linux/kernel.h> |
||||
#include <linux/platform_device.h> |
||||
#include <linux/init.h> |
||||
#include <linux/delay.h> |
||||
#include <linux/module.h> |
||||
#include <linux/console.h> |
||||
#include <linux/clk.h> |
||||
#include <linux/tty.h> |
||||
#include <linux/tty_flip.h> |
||||
#include <linux/sysrq.h> |
||||
#include <linux/serial.h> |
||||
#include <linux/serial_core.h> |
||||
#include <adm8668.h> |
||||
|
||||
#define ADM8668_NR_UARTS 1 |
||||
|
||||
static struct uart_port ports[ADM8668_NR_UARTS]; |
||||
|
||||
/*
|
||||
* handy uart register accessor |
||||
*/ |
||||
static inline unsigned int adm_uart_readl(struct uart_port *port, |
||||
unsigned int offset) |
||||
{ |
||||
return (*(volatile unsigned int *)(port->membase + offset)); |
||||
} |
||||
|
||||
static inline void adm_uart_writel(struct uart_port *port, |
||||
unsigned int value, unsigned int offset) |
||||
{ |
||||
(*((volatile unsigned int *)(port->membase + offset))) = value; |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to check if uart tx fifo is empty |
||||
*/ |
||||
static unsigned int adm_uart_tx_empty(struct uart_port *port) |
||||
{ |
||||
/* we always wait for completion, no buffer is made... */ |
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to set RTS and DTR pin state and loopback mode |
||||
*/ |
||||
static void adm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
||||
{ |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to return RI, CTS, DCD and DSR pin state |
||||
*/ |
||||
static unsigned int adm_uart_get_mctrl(struct uart_port *port) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to disable tx ASAP (used for flow control) |
||||
*/ |
||||
static void adm_uart_stop_tx(struct uart_port *port) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = adm_uart_readl(port, UART_CR_REG); |
||||
val &= ~(UART_TX_INT_EN); |
||||
adm_uart_writel(port, val, UART_CR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to (re)enable tx |
||||
*/ |
||||
static void adm_uart_start_tx(struct uart_port *port) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = adm_uart_readl(port, UART_CR_REG); |
||||
val |= UART_TX_INT_EN; |
||||
adm_uart_writel(port, val, UART_CR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to stop rx, called before port shutdown |
||||
*/ |
||||
static void adm_uart_stop_rx(struct uart_port *port) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = adm_uart_readl(port, UART_CR_REG); |
||||
val &= ~UART_RX_INT_EN; |
||||
adm_uart_writel(port, val, UART_CR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to enable modem status interrupt reporting |
||||
*/ |
||||
static void adm_uart_enable_ms(struct uart_port *port) |
||||
{ |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to start/stop emitting break char |
||||
*/ |
||||
static void adm_uart_break_ctl(struct uart_port *port, int ctl) |
||||
{ |
||||
} |
||||
|
||||
/*
|
||||
* return port type in string format |
||||
*/ |
||||
static const char *adm_uart_type(struct uart_port *port) |
||||
{ |
||||
return (port->type == PORT_ADM8668) ? "adm8668_uart" : NULL; |
||||
} |
||||
|
||||
/*
|
||||
* read all chars in rx fifo and send them to core |
||||
*/ |
||||
static void adm_uart_do_rx(struct uart_port *port) |
||||
{ |
||||
struct tty_struct *tty; |
||||
unsigned int max_count; |
||||
|
||||
/* limit number of char read in interrupt, should not be
|
||||
* higher than fifo size anyway since we're much faster than |
||||
* serial port */ |
||||
max_count = 32; |
||||
tty = port->state->port.tty; |
||||
do { |
||||
unsigned int iestat, c, cstat; |
||||
char flag; |
||||
|
||||
/* get overrun/fifo empty information from ier
|
||||
* register */ |
||||
iestat = adm_uart_readl(port, UART_FR_REG); |
||||
if (iestat & UART_RX_FIFO_EMPTY) |
||||
break; |
||||
|
||||
/* recieve status */ |
||||
cstat = adm_uart_readl(port, UART_RSR_REG); |
||||
/* clear errors */ |
||||
adm_uart_writel(port, cstat, UART_RSR_REG); |
||||
|
||||
c = adm_uart_readl(port, UART_DR_REG); |
||||
port->icount.rx++; |
||||
flag = TTY_NORMAL; |
||||
|
||||
if (unlikely((cstat & UART_RX_STATUS_MASK))) { |
||||
/* do stats first */ |
||||
if (cstat & UART_BREAK_ERR) { |
||||
port->icount.brk++; |
||||
if (uart_handle_break(port)) |
||||
continue; |
||||
} |
||||
|
||||
if (cstat & UART_PARITY_ERR) |
||||
port->icount.parity++; |
||||
if (cstat & UART_FRAMING_ERR) |
||||
port->icount.frame++; |
||||
if (cstat & UART_OVERRUN_ERR) { |
||||
port->icount.overrun++; |
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
||||
} |
||||
|
||||
/* update flag wrt read_status_mask */ |
||||
cstat &= port->read_status_mask; |
||||
if (cstat & UART_BREAK_ERR) |
||||
flag = TTY_BREAK; |
||||
if (cstat & UART_FRAMING_ERR) |
||||
flag = TTY_FRAME; |
||||
if (cstat & UART_PARITY_ERR) |
||||
flag = TTY_PARITY; |
||||
} |
||||
|
||||
if (uart_handle_sysrq_char(port, c)) |
||||
continue; |
||||
|
||||
/* fixthis */ |
||||
if ((cstat & port->ignore_status_mask) == 0) |
||||
tty_insert_flip_char(tty, c, flag); |
||||
} while (max_count--); |
||||
|
||||
tty_flip_buffer_push(tty); |
||||
} |
||||
|
||||
/*
|
||||
* fill tx fifo with chars to send, stop when fifo is about to be full |
||||
* or when all chars have been sent. |
||||
*/ |
||||
static void adm_uart_do_tx(struct uart_port *port) |
||||
{ |
||||
struct circ_buf *xmit; |
||||
|
||||
if (port->x_char) { |
||||
adm_uart_writel(port, port->x_char, UART_DR_REG); |
||||
port->icount.tx++; |
||||
port->x_char = 0; |
||||
return; |
||||
} |
||||
|
||||
if (uart_tx_stopped(port)) |
||||
adm_uart_stop_tx(port); |
||||
|
||||
xmit = &port->state->xmit; |
||||
|
||||
if (uart_circ_empty(xmit)) |
||||
goto txq_empty; |
||||
do |
||||
{ |
||||
while ((adm_uart_readl(port, UART_FR_REG) & UART_TX_FIFO_FULL) != 0) |
||||
; |
||||
adm_uart_writel(port, xmit->buf[xmit->tail], UART_DR_REG); |
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
||||
port->icount.tx++; |
||||
if (uart_circ_empty(xmit)) |
||||
break; |
||||
} while (1); |
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
||||
uart_write_wakeup(port); |
||||
|
||||
if (uart_circ_empty(xmit)) |
||||
goto txq_empty; |
||||
|
||||
return; |
||||
|
||||
txq_empty: |
||||
adm_uart_stop_tx(port); |
||||
} |
||||
|
||||
/*
|
||||
* process uart interrupt |
||||
*/ |
||||
static irqreturn_t adm_uart_interrupt(int irq, void *dev_id) |
||||
{ |
||||
struct uart_port *port; |
||||
unsigned int irqstat; |
||||
|
||||
port = dev_id; |
||||
spin_lock(&port->lock); |
||||
|
||||
irqstat = adm_uart_readl(port, UART_IIR_REG); |
||||
|
||||
if (irqstat & (UART_RX_INT|UART_RX_TIMEOUT_INT)) { |
||||
adm_uart_do_rx(port); |
||||
} |
||||
|
||||
if (irqstat & UART_TX_INT) { |
||||
adm_uart_do_tx(port); |
||||
} |
||||
spin_unlock(&port->lock); |
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
/*
|
||||
* enable rx & tx operation on uart |
||||
*/ |
||||
static void adm_uart_enable(struct uart_port *port) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = adm_uart_readl(port, UART_CR_REG); |
||||
// BREAK_INT too
|
||||
val |= (UART_RX_INT_EN | UART_RX_TIMEOUT_INT_EN); |
||||
adm_uart_writel(port, val, UART_CR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* disable rx & tx operation on uart |
||||
*/ |
||||
static void adm_uart_disable(struct uart_port *port) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = adm_uart_readl(port, UART_CR_REG); |
||||
val &= ~(UART_TX_INT_EN | UART_RX_INT_EN | UART_RX_TIMEOUT_INT_EN); |
||||
adm_uart_writel(port, val, UART_CR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* clear all unread data in rx fifo and unsent data in tx fifo |
||||
*/ |
||||
static void adm_uart_flush(struct uart_port *port) |
||||
{ |
||||
/* read any pending char to make sure all irq status are
|
||||
* cleared */ |
||||
(void)adm_uart_readl(port, UART_DR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to initialize uart and start rx operation |
||||
*/ |
||||
static int adm_uart_startup(struct uart_port *port) |
||||
{ |
||||
int ret; |
||||
|
||||
/* clear any pending external input interrupt */ |
||||
(void)adm_uart_readl(port, UART_IIR_REG); |
||||
|
||||
/* register irq and enable rx interrupts */ |
||||
ret = request_irq(port->irq, adm_uart_interrupt, 0, |
||||
adm_uart_type(port), port); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
adm_uart_enable(port); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to flush & disable uart |
||||
*/ |
||||
static void adm_uart_shutdown(struct uart_port *port) |
||||
{ |
||||
unsigned long flags; |
||||
|
||||
spin_lock_irqsave(&port->lock, flags); |
||||
// adm_uart_writel(port, 0, UART_CR_REG);
|
||||
spin_unlock_irqrestore(&port->lock, flags); |
||||
|
||||
adm_uart_disable(port); |
||||
adm_uart_flush(port); |
||||
free_irq(port->irq, port); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to change current uart setting |
||||
*/ |
||||
static void adm_uart_set_termios(struct uart_port *port, |
||||
struct ktermios *new, |
||||
struct ktermios *old) |
||||
{ |
||||
port->ignore_status_mask = 0; |
||||
uart_update_timeout(port, new->c_cflag, 115200); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to claim uart iomem |
||||
*/ |
||||
static int adm_uart_request_port(struct uart_port *port) |
||||
{ |
||||
unsigned int size = 0xf; |
||||
if (!request_mem_region(port->mapbase, size, "adm8668")) { |
||||
dev_err(port->dev, "Memory region busy\n"); |
||||
return -EBUSY; |
||||
} |
||||
|
||||
port->membase = ioremap(port->mapbase, size); |
||||
if (!port->membase) { |
||||
dev_err(port->dev, "Unable to map registers\n"); |
||||
release_mem_region(port->mapbase, size); |
||||
return -EBUSY; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to release uart iomem |
||||
*/ |
||||
static void adm_uart_release_port(struct uart_port *port) |
||||
{ |
||||
release_mem_region(port->mapbase, 0xf); |
||||
iounmap(port->membase); |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to do any port required autoconfiguration |
||||
*/ |
||||
static void adm_uart_config_port(struct uart_port *port, int flags) |
||||
{ |
||||
if (flags & UART_CONFIG_TYPE) { |
||||
if (adm_uart_request_port(port)) |
||||
return; |
||||
port->type = PORT_ADM8668; |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* serial core request to check that port information in serinfo are |
||||
* suitable |
||||
*/ |
||||
static int adm_uart_verify_port(struct uart_port *port, |
||||
struct serial_struct *serinfo) |
||||
{ |
||||
if (port->type != PORT_ADM8668) |
||||
return -EINVAL; |
||||
if (port->irq != serinfo->irq) |
||||
return -EINVAL; |
||||
if (port->iotype != serinfo->io_type) |
||||
return -EINVAL; |
||||
if (port->mapbase != (unsigned long)serinfo->iomem_base) |
||||
return -EINVAL; |
||||
return 0; |
||||
} |
||||
|
||||
/* serial core callbacks */ |
||||
static struct uart_ops adm_uart_ops = { |
||||
.tx_empty = adm_uart_tx_empty, |
||||
.get_mctrl = adm_uart_get_mctrl, |
||||
.set_mctrl = adm_uart_set_mctrl, |
||||
.start_tx = adm_uart_start_tx, |
||||
.stop_tx = adm_uart_stop_tx, |
||||
.stop_rx = adm_uart_stop_rx, |
||||
.enable_ms = adm_uart_enable_ms, |
||||
.break_ctl = adm_uart_break_ctl, |
||||
.startup = adm_uart_startup, |
||||
.shutdown = adm_uart_shutdown, |
||||
.set_termios = adm_uart_set_termios, |
||||
.type = adm_uart_type, |
||||
.release_port = adm_uart_release_port, |
||||
.request_port = adm_uart_request_port, |
||||
.config_port = adm_uart_config_port, |
||||
.verify_port = adm_uart_verify_port, |
||||
}; |
||||
|
||||
#ifdef CONFIG_SERIAL_ADM8668_CONSOLE |
||||
static inline void wait_for_xmitr(struct uart_port *port) |
||||
{ |
||||
while ((adm_uart_readl(port, UART_FR_REG) & UART_TX_FIFO_FULL) != 0) |
||||
; |
||||
} |
||||
|
||||
/*
|
||||
* output given char |
||||
*/ |
||||
static void adm_console_putchar(struct uart_port *port, int ch) |
||||
{ |
||||
wait_for_xmitr(port); |
||||
adm_uart_writel(port, ch, UART_DR_REG); |
||||
} |
||||
|
||||
/*
|
||||
* console core request to output given string |
||||
*/ |
||||
static void adm_console_write(struct console *co, const char *s, |
||||
unsigned int count) |
||||
{ |
||||
struct uart_port *port; |
||||
unsigned long flags; |
||||
int locked; |
||||
|
||||
port = &ports[co->index]; |
||||
|
||||
local_irq_save(flags); |
||||
if (port->sysrq) { |
||||
/* adm_uart_interrupt() already took the lock */ |
||||
locked = 0; |
||||
} else if (oops_in_progress) { |
||||
locked = spin_trylock(&port->lock); |
||||
} else { |
||||
spin_lock(&port->lock); |
||||
locked = 1; |
||||
} |
||||
|
||||
/* call helper to deal with \r\n */ |
||||
uart_console_write(port, s, count, adm_console_putchar); |
||||
|
||||
/* and wait for char to be transmitted */ |
||||
wait_for_xmitr(port); |
||||
|
||||
if (locked) |
||||
spin_unlock(&port->lock); |
||||
local_irq_restore(flags); |
||||
} |
||||
|
||||
/*
|
||||
* console core request to setup given console, find matching uart |
||||
* port and setup it. |
||||
*/ |
||||
static int adm_console_setup(struct console *co, char *options) |
||||
{ |
||||
struct uart_port *port; |
||||
int baud = 115200; |
||||
int bits = 8; |
||||
int parity = 'n'; |
||||
int flow = 'n'; |
||||
|
||||
if (co->index < 0 || co->index >= ADM8668_NR_UARTS) |
||||
return -EINVAL; |
||||
port = &ports[co->index]; |
||||
if (!port->membase) |
||||
return -ENODEV; |
||||
|
||||
if (options) |
||||
uart_parse_options(options, &baud, &parity, &bits, &flow); |
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow); |
||||
} |
||||
|
||||
static struct uart_driver adm_uart_driver; |
||||
|
||||
static struct console adm8668_console = { |
||||
.name = "ttyS", |
||||
.write = adm_console_write, |
||||
.device = uart_console_device, |
||||
.setup = adm_console_setup, |
||||
.flags = CON_PRINTBUFFER, |
||||
.index = -1, |
||||
.data = &adm_uart_driver, |
||||
}; |
||||
|
||||
static int __init adm8668_console_init(void) |
||||
{ |
||||
register_console(&adm8668_console); |
||||
return 0; |
||||
} |
||||
|
||||
console_initcall(adm8668_console_init); |
||||
|
||||
#define ADM8668_CONSOLE (&adm8668_console) |
||||
#else |
||||
#define ADM8668_CONSOLE NULL |
||||
#endif /* CONFIG_SERIAL_ADM8668_CONSOLE */ |
||||
|
||||
static struct uart_driver adm_uart_driver = { |
||||
.owner = THIS_MODULE, |
||||
.driver_name = "adm8668_uart", |
||||
.dev_name = "ttyS", |
||||
.major = TTY_MAJOR, |
||||
.minor = 64, |
||||
.nr = 1, |
||||
.cons = ADM8668_CONSOLE, |
||||
}; |
||||
|
||||
/*
|
||||
* platform driver probe/remove callback |
||||
*/ |
||||
static int __devinit adm_uart_probe(struct platform_device *pdev) |
||||
{ |
||||
struct resource *res_mem, *res_irq; |
||||
struct uart_port *port; |
||||
int ret; |
||||
|
||||
if (pdev->id < 0 || pdev->id >= ADM8668_NR_UARTS) |
||||
return -EINVAL; |
||||
|
||||
if (ports[pdev->id].membase) |
||||
return -EBUSY; |
||||
|
||||
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
||||
if (!res_mem) |
||||
return -ENODEV; |
||||
|
||||
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
||||
if (!res_irq) |
||||
return -ENODEV; |
||||
|
||||
port = &ports[pdev->id]; |
||||
memset(port, 0, sizeof(*port)); |
||||
port->iotype = UPIO_MEM; |
||||
port->mapbase = res_mem->start; |
||||
port->irq = res_irq->start; |
||||
port->ops = &adm_uart_ops; |
||||
port->flags = UPF_BOOT_AUTOCONF; |
||||
port->dev = &pdev->dev; |
||||
port->fifosize = 8; |
||||
port->uartclk = ADM8668_UARTCLK_FREQ; |
||||
|
||||
ret = uart_add_one_port(&adm_uart_driver, port); |
||||
if (ret) { |
||||
ports[pdev->id].membase = 0; |
||||
return ret; |
||||
} |
||||
platform_set_drvdata(pdev, port); |
||||
return 0; |
||||
} |
||||
|
||||
static int __devexit adm_uart_remove(struct platform_device *pdev) |
||||
{ |
||||
struct uart_port *port; |
||||
|
||||
port = platform_get_drvdata(pdev); |
||||
uart_remove_one_port(&adm_uart_driver, port); |
||||
platform_set_drvdata(pdev, NULL); |
||||
/* mark port as free */ |
||||
ports[pdev->id].membase = 0; |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* platform driver stuff |
||||
*/ |
||||
static struct platform_driver adm_uart_platform_driver = { |
||||
.probe = adm_uart_probe, |
||||
.remove = __devexit_p(adm_uart_remove), |
||||
.driver = { |
||||
.owner = THIS_MODULE, |
||||
.name = "adm8668_uart", |
||||
}, |
||||
}; |
||||
|
||||
static int __init adm_uart_init(void) |
||||
{ |
||||
int ret; |
||||
|
||||
ret = uart_register_driver(&adm_uart_driver); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
ret = platform_driver_register(&adm_uart_platform_driver); |
||||
if (ret) |
||||
uart_unregister_driver(&adm_uart_driver); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static void __exit adm_uart_exit(void) |
||||
{ |
||||
platform_driver_unregister(&adm_uart_platform_driver); |
||||
uart_unregister_driver(&adm_uart_driver); |
||||
} |
||||
|
||||
module_init(adm_uart_init); |
||||
module_exit(adm_uart_exit); |
||||
|
||||
MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>"); |
||||
MODULE_DESCRIPTION("ADM8668 integrated uart driver"); |
||||
MODULE_LICENSE("GPL"); |
@ -0,0 +1,52 @@ |
||||
/*
|
||||
* (C) Copyright 2003 |
||||
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de> |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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 _U_BOOT_H_ |
||||
#define _U_BOOT_H_ 1 |
||||
|
||||
typedef struct bd_info { |
||||
int bi_baudrate; /* serial console baudrate */ |
||||
unsigned long bi_ip_addr; /* IP Address */ |
||||
unsigned char bi_enetaddr[6]; /* Ethernet adress */ |
||||
unsigned long bi_arch_number; /* unique id for this board */ |
||||
unsigned long bi_boot_params; /* where this board expects params */ |
||||
unsigned long bi_memstart; /* start of DRAM memory */ |
||||
unsigned long bi_memsize; /* size of DRAM memory in bytes */ |
||||
unsigned long bi_flashstart; /* start of FLASH memory */ |
||||
unsigned long bi_flashsize; /* size of FLASH memory */ |
||||
unsigned long bi_flashoffset; /* reserved area for startup monitor */ |
||||
} bd_t; |
||||
|
||||
struct global_data { |
||||
bd_t *bd; /* board data... */ |
||||
unsigned long flags; |
||||
unsigned long baudrate; |
||||
unsigned long have_console; /* serial_init() was called */ |
||||
unsigned long ram_size; /* RAM size */ |
||||
unsigned long reloc_off; /* Relocation Offset */ |
||||
unsigned long env_addr; /* Address of Environment struct */ |
||||
unsigned long env_valid; /* Checksum of Environment valid? */ |
||||
void **jt; /* jump table */ |
||||
}; |
||||
|
||||
#endif /* _U_BOOT_H_ */ |
@ -0,0 +1,416 @@ |
||||
/************************************************************************
|
||||
* |
||||
* Copyright (c) 2005 |
||||
* Infineon Technologies AG |
||||
* St. Martin Strasse 53; 81669 Muenchen; Germany |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#ifndef __ADM8668_H__ |
||||
#define __ADM8668_H__ |
||||
|
||||
#include <asm/addrspace.h> |
||||
#include "bsp_sup.h" |
||||
|
||||
#define MEM_KSEG0_BASE 0x80000000 |
||||
#define MEM_KSEG1_BASE 0xA0000000 |
||||
#define MEM_SEG_MASK 0xE0000000 |
||||
#define KVA2PA(_addr) ((unsigned long)(_addr) & ~MEM_SEG_MASK) |
||||
|
||||
#define MIPS_KSEG0A(_addr) (KVA2PA(_addr) | MEM_KSEG0_BASE) |
||||
#define MIPS_KSEG1A(_addr) (KVA2PA(_addr) | MEM_KSEG1_BASE) |
||||
|
||||
#define PA2VA(_addr) (KVA2PA(_addr) | MEM_KSEG1_BASE) |
||||
#define PA2CACHEVA(_addr) (KVA2PA(_addr) | MEM_KSEG0_BASE) |
||||
|
||||
|
||||
/*======================= Physical Memory Map ============================*/ |
||||
#define ADM8668_SDRAM_BASE 0 |
||||
#define ADM8668_SMEM1_BASE 0x10000000 |
||||
#define ADM8668_MPMC_BASE 0x11000000 |
||||
#define ADM8668_USB_BASE 0x11200000 |
||||
#define ADM8668_CONFIG_BASE 0x11400000 |
||||
#define ADM8668_WAN_BASE 0x11600000 |
||||
#define ADM8668_WLAN_BASE 0x11800000 |
||||
#define ADM8668_LAN_BASE 0x11A00000 |
||||
#define ADM8668_INTC_BASE 0x1E000000 |
||||
#define ADM8668_TMR_BASE 0x1E200000 |
||||
#define ADM8668_UART0_BASE 0x1E400000 |
||||
#define ADM8668_SMEM0_BASE 0x1FC00000 |
||||
#define ADM8668_NAND_BASE 0x1fffff00 |
||||
|
||||
#define PCICFG_BASE 0x12200000 |
||||
#define PCIDAT_BASE 0x12400000 |
||||
|
||||
/* for PCI bridge fixup ! */ |
||||
#define PCI_BRIDGE_MASK 0x40 |
||||
|
||||
/* WLAN registers */ |
||||
#define WCSR0 0x00 |
||||
#define WCSR11A 0x5c |
||||
|
||||
#define GPIO_REG WCSR11A |
||||
|
||||
#define ADM8668_WLAN_REG(_reg) \ |
||||
(*((volatile unsigned int *)(PA2VA(ADM8668_WLAN_BASE + (_reg))))) |
||||
|
||||
/* configuration registers */ |
||||
#define ADM8668_CR0 0x00 |
||||
#define ADM8668_CR1 0x04 |
||||
#define ADM8668_CR2 0x08 |
||||
#define ADM8668_CR3 0x0C |
||||
#define ADM8668_CR8 0x20 |
||||
#define ADM8668_CR10 0x28 |
||||
#define ADM8668_CR11 0x2C |
||||
#define ADM8668_CR12 0x30 |
||||
#define ADM8668_CR13 0x34 |
||||
#define ADM8668_CR14 0x38 |
||||
#define ADM8668_CR15 0x3C |
||||
#define ADM8668_CR16 0x40 |
||||
#define ADM8668_CR17 0x44 |
||||
#define ADM8668_CR18 0x48 |
||||
#define ADM8668_CR19 0x4C |
||||
#define ADM8668_CR20 0x50 |
||||
#define ADM8668_CR21 0x54 |
||||
#define ADM8668_CR22 0x58 |
||||
#define ADM8668_CR23 0x5C |
||||
#define ADM8668_CR24 0x60 |
||||
#define ADM8668_CR25 0x64 |
||||
#define ADM8668_CR26 0x68 |
||||
#define ADM8668_CR27 0x6C |
||||
#define ADM8668_CR28 0x70 |
||||
#define ADM8668_CR29 0x74 |
||||
#define ADM8668_CR30 0x78 |
||||
#define ADM8668_CR31 0x7C |
||||
#define ADM8668_CR32 0x80 |
||||
#define ADM8668_CR33 0x84 |
||||
#define ADM8668_CR34 0x88 |
||||
#define ADM8668_CR35 0x8C |
||||
#define ADM8668_CR36 0x90 |
||||
#define ADM8668_CR37 0x94 |
||||
#define ADM8668_CR38 0x98 |
||||
#define ADM8668_CR39 0x9C |
||||
#define ADM8668_CR40 0xA0 |
||||
#define ADM8668_CR41 0xA4 |
||||
#define ADM8668_CR42 0xA8 |
||||
#define ADM8668_CR43 0xAC |
||||
#define ADM8668_CR44 0xB0 |
||||
#define ADM8668_CR45 0xB4 |
||||
#define ADM8668_CR46 0xB8 |
||||
#define ADM8668_CR47 0xBC |
||||
#define ADM8668_CR48 0xC0 |
||||
#define ADM8668_CR49 0xC4 |
||||
#define ADM8668_CR50 0xC8 |
||||
#define ADM8668_CR51 0xCC |
||||
#define ADM8668_CR52 0xD0 |
||||
#define ADM8668_CR53 0xD4 |
||||
#define ADM8668_CR54 0xD8 |
||||
#define ADM8668_CR55 0xDC |
||||
#define ADM8668_CR56 0xE0 |
||||
#define ADM8668_CR57 0xE4 |
||||
#define ADM8668_CR58 0xE8 |
||||
#define ADM8668_CR59 0xEC |
||||
#define ADM8668_CR60 0xF0 |
||||
#define ADM8668_CR61 0xF4 |
||||
#define ADM8668_CR62 0xF8 |
||||
#define ADM8668_CR63 0xFC |
||||
#define ADM8668_CR64 0x100 |
||||
#define ADM8668_CR65 0x104 |
||||
#define ADM8668_CR66 0x108 |
||||
#define ADM8668_CR67 0x10C |
||||
#define ADM8668_CR68 0x110 |
||||
|
||||
#define CRGPIO_REG ADM8668_CR8 |
||||
|
||||
#define ADM8668_CONFIG_REG(_reg) \ |
||||
(*((volatile unsigned int *)(PA2VA(ADM8668_CONFIG_BASE + (_reg))))) |
||||
#define ADM8668_MPMC_REG(_reg) \ |
||||
(*((volatile unsigned int *)(PA2VA(ADM8668_MPMC_BASE + (_reg))))) |
||||
|
||||
|
||||
/*========================== Interrupt Controller ==========================*/ |
||||
/* registers offset */ |
||||
#define IRQ_STATUS_REG 0x00 /* Read */ |
||||
#define IRQ_RAW_STATUS_REG 0x04 /* Read */ |
||||
#define IRQ_ENABLE_REG 0x08 /* Read/Write */ |
||||
#define IRQ_DISABLE_REG 0x0C /* Write */ |
||||
#define IRQ_SOFT_REG 0x10 /* Write */ |
||||
|
||||
#define FIQ_STATUS_REG 0x100 /* Read */ |
||||
#define FIQ_RAW_STATUS_REG 0x104 |
||||
#define FIQ_ENABLE_REG 0x108 |
||||
#define FIQ_DISABLE_REG 0x10c |
||||
|
||||
|
||||
/* Macro for accessing Interrupt controller register */ |
||||
#define ADM8668_INTC_REG(_reg) \ |
||||
(*((volatile unsigned long *)(PA2VA(ADM8668_INTC_BASE + (_reg))))) |
||||
|
||||
|
||||
/* interrupt levels */ |
||||
#define INT_LVL_SWI 1 |
||||
#define INT_LVL_COMMS_RX 2 |
||||
#define INT_LVL_COMMS_TX 3 |
||||
#define INT_LVL_TIMERINT0 4 |
||||
#define INT_LVL_TIMERINT1 5 |
||||
#define INT_LVL_UART0 6 |
||||
#define INT_LVL_LAN 7 |
||||
#define INT_LVL_WAN 8 |
||||
#define INT_LVL_WLAN 9 |
||||
#define INT_LVL_GPIO 10 |
||||
#define INT_LVL_IDE 11 |
||||
#define INT_LVL_PCI2 12 |
||||
#define INT_LVL_PCI1 13 |
||||
#define INT_LVL_PCI0 14 |
||||
#define INT_LVL_USB 15 |
||||
#define INT_LVL_MAX INT_LVL_USB |
||||
|
||||
#define IRQ_MASK 0xffff |
||||
|
||||
#define IRQ_SWI (0x1<<INT_LVL_SWI) |
||||
#define IRQ_TIMERINT0 (0x1<<INT_LVL_TIMERINT0) |
||||
#define IRQ_TIMERINT1 (0x1<<INT_LVL_TIMERINT1) |
||||
#define IRQ_UART0 (0x1<<INT_LVL_UART0) |
||||
#define IRQ_LAN (0x1<<INT_LVL_LAN) |
||||
#define IRQ_WAN (0x1<<INT_LVL_WAN) |
||||
#define IRQ_WLAN (0x1<<INT_LVL_WLAN) |
||||
#define IRQ_GPIO (0x1<<INT_LVL_GPIO) |
||||
#define IRQ_IDEINT (0x1<<INT_LVL_IDE) |
||||
#define IRQ_PCI2 (0x1<<INT_LVL_PCI2) |
||||
#define IRQ_PCI1 (0x1<<INT_LVL_PCI1) |
||||
#define IRQ_PCI0 (0x1<<INT_LVL_PCI0) |
||||
#define IRQ_USB (0x1<<INT_LVL_USB) |
||||
|
||||
|
||||
/*=========================== UART Control Register ========================*/ |
||||
#define UART_DR_REG 0x00 |
||||
#define UART_RSR_REG 0x04 |
||||
#define UART_ECR_REG 0x04 |
||||
#define UART_LCR_H_REG 0x08 |
||||
#define UART_LCR_M_REG 0x0c |
||||
#define UART_LCR_L_REG 0x10 |
||||
#define UART_CR_REG 0x14 |
||||
#define UART_FR_REG 0x18 |
||||
#define UART_IIR_REG 0x1c |
||||
#define UART_ICR_REG 0x1C |
||||
#define UART_ILPR_REG 0x20 |
||||
|
||||
/* rsr/ecr reg */ |
||||
#define UART_OVERRUN_ERR 0x08 |
||||
#define UART_BREAK_ERR 0x04 |
||||
#define UART_PARITY_ERR 0x02 |
||||
#define UART_FRAMING_ERR 0x01 |
||||
#define UART_RX_STATUS_MASK 0x0f |
||||
#define UART_RX_ERROR ( UART_BREAK_ERR \ |
||||
| UART_PARITY_ERR \
|
||||
| UART_FRAMING_ERR) |
||||
|
||||
/* lcr_h reg */ |
||||
#define UART_SEND_BREAK 0x01 |
||||
#define UART_PARITY_EN 0x02 |
||||
#define UART_EVEN_PARITY 0x04 |
||||
#define UART_TWO_STOP_BITS 0x08 |
||||
#define UART_ENABLE_FIFO 0x10 |
||||
|
||||
#define UART_WLEN_5BITS 0x00 |
||||
#define UART_WLEN_6BITS 0x20 |
||||
#define UART_WLEN_7BITS 0x40 |
||||
#define UART_WLEN_8BITS 0x60 |
||||
#define UART_WLEN_MASK 0x60 |
||||
|
||||
/* cr reg */ |
||||
#define UART_PORT_EN 0x01 |
||||
#define UART_SIREN 0x02 |
||||
#define UART_SIRLP 0x04 |
||||
#define UART_MODEM_STATUS_INT_EN 0x08 |
||||
#define UART_RX_INT_EN 0x10 |
||||
#define UART_TX_INT_EN 0x20 |
||||
#define UART_RX_TIMEOUT_INT_EN 0x40 |
||||
#define UART_LOOPBACK_EN 0x80 |
||||
|
||||
/* fr reg */ |
||||
#define UART_CTS 0x01 |
||||
#define UART_DSR 0x02 |
||||
#define UART_DCD 0x04 |
||||
#define UART_BUSY 0x08 |
||||
#define UART_RX_FIFO_EMPTY 0x10 |
||||
#define UART_TX_FIFO_FULL 0x20 |
||||
#define UART_RX_FIFO_FULL 0x40 |
||||
#define UART_TX_FIFO_EMPTY 0x80 |
||||
|
||||
/* iir/icr reg */ |
||||
#define UART_MODEM_STATUS_INT 0x01 |
||||
#define UART_RX_INT 0x02 |
||||
#define UART_TX_INT 0x04 |
||||
#define UART_RX_TIMEOUT_INT 0x08 |
||||
|
||||
#define UART_INT_MASK 0x0f |
||||
|
||||
#ifdef _FPGA_ |
||||
#define ADM8668_UARTCLK_FREQ 3686400 |
||||
#else |
||||
#define ADM8668_UARTCLK_FREQ 62500000 |
||||
#endif |
||||
|
||||
#define UART_BAUDDIV(_rate) \ |
||||
((unsigned long)(ADM8668_UARTCLK_FREQ/(16*(_rate)) - 1)) |
||||
|
||||
/* uart_baudrate */ |
||||
#define UART_230400bps_DIVISOR UART_BAUDDIV(230400) |
||||
#define UART_115200bps_DIVISOR UART_BAUDDIV(115200) |
||||
#define UART_76800bps_DIVISOR UART_BAUDDIV(76800) |
||||
#define UART_57600bps_DIVISOR UART_BAUDDIV(57600) |
||||
#define UART_38400bps_DIVISOR UART_BAUDDIV(38400) |
||||
#define UART_19200bps_DIVISOR UART_BAUDDIV(19200) |
||||
#define UART_14400bps_DIVISOR UART_BAUDDIV(14400) |
||||
#define UART_9600bps_DIVISOR UART_BAUDDIV(9600) |
||||
#define UART_2400bps_DIVISOR UART_BAUDDIV(2400) |
||||
#define UART_1200bps_DIVISOR UART_BAUDDIV(1200) |
||||
|
||||
|
||||
/*=========================== Counter Timer ==============================*/ |
||||
#define TIMER0_REG_BASE ADM8668_TMR_BASE |
||||
#define TIMER1_REG_BASE ADM8668_TMR_BASE+0x20 |
||||
|
||||
#define TIMER_LOAD_REG 0x00 |
||||
#define TIMER_VALUE_REG 0x04 |
||||
#define TIMER_CTRL_REG 0x08 |
||||
#define TIMER_CLR_REG 0x0c |
||||
|
||||
/* TIMER_LOAD_REG */ |
||||
#ifdef _FPGA_ |
||||
#define SYS_CLOCK 56000000 |
||||
#else |
||||
#define SYS_CLOCK 175000000 |
||||
#endif |
||||
|
||||
#define SYS_PRESCALE 256 |
||||
|
||||
#define TMR_10MS_TICKS (SYS_CLOCK/SYS_PRESCALE/100) |
||||
|
||||
/* TIMER_CTRL_REG */ |
||||
#define TMR_PRESCALE_1 0x00 |
||||
#define TMR_PRESCALE_16 0x04 |
||||
#define TMR_PRESCALE_256 0x08 |
||||
#define TMR_MODE_PERIODIC 0x40 |
||||
#define TMR_ENABLE 0x80 |
||||
|
||||
/* TIMER_CLR_REG */ |
||||
#define TMR_CLEAR_BIT 1 |
||||
|
||||
|
||||
/* Macro for access MPMC register */ |
||||
#define ADM8668_TMR_REG(base, _offset) \ |
||||
(*((volatile unsigned long *)(PA2VA(base + (_offset))))) |
||||
|
||||
|
||||
/* For GPIO control */ |
||||
#define GPIO0_OUTPUT_ENABLE 0x1000 |
||||
#define GPIO1_OUTPUT_ENABLE 0x2000 |
||||
#define GPIO2_OUTPUT_ENABLE 0x4000 |
||||
#define GPIO_OUTPUT_ENABLE_ALL 0x7000 |
||||
#define GPIO0_OUTPUT_1 0x40 |
||||
#define GPIO1_OUTPUT_1 0x80 |
||||
#define GPIO2_OUTPUT_1 0x100 |
||||
#define GPIO0_INPUT_1 0x1 |
||||
#define GPIO1_INPUT_1 0x2 |
||||
#define GPIO2_INPUT_1 0x4 |
||||
|
||||
#define GPIO_SET_HI(num) \ |
||||
ADM8668_WLAN_REG(GPIO_REG) |= (1 << (6 + num)) |
||||
|
||||
#define GPIO_SET_LOW(num) \ |
||||
ADM8668_WLAN_REG(GPIO_REG) &= ~(1 << (6 + num)) |
||||
|
||||
#define GPIO_TOGGLE(num) \ |
||||
ADM8668_WLAN_REG(GPIO_REG) ^= (1 << (6 + num)) |
||||
|
||||
#define CRGPIO_SET_HI(num) \ |
||||
ADM8668_CONFIG_REG(CRGPIO_REG) |= (1 << (6 + num)) |
||||
|
||||
#define CRGPIO_SET_LOW(num) \ |
||||
ADM8668_CONFIG_REG(CRGPIO_REG) &= ~(1 << (6 + num)) |
||||
|
||||
#define CRGPIO_TOGGLE(num) \ |
||||
ADM8668_CONFIG_REG(CRGPIO_REG) ^= (1 << (6 + num)) |
||||
|
||||
|
||||
/*==========================================================================*/ |
||||
/* Cache Controller */ |
||||
#define ADM8668_CACHE_LINE_SIZE 16 |
||||
|
||||
#define BIT_0 0x00000001 |
||||
#define BIT_1 0x00000002 |
||||
#define BIT_2 0x00000004 |
||||
#define BIT_3 0x00000008 |
||||
#define BIT_4 0x00000010 |
||||
#define BIT_5 0x00000020 |
||||
#define BIT_6 0x00000040 |
||||
#define BIT_7 0x00000080 |
||||
#define BIT_8 0x00000100 |
||||
#define BIT_9 0x00000200 |
||||
#define BIT_10 0x00000400 |
||||
#define BIT_11 0x00000800 |
||||
#define BIT_12 0x00001000 |
||||
#define BIT_13 0x00002000 |
||||
#define BIT_14 0x00004000 |
||||
#define BIT_15 0x00008000 |
||||
#define BIT_16 0x00010000 |
||||
#define BIT_17 0x00020000 |
||||
#define BIT_18 0x00040000 |
||||
#define BIT_19 0x00080000 |
||||
#define BIT_20 0x00100000 |
||||
#define BIT_21 0x00200000 |
||||
#define BIT_22 0x00400000 |
||||
#define BIT_23 0x00800000 |
||||
#define BIT_24 0x01000000 |
||||
#define BIT_25 0x02000000 |
||||
#define BIT_26 0x04000000 |
||||
#define BIT_27 0x08000000 |
||||
#define BIT_28 0x10000000 |
||||
#define BIT_29 0x20000000 |
||||
#define BIT_30 0x40000000 |
||||
#define BIT_31 0x80000000 |
||||
|
||||
/* network regs */ |
||||
#define NETCSR0 0x0 |
||||
#define NETCSR1 0x08 |
||||
#define NETCSR2 0x10 |
||||
#define NETCSR3 0x18 |
||||
#define NETCSR4 0x20 |
||||
#define NETCSR5 0x28 |
||||
#define NETCSR6 0x30 |
||||
#define NETCSR7 0x38 |
||||
#define NETCSR8 0x40 |
||||
#define NETCSR9 0x48 |
||||
#define NETCSR10 0x50 |
||||
#define NETCSR11 0x58 |
||||
#define NETCSR12 0x60 |
||||
#define NETCSR13 0x68 |
||||
#define NETCSR14 0x70 |
||||
#define NETCSR15 0x78 |
||||
#define NETCSR36 0xD0 |
||||
#define NETCSR36A 0xD4 |
||||
#define NETCSR36B 0xD8 |
||||
#define NETCSR36C 0xDC // dummy
|
||||
#define NETCSR36D 0xE0 |
||||
#define NETCSR36E 0xE4 |
||||
#define NETCSR36F 0xE8 |
||||
#define NETCSR36G 0xEC |
||||
#define NETCSR36H 0xF0 |
||||
#define NETCSR36I 0xF4 |
||||
#define NETCSR37 0xF8 |
||||
|
||||
/* for descriptor skip DWs */ |
||||
#define NETDESCSKIP_1DW BIT_2 |
||||
#define NETDESCSKIP_2DW BIT_3 |
||||
#define NETDESCSKIP_3DW (BIT_3|BIT_2) |
||||
#define NETDESCSKIP_4DW BIT_4 |
||||
|
||||
|
||||
#define ADM8668_LAN_REG(_reg) \ |
||||
(*((volatile unsigned int *)(PA2VA(ADM8668_LAN_BASE + (_reg))))) |
||||
#define ADM8668_WAN_REG(_reg) \ |
||||
(*((volatile unsigned int *)(PA2VA(ADM8668_WAN_BASE + (_reg))))) |
||||
|
||||
#endif /* __ADM8668_H__ */ |
@ -0,0 +1,84 @@ |
||||
/************************************************************************
|
||||
* |
||||
* Copyright (c) 2005 |
||||
* Infineon Technologies AG |
||||
* St. Martin Strasse 53; 81669 Muenchen; Germany |
||||
* |
||||
************************************************************************/ |
||||
#ifndef _BSP_SUP_H_ |
||||
#define _BSP_SUP_H_ |
||||
|
||||
#define ADD_WAN_MAC |
||||
#define CONFIG_IFX_GAN |
||||
#define UBOOT_CFG_ENV_SIZE (0x400-4) |
||||
#define ADM8668_BL_MAGIC 0x6c62676d |
||||
#define ADM8668_MAC_MAGIC 0x69666164 |
||||
#define ADM8668_VER_MAGIC 0x7276676d |
||||
#define ADM8668_ID_MAGIC 0x6469676d |
||||
#define ADM8668_IF_MAGIC 0x6669676d |
||||
#define ADM8668_WANMAC_MAGIC 0x69666164 |
||||
#define ADM8668_IMEI_MAGIC 0x6669676e |
||||
|
||||
#define BSP_IFNAME_MAX_LEN 15 |
||||
#define BOOT_LINE_SIZE 255 |
||||
#define BSP_STR_LEN 79 |
||||
|
||||
|
||||
/*
|
||||
* Boot mode configuration |
||||
*/ |
||||
typedef struct BTMODE_CFG_S |
||||
{ |
||||
unsigned long btmode; |
||||
unsigned long dlmethod; |
||||
} BTMODE_CFG_T; |
||||
|
||||
|
||||
/*
|
||||
* Interface configuration |
||||
*/ |
||||
typedef struct IF_CFG_S |
||||
{ |
||||
char ifname[BSP_IFNAME_MAX_LEN+1]; |
||||
unsigned long ip; |
||||
unsigned long mask; |
||||
unsigned long gateway; |
||||
} IF_CFG_T; |
||||
|
||||
|
||||
/*
|
||||
* Board configuration |
||||
*/ |
||||
typedef struct BOARD_CFG_S |
||||
{ |
||||
unsigned long blmagic; |
||||
unsigned char blreserved[UBOOT_CFG_ENV_SIZE]; |
||||
|
||||
unsigned long macmagic; |
||||
unsigned char mac[8]; |
||||
unsigned long macnum; |
||||
|
||||
unsigned long idmagic; |
||||
unsigned char serial[BSP_STR_LEN+1]; |
||||
|
||||
unsigned long vermagic; |
||||
unsigned char ver[BSP_STR_LEN+1]; |
||||
|
||||
unsigned long ifmagic; |
||||
IF_CFG_T ifcfg[8]; |
||||
|
||||
unsigned long btmagic; |
||||
BTMODE_CFG_T bootmode; |
||||
|
||||
unsigned long wanmagic; |
||||
unsigned char wanmac[8]; |
||||
|
||||
unsigned long imeimagic; |
||||
unsigned char imei0[16]; |
||||
unsigned char imei1[16]; |
||||
} BOARD_CFG_T, *PBOARD_CFG_T; |
||||
|
||||
#define ADM8668_BOARD_CFG_ADDR (ADM8668_SMEM0_BASE + CONFIG_ADM8668_BSP_OFFSET*1024) |
||||
#define ADM8668_BOARD_CFG_SIZE (CONFIG_ADM8668_BSP_SIZE*1024) |
||||
|
||||
#endif /* _BSP_SUP_H_ */ |
@ -0,0 +1,35 @@ |
||||
/*
|
||||
* 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. |
||||
* |
||||
* Copyright (C) 2003 by Ralf Baechle |
||||
*/ |
||||
#ifndef __ASM_MACH_ADM8668_IRQ_H |
||||
#define __ASM_MACH_ADM8668_IRQ_H |
||||
|
||||
#ifndef NR_IRQS |
||||
#define NR_IRQS 32 |
||||
#endif |
||||
|
||||
#ifdef CONFIG_IRQ_CPU |
||||
|
||||
#ifndef MIPS_CPU_IRQ_BASE |
||||
#define MIPS_CPU_IRQ_BASE 16 |
||||
#endif |
||||
|
||||
#ifdef CONFIG_IRQ_CPU_RM7K |
||||
#ifndef RM7K_CPU_IRQ_BASE |
||||
#define RM7K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+8) |
||||
#endif |
||||
#endif |
||||
|
||||
#ifdef CONFIG_IRQ_CPU_RM9K |
||||
#ifndef RM9K_CPU_IRQ_BASE |
||||
#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12) |
||||
#endif |
||||
#endif |
||||
|
||||
#endif /* CONFIG_IRQ_CPU */ |
||||
|
||||
#endif /* __ASM_MACH_ADM8668_IRQ_H */ |
@ -0,0 +1,55 @@ |
||||
/*
|
||||
* Carsten Langgaard, carstenl@mips.com |
||||
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. |
||||
* |
||||
* ######################################################################## |
||||
* |
||||
* This program is free software; you can distribute it and/or modify it |
||||
* under the terms of the GNU General Public License (Version 2) as |
||||
* published by the Free Software Foundation. |
||||
* |
||||
* This program is distributed in the hope 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. |
||||
* |
||||
* ######################################################################## |
||||
* |
||||
* MIPS boards bootprom interface for the Linux kernel. |
||||
* |
||||
*/ |
||||
/************************************************************************
|
||||
* |
||||
* Copyright (c) 2005 |
||||
* Infineon Technologies AG |
||||
* St. Martin Strasse 53; 81669 Muenchen; Germany |
||||
* |
||||
************************************************************************/ |
||||
#ifndef _MIPS_PROM_H |
||||
#define _MIPS_PROM_H |
||||
|
||||
extern char *prom_getcmdline(void); |
||||
extern char *prom_getenv(char *name); |
||||
extern void setup_prom_printf(int tty_no); |
||||
extern void prom_printf(char *fmt, ...); |
||||
extern void prom_init_cmdline(void); |
||||
extern void prom_meminit(void); |
||||
extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); |
||||
extern void prom_free_prom_memory (void); |
||||
extern void mips_display_message(const char *str); |
||||
extern void mips_display_word(unsigned int num); |
||||
extern int get_ethernet_addr(char *ethernet_addr); |
||||
|
||||
/* Memory descriptor management. */ |
||||
#define PROM_MAX_PMEMBLOCKS 32 |
||||
struct prom_pmemblock { |
||||
unsigned long base; /* Within KSEG0. */ |
||||
unsigned int size; /* In bytes. */ |
||||
unsigned int type; /* free or prom memory */ |
||||
}; |
||||
|
||||
#endif /* !(_MIPS_PROM_H) */ |
@ -0,0 +1,25 @@ |
||||
/*
|
||||
* 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. |
||||
* |
||||
* Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> |
||||
*/ |
||||
#ifndef __ASM_MIPS_MACH_ADM8668_WAR_H |
||||
#define __ASM_MIPS_MACH_ADM8668_WAR_H |
||||
|
||||
#define R4600_V1_INDEX_ICACHEOP_WAR 0 |
||||
#define R4600_V1_HIT_CACHEOP_WAR 0 |
||||
#define R4600_V2_HIT_CACHEOP_WAR 0 |
||||
#define R5432_CP0_INTERRUPT_WAR 0 |
||||
#define BCM1250_M3_WAR 0 |
||||
#define SIBYTE_1956_WAR 0 |
||||
#define MIPS4K_ICACHE_REFILL_WAR 0 |
||||
#define MIPS_CACHE_SYNC_WAR 0 |
||||
#define TX49XX_ICACHE_INDEX_INV_WAR 0 |
||||
#define RM9000_CDEX_SMP_WAR 0 |
||||
#define ICACHE_REFILLS_WORKAROUND_WAR 0 |
||||
#define R10000_LLSC_WAR 0 |
||||
#define MIPS34K_MISSED_ITLB_WAR 0 |
||||
|
||||
#endif /* __ASM_MIPS_MACH_ADM8668_WAR_H */ |
@ -0,0 +1,126 @@ |
||||
/*
|
||||
* Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
* |
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||||
*/ |
||||
|
||||
#include <linux/module.h> |
||||
#include <linux/types.h> |
||||
#include <linux/kernel.h> |
||||
#include <linux/init.h> |
||||
#include <linux/mtd/mtd.h> |
||||
#include <linux/mtd/map.h> |
||||
#include <linux/mtd/partitions.h> |
||||
#include <linux/magic.h> |
||||
#include <asm/io.h> |
||||
|
||||
#define FLASH_SIZE 0x800000 |
||||
#define FLASH_PHYS_ADDR 0x10000000 |
||||
|
||||
/* just interested in part of the full struct */ |
||||
struct squashfs_super_block { |
||||
__le32 s_magic; |
||||
__le32 pad0[9]; /* it's not really padding */ |
||||
__le64 bytes_used; |
||||
}; |
||||
|
||||
static struct mtd_info *mymtd; |
||||
|
||||
static struct map_info nor_map = { |
||||
name: "adm8668-nor", |
||||
size: FLASH_SIZE, |
||||
phys: FLASH_PHYS_ADDR, |
||||
bankwidth: 2, |
||||
}; |
||||
|
||||
static struct mtd_partition nor_parts[] = { |
||||
{ name: "linux", offset: 0x40000, size: FLASH_SIZE - 0x40000, }, |
||||
{ name: "rootfs", offset: 0x200000, size: 0x400000, }, |
||||
{ name: NULL, }, |
||||
}; |
||||
|
||||
int __init init_mtd_partitions(struct mtd_info *mtd, size_t size) |
||||
{ |
||||
int blocksize, off; |
||||
size_t len; |
||||
struct squashfs_super_block hdr; |
||||
|
||||
blocksize = mtd->erasesize; |
||||
if (blocksize < 0x10000) |
||||
blocksize = 0x10000; |
||||
|
||||
memset(&hdr, 0xe5, sizeof(hdr)); |
||||
/* find and size squashfs */ |
||||
for (off = (128*1024); off < size; off += blocksize) { |
||||
if (mtd->read(mtd, off, sizeof(hdr), &len, (char *)&hdr) || |
||||
len != sizeof(hdr)) |
||||
continue; |
||||
|
||||
if (hdr.s_magic == SQUASHFS_MAGIC) { |
||||
printk(KERN_INFO "%s: Filesystem type: squashfs, off=%#x size=%#x\n", |
||||
mtd->name, off, (unsigned int)hdr.bytes_used); |
||||
/* Update the squashfs start address only! */ |
||||
nor_parts[1].offset = off; |
||||
nor_parts[1].size = FLASH_SIZE - off; |
||||
return 2; |
||||
} |
||||
} |
||||
return 2; |
||||
} |
||||
|
||||
int __init init_nor(void) |
||||
{ |
||||
int nr_parts; |
||||
|
||||
printk(KERN_NOTICE "ADM8668 NOR flash device: %#x at %#x\n", |
||||
FLASH_SIZE, FLASH_PHYS_ADDR); |
||||
|
||||
nor_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); |
||||
if (!nor_map.virt) { |
||||
printk("Failed to ioremap\n"); |
||||
return -EIO; |
||||
} |
||||
|
||||
simple_map_init(&nor_map); |
||||
mymtd = do_map_probe("cfi_probe", &nor_map); |
||||
if (!mymtd) { |
||||
iounmap((void *)nor_map.virt); |
||||
return -ENXIO; |
||||
} |
||||
mymtd->owner = THIS_MODULE; |
||||
nr_parts = init_mtd_partitions(mymtd, mymtd->size); |
||||
add_mtd_partitions(mymtd, nor_parts, nr_parts); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static void __exit cleanup_nor(void) |
||||
{ |
||||
if (mymtd) { |
||||
del_mtd_partitions(mymtd); |
||||
map_destroy(mymtd); |
||||
} |
||||
if (nor_map.virt) { |
||||
iounmap((void *)nor_map.virt); |
||||
nor_map.virt = 0; |
||||
} |
||||
} |
||||
|
||||
module_init(init_nor); |
||||
module_exit(cleanup_nor); |
||||
|
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_AUTHOR("Scott Nicholas <neutronscott@scottn.us>"); |
||||
MODULE_DESCRIPTION("MTD map driver for ADM8668 NOR Flash"); |
@ -0,0 +1,26 @@ |
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk |
||||
include $(INCLUDE_DIR)/image.mk |
||||
|
||||
define Build/Clean |
||||
$(MAKE) -C lzma-loader clean
|
||||
endef |
||||
|
||||
define Image/Prepare |
||||
cat $(KDIR)/vmlinux | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
|
||||
$(MAKE) -C lzma-loader \
|
||||
KDIR="$(KDIR)" \
|
||||
clean compile
|
||||
endef |
||||
|
||||
define Image/Build |
||||
./my-mkimage $(KDIR)/loader.bin $(KDIR)/root.squashfs \
|
||||
$(BIN_DIR)/$(IMG_PREFIX)-$(1).bin
|
||||
endef |
||||
|
||||
$(eval $(call BuildImage)) |
@ -0,0 +1,41 @@ |
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk |
||||
|
||||
PKG_NAME := loader
|
||||
PKG_VERSION := 0.05
|
||||
|
||||
PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME)-$(PKG_VERSION)$(LOADER_TYPE)
|
||||
|
||||
$(PKG_BUILD_DIR)/.prepared: |
||||
mkdir $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
touch $@
|
||||
|
||||
$(PKG_BUILD_DIR)/lzma.elf: $(PKG_BUILD_DIR)/.prepared $(PKG_BUILD_DIR)/vmlinux.lzma |
||||
PATH="$(TARGET_PATH)" $(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
CC="$(TARGET_CC)" CROSS_COMPILE="$(TARGET_CROSS)"
|
||||
|
||||
$(PKG_BUILD_DIR)/vmlinux.lzma: $(KDIR)/vmlinux.lzma |
||||
$(CP) $< $@
|
||||
|
||||
$(KDIR)/loader$(LOADER_TYPE).elf: $(PKG_BUILD_DIR)/lzma.elf |
||||
$(CP) $< $@
|
||||
|
||||
$(KDIR)/loader$(LOADER_TYPE).bin: $(PKG_BUILD_DIR)/lzma.bin |
||||
$(CP) $< $@
|
||||
|
||||
download: |
||||
prepare: $(PKG_BUILD_DIR)/.prepared |
||||
compile: $(KDIR)/loader$(LOADER_TYPE).elf $(KDIR)/loader$(LOADER_TYPE).bin |
||||
install: |
||||
|
||||
clean: |
||||
rm -rf $(PKG_BUILD_DIR)
|
||||
rm -f $(KDIR)/loader.elf
|
||||
rm -f $(KDIR)/loader.bin
|
@ -0,0 +1,590 @@ |
||||
/*
|
||||
LzmaDecode.c |
||||
LZMA Decoder (optimized for Speed version) |
||||
|
||||
LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10) |
||||
http://www.7-zip.org/
|
||||
|
||||
LZMA SDK is licensed under two licenses: |
||||
1) GNU Lesser General Public License (GNU LGPL) |
||||
2) Common Public License (CPL) |
||||
It means that you can select one of these two licenses and |
||||
follow rules of that license. |
||||
|
||||
SPECIAL EXCEPTION: |
||||
Igor Pavlov, as the author of this Code, expressly permits you to |
||||
statically or dynamically link your Code (or bind by name) to the |
||||
interfaces of this file without subjecting your linked Code to the |
||||
terms of the CPL or GNU LGPL. Any modifications or additions |
||||
to this file, however, are subject to the LGPL or CPL terms. |
||||
*/ |
||||
|
||||
#include "LzmaDecode.h" |
||||
|
||||
#ifndef Byte |
||||
#define Byte unsigned char |
||||
#endif |
||||
|
||||
#define kNumTopBits 24 |
||||
#define kTopValue ((UInt32)1 << kNumTopBits) |
||||
|
||||
#define kNumBitModelTotalBits 11 |
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits) |
||||
#define kNumMoveBits 5 |
||||
|
||||
#define RC_READ_BYTE (*Buffer++) |
||||
|
||||
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ |
||||
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} |
||||
|
||||
#ifdef _LZMA_IN_CB |
||||
|
||||
#define RC_TEST { if (Buffer == BufferLim) \ |
||||
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
|
||||
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} |
||||
|
||||
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 |
||||
|
||||
#else |
||||
|
||||
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } |
||||
|
||||
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 |
||||
|
||||
#endif |
||||
|
||||
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } |
||||
|
||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) |
||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; |
||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; |
||||
|
||||
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ |
||||
{ UpdateBit0(p); mi <<= 1; A0; } else \
|
||||
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; } |
||||
|
||||
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) |
||||
|
||||
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ |
||||
{ int i = numLevels; res = 1; \
|
||||
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
|
||||
res -= (1 << numLevels); } |
||||
|
||||
|
||||
#define kNumPosBitsMax 4 |
||||
#define kNumPosStatesMax (1 << kNumPosBitsMax) |
||||
|
||||
#define kLenNumLowBits 3 |
||||
#define kLenNumLowSymbols (1 << kLenNumLowBits) |
||||
#define kLenNumMidBits 3 |
||||
#define kLenNumMidSymbols (1 << kLenNumMidBits) |
||||
#define kLenNumHighBits 8 |
||||
#define kLenNumHighSymbols (1 << kLenNumHighBits) |
||||
|
||||
#define LenChoice 0 |
||||
#define LenChoice2 (LenChoice + 1) |
||||
#define LenLow (LenChoice2 + 1) |
||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) |
||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) |
||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols) |
||||
|
||||
|
||||
#define kNumStates 12 |
||||
#define kNumLitStates 7 |
||||
|
||||
#define kStartPosModelIndex 4 |
||||
#define kEndPosModelIndex 14 |
||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) |
||||
|
||||
#define kNumPosSlotBits 6 |
||||
#define kNumLenToPosStates 4 |
||||
|
||||
#define kNumAlignBits 4 |
||||
#define kAlignTableSize (1 << kNumAlignBits) |
||||
|
||||
#define kMatchMinLen 2 |
||||
|
||||
#define IsMatch 0 |
||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) |
||||
#define IsRepG0 (IsRep + kNumStates) |
||||
#define IsRepG1 (IsRepG0 + kNumStates) |
||||
#define IsRepG2 (IsRepG1 + kNumStates) |
||||
#define IsRep0Long (IsRepG2 + kNumStates) |
||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) |
||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) |
||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) |
||||
#define LenCoder (Align + kAlignTableSize) |
||||
#define RepLenCoder (LenCoder + kNumLenProbs) |
||||
#define Literal (RepLenCoder + kNumLenProbs) |
||||
|
||||
#if Literal != LZMA_BASE_SIZE |
||||
StopCompilingDueBUG |
||||
#endif |
||||
|
||||
#if 0 |
||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) |
||||
{ |
||||
unsigned char prop0; |
||||
if (size < LZMA_PROPERTIES_SIZE) |
||||
return LZMA_RESULT_DATA_ERROR; |
||||
prop0 = propsData[0]; |
||||
if (prop0 >= (9 * 5 * 5)) |
||||
return LZMA_RESULT_DATA_ERROR; |
||||
{ |
||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); |
||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); |
||||
propsRes->lc = prop0; |
||||
/*
|
||||
unsigned char remainder = (unsigned char)(prop0 / 9); |
||||
propsRes->lc = prop0 % 9; |
||||
propsRes->pb = remainder / 5; |
||||
propsRes->lp = remainder % 5; |
||||
*/ |
||||
} |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
{ |
||||
int i; |
||||
propsRes->DictionarySize = 0; |
||||
for (i = 0; i < 4; i++) |
||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); |
||||
if (propsRes->DictionarySize == 0) |
||||
propsRes->DictionarySize = 1; |
||||
} |
||||
#endif |
||||
return LZMA_RESULT_OK; |
||||
} |
||||
#endif |
||||
|
||||
#define kLzmaStreamWasFinishedId (-1) |
||||
|
||||
int LzmaDecode(CLzmaDecoderState *vs, |
||||
#ifdef _LZMA_IN_CB |
||||
ILzmaInCallback *InCallback, |
||||
#else |
||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, |
||||
#endif |
||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) |
||||
{ |
||||
CProb *p = vs->Probs; |
||||
SizeT nowPos = 0; |
||||
Byte previousByte = 0; |
||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; |
||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; |
||||
int lc = vs->Properties.lc; |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
|
||||
UInt32 Range = vs->Range; |
||||
UInt32 Code = vs->Code; |
||||
#ifdef _LZMA_IN_CB |
||||
const Byte *Buffer = vs->Buffer; |
||||
const Byte *BufferLim = vs->BufferLim; |
||||
#else |
||||
const Byte *Buffer = inStream; |
||||
const Byte *BufferLim = inStream + inSize; |
||||
#endif |
||||
int state = vs->State; |
||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; |
||||
int len = vs->RemainLen; |
||||
UInt32 globalPos = vs->GlobalPos; |
||||
UInt32 distanceLimit = vs->DistanceLimit; |
||||
|
||||
Byte *dictionary = vs->Dictionary; |
||||
UInt32 dictionarySize = vs->Properties.DictionarySize; |
||||
UInt32 dictionaryPos = vs->DictionaryPos; |
||||
|
||||
Byte tempDictionary[4]; |
||||
|
||||
#ifndef _LZMA_IN_CB |
||||
*inSizeProcessed = 0; |
||||
#endif |
||||
*outSizeProcessed = 0; |
||||
if (len == kLzmaStreamWasFinishedId) |
||||
return LZMA_RESULT_OK; |
||||
|
||||
if (dictionarySize == 0) |
||||
{ |
||||
dictionary = tempDictionary; |
||||
dictionarySize = 1; |
||||
tempDictionary[0] = vs->TempDictionary[0]; |
||||
} |
||||
|
||||
if (len == kLzmaNeedInitId) |
||||
{ |
||||
{ |
||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); |
||||
UInt32 i; |
||||
for (i = 0; i < numProbs; i++) |
||||
p[i] = kBitModelTotal >> 1; |
||||
rep0 = rep1 = rep2 = rep3 = 1; |
||||
state = 0; |
||||
globalPos = 0; |
||||
distanceLimit = 0; |
||||
dictionaryPos = 0; |
||||
dictionary[dictionarySize - 1] = 0; |
||||
#ifdef _LZMA_IN_CB |
||||
RC_INIT; |
||||
#else |
||||
RC_INIT(inStream, inSize); |
||||
#endif |
||||
} |
||||
len = 0; |
||||
} |
||||
while(len != 0 && nowPos < outSize) |
||||
{ |
||||
UInt32 pos = dictionaryPos - rep0; |
||||
if (pos >= dictionarySize) |
||||
pos += dictionarySize; |
||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; |
||||
if (++dictionaryPos == dictionarySize) |
||||
dictionaryPos = 0; |
||||
len--; |
||||
} |
||||
if (dictionaryPos == 0) |
||||
previousByte = dictionary[dictionarySize - 1]; |
||||
else |
||||
previousByte = dictionary[dictionaryPos - 1]; |
||||
|
||||
#else /* if !_LZMA_OUT_READ */ |
||||
|
||||
int state = 0; |
||||
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; |
||||
int len = 0; |
||||
const Byte *Buffer; |
||||
const Byte *BufferLim; |
||||
UInt32 Range; |
||||
UInt32 Code; |
||||
|
||||
#ifndef _LZMA_IN_CB |
||||
*inSizeProcessed = 0; |
||||
#endif |
||||
*outSizeProcessed = 0; |
||||
|
||||
{ |
||||
UInt32 i; |
||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); |
||||
for (i = 0; i < numProbs; i++) |
||||
p[i] = kBitModelTotal >> 1; |
||||
} |
||||
|
||||
#ifdef _LZMA_IN_CB |
||||
RC_INIT; |
||||
#else |
||||
RC_INIT(inStream, inSize); |
||||
#endif |
||||
|
||||
#endif /* _LZMA_OUT_READ */ |
||||
|
||||
while(nowPos < outSize) |
||||
{ |
||||
CProb *prob; |
||||
UInt32 bound; |
||||
int posState = (int)( |
||||
(nowPos |
||||
#ifdef _LZMA_OUT_READ |
||||
+ globalPos |
||||
#endif |
||||
) |
||||
& posStateMask); |
||||
|
||||
prob = p + IsMatch + (state << kNumPosBitsMax) + posState; |
||||
IfBit0(prob) |
||||
{ |
||||
int symbol = 1; |
||||
UpdateBit0(prob) |
||||
prob = p + Literal + (LZMA_LIT_SIZE * |
||||
((( |
||||
(nowPos |
||||
#ifdef _LZMA_OUT_READ |
||||
+ globalPos |
||||
#endif |
||||
) |
||||
& literalPosMask) << lc) + (previousByte >> (8 - lc)))); |
||||
|
||||
if (state >= kNumLitStates) |
||||
{ |
||||
int matchByte; |
||||
#ifdef _LZMA_OUT_READ |
||||
UInt32 pos = dictionaryPos - rep0; |
||||
if (pos >= dictionarySize) |
||||
pos += dictionarySize; |
||||
matchByte = dictionary[pos]; |
||||
#else |
||||
matchByte = outStream[nowPos - rep0]; |
||||
#endif |
||||
do |
||||
{ |
||||
int bit; |
||||
CProb *probLit; |
||||
matchByte <<= 1; |
||||
bit = (matchByte & 0x100); |
||||
probLit = prob + 0x100 + bit + symbol; |
||||
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) |
||||
} |
||||
while (symbol < 0x100); |
||||
} |
||||
while (symbol < 0x100) |
||||
{ |
||||
CProb *probLit = prob + symbol; |
||||
RC_GET_BIT(probLit, symbol) |
||||
} |
||||
previousByte = (Byte)symbol; |
||||
|
||||
outStream[nowPos++] = previousByte; |
||||
#ifdef _LZMA_OUT_READ |
||||
if (distanceLimit < dictionarySize) |
||||
distanceLimit++; |
||||
|
||||
dictionary[dictionaryPos] = previousByte; |
||||
if (++dictionaryPos == dictionarySize) |
||||
dictionaryPos = 0; |
||||
#endif |
||||
if (state < 4) state = 0; |
||||
else if (state < 10) state -= 3; |
||||
else state -= 6; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(prob); |
||||
prob = p + IsRep + state; |
||||
IfBit0(prob) |
||||
{ |
||||
UpdateBit0(prob); |
||||
rep3 = rep2; |
||||
rep2 = rep1; |
||||
rep1 = rep0; |
||||
state = state < kNumLitStates ? 0 : 3; |
||||
prob = p + LenCoder; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(prob); |
||||
prob = p + IsRepG0 + state; |
||||
IfBit0(prob) |
||||
{ |
||||
UpdateBit0(prob); |
||||
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; |
||||
IfBit0(prob) |
||||
{ |
||||
#ifdef _LZMA_OUT_READ |
||||
UInt32 pos; |
||||
#endif |
||||
UpdateBit0(prob); |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
if (distanceLimit == 0) |
||||
#else |
||||
if (nowPos == 0) |
||||
#endif |
||||
return LZMA_RESULT_DATA_ERROR; |
||||
|
||||
state = state < kNumLitStates ? 9 : 11; |
||||
#ifdef _LZMA_OUT_READ |
||||
pos = dictionaryPos - rep0; |
||||
if (pos >= dictionarySize) |
||||
pos += dictionarySize; |
||||
previousByte = dictionary[pos]; |
||||
dictionary[dictionaryPos] = previousByte; |
||||
if (++dictionaryPos == dictionarySize) |
||||
dictionaryPos = 0; |
||||
#else |
||||
previousByte = outStream[nowPos - rep0]; |
||||
#endif |
||||
outStream[nowPos++] = previousByte; |
||||
#ifdef _LZMA_OUT_READ |
||||
if (distanceLimit < dictionarySize) |
||||
distanceLimit++; |
||||
#endif |
||||
|
||||
continue; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(prob); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
UInt32 distance; |
||||
UpdateBit1(prob); |
||||
prob = p + IsRepG1 + state; |
||||
IfBit0(prob) |
||||
{ |
||||
UpdateBit0(prob); |
||||
distance = rep1; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(prob); |
||||
prob = p + IsRepG2 + state; |
||||
IfBit0(prob) |
||||
{ |
||||
UpdateBit0(prob); |
||||
distance = rep2; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(prob); |
||||
distance = rep3; |
||||
rep3 = rep2; |
||||
} |
||||
rep2 = rep1; |
||||
} |
||||
rep1 = rep0; |
||||
rep0 = distance; |
||||
} |
||||
state = state < kNumLitStates ? 8 : 11; |
||||
prob = p + RepLenCoder; |
||||
} |
||||
{ |
||||
int numBits, offset; |
||||
CProb *probLen = prob + LenChoice; |
||||
IfBit0(probLen) |
||||
{ |
||||
UpdateBit0(probLen); |
||||
probLen = prob + LenLow + (posState << kLenNumLowBits); |
||||
offset = 0; |
||||
numBits = kLenNumLowBits; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(probLen); |
||||
probLen = prob + LenChoice2; |
||||
IfBit0(probLen) |
||||
{ |
||||
UpdateBit0(probLen); |
||||
probLen = prob + LenMid + (posState << kLenNumMidBits); |
||||
offset = kLenNumLowSymbols; |
||||
numBits = kLenNumMidBits; |
||||
} |
||||
else |
||||
{ |
||||
UpdateBit1(probLen); |
||||
probLen = prob + LenHigh; |
||||
offset = kLenNumLowSymbols + kLenNumMidSymbols; |
||||
numBits = kLenNumHighBits; |
||||
} |
||||
} |
||||
RangeDecoderBitTreeDecode(probLen, numBits, len); |
||||
len += offset; |
||||
} |
||||
|
||||
if (state < 4) |
||||
{ |
||||
int posSlot; |
||||
state += kNumLitStates; |
||||
prob = p + PosSlot + |
||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << |
||||
kNumPosSlotBits); |
||||
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); |
||||
if (posSlot >= kStartPosModelIndex) |
||||
{ |
||||
int numDirectBits = ((posSlot >> 1) - 1); |
||||
rep0 = (2 | ((UInt32)posSlot & 1)); |
||||
if (posSlot < kEndPosModelIndex) |
||||
{ |
||||
rep0 <<= numDirectBits; |
||||
prob = p + SpecPos + rep0 - posSlot - 1; |
||||
} |
||||
else |
||||
{ |
||||
numDirectBits -= kNumAlignBits; |
||||
do |
||||
{ |
||||
RC_NORMALIZE |
||||
Range >>= 1; |
||||
rep0 <<= 1; |
||||
if (Code >= Range) |
||||
{ |
||||
Code -= Range; |
||||
rep0 |= 1; |
||||
} |
||||
} |
||||
while (--numDirectBits != 0); |
||||
prob = p + Align; |
||||
rep0 <<= kNumAlignBits; |
||||
numDirectBits = kNumAlignBits; |
||||
} |
||||
{ |
||||
int i = 1; |
||||
int mi = 1; |
||||
do |
||||
{ |
||||
CProb *prob3 = prob + mi; |
||||
RC_GET_BIT2(prob3, mi, ; , rep0 |= i); |
||||
i <<= 1; |
||||
} |
||||
while(--numDirectBits != 0); |
||||
} |
||||
} |
||||
else |
||||
rep0 = posSlot; |
||||
if (++rep0 == (UInt32)(0)) |
||||
{ |
||||
/* it's for stream version */ |
||||
len = kLzmaStreamWasFinishedId; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
len += kMatchMinLen; |
||||
#ifdef _LZMA_OUT_READ |
||||
if (rep0 > distanceLimit) |
||||
#else |
||||
if (rep0 > nowPos) |
||||
#endif |
||||
return LZMA_RESULT_DATA_ERROR; |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
if (dictionarySize - distanceLimit > (UInt32)len) |
||||
distanceLimit += len; |
||||
else |
||||
distanceLimit = dictionarySize; |
||||
#endif |
||||
|
||||
do |
||||
{ |
||||
#ifdef _LZMA_OUT_READ |
||||
UInt32 pos = dictionaryPos - rep0; |
||||
if (pos >= dictionarySize) |
||||
pos += dictionarySize; |
||||
previousByte = dictionary[pos]; |
||||
dictionary[dictionaryPos] = previousByte; |
||||
if (++dictionaryPos == dictionarySize) |
||||
dictionaryPos = 0; |
||||
#else |
||||
previousByte = outStream[nowPos - rep0]; |
||||
#endif |
||||
len--; |
||||
outStream[nowPos++] = previousByte; |
||||
} |
||||
while(len != 0 && nowPos < outSize); |
||||
} |
||||
} |
||||
RC_NORMALIZE; |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
vs->Range = Range; |
||||
vs->Code = Code; |
||||
vs->DictionaryPos = dictionaryPos; |
||||
vs->GlobalPos = globalPos + (UInt32)nowPos; |
||||
vs->DistanceLimit = distanceLimit; |
||||
vs->Reps[0] = rep0; |
||||
vs->Reps[1] = rep1; |
||||
vs->Reps[2] = rep2; |
||||
vs->Reps[3] = rep3; |
||||
vs->State = state; |
||||
vs->RemainLen = len; |
||||
vs->TempDictionary[0] = tempDictionary[0]; |
||||
#endif |
||||
|
||||
#ifdef _LZMA_IN_CB |
||||
vs->Buffer = Buffer; |
||||
vs->BufferLim = BufferLim; |
||||
#else |
||||
*inSizeProcessed = (SizeT)(Buffer - inStream); |
||||
#endif |
||||
*outSizeProcessed = nowPos; |
||||
return LZMA_RESULT_OK; |
||||
} |
@ -0,0 +1,131 @@ |
||||
/*
|
||||
LzmaDecode.h |
||||
LZMA Decoder interface |
||||
|
||||
LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08) |
||||
http://www.7-zip.org/
|
||||
|
||||
LZMA SDK is licensed under two licenses: |
||||
1) GNU Lesser General Public License (GNU LGPL) |
||||
2) Common Public License (CPL) |
||||
It means that you can select one of these two licenses and |
||||
follow rules of that license. |
||||
|
||||
SPECIAL EXCEPTION: |
||||
Igor Pavlov, as the author of this code, expressly permits you to |
||||
statically or dynamically link your code (or bind by name) to the |
||||
interfaces of this file without subjecting your linked code to the |
||||
terms of the CPL or GNU LGPL. Any modifications or additions |
||||
to this file, however, are subject to the LGPL or CPL terms. |
||||
*/ |
||||
|
||||
#ifndef __LZMADECODE_H |
||||
#define __LZMADECODE_H |
||||
|
||||
/* #define _LZMA_IN_CB */ |
||||
/* Use callback for input data */ |
||||
|
||||
/* #define _LZMA_OUT_READ */ |
||||
/* Use read function for output data */ |
||||
|
||||
/* #define _LZMA_PROB32 */ |
||||
/* It can increase speed on some 32-bit CPUs,
|
||||
but memory usage will be doubled in that case */ |
||||
|
||||
/* #define _LZMA_LOC_OPT */ |
||||
/* Enable local speed optimizations inside code */ |
||||
|
||||
/* #define _LZMA_SYSTEM_SIZE_T */ |
||||
/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/ |
||||
|
||||
#ifndef UInt32 |
||||
#ifdef _LZMA_UINT32_IS_ULONG |
||||
#define UInt32 unsigned long |
||||
#else |
||||
#define UInt32 unsigned int |
||||
#endif |
||||
#endif |
||||
|
||||
#ifndef SizeT |
||||
#ifdef _LZMA_SYSTEM_SIZE_T |
||||
#include <stddef.h> |
||||
#define SizeT size_t |
||||
#else |
||||
#define SizeT UInt32 |
||||
#endif |
||||
#endif |
||||
|
||||
#ifdef _LZMA_PROB32 |
||||
#define CProb UInt32 |
||||
#else |
||||
#define CProb unsigned short |
||||
#endif |
||||
|
||||
#define LZMA_RESULT_OK 0 |
||||
#define LZMA_RESULT_DATA_ERROR 1 |
||||
|
||||
#ifdef _LZMA_IN_CB |
||||
typedef struct _ILzmaInCallback |
||||
{ |
||||
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); |
||||
} ILzmaInCallback; |
||||
#endif |
||||
|
||||
#define LZMA_BASE_SIZE 1846 |
||||
#define LZMA_LIT_SIZE 768 |
||||
|
||||
#define LZMA_PROPERTIES_SIZE 5 |
||||
|
||||
typedef struct _CLzmaProperties |
||||
{ |
||||
int lc; |
||||
int lp; |
||||
int pb; |
||||
#ifdef _LZMA_OUT_READ |
||||
UInt32 DictionarySize; |
||||
#endif |
||||
}CLzmaProperties; |
||||
|
||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); |
||||
|
||||
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) |
||||
|
||||
#define kLzmaNeedInitId (-2) |
||||
|
||||
typedef struct _CLzmaDecoderState |
||||
{ |
||||
CLzmaProperties Properties; |
||||
CProb *Probs; |
||||
|
||||
#ifdef _LZMA_IN_CB |
||||
const unsigned char *Buffer; |
||||
const unsigned char *BufferLim; |
||||
#endif |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
unsigned char *Dictionary; |
||||
UInt32 Range; |
||||
UInt32 Code; |
||||
UInt32 DictionaryPos; |
||||
UInt32 GlobalPos; |
||||
UInt32 DistanceLimit; |
||||
UInt32 Reps[4]; |
||||
int State; |
||||
int RemainLen; |
||||
unsigned char TempDictionary[4]; |
||||
#endif |
||||
} CLzmaDecoderState; |
||||
|
||||
#ifdef _LZMA_OUT_READ |
||||
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } |
||||
#endif |
||||
|
||||
int LzmaDecode(CLzmaDecoderState *vs, |
||||
#ifdef _LZMA_IN_CB |
||||
ILzmaInCallback *inCallback, |
||||
#else |
||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, |
||||
#endif |
||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); |
||||
|
||||
#endif |
@ -0,0 +1,47 @@ |
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
RAMSTART = 0x80000000
|
||||
RAMSIZE = 0x00800000 # 1MB
|
||||
LOADADDR = 0x80400000 # RAM start + 4M
|
||||
KERNEL_ENTRY = 0x80002000
|
||||
|
||||
CROSS_COMPILE = mipsel-openwrt-linux-
|
||||
|
||||
OBJCOPY:= $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
|
||||
CFLAGS := -I./include -fno-builtin -Os -G 0 -ffunction-sections -mno-abicalls -fno-pic -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -Wall -DRAMSTART=${RAMSTART} -DRAMSIZE=${RAMSIZE} -DKERNEL_ENTRY=${KERNEL_ENTRY}
|
||||
|
||||
.c.o: |
||||
$(CC) $(CFLAGS) -c $< -o $*.o
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||
|
||||
O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
|
||||
|
||||
# Drop some uninteresting sections in the kernel.
|
||||
# This is only relevant for ELF kernels but doesn't hurt a.out
|
||||
drop-sections = .reginfo .mdebug .comment
|
||||
strip-flags = $(addprefix --remove-section=,$(drop-sections))
|
||||
|
||||
all : lzma.elf lzma.bin |
||||
|
||||
lzma.lds: lzma.lds.in |
||||
sed -e 's,@LOADADDR@,$(LOADADDR),g' $< >$@
|
||||
|
||||
kernel.o: vmlinux.lzma lzma.lds |
||||
$(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $<
|
||||
|
||||
lzma.bin: lzma.elf |
||||
$(OBJCOPY) $< $@
|
||||
|
||||
lzma.elf: decompress.o stubs.o LzmaDecode.o kernel.o lzma.lds |
||||
$(LD) -T lzma.lds -o $@ $^
|
||||
#-s ^
|
||||
|
||||
clean: |
||||
rm -f *.o lzma.elf lzma.bin *.tmp *.lds
|
@ -0,0 +1,118 @@ |
||||
/*
|
||||
* LZMA compressed kernel decompressor for bcm947xx boards |
||||
* |
||||
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> |
||||
* |
||||
* 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 |
||||
* |
||||
* |
||||
* Please note, this was code based on the bunzip2 decompressor code |
||||
* by Manuel Novoa III (mjn3@codepoet.org), although the only thing left |
||||
* is an idea and part of original vendor code |
||||
* |
||||
* |
||||
* 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com> |
||||
* pass actual output size to decoder (stream mode |
||||
* compressed input is not a requirement anymore) |
||||
* |
||||
* 24-Apr-2005 Oleg I. Vdovikin |
||||
* reordered functions using lds script, removed forward decl |
||||
* |
||||
* ??-Nov-2005 Mike Baker |
||||
* reorder the script as an lzma wrapper; do not depend on flash access |
||||
*/ |
||||
|
||||
#include "LzmaDecode.h" |
||||
#include <exports.h> |
||||
|
||||
#define KSEG0ADDR(addr) (0x80000000|addr) |
||||
|
||||
register volatile gd_t *gd asm ("k0"); |
||||
unsigned char *data; |
||||
|
||||
static __inline__ unsigned char get_byte() |
||||
{ |
||||
unsigned char *buffer; |
||||
|
||||
buffer = data; |
||||
data++; |
||||
|
||||
return *buffer; |
||||
} |
||||
|
||||
/* This puts lzma workspace 128k below RAM end.
|
||||
* That should be enough for both lzma and stack |
||||
*/ |
||||
static char *buffer = (char *)(RAMSTART + RAMSIZE - 0x00020000); |
||||
extern char _binary_vmlinux_lzma_start[]; |
||||
extern char _binary_vmlinux_lzma_end[]; |
||||
extern char lzma_start[]; |
||||
extern char lzma_end[]; |
||||
|
||||
/* should be the first function */ |
||||
void entry(unsigned int arg0, unsigned int arg1, |
||||
unsigned int arg2, unsigned int arg3) |
||||
{ |
||||
unsigned int i; /* temp value */ |
||||
unsigned int isize; /* compressed size */ |
||||
unsigned int osize; /* uncompressed size */ |
||||
int argc = arg0; |
||||
char **argv = (char **)arg1; |
||||
char **envp = (char **)arg2; |
||||
|
||||
CLzmaDecoderState vs; |
||||
|
||||
data = (unsigned char *)_binary_vmlinux_lzma_start; |
||||
isize = _binary_vmlinux_lzma_end - _binary_vmlinux_lzma_start + 1; |
||||
|
||||
puts("\nLZMA kernel loader\n"); |
||||
|
||||
printf("lzma data @ %#x - %#x\n", _binary_vmlinux_lzma_start, _binary_vmlinux_lzma_end); |
||||
printf("load addr @ %#x\n\n", KERNEL_ENTRY); |
||||
printf("jump table @ %#x\n", gd->jt[3]); |
||||
|
||||
/* lzma args */ |
||||
i = get_byte(); |
||||
vs.Properties.lc = i % 9, i = i / 9; |
||||
vs.Properties.lp = i % 5, vs.Properties.pb = i / 5; |
||||
|
||||
vs.Probs = (CProb *)buffer; |
||||
|
||||
/* skip rest of the LZMA coder property */ |
||||
data += 4; |
||||
|
||||
/* read the lower half of uncompressed size in the header */ |
||||
osize = ((unsigned int)get_byte()) + |
||||
((unsigned int)get_byte() << 8) + |
||||
((unsigned int)get_byte() << 16) + |
||||
((unsigned int)get_byte() << 24); |
||||
|
||||
/* skip rest of the header (upper half of uncompressed size) */ |
||||
data += 4; |
||||
|
||||
/* decompress kernel */ |
||||
puts("\nDecompressing kernel..."); |
||||
if ((i = LzmaDecode(&vs, |
||||
(unsigned char*)data, isize, &isize, |
||||
(unsigned char*)KERNEL_ENTRY, osize, &osize)) == LZMA_RESULT_OK) |
||||
{ |
||||
puts("success!\n"); |
||||
|
||||
/* Jump to load address */ |
||||
// ((void (*)(int a0, int a1, int a2, int a3))KERNEL_ENTRY)(0,0,0,0);
|
||||
((void (*)(int a0, int a1, int a2, int a3))KERNEL_ENTRY)(arg0, arg1, arg2, arg3); |
||||
} |
||||
puts("failure!\n"); |
||||
} |
@ -0,0 +1,18 @@ |
||||
EXPORT_FUNC(get_version) |
||||
EXPORT_FUNC(getc) |
||||
EXPORT_FUNC(tstc) |
||||
EXPORT_FUNC(putc) |
||||
EXPORT_FUNC(puts) |
||||
EXPORT_FUNC(printf) |
||||
EXPORT_FUNC(install_hdlr) |
||||
EXPORT_FUNC(free_hdlr) |
||||
EXPORT_FUNC(malloc) |
||||
EXPORT_FUNC(free) |
||||
EXPORT_FUNC(udelay) |
||||
EXPORT_FUNC(get_timer) |
||||
EXPORT_FUNC(vprintf) |
||||
EXPORT_FUNC(do_reset) |
||||
#if (CONFIG_COMMANDS & CFG_CMD_I2C) |
||||
EXPORT_FUNC(i2c_write) |
||||
EXPORT_FUNC(i2c_read) |
||||
#endif /* CFG_CMD_I2C */ |
@ -0,0 +1,60 @@ |
||||
/*
|
||||
* (C) Copyright 2002-2003 |
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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_GBL_DATA_H |
||||
#define __ASM_GBL_DATA_H |
||||
|
||||
#include <asm/regdef.h> |
||||
|
||||
/*
|
||||
* The following data structure is placed in some memory wich is |
||||
* available very early after boot (like DPRAM on MPC8xx/MPC82xx, or |
||||
* some locked parts of the data cache) to allow for a minimum set of |
||||
* global variables during system initialization (until we have set |
||||
* up the memory controller so that we can use RAM). |
||||
* |
||||
* Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) |
||||
*/ |
||||
|
||||
typedef struct global_data { |
||||
bd_t *bd; |
||||
unsigned long flags; |
||||
unsigned long baudrate; |
||||
unsigned long have_console; /* serial_init() was called */ |
||||
unsigned long ram_size; /* RAM size */ |
||||
unsigned long reloc_off; /* Relocation Offset */ |
||||
unsigned long env_addr; /* Address of Environment struct */ |
||||
unsigned long env_valid; /* Checksum of Environment valid? */ |
||||
void **jt; /* jump table */ |
||||
} gd_t; |
||||
|
||||
/*
|
||||
* Global Data Flags |
||||
*/ |
||||
#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */ |
||||
#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ |
||||
#define GD_FLG_SILENT 0x00004 /* Silent mode */ |
||||
|
||||
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("k0") |
||||
|
||||
#endif /* __ASM_GBL_DATA_H */ |
@ -0,0 +1,42 @@ |
||||
/*
|
||||
* (C) Copyright 2003 |
||||
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de> |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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 _U_BOOT_H_ |
||||
#define _U_BOOT_H_ 1 |
||||
|
||||
typedef struct bd_info { |
||||
int bi_baudrate; /* serial console baudrate */ |
||||
unsigned long bi_ip_addr; /* IP Address */ |
||||
unsigned char bi_enetaddr[6]; /* Ethernet adress */ |
||||
unsigned long bi_arch_number; /* unique id for this board */ |
||||
unsigned long bi_boot_params; /* where this board expects params */ |
||||
unsigned long bi_memstart; /* start of DRAM memory */ |
||||
unsigned long bi_memsize; /* size of DRAM memory in bytes */ |
||||
unsigned long bi_flashstart; /* start of FLASH memory */ |
||||
unsigned long bi_flashsize; /* size of FLASH memory */ |
||||
unsigned long bi_flashoffset; /* reserved area for startup monitor */ |
||||
} bd_t; |
||||
#define bi_env_data bi_env->data |
||||
#define bi_env_crc bi_env->crc |
||||
|
||||
#endif /* _U_BOOT_H_ */ |
@ -0,0 +1,48 @@ |
||||
/*
|
||||
* (C) Copyright 2000-2004 |
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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 __COMMON_H_ |
||||
#define __COMMON_H_ 1 |
||||
|
||||
#undef _LINUX_CONFIG_H |
||||
#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ |
||||
|
||||
typedef unsigned char uchar; |
||||
typedef volatile unsigned long vu_long; |
||||
typedef volatile unsigned short vu_short; |
||||
typedef volatile unsigned char vu_char; |
||||
|
||||
#include <inttypes.h> |
||||
#include <linux/types.h> |
||||
#include <linux/string.h> |
||||
#include <asm/ptrace.h> |
||||
#include <stdarg.h> |
||||
#include <image.h> |
||||
|
||||
typedef void (interrupt_handler_t)(void *); |
||||
|
||||
#include <asm/u-boot.h> /* boot information for Linux kernel */ |
||||
#include <asm/global_data.h> /* global data used for startup functions */ |
||||
|
||||
|
||||
#endif /* __COMMON_H_ */ |
@ -0,0 +1,38 @@ |
||||
#ifndef __EXPORTS_H__ |
||||
#define __EXPORTS_H__ |
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
||||
#ifndef __ASSEMBLY__ |
||||
|
||||
#include <common.h> |
||||
|
||||
/* These are declarations of exported functions available in C code */ |
||||
unsigned long get_version(void); |
||||
int getc(void); |
||||
int tstc(void); |
||||
void putc(const char); |
||||
void puts(const char*); |
||||
void printf(const char* fmt, ...); |
||||
void install_hdlr(int, interrupt_handler_t*, void*); |
||||
void free_hdlr(int); |
||||
void *malloc(size_t); |
||||
void free(void*); |
||||
void udelay(unsigned long); |
||||
unsigned long get_timer(unsigned long); |
||||
void vprintf(const char *, va_list); |
||||
void do_reset (void); |
||||
|
||||
void app_startup(char **); |
||||
|
||||
#endif /* ifndef __ASSEMBLY__ */ |
||||
|
||||
enum { |
||||
#define EXPORT_FUNC(x) XF_ ## x , |
||||
#include <_exports.h> |
||||
#undef EXPORT_FUNC |
||||
|
||||
XF_MAX |
||||
}; |
||||
|
||||
#define XF_VERSION 2 |
||||
|
||||
#endif /* __EXPORTS_H__ */ |
@ -0,0 +1,157 @@ |
||||
/*
|
||||
* (C) Copyright 2000 |
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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 __IMAGE_H__ |
||||
#define __IMAGE_H__ |
||||
|
||||
/*
|
||||
* Operating System Codes |
||||
*/ |
||||
#define IH_OS_INVALID 0 /* Invalid OS */ |
||||
#define IH_OS_OPENBSD 1 /* OpenBSD */ |
||||
#define IH_OS_NETBSD 2 /* NetBSD */ |
||||
#define IH_OS_FREEBSD 3 /* FreeBSD */ |
||||
#define IH_OS_4_4BSD 4 /* 4.4BSD */ |
||||
#define IH_OS_LINUX 5 /* Linux */ |
||||
#define IH_OS_SVR4 6 /* SVR4 */ |
||||
#define IH_OS_ESIX 7 /* Esix */ |
||||
#define IH_OS_SOLARIS 8 /* Solaris */ |
||||
#define IH_OS_IRIX 9 /* Irix */ |
||||
#define IH_OS_SCO 10 /* SCO */ |
||||
#define IH_OS_DELL 11 /* Dell */ |
||||
#define IH_OS_NCR 12 /* NCR */ |
||||
#define IH_OS_LYNXOS 13 /* LynxOS */ |
||||
#define IH_OS_VXWORKS 14 /* VxWorks */ |
||||
#define IH_OS_PSOS 15 /* pSOS */ |
||||
#define IH_OS_QNX 16 /* QNX */ |
||||
#define IH_OS_U_BOOT 17 /* Firmware */ |
||||
#define IH_OS_RTEMS 18 /* RTEMS */ |
||||
#define IH_OS_ARTOS 19 /* ARTOS */ |
||||
#define IH_OS_UNITY 20 /* Unity OS */ |
||||
|
||||
/*
|
||||
* CPU Architecture Codes (supported by Linux) |
||||
*/ |
||||
#define IH_CPU_INVALID 0 /* Invalid CPU */ |
||||
#define IH_CPU_ALPHA 1 /* Alpha */ |
||||
#define IH_CPU_ARM 2 /* ARM */ |
||||
#define IH_CPU_I386 3 /* Intel x86 */ |
||||
#define IH_CPU_IA64 4 /* IA64 */ |
||||
#define IH_CPU_MIPS 5 /* MIPS */ |
||||
#define IH_CPU_MIPS64 6 /* MIPS 64 Bit */ |
||||
#define IH_CPU_PPC 7 /* PowerPC */ |
||||
#define IH_CPU_S390 8 /* IBM S390 */ |
||||
#define IH_CPU_SH 9 /* SuperH */ |
||||
#define IH_CPU_SPARC 10 /* Sparc */ |
||||
#define IH_CPU_SPARC64 11 /* Sparc 64 Bit */ |
||||
#define IH_CPU_M68K 12 /* M68K */ |
||||
#define IH_CPU_NIOS 13 /* Nios-32 */ |
||||
#define IH_CPU_MICROBLAZE 14 /* MicroBlaze */ |
||||
#define IH_CPU_NIOS2 15 /* Nios-II */ |
||||
|
||||
/*
|
||||
* Image Types |
||||
* |
||||
* "Standalone Programs" are directly runnable in the environment |
||||
* provided by U-Boot; it is expected that (if they behave |
||||
* well) you can continue to work in U-Boot after return from |
||||
* the Standalone Program. |
||||
* "OS Kernel Images" are usually images of some Embedded OS which |
||||
* will take over control completely. Usually these programs |
||||
* will install their own set of exception handlers, device |
||||
* drivers, set up the MMU, etc. - this means, that you cannot |
||||
* expect to re-enter U-Boot except by resetting the CPU. |
||||
* "RAMDisk Images" are more or less just data blocks, and their |
||||
* parameters (address, size) are passed to an OS kernel that is |
||||
* being started. |
||||
* "Multi-File Images" contain several images, typically an OS |
||||
* (Linux) kernel image and one or more data images like |
||||
* RAMDisks. This construct is useful for instance when you want |
||||
* to boot over the network using BOOTP etc., where the boot |
||||
* server provides just a single image file, but you want to get |
||||
* for instance an OS kernel and a RAMDisk image. |
||||
* |
||||
* "Multi-File Images" start with a list of image sizes, each |
||||
* image size (in bytes) specified by an "uint32_t" in network |
||||
* byte order. This list is terminated by an "(uint32_t)0". |
||||
* Immediately after the terminating 0 follow the images, one by |
||||
* one, all aligned on "uint32_t" boundaries (size rounded up to |
||||
* a multiple of 4 bytes - except for the last file). |
||||
* |
||||
* "Firmware Images" are binary images containing firmware (like |
||||
* U-Boot or FPGA images) which usually will be programmed to |
||||
* flash memory. |
||||
* |
||||
* "Script files" are command sequences that will be executed by |
||||
* U-Boot's command interpreter; this feature is especially |
||||
* useful when you configure U-Boot to use a real shell (hush) |
||||
* as command interpreter (=> Shell Scripts). |
||||
*/ |
||||
|
||||
#define IH_TYPE_INVALID 0 /* Invalid Image */ |
||||
#define IH_TYPE_STANDALONE 1 /* Standalone Program */ |
||||
#define IH_TYPE_KERNEL 2 /* OS Kernel Image */ |
||||
#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */ |
||||
#define IH_TYPE_MULTI 4 /* Multi-File Image */ |
||||
#define IH_TYPE_FIRMWARE 5 /* Firmware Image */ |
||||
#define IH_TYPE_SCRIPT 6 /* Script file */ |
||||
#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */ |
||||
|
||||
/*
|
||||
* Compression Types |
||||
*/ |
||||
#define IH_COMP_NONE 0 /* No Compression Used */ |
||||
#define IH_COMP_GZIP 1 /* gzip Compression Used */ |
||||
#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */ |
||||
|
||||
#define IH_MAGIC 0x27051956 /* Image Magic Number */ |
||||
#define IH_NMLEN 32 /* Image Name Length */ |
||||
|
||||
#define IH_NAMEMAGIC 0x86680001 /* Name Magic Number */ |
||||
#define IH_SIZEMAX 5800000 /* Max image size */ |
||||
/*
|
||||
* all data in network byte order (aka natural aka bigendian) |
||||
*/ |
||||
|
||||
typedef struct image_header { |
||||
uint32_t ih_magic; /* Image Header Magic Number */ |
||||
uint32_t ih_hcrc; /* Image Header CRC Checksum */ |
||||
uint32_t ih_time; /* Image Creation Timestamp */ |
||||
uint32_t ih_size; /* Image Data Size */ |
||||
uint32_t ih_load; /* Data Load Address */ |
||||
uint32_t ih_ep; /* Entry Point Address */ |
||||
uint32_t ih_dcrc; /* Image Data CRC Checksum */ |
||||
uint8_t ih_os; /* Operating System */ |
||||
uint8_t ih_arch; /* CPU architecture */ |
||||
uint8_t ih_type; /* Image Type */ |
||||
uint8_t ih_comp; /* Compression Type */ |
||||
#ifdef NEW_IMAGE_HEADER |
||||
uint32_t ih_namemagic; /* image name CRC */ |
||||
uint8_t ih_name[IH_NMLEN-4]; /* image name */ |
||||
#else |
||||
uint8_t ih_name[IH_NMLEN]; /* Image Name */ |
||||
#endif |
||||
} image_header_t; |
||||
|
||||
|
||||
#endif /* __IMAGE_H__ */ |
@ -0,0 +1,24 @@ |
||||
OUTPUT_ARCH(mips) |
||||
ENTRY(entry) |
||||
SECTIONS |
||||
{ |
||||
/* Read-only sections, merged into text segment: */ |
||||
. = @LOADADDR@; |
||||
.text : |
||||
{ |
||||
_ftext = . ; |
||||
*(.text.entry) |
||||
*(.text) |
||||
lzma_start = .; |
||||
kernel.o |
||||
lzma_end = .; |
||||
*(.rodata) |
||||
} =0 |
||||
|
||||
.reginfo : { *(.reginfo) } |
||||
|
||||
.bss : |
||||
{ |
||||
*(.bss) |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
#include <exports.h> |
||||
|
||||
#ifndef GCC_VERSION |
||||
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) |
||||
#endif /* GCC_VERSION */ |
||||
|
||||
/*
|
||||
* k0 ($26) holds the pointer to the global_data; t9 ($25) is a call- |
||||
* clobbered register that is also used to set gp ($26). Note that the |
||||
* jr instruction also executes the instruction immediately following |
||||
* it; however, GCC/mips generates an additional `nop' after each asm |
||||
* statement |
||||
*/ |
||||
#define EXPORT_FUNC(x) \ |
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \ |
||||
" lw $25, %0($26)\n" \
|
||||
" lw $25, %1($25)\n" \
|
||||
" jr $25\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9"); |
||||
|
||||
/* This function is necessary to prevent the compiler from
|
||||
* generating prologue/epilogue, preparing stack frame etc. |
||||
* The stub functions are special, they do not use the stack |
||||
* frame passed to them, but pass it intact to the actual |
||||
* implementation. On the other hand, asm() statements with |
||||
* arguments can be used only inside the functions (gcc limitation) |
||||
*/ |
||||
#if GCC_VERSION < 3004 |
||||
static |
||||
#endif /* GCC_VERSION */ |
||||
void __attribute__((unused)) dummy(void) |
||||
{ |
||||
#include <_exports.h> |
||||
} |
||||
|
||||
#if 0 |
||||
extern unsigned long __bss_start, _end; |
||||
|
||||
void app_startup(char **argv) |
||||
{ |
||||
unsigned long * cp = &__bss_start; |
||||
|
||||
/* Zero out BSS */ |
||||
while (cp < &_end) { |
||||
*cp++ = 0; |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
#undef EXPORT_FUNC |
@ -0,0 +1,26 @@ |
||||
#!/bin/sh |
||||
# my-mkimage |
||||
# This will just pad the kernel partition to 64k boundary, then add rootfs. |
||||
# but we have to be fancy because u-boot mkimage is going to add 64 byte header. |
||||
# |
||||
# Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us> |
||||
|
||||
PATH_LOADER=$1 |
||||
PATH_ROOTFS=$2 |
||||
OUTPUT=$3 |
||||
|
||||
# todo - check arguments...? nah... |
||||
if [ -x $OUTPUT ]; then |
||||
echo usage: $0 loader.bin root.squashfs output.bin |
||||
exit |
||||
fi |
||||
|
||||
OLDSIZE=$(stat -c%s $PATH_LOADER) |
||||
NEWSIZE=$(((OLDSIZE / 65536 + 1) * 65536 - 64)) |
||||
|
||||
dd if=$PATH_LOADER of=vmlinuz.tmp bs=$NEWSIZE conv=sync |
||||
cat $PATH_ROOTFS >>vmlinuz.tmp |
||||
../../../../staging_dir/host/bin/mkimage -A mips -O linux -T kernel -C none -a 0x400000 -e 0x400000 -n "ADM8668 Linux Kernel(2.4.31)" -d vmlinuz.tmp $OUTPUT |
||||
rm vmlinuz.tmp |
||||
|
||||
printf '\n\nOk done, now your squashfs starts on an erase boundary of %x :)\n\n' $((NEWSIZE+64)) |
@ -0,0 +1,37 @@ |
||||
--- a/arch/mips/Kbuild.platforms 2010-10-20 16:30:22.000000000 -0400
|
||||
+++ b/arch/mips/Kbuild.platforms 2010-10-22 08:42:06.228968083 -0400
|
||||
@@ -27,6 +27,7 @@
|
||||
platforms += txx9
|
||||
platforms += vr41xx
|
||||
platforms += wrppmc
|
||||
+platforms += adm8668
|
||||
|
||||
# include the platform specific files
|
||||
include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
|
||||
--- a/arch/mips/Kconfig 2010-10-20 16:30:22.000000000 -0400
|
||||
+++ b/arch/mips/Kconfig 2010-10-22 08:37:31.016965108 -0400
|
||||
@@ -82,6 +82,24 @@
|
||||
help
|
||||
Support for BCM47XX based boards
|
||||
|
||||
+config ADM8668
|
||||
+ bool "WildPass ADM8668"
|
||||
+ select SYS_HAS_CPU_MIPS32_R1
|
||||
+ select IRQ_CPU
|
||||
+ select CEVT_R4K
|
||||
+ select CSRC_R4K
|
||||
+ select HW_HAS_PCI
|
||||
+ select PCI
|
||||
+ select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
+ select SYS_SUPPORTS_32BIT_KERNEL
|
||||
+ select DMA_NONCOHERENT
|
||||
+ select SWAP_IO_SPACE
|
||||
+ select SERIAL_ADM8668
|
||||
+ select SERIAL_ADM8668_CONSOLE
|
||||
+ help
|
||||
+ ADM8668 board support by neutronscott
|
||||
+ Scott Nicholas <neutronscott@scottn.us>
|
||||
+
|
||||
config BCM63XX
|
||||
bool "Broadcom BCM63XX based boards"
|
||||
select CEVT_R4K
|
@ -0,0 +1,41 @@ |
||||
--- a/drivers/serial/Kconfig
|
||||
+++ b/drivers/serial/Kconfig
|
||||
@@ -1510,6 +1510,25 @@
|
||||
If you have enabled the serial port on the bcm63xx CPU
|
||||
you can make it the console by answering Y to this option.
|
||||
|
||||
+config SERIAL_ADM8668
|
||||
+ tristate "ADM8668 serial port support"
|
||||
+ select SERIAL_CORE
|
||||
+ depends on ADM8668
|
||||
+ help
|
||||
+ If you have an adm8668 CPU, you can enable its onboard
|
||||
+ serial port by enabling this options.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called adm8668_uart.
|
||||
+
|
||||
+config SERIAL_ADM8668_CONSOLE
|
||||
+ bool "Console on adm8668 serial port"
|
||||
+ depends on SERIAL_ADM8668=y
|
||||
+ select SERIAL_CORE_CONSOLE
|
||||
+ help
|
||||
+ If you have enabled the serial port on the adm8668 CPU
|
||||
+ you can make it the console by answering Y to this option.
|
||||
+
|
||||
config SERIAL_GRLIB_GAISLER_APBUART
|
||||
tristate "GRLIB APBUART serial support"
|
||||
depends on OF
|
||||
--- a/include/linux/serial_core.h
|
||||
+++ b/include/linux/serial_core.h
|
||||
@@ -196,6 +196,9 @@
|
||||
/* High Speed UART for Medfield */
|
||||
#define PORT_MFD 95
|
||||
|
||||
+/* ADM8668 UART */
|
||||
+#define PORT_ADM8668 93
|
||||
+
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
@ -0,0 +1,25 @@ |
||||
--- a/drivers/mtd/maps/Kconfig
|
||||
+++ b/drivers/mtd/maps/Kconfig
|
||||
@@ -103,6 +103,12 @@
|
||||
default "0x02000000"
|
||||
depends on MSP_FLASH_MAP_LIMIT_32M
|
||||
|
||||
+config MTD_ADM8668_NOR
|
||||
+ tristate "ADM8668 NOR mapping"
|
||||
+ depends on ADM8668 && MTD_CFI
|
||||
+ help
|
||||
+ mapping driver for ADM8668 NOR
|
||||
+
|
||||
config MTD_SUN_UFLASH
|
||||
tristate "Sun Microsystems userflash support"
|
||||
depends on SPARC && MTD_CFI && PCI
|
||||
--- a/drivers/mtd/maps/Makefile
|
||||
+++ b/drivers/mtd/maps/Makefile
|
||||
@@ -7,6 +7,7 @@
|
||||
endif
|
||||
|
||||
# Chip mappings
|
||||
+obj-$(CONFIG_MTD_ADM8668_NOR) += adm8668.o
|
||||
obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
|
||||
obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
|
||||
obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
|
Loading…
Reference in new issue