diff options
author | Stefan Roese <sr@denx.de> | 2006-10-07 11:35:25 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2006-10-07 11:35:25 +0200 |
commit | 5bc528fa4da751d472397b308137238a6465afd2 (patch) | |
tree | 9cd3d9702b7b92cffa166ea7a0bd8fdcf1a964a7 /board/prodrive | |
parent | 77d5034847d328753b80c46b83f960a14a26f40e (diff) |
Update ALPR code (NAND support working now)
Patch by Stefan Roese, 07 Oct 2006
Diffstat (limited to 'board/prodrive')
-rw-r--r-- | board/prodrive/alpr/Makefile | 2 | ||||
-rw-r--r-- | board/prodrive/alpr/alpr.c | 31 | ||||
-rw-r--r-- | board/prodrive/alpr/flash.c | 70 | ||||
-rw-r--r-- | board/prodrive/alpr/init.S | 89 | ||||
-rw-r--r-- | board/prodrive/alpr/nand.c | 202 | ||||
-rw-r--r-- | board/prodrive/common/flash.c | 4 |
6 files changed, 185 insertions, 213 deletions
diff --git a/board/prodrive/alpr/Makefile b/board/prodrive/alpr/Makefile index 993ad1995d4..1024a41a075 100644 --- a/board/prodrive/alpr/Makefile +++ b/board/prodrive/alpr/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a -COBJS = $(BOARD).o fpga.o nand.o +COBJS = $(BOARD).o flash.o fpga.o nand.o SOBJS = init.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/prodrive/alpr/alpr.c b/board/prodrive/alpr/alpr.c index 4f250c4f2f7..e8435bf63cb 100644 --- a/board/prodrive/alpr/alpr.c +++ b/board/prodrive/alpr/alpr.c @@ -38,11 +38,19 @@ int board_early_init_f (void) /*-------------------------------------------------------------------------+ | Initialize EBC CONFIG +-------------------------------------------------------------------------*/ +#if 0 mtebc(xbcfg, EBC_CFG_LE_UNLOCK | EBC_CFG_PTD_ENABLE | EBC_CFG_RTC_64PERCLK | EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS | EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_NONDEFAULT | EBC_CFG_PME_DISABLE | EBC_CFG_PR_32); +#else + mtebc(xbcfg, EBC_CFG_LE_UNLOCK | + EBC_CFG_PTD_DISABLE | EBC_CFG_RTC_64PERCLK | + EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS | + EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_NONDEFAULT | + EBC_CFG_PME_DISABLE | EBC_CFG_PR_32); +#endif /*-------------------------------------------------------------------- * Setup the interrupt controller polarities, triggers, etc. @@ -230,19 +238,6 @@ int is_pci_host(struct pci_controller *hose) #if defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) void pci_master_init(struct pci_controller *hose) { - unsigned short temp_short; -#if 0 - /*--------------------------------------------------------------------------+ - | Write the PowerPC440 PCI Configuration regs. - | Enable PowerPC440 to be a master on the PCI bus (PMM). - | Enable PowerPC440 to act as a PCI memory target (PTM). - +--------------------------------------------------------------------------*/ - pci_read_config_word(0, PCI_COMMAND, &temp_short); - pci_write_config_word(0, PCI_COMMAND, - temp_short | PCI_COMMAND_MASTER | - PCI_COMMAND_MEMORY); -#endif -#if 1 /*--------------------------------------------------------------------------+ | PowerPC440 PCI Master configuration. | Map PLB/processor addresses to PCI memory space. @@ -265,8 +260,6 @@ void pci_master_init(struct pci_controller *hose) out32r(PCIX0_POM1PCIAL, CFG_PCI_MEMBASE2); /* PMM0 PCI Low Address */ out32r(PCIX0_POM1PCIAH, 0x00000000); /* PMM0 PCI High Address */ out32r(PCIX0_POM1SA, ~(0x10000000 - 1) | 1); /* 256MB + enable region */ - -#endif } #endif /* defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) */ @@ -281,3 +274,11 @@ int post_hotkeys_pressed(void) return (ctrlc()); } #endif + +void board_reset(void) +{ + /* + * Initiate chip reset in debug control register DBCR + */ + mtspr(dbcr0, 0x20000000); +} diff --git a/board/prodrive/alpr/flash.c b/board/prodrive/alpr/flash.c new file mode 100644 index 00000000000..8fa008430ad --- /dev/null +++ b/board/prodrive/alpr/flash.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * include common flash code (for esd boards) + */ +#include "../common/flash.c" + +/* + * Prototypes + */ +static ulong flash_get_size (vu_long * addr, flash_info_t * info); + +unsigned long flash_init(void) +{ + unsigned long size; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; i++) + flash_info[i].flash_id = FLASH_UNKNOWN; + + size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size, size<<20); + + /* Monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, -CFG_MONITOR_LEN, 0xffffffff, + &flash_info[0]); + + /* Environment protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[CFG_MAX_FLASH_BANKS - 1]); + + /* Redundant environment protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR_REDUND, + CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, + &flash_info[CFG_MAX_FLASH_BANKS - 1]); + + flash_info[0].size = size; + + return size; +} diff --git a/board/prodrive/alpr/init.S b/board/prodrive/alpr/init.S index 59d3ab634e7..1baa609c058 100644 --- a/board/prodrive/alpr/init.S +++ b/board/prodrive/alpr/init.S @@ -1,24 +1,25 @@ /* -* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com> -* -* See file CREDITS for list of people who contributed to this -* project. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License as -* published by the Free Software Foundation; either version 2 of -* the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, -* MA 02111-1307 USA -*/ + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ #include <ppc_asm.tmpl> #include <config.h> @@ -27,15 +28,15 @@ #define TLB_VALID 0x00000200 /* Supported page sizes */ - #define SZ_1K 0x00000000 #define SZ_4K 0x00000010 #define SZ_16K 0x00000020 #define SZ_64K 0x00000030 -#define SZ_256K 0x00000040 +#define SZ_256K 0x00000040 #define SZ_1M 0x00000050 +#define SZ_8M 0x00000060 #define SZ_16M 0x00000070 -#define SZ_256M 0x00000090 +#define SZ_256M 0x00000090 /* Storage attributes */ #define SA_W 0x00000800 /* Write-through */ @@ -81,29 +82,23 @@ * *************************************************************************/ - .section .bootpg,"ax" - .globl tlbtab + .section .bootpg,"ax" + .globl tlbtab tlbtab: - tlbtab_start - tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) - tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) - tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) - tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_SDRAM_BASE+0x10000000, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) - - /* PCI */ - tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 3, AC_R|AC_W|SA_G|SA_I ) -#if 1 - tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 3, AC_R|AC_W|SA_G|SA_I ) - tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 3, AC_R|AC_W|SA_G|SA_I ) -#endif -#if 0 - tlbentry( CFG_PCI_MEMBASE3, SZ_256M, CFG_PCI_MEMBASE3, 3, AC_R|AC_W|SA_G|SA_I ) -#endif - - /* NAND */ - tlbentry( CFG_NAND_BASE, SZ_16M, CFG_NAND_BASE, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) - tlbtab_end + tlbtab_start + tlbentry( 0xff000000, SZ_16M, 0xff000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) + tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) + tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) + + /* PCI */ + tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 3, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 3, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 3, AC_R|AC_W|SA_G|SA_I ) + + /* NAND */ + tlbentry( CFG_NAND_BASE, SZ_4K, CFG_NAND_BASE, 1, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbtab_end diff --git a/board/prodrive/alpr/nand.c b/board/prodrive/alpr/nand.c index bd9ba3560e9..20a80983073 100644 --- a/board/prodrive/alpr/nand.c +++ b/board/prodrive/alpr/nand.c @@ -2,6 +2,9 @@ * (C) Copyright 2006 * Heiko Schocher, DENX Software Engineering, hs@denx.de * + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * See file CREDITS for list of people who contributed to this * project. * @@ -22,69 +25,27 @@ */ #include <common.h> -#include <asm/io.h> #if (CONFIG_COMMANDS & CFG_CMD_NAND) +#include <asm/processor.h> #include <nand.h> -#if 0 -#define HS_printf(fmt,arg...) \ - printf("HS %s %s: " fmt,__FILE__, __FUNCTION__, ##arg) -#else -#define HS_printf(fmt,arg...) \ - do { } while (0) -#endif - -#if 0 -#define CPLD_REG uchar -#else -#define CPLD_REG u16 -#endif - struct alpr_ndfc_regs { - CPLD_REG cmd[4]; - CPLD_REG addr_wait; - CPLD_REG term; - CPLD_REG dummy; - uchar dum2[2]; - CPLD_REG data; + u16 cmd[4]; + u16 addr_wait; + u16 term; + u16 dummy; + u16 dummy2; + u16 data; }; static u8 hwctl; -static struct alpr_ndfc_regs *alpr_ndfc; -static int alpr_chip = 0; +static struct alpr_ndfc_regs *alpr_ndfc = NULL; -#if 1 -static int pdnb3_nand_dev_ready(struct mtd_info *mtd); +#define readb(addr) (u8)(*(volatile u16 *)(addr)) +#define writeb(d,addr) *(volatile u16 *)(addr) = ((u16)(d)) -#if 1 -static u_char alpr_read (void *padr) { - return (u_char )*((u16 *)(padr)); -} -#else -static u_char alpr_read (void *padr) { - u16 hilf; - u_char ret = 0; - hilf = *((u16 *)(padr)); - ret = hilf; -printf("%p hilf: %x ret: %x\n", padr, hilf, ret); - return ret; -} -#endif - -static void alpr_write (u_char byte, void *padr) { -HS_printf("%p Byte: %x\n", padr, byte); - *(volatile u16 *)padr = (u16)(byte); -} - -#elif 0 -#define alpr_read(a) (*(volatile u16 *) (a)) -#define alpr_write(a, b) ((*(volatile u16 *) (a)) = (b)) -#else -#define alpr_read(a) readw(a) -#define alpr_write(a, b) writew(a, b) -#endif /* * The ALPR has a NAND Flash Controller (NDFC) that handles all accesses to * the NAND devices. The NDFC has command, address and data registers that @@ -93,11 +54,10 @@ HS_printf("%p Byte: %x\n", padr, byte); * We can then use this information in the read and write functions to * determine which NDFC register to access. * - * There are 2 NAND devices on the board, a Hynix HY27US08561A (32 MByte). + * There are 2 NAND devices on the board, a Hynix HY27US08561A (1 GByte). */ -static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd) +static void alpr_nand_hwcontrol(struct mtd_info *mtd, int cmd) { -HS_printf("cmd: %x\n", cmd); switch (cmd) { case NAND_CTL_SETCLE: hwctl |= 0x1; @@ -114,136 +74,84 @@ HS_printf("cmd: %x\n", cmd); case NAND_CTL_SETNCE: break; case NAND_CTL_CLRNCE: - alpr_write(0x00, &(alpr_ndfc->term)); + writeb(0x00, &(alpr_ndfc->term)); break; } } -static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte) +static void alpr_nand_write_byte(struct mtd_info *mtd, u_char byte) { -HS_printf("hwctl: %x %x %x %x\n", hwctl, byte, &(alpr_ndfc->cmd[alpr_chip]), &(alpr_ndfc->addr_wait)); + struct nand_chip *nand = mtd->priv; + if (hwctl & 0x1) - alpr_write(byte, &(alpr_ndfc->cmd[alpr_chip])); + /* + * IO_ADDR_W used as CMD[i] reg to support multiple NAND + * chips. + */ + writeb(byte, nand->IO_ADDR_W); else if (hwctl & 0x2) { - alpr_write(byte, &(alpr_ndfc->addr_wait)); + writeb(byte, &(alpr_ndfc->addr_wait)); } else - alpr_write(byte, &(alpr_ndfc->data)); + writeb(byte, &(alpr_ndfc->data)); } -static u_char pdnb3_nand_read_byte(struct mtd_info *mtd) +static u_char alpr_nand_read_byte(struct mtd_info *mtd) { - return alpr_read(&(alpr_ndfc->data)); + return readb(&(alpr_ndfc->data)); } -static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void alpr_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { + struct nand_chip *nand = mtd->priv; int i; -/*printf("%s chip:%d hwctl:%x size:%d\n", __FUNCTION__, alpr_chip, hwctl, len);*/ for (i = 0; i < len; i++) { if (hwctl & 0x1) - alpr_write(buf[i], &(alpr_ndfc->cmd[alpr_chip])); - else if (hwctl & 0x2) { - alpr_write(buf[i], &(alpr_ndfc->addr_wait)); - } else { - alpr_write(buf[i], &(alpr_ndfc->data)); - /*printf("i: %d\n", i);*/ - } + /* + * IO_ADDR_W used as CMD[i] reg to support multiple NAND + * chips. + */ + writeb(buf[i], nand->IO_ADDR_W); + else if (hwctl & 0x2) + writeb(buf[i], &(alpr_ndfc->addr_wait)); + else + writeb(buf[i], &(alpr_ndfc->data)); } } -static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void alpr_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { int i; for (i = 0; i < len; i++) { - buf[i] = alpr_read(&(alpr_ndfc->data)); + buf[i] = readb(&(alpr_ndfc->data)); } } -static int pdnb3_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +static int alpr_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) { int i; for (i = 0; i < len; i++) - if (buf[i] != alpr_read(&(alpr_ndfc->data))) + if (buf[i] != readb(&(alpr_ndfc->data))) return i; return 0; } -static int pdnb3_nand_dev_ready(struct mtd_info *mtd) +static int alpr_nand_dev_ready(struct mtd_info *mtd) { -#if 1 volatile u_char val; -/*printf("%s aufruf\n", __FUNCTION__);*/ /* * Blocking read to wait for NAND to be ready */ - val = alpr_read(&(alpr_ndfc->addr_wait)); + val = readb(&(alpr_ndfc->addr_wait)); /* * Return always true */ return 1; -#else - u8 hwctl_org = hwctl; - unsigned long timeo; - u8 val; - - hwctl = 0x01; - pdnb3_nand_write_byte (mtd, NAND_CMD_STATUS); - hwctl = hwctl_org; - - reset_timer(); - while (1) { - if (get_timer(0) > timeo) { - printf("Timeout!"); - return 0; - } - -val = pdnb3_nand_read_byte(mtd); -/*printf("%s val: %x\n", __FUNCTION__, val);*/ - if (val & NAND_STATUS_READY) - break; - } - return 1; -#endif - -} - -static void alpr_select_chip(struct mtd_info *mtd, int chip) -{ - alpr_chip = chip; -} - -static int alpr_nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) -{ - unsigned long timeo; - - if (state == FL_ERASING) - timeo = CFG_HZ * 400; - else - timeo = CFG_HZ * 20; - - if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) - this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1); - else - this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); - - reset_timer(); - - while (1) { - if (get_timer(0) > timeo) { - printf("Timeout!"); - return 0; - } - - if (this->read_byte(mtd) & NAND_STATUS_READY) - break; - } - return this->read_byte(mtd); } void board_nand_init(struct nand_chip *nand) @@ -252,20 +160,14 @@ void board_nand_init(struct nand_chip *nand) nand->eccmode = NAND_ECC_SOFT; - /* Set address of NAND IO lines (Using Linear Data Access Region) */ - nand->IO_ADDR_R = (void __iomem *) ((ulong) alpr_ndfc + 0x10); - nand->IO_ADDR_W = (void __iomem *) ((ulong) alpr_ndfc + 0x10); /* Reference hardware control function */ - nand->hwcontrol = pdnb3_nand_hwcontrol; + nand->hwcontrol = alpr_nand_hwcontrol; /* Set command delay time */ - nand->hwcontrol = pdnb3_nand_hwcontrol; - nand->write_byte = pdnb3_nand_write_byte; - nand->read_byte = pdnb3_nand_read_byte; - nand->write_buf = pdnb3_nand_write_buf; - nand->read_buf = pdnb3_nand_read_buf; - nand->verify_buf = pdnb3_nand_verify_buf; - nand->dev_ready = pdnb3_nand_dev_ready; - nand->select_chip = alpr_select_chip; - nand->waitfunc = alpr_nand_wait; + nand->write_byte = alpr_nand_write_byte; + nand->read_byte = alpr_nand_read_byte; + nand->write_buf = alpr_nand_write_buf; + nand->read_buf = alpr_nand_read_buf; + nand->verify_buf = alpr_nand_verify_buf; + nand->dev_ready = alpr_nand_dev_ready; } #endif diff --git a/board/prodrive/common/flash.c b/board/prodrive/common/flash.c index 8630cc16642..363631fd84f 100644 --- a/board/prodrive/common/flash.c +++ b/board/prodrive/common/flash.c @@ -48,6 +48,7 @@ void flash_print_info(flash_info_t *info) case FLASH_MAN_AMD: printf ("AMD "); break; case FLASH_MAN_FUJ: printf ("FUJITSU "); break; case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("ST "); break; case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); break; default: printf ("Unknown Vendor "); break; } @@ -156,6 +157,9 @@ static ulong flash_get_size(vu_long *addr, flash_info_t *info) case (CFG_FLASH_WORD_SIZE)SST_MANUFACT: info->flash_id = FLASH_MAN_SST; break; + case (CFG_FLASH_WORD_SIZE)STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT: info->flash_id = FLASH_MAN_EXCEL; break; |