1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-07-05 17:33:16 +03:00

[ifxmips] adss 2.6.33 kernel patches, not defult yet as linux-atm breaks on 2.6.33

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20789 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
blogic 2010-04-10 20:11:28 +00:00
parent 8803bd5059
commit 656f01b9c9
103 changed files with 9649 additions and 55 deletions

View File

@ -0,0 +1,12 @@
--- a/include/linux/atm.h
+++ b/include/linux/atm.h
@@ -139,6 +139,9 @@ struct atm_trafprm {
int min_pcr; /* minimum PCR in cells per second */
int max_cdv; /* maximum CDV in microseconds */
int max_sdu; /* maximum SDU in bytes */
+ int scr; /* sustained rate in cells per second */
+ int mbs; /* maximum burst size (MBS) in cells */
+ int cdv; /* Cell delay varition */
/* extra params for ABR */
unsigned int icr; /* Initial Cell Rate (24-bit) */
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */

View File

@ -10,8 +10,10 @@ ARCH:=mips
BOARD:=ifxmips
BOARDNAME:=Infineon Mips
FEATURES:=squashfs jffs2 atm
SUBTARGETS:=danube #ar9
LINUX_VERSION:=2.6.30.10
#LINUX_VERSION:=2.6.33.2
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time

View File

@ -0,0 +1,220 @@
CONFIG_32BIT=y
# CONFIG_64BIT is not set
CONFIG_ADM6996_PHY=y
# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
# CONFIG_AR7 is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_BCM47XX is not set
# CONFIG_BCM63XX is not set
CONFIG_BITREVERSE=y
# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
CONFIG_CEVT_R4K=y
CONFIG_CEVT_R4K_LIB=y
CONFIG_CMDLINE="console=ttyS0,9600 rootfstype=squashfs,jffs2"
CONFIG_CMDLINE_BOOL=y
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_CAVIUM_OCTEON is not set
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
# CONFIG_CPU_LOONGSON2E is not set
# CONFIG_CPU_LOONGSON2F is not set
CONFIG_CPU_MIPS32=y
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
CONFIG_CPU_MIPSR2=y
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R10000 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
# CONFIG_CPU_R5500 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
# CONFIG_CPU_TX39XX is not set
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_VR41XX is not set
CONFIG_CSRC_R4K=y
CONFIG_CSRC_R4K_LIB=y
CONFIG_DANUBE_MACH_ARV4519=y
CONFIG_DANUBE_MACH_ARV452=y
CONFIG_DANUBE_MACH_EASY4010=y
CONFIG_DANUBE_MACH_EASY50712=y
CONFIG_DECOMPRESS_LZMA=y
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
# CONFIG_DEFAULT_SECURITY_SMACK is not set
# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
CONFIG_DEVPORT=y
# CONFIG_DM9000 is not set
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_EARLY_PRINTK=y
# CONFIG_FSNOTIFY is not set
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_STD_PC_SERIAL_PORT=y
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
CONFIG_IFXMIPS=y
CONFIG_IFXMIPS_ARCAYDIAN_BRNBOOT=y
CONFIG_IFXMIPS_COMPAT=y
CONFIG_IFXMIPS_DANUBE=y
CONFIG_IFXMIPS_MII0=y
# CONFIG_IFXMIPS_PROM_ASC0 is not set
CONFIG_IFXMIPS_PROM_ASC1=y
CONFIG_IFXMIPS_WDT=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_INLINE_READ_LOCK is not set
# CONFIG_INLINE_READ_LOCK_BH is not set
# CONFIG_INLINE_READ_LOCK_IRQ is not set
# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
# CONFIG_INLINE_READ_TRYLOCK is not set
CONFIG_INLINE_READ_UNLOCK=y
# CONFIG_INLINE_READ_UNLOCK_BH is not set
CONFIG_INLINE_READ_UNLOCK_IRQ=y
# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_SPIN_LOCK is not set
# CONFIG_INLINE_SPIN_LOCK_BH is not set
# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
# CONFIG_INLINE_SPIN_TRYLOCK is not set
# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
CONFIG_INLINE_SPIN_UNLOCK=y
# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_WRITE_LOCK is not set
# CONFIG_INLINE_WRITE_LOCK_BH is not set
# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
# CONFIG_INLINE_WRITE_TRYLOCK is not set
CONFIG_INLINE_WRITE_UNLOCK=y
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
CONFIG_IRQ_CPU=y
# CONFIG_ISDN_CAPI is not set
# CONFIG_ISDN_DRV_GIGASET is not set
# CONFIG_ISDN_I4L is not set
CONFIG_KALLSYMS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_IFXMIPS=y
CONFIG_LOONGSON_UART_BASE=y
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_LOONGSON is not set
# CONFIG_MACH_TX39XX is not set
# CONFIG_MACH_TX49XX is not set
# CONFIG_MACH_VR41XX is not set
# CONFIG_MIKROTIK_RB532 is not set
CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=5
CONFIG_MIPS_MACHINE=y
# CONFIG_MIPS_MALTA is not set
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_SIM is not set
# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_IFXMIPS=y
# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
# CONFIG_MUTEX_SPIN_ON_OWNER is not set
CONFIG_NLS=y
# CONFIG_NO_IOPORT is not set
# CONFIG_NXP_STB220 is not set
# CONFIG_NXP_STB225 is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PHYLIB=y
# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_POWERTV is not set
CONFIG_RTL8306_PHY=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_IFXMIPS=y
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
# CONFIG_SGI_IP28 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_RHONE is not set
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_SWARM is not set
CONFIG_SOC_DANUBE=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
# CONFIG_TC35815 is not set
# CONFIG_TINY_RCU is not set
CONFIG_TRAD_SIGNALS=y
# CONFIG_TREE_PREEMPT_RCU is not set
CONFIG_TREE_RCU=y
CONFIG_USB=y
CONFIG_USB_DEBUG=y
# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set
CONFIG_ZONE_DMA_FLAG=0

View File

@ -0,0 +1,9 @@
ARCH:=mips
SUBTARGET:=danube
BOARDNAME:=Danube
FEATURES:=squashfs jffs2
define Target/Description
Infineon Danube
endef

View File

@ -0,0 +1,59 @@
if IFXMIPS
choice
prompt "Infineon SoC chip selection"
default SOC_DANUBE
help
Select Infineon MIPS SoC type.
config IFXMIPS_DANUBE
bool "Danube/Twinpass"
select SOC_DANUBE
endchoice
source "arch/mips/ifxmips/danube/Kconfig"
config SOC_DANUBE
bool
select DMA_NONCOHERENT
select IRQ_CPU
select CEVT_R4K
select CSRC_R4K
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
select HAVE_STD_PC_SERIAL_PORT
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_MULTITHREADING
select SYS_HAS_EARLY_PRINTK
select HW_HAS_PCI
select ARCH_REQUIRE_GPIOLIB
select SWAP_IO_SPACE
select MIPS_MACHINE
if EARLY_PRINTK
menu "Infineon SoC settings"
choice
prompt "Early printk port"
help
Choose which serial port is used, until the console driver is loaded
config IFXMIPS_PROM_ASC0
bool "ASC0"
config IFXMIPS_PROM_ASC1
bool "ASC1"
endchoice
config IFXMIPS_COMPAT
bool "Spinacer compatibility"
default y
help
Enable this to get some legacy API. This is needed if you use Lantiq DSL and VOIP drivers.
endmenu
endif
endif

View File

@ -0,0 +1 @@
obj-y := reset.o prom.o setup.o irq.o dma-core.o pmu.o board.o clock.o gpio.o timer.o dev-gpio-buttons.o

View File

@ -0,0 +1,29 @@
if IFXMIPS_DANUBE
config IFXMIPS_ARCAYDIAN_BRNBOOT
bool
default n
menu "infineon SoC machine selection"
config DANUBE_MACH_EASY50712
bool "Easy50712"
default y
config DANUBE_MACH_EASY4010
bool "Easy4010"
default y
config DANUBE_MACH_ARV4519
bool "ARV4519"
default y
select DANUBE_ARCAYDIAN_BRNBOOT
config DANUBE_MACH_ARV452
bool "ARV452"
default y
select IFXMIPS_ARCAYDIAN_BRNBOOT
endmenu
endif

View File

@ -0,0 +1,3 @@
obj-y := dma-core.o irq.o ebu.o setup.o devices.o cgu.o
obj-$(CONFIG_IFXMIPS_ARCAYDIAN_BRNBOOT) += arcaydian.o
obj-$(CONFIG_DANUBE_MACH_ARV452) += mach-arv452.o

View File

@ -0,0 +1,457 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#include <linux/autoconf.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#define MAX_BOARD_NAME_LEN 32
#define MAX_IFXMIPS_DEVS 9
#define SYSTEM_DANUBE "Danube"
#define SYSTEM_DANUBE_CHIPID1 0x00129083
#define SYSTEM_DANUBE_CHIPID2 0x0012B083
#define SYSTEM_TWINPASS "Twinpass"
#define SYSTEM_TWINPASS_CHIPID 0x0012D083
enum {
EASY50712,
EASY4010,
ARV4519,
ARV452,
};
extern int ifxmips_pci_external_clock;
extern int ifxmips_pci_req_mask;
static unsigned int chiprev;
static int cmdline_mac;
char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 };
struct ifxmips_board {
int type;
char name[32];
unsigned int system_type;
struct platform_device **devs;
struct resource reset_resource;
struct resource gpiodev_resource;
struct gpio_led *ifxmips_leds;
struct gpio_led *gpio_leds;
int pci_external_clock;
int pci_req_mask;
int num_devs;
};
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
extern unsigned char ifxmips_ethaddr[6];
static int ifxmips_brn;
static struct gpio_led_platform_data ifxmips_led_data;
static struct platform_device ifxmips_led = {
.id = 0,
.name = "ifxmips_led",
.dev = {
.platform_data = (void *) &ifxmips_led_data,
}
};
static struct platform_device ifxmips_gpio = {
.id = 0,
.name = "ifxmips_gpio",
.num_resources = 1,
};
static struct platform_device ifxmips_mii = {
.id = 0,
.name = "ifxmips_mii0",
.dev = {
.platform_data = ifxmips_ethaddr,
}
};
static struct platform_device ifxmips_wdt = {
.id = 0,
.name = "ifxmips_wdt",
};
static struct platform_device ifxmips_ebu = {
.id = 0,
.name = "ifxmips_ebu",
};
static struct resource ifxmips_mtd_resource = {
.start = IFXMIPS_FLASH_START,
.end = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ifxmips_mtd = {
.id = 0,
.name = "ifxmips_mtd",
.num_resources = 1,
.resource = &ifxmips_mtd_resource,
};
static struct platform_device ifxmips_gpio_dev = {
.name = "GPIODEV",
.id = -1,
.num_resources = 1,
};
#ifdef CONFIG_LEDS_GPIO
static struct gpio_led arv4519_gpio_leds[] = {
{ .name = "ifx:green:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 7, .active_low = 1, },
{ .name = "ifx:green:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:green:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:internet", .gpio = 8, .active_low = 1, },
{ .name = "ifx:green:wlan", .gpio = 6, .active_low = 1, },
{ .name = "ifx:green:usbpwr", .gpio = 14, .active_low = 1, },
{ .name = "ifx:green:usb", .gpio = 19, .active_low = 1, },
};
static struct gpio_led arv452_gpio_leds[] = {
{ .name = "ifx:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:blue:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:blue:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 6, .active_low = 1, },
{ .name = "ifx:yello:wps", .gpio = 7, .active_low = 1, },
{ .name = "ifx:red:wps", .gpio = 9, .active_low = 1, },
{ .name = "ifx:blue:voip", .gpio = 32, .active_low = 1, },
{ .name = "ifx:blue:fxs1", .gpio = 33, .active_low = 1, },
{ .name = "ifx:blue:fxs2", .gpio = 34, .active_low = 1, },
{ .name = "ifx:blue:fxo", .gpio = 35, .active_low = 1, },
{ .name = "ifx:blue:voice", .gpio = 36, .active_low = 1, },
{ .name = "ifx:blue:usb", .gpio = 37, .active_low = 1, },
{ .name = "ifx:blue:wlan", .gpio = 38, .active_low = 1, },
{ .name = "ifx:red:internet", .gpio = 41, .active_low = 1, },
};
static struct gpio_led_platform_data ifxmips_gpio_led_data;
static struct platform_device ifxmips_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = (void *) &ifxmips_gpio_led_data,
}
};
#endif
static struct resource dwc_usb_res[] = {
{
.name = "dwc3884_membase",
.flags = IORESOURCE_MEM,
.start = 0x1E101000,
.end = 0x1E101FFF
},
{
.name = "dwc3884_irq",
.flags = IORESOURCE_IRQ,
.start = IFXMIPS_USB_INT,
}
};
static struct platform_device dwc_usb =
{
.id = 0,
.name = "dwc3884-hcd",
.resource = dwc_usb_res,
.num_resources = ARRAY_SIZE(dwc_usb_res),
};
struct platform_device *easy50712_devs[] = {
&ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
&ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev, &dwc_usb
};
struct platform_device *easy4010_devs[] = {
&ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
&ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev, &dwc_usb
};
struct platform_device *arv5419_devs[] = {
&ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd,
&ifxmips_gpio_dev, &ifxmips_wdt, &dwc_usb,
#ifdef CONFIG_LEDS_GPIO
&ifxmips_gpio_leds,
#endif
};
struct platform_device *arv452_devs[] = {
&ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd,
&ifxmips_gpio_dev, &ifxmips_wdt, &dwc_usb,
&ifxmips_ebu,
#ifdef CONFIG_LEDS_GPIO
&ifxmips_gpio_leds,
#endif
};
static struct gpio_led easy50712_leds[] = {
{ .name = "ifx:green:test0", .gpio = 0,},
{ .name = "ifx:green:test1", .gpio = 1,},
{ .name = "ifx:green:test2", .gpio = 2,},
{ .name = "ifx:green:test3", .gpio = 3,},
};
static struct gpio_led easy4010_leds[] = {
{ .name = "ifx:green:test0", .gpio = 0,},
{ .name = "ifx:green:test1", .gpio = 1,},
{ .name = "ifx:green:test2", .gpio = 2,},
{ .name = "ifx:green:test3", .gpio = 3,},
};
static struct ifxmips_board boards[] = {
{
/* infineon eval kit */
.type = EASY50712,
.name = "EASY50712",
.system_type = SYSTEM_DANUBE_CHIPID1,
.devs = easy50712_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 15,},
.gpiodev_resource = { .name = "gpio",
.start = (1 << 0) | (1 << 1),
.end = (1 << 0) | (1 << 1)},
.ifxmips_leds = easy50712_leds,
}, {
/* infineon eval kit */
.type = EASY4010,
.name = "EASY4010",
.system_type = SYSTEM_TWINPASS_CHIPID,
.devs = easy4010_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 15},
.gpiodev_resource = { .name = "gpio",
.start = (1 << 0) | (1 << 1),
.end = (1 << 0) | (1 << 1)},
.ifxmips_leds = easy4010_leds,
}, {
/* arcaydian annex-a board used by thompson, airties, ... */
.type = ARV4519,
.name = "ARV4519",
.system_type = SYSTEM_DANUBE_CHIPID2,
.devs = arv5419_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 14},
.pci_external_clock = 1,
#ifdef CONFIG_LEDS_GPIO
.gpio_leds = arv4519_gpio_leds,
#endif
}, {
/* arcaydian annex-b board used by airties, arcor */
.type = ARV452,
.name = "ARV452",
.system_type = SYSTEM_DANUBE_CHIPID2,
.devs = arv452_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 14},
.pci_external_clock = 1,
#ifdef CONFIG_LEDS_GPIO
.gpio_leds = arv452_gpio_leds,
#endif
},
};
const char *get_system_type(void)
{
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
switch (chiprev) {
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
return SYSTEM_DANUBE;
case SYSTEM_TWINPASS_CHIPID:
return SYSTEM_TWINPASS;
}
return BOARD_SYSTEM_TYPE;
}
static int __init ifxmips_set_board_type(char *str)
{
str = strchr(str, '=');
if (!str)
goto out;
str++;
if (strlen(str) > MAX_BOARD_NAME_LEN)
goto out;
strncpy(board_name, str, MAX_BOARD_NAME_LEN);
printk(KERN_INFO "bootloader told us, that this is a %s board\n",
board_name);
out:
return 1;
}
__setup("ifxmips_board", ifxmips_set_board_type);
static int __init ifxmips_set_ethaddr(char *str)
{
#define IS_HEX(x) \
(((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') \
|| (x >= 'A' && x <= 'F')) ? (1) : (0))
int i;
str = strchr(str, '=');
if (!str)
goto out;
str++;
if (strlen(str) != 17)
goto out;
for (i = 0; i < 6; i++) {
if (!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
goto out;
if ((i != 5) && (str[(3 * i) + 2] != ':'))
goto out;
ifxmips_ethaddr[i] = simple_strtoul(&str[3 * i], NULL, 16);
}
if (is_valid_ether_addr(ifxmips_ethaddr))
cmdline_mac = 1;
out:
return 1;
}
__setup("ethaddr", ifxmips_set_ethaddr);
int ifxmips_find_brn_block(void)
{
unsigned char temp[8];
memcpy_fromio(temp,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
if (memcmp(temp, "BRN-BOOT", 8) == 0) {
if (!cmdline_mac)
memcpy_fromio(ifxmips_ethaddr,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START +
0x800000 - 0x10000 + 0x16), 6);
if (is_valid_ether_addr(ifxmips_ethaddr))
cmdline_mac = 1;
return 1;
} else {
return 0;
}
}
int ifxmips_has_brn_block(void)
{
return ifxmips_brn;
}
EXPORT_SYMBOL(ifxmips_has_brn_block);
struct ifxmips_board *ifxmips_find_board(void)
{
int i;
if (!*board_name)
return 0;
for (i = 0; i < ARRAY_SIZE(boards); i++)
if ((boards[i].system_type == chiprev) &&
(!strcmp(boards[i].name, board_name)))
return &boards[i];
return 0;
}
int __init ifxmips_init_devices(void)
{
struct ifxmips_board *board;
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
board = ifxmips_find_board();
ifxmips_brn = ifxmips_find_brn_block();
if (!cmdline_mac)
random_ether_addr(ifxmips_ethaddr);
if (!board) {
switch (chiprev) {
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
default:
board = &boards[0];
break;
case SYSTEM_TWINPASS_CHIPID:
board = &boards[1];
break;
}
}
switch (board->type) {
case EASY50712:
board->num_devs = ARRAY_SIZE(easy50712_devs);
ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds);
break;
case EASY4010:
board->num_devs = ARRAY_SIZE(easy4010_devs);
ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds);
break;
case ARV4519:
/* set some sane defaults for the gpios */
gpio_set_value(3, 0);
gpio_set_value(4, 0);
gpio_set_value(5, 0);
gpio_set_value(6, 0);
gpio_set_value(7, 1);
gpio_set_value(8, 1);
gpio_set_value(19, 0);
board->num_devs = ARRAY_SIZE(arv5419_devs);
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv4519_gpio_leds);
#endif
break;
case ARV452:
/* set some sane defaults for the gpios */
board->num_devs = ARRAY_SIZE(arv452_devs);
ifxmips_w32(0x8001e7ff, IFXMIPS_EBU_BUSCON1);
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv452_gpio_leds);
#endif
break;
}
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.leds = board->gpio_leds;
#endif
ifxmips_led_data.leds = board->ifxmips_leds;
printk(KERN_INFO "%s: adding %d devs\n",
__func__, board->num_devs);
ifxmips_gpio.resource = &board->reset_resource;
ifxmips_gpio_dev.resource = &board->gpiodev_resource;
if (board->pci_external_clock)
ifxmips_pci_external_clock = 1;
if (board->pci_req_mask)
ifxmips_pci_req_mask = board->pci_req_mask;
printk(KERN_INFO "using board definition %s\n", board->name);
return platform_add_devices(board->devs, board->num_devs);
}
arch_initcall(ifxmips_init_devices);

View File

@ -0,0 +1,38 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
void
cgu_setup_pci_clk(int external_clock)
{
/* set clock to 33Mhz */
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~0xf00000,
IFXMIPS_CGU_IFCCR);
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | 0x800000,
IFXMIPS_CGU_IFCCR);
if (external_clock)
{
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~(1 << 16),
IFXMIPS_CGU_IFCCR);
ifxmips_w32((1 << 30), IFXMIPS_CGU_PCICR);
} else {
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | (1 << 16),
IFXMIPS_CGU_IFCCR);
ifxmips_w32((1 << 31) | (1 << 30), IFXMIPS_CGU_PCICR);
}
}

View File

@ -0,0 +1,33 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
/* pci */
extern int ifxmips_pci_external_clock;
extern int ifxmips_pci_req_mask;
void __init
ar9_register_pci(int clock, int irq_mask)
{
ifxmips_pci_external_clock = clock;
if(irq_mask)
ifxmips_pci_req_mask = irq_mask;
}

View File

@ -0,0 +1,16 @@
#ifndef _DANUBE_DEVICES_H__
#define _DANUBE_DEVICES_H__
#include "../common/devices.h"
enum {
PCI_CLOCK_INT = 0,
PCI_CLOCK_EXT
};
void __init danube_register_usb(void);
void __init danube_register_ebu_gpio(struct resource *resource, u32 value);
void __init danube_register_ethernet(unsigned char *mac);
void __init danube_register_pci(int clock, int irq_mask);
#endif

View File

