aliases {
spi0 = &spi0;
+ spi1 = &spi1;
ethernet0 = ð0;
};
reg = <0>; /* Chip select 0 */
spi-max-frequency = <27777777>;
};
+
+ fpga@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-generic-device";
+ reg = <1>; /* Chip select 1 */
+ spi-max-frequency = <27777777>;
+ };
+ };
+
+ spi1: spi@10680 {
+ status = "okay";
+
+ fpga@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-generic-device";
+ reg = <2>; /* Chip select 2 */
+ spi-max-frequency = <27777777>;
+ };
};
};
};
u32 din; /* 0x1060c */
u32 irq_cause; /* 0x10610 */
u32 irq_mask; /* 0x10614 */
+ u32 timing1; /* 0x10618 */
+ u32 timing2; /* 0x1061c */
+ u32 dw_cfg; /* 0x10620 - Direct Write Configuration */
};
/* They are used to define CONFIG_SYS_KW_SPI_MPP
CPU_ATTR_DRAM_CS3 = 0x07,
CPU_ATTR_NANDFLASH = 0x2f,
CPU_ATTR_SPIFLASH = 0x1e,
+ CPU_ATTR_SPI0_CS0 = 0x1e,
+ CPU_ATTR_SPI0_CS1 = 0x5e,
+ CPU_ATTR_SPI1_CS2 = 0x9a,
CPU_ATTR_BOOTROM = 0x1d,
CPU_ATTR_PCIE_IO = 0xe0,
CPU_ATTR_PCIE_MEM = 0xe8,
+++ /dev/null
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
#
obj-y := theadorable.o
+obj-y += fpga.o
--- /dev/null
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/arch-mvebu/spi.h>
+#include "theadorable.h"
+
+/*
+ * FPGA programming support
+ */
+static int fpga_pre_fn(int cookie)
+{
+ int gpio_config = COOKIE2CONFIG(cookie);
+ int gpio_done = COOKIE2DONE(cookie);
+ int ret;
+
+ debug("%s (%d): cookie=%08x gpio_config=%d gpio_done=%d\n",
+ __func__, __LINE__, cookie, gpio_config, gpio_done);
+
+ /* Configure config pin */
+ /* Set to output */
+ ret = gpio_request(gpio_config, "CONFIG");
+ if (ret < 0)
+ return ret;
+ gpio_direction_output(gpio_config, 1);
+
+ /* Configure done pin */
+ /* Set to input */
+ ret = gpio_request(gpio_done, "DONE");
+ if (ret < 0)
+ return ret;
+
+ gpio_direction_input(gpio_done);
+
+ return 0;
+}
+
+static int fpga_config_fn(int assert, int flush, int cookie)
+{
+ int gpio_config = COOKIE2CONFIG(cookie);
+
+ debug("%s (%d): cookie=%08x gpio_config=%d\n",
+ __func__, __LINE__, cookie, gpio_config);
+
+ if (assert)
+ gpio_set_value(gpio_config, 1);
+ else
+ gpio_set_value(gpio_config, 0);
+
+ return 0;
+}
+
+static int fpga_write_fn(const void *buf, size_t len, int flush, int cookie)
+{
+ int spi_bus = COOKIE2SPI_BUS(cookie);
+ int spi_dev = COOKIE2SPI_DEV(cookie);
+ struct kwspi_registers *reg;
+ u32 control_reg;
+ u32 config_reg;
+ void *dst;
+
+ /*
+ * Write data to FPGA attached to SPI bus via SPI direct write.
+ * This results in the fastest and easiest way to program the
+ * bitstream into the FPGA.
+ */
+ debug("%s (%d): cookie=%08x spi_bus=%d spi_dev=%d\n",
+ __func__, __LINE__, cookie, spi_bus, spi_dev);
+
+ if (spi_bus == 0) {
+ reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10600);
+ dst = (void *)SPI_BUS0_DEV1_BASE;
+ } else {
+ reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10680);
+ dst = (void *)SPI_BUS1_DEV2_BASE;
+ }
+
+ /* Configure SPI controller for direct access mode */
+ control_reg = readl(®->ctrl);
+ config_reg = readl(®->cfg);
+ writel(0x00000214, ®->cfg); /* 27MHz clock */
+ writel(0x00000000, ®->dw_cfg); /* don't de-asset CS */
+ writel(KWSPI_CSN_ACT, ®->ctrl); /* activate CS */
+
+ /* Copy data to the SPI direct mapped window */
+ memcpy(dst, buf, len);
+
+ /* Restore original register values */
+ writel(control_reg, ®->ctrl);
+ writel(config_reg, ®->cfg);
+
+ return 0;
+}
+
+/* Returns the state of CONF_DONE Pin */
+static int fpga_done_fn(int cookie)
+{
+ int gpio_done = COOKIE2DONE(cookie);
+ unsigned long ts;
+
+ debug("%s (%d): cookie=%08x gpio_done=%d\n",
+ __func__, __LINE__, cookie, gpio_done);
+
+ ts = get_timer(0);
+ do {
+ if (gpio_get_value(gpio_done))
+ return 0;
+ } while (get_timer(ts) < 1000);
+
+ /* timeout so return error */
+ return -ENODEV;
+}
+
+static altera_board_specific_func stratixv_fns = {
+ .pre = fpga_pre_fn,
+ .config = fpga_config_fn,
+ .write = fpga_write_fn,
+ .done = fpga_done_fn,
+};
+
+static Altera_desc altera_fpga[] = {
+ {
+ /* Family */
+ Altera_StratixV,
+ /* Interface type */
+ passive_serial,
+ /* No limitation as additional data will be ignored */
+ -1,
+ /* Device function table */
+ (void *)&stratixv_fns,
+ /* Base interface address specified in driver */
+ NULL,
+ /* Cookie implementation */
+ /*
+ * In this 32bit word the following information is coded:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+ FPGA_COOKIE(0, 1, 26, 7)
+ },
+ {
+ /* Family */
+ Altera_StratixV,
+ /* Interface type */
+ passive_serial,
+ /* No limitation as additional data will be ignored */
+ -1,
+ /* Device function table */
+ (void *)&stratixv_fns,
+ /* Base interface address specified in driver */
+ NULL,
+ /* Cookie implementation */
+ /*
+ * In this 32bit word the following information is coded:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+ FPGA_COOKIE(1, 2, 29, 9)
+ },
+};
+
+/* Add device descriptor to FPGA device table */
+void board_fpga_add(void)
+{
+ int i;
+
+ fpga_init();
+ for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
+ fpga_add(fpga_altera, &altera_fpga[i]);
+}
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
+#include <linux/mbus.h>
#ifdef CONFIG_NET
#include <netdev.h>
#endif
+#include "theadorable.h"
#include "../drivers/ddr/marvell/axp/ddr3_hw_training.h"
#include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
/* adress of boot parameters */
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+ /*
+ * Map SPI devices via MBUS so that they can be accessed via
+ * the SPI direct access mode
+ */
+ mbus_dt_setup_win(&mbus_state, SPI_BUS0_DEV1_BASE, SPI_BUS0_DEV1_SIZE,
+ CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI0_CS1);
+ mbus_dt_setup_win(&mbus_state, SPI_BUS1_DEV2_BASE, SPI_BUS0_DEV1_SIZE,
+ CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI1_CS2);
+
return 0;
}
{
puts("Board: theadorable\n");
+ board_fpga_add();
+
return 0;
}
--- /dev/null
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* Base addresses for the SPI direct access mode */
+#define SPI_BUS0_DEV1_BASE 0xe0000000
+#define SPI_BUS0_DEV1_SIZE (1 << 20)
+#define SPI_BUS1_DEV2_BASE (SPI_BUS0_DEV1_BASE + SPI_BUS0_DEV1_SIZE)
+
+void board_fpga_add(void);
CONFIG_ARCH_MVEBU=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
CONFIG_ARCH_MVEBU=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_SF=y
-# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NET is not set
# CONFIG_CMD_NFS is not set
SAR1_CPU_CORE_OFFSET;
switch (soc_num) {
case 0x3:
- reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
- reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
case 0x1:
reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
case 0x0:
obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
endif
{ Altera_StratixII, "StratixII", StratixII_load,
StratixII_dump, StratixII_info },
#endif
+#if defined(CONFIG_FPGA_STRATIX_V)
+ { Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
+#endif
#if defined(CONFIG_FPGA_SOCFPGA)
{ Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
#endif
--- /dev/null
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+/* Write the RBF data to FPGA via SPI */
+static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
+ unsigned long rbf_size)
+{
+ struct spi_slave *slave;
+ int ret;
+
+ debug("%s (%d): data=%p size=%ld\n",
+ __func__, __LINE__, rbf_data, rbf_size);
+
+ /* FIXME: How to get the max. SPI clock and SPI mode? */
+ slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
+ if (!slave)
+ return -1;
+
+ if (spi_claim_bus(slave))
+ return -1;
+
+ ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+
+ spi_release_bus(slave);
+
+ return ret;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ altera_board_specific_func *pfns = desc->iface_fns;
+ int cookie = desc->cookie;
+ int spi_bus;
+ int spi_dev;
+ int ret = 0;
+
+ if ((u32)rbf_data & 0x3) {
+ puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+ return -EINVAL;
+ }
+
+ /* Run the pre configuration function if there is one */
+ if (pfns->pre)
+ (pfns->pre)(cookie);
+
+ /* Establish the initial state */
+ if (pfns->config) {
+ /* De-assert nCONFIG */
+ (pfns->config)(false, true, cookie);
+
+ /* nConfig minimum low pulse width is 2us */
+ udelay(200);
+
+ /* Assert nCONFIG */
+ (pfns->config)(true, true, cookie);
+
+ /* nCONFIG high to first rising clock on DCLK min 1506 us */
+ udelay(1600);
+ }
+
+ /* Write the RBF data to FPGA */
+ if (pfns->write) {
+ /*
+ * Use board specific data function to write bitstream
+ * into the FPGA
+ */
+ ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
+ } else {
+ /*
+ * Use common SPI functions to write bitstream into the
+ * FPGA
+ */
+ spi_bus = COOKIE2SPI_BUS(cookie);
+ spi_dev = COOKIE2SPI_DEV(cookie);
+ ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
+ }
+ if (ret)
+ return ret;
+
+ /* Check done pin */
+ if (pfns->done) {
+ ret = (pfns->done)(cookie);
+
+ if (ret)
+ printf("Error: DONE not set (ret=%d)!\n", ret);
+ }
+
+ return ret;
+}
help
Say yes here to support Microchip PIC32 GPIOs.
+config MVEBU_GPIO
+ bool "Marvell MVEBU GPIO driver"
+ depends on DM_GPIO && ARCH_MVEBU
+ default y
+ help
+ Say yes here to support Marvell MVEBU (Armada XP/38x) GPIOs.
+
endmenu
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o
obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o
+obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o
--- /dev/null
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MVEBU_GPIOS_PER_BANK 32
+
+struct mvebu_gpio_regs {
+ u32 data_out;
+ u32 io_conf;
+ u32 blink_en;
+ u32 in_pol;
+ u32 data_in;
+};
+
+struct mvebu_gpio_priv {
+ struct mvebu_gpio_regs *regs;
+ char name[2];
+};
+
+static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ setbits_le32(®s->io_conf, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio,
+ int value)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ clrbits_le32(®s->io_conf, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+ u32 val;
+
+ val = readl(®s->io_conf) & BIT(gpio);
+ if (val)
+ return GPIOF_INPUT;
+ else
+ return GPIOF_OUTPUT;
+}
+
+static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio,
+ int value)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ if (value)
+ setbits_le32(®s->data_out, BIT(gpio));
+ else
+ clrbits_le32(®s->data_out, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ return !!(readl(®s->data_in) & BIT(gpio));
+}
+
+static int mvebu_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+
+ priv->regs = (struct mvebu_gpio_regs *)dev_get_addr(dev);
+ uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
+ priv->name[0] = 'A' + dev->req_seq;
+ uc_priv->bank_name = priv->name;
+
+ return 0;
+}
+
+static const struct dm_gpio_ops mvebu_gpio_ops = {
+ .direction_input = mvebu_gpio_direction_input,
+ .direction_output = mvebu_gpio_direction_output,
+ .get_function = mvebu_gpio_get_function,
+ .get_value = mvebu_gpio_get_value,
+ .set_value = mvebu_gpio_set_value,
+};
+
+static const struct udevice_id mvebu_gpio_ids[] = {
+ { .compatible = "marvell,orion-gpio" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_mvebu) = {
+ .name = "gpio_mvebu",
+ .id = UCLASS_GPIO,
+ .of_match = mvebu_gpio_ids,
+ .ops = &mvebu_gpio_ops,
+ .probe = mvebu_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct mvebu_gpio_priv),
+};
#ifndef _ALTERA_H_
#define _ALTERA_H_
+/*
+ * For the StratixV FPGA programming via SPI, the following
+ * information is coded in the 32bit cookie:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+#define FPGA_COOKIE(bus, dev, config, done) \
+ (((bus) << 24) | ((dev) << 16) | ((config) << 8) | (done))
+#define COOKIE2SPI_BUS(c) (((c) >> 24) & 0xff)
+#define COOKIE2SPI_DEV(c) (((c) >> 16) & 0xff)
+#define COOKIE2CONFIG(c) (((c) >> 8) & 0xff)
+#define COOKIE2DONE(c) ((c) & 0xff)
+
enum altera_iface {
/* insert all new types after this */
min_altera_iface_type,
Altera_CYC2,
/* StratixII Family */
Altera_StratixII,
+ /* StratixV Family */
+ Altera_StratixV,
/* SoCFPGA Family */
Altera_SoCFPGA,
Altera_done_fn done;
Altera_clk_fn clk;
Altera_data_fn data;
+ Altera_write_fn write;
Altera_abort_fn abort;
Altera_post_fn post;
} altera_board_specific_func;
int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
#endif
+#ifdef CONFIG_FPGA_STRATIX_V
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
+#endif
+
#endif /* _ALTERA_H_ */
#define CONFIG_MTDPARTS \
"orion_nand:512K(uboot)," \
- "512K(env),1M(script),6M(kernel)," \
- "12M(ramdisk),4M(spare),-(rootfs)\0"
+ "512K(env),4M(kernel)," \
+ "-(rootfs)\0"
#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console" \
"=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \
- "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \
+ "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x400000\0" \
"x_bootcmd_usb=usb start\0" \
"x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0"
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_CMD_BMP
+/* FPGA programming support */
+#define CONFIG_FPGA
+#define CONFIG_FPGA_ALTERA
+#define CONFIG_FPGA_STRATIX_V
+
/*
* mv-common.h should be defined after CMD configs since it used them
* to enable certain macros
static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
+static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO;
static void
kwboot_printv(const char *fmt, ...)
break;
do {
- rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
+ rc = kwboot_tty_recv(fd, &c, 1, blk_rsp_timeo);
if (rc)
break;
kwboot_usage(FILE *stream, char *progname)
{
fprintf(stream,
- "Usage: %s [-d | -a | -q <req-delay> | -s <resp-timeo> | -b <image> | -D <image> ] [ -t ] [-B <baud> ] <TTY>\n",
+ "Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
progname);
fprintf(stream, "\n");
fprintf(stream,
fprintf(stream, " -a: use timings for Armada XP\n");
fprintf(stream, " -q <req-delay>: use specific request-delay\n");
fprintf(stream, " -s <resp-timeo>: use specific response-timeout\n");
+ fprintf(stream,
+ " -o <block-timeo>: use specific xmodem block timeout\n");
fprintf(stream, "\n");
fprintf(stream, " -t: mini terminal\n");
fprintf(stream, "\n");
kwboot_verbose = isatty(STDOUT_FILENO);
do {
- int c = getopt(argc, argv, "hb:ptaB:dD:q:s:");
+ int c = getopt(argc, argv, "hb:ptaB:dD:q:s:o:");
if (c < 0)
break;
msg_rsp_timeo = atoi(optarg);
break;
+ case 'o':
+ blk_rsp_timeo = atoi(optarg);
+ break;
+
case 'B':
speed = kwboot_tty_speed(atoi(optarg));
if (speed == -1)