[U-Boot] [PATCH v2 0/5] Add multi-chips support for NAND, FSL-UPM and TQM8548

The following patch series intends to support the Micron multi-chip NAND device MT29F8G08FAB on the TQM8548 modules from TQ-Components. To offer this multi-chip device as one single device to the user, multi-chip device has been added to the MTD NAND layer and the FSL-UPM-NAND driver.
The TQM8548 support is based on the following patch series sent a few minutes ago:
[PATCH 0/8] MPC85xx: Support for TQM8548-AG and TQM8548-BE
Wolfgang.

This patch adds support for NAND_MAX_CHIPS to the MTD NAND layer. Multi-chips devices are displayed as shown:
Device 0: 2x NAND 512MiB 3,3V 8-bit, sector size 128 KiB
Signed-off-by: Wolfgang Grandegger wg@grandegger.com --- common/cmd_nand.c | 21 +++++++++++++++------ drivers/mtd/nand/nand.c | 6 +++++- drivers/mtd/nand/nand_base.c | 2 ++ 3 files changed, 22 insertions(+), 7 deletions(-)
Index: u-boot/common/cmd_nand.c =================================================================== --- u-boot.orig/common/cmd_nand.c +++ u-boot/common/cmd_nand.c @@ -205,6 +205,17 @@ static void do_nand_status(nand_info_t * } #endif
+static void nand_print_info(int idx) +{ + nand_info_t *nand = &nand_info[idx]; + struct nand_chip *chip = nand->priv; + printf("Device %d: ", idx); + if (chip->numchips > 1) + printf("%dx ", chip->numchips); + printf("%s, sector size %u KiB\n", + nand->name, nand->erasesize >> 10); +} + int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret = 0; @@ -233,9 +244,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, putc('\n'); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { if (nand_info[i].name) - printf("Device %d: %s, sector size %u KiB\n", - i, nand_info[i].name, - nand_info[i].erasesize >> 10); + nand_print_info(i); } return 0; } @@ -243,12 +252,12 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, if (strcmp(cmd, "device") == 0) {
if (argc < 3) { + putc('\n'); if ((nand_curr_device < 0) || (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE)) - puts("\nno devices available\n"); + puts("no devices available\n"); else - printf("\nDevice %d: %s\n", nand_curr_device, - nand_info[nand_curr_device].name); + nand_print_info(nand_curr_device); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); Index: u-boot/drivers/mtd/nand/nand.c =================================================================== --- u-boot.orig/drivers/mtd/nand/nand.c +++ u-boot/drivers/mtd/nand/nand.c @@ -41,11 +41,15 @@ static const char default_nand_name[] = static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) { + int maxchips = CONFIG_SYS_NAND_MAX_CHIPS; + + if (maxchips < 1) + maxchips = 1; mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; if (board_nand_init(nand) == 0) { - if (nand_scan(mtd, 1) == 0) { + if (nand_scan(mtd, maxchips) == 0) { if (!mtd->name) mtd->name = (char *)default_nand_name; else Index: u-boot/drivers/mtd/nand/nand_base.c =================================================================== --- u-boot.orig/drivers/mtd/nand/nand_base.c +++ u-boot/drivers/mtd/nand/nand_base.c @@ -2652,8 +2652,10 @@ int nand_scan_ident(struct mtd_info *mtd type->id != chip->read_byte(mtd)) break; } +#ifdef DEBUG if (i > 1) printk(KERN_INFO "%d NAND chips detected\n", i); +#endif
/* Store the number of chips and calc total size for mtd */ chip->numchips = i;

This patch adds support for multi-chip NAND devices to the FSL-UPM driver. The "dev_ready" callback of the "struct fsl_upm_nand" is now called with the argument "chip_nr" to allow testing the proper chip select line. The NAND support of the MPC8360ERDK is updated as well. No other boards are currently using the FSL UPM driver.
Signed-off-by: Wolfgang Grandegger wg@grandegger.com --- board/freescale/mpc8360erdk/nand.c | 2 - drivers/mtd/nand/fsl_upm.c | 44 ++++++++++++++++++++++++++++++------- include/linux/mtd/fsl_upm.h | 4 ++- 3 files changed, 40 insertions(+), 10 deletions(-)
Index: u-boot/drivers/mtd/nand/fsl_upm.c =================================================================== --- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -31,26 +31,45 @@ static void fsl_upm_end_pattern(struct f eieio(); }
-static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, u32 cmd) +static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, + void __iomem *io_addr, u32 mar) { - out_be32(upm->mar, cmd << (32 - width)); + out_be32(upm->mar, mar); switch (width) { case 8: - out_8(upm->io_addr, 0x0); + out_8(io_addr, 0x0); break; case 16: - out_be16(upm->io_addr, 0x0); + out_be16(io_addr, 0x0); break; case 32: - out_be32(upm->io_addr, 0x0); + out_be32(io_addr, 0x0); break; } }
+#if CONFIG_SYS_NAND_MAX_CHIPS > 1 +static void fun_select_chip(struct mtd_info *mtd, int chip_nr) +{ + struct nand_chip *chip = mtd->priv; + struct fsl_upm_nand *fun = chip->priv; + + if (chip_nr >= 0) { + fun->chip_nr = chip_nr; + chip->IO_ADDR_R = chip->IO_ADDR_W = + fun->upm.io_addr + fun->chip_offset * chip_nr; + } else if (chip_nr == -1) { + chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + } +} +#endif + static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct nand_chip *chip = mtd->priv; struct fsl_upm_nand *fun = chip->priv; + void __iomem *io_addr; + u32 mar;
if (!(ctrl & fun->last_ctrl)) { fsl_upm_end_pattern(&fun->upm); @@ -68,7 +87,13 @@ static void fun_cmd_ctrl(struct mtd_info fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); }
- fsl_upm_run_pattern(&fun->upm, fun->width, cmd); + mar = cmd << (32 - fun->width); + io_addr = fun->upm.io_addr; +#if CONFIG_SYS_NAND_MAX_CHIPS > 1 + if (fun->chip_nr > 0) + io_addr += fun->chip_offset * fun->chip_nr; +#endif + fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
/* * Some boards/chips needs this. At least on MPC8360E-RDK we @@ -77,7 +102,7 @@ static void fun_cmd_ctrl(struct mtd_info * 0-2 unexpected busy states per block read. */ if (fun->wait_pattern) { - while (!fun->dev_ready()) + while (!fun->dev_ready(fun->chip_nr)) debug("unexpected busy state\n"); } } @@ -125,7 +150,7 @@ static int nand_dev_ready(struct mtd_inf struct nand_chip *chip = mtd->priv; struct fsl_upm_nand *fun = chip->priv;
- return fun->dev_ready(); + return fun->dev_ready(fun->chip_nr); }
int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun) @@ -139,6 +164,9 @@ int fsl_upm_nand_init(struct nand_chip * chip->chip_delay = fun->chip_delay; chip->ecc.mode = NAND_ECC_SOFT; chip->cmd_ctrl = fun_cmd_ctrl; +#if CONFIG_SYS_NAND_MAX_CHIPS > 1 + chip->select_chip = fun_select_chip; +#endif chip->read_byte = nand_read_byte; chip->read_buf = nand_read_buf; chip->write_buf = nand_write_buf; Index: u-boot/include/linux/mtd/fsl_upm.h =================================================================== --- u-boot.orig/include/linux/mtd/fsl_upm.h +++ u-boot/include/linux/mtd/fsl_upm.h @@ -29,8 +29,10 @@ struct fsl_upm_nand { int upm_cmd_offset; int upm_addr_offset; int wait_pattern; - int (*dev_ready)(void); + int (*dev_ready)(int chip_nr); int chip_delay; + int chip_offset; + int chip_nr;
/* no need to fill */ int last_ctrl; Index: u-boot/board/freescale/mpc8360erdk/nand.c =================================================================== --- u-boot.orig/board/freescale/mpc8360erdk/nand.c +++ u-boot/board/freescale/mpc8360erdk/nand.c @@ -57,7 +57,7 @@ static void upm_setup(struct fsl_upm *up eieio(); }
-static int dev_ready(void) +static int dev_ready(int chip_nr) { if (in_be32(&im->qepio.ioport[4].pdat) & 0x00002000) { debug("nand ready\n");

For the NAND chips on the TQM8548 modules, a special chip-select logic is used. It uses dedicated address lines to be set via UPM machine address register (mar). This patch adds such support to the FSL-UPM driver.
Signed-off-by: Wolfgang Grandegger wg@grandegger.com --- drivers/mtd/nand/fsl_upm.c | 5 ++++- include/linux/mtd/fsl_upm.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-)
Index: u-boot/drivers/mtd/nand/fsl_upm.c =================================================================== --- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -90,8 +90,11 @@ static void fun_cmd_ctrl(struct mtd_info mar = cmd << (32 - fun->width); io_addr = fun->upm.io_addr; #if CONFIG_SYS_NAND_MAX_CHIPS > 1 - if (fun->chip_nr > 0) + if (fun->chip_nr > 0) { io_addr += fun->chip_offset * fun->chip_nr; + if (fun->upm_mar_chip_offset) + mar |= fun->upm_mar_chip_offset * fun->chip_nr; + } #endif fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
Index: u-boot/include/linux/mtd/fsl_upm.h =================================================================== --- u-boot.orig/include/linux/mtd/fsl_upm.h +++ u-boot/include/linux/mtd/fsl_upm.h @@ -28,6 +28,7 @@ struct fsl_upm_nand { int width; int upm_cmd_offset; int upm_addr_offset; + int upm_mar_chip_offset; int wait_pattern; int (*dev_ready)(int chip_nr); int chip_delay;

On Wed, Feb 11, 2009 at 06:38:22PM +0100, Wolfgang Grandegger wrote:
Index: u-boot/drivers/mtd/nand/fsl_upm.c
--- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -90,8 +90,11 @@ static void fun_cmd_ctrl(struct mtd_info mar = cmd << (32 - fun->width); io_addr = fun->upm.io_addr; #if CONFIG_SYS_NAND_MAX_CHIPS > 1
- if (fun->chip_nr > 0)
- if (fun->chip_nr > 0) { io_addr += fun->chip_offset * fun->chip_nr;
if (fun->upm_mar_chip_offset)
mar |= fun->upm_mar_chip_offset * fun->chip_nr;
- }
Any particular reason not to drop the > 0 conditional?
-Scott

Scott Wood wrote:
On Wed, Feb 11, 2009 at 06:38:22PM +0100, Wolfgang Grandegger wrote:
Index: u-boot/drivers/mtd/nand/fsl_upm.c
--- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -90,8 +90,11 @@ static void fun_cmd_ctrl(struct mtd_info mar = cmd << (32 - fun->width); io_addr = fun->upm.io_addr; #if CONFIG_SYS_NAND_MAX_CHIPS > 1
- if (fun->chip_nr > 0)
- if (fun->chip_nr > 0) { io_addr += fun->chip_offset * fun->chip_nr;
if (fun->upm_mar_chip_offset)
mar |= fun->upm_mar_chip_offset * fun->chip_nr;
- }
Any particular reason not to drop the > 0 conditional?
No, apart from saving some space. Should I send an updated patch?
Wolfgang.

Wolfgang Grandegger wrote:
Scott Wood wrote:
On Wed, Feb 11, 2009 at 06:38:22PM +0100, Wolfgang Grandegger wrote:
Index: u-boot/drivers/mtd/nand/fsl_upm.c
--- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -90,8 +90,11 @@ static void fun_cmd_ctrl(struct mtd_info mar = cmd << (32 - fun->width); io_addr = fun->upm.io_addr; #if CONFIG_SYS_NAND_MAX_CHIPS > 1
- if (fun->chip_nr > 0)
- if (fun->chip_nr > 0) { io_addr += fun->chip_offset * fun->chip_nr;
if (fun->upm_mar_chip_offset)
mar |= fun->upm_mar_chip_offset * fun->chip_nr;
- }
Any particular reason not to drop the > 0 conditional?
No, apart from saving some space. Should I send an updated patch?
No, I've applied it. You can send a follow-up patch if you like.
-Scott

Wolfgang Grandegger wrote:
Scott Wood wrote:
On Wed, Feb 11, 2009 at 06:38:22PM +0100, Wolfgang Grandegger wrote:
Index: u-boot/drivers/mtd/nand/fsl_upm.c
--- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -90,8 +90,11 @@ static void fun_cmd_ctrl(struct mtd_info mar = cmd << (32 - fun->width); io_addr = fun->upm.io_addr; #if CONFIG_SYS_NAND_MAX_CHIPS > 1
- if (fun->chip_nr > 0)
- if (fun->chip_nr > 0) { io_addr += fun->chip_offset * fun->chip_nr;
if (fun->upm_mar_chip_offset)
mar |= fun->upm_mar_chip_offset * fun->chip_nr;
- }
Any particular reason not to drop the > 0 conditional?
No, apart from saving some space. Should I send an updated patch?
BTW, it seems to me that the conditional adds to the image size, rather than reducing it...
-Scott

The NAND flash on the TQM8548_BE modules requires a short delay after running the UPM pattern like the MPC8360ERDK board does. The TQM8548_BE requires a further short delay after writing out a buffer. Normally the R/B pin should be checked, but it's not connected on the TQM8548_BE. The corresponding Linux FSL UPM driver uses similar delay points at the same locations. To manage these extra delays in a more general way, I introduced the "wait_flags" field allowing the board-specific driver to specify various types of extra delay.
Signed-off-by: Wolfgang Grandegger wg@grandegger.com --- board/freescale/mpc8360erdk/nand.c | 2 +- drivers/mtd/nand/fsl_upm.c | 37 ++++++++++++++++++++++++++++--------- include/linux/mtd/fsl_upm.h | 6 +++++- 3 files changed, 34 insertions(+), 11 deletions(-)
Index: u-boot/drivers/mtd/nand/fsl_upm.c =================================================================== --- u-boot.orig/drivers/mtd/nand/fsl_upm.c +++ u-boot/drivers/mtd/nand/fsl_upm.c @@ -48,6 +48,20 @@ static void fsl_upm_run_pattern(struct f } }
+static void fun_wait(struct fsl_upm_nand *fun) +{ + if (fun->dev_ready) { + while (!fun->dev_ready(fun->chip_nr)) + debug("unexpected busy state\n"); + } else { + /* + * If the R/B pin is not connected, like on the TQM8548, + * a short delay is necessary. + */ + udelay(1); + } +} + #if CONFIG_SYS_NAND_MAX_CHIPS > 1 static void fun_select_chip(struct mtd_info *mtd, int chip_nr) { @@ -99,15 +113,13 @@ static void fun_cmd_ctrl(struct mtd_info fsl_upm_run_pattern(&fun->upm, fun->width, io_addr, mar);
/* - * Some boards/chips needs this. At least on MPC8360E-RDK we - * need it. Probably weird chip, because I don't see any need - * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are - * 0-2 unexpected busy states per block read. + * Some boards/chips needs this. At least the MPC8360E-RDK and + * TQM8548 need it. Probably weird chip, because I don't see + * any need for this on MPC8555E + Samsung K9F1G08U0A. Usually + * here are 0-2 unexpected busy states per block read. */ - if (fun->wait_pattern) { - while (!fun->dev_ready(fun->chip_nr)) - debug("unexpected busy state\n"); - } + if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN) + fun_wait(fun); }
static u8 nand_read_byte(struct mtd_info *mtd) @@ -121,9 +133,16 @@ static void nand_write_buf(struct mtd_in { int i; struct nand_chip *chip = mtd->priv; + struct fsl_upm_nand *fun = chip->priv;
- for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { out_8(chip->IO_ADDR_W, buf[i]); + if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE) + fun_wait(fun); + } + + if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BUFFER) + fun_wait(fun); }
static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) Index: u-boot/include/linux/mtd/fsl_upm.h =================================================================== --- u-boot.orig/include/linux/mtd/fsl_upm.h +++ u-boot/include/linux/mtd/fsl_upm.h @@ -15,6 +15,10 @@
#include <linux/mtd/nand.h>
+#define FSL_UPM_WAIT_RUN_PATTERN 0x1 +#define FSL_UPM_WAIT_WRITE_BYTE 0x2 +#define FSL_UPM_WAIT_WRITE_BUFFER 0x4 + struct fsl_upm { void __iomem *mdr; void __iomem *mxmr; @@ -29,7 +33,7 @@ struct fsl_upm_nand { int upm_cmd_offset; int upm_addr_offset; int upm_mar_chip_offset; - int wait_pattern; + int wait_flags; int (*dev_ready)(int chip_nr); int chip_delay; int chip_offset; Index: u-boot/board/freescale/mpc8360erdk/nand.c =================================================================== --- u-boot.orig/board/freescale/mpc8360erdk/nand.c +++ u-boot/board/freescale/mpc8360erdk/nand.c @@ -76,7 +76,7 @@ static struct fsl_upm_nand fun = { .upm_cmd_offset = 8, .upm_addr_offset = 16, .dev_ready = dev_ready, - .wait_pattern = 1, + .wait_flags = FSL_UPM_WAIT_RUN_PATTERN, .chip_delay = 50, };

This patches configures the NAND UPM-FSL driver with multi-chip support for the Micron MT29F8G08FAB NAND flash memory on the TQM8548 modules.
Signed-off-by: Wolfgang Grandegger wg@grandegger.com --- board/tqc/tqm85xx/nand.c | 5 ++++- include/configs/TQM85xx.h | 32 +++++++------------------------- 2 files changed, 11 insertions(+), 26 deletions(-)
Index: u-boot/board/tqc/tqm85xx/nand.c =================================================================== --- u-boot.orig/board/tqc/tqm85xx/nand.c +++ u-boot/board/tqc/tqm85xx/nand.c @@ -385,7 +385,7 @@ static void upmb_write (u_char addr, ulo MxMR_OP_WARR | (addr & MxMR_MAD_MSK));
/* dummy access to perform write */ - out_8 ((void __iomem *)CONFIG_SYS_NAND0_BASE, 0); + out_8 ((void __iomem *)CONFIG_SYS_NAND_BASE, 0);
clrbits_be32(&lbc->mbmr, MxMR_OP_WARR); } @@ -446,7 +446,10 @@ static struct fsl_upm_nand fun = { .width = 8, .upm_cmd_offset = 0x08, .upm_addr_offset = 0x10, + .upm_mar_chip_offset = CONFIG_SYS_NAND_CS_DIST, + .chip_offset = CONFIG_SYS_NAND_CS_DIST, .chip_delay = NAND_BIG_DELAY_US, + .wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BUFFER, };
void board_nand_select_device (struct nand_chip *nand, int chip) Index: u-boot/include/configs/TQM85xx.h =================================================================== --- u-boot.orig/include/configs/TQM85xx.h +++ u-boot/include/configs/TQM85xx.h @@ -371,35 +371,17 @@ #define CONFIG_SYS_NAND_CS_DIST 0x200
#define CONFIG_SYS_NAND_SIZE 0x8000 -#define CONFIG_SYS_NAND0_BASE (CONFIG_SYS_CCSRBAR + 0x03010000) -#define CONFIG_SYS_NAND1_BASE (CONFIG_SYS_NAND0_BASE + CONFIG_SYS_NAND_CS_DIST) -#define CONFIG_SYS_NAND2_BASE (CONFIG_SYS_NAND1_BASE + CONFIG_SYS_NAND_CS_DIST) -#define CONFIG_SYS_NAND3_BASE (CONFIG_SYS_NAND2_BASE + CONFIG_SYS_NAND_CS_DIST) - -#define CONFIG_SYS_MAX_NAND_DEVICE 2 /* Max number of NAND devices */ - -#if (CONFIG_SYS_MAX_NAND_DEVICE == 1) -#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE } -#elif (CONFIG_SYS_MAX_NAND_DEVICE == 2) -#define CONFIG_SYS_NAND_QUIET_TEST 1 -#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE, \ - CONFIG_SYS_NAND1_BASE, \ -} -#elif (CONFIG_SYS_MAX_NAND_DEVICE == 4) -#define CONFIG_SYS_NAND_QUIET_TEST 1 -#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND0_BASE, \ - CONFIG_SYS_NAND1_BASE, \ - CONFIG_SYS_NAND2_BASE, \ - CONFIG_SYS_NAND3_BASE, \ -} -#endif +#define CONFIG_SYS_NAND_BASE (CONFIG_SYS_CCSRBAR + 0x03010000) + +#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define CONFIG_SYS_NAND_MAX_CHIPS 2 /* Number of chips per device */
/* CS3 for NAND Flash */ -#define CONFIG_SYS_BR3_PRELIM ((CONFIG_SYS_NAND0_BASE & BR_BA) | BR_PS_8 | \ - BR_MS_UPMB | BR_V) +#define CONFIG_SYS_BR3_PRELIM ((CONFIG_SYS_NAND_BASE & BR_BA) | \ + BR_PS_8 | BR_MS_UPMB | BR_V) #define CONFIG_SYS_OR3_PRELIM (P2SZ_TO_AM(CONFIG_SYS_NAND_SIZE) | OR_UPM_BI)
-#define NAND_BIG_DELAY_US 25 /* max tR for Samsung devices */ +#define NAND_BIG_DELAY_US 25 /* max tR for Samsung devices */
#endif /* CONFIG_NAND */

On Wed, Feb 11, 2009 at 06:38:19PM +0100, Wolfgang Grandegger wrote:
The following patch series intends to support the Micron multi-chip NAND device MT29F8G08FAB on the TQM8548 modules from TQ-Components. To offer this multi-chip device as one single device to the user, multi-chip device has been added to the MTD NAND layer and the FSL-UPM-NAND driver.
The TQM8548 support is based on the following patch series sent a few minutes ago:
[PATCH 0/8] MPC85xx: Support for TQM8548-AG and TQM8548-BE
Wolfgang.
Applied 1-5 to u-boot-nand-flash/next, thanks!
-Scott
participants (2)
-
Scott Wood
-
Wolfgang Grandegger