@ -0,0 +1,690 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/selection.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_dma.h>
#include <ifxmips_pmu.h>
/*25 descriptors for each dma channel,4096/8/20=25.xx*/
#define IFXMIPS_DMA_DESCRIPTOR_OFFSET 25
#define MAX_DMA_DEVICE_NUM 6 /*max ports connecting to dma */
#define MAX_DMA_CHANNEL_NUM 20 /*max dma channels */
#define DMA_INT_BUDGET 100 /*budget for interrupt handling */
#define DMA_POLL_COUNTER 4 /*fix me, set the correct counter value here! */
extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr);
extern void ifxmips_enable_irq(unsigned int irq_nr);
extern void ifxmips_disable_irq(unsigned int irq_nr);
u64 *g_desc_list;
struct dma_device_info dma_devs[MAX_DMA_DEVICE_NUM];
struct dma_channel_info dma_chan[MAX_DMA_CHANNEL_NUM];
static const char *global_device_name[MAX_DMA_DEVICE_NUM] =
{ "PPE", "DEU", "SPI", "SDIO", "MCTRL0", "MCTRL1" };
struct dma_chan_map default_dma_map[MAX_DMA_CHANNEL_NUM] = {
{"PPE", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH0_INT, 0},
{"PPE", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH1_INT, 0},
{"PPE", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH2_INT, 1},
{"PPE", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH3_INT, 1},
{"PPE", IFXMIPS_DMA_RX, 2, IFXMIPS_DMA_CH4_INT, 2},
{"PPE", IFXMIPS_DMA_TX, 2, IFXMIPS_DMA_CH5_INT, 2},
{"PPE", IFXMIPS_DMA_RX, 3, IFXMIPS_DMA_CH6_INT, 3},
{"PPE", IFXMIPS_DMA_TX, 3, IFXMIPS_DMA_CH7_INT, 3},
{"DEU", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH8_INT, 0},
{"DEU", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH9_INT, 0},
{"DEU", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH10_INT, 1},
{"DEU", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH11_INT, 1},
{"SPI", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH12_INT, 0},
{"SPI", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH13_INT, 0},
{"SDIO", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH14_INT, 0},
{"SDIO", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH15_INT, 0},
{"MCTRL0", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH16_INT, 0},
{"MCTRL0", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH17_INT, 0},
{"MCTRL1", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH18_INT, 1},
{"MCTRL1", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH19_INT, 1}
};
struct dma_chan_map *chan_map = default_dma_map;
volatile u32 g_ifxmips_dma_int_status;
volatile int g_ifxmips_dma_in_process; /* 0=not in process, 1=in process */
void do_dma_tasklet(unsigned long);
DECLARE_TASKLET(dma_tasklet, do_dma_tasklet, 0);
u8 *common_buffer_alloc(int len, int *byte_offset, void **opt)
{
u8 *buffer = kmalloc(len * sizeof(u8), GFP_KERNEL);
*byte_offset = 0;
return buffer;
}
void common_buffer_free(u8 *dataptr, void *opt)
{
kfree(dataptr);
}
void enable_ch_irq(struct dma_channel_info *pCh)
{
int chan_no = (int)(pCh - dma_chan);
unsigned long flag;
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0x4a, IFXMIPS_DMA_CIE);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
local_irq_restore(flag);
ifxmips_enable_irq(pCh->irq);
}
void disable_ch_irq(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int) (pCh - dma_chan);
local_irq_save(flag);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0, IFXMIPS_DMA_CIE);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN);
local_irq_restore(flag);
ifxmips_mask_and_ack_irq(pCh->irq);
}
void open_chan(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int)(pCh - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 1, IFXMIPS_DMA_CCTRL);
if (pCh->dir == IFXMIPS_DMA_RX)
enable_ch_irq(pCh);
local_irq_restore(flag);
}
void close_chan(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int) (pCh - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
disable_ch_irq(pCh);
local_irq_restore(flag);
}
void reset_chan(struct dma_channel_info *pCh)
{
int chan_no = (int) (pCh - dma_chan);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
}
void rx_chan_intr_handler(int chan_no)
{
struct dma_device_info *pDev = (struct dma_device_info *)dma_chan[chan_no].dma_dev;
struct dma_channel_info *pCh = &dma_chan[chan_no];
struct rx_desc *rx_desc_p;
int tmp;
unsigned long flag;
/*handle command complete interrupt */
rx_desc_p = (struct rx_desc *)pCh->desc_base + pCh->curr_desc;
if (rx_desc_p->status.field.OWN == CPU_OWN
&& rx_desc_p->status.field.C
&& rx_desc_p->status.field.data_length < 1536){
/* Every thing is correct, then we inform the upper layer */
pDev->current_rx_chan = pCh->rel_chan_no;
if (pDev->intr_handler)
pDev->intr_handler(pDev, RCV_INT);
pCh->weight--;
} else {
local_irq_save(flag);
tmp = ifxmips_r32(IFXMIPS_DMA_CS);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS);
ifxmips_w32(tmp, IFXMIPS_DMA_CS);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
local_irq_restore(flag);
ifxmips_enable_irq(dma_chan[chan_no].irq);
}
}
inline void tx_chan_intr_handler(int chan_no)
{
struct dma_device_info *pDev = (struct dma_device_info *)dma_chan[chan_no].dma_dev;
struct dma_channel_info *pCh = &dma_chan[chan_no];
int tmp;
unsigned long flag;
local_irq_save(flag);
tmp = ifxmips_r32(IFXMIPS_DMA_CS);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS);
ifxmips_w32(tmp, IFXMIPS_DMA_CS);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
local_irq_restore(flag);
pDev->current_tx_chan = pCh->rel_chan_no;
if (pDev->intr_handler)
pDev->intr_handler(pDev, TRANSMIT_CPT_INT);
}
void do_dma_tasklet(unsigned long unused)
{
int i;
int chan_no = 0;
int budget = DMA_INT_BUDGET;
int weight = 0;
unsigned long flag;
while (g_ifxmips_dma_int_status) {
if (budget-- < 0) {
tasklet_schedule(&dma_tasklet);
return;
}
chan_no = -1;
weight = 0;
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
if ((g_ifxmips_dma_int_status & (1 << i)) && dma_chan[i].weight > 0) {
if (dma_chan[i].weight > weight) {
chan_no = i;
weight = dma_chan[chan_no].weight;
}
}
}
if (chan_no >= 0) {
if (chan_map[chan_no].dir == IFXMIPS_DMA_RX)
rx_chan_intr_handler(chan_no);
else
tx_chan_intr_handler(chan_no);
} else {
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++)
dma_chan[i].weight = dma_chan[i].default_weight;
}
}
local_irq_save(flag);
g_ifxmips_dma_in_process = 0;
if (g_ifxmips_dma_int_status) {
g_ifxmips_dma_in_process = 1;
tasklet_schedule(&dma_tasklet);
}
local_irq_restore(flag);
}
irqreturn_t dma_interrupt(int irq, void *dev_id)
{
struct dma_channel_info *pCh;
int chan_no = 0;
int tmp;
pCh = (struct dma_channel_info *)dev_id;
chan_no = (int)(pCh - dma_chan);
if (chan_no < 0 || chan_no > 19)
BUG();
tmp = ifxmips_r32(IFXMIPS_DMA_IRNEN);
ifxmips_w32(0, IFXMIPS_DMA_IRNEN);
g_ifxmips_dma_int_status |= 1 << chan_no;
ifxmips_w32(tmp, IFXMIPS_DMA_IRNEN);
ifxmips_mask_and_ack_irq(irq);
if (!g_ifxmips_dma_in_process) {
g_ifxmips_dma_in_process = 1;
tasklet_schedule(&dma_tasklet);
}
return IRQ_HANDLED;
}
struct dma_device_info *dma_device_reserve(char *dev_name)
{
int i;
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) {
if (strcmp(dev_name, dma_devs[i].device_name) == 0) {
if (dma_devs[i].reserved)
return NULL;
dma_devs[i].reserved = 1;
break;
}
}
return &dma_devs[i];
}
EXPORT_SYMBOL(dma_device_reserve);
void dma_device_release(struct dma_device_info *dev)
{
dev->reserved = 0;
}
EXPORT_SYMBOL(dma_device_release);
void dma_device_register(struct dma_device_info *dev)
{
int i, j;
int chan_no = 0;
u8 *buffer;
int byte_offset;
unsigned long flag;
struct dma_device_info *pDev;
struct dma_channel_info *pCh;
struct rx_desc *rx_desc_p;
struct tx_desc *tx_desc_p;
for (i = 0; i < dev->max_tx_chan_num; i++) {
pCh = dev->tx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(pCh - dma_chan);
for (j = 0; j < pCh->desc_len; j++) {
tx_desc_p = (struct tx_desc *)pCh->desc_base + j;
memset(tx_desc_p, 0, sizeof(struct tx_desc));
}
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
/* check if the descriptor length is changed */
if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len)
ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2)
;
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
ifxmips_w32(0x30100, IFXMIPS_DMA_CCTRL); /* reset and enable channel,enable channel later */
local_irq_restore(flag);
}
}
for (i = 0; i < dev->max_rx_chan_num; i++) {
pCh = dev->rx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(pCh - dma_chan);
for (j = 0; j < pCh->desc_len; j++) {
rx_desc_p = (struct rx_desc *)pCh->desc_base + j;
pDev = (struct dma_device_info *)(pCh->dma_dev);
buffer = pDev->buffer_alloc(pCh->packet_size, &byte_offset, (void *)&(pCh->opt[j]));
if (!buffer)
break;
dma_cache_inv((unsigned long) buffer, pCh->packet_size);
rx_desc_p->Data_Pointer = (u32)CPHYSADDR((u32)buffer);
rx_desc_p->status.word = 0;
rx_desc_p->status.field.byte_offset = byte_offset;
rx_desc_p->status.field.OWN = DMA_OWN;
rx_desc_p->status.field.data_length = pCh->packet_size;
}
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
/* check if the descriptor length is changed */
if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len)
ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2)
;
ifxmips_w32(0x0a, IFXMIPS_DMA_CIE); /* fix me, should enable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
ifxmips_w32(0x30000, IFXMIPS_DMA_CCTRL);
local_irq_restore(flag);
ifxmips_enable_irq(dma_chan[chan_no].irq);
}
}
}
EXPORT_SYMBOL(dma_device_register);
void dma_device_unregister(struct dma_device_info *dev)
{
int i, j;
int chan_no;
struct dma_channel_info *pCh;
struct rx_desc *rx_desc_p;
struct tx_desc *tx_desc_p;
unsigned long flag;
for (i = 0; i < dev->max_tx_chan_num; i++) {
pCh = dev->tx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(dev->tx_chan[i] - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
pCh->curr_desc = 0;
pCh->prev_desc = 0;
pCh->control = IFXMIPS_DMA_CH_OFF;
ifxmips_w32(0, IFXMIPS_DMA_CIE); /* fix me, should disable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /* disable interrupts */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1)
;
local_irq_restore(flag);
for (j = 0; j < pCh->desc_len; j++) {
tx_desc_p = (struct tx_desc *)pCh->desc_base + j;
if ((tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C)
|| (tx_desc_p->status.field.OWN == DMA_OWN && tx_desc_p->status.field.data_length > 0)) {
dev->buffer_free((u8 *) __va(tx_desc_p->Data_Pointer), (void *)pCh->opt[j]);
}
tx_desc_p->status.field.OWN = CPU_OWN;
memset(tx_desc_p, 0, sizeof(struct tx_desc));
}
/* TODO should free buffer that is not transferred by dma */
}
}
for (i = 0; i < dev->max_rx_chan_num; i++) {
pCh = dev->rx_chan[i];
chan_no = (int)(dev->rx_chan[i] - dma_chan);
ifxmips_disable_irq(pCh->irq);
local_irq_save(flag);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
pCh->curr_desc = 0;
pCh->prev_desc = 0;
pCh->control = IFXMIPS_DMA_CH_OFF;
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0, IFXMIPS_DMA_CIE); /* fix me, should disable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /* disable interrupts */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1)
;
local_irq_restore(flag);
for (j = 0; j < pCh->desc_len; j++) {
rx_desc_p = (struct rx_desc *) pCh->desc_base + j;
if ((rx_desc_p->status.field.OWN == CPU_OWN
&& rx_desc_p->status.field.C)
|| (rx_desc_p->status.field.OWN == DMA_OWN
&& rx_desc_p->status.field.data_length > 0)) {
dev->buffer_free((u8 *)
__va(rx_desc_p->Data_Pointer),
(void *) pCh->opt[j]);
}
}
}
}
EXPORT_SYMBOL(dma_device_unregister);
int dma_device_read(struct dma_device_info *dma_dev, u8 **dataptr, void **opt)
{
u8 *buf;
int len;
int byte_offset = 0;
void *p = NULL;
struct dma_channel_info *pCh = dma_dev->rx_chan[dma_dev->current_rx_chan];
struct rx_desc *rx_desc_p;
/* get the rx data first */
rx_desc_p = (struct rx_desc *) pCh->desc_base + pCh->curr_desc;
if (!(rx_desc_p->status.field.OWN == CPU_OWN && rx_desc_p->status.field.C))
return 0;
buf = (u8 *) __va(rx_desc_p->Data_Pointer);
*(u32 *)dataptr = (u32)buf;
len = rx_desc_p->status.field.data_length;
if (opt)
*(int *)opt = (int)pCh->opt[pCh->curr_desc];
/* replace with a new allocated buffer */
buf = dma_dev->buffer_alloc(pCh->packet_size, &byte_offset, &p);
if (buf) {
dma_cache_inv((unsigned long) buf, pCh->packet_size);
pCh->opt[pCh->curr_desc] = p;
wmb();
rx_desc_p->Data_Pointer = (u32) CPHYSADDR((u32) buf);
rx_desc_p->status.word = (DMA_OWN << 31) | ((byte_offset) << 23) | pCh->packet_size;
wmb();
} else {
*(u32 *) dataptr = 0;
if (opt)
*(int *) opt = 0;
len = 0;
}
/* increase the curr_desc pointer */
pCh->curr_desc++;
if (pCh->curr_desc == pCh->desc_len)
pCh->curr_desc = 0;
return len;
}
EXPORT_SYMBOL(dma_device_read);
int dma_device_write(struct dma_device_info *dma_dev, u8 *dataptr, int len, void *opt)
{
unsigned long flag;
u32 tmp, byte_offset;
struct dma_channel_info *pCh;
int chan_no;
struct tx_desc *tx_desc_p;
local_irq_save(flag);
pCh = dma_dev->tx_chan[dma_dev->current_tx_chan];
chan_no = (int)(pCh - (struct dma_channel_info *) dma_chan);
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->prev_desc;
while (tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C) {
dma_dev->buffer_free((u8 *) __va(tx_desc_p->Data_Pointer), pCh->opt[pCh->prev_desc]);
memset(tx_desc_p, 0, sizeof(struct tx_desc));
pCh->prev_desc = (pCh->prev_desc + 1) % (pCh->desc_len);
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->prev_desc;
}
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->curr_desc;
/* Check whether this descriptor is available */
if (tx_desc_p->status.field.OWN == DMA_OWN || tx_desc_p->status.field.C) {
/* if not, the tell the upper layer device */
dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT);
local_irq_restore(flag);
printk(KERN_INFO "%s %d: failed to write!\n", __func__, __LINE__);
return 0;
}
pCh->opt[pCh->curr_desc] = opt;
/* byte offset----to adjust the starting address of the data buffer, should be multiple of the burst length. */
byte_offset = ((u32) CPHYSADDR((u32) dataptr)) % ((dma_dev->tx_burst_len) * 4);
dma_cache_wback((unsigned long) dataptr, len);
wmb();
tx_desc_p->Data_Pointer = (u32) CPHYSADDR((u32) dataptr) - byte_offset;
wmb();
tx_desc_p->status.word = (DMA_OWN << 31) | DMA_DESC_SOP_SET | DMA_DESC_EOP_SET | ((byte_offset) << 23) | len;
wmb();
pCh->curr_desc++;
if (pCh->curr_desc == pCh->desc_len)
pCh->curr_desc = 0;
/*Check whether this descriptor is available */
tx_desc_p = (struct tx_desc *) pCh->desc_base + pCh->curr_desc;
if (tx_desc_p->status.field.OWN == DMA_OWN) {
/*if not , the tell the upper layer device */
dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT);
}
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
tmp = ifxmips_r32(IFXMIPS_DMA_CCTRL);
if (!(tmp & 1))
pCh->open(pCh);
local_irq_restore(flag);
return len;
}
EXPORT_SYMBOL(dma_device_write);
int map_dma_chan(struct dma_chan_map *map)
{
int i, j;
int result;
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++)
strcpy(dma_devs[i].device_name, global_device_name[i]);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
dma_chan[i].irq = map[i].irq;
result = request_irq(dma_chan[i].irq, dma_interrupt, IRQF_DISABLED, map[i].dev_name, (void *)&dma_chan[i]);
if (result) {
printk(KERN_WARNING "error, cannot get dma_irq!\n");
free_irq(dma_chan[i].irq, (void *) &dma_interrupt);
return -EFAULT;
}
}
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) {
dma_devs[i].num_tx_chan = 0; /*set default tx channel number to be one */
dma_devs[i].num_rx_chan = 0; /*set default rx channel number to be one */
dma_devs[i].max_rx_chan_num = 0;
dma_devs[i].max_tx_chan_num = 0;
dma_devs[i].buffer_alloc = &common_buffer_alloc;
dma_devs[i].buffer_free = &common_buffer_free;
dma_devs[i].intr_handler = NULL;
dma_devs[i].tx_burst_len = 4;
dma_devs[i].rx_burst_len = 4;
if (i == 0) {
ifxmips_w32(0, IFXMIPS_DMA_PS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_PCTRL) | ((0xf << 8) | (1 << 6)), IFXMIPS_DMA_PCTRL); /*enable dma drop */
}
if (i == 1) {
ifxmips_w32(1, IFXMIPS_DMA_PS);
ifxmips_w32(0x14, IFXMIPS_DMA_PCTRL); /*deu port setting */
}
for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) {
dma_chan[j].byte_offset = 0;
dma_chan[j].open = &open_chan;
dma_chan[j].close = &close_chan;
dma_chan[j].reset = &reset_chan;
dma_chan[j].enable_irq = &enable_ch_irq;
dma_chan[j].disable_irq = &disable_ch_irq;
dma_chan[j].rel_chan_no = map[j].rel_chan_no;
dma_chan[j].control = IFXMIPS_DMA_CH_OFF;
dma_chan[j].default_weight = IFXMIPS_DMA_CH_DEFAULT_WEIGHT;
dma_chan[j].weight = dma_chan[j].default_weight;
dma_chan[j].curr_desc = 0;
dma_chan[j].prev_desc = 0;
}
for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) {
if (strcmp(dma_devs[i].device_name, map[j].dev_name) == 0) {
if (map[j].dir == IFXMIPS_DMA_RX) {
dma_chan[j].dir = IFXMIPS_DMA_RX;
dma_devs[i].max_rx_chan_num++;
dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1] = &dma_chan[j];
dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1]->pri = map[j].pri;
dma_chan[j].dma_dev = (void *)&dma_devs[i];
} else if (map[j].dir == IFXMIPS_DMA_TX) {
/*TX direction */
dma_chan[j].dir = IFXMIPS_DMA_TX;
dma_devs[i].max_tx_chan_num++;
dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1] = &dma_chan[j];
dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1]->pri = map[j].pri;
dma_chan[j].dma_dev = (void *)&dma_devs[i];
} else {
printk(KERN_WARNING "WRONG DMA MAP!\n");
}
}
}
}
return 0;
}
void dma_chip_init(void)
{
int i;
/* enable DMA from PMU */
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA);
/* reset DMA */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CTRL) | 1, IFXMIPS_DMA_CTRL);
/* disable all interrupts */
ifxmips_w32(0, IFXMIPS_DMA_IRNEN);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
ifxmips_w32(i, IFXMIPS_DMA_CS);
ifxmips_w32(0x2, IFXMIPS_DMA_CCTRL);
ifxmips_w32(0x80000040, IFXMIPS_DMA_CPOLL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~0x1, IFXMIPS_DMA_CCTRL);
}
}
int ifxmips_dma_init(void)
{
int i;
dma_chip_init();
if (map_dma_chan(default_dma_map))
BUG();
g_desc_list = (u64 *)KSEG1ADDR(__get_free_page(GFP_DMA));
if (g_desc_list == NULL) {
printk(KERN_WARNING "no memory for desriptor\n");
return -ENOMEM;
}
memset(g_desc_list, 0, PAGE_SIZE);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
dma_chan[i].desc_base = (u32)g_desc_list + i * IFXMIPS_DMA_DESCRIPTOR_OFFSET * 8;
dma_chan[i].curr_desc = 0;
dma_chan[i].desc_len = IFXMIPS_DMA_DESCRIPTOR_OFFSET;
ifxmips_w32(i, IFXMIPS_DMA_CS);
ifxmips_w32((u32)CPHYSADDR(dma_chan[i].desc_base), IFXMIPS_DMA_CDBA);
ifxmips_w32(dma_chan[i].desc_len, IFXMIPS_DMA_CDLEN);
}
return 0;
}
arch_initcall(ifxmips_dma_init);
void dma_cleanup(void)
{
int i;
free_page(KSEG0ADDR((unsigned long) g_desc_list));
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++)
free_irq(dma_chan[i].irq, (void *)&dma_interrupt);
}
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,233 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <asm/irq_cpu.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
void
ifxmips_disable_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) & ~(1 << irq_nr), ier);
return;
}
ier += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_disable_irq);
void
ifxmips_mask_and_ack_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
u32 *isr = IFXMIPS_ICU_IM0_ISR;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) & ~(1 << irq_nr), ier);
ifxmips_w32((1 << irq_nr), isr);
return;
}
ier += IFXMIPS_ICU_OFFSET;
isr += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_mask_and_ack_irq);
void
ifxmips_enable_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) | (1 << irq_nr), ier);
return;
}
ier += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_enable_irq);
static unsigned int
ifxmips_startup_irq(unsigned int irq)
{
ifxmips_enable_irq(irq);
return 0;
}
static void
ifxmips_end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
ifxmips_enable_irq(irq);
}
static struct irq_chip
ifxmips_irq_type = {
"ifxmips",
.startup = ifxmips_startup_irq,
.enable = ifxmips_enable_irq,
.disable = ifxmips_disable_irq,
.unmask = ifxmips_enable_irq,
.ack = ifxmips_end_irq,
.mask = ifxmips_disable_irq,
.mask_ack = ifxmips_mask_and_ack_irq,
.end = ifxmips_end_irq,
};
/* silicon bug causes only the msb set to 1 to be valid. all
other bits might be bogus */
static inline int
ls1bit32(unsigned long x)
{
__asm__ (
".set push \n"
".set mips32 \n"
"clz %0, %1 \n"
".set pop \n"
: "=r" (x)
: "r" (x));
return 31 - x;
}
static void
ifxmips_hw_irqdispatch(int module)
{
u32 irq;
irq = ifxmips_r32(IFXMIPS_ICU_IM0_IOSR + (module * IFXMIPS_ICU_OFFSET));
if (irq == 0)
return;
/* we need to do this due to a silicon bug */
irq = ls1bit32(irq);
do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
if ((irq == 22) && (module == 0))
ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_ISTAT) | 0x10,
IFXMIPS_EBU_PCC_ISTAT);
}
#ifdef CONFIG_CPU_MIPSR2_IRQ_VI
#define DEFINE_HWx_IRQDISPATCH(x) \
static void ifxmips_hw ## x ## _irqdispatch(void)\
{\
ifxmips_hw_irqdispatch(x); \
}
static void ifxmips_hw5_irqdispatch(void)
{
do_IRQ(MIPS_CPU_TIMER_IRQ);
}
DEFINE_HWx_IRQDISPATCH(0)
DEFINE_HWx_IRQDISPATCH(1)
DEFINE_HWx_IRQDISPATCH(2)
DEFINE_HWx_IRQDISPATCH(3)
DEFINE_HWx_IRQDISPATCH(4)
/*DEFINE_HWx_IRQDISPATCH(5)*/
#endif /* #ifdef CONFIG_CPU_MIPSR2_IRQ_VI */
asmlinkage void
plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
unsigned int i;
if (pending & CAUSEF_IP7)
{
do_IRQ(MIPS_CPU_TIMER_IRQ);
goto out;
} else {
for (i = 0; i < 5; i++)
{
if (pending & (CAUSEF_IP2 << i))
{
ifxmips_hw_irqdispatch(i);
goto out;
}
}
}
printk(KERN_ALERT "Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
out:
return;
}
static struct irqaction
cascade = {
.handler = no_action,
.flags = IRQF_DISABLED,
.name = "cascade",
};
void __init
arch_init_irq(void)
{
int i;
for (i = 0; i < 5; i++)
ifxmips_w32(0, IFXMIPS_ICU_IM0_IER + (i * IFXMIPS_ICU_OFFSET));
mips_cpu_irq_init();
for (i = 2; i <= 6; i++)
setup_irq(i, &cascade);
#ifdef CONFIG_CPU_MIPSR2_IRQ_VI
if (cpu_has_vint) {
printk(KERN_INFO "Setting up vectored interrupts\n");
set_vi_handler(2, ifxmips_hw0_irqdispatch);
set_vi_handler(3, ifxmips_hw1_irqdispatch);
set_vi_handler(4, ifxmips_hw2_irqdispatch);
set_vi_handler(5, ifxmips_hw3_irqdispatch);
set_vi_handler(6, ifxmips_hw4_irqdispatch);
set_vi_handler(7, ifxmips_hw5_irqdispatch);
}
#endif
for (i = INT_NUM_IRQ0; i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
set_irq_chip_and_handler(i, &ifxmips_irq_type,
handle_level_irq);
#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#else
set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#endif
}
void __cpuinit
arch_fixup_c0_irqs(void)
{
/* FIXME: check for CPUID and only do fix for specific chips/versions */
cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
cp0_perfcount_irq = CP0_LEGACY_PERFCNT_IRQ;
}

View File

@ -0,0 +1,170 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/gpio_buttons.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <machine.h>
#include <ifxmips_prom.h>
#include "arcaydian.h"
#include "devices.h"
#define ARV452_EBU_GPIO_START 0x14000000
#define ARV452_EBU_GPIO_SIZE 0x00001000
#define ARV452_GPIO_BUTTON_RESET 14
#define ARV452_BUTTONS_POLL_INTERVAL 20
#define ARV452_LATCH_SWITCH (1 << 10)
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition arv452_partitions[] =
{
{
.name = "uboot",
.offset = 0x0,
.size = 0x20000,
},
{
.name = "uboot_env",
.offset = 0x20000,
.size = 0x0,
},
{
.name = "kernel",
.offset = 0x0,
.size = 0x0,
},
{
.name = "rootfs",
.offset = 0x0,
.size = 0x0,
},
{
.name = "board_config",
.offset = 0x3f0000,
.size = 0x10000,
},
{
.name = "openwrt",
.offset = 0x0,
.size = 0x0,
},
};
#endif
static struct physmap_flash_data arv452_flash_data = {
#ifdef CONFIG_MTD_PARTITIONS
.nr_parts = ARRAY_SIZE(arv452_partitions),
.parts = arv452_partitions,
#endif
};
static struct gpio_led
arv452_leds_gpio[] __initdata = {
/*
{ .name = "ifx0", .gpio = 0, .active_low = 1, },
{ .name = "ifx1", .gpio = 1, .active_low = 1, },
{ .name = "ifx2", .gpio = 2, .active_low = 1, },
*/
{ .name = "ifx:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:blue:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:blue:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 6, .active_low = 1, },
{ .name = "ifx:yello:wps", .gpio = 7, .active_low = 1, },
{ .name = "ifx:red:wps", .gpio = 9, .active_low = 1, },
/*
{ .name = "ifx10", .gpio = 10, .active_low = 1, },
{ .name = "ifx11", .gpio = 11, .active_low = 1, },
{ .name = "ifx12", .gpio = 12, .active_low = 1, },
{ .name = "ifx13", .gpio = 13, .active_low = 1, },
{ .name = "ifx14", .gpio = 14, .active_low = 1, },
{ .name = "ifx15", .gpio = 15, .active_low = 1, },
{ .name = "ifx16", .gpio = 16, .active_low = 1, },
{ .name = "ifx17", .gpio = 17, .active_low = 1, },
{ .name = "ifx18", .gpio = 18, .active_low = 1, },
{ .name = "ifx19", .gpio = 19, .active_low = 1, },
{ .name = "ifx20", .gpio = 20, .active_low = 1, },
{ .name = "ifx21", .gpio = 21, .active_low = 1, },
{ .name = "ifx22", .gpio = 22, .active_low = 1, },
{ .name = "ifx23", .gpio = 23, .active_low = 1, },
{ .name = "ifx24", .gpio = 24, .active_low = 1, },
{ .name = "ifx25", .gpio = 25, .active_low = 1, },
{ .name = "ifx26", .gpio = 26, .active_low = 1, },
{ .name = "ifx27", .gpio = 27, .active_low = 1, },
{ .name = "ifx28", .gpio = 28, .active_low = 1, },
{ .name = "ifx29", .gpio = 29, .active_low = 1, },
{ .name = "ifx30", .gpio = 30, .active_low = 1, },
{ .name = "ifx31", .gpio = 31, .active_low = 1, },
*/
{ .name = "ifx:blue:voip", .gpio = 32, .active_low = 1, },
{ .name = "ifx:blue:fxs1", .gpio = 33, .active_low = 1, },
{ .name = "ifx:blue:fxs2", .gpio = 34, .active_low = 1, },
{ .name = "ifx:blue:fxo", .gpio = 35, .active_low = 1, },
{ .name = "ifx:blue:voice", .gpio = 36, .active_low = 1, },
{ .name = "ifx:blue:usb", .gpio = 37, .active_low = 1, },
{ .name = "ifx:blue:wlan", .gpio = 38, .active_low = 1, },
/* { .name = "ifx39", .gpio = 39, .active_low = 1, },
{ .name = "ifx40", .gpio = 40, .active_low = 1, },
{ .name = "ifx41", .gpio = 41, .active_low = 1, },
{ .name = "ifx42", .gpio = 42, .active_low = 1, },
{ .name = "ifx43", .gpio = 43, .active_low = 1, },
{ .name = "ifx44", .gpio = 44, .active_low = 1, },
{ .name = "ifx45", .gpio = 45, .active_low = 1, },
{ .name = "ifx46", .gpio = 46, .active_low = 1, },
{ .name = "ifx47", .gpio = 47, .active_low = 1, },
*/
};
static struct gpio_button
arv452_gpio_buttons[] __initdata = {
{
.desc = "reset",
.type = EV_KEY,
.code = BTN_0,
.threshold = 3,
.gpio = ARV452_GPIO_BUTTON_RESET,
.active_low = 1,
}
};
static struct resource arv452_ebu_resource =
{
.name = "ebu-gpio",
.start = ARV452_EBU_GPIO_START,
.end = ARV452_EBU_GPIO_START + ARV452_EBU_GPIO_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static void __init
arv452_init(void)
{
unsigned char mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
ifxmips_find_brn_mac(mac);
ifxmips_register_gpio();
danube_register_ebu_gpio(&arv452_ebu_resource, ARV452_LATCH_SWITCH);
ifxmips_register_mtd(&arv452_flash_data);
danube_register_pci(PCI_CLOCK_EXT, 0);
ifxmips_register_wdt();
ifxmips_register_gpio_leds(arv452_leds_gpio, ARRAY_SIZE(arv452_leds_gpio));
danube_register_ethernet(mac);
danube_register_usb();
}
MIPS_MACHINE(IFXMIPS_MACH_ARV452,
"ARV452",
"Airties WAV-281, Arcor A800",
arv452_init);

View File

@ -0,0 +1,96 @@
#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
#define SYSTEM_DANUBE "Danube"
#define SYSTEM_DANUBE_CHIPID1 0x00129083
#define SYSTEM_DANUBE_CHIPID2 0x0012B083
#define SYSTEM_TWINPASS "Twinpass"
#define SYSTEM_TWINPASS_CHIPID 0x0012D083
static unsigned int chiprev = 0;
unsigned char ifxmips_sys_type[IFXMIPS_SYS_TYPE_LEN];
unsigned int
ifxmips_get_cpu_ver(void)
{
return (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0xF0000000) >> 28;
}
EXPORT_SYMBOL(ifxmips_get_cpu_ver);
const char*
get_system_type(void)
{
return ifxmips_sys_type;
}
static void
ifxmips_machine_restart(char *command)
{
printk(KERN_NOTICE "System restart\n");
local_irq_disable();
ifxmips_w32(ifxmips_r32(IFXMIPS_RCU_RST) | IFXMIPS_RCU_RST_ALL,
IFXMIPS_RCU_RST);
for(;;);
}
static void
ifxmips_machine_halt(void)
{
printk(KERN_NOTICE "System halted.\n");
local_irq_disable();
for(;;);
}
static void
ifxmips_machine_power_off(void)
{
printk(KERN_NOTICE "Please turn off the power now.\n");
local_irq_disable();
for(;;);
}
void __init
ifxmips_soc_setup(void)
{
char *name = SYSTEM_DANUBE;
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
_machine_restart = ifxmips_machine_restart;
_machine_halt = ifxmips_machine_halt;
pm_power_off = ifxmips_machine_power_off;
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
switch (chiprev)
{
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
name = SYSTEM_DANUBE;
break;
case SYSTEM_TWINPASS_CHIPID:
name = SYSTEM_TWINPASS;
break;
default:
printk(KERN_ERR "This is not a danube chiprev : 0x%08X\n", chiprev);
BUG();
break;
}
snprintf(ifxmips_sys_type, IFXMIPS_SYS_TYPE_LEN - 1, "%s rev1.%d %dMhz",
name, ifxmips_get_cpu_ver(),
ifxmips_get_cpu_hz() / 1000000);
ifxmips_sys_type[IFXMIPS_SYS_TYPE_LEN - 1] = '\0';
}

View File

@ -0,0 +1,2 @@
obj-y := gpio.o pmu.o prom.o setup.o devices.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o

View File

@ -0,0 +1,135 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
/* gpiodev */
static struct platform_device ifxmips_gpio_dev =
{
.name = "GPIODEV",
.num_resources = 1,
};
void __init
ifxmips_register_gpio_dev(void)
{
platform_device_register(&ifxmips_gpio_dev);
}
/* gpio leds */
#ifdef CONFIG_LEDS_GPIO
static struct gpio_led_platform_data ifxmips_gpio_led_data;
static struct platform_device ifxmips_gpio_leds =
{
.name = "leds-gpio",
.dev = {
.platform_data = (void *) &ifxmips_gpio_led_data,
}
};
void __init
ifxmips_register_gpio_leds(struct gpio_led *leds, int cnt)
{
ifxmips_gpio_led_data.leds = leds;
ifxmips_gpio_led_data.num_leds = cnt;
platform_device_register(&ifxmips_gpio_leds);
}
#endif
/* leds */
static struct gpio_led_platform_data ifxmips_led_data;
static struct platform_device ifxmips_led =
{
.name = "ifxmips_led",
.dev = {
.platform_data = (void *) &ifxmips_led_data,
}
};
void __init
ifxmips_register_leds(struct gpio_led *leds, int cnt)
{
ifxmips_led_data.leds = leds;
ifxmips_led_data.num_leds = cnt;
platform_device_register(&ifxmips_led);
}
/* mtd flash */
static struct resource ifxmips_mtd_resource =
{
.start = IFXMIPS_FLASH_START,
.end = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ifxmips_mtd =
{
.name = "ifxmips_mtd",
.resource = &ifxmips_mtd_resource,
.num_resources = 1,
};
void __init
ifxmips_register_mtd(struct physmap_flash_data *pdata)
{
ifxmips_mtd.dev.platform_data = pdata;
platform_device_register(&ifxmips_mtd);
}
/* watchdog */
static struct resource ifxmips_wdt_resource =
{
.start = IFXMIPS_WDT_BASE_ADDR,
.end = IFXMIPS_WDT_BASE_ADDR + IFXMIPS_WDT_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ifxmips_wdt =
{
.name = "ifxmips_wdt",
.resource = &ifxmips_wdt_resource,
.num_resources = 1,
};
void __init
ifxmips_register_wdt(void)
{
platform_device_register(&ifxmips_wdt);
}
/* gpio */
static struct platform_device ifxmips_gpio0 =
{
.name = "ifxmips_gpio",
};
static struct platform_device ifxmips_gpio1 =
{
.name = "ifxmips_gpio1",
};
void __init
ifxmips_register_gpio(void)
{
platform_device_register(&ifxmips_gpio0);
platform_device_register(&ifxmips_gpio1);
}

View File

@ -0,0 +1,11 @@
#ifndef _IFXMIPS_DEVICES_H__
#define _IFXMIPS_DEVICES_H__
void __init ifxmips_register_gpio_dev(void);
void __init ifxmips_register_gpio_leds(struct gpio_led *leds, int cnt);
void __init ifxmips_register_leds(struct gpio_led *leds, int cnt);
void __init ifxmips_register_mtd(struct physmap_flash_data *pdata);
void __init ifxmips_register_wdt(void);
void __init ifxmips_register_gpio(void);
#endif

View File

@ -0,0 +1,56 @@
#include <linux/init.h>
#include <linux/cpu.h>
#include <ifxmips.h>
#ifdef CONFIG_IFXMIPS_PROM_ASC0
#define IFXMIPS_ASC_DIFF 0
#else
#define IFXMIPS_ASC_DIFF IFXMIPS_ASC_BASE_DIFF
#endif
static char buf[1024];
static inline u32
asc_r32(unsigned long r)
{
return ifxmips_r32((u32 *)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_DIFF + r));
}
static inline void
asc_w32(u32 v, unsigned long r)
{
ifxmips_w32(v, (u32 *)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_DIFF + r));
}
void
prom_putchar(char c)
{
unsigned long flags;
local_irq_save(flags);
while ((asc_r32(IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK) >> ASCFSTAT_TXFFLOFF);
if (c == '\n')
asc_w32('\r', IFXMIPS_ASC_TBUF);
asc_w32(c, IFXMIPS_ASC_TBUF);
local_irq_restore(flags);
}
void
early_printf(const char *fmt, ...)
{
va_list args;
int l;
char *p, *buf_end;
va_start(args, fmt);
l = vsprintf(buf, fmt, args);
va_end(args);
buf_end = buf + l;
for (p = buf; p < buf_end; p++)
prom_putchar(*p);
}

View File

@ -0,0 +1,345 @@
/*
* 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.
*
* Copyright (C) 2004 btxu Generate from INCA-IP project
* Copyright (C) 2005 Jin-Sze.Sow Comments edited
* Copyright (C) 2006 Huang Xiaogang Modification & verification on Danube chip
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/kobject.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/semaphore.h>
#include <linux/gpio.h>
#include <net/sock.h>
#include <ifxmips.h>
#define MAX_PORTS 2
#define PINS_PER_PORT 16
#define IFXMIPS_GPIO_SANITY {if (port > MAX_PORTS || pin > PINS_PER_PORT) return -EINVAL; }
#define GPIO_TO_PORT(x) ((x > 15) ? (1) : (0))
#define GPIO_TO_GPIO(x) ((x > 15) ? (x - 16) : (x))
int
ifxmips_port_reserve_pin(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
printk(KERN_INFO "%s : call to obseleted function\n", __func__);
return 0;
}
EXPORT_SYMBOL(ifxmips_port_reserve_pin);
int
ifxmips_port_free_pin(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
printk(KERN_INFO "%s : call to obseleted function\n", __func__);
return 0;
}
EXPORT_SYMBOL(ifxmips_port_free_pin);
int
ifxmips_port_set_open_drain(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_OD + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_open_drain);
int
ifxmips_port_clear_open_drain(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_OD + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_open_drain);
int
ifxmips_port_set_pudsel(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_pudsel);
int
ifxmips_port_clear_pudsel(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_pudsel);
int
ifxmips_port_set_puden(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_PUDEN + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_puden);
int
ifxmips_port_clear_puden(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_PUDEN + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_puden);
int
ifxmips_port_set_stoff(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_STOFF + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_stoff);
int
ifxmips_port_clear_stoff(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_STOFF + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_stoff);
int
ifxmips_port_set_dir_out(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_DIR + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_dir_out);
int
ifxmips_port_set_dir_in(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_DIR + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_dir_in);
int
ifxmips_port_set_output(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_OUT + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_output);
int
ifxmips_port_clear_output(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_OUT + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_output);
int
ifxmips_port_get_input(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
if (ifxmips_r32(IFXMIPS_GPIO_P0_IN + (port * 0xC)) & (1 << pin))
return 0;
else
return 1;
}
EXPORT_SYMBOL(ifxmips_port_get_input);
int
ifxmips_port_set_altsel0(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_altsel0);
int
ifxmips_port_clear_altsel0(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_altsel0);
int
ifxmips_port_set_altsel1(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) | (1 << pin),
IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_set_altsel1);
int
ifxmips_port_clear_altsel1(unsigned int port, unsigned int pin)
{
IFXMIPS_GPIO_SANITY;
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) & ~(1 << pin),
IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC));
return 0;
}
EXPORT_SYMBOL(ifxmips_port_clear_altsel1);
static void
ifxmips_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
int port = GPIO_TO_PORT(offset);
int gpio = GPIO_TO_GPIO(offset);
if(value)
ifxmips_port_set_output(port, gpio);
else
ifxmips_port_clear_output(port, gpio);
}
static int
ifxmips_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
int port = GPIO_TO_PORT(offset);
int gpio = GPIO_TO_GPIO(offset);
return ifxmips_port_get_input(port, gpio);
}
static int
ifxmips_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
int port = GPIO_TO_PORT(offset);
int gpio = GPIO_TO_GPIO(offset);
ifxmips_port_set_open_drain(port, gpio);
ifxmips_port_clear_altsel0(port, gpio);
ifxmips_port_clear_altsel1(port, gpio);
ifxmips_port_set_dir_in(port, gpio);
return 0;
}
static int
ifxmips_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)
{
int port = GPIO_TO_PORT(offset);
int gpio = GPIO_TO_GPIO(offset);
ifxmips_port_clear_open_drain(port, gpio);
ifxmips_port_clear_altsel0(port, gpio);
ifxmips_port_clear_altsel1(port, gpio);
ifxmips_port_set_dir_out(port, gpio);
ifxmips_gpio_set(chip, offset, value);
return 0;
}
int
gpio_to_irq(unsigned int gpio)
{
return -EINVAL;
}
EXPORT_SYMBOL(gpio_to_irq);
struct gpio_chip
ifxmips_gpio_chip =
{
.label = "ifxmips-gpio",
.direction_input = ifxmips_gpio_direction_input,
.direction_output = ifxmips_gpio_direction_output,
.get = ifxmips_gpio_get,
.set = ifxmips_gpio_set,
.base = 0,
.ngpio = 32,
};
static int
ifxmips_gpio_probe(struct platform_device *dev)
{
gpiochip_add(&ifxmips_gpio_chip);
return 0;
}
static int
ifxmips_gpio_remove(struct platform_device *pdev)
{
gpiochip_remove(&ifxmips_gpio_chip);
return 0;
}
static struct platform_driver
ifxmips_gpio_driver = {
.probe = ifxmips_gpio_probe,
.remove = ifxmips_gpio_remove,
.driver = {
.name = "ifxmips_gpio",
.owner = THIS_MODULE,
},
};
int __init
ifxmips_gpio_init(void)
{
int ret = platform_driver_register(&ifxmips_gpio_driver);
if (ret)
printk(KERN_INFO "ifxmips_gpio : Error registering platfom driver!");
return ret;
}
void __exit
ifxmips_gpio_exit(void)
{
platform_driver_unregister(&ifxmips_gpio_driver);
}
module_init(ifxmips_gpio_init);
module_exit(ifxmips_gpio_exit);

View File

@ -0,0 +1,25 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <ifxmips.h>
void
ifxmips_pmu_enable(unsigned int module)
{
int err = 1000000;
ifxmips_w32(ifxmips_r32(IFXMIPS_PMU_PWDCR) & ~module, IFXMIPS_PMU_PWDCR);
while (--err && (ifxmips_r32(IFXMIPS_PMU_PWDSR) & module));
if (!err)
panic("activating PMU module failed!");
}
EXPORT_SYMBOL(ifxmips_pmu_enable);
void
ifxmips_pmu_disable(unsigned int module)
{
ifxmips_w32(ifxmips_r32(IFXMIPS_PMU_PWDCR) | module, IFXMIPS_PMU_PWDCR);
}
EXPORT_SYMBOL(ifxmips_pmu_disable);

View File

@ -0,0 +1,131 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/bootmem.h>
#include <linux/etherdevice.h>
#include <asm/bootinfo.h>
#include <ifxmips.h>
#include <ifxmips_prom.h>
/* for voice cpu (MIPS24K) */
unsigned int *prom_cp1_base;
unsigned int prom_cp1_size;
/* for Multithreading (APRP) on MIPS34K */
unsigned long physical_memsize;
void
prom_free_prom_memory(void)
{
}
unsigned int*
prom_get_cp1_base(void)
{
return prom_cp1_base;
}
EXPORT_SYMBOL(prom_get_cp1_base);
unsigned int
prom_get_cp1_size(void)
{
/* return size im MB */
return prom_cp1_size>>20;
}
EXPORT_SYMBOL(prom_get_cp1_size);
extern unsigned char ifxmips_ethaddr[6];
int cmdline_mac = 0;
static int __init
ifxmips_set_ethaddr(char *str)
{
#define IS_HEX(x) \
(((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') \
|| (x >= 'A' && x <= 'F')) ? (1) : (0))
int i;
str = strchr(str, '=');
if (!str)
goto out;
str++;
if (strlen(str) != 17)
goto out;
for (i = 0; i < 6; i++) {
if (!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
goto out;
if ((i != 5) && (str[(3 * i) + 2] != ':'))
goto out;
ifxmips_ethaddr[i] = simple_strtoul(&str[3 * i], NULL, 16);
}
if (is_valid_ether_addr(ifxmips_ethaddr))
cmdline_mac = 1;
out:
return 1;
}
__setup("ethaddr", ifxmips_set_ethaddr);
void __init
prom_init(void)
{
int argc = fw_arg0;
char **argv = (char **) fw_arg1;
char **envp = (char **) fw_arg2;
int memsize = 16; /* assume 16M as default */
int i;
if (argc)
{
argv = (char **)KSEG1ADDR((unsigned long)argv);
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++)
{
char *a = (char *)KSEG1ADDR(argv[i]);
if (!argv[i])
continue;
/* for voice cpu on Twinpass/Danube */
if (cpu_data[0].cputype == CPU_24K)
if (!strncmp(a, "cp1_size=", 9))
{
prom_cp1_size = memparse(a + 9, &a);
continue;
}
if (strlen(arcs_cmdline) + strlen(a + 1) >= sizeof(arcs_cmdline))
{
early_printf("cmdline overflow, skipping: %s\n", a);
break;
}
strcat(arcs_cmdline, a);
strcat(arcs_cmdline, " ");
}
if (!*arcs_cmdline)
strcpy(&(arcs_cmdline[0]),
"console=ttyS0,115200 rootfstype=squashfs,jffs2");
}
envp = (char **)KSEG1ADDR((unsigned long)envp);
while (*envp)
{
char *e = (char *)KSEG1ADDR(*envp);
if (!strncmp(e, "memsize=", 8))
{
e += 8;
memsize = simple_strtoul(e, NULL, 10);
}
envp++;
}
memsize *= 1024 * 1024;
/* only on Twinpass/Danube a second CPU is used for Voice */
if ((cpu_data[0].cputype == CPU_24K) && (prom_cp1_size))
{
memsize -= prom_cp1_size;
prom_cp1_base = (unsigned int *)KSEG1ADDR(memsize);
early_printf("Using %dMB Ram and reserving %dMB for cp1\n",
memsize>>20, prom_cp1_size>>20);
}
add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
}

View File

@ -0,0 +1,104 @@
#include <linux/init.h>
#include <linux/cpu.h>
#include <asm/time.h>
#include <asm/traps.h>
#include <asm/irq.h>
#include <asm/bootinfo.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_pmu.h>
#include <ifxmips_cgu.h>
#include <ifxmips_prom.h>
#include <machine.h>
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
static unsigned int r4k_offset;
static unsigned int r4k_cur;
static unsigned int ifxmips_ram_clocks[] = {CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
#define DDR_HZ ifxmips_ram_clocks[ifxmips_r32(IFXMIPS_CGU_SYS) & 0x3]
extern void __init ifxmips_soc_setup(void);
static inline u32
ifxmips_get_counter_resolution(void)
{
u32 res;
__asm__ __volatile__(
".set push\n"
".set mips32r2\n"
".set noreorder\n"
"rdhwr %0, $3\n"
"ehb\n"
".set pop\n"
: "=&r" (res)
: /* no input */
: "memory");
instruction_hazard();
return res;
}
void __init
plat_time_init(void)
{
mips_hpt_frequency = ifxmips_get_cpu_hz() / ifxmips_get_counter_resolution();
r4k_cur = (read_c0_count() + r4k_offset);
write_c0_compare(r4k_cur);
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_GPT | IFXMIPS_PMU_PWDCR_FPI);
ifxmips_w32(0x100, IFXMIPS_GPTU_GPT_CLC); /* set clock divider to 1 */
}
void __init
plat_mem_setup(void)
{
u32 status;
/* make sure to have no "reverse endian" for user mode! */
status = read_c0_status();
status &= (~(1<<25));
write_c0_status(status);
/* call the chip specific init code */
ifxmips_soc_setup();
}
unsigned int
ifxmips_get_cpu_hz(void)
{
switch (ifxmips_r32(IFXMIPS_CGU_SYS) & 0xc)
{
case 0:
return CLOCK_333M;
case 4:
return DDR_HZ;
}
return DDR_HZ >> 1;
}
EXPORT_SYMBOL(ifxmips_get_cpu_hz);
static int __init
ifxmips_machine_setup(void)
{
mips_machine_setup();
return 0;
}
arch_initcall(ifxmips_machine_setup);
static void __init
ifxmips_generic_init(void)
{
}
MIPS_MACHINE(IFXMIPS_MACH_GENERIC, "Generic", "Generic Infineon board",
ifxmips_generic_init);
__setup("board=", mips_machtype_setup);

View File

@ -0,0 +1 @@
obj-y := timer.o cgu.o

View File

@ -0,0 +1,173 @@
/*
* 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.
*
* Copyright (C) 2007 Xu Liang, infineon
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
static unsigned int cgu_get_pll0_fdiv(void);
unsigned int ifxmips_clocks[] = {CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
#define DDR_HZ ifxmips_clocks[ifxmips_r32(IFXMIPS_CGU_SYS) & 0x3]
static inline unsigned int get_input_clock(int pll)
{
switch (pll) {
case 0:
if (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & CGU_PLL0_SRC)
return BASIS_INPUT_CRYSTAL_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_INPUT_CLOCK_FREQUENCY_1;
else
return BASIC_INPUT_CLOCK_FREQUENCY_2;
case 1:
if (CGU_PLL1_SRC)
return BASIS_INPUT_CRYSTAL_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_INPUT_CLOCK_FREQUENCY_1;
else
return BASIC_INPUT_CLOCK_FREQUENCY_2;
case 2:
switch (CGU_PLL2_SRC) {
case 0:
return cgu_get_pll0_fdiv();
case 1:
return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
BASIC_INPUT_CLOCK_FREQUENCY_1 :
BASIC_INPUT_CLOCK_FREQUENCY_2;
case 2:
return BASIS_INPUT_CRYSTAL_USB;
}
default:
return 0;
}
}
static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
{
u64 res, clock = get_input_clock(pll);
res = num * clock;
do_div(res, den);
return res;
}
static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 10) + K;
unsigned int den = (M + 1) << 10;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 11) + K + 512;
unsigned int den = (M + 1) << 11;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = K >= 512 ?
((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
unsigned int den = (M + 1) << 12;
return cal_dsm(pll, num, den);
}
static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
{
if (!dsmsel)
return mash_dsm(pll, M, N, K);
else if (!phase_div_en)
return mash_dsm(pll, M, N, K);
else
return ssff_dsm_2(pll, M, N, K);
}
static inline unsigned int cgu_get_pll0_fosc(void)
{
if (CGU_PLL0_BYPASS)
return get_input_clock(0);
else
return !CGU_PLL0_CFG_FRAC_EN
? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0, CGU_PLL0_CFG_DSMSEL,
CGU_PLL0_PHASE_DIVIDER_ENABLE)
: dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, CGU_PLL0_CFG_PLLK,
CGU_PLL0_CFG_DSMSEL, CGU_PLL0_PHASE_DIVIDER_ENABLE);
}
static unsigned int cgu_get_pll0_fdiv(void)
{
unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
return (cgu_get_pll0_fosc() + (div >> 1)) / div;
}
unsigned int cgu_get_io_region_clock(void)
{
unsigned int ret = cgu_get_pll0_fosc();
switch (ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
default:
case 0:
return (ret + 1) / 2;
case 1:
return (ret * 2 + 2) / 5;
case 2:
return (ret + 1) / 3;
case 3:
return (ret + 2) / 4;
}
}
unsigned int cgu_get_fpi_bus_clock(int fpi)
{
unsigned int ret = cgu_get_io_region_clock();
if ((fpi == 2) && (ifxmips_r32(IFXMIPS_CGU_SYS) & CGU_SYS_FPI_SEL))
ret >>= 1;
return ret;
}
EXPORT_SYMBOL(cgu_get_fpi_bus_clock);
unsigned int ifxmips_get_fpi_hz(void)
{
unsigned int ddr_clock = DDR_HZ;
if (ifxmips_r32(IFXMIPS_CGU_SYS) & 0x40)
return ddr_clock >> 1;
return ddr_clock;
}
EXPORT_SYMBOL(ifxmips_get_fpi_hz);

View File

@ -0,0 +1,830 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_cgu.h>
#include <ifxmips_gptu.h>
#include <ifxmips_pmu.h>
#define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6
#ifdef TIMER1A
#define FIRST_TIMER TIMER1A
#else
#define FIRST_TIMER 2
#endif
/*
* GPTC divider is set or not.
*/
#define GPTU_CLC_RMC_IS_SET 0
/*
* Timer Interrupt (IRQ)
*/
/* Must be adjusted when ICU driver is available */
#define TIMER_INTERRUPT (INT_NUM_IM3_IRL0 + 22)
/*
* Bits Operation
*/
#define GET_BITS(x, msb, lsb) \
(((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
#define SET_BITS(x, msb, lsb, value) \
(((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | \
(((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
/*
* GPTU Register Mapping
*/
#define IFXMIPS_GPTU (KSEG1 + 0x1E100A00)
#define IFXMIPS_GPTU_CLC ((volatile u32 *)(IFXMIPS_GPTU + 0x0000))
#define IFXMIPS_GPTU_ID ((volatile u32 *)(IFXMIPS_GPTU + 0x0008))
#define IFXMIPS_GPTU_CON(n, X) ((volatile u32 *)(IFXMIPS_GPTU + 0x0010 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
#define IFXMIPS_GPTU_RUN(n, X) ((volatile u32 *)(IFXMIPS_GPTU + 0x0018 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
#define IFXMIPS_GPTU_RELOAD(n, X) ((volatile u32 *)(IFXMIPS_GPTU + 0x0020 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
#define IFXMIPS_GPTU_COUNT(n, X) ((volatile u32 *)(IFXMIPS_GPTU + 0x0028 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
#define IFXMIPS_GPTU_IRNEN ((volatile u32 *)(IFXMIPS_GPTU + 0x00F4))
#define IFXMIPS_GPTU_IRNICR ((volatile u32 *)(IFXMIPS_GPTU + 0x00F8))
#define IFXMIPS_GPTU_IRNCR ((volatile u32 *)(IFXMIPS_GPTU + 0x00FC))
/*
* Clock Control Register
*/
#define GPTU_CLC_SMC GET_BITS(*IFXMIPS_GPTU_CLC, 23, 16)
#define GPTU_CLC_RMC GET_BITS(*IFXMIPS_GPTU_CLC, 15, 8)
#define GPTU_CLC_FSOE (*IFXMIPS_GPTU_CLC & (1 << 5))
#define GPTU_CLC_EDIS (*IFXMIPS_GPTU_CLC & (1 << 3))
#define GPTU_CLC_SPEN (*IFXMIPS_GPTU_CLC & (1 << 2))
#define GPTU_CLC_DISS (*IFXMIPS_GPTU_CLC & (1 << 1))
#define GPTU_CLC_DISR (*IFXMIPS_GPTU_CLC & (1 << 0))
#define GPTU_CLC_SMC_SET(value) SET_BITS(0, 23, 16, (value))
#define GPTU_CLC_RMC_SET(value) SET_BITS(0, 15, 8, (value))
#define GPTU_CLC_FSOE_SET(value) ((value) ? (1 << 5) : 0)
#define GPTU_CLC_SBWE_SET(value) ((value) ? (1 << 4) : 0)
#define GPTU_CLC_EDIS_SET(value) ((value) ? (1 << 3) : 0)
#define GPTU_CLC_SPEN_SET(value) ((value) ? (1 << 2) : 0)
#define GPTU_CLC_DISR_SET(value) ((value) ? (1 << 0) : 0)
/*
* ID Register
*/
#define GPTU_ID_ID GET_BITS(*IFXMIPS_GPTU_ID, 15, 8)
#define GPTU_ID_CFG GET_BITS(*IFXMIPS_GPTU_ID, 7, 5)
#define GPTU_ID_REV GET_BITS(*IFXMIPS_GPTU_ID, 4, 0)
/*
* Control Register of Timer/Counter nX
* n is the index of block (1 based index)
* X is either A or B
*/
#define GPTU_CON_SRC_EG(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 10))
#define GPTU_CON_SRC_EXT(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 9))
#define GPTU_CON_SYNC(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 8))
#define GPTU_CON_EDGE(n, X) GET_BITS(*IFXMIPS_GPTU_CON(n, X), 7, 6)
#define GPTU_CON_INV(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 5))
#define GPTU_CON_EXT(n, X) (*IFXMIPS_GPTU_CON(n, A) & (1 << 4)) /* Timer/Counter B does not have this bit */
#define GPTU_CON_STP(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 3))
#define GPTU_CON_CNT(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 2))
#define GPTU_CON_DIR(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 1))
#define GPTU_CON_EN(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 0))
#define GPTU_CON_SRC_EG_SET(value) ((value) ? 0 : (1 << 10))
#define GPTU_CON_SRC_EXT_SET(value) ((value) ? (1 << 9) : 0)
#define GPTU_CON_SYNC_SET(value) ((value) ? (1 << 8) : 0)
#define GPTU_CON_EDGE_SET(value) SET_BITS(0, 7, 6, (value))
#define GPTU_CON_INV_SET(value) ((value) ? (1 << 5) : 0)
#define GPTU_CON_EXT_SET(value) ((value) ? (1 << 4) : 0)
#define GPTU_CON_STP_SET(value) ((value) ? (1 << 3) : 0)
#define GPTU_CON_CNT_SET(value) ((value) ? (1 << 2) : 0)
#define GPTU_CON_DIR_SET(value) ((value) ? (1 << 1) : 0)
#define GPTU_RUN_RL_SET(value) ((value) ? (1 << 2) : 0)
#define GPTU_RUN_CEN_SET(value) ((value) ? (1 << 1) : 0)
#define GPTU_RUN_SEN_SET(value) ((value) ? (1 << 0) : 0)
#define GPTU_IRNEN_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
#define GPTU_IRNCR_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
#define TIMER_FLAG_MASK_SIZE(x) (x & 0x0001)
#define TIMER_FLAG_MASK_TYPE(x) (x & 0x0002)
#define TIMER_FLAG_MASK_STOP(x) (x & 0x0004)
#define TIMER_FLAG_MASK_DIR(x) (x & 0x0008)
#define TIMER_FLAG_NONE_EDGE 0x0000
#define TIMER_FLAG_MASK_EDGE(x) (x & 0x0030)
#define TIMER_FLAG_REAL 0x0000
#define TIMER_FLAG_INVERT 0x0040
#define TIMER_FLAG_MASK_INVERT(x) (x & 0x0040)
#define TIMER_FLAG_MASK_TRIGGER(x) (x & 0x0070)
#define TIMER_FLAG_MASK_SYNC(x) (x & 0x0080)
#define TIMER_FLAG_CALLBACK_IN_HB 0x0200
#define TIMER_FLAG_MASK_HANDLE(x) (x & 0x0300)
#define TIMER_FLAG_MASK_SRC(x) (x & 0x1000)
struct timer_dev_timer {
unsigned int f_irq_on;
unsigned int irq;
unsigned int flag;
unsigned long arg1;
unsigned long arg2;
};
struct timer_dev {
struct mutex gptu_mutex;
unsigned int number_of_timers;
unsigned int occupation;
unsigned int f_gptu_on;
struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2];
};
static int gptu_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
static int gptu_open(struct inode *, struct file *);
static int gptu_release(struct inode *, struct file *);
static struct file_operations gptu_fops = {
.owner = THIS_MODULE,
.ioctl = gptu_ioctl,
.open = gptu_open,
.release = gptu_release
};
static struct miscdevice gptu_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "gptu",
.fops = &gptu_fops,
};
static struct timer_dev timer_dev;
static irqreturn_t timer_irq_handler(int irq, void *p)
{
unsigned int timer;
unsigned int flag;
struct timer_dev_timer *dev_timer = (struct timer_dev_timer *)p;
timer = irq - TIMER_INTERRUPT;
if (timer < timer_dev.number_of_timers
&& dev_timer == &timer_dev.timer[timer]) {
/* Clear interrupt. */
ifxmips_w32(1 << timer, IFXMIPS_GPTU_IRNCR);
/* Call user hanler or signal. */
flag = dev_timer->flag;
if (!(timer & 0x01)
|| TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
/* 16-bit timer or timer A of 32-bit timer */
switch (TIMER_FLAG_MASK_HANDLE(flag)) {
case TIMER_FLAG_CALLBACK_IN_IRQ:
case TIMER_FLAG_CALLBACK_IN_HB:
if (dev_timer->arg1)
(*(timer_callback)dev_timer->arg1)(dev_timer->arg2);
break;
case TIMER_FLAG_SIGNAL:
send_sig((int)dev_timer->arg2, (struct task_struct *)dev_timer->arg1, 0);
break;
}
}
}
return IRQ_HANDLED;
}
static inline void ifxmips_enable_gptu(void)
{
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_GPT);
/* Set divider as 1, disable write protection for SPEN, enable module. */
*IFXMIPS_GPTU_CLC =
GPTU_CLC_SMC_SET(0x00) |
GPTU_CLC_RMC_SET(0x01) |
GPTU_CLC_FSOE_SET(0) |
GPTU_CLC_SBWE_SET(1) |
GPTU_CLC_EDIS_SET(0) |
GPTU_CLC_SPEN_SET(0) |
GPTU_CLC_DISR_SET(0);
}
static inline void ifxmips_disable_gptu(void)
{
ifxmips_w32(0x00, IFXMIPS_GPTU_IRNEN);
ifxmips_w32(0xfff, IFXMIPS_GPTU_IRNCR);
/* Set divider as 0, enable write protection for SPEN, disable module. */
*IFXMIPS_GPTU_CLC =
GPTU_CLC_SMC_SET(0x00) |
GPTU_CLC_RMC_SET(0x00) |
GPTU_CLC_FSOE_SET(0) |
GPTU_CLC_SBWE_SET(0) |
GPTU_CLC_EDIS_SET(0) |
GPTU_CLC_SPEN_SET(0) |
GPTU_CLC_DISR_SET(1);
ifxmips_pmu_disable(IFXMIPS_PMU_PWDCR_GPT);
}
int ifxmips_request_timer(unsigned int timer, unsigned int flag,
unsigned long value, unsigned long arg1, unsigned long arg2)
{
int ret = 0;
unsigned int con_reg, irnen_reg;
int n, X;
if (timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
printk(KERN_INFO "request_timer(%d, 0x%08X, %lu)...",
timer, flag, value);
if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT)
value &= 0xFFFF;
else
timer &= ~0x01;
mutex_lock(&timer_dev.gptu_mutex);
/*
* Allocate timer.
*/
if (timer < FIRST_TIMER) {
unsigned int mask;
unsigned int shift;
/* This takes care of TIMER1B which is the only choice for Voice TAPI system */
unsigned int offset = TIMER2A;
/*
* Pick up a free timer.
*/
if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
mask = 1 << offset;
shift = 1;
} else {
mask = 3 << offset;
shift = 2;
}
for (timer = offset;
timer < offset + timer_dev.number_of_timers;
timer += shift, mask <<= shift)
if (!(timer_dev.occupation & mask)) {
timer_dev.occupation |= mask;
break;
}
if (timer >= offset + timer_dev.number_of_timers) {
printk("failed![%d]\n", __LINE__);
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
} else
ret = timer;
} else {
register unsigned int mask;
/*
* Check if the requested timer is free.
*/
mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
if ((timer_dev.occupation & mask)) {
printk("failed![%d] mask %#x, timer_dev.occupation %#x\n",
__LINE__, mask, timer_dev.occupation);
mutex_unlock(&timer_dev.gptu_mutex);
return -EBUSY;
} else {
timer_dev.occupation |= mask;
ret = 0;
}
}
/*
* Prepare control register value.
*/
switch (TIMER_FLAG_MASK_EDGE(flag)) {
default:
case TIMER_FLAG_NONE_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x00);
break;
case TIMER_FLAG_RISE_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x01);
break;
case TIMER_FLAG_FALL_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x02);
break;
case TIMER_FLAG_ANY_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x03);
break;
}
if (TIMER_FLAG_MASK_TYPE(flag) == TIMER_FLAG_TIMER)
con_reg |=
TIMER_FLAG_MASK_SRC(flag) ==
TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) :
GPTU_CON_SRC_EXT_SET(0);
else
con_reg |=
TIMER_FLAG_MASK_SRC(flag) ==
TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) :
GPTU_CON_SRC_EG_SET(0);
con_reg |=
TIMER_FLAG_MASK_SYNC(flag) ==
TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) :
GPTU_CON_SYNC_SET(1);
con_reg |=
TIMER_FLAG_MASK_INVERT(flag) ==
TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
con_reg |=
TIMER_FLAG_MASK_SIZE(flag) ==
TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) :
GPTU_CON_EXT_SET(1);
con_reg |=
TIMER_FLAG_MASK_STOP(flag) ==
TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
con_reg |=
TIMER_FLAG_MASK_TYPE(flag) ==
TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) :
GPTU_CON_CNT_SET(1);
con_reg |=
TIMER_FLAG_MASK_DIR(flag) ==
TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
/*
* Fill up running data.
*/
timer_dev.timer[timer - FIRST_TIMER].flag = flag;
timer_dev.timer[timer - FIRST_TIMER].arg1 = arg1;
timer_dev.timer[timer - FIRST_TIMER].arg2 = arg2;
if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
timer_dev.timer[timer - FIRST_TIMER + 1].flag = flag;
/*
* Enable GPTU module.
*/
if (!timer_dev.f_gptu_on) {
ifxmips_enable_gptu();
timer_dev.f_gptu_on = 1;
}
/*
* Enable IRQ.
*/
if (TIMER_FLAG_MASK_HANDLE(flag) != TIMER_FLAG_NO_HANDLE) {
if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL)
timer_dev.timer[timer - FIRST_TIMER].arg1 =
(unsigned long) find_task_by_vpid((int) arg1);
irnen_reg = 1 << (timer - FIRST_TIMER);
if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL
|| (TIMER_FLAG_MASK_HANDLE(flag) ==
TIMER_FLAG_CALLBACK_IN_IRQ
&& timer_dev.timer[timer - FIRST_TIMER].arg1)) {
enable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 1;
}
} else
irnen_reg = 0;
/*
* Write config register, reload value and enable interrupt.
*/
n = timer >> 1;
X = timer & 0x01;
*IFXMIPS_GPTU_CON(n, X) = con_reg;
*IFXMIPS_GPTU_RELOAD(n, X) = value;
/* printk("reload value = %d\n", (u32)value); */
*IFXMIPS_GPTU_IRNEN |= irnen_reg;
mutex_unlock(&timer_dev.gptu_mutex);
printk("successful!\n");
return ret;
}
EXPORT_SYMBOL(ifxmips_request_timer);
int ifxmips_free_timer(unsigned int timer)
{
unsigned int flag;
unsigned int mask;
int n, X;
if (!timer_dev.f_gptu_on)
return -EINVAL;
if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
mutex_lock(&timer_dev.gptu_mutex);
flag = timer_dev.timer[timer - FIRST_TIMER].flag;
if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
timer &= ~0x01;
mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
if (((timer_dev.occupation & mask) ^ mask)) {
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
}
n = timer >> 1;
X = timer & 0x01;
if (GPTU_CON_EN(n, X))
*IFXMIPS_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
*IFXMIPS_GPTU_IRNEN &= ~GPTU_IRNEN_TC_SET(n, X, 1);
*IFXMIPS_GPTU_IRNCR |= GPTU_IRNCR_TC_SET(n, X, 1);
if (timer_dev.timer[timer - FIRST_TIMER].f_irq_on) {
disable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 0;
}
timer_dev.occupation &= ~mask;
if (!timer_dev.occupation && timer_dev.f_gptu_on) {
ifxmips_disable_gptu();
timer_dev.f_gptu_on = 0;
}
mutex_unlock(&timer_dev.gptu_mutex);
return 0;
}
EXPORT_SYMBOL(ifxmips_free_timer);
int ifxmips_start_timer(unsigned int timer, int is_resume)
{
unsigned int flag;
unsigned int mask;
int n, X;
if (!timer_dev.f_gptu_on)
return -EINVAL;
if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
mutex_lock(&timer_dev.gptu_mutex);
flag = timer_dev.timer[timer - FIRST_TIMER].flag;
if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
timer &= ~0x01;
mask = (TIMER_FLAG_MASK_SIZE(flag) ==
TIMER_FLAG_16BIT ? 1 : 3) << timer;
if (((timer_dev.occupation & mask) ^ mask)) {
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
}
n = timer >> 1;
X = timer & 0x01;
*IFXMIPS_GPTU_RUN(n, X) = GPTU_RUN_RL_SET(!is_resume) | GPTU_RUN_SEN_SET(1);
mutex_unlock(&timer_dev.gptu_mutex);
return 0;
}
EXPORT_SYMBOL(ifxmips_start_timer);
int ifxmips_stop_timer(unsigned int timer)
{
unsigned int flag;
unsigned int mask;
int n, X;
if (!timer_dev.f_gptu_on)
return -EINVAL;
if (timer < FIRST_TIMER
|| timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
mutex_lock(&timer_dev.gptu_mutex);
flag = timer_dev.timer[timer - FIRST_TIMER].flag;
if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
timer &= ~0x01;
mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
if (((timer_dev.occupation & mask) ^ mask)) {
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
}
n = timer >> 1;
X = timer & 0x01;
*IFXMIPS_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
mutex_unlock(&timer_dev.gptu_mutex);
return 0;
}
EXPORT_SYMBOL(ifxmips_stop_timer);
int ifxmips_reset_counter_flags(u32 timer, u32 flags)
{
unsigned int oflag;
unsigned int mask, con_reg;
int n, X;
if (!timer_dev.f_gptu_on)
return -EINVAL;
if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
mutex_lock(&timer_dev.gptu_mutex);
oflag = timer_dev.timer[timer - FIRST_TIMER].flag;
if (TIMER_FLAG_MASK_SIZE(oflag) != TIMER_FLAG_16BIT)
timer &= ~0x01;
mask = (TIMER_FLAG_MASK_SIZE(oflag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
if (((timer_dev.occupation & mask) ^ mask)) {
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
}
switch (TIMER_FLAG_MASK_EDGE(flags)) {
default:
case TIMER_FLAG_NONE_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x00);
break;
case TIMER_FLAG_RISE_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x01);
break;
case TIMER_FLAG_FALL_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x02);
break;
case TIMER_FLAG_ANY_EDGE:
con_reg = GPTU_CON_EDGE_SET(0x03);
break;
}
if (TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER)
con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) : GPTU_CON_SRC_EXT_SET(0);
else
con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) : GPTU_CON_SRC_EG_SET(0);
con_reg |= TIMER_FLAG_MASK_SYNC(flags) == TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) : GPTU_CON_SYNC_SET(1);
con_reg |= TIMER_FLAG_MASK_INVERT(flags) == TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
con_reg |= TIMER_FLAG_MASK_SIZE(flags) == TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) : GPTU_CON_EXT_SET(1);
con_reg |= TIMER_FLAG_MASK_STOP(flags) == TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
con_reg |= TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) : GPTU_CON_CNT_SET(1);
con_reg |= TIMER_FLAG_MASK_DIR(flags) == TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
timer_dev.timer[timer - FIRST_TIMER].flag = flags;
if (TIMER_FLAG_MASK_SIZE(flags) != TIMER_FLAG_16BIT)
timer_dev.timer[timer - FIRST_TIMER + 1].flag = flags;
n = timer >> 1;
X = timer & 0x01;
*IFXMIPS_GPTU_CON(n, X) = con_reg;
smp_wmb();
printk(KERN_INFO "[%s]: counter%d oflags %#x, nflags %#x, GPTU_CON %#x\n", __func__, timer, oflag, flags, *IFXMIPS_GPTU_CON(n, X));
mutex_unlock(&timer_dev.gptu_mutex);
return 0;
}
EXPORT_SYMBOL(ifxmips_reset_counter_flags);
int ifxmips_get_count_value(unsigned int timer, unsigned long *value)
{
unsigned int flag;
unsigned int mask;
int n, X;
if (!timer_dev.f_gptu_on)
return -EINVAL;
if (timer < FIRST_TIMER
|| timer >= FIRST_TIMER + timer_dev.number_of_timers)
return -EINVAL;
mutex_lock(&timer_dev.gptu_mutex);
flag = timer_dev.timer[timer - FIRST_TIMER].flag;
if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
timer &= ~0x01;
mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
if (((timer_dev.occupation & mask) ^ mask)) {
mutex_unlock(&timer_dev.gptu_mutex);
return -EINVAL;
}
n = timer >> 1;
X = timer & 0x01;
*value = *IFXMIPS_GPTU_COUNT(n, X);
mutex_unlock(&timer_dev.gptu_mutex);
return 0;
}
EXPORT_SYMBOL(ifxmips_get_count_value);
u32 ifxmips_cal_divider(unsigned long freq)
{
u64 module_freq, fpi = cgu_get_fpi_bus_clock(2);
u32 clock_divider = 1;
module_freq = fpi * 1000;
do_div(module_freq, clock_divider * freq);
return module_freq;
}
EXPORT_SYMBOL(ifxmips_cal_divider);
int ifxmips_set_timer(unsigned int timer, unsigned int freq, int is_cyclic,
int is_ext_src, unsigned int handle_flag, unsigned long arg1,
unsigned long arg2)
{
unsigned long divider;
unsigned int flag;
divider = ifxmips_cal_divider(freq);
if (divider == 0)
return -EINVAL;
flag = ((divider & ~0xFFFF) ? TIMER_FLAG_32BIT : TIMER_FLAG_16BIT)
| (is_cyclic ? TIMER_FLAG_CYCLIC : TIMER_FLAG_ONCE)
| (is_ext_src ? TIMER_FLAG_EXT_SRC : TIMER_FLAG_INT_SRC)
| TIMER_FLAG_TIMER | TIMER_FLAG_DOWN
| TIMER_FLAG_MASK_HANDLE(handle_flag);
printk(KERN_INFO "ifxmips_set_timer(%d, %d), divider = %lu\n",
timer, freq, divider);
return ifxmips_request_timer(timer, flag, divider, arg1, arg2);
}
EXPORT_SYMBOL(ifxmips_set_timer);
int ifxmips_set_counter(unsigned int timer, unsigned int flag, u32 reload,
unsigned long arg1, unsigned long arg2)
{
printk(KERN_INFO "ifxmips_set_counter(%d, %#x, %d)\n", timer, flag, reload);
return ifxmips_request_timer(timer, flag, reload, arg1, arg2);
}
EXPORT_SYMBOL(ifxmips_set_counter);
static int gptu_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int ret;
struct gptu_ioctl_param param;
if (!access_ok(VERIFY_READ, arg, sizeof(struct gptu_ioctl_param)))
return -EFAULT;
copy_from_user(&param, (void *) arg, sizeof(param));
if ((((cmd == GPTU_REQUEST_TIMER || cmd == GPTU_SET_TIMER
|| GPTU_SET_COUNTER) && param.timer < 2)
|| cmd == GPTU_GET_COUNT_VALUE || cmd == GPTU_CALCULATE_DIVIDER)
&& !access_ok(VERIFY_WRITE, arg,
sizeof(struct gptu_ioctl_param)))
return -EFAULT;
switch (cmd) {
case GPTU_REQUEST_TIMER:
ret = ifxmips_request_timer(param.timer, param.flag, param.value,
(unsigned long) param.pid,
(unsigned long) param.sig);
if (ret > 0) {
copy_to_user(&((struct gptu_ioctl_param *) arg)->
timer, &ret, sizeof(&ret));
ret = 0;
}
break;
case GPTU_FREE_TIMER:
ret = ifxmips_free_timer(param.timer);
break;
case GPTU_START_TIMER:
ret = ifxmips_start_timer(param.timer, param.flag);
break;
case GPTU_STOP_TIMER:
ret = ifxmips_stop_timer(param.timer);
break;
case GPTU_GET_COUNT_VALUE:
ret = ifxmips_get_count_value(param.timer, &param.value);
if (!ret)
copy_to_user(&((struct gptu_ioctl_param *) arg)->
value, &param.value,
sizeof(param.value));
break;
case GPTU_CALCULATE_DIVIDER:
param.value = ifxmips_cal_divider(param.value);
if (param.value == 0)
ret = -EINVAL;
else {
copy_to_user(&((struct gptu_ioctl_param *) arg)->
value, &param.value,
sizeof(param.value));
ret = 0;
}
break;
case GPTU_SET_TIMER:
ret = ifxmips_set_timer(param.timer, param.value,
TIMER_FLAG_MASK_STOP(param.flag) !=
TIMER_FLAG_ONCE ? 1 : 0,
TIMER_FLAG_MASK_SRC(param.flag) ==
TIMER_FLAG_EXT_SRC ? 1 : 0,
TIMER_FLAG_MASK_HANDLE(param.flag) ==
TIMER_FLAG_SIGNAL ? TIMER_FLAG_SIGNAL :
TIMER_FLAG_NO_HANDLE,
(unsigned long) param.pid,
(unsigned long) param.sig);
if (ret > 0) {
copy_to_user(&((struct gptu_ioctl_param *) arg)->
timer, &ret, sizeof(&ret));
ret = 0;
}
break;
case GPTU_SET_COUNTER:
ifxmips_set_counter(param.timer, param.flag, param.value, 0, 0);
if (ret > 0) {
copy_to_user(&((struct gptu_ioctl_param *) arg)->
timer, &ret, sizeof(&ret));
ret = 0;
}
break;
default:
ret = -ENOTTY;
}
return ret;
}
static int gptu_open(struct inode *inode, struct file *file)
{
return 0;
}
static int gptu_release(struct inode *inode, struct file *file)
{
return 0;
}
int __init ifxmips_gptu_init(void)
{
int ret;
unsigned int i;
ifxmips_w32(0, IFXMIPS_GPTU_IRNEN);
ifxmips_w32(0xfff, IFXMIPS_GPTU_IRNCR);
memset(&timer_dev, 0, sizeof(timer_dev));
mutex_init(&timer_dev.gptu_mutex);
ifxmips_enable_gptu();
timer_dev.number_of_timers = GPTU_ID_CFG * 2;
ifxmips_disable_gptu();
if (timer_dev.number_of_timers > MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2)
timer_dev.number_of_timers = MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2;
printk(KERN_INFO "gptu: totally %d 16-bit timers/counters\n", timer_dev.number_of_timers);
ret = misc_register(&gptu_miscdev);
if (ret) {
printk(KERN_ERR "gptu: can't misc_register, get error %d\n", -ret);
return ret;
} else {
printk(KERN_INFO "gptu: misc_register on minor %d\n", gptu_miscdev.minor);
}
for (i = 0; i < timer_dev.number_of_timers; i++) {
ret = request_irq(TIMER_INTERRUPT + i, timer_irq_handler, IRQF_TIMER, gptu_miscdev.name, &timer_dev.timer[i]);
if (ret) {
for (; i >= 0; i--)
free_irq(TIMER_INTERRUPT + i, &timer_dev.timer[i]);
misc_deregister(&gptu_miscdev);
printk(KERN_ERR "gptu: failed in requesting irq (%d), get error %d\n", i, -ret);
return ret;
} else {
timer_dev.timer[i].irq = TIMER_INTERRUPT + i;
disable_irq(timer_dev.timer[i].irq);
printk(KERN_INFO "gptu: succeeded to request irq %d\n", timer_dev.timer[i].irq);
}
}
return 0;
}
void __exit ifxmips_gptu_exit(void)
{
unsigned int i;
for (i = 0; i < timer_dev.number_of_timers; i++) {
if (timer_dev.timer[i].f_irq_on)
disable_irq(timer_dev.timer[i].irq);
free_irq(timer_dev.timer[i].irq, &timer_dev.timer[i]);
}
ifxmips_disable_gptu();
misc_deregister(&gptu_miscdev);
}
module_init(ifxmips_gptu_init);
module_exit(ifxmips_gptu_exit);

