diff options
Diffstat (limited to 'arch/xtensa/platforms/xtavnet')
-rw-r--r-- | arch/xtensa/platforms/xtavnet/Makefile | 10 | ||||
-rw-r--r-- | arch/xtensa/platforms/xtavnet/include/platform/hardware.h | 85 | ||||
-rw-r--r-- | arch/xtensa/platforms/xtavnet/include/platform/lcd.h | 22 | ||||
-rw-r--r-- | arch/xtensa/platforms/xtavnet/include/platform/serial.h | 1 | ||||
-rw-r--r-- | arch/xtensa/platforms/xtavnet/lcd.c | 79 | ||||
-rw-r--r-- | arch/xtensa/platforms/xtavnet/setup.c | 269 |
6 files changed, 466 insertions, 0 deletions
diff --git a/arch/xtensa/platforms/xtavnet/Makefile b/arch/xtensa/platforms/xtavnet/Makefile new file mode 100644 index 000000000000..06b120b40015 --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/Makefile @@ -0,0 +1,10 @@ +# Makefile for the Tensilica Avnet-based Emulation Boards +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are in the main makefile... + +obj-y = setup.o lcd.o + diff --git a/arch/xtensa/platforms/xtavnet/include/platform/hardware.h b/arch/xtensa/platforms/xtavnet/include/platform/hardware.h new file mode 100644 index 000000000000..5301be745113 --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/include/platform/hardware.h @@ -0,0 +1,85 @@ +/* + * arch/xtensa/platforms/xtavnet/include/platform/hardware.h + * + * This file contains the hardware configuration of Tensilica Avnet boards + * (XT-AV60, XT-AV110, XT-AV200, derived from Avnet LX60, LX110, LX200 + * boards respectively). + * + * Copyright (C) 2006-2010 Tensilica Inc. + * + * 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 __XTAVNET_HARDWARE_H +#define __XTAVNET_HARDWARE_H + +#include <variant/core.h> + +/* Memory configuration. */ + +#define PLATFORM_DEFAULT_MEM_START 0x00000000 +#define PLATFORM_DEFAULT_MEM_SIZE 0x04000000 + +/* Interrupt configuration. */ + +#define PLATFORM_NR_IRQS 2 + +/* + * Default assignment of XTAVnet devices to external interrupts. + * + * CONFIG_ARCH_HAS_SMP means the hardware supports SMP, ie. is Xtensa MX. + * + * Systems with SMP support (MX) have an External Interrupt Distributor + * between external interrupts and the core's interrupts. The first three + * core interrupts are used for IPI (interprocessor interrupts), so + * external (board device) interrupts end up shifted up by 3. + */ + +/* UART interrupt: */ +#ifdef CONFIG_ARCH_HAS_SMP +#define UART_INTNUM XCHAL_EXTINT3_NUM +#else +#define UART_INTNUM XCHAL_EXTINT0_NUM +#endif + +/* Ethernet interrupt: */ +#ifdef CONFIG_ARCH_HAS_SMP +#define OETH_IRQ XCHAL_EXTINT4_NUM +#else +#define OETH_IRQ XCHAL_EXTINT1_NUM +#endif + +/* + * Device addresses and parameters. + */ + +/* UART */ +#define UART_PADDR 0xFD050020 + +/* LCD instruction and data virt. addresses. */ +#define LCD_INSTR_ADDR (char*)(0xFD040000) +#define LCD_DATA_ADDR (char*)(0xFD040004) + +/* Misc. */ +#define XTAVNET_FPGAREGS_VADDR 0xFD020000 +/* Clock frequency in Hz (read-only): */ +#define XTAVNET_CLKFRQ_VADDR (XTAVNET_FPGAREGS_VADDR + 0x04) +/* Setting of 8 DIP switches: */ +#define DIP_SWITCHES_VADDR (XTAVNET_FPGAREGS_VADDR + 0x0C) +/* Software reset (write 0xdead): */ +#define XTAVNET_SWRST_VADDR (XTAVNET_FPGAREGS_VADDR + 0x10) + +/* OpenCores Ethernet controller: */ +#define OETH_REGS_PADDR IOADDR(0xD030000) /* regs + RX/TX descriptors */ +#define OETH_REGS_VADDR 0xFD030000 +#define OETH_REGS_SIZE 0x1000 +#define OETH_SRAMBUFF_PADDR 0xFD800000 +#define OETH_SRAMBUFF_SIZE (5*0x600 + 5*0x600) /* 5*rx buffs + 5*tx buffs */ +/*#define OETH_SRAMBUFF_SIZE 0x3C00*/ /* probably 0x4000 ? */ +/* The MAC address for these boards is 00:50:c2:13:6f:xx. + The last byte (here as zero) is read from the DIP switches on the board. */ +#define OETH_MACADDR 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 + +#endif /* __XTAVNET_HARDWARE_H */ diff --git a/arch/xtensa/platforms/xtavnet/include/platform/lcd.h b/arch/xtensa/platforms/xtavnet/include/platform/lcd.h new file mode 100644 index 000000000000..67de96acb2f9 --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/include/platform/lcd.h @@ -0,0 +1,22 @@ +/* + * arch/xtensa/platforms/xtavnet/include/platform/lcd.h + * + * Copyright (C) 2001-2006 Tensilica Inc. + * + * 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 __XTAVNET_LCD_H +#define __XTAVNET_LCD_H + +/* Display string STR at position POS on the LCD. */ +void lcd_disp_at_pos(char *str, unsigned char pos); + +/* Shift the contents of the LCD display left or right. */ +void lcd_shiftleft(void); +void lcd_shiftright(void); + +#endif + diff --git a/arch/xtensa/platforms/xtavnet/include/platform/serial.h b/arch/xtensa/platforms/xtavnet/include/platform/serial.h new file mode 100644 index 000000000000..a0cb0caff152 --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/include/platform/serial.h @@ -0,0 +1 @@ +#include <asm-generic/serial.h> diff --git a/arch/xtensa/platforms/xtavnet/lcd.c b/arch/xtensa/platforms/xtavnet/lcd.c new file mode 100644 index 000000000000..283986f158ad --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/lcd.c @@ -0,0 +1,79 @@ +/* + * Driver for the LCD display on the Tensilica LX60 Board. + * This code has no effect on the LX200 board. (LX110: TBD) + * + * Copyright (C) 2001-2006 Tensilica Inc. + * + * 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. + */ + +/* + * + * FIXME: this code is from the examples from the LX60 user guide. + * + * The lcd_pause function does busy waiting, which is probably not + * great. Maybe the code could be changed to use kernel timers, or + * change the hardware to not need to wait. + */ + +#include <linux/init.h> + +#include <platform/hardware.h> +#include <asm/processor.h> +#include <platform/lcd.h> +#include <linux/delay.h> + +#define LCD_PAUSE_ITERATIONS 4000 +#define LCD_CLEAR 0x1 +#define LCD_DISPLAY_ON 0xc + +/* 8bit and 2 lines display */ +#define LCD_DISPLAY_MODE8BIT 0x38 +#define LCD_DISPLAY_POS 0x80 +#define LCD_SHIFT_LEFT 0x18 +#define LCD_SHIFT_RIGHT 0x1c + +static int __init lcd_init(void) +{ + *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; + mdelay(5); + *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; + udelay(200); + *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; + udelay(50); + *LCD_INSTR_ADDR = LCD_DISPLAY_ON; + udelay(50); + *LCD_INSTR_ADDR = LCD_CLEAR; + mdelay(10); + lcd_disp_at_pos("XTENSA LINUX", 0); + + return 0; +} + +void lcd_disp_at_pos (char *str, unsigned char pos) +{ + *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; + udelay(100); + while (*str != 0){ + *LCD_DATA_ADDR = *str; + udelay(200); + str++; + } +} + +void lcd_shiftleft(void) +{ + *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; + udelay(50); +} + +void lcd_shiftright(void) +{ + *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; + udelay(50); +} + +arch_initcall(lcd_init); + diff --git a/arch/xtensa/platforms/xtavnet/setup.c b/arch/xtensa/platforms/xtavnet/setup.c new file mode 100644 index 000000000000..256fcb2b2af4 --- /dev/null +++ b/arch/xtensa/platforms/xtavnet/setup.c @@ -0,0 +1,269 @@ +/* + * arch/xtensa/platform-xtavnet/setup.c + * + * Setup/initialization for Tensilica Avnet boards (XT-AV60, XT-AV110, XT-AV200, + * derived from Avnet LX60, LX110, LX200 boards respectively). + * For details, see "Tensilica Avnet LX### (XT-AV###) Board User's Guide" + * (where ### is 60, 110, or 200). + * + * Authors: Chris Zankel <chris@zankel.net> + * Joe Taylor <joe@tensilica.com> + * Pete Delaney <piet@tensilica.com> + * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca> + * + * Copyright 2001-2010 Tensilica Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License, version 2. See the file "COPYING" in the main directory of this + * archive for more details. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/kdev_t.h> +#include <linux/types.h> +#include <linux/major.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/stringify.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> +#include <asm/timex.h> + +#include <linux/etherdevice.h> +#include <net/ethoc.h> + +#include <asm/processor.h> +#include <asm/platform.h> +#include <asm/bootparam.h> +#include <platform/lcd.h> +#include <platform/hardware.h> +#include <variant/core.h> + +/* For doing extra init. beyond what the ethoc driver does. */ +struct oeth_regs { + unsigned moder; /* Mode Register */ + unsigned int_src; /* Interrupt Source Register */ + unsigned int_mask; /* Interrupt Mask Register */ + unsigned ipgt; /* Back to Bak Inter Packet Gap Register */ + unsigned ipgr1; /* Non Back to Back Inter Packet Gap Register 1 */ + unsigned ipgr2; /* Non Back to Back Inter Packet Gap Register 2 */ + unsigned packet_len; /* Packet Length Register (min. and max.) */ + unsigned collconf; /* Collision and Retry Configuration Register */ + unsigned tx_bd_num; /* Transmit Buffer Descriptor Number Register */ + unsigned ctrlmoder; /* Control Module Mode Register */ + unsigned miimoder; /* MII Mode Register */ + unsigned miicommand; /* MII Command Register */ + unsigned miiaddress; /* MII Address Register */ + unsigned miitx_data; /* MII Transmit Data Register */ + unsigned miirx_data; /* MII Receive Data Register */ + unsigned miistatus; /* MII Status Register */ + unsigned mac_addr0; /* MAC Individual Address Register 0 */ + unsigned mac_addr1; /* MAC Individual Address Register 1 */ + unsigned hash_addr0; /* Hash Register 0 */ + unsigned hash_addr1; /* Hash Register 1 */ +}; +/* MODER Register */ +#define OETH_MODER_RST 0x00000800 /* Reset MAC */ +/* MII Mode Register */ +#define OETH_MIIMODER_CLKDIV 0x000000FF /* Clock Divider */ + + + +void platform_halt(void) +{ + /* Just display HALT on LCD display, and loop. */ + lcd_disp_at_pos(" HALT ", 0); + local_irq_disable(); + while (1); +} + +void platform_power_off(void) +{ + /* No software-controlled power-off, just display POWEROFF and loop. */ + lcd_disp_at_pos ("POWEROFF", 0); + local_irq_disable(); + while (1); +} + +void platform_restart(void) +{ + /* Software-initiated board reset. */ + *(volatile unsigned *)XTAVNET_SWRST_VADDR = 0xdead; +} + +void platform_heartbeat(void) +{ + /* Executes every timer tick. */ +} + + +/* + * Called from time_init(). "Calibrating" is a misnomer, here we just read + * the clock rate from the board specific FPGA registers. + */ +void platform_calibrate_ccount(void) +{ + long clk_freq = *(long *)XTAVNET_CLKFRQ_VADDR; + + ccount_per_jiffy = clk_freq / HZ; + nsec_per_ccount = 1000000000UL / clk_freq; +} + + +/*---------------------------------------------------------------------------- + * Ethernet -- OpenCores Ethernet MAC (ethoc driver) + */ + +static struct resource ethoc_res[] = { + [0] = { /* register space */ + .start = OETH_REGS_PADDR, + .end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { /* buffer space */ + .start = OETH_SRAMBUFF_PADDR, + .end = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { /* IRQ number */ + .start = OETH_IRQ, + .end = OETH_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct ethoc_platform_data ethoc_pdata = { + .hwaddr = { OETH_MACADDR }, /* last byte written in setup below */ + .phy_id = -1, +}; + +static struct platform_device ethoc_device = { + .name = "ethoc", + .id = -1, + .num_resources = ARRAY_SIZE(ethoc_res), + .resource = ethoc_res, + .dev = { + .platform_data = ðoc_pdata, + }, +}; + + +/*---------------------------------------------------------------------------- + * UART + */ + +static struct resource serial_resource = { + .start = UART_PADDR, + .end = UART_PADDR + 0x1f, + .flags = IORESOURCE_MEM, +}; + +static struct plat_serial8250_port serial_platform_data[] = { + [0] = { + .mapbase = UART_PADDR, + .irq = UART_INTNUM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + .iotype = UPIO_MEM32, + .regshift = 2, + .uartclk = 0, /* set in xtavnet_init() */ + }, + { }, +}; + +static struct platform_device xtavnet_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = serial_platform_data, + }, + .num_resources = 1, + .resource = &serial_resource, +}; + + +/*---------------------------------------------------------------------------- + */ + +/* platform devices */ +static struct platform_device *platform_devices[] = { + ðoc_device, + &xtavnet_uart, +}; + + + +/* very early init */ +void __init platform_setup(char **cmdline) +{ + if (cmdline) { + if (cmdline[0]) + printk("XTAVnet: platform_setup(cmdline[0]:'%s')\n", cmdline[0]); + else + printk("XTAVnet: platform_setup(cmdline[0]:<null>)\n"); + } +} + +/* early initialization, before secondary cpu's have been brought up */ + +void platform_init(bp_tag_t *bootparams) +{ + printk("\n"); + if( bootparams ) + printk("XTAVnet: platform_init(bootparams:0x%x)\n", (unsigned)bootparams); +} + +static int xtavnet_init(void) +{ + volatile struct oeth_regs *regs = (volatile struct oeth_regs*)OETH_REGS_VADDR; + + /* + * Do some of the initialization missing in the ETHOC driver. + * (Perhaps not all necessary, but was in a previously used driver.) + */ + + /* Reset the controller. */ + regs->moder = OETH_MODER_RST; /* Reset ON */ + regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ + + regs->packet_len = (64 << 16) | 1536; + regs->ipgr1 = 0x0000000c; + regs->ipgr2 = 0x00000012; + regs->collconf = 0x000f003f; + regs->ctrlmoder = 0; + regs->miimoder = (OETH_MIIMODER_CLKDIV & 0x2); + + /* + * Setup dynamic info in platform device init structures. + */ + + /* Ethernet MAC address. */ + ethoc_pdata.hwaddr[5] = *(u32*)DIP_SWITCHES_VADDR; + + /* Clock rate varies among FPGA bitstreams; board specific FPGA register + * reports the actual clock rate. */ + serial_platform_data[0].uartclk = *(long *)XTAVNET_CLKFRQ_VADDR; + + + /* register platform devices */ + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + + /* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user + knows whether they set it correctly on the DIP switches. */ + printk("XTAVnet: Ethernet MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + ethoc_pdata.hwaddr[0], ethoc_pdata.hwaddr[1], ethoc_pdata.hwaddr[2], + ethoc_pdata.hwaddr[3], ethoc_pdata.hwaddr[4], ethoc_pdata.hwaddr[5]); + + return 0; +} + + +/* + * Register to be done during do_initcalls(). + */ +arch_initcall(xtavnet_init); + + |