View File

@ -0,0 +1,29 @@
if IFXMIPS_DANUBE
config IFXMIPS_ARCAYDIAN_BRNBOOT
bool
default n
menu "infineon SoC machine selection"
config DANUBE_MACH_EASY50712
bool "Easy50712"
default y
config DANUBE_MACH_EASY4010
bool "Easy4010"
default y
config DANUBE_MACH_ARV4519
bool "ARV4519"
default y
select DANUBE_ARCAYDIAN_BRNBOOT
config DANUBE_MACH_ARV452
bool "ARV452"
default y
select IFXMIPS_ARCAYDIAN_BRNBOOT
endmenu
endif

View File

@ -0,0 +1,3 @@
obj-y := dma-core.o irq.o ebu.o setup.o devices.o cgu.o
obj-$(CONFIG_IFXMIPS_ARCAYDIAN_BRNBOOT) += arcaydian.o
obj-$(CONFIG_DANUBE_MACH_ARV452) += mach-arv452.o

View File

@ -0,0 +1,47 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <ifxmips.h>
#include <ifxmips_prom.h>
#include "arcaydian.h"
static int ifxmips_brn = 1;
int __init
ifxmips_find_brn_mac(unsigned char *ifxmips_ethaddr)
{
unsigned char temp[8];
memcpy_fromio(temp,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
if (!memcmp(temp, "BRN-BOOT", 8))
{
memcpy_fromio(ifxmips_ethaddr,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START +
0x800000 - 0x10000 + 0x16), 6);
if (is_valid_ether_addr(ifxmips_ethaddr))
return 1;
} else {
ifxmips_brn = 0;
}
return 0;
}
int
ifxmips_has_brn_block(void)
{
return ifxmips_brn;
}
EXPORT_SYMBOL(ifxmips_has_brn_block);

View File

@ -0,0 +1,6 @@
#ifndef _ARCAYDIAN_H__
#define _ARCAYDIAN_H__
int __init ifxmips_find_brn_mac(unsigned char *ifxmips_ethaddr);
#endif

View File

@ -0,0 +1,457 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#include <linux/autoconf.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#define MAX_BOARD_NAME_LEN 32
#define MAX_IFXMIPS_DEVS 9
#define SYSTEM_DANUBE "Danube"
#define SYSTEM_DANUBE_CHIPID1 0x00129083
#define SYSTEM_DANUBE_CHIPID2 0x0012B083
#define SYSTEM_TWINPASS "Twinpass"
#define SYSTEM_TWINPASS_CHIPID 0x0012D083
enum {
EASY50712,
EASY4010,
ARV4519,
ARV452,
};
extern int ifxmips_pci_external_clock;
extern int ifxmips_pci_req_mask;
static unsigned int chiprev;
static int cmdline_mac;
char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 };
struct ifxmips_board {
int type;
char name[32];
unsigned int system_type;
struct platform_device **devs;
struct resource reset_resource;
struct resource gpiodev_resource;
struct gpio_led *ifxmips_leds;
struct gpio_led *gpio_leds;
int pci_external_clock;
int pci_req_mask;
int num_devs;
};
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
extern unsigned char ifxmips_ethaddr[6];
static int ifxmips_brn;
static struct gpio_led_platform_data ifxmips_led_data;
static struct platform_device ifxmips_led = {
.id = 0,
.name = "ifxmips_led",
.dev = {
.platform_data = (void *) &ifxmips_led_data,
}
};
static struct platform_device ifxmips_gpio = {
.id = 0,
.name = "ifxmips_gpio",
.num_resources = 1,
};
static struct platform_device ifxmips_mii = {
.id = 0,
.name = "ifxmips_mii0",
.dev = {
.platform_data = ifxmips_ethaddr,
}
};
static struct platform_device ifxmips_wdt = {
.id = 0,
.name = "ifxmips_wdt",
};
static struct platform_device ifxmips_ebu = {
.id = 0,
.name = "ifxmips_ebu",
};
static struct resource ifxmips_mtd_resource = {
.start = IFXMIPS_FLASH_START,
.end = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ifxmips_mtd = {
.id = 0,
.name = "ifxmips_mtd",
.num_resources = 1,
.resource = &ifxmips_mtd_resource,
};
static struct platform_device ifxmips_gpio_dev = {
.name = "GPIODEV",
.id = -1,
.num_resources = 1,
};
#ifdef CONFIG_LEDS_GPIO
static struct gpio_led arv4519_gpio_leds[] = {
{ .name = "ifx:green:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 7, .active_low = 1, },
{ .name = "ifx:green:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:green:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:internet", .gpio = 8, .active_low = 1, },
{ .name = "ifx:green:wlan", .gpio = 6, .active_low = 1, },
{ .name = "ifx:green:usbpwr", .gpio = 14, .active_low = 1, },
{ .name = "ifx:green:usb", .gpio = 19, .active_low = 1, },
};
static struct gpio_led arv452_gpio_leds[] = {
{ .name = "ifx:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:blue:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:blue:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 6, .active_low = 1, },
{ .name = "ifx:yello:wps", .gpio = 7, .active_low = 1, },
{ .name = "ifx:red:wps", .gpio = 9, .active_low = 1, },
{ .name = "ifx:blue:voip", .gpio = 32, .active_low = 1, },
{ .name = "ifx:blue:fxs1", .gpio = 33, .active_low = 1, },
{ .name = "ifx:blue:fxs2", .gpio = 34, .active_low = 1, },
{ .name = "ifx:blue:fxo", .gpio = 35, .active_low = 1, },
{ .name = "ifx:blue:voice", .gpio = 36, .active_low = 1, },
{ .name = "ifx:blue:usb", .gpio = 37, .active_low = 1, },
{ .name = "ifx:blue:wlan", .gpio = 38, .active_low = 1, },
{ .name = "ifx:red:internet", .gpio = 41, .active_low = 1, },
};
static struct gpio_led_platform_data ifxmips_gpio_led_data;
static struct platform_device ifxmips_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = (void *) &ifxmips_gpio_led_data,
}
};
#endif
static struct resource dwc_usb_res[] = {
{
.name = "dwc3884_membase",
.flags = IORESOURCE_MEM,
.start = 0x1E101000,
.end = 0x1E101FFF
},
{
.name = "dwc3884_irq",
.flags = IORESOURCE_IRQ,
.start = IFXMIPS_USB_INT,
}
};
static struct platform_device dwc_usb =
{
.id = 0,
.name = "dwc3884-hcd",
.resource = dwc_usb_res,
.num_resources = ARRAY_SIZE(dwc_usb_res),
};
struct platform_device *easy50712_devs[] = {
&ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
&ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev, &dwc_usb
};
struct platform_device *easy4010_devs[] = {
&ifxmips_led, &ifxmips_gpio, &ifxmips_mii,
&ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev, &dwc_usb
};
struct platform_device *arv5419_devs[] = {
&ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd,
&ifxmips_gpio_dev, &ifxmips_wdt, &dwc_usb,
#ifdef CONFIG_LEDS_GPIO
&ifxmips_gpio_leds,
#endif
};
struct platform_device *arv452_devs[] = {
&ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd,
&ifxmips_gpio_dev, &ifxmips_wdt, &dwc_usb,
&ifxmips_ebu,
#ifdef CONFIG_LEDS_GPIO
&ifxmips_gpio_leds,
#endif
};
static struct gpio_led easy50712_leds[] = {
{ .name = "ifx:green:test0", .gpio = 0,},
{ .name = "ifx:green:test1", .gpio = 1,},
{ .name = "ifx:green:test2", .gpio = 2,},
{ .name = "ifx:green:test3", .gpio = 3,},
};
static struct gpio_led easy4010_leds[] = {
{ .name = "ifx:green:test0", .gpio = 0,},
{ .name = "ifx:green:test1", .gpio = 1,},
{ .name = "ifx:green:test2", .gpio = 2,},
{ .name = "ifx:green:test3", .gpio = 3,},
};
static struct ifxmips_board boards[] = {
{
/* infineon eval kit */
.type = EASY50712,
.name = "EASY50712",
.system_type = SYSTEM_DANUBE_CHIPID1,
.devs = easy50712_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 15,},
.gpiodev_resource = { .name = "gpio",
.start = (1 << 0) | (1 << 1),
.end = (1 << 0) | (1 << 1)},
.ifxmips_leds = easy50712_leds,
}, {
/* infineon eval kit */
.type = EASY4010,
.name = "EASY4010",
.system_type = SYSTEM_TWINPASS_CHIPID,
.devs = easy4010_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 15},
.gpiodev_resource = { .name = "gpio",
.start = (1 << 0) | (1 << 1),
.end = (1 << 0) | (1 << 1)},
.ifxmips_leds = easy4010_leds,
}, {
/* arcaydian annex-a board used by thompson, airties, ... */
.type = ARV4519,
.name = "ARV4519",
.system_type = SYSTEM_DANUBE_CHIPID2,
.devs = arv5419_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 14},
.pci_external_clock = 1,
#ifdef CONFIG_LEDS_GPIO
.gpio_leds = arv4519_gpio_leds,
#endif
}, {
/* arcaydian annex-b board used by airties, arcor */
.type = ARV452,
.name = "ARV452",
.system_type = SYSTEM_DANUBE_CHIPID2,
.devs = arv452_devs,
.reset_resource = {.name = "reset", .start = 1, .end = 14},
.pci_external_clock = 1,
#ifdef CONFIG_LEDS_GPIO
.gpio_leds = arv452_gpio_leds,
#endif
},
};
const char *get_system_type(void)
{
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
switch (chiprev) {
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
return SYSTEM_DANUBE;
case SYSTEM_TWINPASS_CHIPID:
return SYSTEM_TWINPASS;
}
return BOARD_SYSTEM_TYPE;
}
static int __init ifxmips_set_board_type(char *str)
{
str = strchr(str, '=');
if (!str)
goto out;
str++;
if (strlen(str) > MAX_BOARD_NAME_LEN)
goto out;
strncpy(board_name, str, MAX_BOARD_NAME_LEN);
printk(KERN_INFO "bootloader told us, that this is a %s board\n",
board_name);
out:
return 1;
}
__setup("ifxmips_board", ifxmips_set_board_type);
static int __init ifxmips_set_ethaddr(char *str)
{
#define IS_HEX(x) \
(((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') \
|| (x >= 'A' && x <= 'F')) ? (1) : (0))
int i;
str = strchr(str, '=');
if (!str)
goto out;
str++;
if (strlen(str) != 17)
goto out;
for (i = 0; i < 6; i++) {
if (!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1]))
goto out;
if ((i != 5) && (str[(3 * i) + 2] != ':'))
goto out;
ifxmips_ethaddr[i] = simple_strtoul(&str[3 * i], NULL, 16);
}
if (is_valid_ether_addr(ifxmips_ethaddr))
cmdline_mac = 1;
out:
return 1;
}
__setup("ethaddr", ifxmips_set_ethaddr);
int ifxmips_find_brn_block(void)
{
unsigned char temp[8];
memcpy_fromio(temp,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8);
if (memcmp(temp, "BRN-BOOT", 8) == 0) {
if (!cmdline_mac)
memcpy_fromio(ifxmips_ethaddr,
(void *)KSEG1ADDR(IFXMIPS_FLASH_START +
0x800000 - 0x10000 + 0x16), 6);
if (is_valid_ether_addr(ifxmips_ethaddr))
cmdline_mac = 1;
return 1;
} else {
return 0;
}
}
int ifxmips_has_brn_block(void)
{
return ifxmips_brn;
}
EXPORT_SYMBOL(ifxmips_has_brn_block);
struct ifxmips_board *ifxmips_find_board(void)
{
int i;
if (!*board_name)
return 0;
for (i = 0; i < ARRAY_SIZE(boards); i++)
if ((boards[i].system_type == chiprev) &&
(!strcmp(boards[i].name, board_name)))
return &boards[i];
return 0;
}
int __init ifxmips_init_devices(void)
{
struct ifxmips_board *board;
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
board = ifxmips_find_board();
ifxmips_brn = ifxmips_find_brn_block();
if (!cmdline_mac)
random_ether_addr(ifxmips_ethaddr);
if (!board) {
switch (chiprev) {
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
default:
board = &boards[0];
break;
case SYSTEM_TWINPASS_CHIPID:
board = &boards[1];
break;
}
}
switch (board->type) {
case EASY50712:
board->num_devs = ARRAY_SIZE(easy50712_devs);
ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds);
break;
case EASY4010:
board->num_devs = ARRAY_SIZE(easy4010_devs);
ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds);
break;
case ARV4519:
/* set some sane defaults for the gpios */
gpio_set_value(3, 0);
gpio_set_value(4, 0);
gpio_set_value(5, 0);
gpio_set_value(6, 0);
gpio_set_value(7, 1);
gpio_set_value(8, 1);
gpio_set_value(19, 0);
board->num_devs = ARRAY_SIZE(arv5419_devs);
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv4519_gpio_leds);
#endif
break;
case ARV452:
/* set some sane defaults for the gpios */
board->num_devs = ARRAY_SIZE(arv452_devs);
ifxmips_w32(0x8001e7ff, IFXMIPS_EBU_BUSCON1);
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv452_gpio_leds);
#endif
break;
}
#ifdef CONFIG_LEDS_GPIO
ifxmips_gpio_led_data.leds = board->gpio_leds;
#endif
ifxmips_led_data.leds = board->ifxmips_leds;
printk(KERN_INFO "%s: adding %d devs\n",
__func__, board->num_devs);
ifxmips_gpio.resource = &board->reset_resource;
ifxmips_gpio_dev.resource = &board->gpiodev_resource;
if (board->pci_external_clock)
ifxmips_pci_external_clock = 1;
if (board->pci_req_mask)
ifxmips_pci_req_mask = board->pci_req_mask;
printk(KERN_INFO "using board definition %s\n", board->name);
return platform_add_devices(board->devs, board->num_devs);
}
arch_initcall(ifxmips_init_devices);

View File

@ -0,0 +1,38 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
void
cgu_setup_pci_clk(int external_clock)
{
/* set clock to 33Mhz */
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~0xf00000,
IFXMIPS_CGU_IFCCR);
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | 0x800000,
IFXMIPS_CGU_IFCCR);
if (external_clock)
{
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~(1 << 16),
IFXMIPS_CGU_IFCCR);
ifxmips_w32((1 << 30), IFXMIPS_CGU_PCICR);
} else {
ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | (1 << 16),
IFXMIPS_CGU_IFCCR);
ifxmips_w32((1 << 31) | (1 << 30), IFXMIPS_CGU_PCICR);
}
}

View File

@ -0,0 +1,104 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
/* usb */
static struct resource dwc_usb_res[] =
{
{
.name = "dwc3884_membase",
.flags = IORESOURCE_MEM,
.start = 0x1E101000,
.end = 0x1E101FFF
},
{
.name = "dwc3884_irq",
.flags = IORESOURCE_IRQ,
.start = IFXMIPS_USB_INT,
}
};
static struct platform_device dwc_usb =
{
.name = "dwc3884-hcd",
.resource = dwc_usb_res,
.num_resources = ARRAY_SIZE(dwc_usb_res),
};
void __init
danube_register_usb(void)
{
platform_device_register(&dwc_usb);
}
/* ebu gpio */
static struct platform_device ifxmips_ebu_gpio =
{
.name = "ifxmips_ebu",
.num_resources = 1,
};
void __init
danube_register_ebu_gpio(struct resource *resource, u32 value)
{
ifxmips_ebu_gpio.resource = resource;
ifxmips_ebu_gpio.dev.platform_data = (void*)value;
platform_device_register(&ifxmips_ebu_gpio);
}
/* ethernet */
unsigned char ifxmips_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static struct resource danube_ethernet_resources =
{
.start = IFXMIPS_PPE32_BASE_ADDR,
.end = IFXMIPS_PPE32_BASE_ADDR + IFXMIPS_PPE32_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device danube_ethernet =
{
.name = "danube_ethernet",
.resource = &danube_ethernet_resources,
.num_resources = 1,
.dev = {
.platform_data = ifxmips_ethaddr,
}
};
void __init
danube_register_ethernet(unsigned char *mac)
{
if(mac)
danube_ethernet.dev.platform_data = mac;
platform_device_register(&danube_ethernet);
}
/* pci */
extern int ifxmips_pci_external_clock;
extern int ifxmips_pci_req_mask;
void __init
danube_register_pci(int clock, int irq_mask)
{
ifxmips_pci_external_clock = clock;
if(irq_mask)
ifxmips_pci_req_mask = irq_mask;
}

View File

@ -0,0 +1,16 @@
#ifndef _DANUBE_DEVICES_H__
#define _DANUBE_DEVICES_H__
#include "../common/devices.h"
enum {
PCI_CLOCK_INT = 0,
PCI_CLOCK_EXT
};
void __init danube_register_usb(void);
void __init danube_register_ebu_gpio(struct resource *resource, u32 value);
void __init danube_register_ethernet(unsigned char *mac);
void __init danube_register_pci(int clock, int irq_mask);
#endif

View File

@ -0,0 +1,690 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/selection.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_dma.h>
#include <ifxmips_pmu.h>
/*25 descriptors for each dma channel,4096/8/20=25.xx*/
#define IFXMIPS_DMA_DESCRIPTOR_OFFSET 25
#define MAX_DMA_DEVICE_NUM 6 /*max ports connecting to dma */
#define MAX_DMA_CHANNEL_NUM 20 /*max dma channels */
#define DMA_INT_BUDGET 100 /*budget for interrupt handling */
#define DMA_POLL_COUNTER 4 /*fix me, set the correct counter value here! */
extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr);
extern void ifxmips_enable_irq(unsigned int irq_nr);
extern void ifxmips_disable_irq(unsigned int irq_nr);
u64 *g_desc_list;
struct dma_device_info dma_devs[MAX_DMA_DEVICE_NUM];
struct dma_channel_info dma_chan[MAX_DMA_CHANNEL_NUM];
static const char *global_device_name[MAX_DMA_DEVICE_NUM] =
{ "PPE", "DEU", "SPI", "SDIO", "MCTRL0", "MCTRL1" };
struct dma_chan_map default_dma_map[MAX_DMA_CHANNEL_NUM] = {
{"PPE", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH0_INT, 0},
{"PPE", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH1_INT, 0},
{"PPE", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH2_INT, 1},
{"PPE", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH3_INT, 1},
{"PPE", IFXMIPS_DMA_RX, 2, IFXMIPS_DMA_CH4_INT, 2},
{"PPE", IFXMIPS_DMA_TX, 2, IFXMIPS_DMA_CH5_INT, 2},
{"PPE", IFXMIPS_DMA_RX, 3, IFXMIPS_DMA_CH6_INT, 3},
{"PPE", IFXMIPS_DMA_TX, 3, IFXMIPS_DMA_CH7_INT, 3},
{"DEU", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH8_INT, 0},
{"DEU", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH9_INT, 0},
{"DEU", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH10_INT, 1},
{"DEU", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH11_INT, 1},
{"SPI", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH12_INT, 0},
{"SPI", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH13_INT, 0},
{"SDIO", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH14_INT, 0},
{"SDIO", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH15_INT, 0},
{"MCTRL0", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH16_INT, 0},
{"MCTRL0", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH17_INT, 0},
{"MCTRL1", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH18_INT, 1},
{"MCTRL1", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH19_INT, 1}
};
struct dma_chan_map *chan_map = default_dma_map;
volatile u32 g_ifxmips_dma_int_status;
volatile int g_ifxmips_dma_in_process; /* 0=not in process, 1=in process */
void do_dma_tasklet(unsigned long);
DECLARE_TASKLET(dma_tasklet, do_dma_tasklet, 0);
u8 *common_buffer_alloc(int len, int *byte_offset, void **opt)
{
u8 *buffer = kmalloc(len * sizeof(u8), GFP_KERNEL);
*byte_offset = 0;
return buffer;
}
void common_buffer_free(u8 *dataptr, void *opt)
{
kfree(dataptr);
}
void enable_ch_irq(struct dma_channel_info *pCh)
{
int chan_no = (int)(pCh - dma_chan);
unsigned long flag;
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0x4a, IFXMIPS_DMA_CIE);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
local_irq_restore(flag);
ifxmips_enable_irq(pCh->irq);
}
void disable_ch_irq(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int) (pCh - dma_chan);
local_irq_save(flag);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0, IFXMIPS_DMA_CIE);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN);
local_irq_restore(flag);
ifxmips_mask_and_ack_irq(pCh->irq);
}
void open_chan(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int)(pCh - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 1, IFXMIPS_DMA_CCTRL);
if (pCh->dir == IFXMIPS_DMA_RX)
enable_ch_irq(pCh);
local_irq_restore(flag);
}
void close_chan(struct dma_channel_info *pCh)
{
unsigned long flag;
int chan_no = (int) (pCh - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
disable_ch_irq(pCh);
local_irq_restore(flag);
}
void reset_chan(struct dma_channel_info *pCh)
{
int chan_no = (int) (pCh - dma_chan);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
}
void rx_chan_intr_handler(int chan_no)
{
struct dma_device_info *pDev = (struct dma_device_info *)dma_chan[chan_no].dma_dev;
struct dma_channel_info *pCh = &dma_chan[chan_no];
struct rx_desc *rx_desc_p;
int tmp;
unsigned long flag;
/*handle command complete interrupt */
rx_desc_p = (struct rx_desc *)pCh->desc_base + pCh->curr_desc;
if (rx_desc_p->status.field.OWN == CPU_OWN
&& rx_desc_p->status.field.C
&& rx_desc_p->status.field.data_length < 1536){
/* Every thing is correct, then we inform the upper layer */
pDev->current_rx_chan = pCh->rel_chan_no;
if (pDev->intr_handler)
pDev->intr_handler(pDev, RCV_INT);
pCh->weight--;
} else {
local_irq_save(flag);
tmp = ifxmips_r32(IFXMIPS_DMA_CS);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS);
ifxmips_w32(tmp, IFXMIPS_DMA_CS);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
local_irq_restore(flag);
ifxmips_enable_irq(dma_chan[chan_no].irq);
}
}
inline void tx_chan_intr_handler(int chan_no)
{
struct dma_device_info *pDev = (struct dma_device_info *)dma_chan[chan_no].dma_dev;
struct dma_channel_info *pCh = &dma_chan[chan_no];
int tmp;
unsigned long flag;
local_irq_save(flag);
tmp = ifxmips_r32(IFXMIPS_DMA_CS);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS);
ifxmips_w32(tmp, IFXMIPS_DMA_CS);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
local_irq_restore(flag);
pDev->current_tx_chan = pCh->rel_chan_no;
if (pDev->intr_handler)
pDev->intr_handler(pDev, TRANSMIT_CPT_INT);
}
void do_dma_tasklet(unsigned long unused)
{
int i;
int chan_no = 0;
int budget = DMA_INT_BUDGET;
int weight = 0;
unsigned long flag;
while (g_ifxmips_dma_int_status) {
if (budget-- < 0) {
tasklet_schedule(&dma_tasklet);
return;
}
chan_no = -1;
weight = 0;
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
if ((g_ifxmips_dma_int_status & (1 << i)) && dma_chan[i].weight > 0) {
if (dma_chan[i].weight > weight) {
chan_no = i;
weight = dma_chan[chan_no].weight;
}
}
}
if (chan_no >= 0) {
if (chan_map[chan_no].dir == IFXMIPS_DMA_RX)
rx_chan_intr_handler(chan_no);
else
tx_chan_intr_handler(chan_no);
} else {
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++)
dma_chan[i].weight = dma_chan[i].default_weight;
}
}
local_irq_save(flag);
g_ifxmips_dma_in_process = 0;
if (g_ifxmips_dma_int_status) {
g_ifxmips_dma_in_process = 1;
tasklet_schedule(&dma_tasklet);
}
local_irq_restore(flag);
}
irqreturn_t dma_interrupt(int irq, void *dev_id)
{
struct dma_channel_info *pCh;
int chan_no = 0;
int tmp;
pCh = (struct dma_channel_info *)dev_id;
chan_no = (int)(pCh - dma_chan);
if (chan_no < 0 || chan_no > 19)
BUG();
tmp = ifxmips_r32(IFXMIPS_DMA_IRNEN);
ifxmips_w32(0, IFXMIPS_DMA_IRNEN);
g_ifxmips_dma_int_status |= 1 << chan_no;
ifxmips_w32(tmp, IFXMIPS_DMA_IRNEN);
ifxmips_mask_and_ack_irq(irq);
if (!g_ifxmips_dma_in_process) {
g_ifxmips_dma_in_process = 1;
tasklet_schedule(&dma_tasklet);
}
return IRQ_HANDLED;
}
struct dma_device_info *dma_device_reserve(char *dev_name)
{
int i;
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) {
if (strcmp(dev_name, dma_devs[i].device_name) == 0) {
if (dma_devs[i].reserved)
return NULL;
dma_devs[i].reserved = 1;
break;
}
}
return &dma_devs[i];
}
EXPORT_SYMBOL(dma_device_reserve);
void dma_device_release(struct dma_device_info *dev)
{
dev->reserved = 0;
}
EXPORT_SYMBOL(dma_device_release);
void dma_device_register(struct dma_device_info *dev)
{
int i, j;
int chan_no = 0;
u8 *buffer;
int byte_offset;
unsigned long flag;
struct dma_device_info *pDev;
struct dma_channel_info *pCh;
struct rx_desc *rx_desc_p;
struct tx_desc *tx_desc_p;
for (i = 0; i < dev->max_tx_chan_num; i++) {
pCh = dev->tx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(pCh - dma_chan);
for (j = 0; j < pCh->desc_len; j++) {
tx_desc_p = (struct tx_desc *)pCh->desc_base + j;
memset(tx_desc_p, 0, sizeof(struct tx_desc));
}
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
/* check if the descriptor length is changed */
if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len)
ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2)
;
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
ifxmips_w32(0x30100, IFXMIPS_DMA_CCTRL); /* reset and enable channel,enable channel later */
local_irq_restore(flag);
}
}
for (i = 0; i < dev->max_rx_chan_num; i++) {
pCh = dev->rx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(pCh - dma_chan);
for (j = 0; j < pCh->desc_len; j++) {
rx_desc_p = (struct rx_desc *)pCh->desc_base + j;
pDev = (struct dma_device_info *)(pCh->dma_dev);
buffer = pDev->buffer_alloc(pCh->packet_size, &byte_offset, (void *)&(pCh->opt[j]));
if (!buffer)
break;
dma_cache_inv((unsigned long) buffer, pCh->packet_size);
rx_desc_p->Data_Pointer = (u32)CPHYSADDR((u32)buffer);
rx_desc_p->status.word = 0;
rx_desc_p->status.field.byte_offset = byte_offset;
rx_desc_p->status.field.OWN = DMA_OWN;
rx_desc_p->status.field.data_length = pCh->packet_size;
}
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
/* check if the descriptor length is changed */
if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len)
ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2)
;
ifxmips_w32(0x0a, IFXMIPS_DMA_CIE); /* fix me, should enable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN);
ifxmips_w32(0x30000, IFXMIPS_DMA_CCTRL);
local_irq_restore(flag);
ifxmips_enable_irq(dma_chan[chan_no].irq);
}
}
}
EXPORT_SYMBOL(dma_device_register);
void dma_device_unregister(struct dma_device_info *dev)
{
int i, j;
int chan_no;
struct dma_channel_info *pCh;
struct rx_desc *rx_desc_p;
struct tx_desc *tx_desc_p;
unsigned long flag;
for (i = 0; i < dev->max_tx_chan_num; i++) {
pCh = dev->tx_chan[i];
if (pCh->control == IFXMIPS_DMA_CH_ON) {
chan_no = (int)(dev->tx_chan[i] - dma_chan);
local_irq_save(flag);
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
pCh->curr_desc = 0;
pCh->prev_desc = 0;
pCh->control = IFXMIPS_DMA_CH_OFF;
ifxmips_w32(0, IFXMIPS_DMA_CIE); /* fix me, should disable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /* disable interrupts */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1)
;
local_irq_restore(flag);
for (j = 0; j < pCh->desc_len; j++) {
tx_desc_p = (struct tx_desc *)pCh->desc_base + j;
if ((tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C)
|| (tx_desc_p->status.field.OWN == DMA_OWN && tx_desc_p->status.field.data_length > 0)) {
dev->buffer_free((u8 *) __va(tx_desc_p->Data_Pointer), (void *)pCh->opt[j]);
}
tx_desc_p->status.field.OWN = CPU_OWN;
memset(tx_desc_p, 0, sizeof(struct tx_desc));
}
/* TODO should free buffer that is not transferred by dma */
}
}
for (i = 0; i < dev->max_rx_chan_num; i++) {
pCh = dev->rx_chan[i];
chan_no = (int)(dev->rx_chan[i] - dma_chan);
ifxmips_disable_irq(pCh->irq);
local_irq_save(flag);
g_ifxmips_dma_int_status &= ~(1 << chan_no);
pCh->curr_desc = 0;
pCh->prev_desc = 0;
pCh->control = IFXMIPS_DMA_CH_OFF;
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
ifxmips_w32(0, IFXMIPS_DMA_CIE); /* fix me, should disable all the interrupts here? */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /* disable interrupts */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL);
while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1)
;
local_irq_restore(flag);
for (j = 0; j < pCh->desc_len; j++) {
rx_desc_p = (struct rx_desc *) pCh->desc_base + j;
if ((rx_desc_p->status.field.OWN == CPU_OWN
&& rx_desc_p->status.field.C)
|| (rx_desc_p->status.field.OWN == DMA_OWN
&& rx_desc_p->status.field.data_length > 0)) {
dev->buffer_free((u8 *)
__va(rx_desc_p->Data_Pointer),
(void *) pCh->opt[j]);
}
}
}
}
EXPORT_SYMBOL(dma_device_unregister);
int dma_device_read(struct dma_device_info *dma_dev, u8 **dataptr, void **opt)
{
u8 *buf;
int len;
int byte_offset = 0;
void *p = NULL;
struct dma_channel_info *pCh = dma_dev->rx_chan[dma_dev->current_rx_chan];
struct rx_desc *rx_desc_p;
/* get the rx data first */
rx_desc_p = (struct rx_desc *) pCh->desc_base + pCh->curr_desc;
if (!(rx_desc_p->status.field.OWN == CPU_OWN && rx_desc_p->status.field.C))
return 0;
buf = (u8 *) __va(rx_desc_p->Data_Pointer);
*(u32 *)dataptr = (u32)buf;
len = rx_desc_p->status.field.data_length;
if (opt)
*(int *)opt = (int)pCh->opt[pCh->curr_desc];
/* replace with a new allocated buffer */
buf = dma_dev->buffer_alloc(pCh->packet_size, &byte_offset, &p);
if (buf) {
dma_cache_inv((unsigned long) buf, pCh->packet_size);
pCh->opt[pCh->curr_desc] = p;
wmb();
rx_desc_p->Data_Pointer = (u32) CPHYSADDR((u32) buf);
rx_desc_p->status.word = (DMA_OWN << 31) | ((byte_offset) << 23) | pCh->packet_size;
wmb();
} else {
*(u32 *) dataptr = 0;
if (opt)
*(int *) opt = 0;
len = 0;
}
/* increase the curr_desc pointer */
pCh->curr_desc++;
if (pCh->curr_desc == pCh->desc_len)
pCh->curr_desc = 0;
return len;
}
EXPORT_SYMBOL(dma_device_read);
int dma_device_write(struct dma_device_info *dma_dev, u8 *dataptr, int len, void *opt)
{
unsigned long flag;
u32 tmp, byte_offset;
struct dma_channel_info *pCh;
int chan_no;
struct tx_desc *tx_desc_p;
local_irq_save(flag);
pCh = dma_dev->tx_chan[dma_dev->current_tx_chan];
chan_no = (int)(pCh - (struct dma_channel_info *) dma_chan);
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->prev_desc;
while (tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C) {
dma_dev->buffer_free((u8 *) __va(tx_desc_p->Data_Pointer), pCh->opt[pCh->prev_desc]);
memset(tx_desc_p, 0, sizeof(struct tx_desc));
pCh->prev_desc = (pCh->prev_desc + 1) % (pCh->desc_len);
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->prev_desc;
}
tx_desc_p = (struct tx_desc *)pCh->desc_base + pCh->curr_desc;
/* Check whether this descriptor is available */
if (tx_desc_p->status.field.OWN == DMA_OWN || tx_desc_p->status.field.C) {
/* if not, the tell the upper layer device */
dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT);
local_irq_restore(flag);
printk(KERN_INFO "%s %d: failed to write!\n", __func__, __LINE__);
return 0;
}
pCh->opt[pCh->curr_desc] = opt;
/* byte offset----to adjust the starting address of the data buffer, should be multiple of the burst length. */
byte_offset = ((u32) CPHYSADDR((u32) dataptr)) % ((dma_dev->tx_burst_len) * 4);
dma_cache_wback((unsigned long) dataptr, len);
wmb();
tx_desc_p->Data_Pointer = (u32) CPHYSADDR((u32) dataptr) - byte_offset;
wmb();
tx_desc_p->status.word = (DMA_OWN << 31) | DMA_DESC_SOP_SET | DMA_DESC_EOP_SET | ((byte_offset) << 23) | len;
wmb();
pCh->curr_desc++;
if (pCh->curr_desc == pCh->desc_len)
pCh->curr_desc = 0;
/*Check whether this descriptor is available */
tx_desc_p = (struct tx_desc *) pCh->desc_base + pCh->curr_desc;
if (tx_desc_p->status.field.OWN == DMA_OWN) {
/*if not , the tell the upper layer device */
dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT);
}
ifxmips_w32(chan_no, IFXMIPS_DMA_CS);
tmp = ifxmips_r32(IFXMIPS_DMA_CCTRL);
if (!(tmp & 1))
pCh->open(pCh);
local_irq_restore(flag);
return len;
}
EXPORT_SYMBOL(dma_device_write);
int map_dma_chan(struct dma_chan_map *map)
{
int i, j;
int result;
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++)
strcpy(dma_devs[i].device_name, global_device_name[i]);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
dma_chan[i].irq = map[i].irq;
result = request_irq(dma_chan[i].irq, dma_interrupt, IRQF_DISABLED, map[i].dev_name, (void *)&dma_chan[i]);
if (result) {
printk(KERN_WARNING "error, cannot get dma_irq!\n");
free_irq(dma_chan[i].irq, (void *) &dma_interrupt);
return -EFAULT;
}
}
for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) {
dma_devs[i].num_tx_chan = 0; /*set default tx channel number to be one */
dma_devs[i].num_rx_chan = 0; /*set default rx channel number to be one */
dma_devs[i].max_rx_chan_num = 0;
dma_devs[i].max_tx_chan_num = 0;
dma_devs[i].buffer_alloc = &common_buffer_alloc;
dma_devs[i].buffer_free = &common_buffer_free;
dma_devs[i].intr_handler = NULL;
dma_devs[i].tx_burst_len = 4;
dma_devs[i].rx_burst_len = 4;
if (i == 0) {
ifxmips_w32(0, IFXMIPS_DMA_PS);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_PCTRL) | ((0xf << 8) | (1 << 6)), IFXMIPS_DMA_PCTRL); /*enable dma drop */
}
if (i == 1) {
ifxmips_w32(1, IFXMIPS_DMA_PS);
ifxmips_w32(0x14, IFXMIPS_DMA_PCTRL); /*deu port setting */
}
for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) {
dma_chan[j].byte_offset = 0;
dma_chan[j].open = &open_chan;
dma_chan[j].close = &close_chan;
dma_chan[j].reset = &reset_chan;
dma_chan[j].enable_irq = &enable_ch_irq;
dma_chan[j].disable_irq = &disable_ch_irq;
dma_chan[j].rel_chan_no = map[j].rel_chan_no;
dma_chan[j].control = IFXMIPS_DMA_CH_OFF;
dma_chan[j].default_weight = IFXMIPS_DMA_CH_DEFAULT_WEIGHT;
dma_chan[j].weight = dma_chan[j].default_weight;
dma_chan[j].curr_desc = 0;
dma_chan[j].prev_desc = 0;
}
for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) {
if (strcmp(dma_devs[i].device_name, map[j].dev_name) == 0) {
if (map[j].dir == IFXMIPS_DMA_RX) {
dma_chan[j].dir = IFXMIPS_DMA_RX;
dma_devs[i].max_rx_chan_num++;
dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1] = &dma_chan[j];
dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1]->pri = map[j].pri;
dma_chan[j].dma_dev = (void *)&dma_devs[i];
} else if (map[j].dir == IFXMIPS_DMA_TX) {
/*TX direction */
dma_chan[j].dir = IFXMIPS_DMA_TX;
dma_devs[i].max_tx_chan_num++;
dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1] = &dma_chan[j];
dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1]->pri = map[j].pri;
dma_chan[j].dma_dev = (void *)&dma_devs[i];
} else {
printk(KERN_WARNING "WRONG DMA MAP!\n");
}
}
}
}
return 0;
}
void dma_chip_init(void)
{
int i;
/* enable DMA from PMU */
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA);
/* reset DMA */
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CTRL) | 1, IFXMIPS_DMA_CTRL);
/* disable all interrupts */
ifxmips_w32(0, IFXMIPS_DMA_IRNEN);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
ifxmips_w32(i, IFXMIPS_DMA_CS);
ifxmips_w32(0x2, IFXMIPS_DMA_CCTRL);
ifxmips_w32(0x80000040, IFXMIPS_DMA_CPOLL);
ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~0x1, IFXMIPS_DMA_CCTRL);
}
}
int ifxmips_dma_init(void)
{
int i;
dma_chip_init();
if (map_dma_chan(default_dma_map))
BUG();
g_desc_list = (u64 *)KSEG1ADDR(__get_free_page(GFP_DMA));
if (g_desc_list == NULL) {
printk(KERN_WARNING "no memory for desriptor\n");
return -ENOMEM;
}
memset(g_desc_list, 0, PAGE_SIZE);
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) {
dma_chan[i].desc_base = (u32)g_desc_list + i * IFXMIPS_DMA_DESCRIPTOR_OFFSET * 8;
dma_chan[i].curr_desc = 0;
dma_chan[i].desc_len = IFXMIPS_DMA_DESCRIPTOR_OFFSET;
ifxmips_w32(i, IFXMIPS_DMA_CS);
ifxmips_w32((u32)CPHYSADDR(dma_chan[i].desc_base), IFXMIPS_DMA_CDBA);
ifxmips_w32(dma_chan[i].desc_len, IFXMIPS_DMA_CDLEN);
}
return 0;
}
arch_initcall(ifxmips_dma_init);
void dma_cleanup(void)
{
int i;
free_page(KSEG0ADDR((unsigned long) g_desc_list));
for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++)
free_irq(dma_chan[i].irq, (void *)&dma_interrupt);
}
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,96 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include <ifxmips.h>
#include <ifxmips_ebu.h>
#define IFXMIPS_EBU_BUSCON 0x1e7ff
#define IFXMIPS_EBU_WP 0x80000000
static int shadow = 0;
static void __iomem *virt;
static int
ifxmips_ebu_direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
return 0;
}
static void
ifxmips_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
{
unsigned long flags;
if(value)
shadow |= (1 << offset);
else
shadow &= ~(1 << offset);
spin_lock_irqsave(&ebu_lock, flags);
ifxmips_w32(IFXMIPS_EBU_BUSCON, IFXMIPS_EBU_BUSCON1);
*((__u16*)virt) = shadow;
ifxmips_w32(IFXMIPS_EBU_BUSCON | IFXMIPS_EBU_WP, IFXMIPS_EBU_BUSCON1);
spin_unlock_irqrestore(&ebu_lock, flags);
}
static struct gpio_chip
ifxmips_ebu_chip =
{
.label = "ifxmips_ebu",
.direction_output = ifxmips_ebu_direction_output,
.set = ifxmips_ebu_set,
.base = 32,
.ngpio = 16,
.can_sleep = 1,
.owner = THIS_MODULE,
};
static int __devinit
ifxmips_ebu_probe(struct platform_device *pdev)
{
ifxmips_w32(pdev->resource->start | 0x1, IFXMIPS_EBU_ADDRSEL1);
ifxmips_w32(IFXMIPS_EBU_BUSCON | IFXMIPS_EBU_WP, IFXMIPS_EBU_BUSCON1);
virt = ioremap_nocache(pdev->resource->start, pdev->resource->end);
if(gpiochip_add(&ifxmips_ebu_chip))
return -EINVAL;
shadow = (int) pdev->dev.platform_data;
printk("IFXMIPS: ebu-gpio loaded\n");
return 0;
}
static int
ifxmips_ebu_remove(struct platform_device *dev)
{
return gpiochip_remove(&ifxmips_ebu_chip);
}
static struct platform_driver
ifxmips_ebu_driver = {
.probe = ifxmips_ebu_probe,
.remove = ifxmips_ebu_remove,
.driver = {
.name = "ifxmips_ebu",
.owner = THIS_MODULE,
},
};
static int __init
ifxmips_ebu_init(void)
{
return platform_driver_register(&ifxmips_ebu_driver);
}
static void __exit
ifxmips_ebu_exit(void)
{
platform_driver_unregister(&ifxmips_ebu_driver);
}
module_init(ifxmips_ebu_init);
module_exit(ifxmips_ebu_exit);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ifxmips - EBU Latch GPIO-Expander");

View File

@ -0,0 +1,233 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <asm/irq_cpu.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
void
ifxmips_disable_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) & ~(1 << irq_nr), ier);
return;
}
ier += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_disable_irq);
void
ifxmips_mask_and_ack_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
u32 *isr = IFXMIPS_ICU_IM0_ISR;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) & ~(1 << irq_nr), ier);
ifxmips_w32((1 << irq_nr), isr);
return;
}
ier += IFXMIPS_ICU_OFFSET;
isr += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_mask_and_ack_irq);
void
ifxmips_enable_irq(unsigned int irq_nr)
{
int i;
u32 *ier = IFXMIPS_ICU_IM0_IER;
irq_nr -= INT_NUM_IRQ0;
for (i = 0; i <= 4; i++)
{
if (irq_nr < INT_NUM_IM_OFFSET)
{
ifxmips_w32(ifxmips_r32(ier) | (1 << irq_nr), ier);
return;
}
ier += IFXMIPS_ICU_OFFSET;
irq_nr -= INT_NUM_IM_OFFSET;
}
}
EXPORT_SYMBOL(ifxmips_enable_irq);
static unsigned int
ifxmips_startup_irq(unsigned int irq)
{
ifxmips_enable_irq(irq);
return 0;
}
static void
ifxmips_end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
ifxmips_enable_irq(irq);
}
static struct irq_chip
ifxmips_irq_type = {
"ifxmips",
.startup = ifxmips_startup_irq,
.enable = ifxmips_enable_irq,
.disable = ifxmips_disable_irq,
.unmask = ifxmips_enable_irq,
.ack = ifxmips_end_irq,
.mask = ifxmips_disable_irq,
.mask_ack = ifxmips_mask_and_ack_irq,
.end = ifxmips_end_irq,
};
/* silicon bug causes only the msb set to 1 to be valid. all
other bits might be bogus */
static inline int
ls1bit32(unsigned long x)
{
__asm__ (
".set push \n"
".set mips32 \n"
"clz %0, %1 \n"
".set pop \n"
: "=r" (x)
: "r" (x));
return 31 - x;
}
static void
ifxmips_hw_irqdispatch(int module)
{
u32 irq;
irq = ifxmips_r32(IFXMIPS_ICU_IM0_IOSR + (module * IFXMIPS_ICU_OFFSET));
if (irq == 0)
return;
/* we need to do this due to a silicon bug */
irq = ls1bit32(irq);
do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
if ((irq == 22) && (module == 0))
ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_ISTAT) | 0x10,
IFXMIPS_EBU_PCC_ISTAT);
}
#ifdef CONFIG_CPU_MIPSR2_IRQ_VI
#define DEFINE_HWx_IRQDISPATCH(x) \
static void ifxmips_hw ## x ## _irqdispatch(void)\
{\
ifxmips_hw_irqdispatch(x); \
}
static void ifxmips_hw5_irqdispatch(void)
{
do_IRQ(MIPS_CPU_TIMER_IRQ);
}
DEFINE_HWx_IRQDISPATCH(0)
DEFINE_HWx_IRQDISPATCH(1)
DEFINE_HWx_IRQDISPATCH(2)
DEFINE_HWx_IRQDISPATCH(3)
DEFINE_HWx_IRQDISPATCH(4)
/*DEFINE_HWx_IRQDISPATCH(5)*/
#endif /* #ifdef CONFIG_CPU_MIPSR2_IRQ_VI */
asmlinkage void
plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
unsigned int i;
if (pending & CAUSEF_IP7)
{
do_IRQ(MIPS_CPU_TIMER_IRQ);
goto out;
} else {
for (i = 0; i < 5; i++)
{
if (pending & (CAUSEF_IP2 << i))
{
ifxmips_hw_irqdispatch(i);
goto out;
}
}
}
printk(KERN_ALERT "Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
out:
return;
}
static struct irqaction
cascade = {
.handler = no_action,
.flags = IRQF_DISABLED,
.name = "cascade",
};
void __init
arch_init_irq(void)
{
int i;
for (i = 0; i < 5; i++)
ifxmips_w32(0, IFXMIPS_ICU_IM0_IER + (i * IFXMIPS_ICU_OFFSET));
mips_cpu_irq_init();
for (i = 2; i <= 6; i++)
setup_irq(i, &cascade);
#ifdef CONFIG_CPU_MIPSR2_IRQ_VI
if (cpu_has_vint) {
printk(KERN_INFO "Setting up vectored interrupts\n");
set_vi_handler(2, ifxmips_hw0_irqdispatch);
set_vi_handler(3, ifxmips_hw1_irqdispatch);
set_vi_handler(4, ifxmips_hw2_irqdispatch);
set_vi_handler(5, ifxmips_hw3_irqdispatch);
set_vi_handler(6, ifxmips_hw4_irqdispatch);
set_vi_handler(7, ifxmips_hw5_irqdispatch);
}
#endif
for (i = INT_NUM_IRQ0; i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
set_irq_chip_and_handler(i, &ifxmips_irq_type,
handle_level_irq);
#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#else
set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#endif
}
void __cpuinit
arch_fixup_c0_irqs(void)
{
/* FIXME: check for CPUID and only do fix for specific chips/versions */
cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
cp0_perfcount_irq = CP0_LEGACY_PERFCNT_IRQ;
}

View File

@ -0,0 +1,170 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/gpio_buttons.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <machine.h>
#include <ifxmips_prom.h>
#include "arcaydian.h"
#include "devices.h"
#define ARV452_EBU_GPIO_START 0x14000000
#define ARV452_EBU_GPIO_SIZE 0x00001000
#define ARV452_GPIO_BUTTON_RESET 14
#define ARV452_BUTTONS_POLL_INTERVAL 20
#define ARV452_LATCH_SWITCH (1 << 10)
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition arv452_partitions[] =
{
{
.name = "uboot",
.offset = 0x0,
.size = 0x20000,
},
{
.name = "uboot_env",
.offset = 0x20000,
.size = 0x0,
},
{
.name = "kernel",
.offset = 0x0,
.size = 0x0,
},
{
.name = "rootfs",
.offset = 0x0,
.size = 0x0,
},
{
.name = "board_config",
.offset = 0x3f0000,
.size = 0x10000,
},
{
.name = "openwrt",
.offset = 0x0,
.size = 0x0,
},
};
#endif
static struct physmap_flash_data arv452_flash_data = {
#ifdef CONFIG_MTD_PARTITIONS
.nr_parts = ARRAY_SIZE(arv452_partitions),
.parts = arv452_partitions,
#endif
};
static struct gpio_led
arv452_leds_gpio[] __initdata = {
/*
{ .name = "ifx0", .gpio = 0, .active_low = 1, },
{ .name = "ifx1", .gpio = 1, .active_low = 1, },
{ .name = "ifx2", .gpio = 2, .active_low = 1, },
*/
{ .name = "ifx:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "ifx:blue:adsl", .gpio = 4, .active_low = 1, },
{ .name = "ifx:blue:internet", .gpio = 5, .active_low = 1, },
{ .name = "ifx:red:power", .gpio = 6, .active_low = 1, },
{ .name = "ifx:yello:wps", .gpio = 7, .active_low = 1, },
{ .name = "ifx:red:wps", .gpio = 9, .active_low = 1, },
/*
{ .name = "ifx10", .gpio = 10, .active_low = 1, },
{ .name = "ifx11", .gpio = 11, .active_low = 1, },
{ .name = "ifx12", .gpio = 12, .active_low = 1, },
{ .name = "ifx13", .gpio = 13, .active_low = 1, },
{ .name = "ifx14", .gpio = 14, .active_low = 1, },
{ .name = "ifx15", .gpio = 15, .active_low = 1, },
{ .name = "ifx16", .gpio = 16, .active_low = 1, },
{ .name = "ifx17", .gpio = 17, .active_low = 1, },
{ .name = "ifx18", .gpio = 18, .active_low = 1, },
{ .name = "ifx19", .gpio = 19, .active_low = 1, },
{ .name = "ifx20", .gpio = 20, .active_low = 1, },
{ .name = "ifx21", .gpio = 21, .active_low = 1, },
{ .name = "ifx22", .gpio = 22, .active_low = 1, },
{ .name = "ifx23", .gpio = 23, .active_low = 1, },
{ .name = "ifx24", .gpio = 24, .active_low = 1, },
{ .name = "ifx25", .gpio = 25, .active_low = 1, },
{ .name = "ifx26", .gpio = 26, .active_low = 1, },
{ .name = "ifx27", .gpio = 27, .active_low = 1, },
{ .name = "ifx28", .gpio = 28, .active_low = 1, },
{ .name = "ifx29", .gpio = 29, .active_low = 1, },
{ .name = "ifx30", .gpio = 30, .active_low = 1, },
{ .name = "ifx31", .gpio = 31, .active_low = 1, },
*/
{ .name = "ifx:blue:voip", .gpio = 32, .active_low = 1, },
{ .name = "ifx:blue:fxs1", .gpio = 33, .active_low = 1, },
{ .name = "ifx:blue:fxs2", .gpio = 34, .active_low = 1, },
{ .name = "ifx:blue:fxo", .gpio = 35, .active_low = 1, },
{ .name = "ifx:blue:voice", .gpio = 36, .active_low = 1, },
{ .name = "ifx:blue:usb", .gpio = 37, .active_low = 1, },
{ .name = "ifx:blue:wlan", .gpio = 38, .active_low = 1, },
/* { .name = "ifx39", .gpio = 39, .active_low = 1, },
{ .name = "ifx40", .gpio = 40, .active_low = 1, },
{ .name = "ifx41", .gpio = 41, .active_low = 1, },
{ .name = "ifx42", .gpio = 42, .active_low = 1, },
{ .name = "ifx43", .gpio = 43, .active_low = 1, },
{ .name = "ifx44", .gpio = 44, .active_low = 1, },
{ .name = "ifx45", .gpio = 45, .active_low = 1, },
{ .name = "ifx46", .gpio = 46, .active_low = 1, },
{ .name = "ifx47", .gpio = 47, .active_low = 1, },
*/
};
static struct gpio_button
arv452_gpio_buttons[] __initdata = {
{
.desc = "reset",
.type = EV_KEY,
.code = BTN_0,
.threshold = 3,
.gpio = ARV452_GPIO_BUTTON_RESET,
.active_low = 1,
}
};
static struct resource arv452_ebu_resource =
{
.name = "ebu-gpio",
.start = ARV452_EBU_GPIO_START,
.end = ARV452_EBU_GPIO_START + ARV452_EBU_GPIO_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static void __init
arv452_init(void)
{
unsigned char mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
ifxmips_find_brn_mac(mac);
ifxmips_register_gpio();
danube_register_ebu_gpio(&arv452_ebu_resource, ARV452_LATCH_SWITCH);
ifxmips_register_mtd(&arv452_flash_data);
danube_register_pci(PCI_CLOCK_EXT, 0);
ifxmips_register_wdt();
ifxmips_register_gpio_leds(arv452_leds_gpio, ARRAY_SIZE(arv452_leds_gpio));
danube_register_ethernet(mac);
danube_register_usb();
}
MIPS_MACHINE(IFXMIPS_MACH_ARV452,
"ARV452",
"Airties WAV-281, Arcor A800",
arv452_init);

View File

@ -0,0 +1,96 @@
#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
#define SYSTEM_DANUBE "Danube"
#define SYSTEM_DANUBE_CHIPID1 0x00129083
#define SYSTEM_DANUBE_CHIPID2 0x0012B083
#define SYSTEM_TWINPASS "Twinpass"
#define SYSTEM_TWINPASS_CHIPID 0x0012D083
static unsigned int chiprev = 0;
unsigned char ifxmips_sys_type[IFXMIPS_SYS_TYPE_LEN];
unsigned int
ifxmips_get_cpu_ver(void)
{
return (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0xF0000000) >> 28;
}
EXPORT_SYMBOL(ifxmips_get_cpu_ver);
const char*
get_system_type(void)
{
return ifxmips_sys_type;
}
static void
ifxmips_machine_restart(char *command)
{
printk(KERN_NOTICE "System restart\n");
local_irq_disable();
ifxmips_w32(ifxmips_r32(IFXMIPS_RCU_RST) | IFXMIPS_RCU_RST_ALL,
IFXMIPS_RCU_RST);
for(;;);
}
static void
ifxmips_machine_halt(void)
{
printk(KERN_NOTICE "System halted.\n");
local_irq_disable();
for(;;);
}
static void
ifxmips_machine_power_off(void)
{
printk(KERN_NOTICE "Please turn off the power now.\n");
local_irq_disable();
for(;;);
}
void __init
ifxmips_soc_setup(void)
{
char *name = SYSTEM_DANUBE;
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
_machine_restart = ifxmips_machine_restart;
_machine_halt = ifxmips_machine_halt;
pm_power_off = ifxmips_machine_power_off;
chiprev = (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0x0FFFFFFF);
switch (chiprev)
{
case SYSTEM_DANUBE_CHIPID1:
case SYSTEM_DANUBE_CHIPID2:
name = SYSTEM_DANUBE;
break;
case SYSTEM_TWINPASS_CHIPID:
name = SYSTEM_TWINPASS;
break;
default:
printk(KERN_ERR "This is not a danube chiprev : 0x%08X\n", chiprev);
BUG();
break;
}
snprintf(ifxmips_sys_type, IFXMIPS_SYS_TYPE_LEN - 1, "%s rev1.%d %dMhz",
name, ifxmips_get_cpu_ver(),
ifxmips_get_cpu_hz() / 1000000);
ifxmips_sys_type[IFXMIPS_SYS_TYPE_LEN - 1] = '\0';
}

View File

@ -0,0 +1,520 @@
/*
* 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.
*
* Copyright (C) 2005 infineon
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_H__
#define _IFXMIPS_H__
#define ifxmips_r32(reg) __raw_readl(reg)
#define ifxmips_w32(val, reg) __raw_writel(val, reg)
#define ifxmips_w32_mask(clear, set, reg) ifxmips_w32((ifxmips_r32(reg) & ~clear) | set, reg)
/*------------ GENERAL */
#define BOARD_SYSTEM_TYPE "IFXMIPS"
#define IFXMIPS_SYS_TYPE_LEN 0x100
#define IOPORT_RESOURCE_START 0x10000000
#define IOPORT_RESOURCE_END 0xffffffff
#define IOMEM_RESOURCE_START 0x10000000
#define IOMEM_RESOURCE_END 0xffffffff
#define IFXMIPS_FLASH_START 0x10000000
#define IFXMIPS_FLASH_MAX 0x02000000
/*------------ ASC0/1 */
#define IFXMIPS_ASC_BASE_ADDR (KSEG1 + 0x1E100400)
#define IFXMIPS_ASC_BASE_DIFF (0x1E100C00 - 0x1E100400)
#define IFXMIPS_ASC_FSTAT 0x0048
#define IFXMIPS_ASC_TBUF 0x0020
#define IFXMIPS_ASC_WHBSTATE 0x0018
#define IFXMIPS_ASC_RBUF 0x0024
#define IFXMIPS_ASC_STATE 0x0014
#define IFXMIPS_ASC_IRNCR 0x00F8
#define IFXMIPS_ASC_CLC 0x0000
#define IFXMIPS_ASC_PISEL 0x0004
#define IFXMIPS_ASC_TXFCON 0x0044
#define IFXMIPS_ASC_RXFCON 0x0040
#define IFXMIPS_ASC_CON 0x0010
#define IFXMIPS_ASC_BG 0x0050
#define IFXMIPS_ASC_IRNREN 0x00F4
#define IFXMIPS_ASC_CLC_DISS 0x2
#define ASC_IRNREN_RX_BUF 0x8
#define ASC_IRNREN_TX_BUF 0x4
#define ASC_IRNREN_ERR 0x2
#define ASC_IRNREN_TX 0x1
#define ASC_IRNCR_TIR 0x4
#define ASC_IRNCR_RIR 0x2
#define ASC_IRNCR_EIR 0x4
#define ASCOPT_CSIZE 0x3
#define ASCOPT_CS7 0x1
#define ASCOPT_CS8 0x2
#define ASCOPT_PARENB 0x4
#define ASCOPT_STOPB 0x8
#define ASCOPT_PARODD 0x0
#define ASCOPT_CREAD 0x20
#define TXFIFO_FL 1
#define RXFIFO_FL 1
#define TXFIFO_FULL 16
#define ASCCLC_RMCMASK 0x0000FF00
#define ASCCLC_RMCOFFSET 8
#define ASCCON_M_8ASYNC 0x0
#define ASCCON_M_7ASYNC 0x2
#define ASCCON_ODD 0x00000020
#define ASCCON_STP 0x00000080
#define ASCCON_BRS 0x00000100
#define ASCCON_FDE 0x00000200
#define ASCCON_R 0x00008000
#define ASCCON_FEN 0x00020000
#define ASCCON_ROEN 0x00080000
#define ASCCON_TOEN 0x00100000
#define ASCSTATE_PE 0x00010000
#define ASCSTATE_FE 0x00020000
#define ASCSTATE_ROE 0x00080000
#define ASCSTATE_ANY (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
#define ASCWHBSTATE_CLRREN 0x00000001
#define ASCWHBSTATE_SETREN 0x00000002
#define ASCWHBSTATE_CLRPE 0x00000004
#define ASCWHBSTATE_CLRFE 0x00000008
#define ASCWHBSTATE_CLRROE 0x00000020
#define ASCTXFCON_TXFEN 0x0001
#define ASCTXFCON_TXFFLU 0x0002
#define ASCTXFCON_TXFITLMASK 0x3F00
#define ASCTXFCON_TXFITLOFF 8
#define ASCRXFCON_RXFEN 0x0001
#define ASCRXFCON_RXFFLU 0x0002
#define ASCRXFCON_RXFITLMASK 0x3F00
#define ASCRXFCON_RXFITLOFF 8
#define ASCFSTAT_RXFFLMASK 0x003F
#define ASCFSTAT_TXFFLMASK 0x3F00
#define ASCFSTAT_TXFFLOFF 8
/*------------ RCU */
#define IFXMIPS_RCU_BASE_ADDR 0xBF203000
/* reset request */
#define IFXMIPS_RCU_RST ((u32 *)(IFXMIPS_RCU_BASE_ADDR + 0x0010))
#define IFXMIPS_RCU_RST_CPU1 (1 << 3)
#define IFXMIPS_RCU_RST_ALL 0x40000000
#define IFXMIPS_RCU_RST_REQ_DFE (1 << 7)
#define IFXMIPS_RCU_RST_REQ_AFE (1 << 11)
#define IFXMIPS_RCU_RST_REQ_ARC_JTAG (1 << 20)
/*------------ GPTU */
#define IFXMIPS_GPTU_BASE_ADDR 0xB8000300
/* clock control register */
#define IFXMIPS_GPTU_GPT_CLC ((u32 *)(IFXMIPS_GPTU_BASE_ADDR + 0x0000))
/* captur reload register */
#define IFXMIPS_GPTU_GPT_CAPREL ((u32 *)(IFXMIPS_GPTU_BASE_ADDR + 0x0030))
/* timer 6 control register */
#define IFXMIPS_GPTU_GPT_T6CON ((u32 *)(IFXMIPS_GPTU_BASE_ADDR + 0x0020))
/*------------ EBU */
#define IFXMIPS_EBU_BASE_ADDR 0xBE105300
/* bus configuration register */
#define IFXMIPS_EBU_BUSCON0 ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x0060))
#define IFXMIPS_EBU_PCC_CON ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x0090))
#define IFXMIPS_EBU_PCC_IEN ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x00A4))
#define IFXMIPS_EBU_PCC_ISTAT ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x00A0))
#define IFXMIPS_EBU_BUSCON1 ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x0064))
#define IFXMIPS_EBU_ADDRSEL1 ((u32 *)(IFXMIPS_EBU_BASE_ADDR + 0x0024))
/*------------ CGU */
#define IFXMIPS_CGU_BASE_ADDR (KSEG1 + 0x1F103000)
#define IFXMIPS_CGU_PLL0_CFG ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0004))
#define IFXMIPS_CGU_PLL1_CFG ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0008))
#define IFXMIPS_CGU_PLL2_CFG ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x000C))
#define IFXMIPS_CGU_SYS ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0010))
#define IFXMIPS_CGU_UPDATE ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0014))
#define IFXMIPS_CGU_IF_CLK ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0018))
#define IFXMIPS_CGU_OSC_CON ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x001C))
#define IFXMIPS_CGU_SMD ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0020))
#define IFXMIPS_CGU_CT1SR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0028))
#define IFXMIPS_CGU_CT2SR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x002C))
#define IFXMIPS_CGU_PCMCR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0030))
#define IFXMIPS_CGU_PCI_CR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0034))
#define IFXMIPS_CGU_PD_PC ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0038))
#define IFXMIPS_CGU_FMR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x003C))
/* clock mux */
#define IFXMIPS_CGU_SYS ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0010))
#define IFXMIPS_CGU_IFCCR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0018))
#define IFXMIPS_CGU_PCICR ((u32 *)(IFXMIPS_CGU_BASE_ADDR + 0x0034))
#define CLOCK_60M 60000000
#define CLOCK_83M 83333333
#define CLOCK_111M 111111111
#define CLOCK_133M 133333333
#define CLOCK_167M 166666667
#define CLOCK_333M 333333333
/*------------ CGU */
#define IFXMIPS_PMU_BASE_ADDR (KSEG1 + 0x1F102000)
#define IFXMIPS_PMU_PWDCR ((u32 *)(IFXMIPS_PMU_BASE_ADDR + 0x001C))
#define IFXMIPS_PMU_PWDSR ((u32 *)(IFXMIPS_PMU_BASE_ADDR + 0x0020))
/*------------ ICU */
#define IFXMIPS_ICU_BASE_ADDR 0xBF880200
#define IFXMIPS_ICU_IM0_ISR ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0000))
#define IFXMIPS_ICU_IM0_IER ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0008))
#define IFXMIPS_ICU_IM0_IOSR ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0010))
#define IFXMIPS_ICU_IM0_IRSR ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0018))
#define IFXMIPS_ICU_IM0_IMR ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0020))
#define IFXMIPS_ICU_IM1_ISR ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0028))
#define IFXMIPS_ICU_IM2_IER ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0058))
#define IFXMIPS_ICU_IM3_IER ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x0080))
#define IFXMIPS_ICU_IM4_IER ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x00A8))
#define IFXMIPS_ICU_IM5_IER ((u32 *)(IFXMIPS_ICU_BASE_ADDR + 0x00D0))
#define IFXMIPS_ICU_OFFSET (IFXMIPS_ICU_IM1_ISR - IFXMIPS_ICU_IM0_ISR)
/*------------ ETOP */
#define IFXMIPS_PPE32_BASE_ADDR 0xBE180000
#define IFXMIPS_PPE32_SIZE 0x40000
#define ETHERNET_PACKET_DMA_BUFFER_SIZE 0x600
#define IFXMIPS_PPE32_MEM_MAP ((u32 *)(IFXMIPS_PPE32_BASE_ADDR + 0x10000))
#define IFXMIPS_PPE32_SRST ((u32 *)(IFXMIPS_PPE32_BASE_ADDR + 0x10080))
#define MII_MODE 1
#define REV_MII_MODE 2
/* mdio access */
#define IFXMIPS_PPE32_MDIO_CFG ((u32 *)(IFXMIPS_PPE32_BASE_ADDR + 0x11800))
#define IFXMIPS_PPE32_MDIO_ACC ((u32 *)(IFXMIPS_PPE32_BASE_ADDR + 0x11804))
#define MDIO_ACC_REQUEST 0x80000000
#define MDIO_ACC_READ 0x40000000
#define MDIO_ACC_ADDR_MASK 0x1f
#define MDIO_ACC_ADDR_OFFSET 0x15
#define MDIO_ACC_REG_MASK 0x1f
#define MDIO_ACC_REG_OFFSET 0x10
#define MDIO_ACC_VAL_MASK 0xffff
/* configuration */
#define IFXMIPS_PPE32_CFG ((u32 *)(IFXMIPS_PPE32_MEM_MAP + 0x1808))
#define PPE32_MII_MASK 0xfffffffc
#define PPE32_MII_NORMAL 0x8
#define PPE32_MII_REVERSE 0xe
/* packet length */
#define IFXMIPS_PPE32_IG_PLEN_CTRL ((u32 *)(IFXMIPS_PPE32_MEM_MAP + 0x1820))
#define PPE32_PLEN_OVER 0x5ee
#define PPE32_PLEN_UNDER 0x400000
/* enet */
#define IFXMIPS_PPE32_ENET_MAC_CFG ((u32 *)(IFXMIPS_PPE32_MEM_MAP + 0x1840))
#define PPE32_CGEN 0x800
/*------------ DMA */
#define IFXMIPS_DMA_BASE_ADDR 0xBE104100
#define IFXMIPS_DMA_CS ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x18))
#define IFXMIPS_DMA_CIE ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x2C))
#define IFXMIPS_DMA_IRNEN ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0xf4))
#define IFXMIPS_DMA_CCTRL ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x1C))
#define IFXMIPS_DMA_CIS ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x28))
#define IFXMIPS_DMA_CDLEN ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x24))
#define IFXMIPS_DMA_PS ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x40))
#define IFXMIPS_DMA_PCTRL ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x44))
#define IFXMIPS_DMA_CTRL ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x10))
#define IFXMIPS_DMA_CPOLL ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x14))
#define IFXMIPS_DMA_CDBA ((u32 *)(IFXMIPS_DMA_BASE_ADDR + 0x20))
/*------------ PCI */
#define PCI_CR_PR_BASE_ADDR (KSEG1 + 0x1E105400)
#define PCI_CR_FCI_ADDR_MAP0 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00C0))
#define PCI_CR_FCI_ADDR_MAP1 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00C4))
#define PCI_CR_FCI_ADDR_MAP2 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00C8))
#define PCI_CR_FCI_ADDR_MAP3 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00CC))
#define PCI_CR_FCI_ADDR_MAP4 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00D0))
#define PCI_CR_FCI_ADDR_MAP5 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00D4))
#define PCI_CR_FCI_ADDR_MAP6 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00D8))
#define PCI_CR_FCI_ADDR_MAP7 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00DC))
#define PCI_CR_CLK_CTRL ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0000))
#define PCI_CR_PCI_MOD ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0030))
#define PCI_CR_PC_ARB ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0080))
#define PCI_CR_FCI_ADDR_MAP11hg ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00E4))
#define PCI_CR_BAR11MASK ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0044))
#define PCI_CR_BAR12MASK ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0048))
#define PCI_CR_BAR13MASK ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x004C))
#define PCI_CS_BASE_ADDR1 ((u32 *)(PCI_CS_PR_BASE_ADDR + 0x0010))
#define PCI_CR_PCI_ADDR_MAP11 ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x0064))
#define PCI_CR_FCI_BURST_LENGTH ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x00E8))
#define PCI_CR_PCI_EOI ((u32 *)(PCI_CR_PR_BASE_ADDR + 0x002C))
#define PCI_CS_PR_BASE_ADDR (KSEG1 + 0x17000000)
#define PCI_CS_STS_CMD ((u32 *)(PCI_CS_PR_BASE_ADDR + 0x0004))
#define PCI_MASTER0_REQ_MASK_2BITS 8
#define PCI_MASTER1_REQ_MASK_2BITS 10
#define PCI_MASTER2_REQ_MASK_2BITS 12
#define INTERNAL_ARB_ENABLE_BIT 0
/*------------ WDT */
#define IFXMIPS_WDT_BASE_ADDR (KSEG1 + 0x1F880000)
#define IFXMIPS_WDT_SIZE 0x400
#define IFXMIPS_BIU_WDT_CR ((u32 *)(IFXMIPS_WDT_BASE_ADDR + 0x03F0))
#define IFXMIPS_BIU_WDT_SR ((u32 *)(IFXMIPS_WDT_BASE_ADDR + 0x03F8))
/*------------ LED */
#define IFXMIPS_LED_BASE_ADDR (KSEG1 + 0x1E100BB0)
#define IFXMIPS_LED_CON0 ((u32 *)(IFXMIPS_LED_BASE_ADDR + 0x0000))
#define IFXMIPS_LED_CON1 ((u32 *)(IFXMIPS_LED_BASE_ADDR + 0x0004))
#define IFXMIPS_LED_CPU0 ((u32 *)(IFXMIPS_LED_BASE_ADDR + 0x0008))
#define IFXMIPS_LED_CPU1 ((u32 *)(IFXMIPS_LED_BASE_ADDR + 0x000C))
#define IFXMIPS_LED_AR ((u32 *)(IFXMIPS_LED_BASE_ADDR + 0x0010))
#define LED_CON0_SWU (1 << 31)
#define LED_CON0_AD1 (1 << 25)
#define LED_CON0_AD0 (1 << 24)
#define IFXMIPS_LED_2HZ (0)
#define IFXMIPS_LED_4HZ (1 << 23)
#define IFXMIPS_LED_8HZ (2 << 23)
#define IFXMIPS_LED_10HZ (3 << 23)
#define IFXMIPS_LED_MASK (0xf << 23)
#define IFXMIPS_LED_UPD_SRC_FPI (1 << 31)
#define IFXMIPS_LED_UPD_MASK (3 << 30)
#define IFXMIPS_LED_ADSL_SRC (3 << 24)
#define IFXMIPS_LED_GROUP0 (1 << 0)
#define IFXMIPS_LED_GROUP1 (1 << 1)
#define IFXMIPS_LED_GROUP2 (1 << 2)
#define IFXMIPS_LED_RISING 0
#define IFXMIPS_LED_FALLING (1 << 26)
#define IFXMIPS_LED_EDGE_MASK (1 << 26)
/*------------ GPIO */
#define IFXMIPS_GPIO_BASE_ADDR (0xBE100B00)
#define IFXMIPS_GPIO_P0_OUT ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0010))
#define IFXMIPS_GPIO_P1_OUT ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0040))
#define IFXMIPS_GPIO_P0_IN ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0014))
#define IFXMIPS_GPIO_P1_IN ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0044))
#define IFXMIPS_GPIO_P0_DIR ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0018))
#define IFXMIPS_GPIO_P1_DIR ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0048))
#define IFXMIPS_GPIO_P0_ALTSEL0 ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x001C))
#define IFXMIPS_GPIO_P1_ALTSEL0 ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x004C))
#define IFXMIPS_GPIO_P0_ALTSEL1 ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0020))
#define IFXMIPS_GPIO_P1_ALTSEL1 ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0050))
#define IFXMIPS_GPIO_P0_OD ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0024))
#define IFXMIPS_GPIO_P1_OD ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0054))
#define IFXMIPS_GPIO_P0_STOFF ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0028))
#define IFXMIPS_GPIO_P1_STOFF ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0058))
#define IFXMIPS_GPIO_P0_PUDSEL ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x002C))
#define IFXMIPS_GPIO_P1_PUDSEL ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x005C))
#define IFXMIPS_GPIO_P0_PUDEN ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0030))
#define IFXMIPS_GPIO_P1_PUDEN ((u32 *)(IFXMIPS_GPIO_BASE_ADDR + 0x0060))
/*------------ SSC */
#define IFXMIPS_SSC_BASE_ADDR (KSEG1 + 0x1e100800)
#define IFXMIPS_SSC_CLC ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0000))
#define IFXMIPS_SSC_IRN ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x00F4))
#define IFXMIPS_SSC_SFCON ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0060))
#define IFXMIPS_SSC_WHBGPOSTAT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0078))
#define IFXMIPS_SSC_STATE ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0014))
#define IFXMIPS_SSC_WHBSTATE ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0018))
#define IFXMIPS_SSC_FSTAT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0038))
#define IFXMIPS_SSC_ID ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0008))
#define IFXMIPS_SSC_TB ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0020))
#define IFXMIPS_SSC_RXFCON ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0030))
#define IFXMIPS_SSC_TXFCON ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0034))
#define IFXMIPS_SSC_CON ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0010))
#define IFXMIPS_SSC_GPOSTAT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0074))
#define IFXMIPS_SSC_RB ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0024))
#define IFXMIPS_SSC_RXCNT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0084))
#define IFXMIPS_SSC_GPOCON ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0070))
#define IFXMIPS_SSC_BR ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0040))
#define IFXMIPS_SSC_RXREQ ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0080))
#define IFXMIPS_SSC_SFSTAT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0064))
#define IFXMIPS_SSC_RXCNT ((u32 *)(IFXMIPS_SSC_BASE_ADDR + 0x0084))
/*------------ MEI */
#define IFXMIPS_MEI_BASE_ADDR (KSEG1 + 0x1E116000)
#define MEI_DATA_XFR ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0000))
#define MEI_VERSION ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0004))
#define MEI_ARC_GP_STAT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0008))
#define MEI_DATA_XFR_STAT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x000C))
#define MEI_XFR_ADDR ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0010))
#define MEI_MAX_WAIT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0014))
#define MEI_TO_ARC_INT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0018))
#define ARC_TO_MEI_INT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x001C))
#define ARC_TO_MEI_INT_MASK ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0020))
#define MEI_DEBUG_WAD ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0024))
#define MEI_DEBUG_RAD ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0028))
#define MEI_DEBUG_DATA ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x002C))
#define MEI_DEBUG_DEC ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0030))
#define MEI_CONFIG ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0034))
#define MEI_RST_CONTROL ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0038))
#define MEI_DBG_MASTER ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x003C))
#define MEI_CLK_CONTROL ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0040))
#define MEI_BIST_CONTROL ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0044))
#define MEI_BIST_STAT ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0048))
#define MEI_XDATA_BASE_SH ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x004c))
#define MEI_XDATA_BASE ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0050))
#define MEI_XMEM_BAR_BASE ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0054))
#define MEI_XMEM_BAR0 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0054))
#define MEI_XMEM_BAR1 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0058))
#define MEI_XMEM_BAR2 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x005C))
#define MEI_XMEM_BAR3 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0060))
#define MEI_XMEM_BAR4 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0064))
#define MEI_XMEM_BAR5 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0068))
#define MEI_XMEM_BAR6 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x006C))
#define MEI_XMEM_BAR7 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0070))
#define MEI_XMEM_BAR8 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0074))
#define MEI_XMEM_BAR9 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0078))
#define MEI_XMEM_BAR10 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x007C))
#define MEI_XMEM_BAR11 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0080))
#define MEI_XMEM_BAR12 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0084))
#define MEI_XMEM_BAR13 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0088))
#define MEI_XMEM_BAR14 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x008C))
#define MEI_XMEM_BAR15 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0090))
#define MEI_XMEM_BAR16 ((u32 *)(IFXMIPS_MEI_BASE_ADDR + 0x0094))
/*------------ DEU */
#define IFXMIPS_DEU_BASE (KSEG1 + 0x1E103100)
#define IFXMIPS_DEU_CLK ((u32 *)(IFXMIPS_DEU_BASE + 0x0000))
#define IFXMIPS_DEU_ID ((u32 *)(IFXMIPS_DEU_BASE + 0x0008))
#define IFXMIPS_DES_CON ((u32 *)(IFXMIPS_DEU_BASE + 0x0010))
#define IFXMIPS_DES_IHR ((u32 *)(IFXMIPS_DEU_BASE + 0x0014))
#define IFXMIPS_DES_ILR ((u32 *)(IFXMIPS_DEU_BASE + 0x0018))
#define IFXMIPS_DES_K1HR ((u32 *)(IFXMIPS_DEU_BASE + 0x001C))
#define IFXMIPS_DES_K1LR ((u32 *)(IFXMIPS_DEU_BASE + 0x0020))
#define IFXMIPS_DES_K3HR ((u32 *)(IFXMIPS_DEU_BASE + 0x0024))
#define IFXMIPS_DES_K3LR ((u32 *)(IFXMIPS_DEU_BASE + 0x0028))
#define IFXMIPS_DES_IVHR ((u32 *)(IFXMIPS_DEU_BASE + 0x002C))
#define IFXMIPS_DES_IVLR ((u32 *)(IFXMIPS_DEU_BASE + 0x0030))
#define IFXMIPS_DES_OHR ((u32 *)(IFXMIPS_DEU_BASE + 0x0040))
#define IFXMIPS_DES_OLR ((u32 *)(IFXMIPS_DEU_BASE + 0x0050))
#define IFXMIPS_AES_CON ((u32 *)(IFXMIPS_DEU_BASE + 0x0050))
#define IFXMIPS_AES_ID3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0054))
#define IFXMIPS_AES_ID2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0058))
#define IFXMIPS_AES_ID1R ((u32 *)(IFXMIPS_DEU_BASE + 0x005C))
#define IFXMIPS_AES_ID0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0060))
#define IFXMIPS_AES_K7R ((u32 *)(IFXMIPS_DEU_BASE + 0x0064))
#define IFXMIPS_AES_K6R ((u32 *)(IFXMIPS_DEU_BASE + 0x0068))
#define IFXMIPS_AES_K5R ((u32 *)(IFXMIPS_DEU_BASE + 0x006C))
#define IFXMIPS_AES_K4R ((u32 *)(IFXMIPS_DEU_BASE + 0x0070))
#define IFXMIPS_AES_K3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0074))
#define IFXMIPS_AES_K2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0078))
#define IFXMIPS_AES_K1R ((u32 *)(IFXMIPS_DEU_BASE + 0x007C))
#define IFXMIPS_AES_K0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0080))
#define IFXMIPS_AES_IV3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0084))
#define IFXMIPS_AES_IV2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0088))
#define IFXMIPS_AES_IV1R ((u32 *)(IFXMIPS_DEU_BASE + 0x008C))
#define IFXMIPS_AES_IV0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0090))
#define IFXMIPS_AES_0D3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0094))
#define IFXMIPS_AES_0D2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0098))
#define IFXMIPS_AES_OD1R ((u32 *)(IFXMIPS_DEU_BASE + 0x009C))
#define IFXMIPS_AES_OD0R ((u32 *)(IFXMIPS_DEU_BASE + 0x00A0))
/*------------ FUSE */
#define IFXMIPS_FUSE_BASE_ADDR (KSEG1 + 0x1F107354)
/*------------ MPS */
#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
#define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000))
#define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344))
#define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000))
#define IFXMIPS_MPS_VC1ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0004))
#define IFXMIPS_MPS_VC2ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0008))
#define IFXMIPS_MPS_VC3ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x000C))
#define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010))
#define IFXMIPS_MPS_RVC1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0014))
#define IFXMIPS_MPS_RVC2SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0018))
#define IFXMIPS_MPS_RVC3SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x001C))
#define IFXMIPS_MPS_SVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0020))
#define IFXMIPS_MPS_SVC1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0024))
#define IFXMIPS_MPS_SVC2SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0028))
#define IFXMIPS_MPS_SVC3SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x002C))
#define IFXMIPS_MPS_CVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0030))
#define IFXMIPS_MPS_CVC1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0034))
#define IFXMIPS_MPS_CVC2SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0038))
#define IFXMIPS_MPS_CVC3SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x003C))
#define IFXMIPS_MPS_RAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0040))
#define IFXMIPS_MPS_RAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0044))
#define IFXMIPS_MPS_SAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0048))
#define IFXMIPS_MPS_SAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x004C))
#define IFXMIPS_MPS_CAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0050))
#define IFXMIPS_MPS_CAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0054))
#define IFXMIPS_MPS_AD0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0058))
#define IFXMIPS_MPS_AD1ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x005C))
#define IFXMIPS_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
#define IFXMIPS_MPS_CHIPID_VERSION_SET(value) ((((1 << 4) - 1) & (value)) << 28)
#define IFXMIPS_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1))
#define IFXMIPS_MPS_CHIPID_PARTNUM_SET(value) ((((1 << 16) - 1) & (value)) << 12)
#define IFXMIPS_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1))
#define IFXMIPS_MPS_CHIPID_MANID_SET(value) ((((1 << 10) - 1) & (value)) << 1)
#endif

View File

@ -0,0 +1,64 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_CGU_H__
#define _IFXMIPS_CGU_H__
#define BASIC_INPUT_CLOCK_FREQUENCY_1 35328000
#define BASIC_INPUT_CLOCK_FREQUENCY_2 36000000
#define BASIS_INPUT_CRYSTAL_USB 12000000
#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
#define CGU_PLL0_PHASE_DIVIDER_ENABLE (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 31))
#define CGU_PLL0_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 30))
#define CGU_PLL0_CFG_DSMSEL (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 28))
#define CGU_PLL0_CFG_FRAC_EN (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 27))
#define CGU_PLL1_SRC (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 31))
#define CGU_PLL1_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 30))
#define CGU_PLL1_CFG_DSMSEL (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 28))
#define CGU_PLL1_CFG_FRAC_EN (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 27))
#define CGU_PLL2_PHASE_DIVIDER_ENABLE (ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & (1 << 20))
#define CGU_PLL2_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & (1 << 19))
#define CGU_SYS_FPI_SEL (1 << 6)
#define CGU_SYS_DDR_SEL 0x3
#define CGU_PLL0_SRC (1 << 29)
#define CGU_PLL0_CFG_PLLK GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 26, 17)
#define CGU_PLL0_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 12, 6)
#define CGU_PLL0_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 5, 2)
#define CGU_PLL1_CFG_PLLK GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 26, 17)
#define CGU_PLL1_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 12, 6)
#define CGU_PLL1_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 5, 2)
#define CGU_PLL2_SRC GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 18, 17)
#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 16, 13)
#define CGU_PLL2_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 12, 6)
#define CGU_PLL2_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 5, 2)
#define CGU_IF_CLK_PCI_CLK GET_BITS(*IFXMIPS_CGU_IF_CLK, 23, 20)
unsigned int cgu_get_mips_clock(int cpu);
unsigned int cgu_get_io_region_clock(void);
unsigned int cgu_get_fpi_bus_clock(int fpi);
void cgu_setup_pci_clk(int internal_clock);
unsigned int ifxmips_get_ddr_hz(void);
unsigned int ifxmips_get_fpi_hz(void);
unsigned int ifxmips_get_cpu_hz(void);
#endif

View File

@ -0,0 +1,195 @@
/*
* 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.
*
* Copyright (C) 2005 infineon
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*
*/
#ifndef _IFXMIPS_DMA_H__
#define _IFXMIPS_DMA_H__
#define RCV_INT 1
#define TX_BUF_FULL_INT 2
#define TRANSMIT_CPT_INT 4
#define IFXMIPS_DMA_CH_ON 1
#define IFXMIPS_DMA_CH_OFF 0
#define IFXMIPS_DMA_CH_DEFAULT_WEIGHT 100
enum attr_t{
TX = 0,
RX = 1,
RESERVED = 2,
DEFAULT = 3,
};
#define DMA_OWN 1
#define CPU_OWN 0
#define DMA_MAJOR 250
#define DMA_DESC_OWN_CPU 0x0
#define DMA_DESC_OWN_DMA 0x80000000
#define DMA_DESC_CPT_SET 0x40000000
#define DMA_DESC_SOP_SET 0x20000000
#define DMA_DESC_EOP_SET 0x10000000
#define MISCFG_MASK 0x40
#define RDERR_MASK 0x20
#define CHOFF_MASK 0x10
#define DESCPT_MASK 0x8
#define DUR_MASK 0x4
#define EOP_MASK 0x2
#define DMA_DROP_MASK (1<<31)
#define IFXMIPS_DMA_RX -1
#define IFXMIPS_DMA_TX 1
struct dma_chan_map {
const char *dev_name;
enum attr_t dir;
int pri;
int irq;
int rel_chan_no;
};
#ifdef CONFIG_CPU_LITTLE_ENDIAN
struct rx_desc {
u32 data_length:16;
volatile u32 reserved:7;
volatile u32 byte_offset:2;
volatile u32 Burst_length_offset:3;
volatile u32 EoP:1;
volatile u32 Res:1;
volatile u32 C:1;
volatile u32 OWN:1;
volatile u32 Data_Pointer; /* fixme: should be 28 bits here */
};
struct tx_desc {
volatile u32 data_length:16;
volatile u32 reserved1:7;
volatile u32 byte_offset:5;
volatile u32 EoP:1;
volatile u32 SoP:1;
volatile u32 C:1;
volatile u32 OWN:1;
volatile u32 Data_Pointer; /* fixme: should be 28 bits here */
};
#else /* BIG */
struct rx_desc {
union {
struct {
volatile u32 OWN:1;
volatile u32 C:1;
volatile u32 SoP:1;
volatile u32 EoP:1;
volatile u32 Burst_length_offset:3;
volatile u32 byte_offset:2;
volatile u32 reserve:7;
volatile u32 data_length:16;
} field;
volatile u32 word;
} status;
volatile u32 Data_Pointer;
};
struct tx_desc {
union {
struct {
volatile u32 OWN:1;
volatile u32 C:1;
volatile u32 SoP:1;
volatile u32 EoP:1;
volatile u32 byte_offset:5;
volatile u32 reserved:7;
volatile u32 data_length:16;
} field;
volatile u32 word;
} status;
volatile u32 Data_Pointer;
};
#endif /* ENDIAN */
struct dma_channel_info {
/* relative channel number */
int rel_chan_no;
/* class for this channel for QoS */
int pri;
/* specify byte_offset */
int byte_offset;
/* direction */
int dir;
/* irq number */
int irq;
/* descriptor parameter */
int desc_base;
int desc_len;
int curr_desc;
int prev_desc; /* only used if it is a tx channel*/
/* weight setting for WFQ algorithm*/
int weight;
int default_weight;
int packet_size;
int burst_len;
/* on or off of this channel */
int control;
/* optional information for the upper layer devices */
#if defined(CONFIG_IFXMIPS_ETHERNET_D2) || defined(CONFIG_IFXMIPS_PPA)
void *opt[64];
#else
void *opt[25];
#endif
/* Pointer to the peripheral device who is using this channel */
void *dma_dev;
/* channel operations */
void (*open)(struct dma_channel_info *pCh);
void (*close)(struct dma_channel_info *pCh);
void (*reset)(struct dma_channel_info *pCh);
void (*enable_irq)(struct dma_channel_info *pCh);
void (*disable_irq)(struct dma_channel_info *pCh);
};
struct dma_device_info {
/* device name of this peripheral */
char device_name[15];
int reserved;
int tx_burst_len;
int rx_burst_len;
int default_weight;
int current_tx_chan;
int current_rx_chan;
int num_tx_chan;
int num_rx_chan;
int max_rx_chan_num;
int max_tx_chan_num;
struct dma_channel_info *tx_chan[20];
struct dma_channel_info *rx_chan[20];
/*functions, optional*/
u8 *(*buffer_alloc)(int len, int *offset, void **opt);
void (*buffer_free)(u8 *dataptr, void *opt);
int (*intr_handler)(struct dma_device_info *info, int status);
void *priv; /* used by peripheral driver only */
};
struct dma_device_info *dma_device_reserve(char *dev_name);
void dma_device_release(struct dma_device_info *dev);
void dma_device_register(struct dma_device_info *info);
void dma_device_unregister(struct dma_device_info *info);
int dma_device_read(struct dma_device_info *info, u8 **dataptr, void **opt);
int dma_device_write(struct dma_device_info *info, u8 *dataptr, int len,
void *opt);
#endif

View File

@ -0,0 +1,23 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_EBU_H__
#define _IFXMIPS_EBU_H__
extern spinlock_t ebu_lock;
#endif

View File

@ -0,0 +1,40 @@
/*
* 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.
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_GPIO_H__
#define _IFXMIPS_GPIO_H__
extern int ifxmips_port_reserve_pin(unsigned int port, unsigned int pin);
extern int ifxmips_port_free_pin(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_open_drain(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_open_drain(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_pudsel(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_pudsel(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_puden(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_puden(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_stoff(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_stoff(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_dir_out(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_dir_in(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_output(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_output(unsigned int port, unsigned int pin);
extern int ifxmips_port_get_input(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_altsel0(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_altsel0(unsigned int port, unsigned int pin);
extern int ifxmips_port_set_altsel1(unsigned int port, unsigned int pin);
extern int ifxmips_port_clear_altsel1(unsigned int port, unsigned int pin);
#endif

View File

@ -0,0 +1,155 @@
#ifndef __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
#define __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
/******************************************************************************
Copyright (c) 2002, Infineon Technologies. All rights reserved.
No Warranty
Because the program is licensed free of charge, there is no warranty for
the program, to the extent permitted by applicable law. Except when
otherwise stated in writing the copyright holders and/or other parties
provide the program "as is" without warranty of any kind, either
expressed or implied, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose. The
entire risk as to the quality and performance of the program is with
you. should the program prove defective, you assume the cost of all
necessary servicing, repair or correction.
In no event unless required by applicable law or agreed to in writing
will any copyright holder, or any other party who may modify and/or
redistribute the program as permitted above, be liable to you for
damages, including any general, special, incidental or consequential
damages arising out of the use or inability to use the program
(including but not limited to loss of data or data being rendered
inaccurate or losses sustained by you or third parties or a failure of
the program to operate with any other programs), even if such holder or
other party has been advised of the possibility of such damages.
******************************************************************************/
/*
* ####################################
* Definition
* ####################################
*/
/*
* Available Timer/Counter Index
*/
#define TIMER(n, X) (n * 2 + (X ? 1 : 0))
#define TIMER_ANY 0x00
#define TIMER1A TIMER(1, 0)
#define TIMER1B TIMER(1, 1)
#define TIMER2A TIMER(2, 0)
#define TIMER2B TIMER(2, 1)
#define TIMER3A TIMER(3, 0)
#define TIMER3B TIMER(3, 1)
/*
* Flag of Timer/Counter
* These flags specify the way in which timer is configured.
*/
/* Bit size of timer/counter. */
#define TIMER_FLAG_16BIT 0x0000
#define TIMER_FLAG_32BIT 0x0001
/* Switch between timer and counter. */
#define TIMER_FLAG_TIMER 0x0000
#define TIMER_FLAG_COUNTER 0x0002
/* Stop or continue when overflowing/underflowing. */
#define TIMER_FLAG_ONCE 0x0000
#define TIMER_FLAG_CYCLIC 0x0004
/* Count up or counter down. */
#define TIMER_FLAG_UP 0x0000
#define TIMER_FLAG_DOWN 0x0008
/* Count on specific level or edge. */
#define TIMER_FLAG_HIGH_LEVEL_SENSITIVE 0x0000
#define TIMER_FLAG_LOW_LEVEL_SENSITIVE 0x0040
#define TIMER_FLAG_RISE_EDGE 0x0010
#define TIMER_FLAG_FALL_EDGE 0x0020
#define TIMER_FLAG_ANY_EDGE 0x0030
/* Signal is syncronous to module clock or not. */
#define TIMER_FLAG_UNSYNC 0x0000
#define TIMER_FLAG_SYNC 0x0080
/* Different interrupt handle type. */
#define TIMER_FLAG_NO_HANDLE 0x0000
#if defined(__KERNEL__)
#define TIMER_FLAG_CALLBACK_IN_IRQ 0x0100
#endif // defined(__KERNEL__)
#define TIMER_FLAG_SIGNAL 0x0300
/* Internal clock source or external clock source */
#define TIMER_FLAG_INT_SRC 0x0000
#define TIMER_FLAG_EXT_SRC 0x1000
/*
* ioctl Command
*/
#define GPTU_REQUEST_TIMER 0x01 /* General method to setup timer/counter. */
#define GPTU_FREE_TIMER 0x02 /* Free timer/counter. */
#define GPTU_START_TIMER 0x03 /* Start or resume timer/counter. */
#define GPTU_STOP_TIMER 0x04 /* Suspend timer/counter. */
#define GPTU_GET_COUNT_VALUE 0x05 /* Get current count value. */
#define GPTU_CALCULATE_DIVIDER 0x06 /* Calculate timer divider from given freq.*/
#define GPTU_SET_TIMER 0x07 /* Simplified method to setup timer. */
#define GPTU_SET_COUNTER 0x08 /* Simplified method to setup counter. */
/*
* Data Type Used to Call ioctl
*/
struct gptu_ioctl_param {
unsigned int timer; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
* GPTU_SET_COUNTER, this field is ID of expected *
* timer/counter. If it's zero, a timer/counter would *
* be dynamically allocated and ID would be stored in *
* this field. *
* In command GPTU_GET_COUNT_VALUE, this field is *
* ignored. *
* In other command, this field is ID of timer/counter *
* allocated. */
unsigned int flag; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
* GPTU_SET_COUNTER, this field contains flags to *
* specify how to configure timer/counter. *
* In command GPTU_START_TIMER, zero indicate start *
* and non-zero indicate resume timer/counter. *
* In other command, this field is ignored. */
unsigned long value; /* In command GPTU_REQUEST_TIMER, this field contains *
* init/reload value. *
* In command GPTU_SET_TIMER, this field contains *
* frequency (0.001Hz) of timer. *
* In command GPTU_GET_COUNT_VALUE, current count *
* value would be stored in this field. *
* In command GPTU_CALCULATE_DIVIDER, this field *
* contains frequency wanted, and after calculation, *
* divider would be stored in this field to overwrite *
* the frequency. *
* In other command, this field is ignored. */
int pid; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
* if signal is required, this field contains process *
* ID to which signal would be sent. *
* In other command, this field is ignored. */
int sig; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
* if signal is required, this field contains signal *
* number which would be sent. *
* In other command, this field is ignored. */
};
/*
* ####################################
* Data Type
* ####################################
*/
typedef void (*timer_callback)(unsigned long arg);
extern int ifxmips_request_timer(unsigned int, unsigned int, unsigned long, unsigned long, unsigned long);
extern int ifxmips_free_timer(unsigned int);
extern int ifxmips_start_timer(unsigned int, int);
extern int ifxmips_stop_timer(unsigned int);
extern int ifxmips_reset_counter_flags(u32 timer, u32 flags);
extern int ifxmips_get_count_value(unsigned int, unsigned long *);
extern u32 ifxmips_cal_divider(unsigned long);
extern int ifxmips_set_timer(unsigned int, unsigned int, int, int, unsigned int, unsigned long, unsigned long);
extern int ifxmips_set_counter(unsigned int timer, unsigned int flag,
u32 reload, unsigned long arg1, unsigned long arg2);
#endif /* __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ */

View File

@ -0,0 +1,78 @@
/*
* 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.
*
* Copyright (C) 2005 infineon
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_IRQ__
#define _IFXMIPS_IRQ__
#define INT_NUM_IRQ0 8
#define INT_NUM_IM0_IRL0 (INT_NUM_IRQ0 + 0)
#define INT_NUM_IM1_IRL0 (INT_NUM_IRQ0 + 32)
#define INT_NUM_IM2_IRL0 (INT_NUM_IRQ0 + 64)
#define INT_NUM_IM3_IRL0 (INT_NUM_IRQ0 + 96)
#define INT_NUM_IM4_IRL0 (INT_NUM_IRQ0 + 128)
#define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
#define IFXMIPSASC_TIR(x) (INT_NUM_IM3_IRL0 + (x * 7))
#define IFXMIPSASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 7) + 2)
#define IFXMIPSASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 7) + 3)
#define IFXMIPS_SSC_TIR (INT_NUM_IM0_IRL0 + 15)
#define IFXMIPS_SSC_RIR (INT_NUM_IM0_IRL0 + 14)
#define IFXMIPS_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define IFXMIPS_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
#define IFXMIPS_MEI_INT (INT_NUM_IM1_IRL0 + 23)
#define IFXMIPS_TIMER6_INT (INT_NUM_IM1_IRL0 + 23)
#define IFXMIPS_USB_INT (INT_NUM_IM1_IRL0 + 22)
#define IFXMIPS_USB_OC_INT (INT_NUM_IM4_IRL0 + 23)
#define MIPS_CPU_TIMER_IRQ 7
#define IFXMIPS_DMA_CH0_INT (INT_NUM_IM2_IRL0)
#define IFXMIPS_DMA_CH1_INT (INT_NUM_IM2_IRL0 + 1)
#define IFXMIPS_DMA_CH2_INT (INT_NUM_IM2_IRL0 + 2)
#define IFXMIPS_DMA_CH3_INT (INT_NUM_IM2_IRL0 + 3)
#define IFXMIPS_DMA_CH4_INT (INT_NUM_IM2_IRL0 + 4)
#define IFXMIPS_DMA_CH5_INT (INT_NUM_IM2_IRL0 + 5)
#define IFXMIPS_DMA_CH6_INT (INT_NUM_IM2_IRL0 + 6)
#define IFXMIPS_DMA_CH7_INT (INT_NUM_IM2_IRL0 + 7)
#define IFXMIPS_DMA_CH8_INT (INT_NUM_IM2_IRL0 + 8)
#define IFXMIPS_DMA_CH9_INT (INT_NUM_IM2_IRL0 + 9)
#define IFXMIPS_DMA_CH10_INT (INT_NUM_IM2_IRL0 + 10)
#define IFXMIPS_DMA_CH11_INT (INT_NUM_IM2_IRL0 + 11)
#define IFXMIPS_DMA_CH12_INT (INT_NUM_IM2_IRL0 + 25)
#define IFXMIPS_DMA_CH13_INT (INT_NUM_IM2_IRL0 + 26)
#define IFXMIPS_DMA_CH14_INT (INT_NUM_IM2_IRL0 + 27)
#define IFXMIPS_DMA_CH15_INT (INT_NUM_IM2_IRL0 + 28)
#define IFXMIPS_DMA_CH16_INT (INT_NUM_IM2_IRL0 + 29)
#define IFXMIPS_DMA_CH17_INT (INT_NUM_IM2_IRL0 + 30)
#define IFXMIPS_DMA_CH18_INT (INT_NUM_IM2_IRL0 + 16)
#define IFXMIPS_DMA_CH19_INT (INT_NUM_IM2_IRL0 + 21)
#define IFXMIPS_PPE_MBOX_INT (INT_NUM_IM2_IRL0 + 24)
#define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14)
#define INT_NUM_IM4_IRL18 (INT_NUM_IM4_IRL0 + 18)
#define INT_NUM_IM4_IRL19 (INT_NUM_IM4_IRL0 + 19)
#define IFXMIPS_USB_OC_INT (INT_NUM_IM4_IRL0 + 23)
extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr);
#endif

View File

@ -0,0 +1,26 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_LED_H__
#define _IFXMIPS_LED_H__
extern void ifxmips_led_set(unsigned int led);
extern void ifxmips_led_clear(unsigned int led);
extern void ifxmips_led_blink_set(unsigned int led);
extern void ifxmips_led_blink_clear(unsigned int led);
#endif

View File

@ -0,0 +1,32 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXMIPS_PMU_H__
#define _IFXMIPS_PMU_H__
#define IFXMIPS_PMU_PWDCR_DMA 0x0020
#define IFXMIPS_PMU_PWDCR_USB 0x8041
#define IFXMIPS_PMU_PWDCR_LED 0x0800
#define IFXMIPS_PMU_PWDCR_GPT 0x1000
#define IFXMIPS_PMU_PWDCR_PPE 0x2000
#define IFXMIPS_PMU_PWDCR_FPI 0x4000
void ifxmips_pmu_enable(unsigned int module);
void ifxmips_pmu_disable(unsigned int module);
#endif

View File

@ -0,0 +1,26 @@
/*
* 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.
*
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#ifndef _IFXPROM_H__
#define _IFXPROM_H__
extern void early_printf(const char *fmt, ...);
extern u32 *prom_get_cp1_base(void);
extern u32 prom_get_cp1_size(void);
extern int ifxmips_has_brn_block(void);
#endif

View File

@ -0,0 +1,28 @@
/*
* include/asm-mips/mach-ifxmips/irq.h
*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*
*/
#ifndef __IFXMIPS_IRQ_H
#define __IFXMIPS_IRQ_H
#define NR_IRQS 256
#include_next <irq.h>
#endif

View File

@ -0,0 +1,11 @@
#include <asm/mips_machine.h>
enum ramips_mach_type {
IFXMIPS_MACH_GENERIC,
/* Danube based machines */
IFXMIPS_MACH_EASY50712, /* danube evalkit */
IFXMIPS_MACH_ARV4519, /* Airties WAV-221 */
IFXMIPS_MACH_ARV452, /* Airties WAV-281, Arcor EasyboxA800 */
};

View File

@ -0,0 +1,24 @@
/*
* 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 __ASM_MIPS_MACH_IFXMIPS_WAR_H
#define __ASM_MIPS_MACH_IFXMIPS_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

View File

@ -0,0 +1,120 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <asm/addrspace.h>
#include <linux/vmalloc.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_ebu.h>
#define IFXMIPS_PCI_CFG_BUSNUM_SHF 16
#define IFXMIPS_PCI_CFG_DEVNUM_SHF 11
#define IFXMIPS_PCI_CFG_FUNNUM_SHF 8
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
extern u32 ifxmips_pci_mapped_cfg;
static int
ifxmips_pci_config_access(unsigned char access_type,
struct pci_bus *bus, unsigned int devfn, unsigned int where, u32 *data)
{
unsigned long cfg_base;
unsigned long flags;
u32 temp;
/* IFXMips support slot from 0 to 15 */
/* dev_fn 0&0x68 (AD29) is ifxmips itself */
if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
|| ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
return 1;
spin_lock_irqsave(&ebu_lock, flags);
cfg_base = ifxmips_pci_mapped_cfg;
cfg_base |= (bus->number << IFXMIPS_PCI_CFG_BUSNUM_SHF) | (devfn <<
IFXMIPS_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
/* Perform access */
if (access_type == PCI_ACCESS_WRITE)
{
#ifdef CONFIG_SWAP_IO_SPACE
ifxmips_w32(swab32(*data), ((u32*)cfg_base));
#else
ifxmips_w32(*data, ((u32*)cfg_base));
#endif
} else {
*data = ifxmips_r32(((u32*)(cfg_base)));
#ifdef CONFIG_SWAP_IO_SPACE
*data = swab32(*data);
#endif
}
wmb();
/* clean possible Master abort */
cfg_base = (ifxmips_pci_mapped_cfg | (0x0 << IFXMIPS_PCI_CFG_FUNNUM_SHF)) + 4;
temp = ifxmips_r32(((u32*)(cfg_base)));
#ifdef CONFIG_SWAP_IO_SPACE
temp = swab32 (temp);
#endif
cfg_base = (ifxmips_pci_mapped_cfg | (0x68 << IFXMIPS_PCI_CFG_FUNNUM_SHF)) + 4;
ifxmips_w32(temp, ((u32*)cfg_base));
spin_unlock_irqrestore(&ebu_lock, flags);
if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
return 1;
return 0;
}
int
ifxmips_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 * val)
{
u32 data = 0;
if (ifxmips_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 1)
*val = (data >> ((where & 3) << 3)) & 0xff;
else if (size == 2)
*val = (data >> ((where & 3) << 3)) & 0xffff;
else
*val = data;
return PCIBIOS_SUCCESSFUL;
}
int
ifxmips_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
u32 data = 0;
if (size == 4)
{
data = val;
} else {
if (ifxmips_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 1)
data = (data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
else if (size == 2)
data = (data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
}
if (ifxmips_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
}

View File

@ -0,0 +1,209 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <asm/addrspace.h>
#include <linux/vmalloc.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#include <ifxmips_cgu.h>
#define IFXMIPS_PCI_MEM_BASE 0x18000000
#define IFXMIPS_PCI_MEM_SIZE 0x02000000
#define IFXMIPS_PCI_IO_BASE 0x1AE00000
#define IFXMIPS_PCI_IO_SIZE 0x00200000
extern int ifxmips_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
extern int ifxmips_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
struct pci_ops ifxmips_pci_ops =
{
.read = ifxmips_pci_read_config_dword,
.write = ifxmips_pci_write_config_dword
};
static struct resource pci_io_resource =
{
.name = "io pci IO space",
.start = IFXMIPS_PCI_IO_BASE,
.end = IFXMIPS_PCI_IO_BASE + IFXMIPS_PCI_IO_SIZE - 1,
.flags = IORESOURCE_IO
};
static struct resource pci_mem_resource =
{
.name = "ext pci memory space",
.start = IFXMIPS_PCI_MEM_BASE,
.end = IFXMIPS_PCI_MEM_BASE + IFXMIPS_PCI_MEM_SIZE - 1,
.flags = IORESOURCE_MEM
};
static struct pci_controller ifxmips_pci_controller =
{
.pci_ops = &ifxmips_pci_ops,
.mem_resource = &pci_mem_resource,
.mem_offset = 0x00000000UL,
.io_resource = &pci_io_resource,
.io_offset = 0x00000000UL,
};
/* the cpu can can generate the 33Mhz or rely on an external clock the cgu needs the
proper setting, otherwise the cpu hangs. we have no way of runtime detecting this */
u32 ifxmips_pci_mapped_cfg;
int ifxmips_pci_external_clock = 0;
/* Since the PCI REQ pins can be reused for other functionality, make it possible
to exclude those from interpretation by the PCI controller */
int ifxmips_pci_req_mask = 0xf;
static int __init
ifxmips_pci_set_external_clk(char *str)
{
printk("cgu: setting up external pci clock\n");
ifxmips_pci_external_clock = 1;
return 1;
}
__setup("pci_external_clk", ifxmips_pci_set_external_clk);
int
pcibios_plat_dev_init(struct pci_dev *dev)
{
u8 pin;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
switch(pin)
{
case 0:
break;
case 1:
//falling edge level triggered:0x4, low level:0xc, rising edge:0x2
ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_CON) | 0xc, IFXMIPS_EBU_PCC_CON);
ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_IEN) | 0x10, IFXMIPS_EBU_PCC_IEN);
break;
case 2:
case 3:
case 4:
printk ("WARNING: interrupt pin %d not supported yet!\n", pin);
default:
printk ("WARNING: invalid interrupt pin %d\n", pin);
return 1;
}
return 0;
}
static u32 calc_bar11mask(void)
{
u32 mem, bar11mask;
/* BAR11MASK value depends on available memory on system. */
mem = num_physpages * PAGE_SIZE;
bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) -1)) -1)) | 8;
return bar11mask;
}
static void __init
ifxmips_pci_startup(void)
{
u32 temp_buffer;
cgu_setup_pci_clk(ifxmips_pci_external_clock);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OD) | (1 << 5), IFXMIPS_GPIO_P1_OD);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | (1 << 5), IFXMIPS_GPIO_P1_DIR);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL1);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL0);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) & ~0x2000, IFXMIPS_GPIO_P1_DIR);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | 0x4000, IFXMIPS_GPIO_P1_DIR);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~0x6000, IFXMIPS_GPIO_P1_ALTSEL1);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) | 0x6000, IFXMIPS_GPIO_P1_ALTSEL0);
/* enable auto-switching between PCI and EBU */
ifxmips_w32(0xa, PCI_CR_CLK_CTRL);
/* busy, i.e. configuration is not done, PCI access has to be retried */
ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD);
wmb ();
/* BUS Master/IO/MEM access */
ifxmips_w32(ifxmips_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD);
/* enable external 2 PCI masters */
temp_buffer = ifxmips_r32(PCI_CR_PC_ARB);
temp_buffer &= (~(ifxmips_pci_req_mask << 16));
/* enable internal arbiter */
temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
/* enable internal PCI master reqest */
temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS));
/* enable EBU reqest */
temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS));
/* enable all external masters request */
temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS));
ifxmips_w32(temp_buffer, PCI_CR_PC_ARB);
wmb ();
ifxmips_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0);
ifxmips_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1);
ifxmips_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2);
ifxmips_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3);
ifxmips_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4);
ifxmips_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5);
ifxmips_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6);
ifxmips_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7);
ifxmips_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg);
ifxmips_w32(calc_bar11mask(), PCI_CR_BAR11MASK);
ifxmips_w32(0, PCI_CR_PCI_ADDR_MAP11);
ifxmips_w32(0, PCI_CS_BASE_ADDR1);
#ifdef CONFIG_SWAP_IO_SPACE
/* both TX and RX endian swap are enabled */
ifxmips_w32(ifxmips_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI);
wmb ();
#endif
/*TODO: disable BAR2 & BAR3 - why was this in the origianl infineon code */
ifxmips_w32(ifxmips_r32(PCI_CR_BAR12MASK) | 0x80000000, PCI_CR_BAR12MASK);
ifxmips_w32(ifxmips_r32(PCI_CR_BAR13MASK) | 0x80000000, PCI_CR_BAR13MASK);
/*use 8 dw burst length */
ifxmips_w32(0x303, PCI_CR_FCI_BURST_LENGTH);
ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD);
wmb();
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) & ~(1 << 5), IFXMIPS_GPIO_P1_OUT);
wmb();
mdelay(1);
ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT);
}
int __init
pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin){
switch(slot)
{
case 13:
/* IDSEL = AD29 --> USB Host Controller */
return (INT_NUM_IM1_IRL0 + 17);
case 14:
/* IDSEL = AD30 --> mini PCI connector */
return (INT_NUM_IM0_IRL0 + 22);
default:
printk("Warning: no IRQ found for PCI device in slot %d, pin %d\n", slot, pin);
return 0;
}
}
int __init
pcibios_init(void)
{
extern int pci_probe_only;
pci_probe_only = 0;
printk("PCI: Probing PCI hardware on host bus 0.\n");
ifxmips_pci_startup ();
ifxmips_pci_mapped_cfg = (u32)ioremap_nocache(0x17000000, 0x800 * 16);
printk("IFXMips PCI mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_mapped_cfg);
ifxmips_pci_controller.io_map_base = (unsigned long)ioremap(IFXMIPS_PCI_IO_BASE, IFXMIPS_PCI_IO_SIZE - 1);
printk("IFXMips PCI I/O mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_controller.io_map_base);
register_pci_controller(&ifxmips_pci_controller);
return 0;
}
arch_initcall(pcibios_init);

View File

@ -0,0 +1,196 @@
/*
* 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.
*
* Copyright (C) 2006 infineon
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/unistd.h>
#include <linux/errno.h>
#include <linux/leds.h>
#include <linux/delay.h>
#include <ifxmips.h>
#include <ifxmips_gpio.h>
#include <ifxmips_pmu.h>
#define DRVNAME "ifxmips_led"
/* might need to be changed depending on shift register used on the pcb */
#if 1
#define IFXMIPS_LED_CLK_EDGE IFXMIPS_LED_FALLING
#else
#define IFXMIPS_LED_CLK_EDGE IFXMIPS_LED_RISING
#endif
#define IFXMIPS_LED_SPEED IFXMIPS_LED_8HZ
#define IFXMIPS_LED_GPIO_PORT 0
#define IFXMIPS_MAX_LED 24
struct ifxmips_led {
struct led_classdev cdev;
u8 bit;
};
void ifxmips_led_set(unsigned int led)
{
led &= 0xffffff;
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CPU0) | led, IFXMIPS_LED_CPU0);
}
EXPORT_SYMBOL(ifxmips_led_set);
void ifxmips_led_clear(unsigned int led)
{
led = ~(led & 0xffffff);
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CPU0) & led, IFXMIPS_LED_CPU0);
}
EXPORT_SYMBOL(ifxmips_led_clear);
void ifxmips_led_blink_set(unsigned int led)
{
led &= 0xffffff;
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | led, IFXMIPS_LED_CON0);
}
EXPORT_SYMBOL(ifxmips_led_blink_set);
void ifxmips_led_blink_clear(unsigned int led)
{
led = ~(led & 0xffffff);
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) & led, IFXMIPS_LED_CON0);
}
EXPORT_SYMBOL(ifxmips_led_blink_clear);
static void ifxmips_ledapi_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct ifxmips_led *led_dev =
container_of(led_cdev, struct ifxmips_led, cdev);
if (value)
ifxmips_led_set(1 << led_dev->bit);
else
ifxmips_led_clear(1 << led_dev->bit);
}
void ifxmips_led_setup_gpio(void)
{
int i = 0;
/* leds are controlled via a shift register
we need to setup pins SH,D,ST (4,5,6) to make it work */
for (i = 4; i < 7; i++) {
ifxmips_port_set_altsel0(IFXMIPS_LED_GPIO_PORT, i);
ifxmips_port_clear_altsel1(IFXMIPS_LED_GPIO_PORT, i);
ifxmips_port_set_dir_out(IFXMIPS_LED_GPIO_PORT, i);
ifxmips_port_set_open_drain(IFXMIPS_LED_GPIO_PORT, i);
}
}
static int ifxmips_led_probe(struct platform_device *dev)
{
int i = 0;
ifxmips_led_setup_gpio();
ifxmips_w32(0, IFXMIPS_LED_AR);
ifxmips_w32(0, IFXMIPS_LED_CPU0);
ifxmips_w32(0, IFXMIPS_LED_CPU1);
ifxmips_w32(LED_CON0_SWU, IFXMIPS_LED_CON0);
ifxmips_w32(0, IFXMIPS_LED_CON1);
/* setup the clock edge that the shift register is triggered on */
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) & ~IFXMIPS_LED_EDGE_MASK,
IFXMIPS_LED_CON0);
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | IFXMIPS_LED_CLK_EDGE,
IFXMIPS_LED_CON0);
/* per default leds 15-0 are set */
ifxmips_w32(IFXMIPS_LED_GROUP1 | IFXMIPS_LED_GROUP0, IFXMIPS_LED_CON1);
/* leds are update periodically by the FPID */
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) & ~IFXMIPS_LED_UPD_MASK,
IFXMIPS_LED_CON1);
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) | IFXMIPS_LED_UPD_SRC_FPI,
IFXMIPS_LED_CON1);
/* set led update speed */
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) & ~IFXMIPS_LED_MASK,
IFXMIPS_LED_CON1);
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) | IFXMIPS_LED_SPEED,
IFXMIPS_LED_CON1);
/* adsl 0 and 1 leds are updated by the arc */
ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | IFXMIPS_LED_ADSL_SRC,
IFXMIPS_LED_CON0);
/* per default, the leds are turned on */
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_LED);
for (i = 0; i < IFXMIPS_MAX_LED; i++) {
struct ifxmips_led *tmp =
kzalloc(sizeof(struct ifxmips_led), GFP_KERNEL);
tmp->cdev.brightness_set = ifxmips_ledapi_set;
tmp->cdev.name = kmalloc(sizeof("ifxmips:led:00"), GFP_KERNEL);
sprintf((char *)tmp->cdev.name, "ifxmips:led:%02d", i);
tmp->cdev.default_trigger = NULL;
tmp->bit = i;
led_classdev_register(&dev->dev, &tmp->cdev);
}
return 0;
}
static int ifxmips_led_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver ifxmips_led_driver = {
.probe = ifxmips_led_probe,
.remove = ifxmips_led_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
int __init ifxmips_led_init(void)
{
int ret = platform_driver_register(&ifxmips_led_driver);
if (ret)
printk(KERN_INFO
"ifxmips_led: Error registering platfom driver!");
return ret;
}
void __exit ifxmips_led_exit(void)
{
platform_driver_unregister(&ifxmips_led_driver);
}
module_init(ifxmips_led_init);
module_exit(ifxmips_led_exit);

View File

@ -0,0 +1,282 @@
/*
* 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
*
* Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/cfi.h>
#include <linux/magic.h>
#include <linux/platform_device.h>
#include <ifxmips.h>
#include <ifxmips_prom.h>
#include <ifxmips_ebu.h>
#ifndef CONFIG_MTD_PARTITIONS
#error Please enable CONFIG_MTD_PARTITIONS
#endif
static struct map_info ifxmips_map = {
.name = "ifx-nor",
.bankwidth = 2,
.size = 0x400000,
};
static map_word ifxmips_read16(struct map_info *map, unsigned long adr)
{
unsigned long flags;
map_word temp;
spin_lock_irqsave(&ebu_lock, flags);
adr ^= 2;
temp.x[0] = *((__u16 *)(map->virt + adr));
spin_unlock_irqrestore(&ebu_lock, flags);
return temp;
}
static void ifxmips_write16(struct map_info *map, map_word d, unsigned long adr)
{
unsigned long flags;
spin_lock_irqsave(&ebu_lock, flags);
adr ^= 2;
*((__u16 *)(map->virt + adr)) = d.x[0];
spin_unlock_irqrestore(&ebu_lock, flags);
}
void ifxmips_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
unsigned char *p;
unsigned char *to_8;
unsigned long flags;
spin_lock_irqsave(&ebu_lock, flags);
from = (unsigned long)(from + map->virt);
p = (unsigned char *) from;
to_8 = (unsigned char *) to;
while (len--)
*to_8++ = *p++;
spin_unlock_irqrestore(&ebu_lock, flags);
}
void ifxmips_copy_to(struct map_info *map,
unsigned long to,
const void *from,
ssize_t len)
{
unsigned char *p = (unsigned char *)from;
unsigned char *to_8;
unsigned long flags;
spin_lock_irqsave(&ebu_lock, flags);
to += (unsigned long) map->virt;
to_8 = (unsigned char *)to;
while (len--)
*p++ = *to_8++;
spin_unlock_irqrestore(&ebu_lock, flags);
}
static struct mtd_partition ifxmips_partitions[] = {
{
.name = "uboot",
.offset = 0x00000000,
.size = 0x00020000,
},
{
.name = "uboot_env",
.offset = 0x00020000,
.size = 0x0,
},
{
.name = "kernel",
.offset = 0x0,
.size = 0x0,
},
{
.name = "rootfs",
.offset = 0x0,
.size = 0x0,
},
{
.name = "board_config",
.offset = 0x0,
.size = 0x0,
},
};
static struct mtd_partition ifxmips_meta_partition = {
.name = "linux",
.offset = 0x00030000,
.size = 0x0,
};
static const char *part_probe_types[] = { "cmdlinepart", NULL };
int find_uImage_size(unsigned long start_offset)
{
unsigned long magic;
unsigned long temp;
ifxmips_copy_from(&ifxmips_map, &magic, start_offset, 4);
if (le32_to_cpu(magic) != 0x56190527) {
printk(KERN_INFO "ifxmips_mtd: invalid magic (0x%08X) of kernel at 0x%08lx \n", le32_to_cpu(magic), start_offset);
return 0;
}
ifxmips_copy_from(&ifxmips_map, &temp, start_offset + 12, 4);
printk(KERN_INFO "ifxmips_mtd: kernel size is %ld \n", temp + 0x40);
return temp + 0x40;
}
int find_brn_block(unsigned long start_offset)
{
unsigned char temp[9];
ifxmips_copy_from(&ifxmips_map, &temp, start_offset, 8);
temp[8] = '\0';
printk(KERN_INFO "data in brn block %s\n", temp);
if (memcmp(temp, "BRN-BOOT", 8) == 0)
return 1;
else
return 0;
}
int detect_squashfs_partition(unsigned long start_offset)
{
unsigned long temp;
ifxmips_copy_from(&ifxmips_map, &temp, start_offset, 4);
return le32_to_cpu(temp) == SQUASHFS_MAGIC;
}
static int ifxmips_mtd_probe(struct platform_device *dev)
{
struct mtd_info *ifxmips_mtd = NULL;
struct mtd_partition *parts = NULL;
unsigned long uimage_size;
int err, i;
int kernel_part = 2, rootfs_part = 3;
int num_parts = ARRAY_SIZE(ifxmips_partitions);
ifxmips_w32(0x1d7ff, IFXMIPS_EBU_BUSCON0);
ifxmips_map.read = ifxmips_read16;
ifxmips_map.write = ifxmips_write16;
ifxmips_map.copy_from = ifxmips_copy_from;
ifxmips_map.copy_to = ifxmips_copy_to;
ifxmips_map.phys = dev->resource->start;
ifxmips_map.size = dev->resource->end - ifxmips_map.phys + 1;
ifxmips_map.virt = ioremap_nocache(ifxmips_map.phys, ifxmips_map.size);
if (!ifxmips_map.virt) {
printk(KERN_WARNING "ifxmips_mtd: failed to ioremap!\n");
return -EIO;
}
ifxmips_mtd = (struct mtd_info *) do_map_probe("cfi_probe", &ifxmips_map);
if (!ifxmips_mtd) {
iounmap(ifxmips_map.virt);
printk(KERN_WARNING "ifxmips_mtd: probing failed\n");
return -ENXIO;
}
ifxmips_mtd->owner = THIS_MODULE;
err = parse_mtd_partitions(ifxmips_mtd, part_probe_types, &parts, 0);
if (err > 0) {
printk(KERN_INFO "ifxmips_mtd: found %d partitions from cmdline\n", err);
num_parts = err;
kernel_part = 0;
rootfs_part = 0;
for (i = 0; i < num_parts; i++) {
if (strcmp(parts[i].name, "kernel") == 0)
kernel_part = i;
if (strcmp(parts[i].name, "rootfs") == 0)
rootfs_part = i;
}
} else {
/* if the flash is 64k sectors, the kernel will reside at 0xb0030000
if the flash is 128k sectors, the kernel will reside at 0xb0040000 */
ifxmips_partitions[1].size = ifxmips_mtd->erasesize;
ifxmips_partitions[2].offset = ifxmips_partitions[1].offset + ifxmips_mtd->erasesize;
parts = &ifxmips_partitions[0];
}
/* dynamic size detection only if rootfs-part follows kernel-part */
if (kernel_part+1 == rootfs_part) {
uimage_size = find_uImage_size(parts[kernel_part].offset);
if (detect_squashfs_partition(parts[kernel_part].offset + uimage_size)) {
printk(KERN_INFO "ifxmips_mtd: found a squashfs following the uImage\n");
} else {
uimage_size &= ~(ifxmips_mtd->erasesize -1);
uimage_size += ifxmips_mtd->erasesize;
}
parts[kernel_part].size = uimage_size;
parts[rootfs_part].offset = parts[kernel_part].offset + parts[kernel_part].size;
parts[rootfs_part].size = ((ifxmips_mtd->size >> 20) * 1024 * 1024) - parts[rootfs_part].offset;
ifxmips_meta_partition.offset = parts[kernel_part].offset;
ifxmips_meta_partition.size = parts[kernel_part].size + parts[rootfs_part].size;
}
if (err <= 0) {
if (ifxmips_has_brn_block()) {
parts[3].size -= ifxmips_mtd->erasesize;
parts[4].offset = ifxmips_mtd->size - ifxmips_mtd->erasesize;
parts[4].size = ifxmips_mtd->erasesize;
ifxmips_meta_partition.size -= ifxmips_mtd->erasesize;
} else {
num_parts--;
}
}
add_mtd_partitions(ifxmips_mtd, parts, num_parts);
add_mtd_partitions(ifxmips_mtd, &ifxmips_meta_partition, 1);
printk(KERN_INFO "ifxmips_mtd: added %s flash with %dMB\n",
ifxmips_map.name, ((int)ifxmips_mtd->size) >> 20);
return 0;
}
static struct platform_driver ifxmips_mtd_driver = {
.probe = ifxmips_mtd_probe,
.driver = {
.name = "ifxmips_mtd",
.owner = THIS_MODULE,
},
};
int __init init_ifxmips_mtd(void)
{
int ret = platform_driver_register(&ifxmips_mtd_driver);
if (ret)
printk(KERN_INFO "ifxmips_mtd: error registering platfom driver!");
return ret;
}
static void __exit cleanup_ifxmips_mtd(void)
{
platform_driver_unregister(&ifxmips_mtd_driver);
}
module_init(init_ifxmips_mtd);
module_exit(cleanup_ifxmips_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("MTD map driver for IFXMIPS boards");

View File

@ -0,0 +1,497 @@
/*
* 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.
*
* Copyright (C) 2005 Wu Qi Ming <Qi-Ming.Wu@infineon.com>
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/checksum.h>
#include <ifxmips.h>
#include <ifxmips_dma.h>
#include <ifxmips_pmu.h>
struct ifxmips_mii_priv {
struct net_device_stats stats;
struct dma_device_info *dma_device;
struct sk_buff *skb;
struct mii_bus *mii_bus;
struct phy_device *phydev;
int oldlink, oldspeed, oldduplex;
};
static struct net_device *ifxmips_mii0_dev;
static unsigned char mac_addr[MAX_ADDR_LEN];
static int ifxmips_mdiobus_write(struct mii_bus *bus, int phy_addr,
int phy_reg, u16 phy_data)
{
u32 val = MDIO_ACC_REQUEST |
((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET) |
phy_data;
while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
;
ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
return 0;
}
static int ifxmips_mdiobus_read(struct mii_bus *bus, int phy_addr, int phy_reg)
{
u32 val = MDIO_ACC_REQUEST | MDIO_ACC_READ |
((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET);
while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
;
ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
;
val = ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_VAL_MASK;
return val;
}
int ifxmips_ifxmips_mii_open(struct net_device *dev)
{
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
int i;
for (i = 0; i < dma_dev->max_rx_chan_num; i++) {
if ((dma_dev->rx_chan[i])->control == IFXMIPS_DMA_CH_ON)
(dma_dev->rx_chan[i])->open(dma_dev->rx_chan[i]);
}
netif_start_queue(dev);
return 0;
}
int ifxmips_mii_release(struct net_device *dev)
{
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
int i;
for (i = 0; i < dma_dev->max_rx_chan_num; i++)
dma_dev->rx_chan[i]->close(dma_dev->rx_chan[i]);
netif_stop_queue(dev);
return 0;
}
int ifxmips_mii_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
{
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
unsigned char *buf = NULL;
struct sk_buff *skb = NULL;
int len = 0;
len = dma_device_read(dma_dev, &buf, (void **)&skb);
if (len >= ETHERNET_PACKET_DMA_BUFFER_SIZE) {
printk(KERN_INFO "ifxmips_mii0: packet too large %d\n", len);
goto ifxmips_mii_hw_receive_err_exit;
}
/* remove CRC */
len -= 4;
if (skb == NULL) {
printk(KERN_INFO "ifxmips_mii0: cannot restore pointer\n");
goto ifxmips_mii_hw_receive_err_exit;
}
if (len > (skb->end - skb->tail)) {
printk(KERN_INFO "ifxmips_mii0: BUG, len:%d end:%p tail:%p\n",
(len+4), skb->end, skb->tail);
goto ifxmips_mii_hw_receive_err_exit;
}
skb_put(skb, len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
priv->stats.rx_packets++;
priv->stats.rx_bytes += len;
return 0;
ifxmips_mii_hw_receive_err_exit:
if (len == 0) {
if (skb)
dev_kfree_skb_any(skb);
priv->stats.rx_errors++;
priv->stats.rx_dropped++;
return -EIO;
} else {
return len;
}
}
int ifxmips_mii_hw_tx(char *buf, int len, struct net_device *dev)
{
int ret = 0;
struct ifxmips_mii_priv *priv = netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
ret = dma_device_write(dma_dev, buf, len, priv->skb);
return ret;
}
int ifxmips_mii_tx(struct sk_buff *skb, struct net_device *dev)
{
int len;
char *data;
struct ifxmips_mii_priv *priv = netdev_priv(dev);
struct dma_device_info *dma_dev = priv->dma_device;
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
data = skb->data;
priv->skb = skb;
dev->trans_start = jiffies;
/* TODO: we got more than 1 dma channel,
so we should do something intelligent here to select one */
dma_dev->current_tx_chan = 0;
wmb();
if (ifxmips_mii_hw_tx(data, len, dev) != len) {
dev_kfree_skb_any(skb);
priv->stats.tx_errors++;
priv->stats.tx_dropped++;
} else {
priv->stats.tx_packets++;
priv->stats.tx_bytes += len;
}
return 0;
}
void ifxmips_mii_tx_timeout(struct net_device *dev)
{
int i;
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
priv->stats.tx_errors++;
for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
priv->dma_device->tx_chan[i]->disable_irq(priv->dma_device->tx_chan[i]);
netif_wake_queue(dev);
return;
}
int dma_intr_handler(struct dma_device_info *dma_dev, int status)
{
int i;
switch (status) {
case RCV_INT:
ifxmips_mii_hw_receive(ifxmips_mii0_dev, dma_dev);
break;
case TX_BUF_FULL_INT:
printk(KERN_INFO "ifxmips_mii0: tx buffer full\n");
netif_stop_queue(ifxmips_mii0_dev);
for (i = 0; i < dma_dev->max_tx_chan_num; i++) {
if ((dma_dev->tx_chan[i])->control == IFXMIPS_DMA_CH_ON)
dma_dev->tx_chan[i]->enable_irq(dma_dev->tx_chan[i]);
}
break;
case TRANSMIT_CPT_INT:
for (i = 0; i < dma_dev->max_tx_chan_num; i++)
dma_dev->tx_chan[i]->disable_irq(dma_dev->tx_chan[i]);
netif_wake_queue(ifxmips_mii0_dev);
break;
}
return 0;
}
unsigned char *ifxmips_etop_dma_buffer_alloc(int len, int *byte_offset, void **opt)
{
unsigned char *buffer = NULL;
struct sk_buff *skb = NULL;
skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
if (skb == NULL)
return NULL;
buffer = (unsigned char *)(skb->data);
skb_reserve(skb, 2);
*(int *)opt = (int)skb;
*byte_offset = 2;
return buffer;
}
void ifxmips_etop_dma_buffer_free(unsigned char *dataptr, void *opt)
{
struct sk_buff *skb = NULL;
if (opt == NULL) {
kfree(dataptr);
} else {
skb = (struct sk_buff *)opt;
dev_kfree_skb_any(skb);
}
}
static struct net_device_stats *ifxmips_get_stats(struct net_device *dev)
{
return &((struct ifxmips_mii_priv *)netdev_priv(dev))->stats;
}
static void
ifxmips_adjust_link(struct net_device *dev)
{
struct ifxmips_mii_priv *priv = netdev_priv(dev);
struct phy_device *phydev = priv->phydev;
int new_state = 0;
/* Did anything change? */
if (priv->oldlink != phydev->link ||
priv->oldduplex != phydev->duplex ||
priv->oldspeed != phydev->speed) {
/* Yes, so update status and mark as changed */
new_state = 1;
priv->oldduplex = phydev->duplex;
priv->oldspeed = phydev->speed;
priv->oldlink = phydev->link;
}
/* If link status changed, show new status */
if (new_state)
phy_print_status(phydev);
}
static int mii_probe(struct net_device *dev)
{
struct ifxmips_mii_priv *priv = netdev_priv(dev);
struct phy_device *phydev = NULL;
int phy_addr;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
/* find the first (lowest address) PHY on the current MAC's MII bus */
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
if (priv->mii_bus->phy_map[phy_addr]) {
phydev = priv->mii_bus->phy_map[phy_addr];
break; /* break out with first one found */
}
}
if (!phydev) {
printk (KERN_ERR "%s: no PHY found\n", dev->name);
return -ENODEV;
}
/* now we are supposed to have a proper phydev, to attach to... */
BUG_ON(!phydev);
BUG_ON(phydev->attached_dev);
phydev = phy_connect(dev, dev_name(&phydev->dev), &ifxmips_adjust_link,
0, PHY_INTERFACE_MODE_MII);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
}
/* mask with MAC supported features */
phydev->supported &= (SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg
/* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
| SUPPORTED_MII
| SUPPORTED_TP);
phydev->advertising = phydev->supported;
priv->phydev = phydev;
printk(KERN_INFO "%s: attached PHY driver [%s] "
"(mii_bus:phy_addr=%s, irq=%d)\n",
dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
return 0;
}
static int ifxmips_mii_dev_init(struct net_device *dev)
{
int i;
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
ether_setup(dev);
dev->watchdog_timeo = 10 * HZ;
dev->mtu = 1500;
memset(priv, 0, sizeof(struct ifxmips_mii_priv));
priv->dma_device = dma_device_reserve("PPE");
if (!priv->dma_device) {
BUG();
return -ENODEV;
}
priv->dma_device->buffer_alloc = &ifxmips_etop_dma_buffer_alloc;
priv->dma_device->buffer_free = &ifxmips_etop_dma_buffer_free;
priv->dma_device->intr_handler = &dma_intr_handler;
priv->dma_device->max_rx_chan_num = 4;
for (i = 0; i < priv->dma_device->max_rx_chan_num; i++) {
priv->dma_device->rx_chan[i]->packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
priv->dma_device->rx_chan[i]->control = IFXMIPS_DMA_CH_ON;
}
for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
if (i == 0)
priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_ON;
else
priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_OFF;
dma_device_register(priv->dma_device);
printk(KERN_INFO "%s: using mac=", dev->name);
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = mac_addr[i];
printk("%02X%c", dev->dev_addr[i], (i == 5) ? ('\n') : (':'));
}
priv->mii_bus = mdiobus_alloc();
if (priv->mii_bus == NULL)
return -ENOMEM;
priv->mii_bus->priv = dev;
priv->mii_bus->read = ifxmips_mdiobus_read;
priv->mii_bus->write = ifxmips_mdiobus_write;
priv->mii_bus->name = "ifxmips_mii";
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
for(i = 0; i < PHY_MAX_ADDR; ++i)
priv->mii_bus->irq[i] = PHY_POLL;
mdiobus_register(priv->mii_bus);
return mii_probe(dev);
}
static void ifxmips_mii_chip_init(int mode)
{
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA);
ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_PPE);
if (mode == REV_MII_MODE)
ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_REVERSE, IFXMIPS_PPE32_CFG);
else if (mode == MII_MODE)
ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_NORMAL, IFXMIPS_PPE32_CFG);
ifxmips_w32(PPE32_PLEN_UNDER | PPE32_PLEN_OVER, IFXMIPS_PPE32_IG_PLEN_CTRL);
ifxmips_w32(PPE32_CGEN, IFXMIPS_PPE32_ENET_MAC_CFG);
wmb();
}
static const struct net_device_ops ifxmips_eth_netdev_ops = {
.ndo_init = ifxmips_mii_dev_init,
.ndo_open = ifxmips_ifxmips_mii_open,
.ndo_stop = ifxmips_mii_release,
.ndo_start_xmit = ifxmips_mii_tx,
.ndo_tx_timeout = ifxmips_mii_tx_timeout,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
static int
ifxmips_mii_probe(struct platform_device *dev)
{
int result = 0;
unsigned char *mac = (unsigned char *)dev->dev.platform_data;
ifxmips_mii0_dev = alloc_etherdev(sizeof(struct ifxmips_mii_priv));
ifxmips_mii0_dev->netdev_ops = &ifxmips_eth_netdev_ops;
memcpy(mac_addr, mac, 6);
strcpy(ifxmips_mii0_dev->name, "eth%d");
ifxmips_mii_chip_init(REV_MII_MODE);
result = register_netdev(ifxmips_mii0_dev);
if (result) {
printk(KERN_INFO "ifxmips_mii0: error %i registering device \"%s\"\n", result, ifxmips_mii0_dev->name);
goto out;
}
printk(KERN_INFO "ifxmips_mii0: driver loaded!\n");
out:
return result;
}
static int ifxmips_mii_remove(struct platform_device *dev)
{
struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(ifxmips_mii0_dev);
printk(KERN_INFO "ifxmips_mii0: ifxmips_mii0 cleanup\n");
dma_device_unregister(priv->dma_device);
dma_device_release(priv->dma_device);
kfree(priv->dma_device);
unregister_netdev(ifxmips_mii0_dev);
return 0;
}
static struct platform_driver ifxmips_mii_driver = {
.probe = ifxmips_mii_probe,
.remove = ifxmips_mii_remove,
.driver = {
.name = "ifxmips_mii0",
.owner = THIS_MODULE,
},
};
int __init ifxmips_mii_init(void)
{
int ret = platform_driver_register(&ifxmips_mii_driver);
if (ret)
printk(KERN_INFO "ifxmips_mii0: Error registering platfom driver!");
return ret;
}
static void __exit ifxmips_mii_cleanup(void)
{
platform_driver_unregister(&ifxmips_mii_driver);
}
module_init(ifxmips_mii_init);
module_exit(ifxmips_mii_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("ethernet driver for IFXMIPS boards");

View File

@ -0,0 +1,551 @@
/*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
*
* 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
*
* Copyright (C) 2004 Infineon IFAP DC COM CPE
* Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/circ_buf.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <ifxmips.h>
#include <ifxmips_irq.h>
#define PORT_IFXMIPSASC 111
#include <linux/serial_core.h>
#define UART_DUMMY_UER_RX 1
static void ifxmipsasc_tx_chars(struct uart_port *port);
extern void prom_printf(const char *fmt, ...);
static struct uart_port ifxmipsasc_port[2];
static struct uart_driver ifxmipsasc_reg;
extern unsigned int ifxmips_get_fpi_hz(void);
static void ifxmipsasc_stop_tx(struct uart_port *port)
{
return;
}
static void ifxmipsasc_start_tx(struct uart_port *port)
{
unsigned long flags;
local_irq_save(flags);
ifxmipsasc_tx_chars(port);
local_irq_restore(flags);
return;
}
static void ifxmipsasc_stop_rx(struct uart_port *port)
{
ifxmips_w32(ASCWHBSTATE_CLRREN, port->membase + IFXMIPS_ASC_WHBSTATE);
}
static void ifxmipsasc_enable_ms(struct uart_port *port)
{
}
#include <linux/version.h>
static void ifxmipsasc_rx_chars(struct uart_port *port)
{
struct tty_struct *tty = port->state->port.tty;
unsigned int ch = 0, rsr = 0, fifocnt;
fifocnt = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
while (fifocnt--) {
u8 flag = TTY_NORMAL;
ch = ifxmips_r32(port->membase + IFXMIPS_ASC_RBUF);
rsr = (ifxmips_r32(port->membase + IFXMIPS_ASC_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
tty_flip_buffer_push(tty);
port->icount.rx++;
/*
* Note that the error handling code is
* out of the main execution path
*/
if (rsr & ASCSTATE_ANY) {
if (rsr & ASCSTATE_PE) {
port->icount.parity++;
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE, port->membase + IFXMIPS_ASC_WHBSTATE);
} else if (rsr & ASCSTATE_FE) {
port->icount.frame++;
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRFE, port->membase + IFXMIPS_ASC_WHBSTATE);
}
if (rsr & ASCSTATE_ROE) {
port->icount.overrun++;
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE);
}
rsr &= port->read_status_mask;
if (rsr & ASCSTATE_PE)
flag = TTY_PARITY;
else if (rsr & ASCSTATE_FE)
flag = TTY_FRAME;
}
if ((rsr & port->ignore_status_mask) == 0)
tty_insert_flip_char(tty, ch, flag);
if (rsr & ASCSTATE_ROE)
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character
*/
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
if (ch != 0)
tty_flip_buffer_push(tty);
return;
}
static void ifxmipsasc_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
if (uart_tx_stopped(port)) {
ifxmipsasc_stop_tx(port);
return;
}
while (((ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK)
>> ASCFSTAT_TXFFLOFF) != TXFIFO_FULL) {
if (port->x_char) {
ifxmips_w32(port->x_char, port->membase + IFXMIPS_ASC_TBUF);
port->icount.tx++;
port->x_char = 0;
continue;
}
if (uart_circ_empty(xmit))
break;
ifxmips_w32(port->state->xmit.buf[port->state->xmit.tail], port->membase + IFXMIPS_ASC_TBUF);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
}
static irqreturn_t ifxmipsasc_tx_int(int irq, void *_port)
{
struct uart_port *port = (struct uart_port *)_port;
ifxmips_w32(ASC_IRNCR_TIR, port->membase + IFXMIPS_ASC_IRNCR);
ifxmipsasc_start_tx(port);
ifxmips_mask_and_ack_irq(irq);
return IRQ_HANDLED;
}
static irqreturn_t ifxmipsasc_er_int(int irq, void *_port)
{
struct uart_port *port = (struct uart_port *)_port;
/* clear any pending interrupts */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE |
ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE);
return IRQ_HANDLED;
}
static irqreturn_t ifxmipsasc_rx_int(int irq, void *_port)
{
struct uart_port *port = (struct uart_port *)_port;
ifxmips_w32(ASC_IRNCR_RIR, port->membase + IFXMIPS_ASC_IRNCR);
ifxmipsasc_rx_chars((struct uart_port *)port);
ifxmips_mask_and_ack_irq(irq);
return IRQ_HANDLED;
}
static unsigned int ifxmipsasc_tx_empty(struct uart_port *port)
{
int status;
status = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
return status ? 0 : TIOCSER_TEMT;
}
static unsigned int ifxmipsasc_get_mctrl(struct uart_port *port)
{
return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
}
static void ifxmipsasc_set_mctrl(struct uart_port *port, u_int mctrl)
{
}
static void ifxmipsasc_break_ctl(struct uart_port *port, int break_state)
{
}
static int ifxmipsasc_startup(struct uart_port *port)
{
int retval;
port->uartclk = ifxmips_get_fpi_hz();
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~IFXMIPS_ASC_CLC_DISS, port->membase + IFXMIPS_ASC_CLC);
ifxmips_w32(((ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~ASCCLC_RMCMASK)) | (1 << ASCCLC_RMCOFFSET), port->membase + IFXMIPS_ASC_CLC);
ifxmips_w32(0, port->membase + IFXMIPS_ASC_PISEL);
ifxmips_w32(((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON);
ifxmips_w32(((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON);
wmb();
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN, port->membase + IFXMIPS_ASC_CON);
retval = request_irq(port->irq, ifxmipsasc_tx_int, IRQF_DISABLED, "asc_tx", port);
if (retval) {
printk(KERN_ERR "failed to request ifxmipsasc_tx_int\n");
return retval;
}
retval = request_irq(port->irq + 2, ifxmipsasc_rx_int, IRQF_DISABLED, "asc_rx", port);
if (retval) {
printk(KERN_ERR "failed to request ifxmipsasc_rx_int\n");
goto err1;
}
retval = request_irq(port->irq + 3, ifxmipsasc_er_int, IRQF_DISABLED, "asc_er", port);
if (retval) {
printk(KERN_ERR "failed to request ifxmipsasc_er_int\n");
goto err2;
}
ifxmips_w32(ASC_IRNREN_RX_BUF | ASC_IRNREN_TX_BUF | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + IFXMIPS_ASC_IRNREN);
return 0;
err2:
free_irq(port->irq + 2, port);
err1:
free_irq(port->irq, port);
return retval;
}
static void ifxmipsasc_shutdown(struct uart_port *port)
{
free_irq(port->irq, port);
free_irq(port->irq + 2, port);
free_irq(port->irq + 3, port);
ifxmips_w32(0, port->membase + IFXMIPS_ASC_CON);
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON);
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) & ~ASCRXFCON_RXFEN, port->membase + IFXMIPS_ASC_RXFCON);
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON);
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) & ~ASCTXFCON_TXFEN, port->membase + IFXMIPS_ASC_TXFCON);
}
static void ifxmipsasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old)
{
unsigned int cflag;
unsigned int iflag;
unsigned int quot;
unsigned int baud;
unsigned int con = 0;
unsigned long flags;
cflag = new->c_cflag;
iflag = new->c_iflag;
switch (cflag & CSIZE) {
case CS7:
con = ASCCON_M_7ASYNC;
break;
case CS5:
case CS6:
default:
con = ASCCON_M_8ASYNC;
break;
}
if (cflag & CSTOPB)
con |= ASCCON_STP;
if (cflag & PARENB) {
if (!(cflag & PARODD))
con &= ~ASCCON_ODD;
else
con |= ASCCON_ODD;
}
port->read_status_mask = ASCSTATE_ROE;
if (iflag & INPCK)
port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
port->ignore_status_mask = 0;
if (iflag & IGNPAR)
port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
if (iflag & IGNBRK) {
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (iflag & IGNPAR)
port->ignore_status_mask |= ASCSTATE_ROE;
}
if ((cflag & CREAD) == 0)
port->ignore_status_mask |= UART_DUMMY_UER_RX;
/* set error signals - framing, parity and overrun, enable receiver */
con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
local_irq_save(flags);
/* set up CON */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | con, port->membase + IFXMIPS_ASC_CON);
/* Set baud rate - take a divider of 2 into account */
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
quot = quot / 2 - 1;
/* disable the baudrate generator */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_R, port->membase + IFXMIPS_ASC_CON);
/* make sure the fractional divider is off */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_FDE, port->membase + IFXMIPS_ASC_CON);
/* set up to use divisor of 2 */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_BRS, port->membase + IFXMIPS_ASC_CON);
/* now we can write the new baudrate into the register */
ifxmips_w32(quot, port->membase + IFXMIPS_ASC_BG);
/* turn the baudrate generator back on */
ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_R, port->membase + IFXMIPS_ASC_CON);
/* enable rx */
ifxmips_w32(ASCWHBSTATE_SETREN, port->membase + IFXMIPS_ASC_WHBSTATE);
local_irq_restore(flags);
}
static const char *ifxmipsasc_type(struct uart_port *port)
{
if (port->type == PORT_IFXMIPSASC) {
if (port->membase == (void *)IFXMIPS_ASC_BASE_ADDR)
return "asc0";
else
return "asc1";
} else {
return NULL;
}
}
static void ifxmipsasc_release_port(struct uart_port *port)
{
}
static int ifxmipsasc_request_port(struct uart_port *port)
{
return 0;
}
static void ifxmipsasc_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
port->type = PORT_IFXMIPSASC;
ifxmipsasc_request_port(port);
}
}
static int ifxmipsasc_verify_port(struct uart_port *port, struct serial_struct *ser)
{
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_IFXMIPSASC)
ret = -EINVAL;
if (ser->irq < 0 || ser->irq >= NR_IRQS)
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
return ret;
}
static struct uart_ops ifxmipsasc_pops = {
.tx_empty = ifxmipsasc_tx_empty,
.set_mctrl = ifxmipsasc_set_mctrl,
.get_mctrl = ifxmipsasc_get_mctrl,
.stop_tx = ifxmipsasc_stop_tx,
.start_tx = ifxmipsasc_start_tx,
.stop_rx = ifxmipsasc_stop_rx,
.enable_ms = ifxmipsasc_enable_ms,
.break_ctl = ifxmipsasc_break_ctl,
.startup = ifxmipsasc_startup,
.shutdown = ifxmipsasc_shutdown,
.set_termios = ifxmipsasc_set_termios,
.type = ifxmipsasc_type,
.release_port = ifxmipsasc_release_port,
.request_port = ifxmipsasc_request_port,
.config_port = ifxmipsasc_config_port,
.verify_port = ifxmipsasc_verify_port,
};
static struct uart_port ifxmipsasc_port[2] = {
{
.membase = (void *)IFXMIPS_ASC_BASE_ADDR,
.mapbase = IFXMIPS_ASC_BASE_ADDR,
.iotype = SERIAL_IO_MEM,
.irq = IFXMIPSASC_TIR(0),
.uartclk = 0,
.fifosize = 16,
.type = PORT_IFXMIPSASC,
.ops = &ifxmipsasc_pops,
.flags = ASYNC_BOOT_AUTOCONF,
.line = 0
}, {
.membase = (void *)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF),
.mapbase = IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF,
.iotype = SERIAL_IO_MEM,
.irq = IFXMIPSASC_TIR(1),
.uartclk = 0,
.fifosize = 16,
.type = PORT_IFXMIPSASC,
.ops = &ifxmipsasc_pops,
.flags = ASYNC_BOOT_AUTOCONF,
.line = 1
}
};
static void ifxmipsasc_console_write(struct console *co, const char *s, u_int count)
{
int port = co->index;
int i, fifocnt;
unsigned long flags;
local_irq_save(flags);
for (i = 0; i < count; i++) {
do {
fifocnt = (ifxmips_r32((u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK)
>> ASCFSTAT_TXFFLOFF;
} while (fifocnt == TXFIFO_FULL);
if (s[i] == '\0')
break;
if (s[i] == '\n') {
ifxmips_w32('\r', (u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF));
do {
fifocnt = (ifxmips_r32((u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK)
>> ASCFSTAT_TXFFLOFF;
} while (fifocnt == TXFIFO_FULL);
}
ifxmips_w32(s[i], (u32 *)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF));
}
local_irq_restore(flags);
}
static int __init ifxmipsasc_console_setup(struct console *co, char *options)
{
int port = co->index;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
ifxmipsasc_port[port].uartclk = ifxmips_get_fpi_hz();
ifxmipsasc_port[port].type = PORT_IFXMIPSASC;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(&ifxmipsasc_port[port], co, baud, parity, bits, flow);
}
static struct console ifxmipsasc_console[2] =
{
{
.name = "ttyS",
.write = ifxmipsasc_console_write,
.device = uart_console_device,
.setup = ifxmipsasc_console_setup,
.flags = CON_PRINTBUFFER,
.index = 0,
.data = &ifxmipsasc_reg,
}, {
.name = "ttyS",
.write = ifxmipsasc_console_write,
.device = uart_console_device,
.setup = ifxmipsasc_console_setup,
.flags = CON_PRINTBUFFER,
.index = 1,
.data = &ifxmipsasc_reg,
}
};
static int __init ifxmipsasc_console_init(void)
{
register_console(&ifxmipsasc_console[0]);
register_console(&ifxmipsasc_console[1]);
return 0;
}
console_initcall(ifxmipsasc_console_init);
static struct uart_driver ifxmipsasc_reg = {
.owner = THIS_MODULE,
.driver_name = "serial",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
.nr = 2,
.cons = &ifxmipsasc_console[1],
};
int __init ifxmipsasc_init(void)
{
int ret;
uart_register_driver(&ifxmipsasc_reg);
ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[0]);
ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[1]);
return 0;
}
void __exit ifxmipsasc_exit(void)
{
uart_unregister_driver(&ifxmipsasc_reg);
}
module_init(ifxmipsasc_init);
module_exit(ifxmipsasc_exit);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("MIPS IFXMips serial port driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,195 @@
/*
* 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
*
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
* Based on EP93xx wdt driver
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <ifxmips.h>
#include <ifxmips_cgu.h>
#define IFXMIPS_WDT_PW1 0x00BE0000
#define IFXMIPS_WDT_PW2 0x00DC0000
#ifndef CONFIG_WATCHDOG_NOWAYOUT
static int wdt_ok_to_close;
#endif
static int wdt_timeout = 30;
int ifxmips_wdt_enable(unsigned int timeout)
{
u32 fpi;
fpi = cgu_get_io_region_clock();
ifxmips_w32(IFXMIPS_WDT_PW1, IFXMIPS_BIU_WDT_CR);
ifxmips_w32(IFXMIPS_WDT_PW2 |
(0x3 << 26) | /* PWL */
(0x3 << 24) | /* CLKDIV */
(0x1 << 31) | /* enable */
((timeout * (fpi / 0x40000)) + 0x1000), /* reload */
IFXMIPS_BIU_WDT_CR);
return 0;
}
void ifxmips_wdt_disable(void)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
wdt_ok_to_close = 0;
#endif
ifxmips_w32(IFXMIPS_WDT_PW1, IFXMIPS_BIU_WDT_CR);
ifxmips_w32(IFXMIPS_WDT_PW2, IFXMIPS_BIU_WDT_CR);
}
static ssize_t ifxmips_wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
size_t i;
if (!len)
return 0;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
wdt_ok_to_close = 1;
}
#endif
ifxmips_wdt_enable(wdt_timeout);
return len;
}
static struct watchdog_info ident = {
.options = WDIOF_MAGICCLOSE,
.identity = "ifxmips Watchdog",
};
static int ifxmips_wdt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret = -ENOTTY;
switch (cmd) {
case WDIOC_GETSUPPORT:
ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETTIMEOUT:
ret = put_user(wdt_timeout, (int __user *)arg);
break;
case WDIOC_SETTIMEOUT:
ret = get_user(wdt_timeout, (int __user *)arg);
break;
case WDIOC_KEEPALIVE:
ifxmips_wdt_enable(wdt_timeout);
ret = 0;
break;
}
return ret;
}
static int ifxmips_wdt_open(struct inode *inode, struct file *file)
{
ifxmips_wdt_enable(wdt_timeout);
return nonseekable_open(inode, file);
}
static int ifxmips_wdt_release(struct inode *inode, struct file *file)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
if (wdt_ok_to_close)
ifxmips_wdt_disable();
else
#endif
printk(KERN_ERR "ifxmips_wdt: watchdog closed without warning,"
" rebooting system\n");
return 0;
}
static const struct file_operations ifxmips_wdt_fops = {
.owner = THIS_MODULE,
.write = ifxmips_wdt_write,
.ioctl = ifxmips_wdt_ioctl,
.open = ifxmips_wdt_open,
.release = ifxmips_wdt_release,
};
static struct miscdevice ifxmips_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &ifxmips_wdt_fops,
};
static int ifxmips_wdt_probe(struct platform_device *dev)
{
int err;
err = misc_register(&ifxmips_wdt_miscdev);
if (err)
printk(KERN_INFO "ifxmips_wdt: error creating device\n");
else
printk(KERN_INFO "ifxmips_wdt: loaded\n");
return err;
}
static int ifxmips_wdt_remove(struct platform_device *dev)
{
ifxmips_wdt_disable();
misc_deregister(&ifxmips_wdt_miscdev);
return 0;
}
static struct platform_driver ifxmips_wdt_driver = {
.probe = ifxmips_wdt_probe,
.remove = ifxmips_wdt_remove,
.driver = {
.name = "ifxmips_wdt",
.owner = THIS_MODULE,
},
};
static int __init init_ifxmips_wdt(void)
{
int ret = platform_driver_register(&ifxmips_wdt_driver);
if (ret)
printk(KERN_INFO "ifxmips_wdt: error registering platfom driver!");
return ret;
}
static void __exit exit_ifxmips_wdt(void)
{
platform_driver_unregister(&ifxmips_wdt_driver);
}
module_init(init_ifxmips_wdt);
module_exit(exit_ifxmips_wdt);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("ifxmips Watchdog");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

View File

@ -1,5 +0,0 @@
BOARDNAME:=Generic
define Target/Description
Build standard images for Infineon CPE devices
endef

View File

@ -1,7 +0,0 @@
# Copyright (C) 2006 OpenWrt.org
config interface loopback
option ifname lo
option proto static
option ipaddr 127.0.0.1
option netmask 255.0.0.0

View File

@ -1,12 +0,0 @@
#!/bin/sh
init_nfs() {
grep "/dev/root" /proc/mounts | grep -q nfs && {
echo "- init nfs -"
exec /sbin/init
}
}
boot_hook_add preinit_main init_nfs

View File

@ -1,23 +0,0 @@
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_RNG2=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_DHCP is not set
# CONFIG_IP_PNP_RARP is not set
CONFIG_IP_PNP=y
CONFIG_LOCKD=y
# CONFIG_NETFILTER is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_SUNRPC_GSS=y
CONFIG_SUNRPC=y

View File

@ -1,8 +0,0 @@
BOARDNAME:=NFS Root
FEATURES:=tgz
DEVICE_TYPE:=modem
define Target/Description
Build images for Infineon CPE devices for NFS boot
endef

View File

@ -0,0 +1,39 @@
Index: linux-2.6.33.2/arch/mips/kernel/traps.c
===================================================================
--- linux-2.6.33.2.orig/arch/mips/kernel/traps.c 2010-04-02 01:02:33.000000000 +0200
+++ linux-2.6.33.2/arch/mips/kernel/traps.c 2010-04-02 23:36:16.000000000 +0200
@@ -1496,7 +1496,18 @@
if (cpu_has_mips_r2) {
cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
+
+ if (!cp0_compare_irq)
+ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
+
cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
+
+ if (!cp0_perfcount_irq)
+ cp0_perfcount_irq = CP0_LEGACY_PERFCNT_IRQ;
+
+ if (arch_fixup_c0_irqs)
+ arch_fixup_c0_irqs();
+
if (cp0_perfcount_irq == cp0_compare_irq)
cp0_perfcount_irq = -1;
} else {
Index: linux-2.6.33.2/arch/mips/include/asm/irq.h
===================================================================
--- linux-2.6.33.2.orig/arch/mips/include/asm/irq.h 2010-04-02 01:02:33.000000000 +0200
+++ linux-2.6.33.2/arch/mips/include/asm/irq.h 2010-04-02 23:37:14.000000000 +0200
@@ -133,9 +133,11 @@
* IE7. Since R2 their number has to be read from the c0_intctl register.
*/
#define CP0_LEGACY_COMPARE_IRQ 7
+#define CP0_LEGACY_PERFCNT_IRQ 7
extern int cp0_compare_irq;
extern int cp0_compare_irq_shift;
extern int cp0_perfcount_irq;
+extern void __weak arch_fixup_c0_irqs(void);
#endif /* _ASM_IRQ_H */

View File

@ -0,0 +1,35 @@
Index: linux-2.6.32.10/arch/mips/kernel/cevt-r4k.c
===================================================================
--- linux-2.6.32.10.orig/arch/mips/kernel/cevt-r4k.c 2010-04-02 21:11:39.000000000 +0200
+++ linux-2.6.32.10/arch/mips/kernel/cevt-r4k.c 2010-04-02 21:11:52.000000000 +0200
@@ -22,6 +22,22 @@
#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * Compare interrupt can be routed and latched outside the core,
+ * so a single execution hazard barrier may not be enough to give
+ * it time to clear as seen in the Cause register. 4 time the
+ * pipeline depth seems reasonably conservative, and empirically
+ * works better in configurations with high CPU/bus clock ratios.
+ */
+
+#define compare_change_hazard() \
+ do { \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ irq_disable_hazard(); \
+ } while (0)
+
static int mips_next_event(unsigned long delta,
struct clock_event_device *evt)
{
@@ -31,6 +47,7 @@
cnt = read_c0_count();
cnt += delta;
write_c0_compare(cnt);
+ compare_change_hazard();
res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
return res;
}

View File

@ -0,0 +1,14 @@
Index: linux-2.6.33.2/kernel/irq/chip.c
===================================================================
--- linux-2.6.33.2.orig/kernel/irq/chip.c 2010-04-02 01:02:33.000000000 +0200
+++ linux-2.6.33.2/kernel/irq/chip.c 2010-04-02 23:37:40.000000000 +0200
@@ -650,6 +650,9 @@
kstat_incr_irqs_this_cpu(irq, desc);
+ if (unlikely(!desc->action || (desc->status & IRQ_DISABLED)))
+ return;
+
if (desc->chip->ack)
desc->chip->ack(irq);

View File

@ -0,0 +1,134 @@
--- a/arch/mips/kernel/mips_machine.c
+++ b/arch/mips/kernel/mips_machine.c
@@ -7,12 +7,13 @@
*
*/
#include <linux/mm.h>
+#include <linux/string.h>
#include <asm/mips_machine.h>
-#include <asm/bootinfo.h>
static struct list_head mips_machines __initdata =
LIST_HEAD_INIT(mips_machines);
+static char *mips_machid __initdata;
char *mips_machine_name = "Unknown";
@@ -55,20 +56,65 @@ void __init mips_machine_set_name(char *
}
}
-void __init mips_machine_setup(unsigned long machtype)
+void __init mips_machine_setup(void)
{
struct mips_machine *mach;
- mach = mips_machine_find(machtype);
+ mach = mips_machine_find(mips_machtype);
if (!mach) {
- printk(KERN_ALERT "MIPS: no machine registered for "
- "machtype %lu\n", machtype);
+ printk(KERN_WARNING "MIPS: no machine registered for "
+ "machtype %lu\n", mips_machtype);
return;
}
mips_machine_set_name(mach->mach_name);
- printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name);
+ printk(KERN_NOTICE "MIPS: machine is %s\n", mips_machine_name);
if (mach->mach_setup)
mach->mach_setup();
}
+
+int __init mips_machtype_setup(char *id)
+{
+ if (mips_machid == NULL)
+ mips_machid = id;
+
+ return 1;
+}
+
+__setup("machtype=", mips_machtype_setup);
+
+static int __init mips_machtype_init(void)
+{
+ struct list_head *this;
+ struct mips_machine *mach;
+
+ if (mips_machid == NULL)
+ return 0;
+
+ list_for_each(this, &mips_machines) {
+ mach = list_entry(this, struct mips_machine, list);
+ if (mach->mach_id == NULL)
+ continue;
+
+ if (strcmp(mach->mach_id, mips_machid) == 0) {
+ mips_machtype = mach->mach_type;
+ return 0;
+ }
+ }
+
+ printk(KERN_WARNING
+ "MIPS: no machine found for id: '%s', registered machines:\n",
+ mips_machid);
+ printk(KERN_WARNING "%32s %s\n", "id", "name");
+
+ list_for_each(this, &mips_machines) {
+ mach = list_entry(this, struct mips_machine, list);
+ printk(KERN_WARNING "%32s %s\n",
+ mach->mach_id ? mach->mach_id : "", mach->mach_name);
+ }
+
+ return 0;
+}
+
+core_initcall(mips_machtype_init);
--- a/arch/mips/include/asm/mips_machine.h
+++ b/arch/mips/include/asm/mips_machine.h
@@ -13,25 +13,33 @@
#include <linux/init.h>
#include <linux/list.h>
+#include <asm/bootinfo.h>
+
struct mips_machine {
unsigned long mach_type;
- void (*mach_setup)(void);
+ char *mach_id;
char *mach_name;
+ void (*mach_setup)(void);
struct list_head list;
};
void mips_machine_register(struct mips_machine *) __init;
-void mips_machine_setup(unsigned long machtype) __init;
+void mips_machine_setup(void) __init;
+int mips_machtype_setup(char *id) __init;
void mips_machine_set_name(char *name) __init;
extern char *mips_machine_name;
-#define MIPS_MACHINE(_type, _name, _setup) \
-static char machine_name_##_type[] __initdata = _name; \
+#define MIPS_MACHINE(_type, _id, _name, _setup) \
+static const char machine_name_##_type[] __initconst \
+ __aligned(1) = _name; \
+static const char machine_id_##_type[] __initconst \
+ __aligned(1) = _id; \
static struct mips_machine machine_##_type __initdata = \
{ \
.mach_type = _type, \
- .mach_name = machine_name_##_type, \
+ .mach_id = (char *) machine_id_##_type, \
+ .mach_name = (char *) machine_name_##_type, \
.mach_setup = _setup, \
}; \
\
@@ -44,4 +52,3 @@ static int __init register_machine_##_ty
pure_initcall(register_machine_##_type)
#endif /* __ASM_MIPS_MACHINE_H */
-

View File

@ -0,0 +1,58 @@
Index: linux-2.6.33.2/arch/mips/Kconfig
===================================================================
--- linux-2.6.33.2.orig/arch/mips/Kconfig 2010-04-02 23:31:00.000000000 +0200
+++ linux-2.6.33.2/arch/mips/Kconfig 2010-04-02 23:38:38.000000000 +0200
@@ -139,6 +139,9 @@
otherwise choose R3000.
+config IFXMIPS
+ bool "Infineon MIPS"
+
config MACH_JAZZ
bool "Jazz family of machines"
select ARC
@@ -693,6 +696,7 @@
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
source "arch/mips/loongson/Kconfig"
+source "arch/mips/ifxmips/Kconfig"
endmenu
Index: linux-2.6.33.2/arch/mips/Makefile
===================================================================
--- linux-2.6.33.2.orig/arch/mips/Makefile 2010-04-02 23:31:01.000000000 +0200
+++ linux-2.6.33.2/arch/mips/Makefile 2010-04-02 23:38:38.000000000 +0200
@@ -317,6 +317,18 @@
load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000
#
+# Infineon IFXMIPS
+#
+core-$(CONFIG_IFXMIPS) += arch/mips/ifxmips/common/
+cflags-$(CONFIG_IFXMIPS) += -I$(srctree)/arch/mips/include/asm/mach-ifxmips
+
+core-$(CONFIG_IFXMIPS_DANUBE) += arch/mips/ifxmips/danube/
+cflags-$(CONFIG_IFXMIPS_DANUBE) += -I$(srctree)/arch/mips/include/asm/mach-ifxmips/danube/
+load-$(CONFIG_IFXMIPS_DANUBE) += 0xffffffff80002000
+
+core-$(CONFIG_IFXMIPS_COMPAT) += arch/mips/ifxmips/compat/
+
+#
# DECstation family
#
core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/
Index: linux-2.6.33.2/arch/mips/pci/Makefile
===================================================================
--- linux-2.6.33.2.orig/arch/mips/pci/Makefile 2010-04-02 01:02:33.000000000 +0200
+++ linux-2.6.33.2/arch/mips/pci/Makefile 2010-04-02 23:38:38.000000000 +0200
@@ -55,7 +55,7 @@
obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o
obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o
-
+obj-$(CONFIG_IFXMIPS) += pci-ifxmips.o ops-ifxmips.o
ifdef CONFIG_PCI_MSI
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o
endif

Some files were not shown because too many files have changed in this diff Show More