Antony Pavlov (9): RISC-V: make it possible to run nmon from PBL C code RISC-V: boards: erizo: make it possible to use nmon serial: add litex UART driver gpio: add driver for 74xx-ICs with MMIO access spi: add litex spiflash driver net: add LiteEth driver RISC-V: add initial LiteX SoC support RISC-V: add litex-linux board support RISC-V: add litex_linux_defconfig arch/riscv/Kconfig | 9 + arch/riscv/Makefile | 1 + arch/riscv/boards/Makefile | 1 + arch/riscv/boards/erizo/lowlevel.c | 3 + arch/riscv/boards/litex-linux/Makefile | 3 + arch/riscv/boards/litex-linux/lowlevel.c | 20 + arch/riscv/boot/Makefile | 1 + arch/riscv/boot/nmon_entry.S | 13 + arch/riscv/configs/litex_linux_defconfig | 76 ++++ arch/riscv/dts/Makefile | 1 + arch/riscv/dts/litex-linux.dts | 96 +++++ arch/riscv/dts/litex_soc_linux.dtsi | 49 +++ arch/riscv/include/asm/riscv_nmon.h | 33 +- arch/riscv/mach-litex/Kconfig | 11 + arch/riscv/mach-litex/Makefile | 3 + arch/riscv/mach-litex/include/mach/debug_ll.h | 124 ++++++ drivers/gpio/Kconfig | 14 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-74xx-mmio.c | 170 ++++++++ drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/liteeth.c | 376 ++++++++++++++++++ drivers/serial/Makefile | 1 + drivers/serial/serial_litex.c | 96 +++++ drivers/spi/Kconfig | 3 + drivers/spi/Makefile | 1 + drivers/spi/litex_spiflash.c | 242 +++++++++++ images/Makefile.riscv | 4 + 28 files changed, 1344 insertions(+), 17 deletions(-) create mode 100644 arch/riscv/boards/litex-linux/Makefile create mode 100644 arch/riscv/boards/litex-linux/lowlevel.c create mode 100644 arch/riscv/boot/nmon_entry.S create mode 100644 arch/riscv/configs/litex_linux_defconfig create mode 100644 arch/riscv/dts/litex-linux.dts create mode 100644 arch/riscv/dts/litex_soc_linux.dtsi create mode 100644 arch/riscv/mach-litex/Kconfig create mode 100644 arch/riscv/mach-litex/Makefile create mode 100644 arch/riscv/mach-litex/include/mach/debug_ll.h create mode 100644 drivers/gpio/gpio-74xx-mmio.c create mode 100644 drivers/net/liteeth.c create mode 100644 drivers/serial/serial_litex.c create mode 100644 drivers/spi/litex_spiflash.c -- Cc: Florent Kermarrec <florent@enjoy-digital.fr> Cc: Marek Czerski <m.czerski@ap-tech.pl> 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
After migrating to PBL we can't use nmon assembler macro in C code anymore. Some changes are introduced to invoke nmon from PBL C code: * use 'lla' macro instruction instead of 'la'; * don't touch the 'ra' register, use 'a2' instead; * add wrapper C function for nmon. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- arch/riscv/boot/Makefile | 1 + arch/riscv/boot/nmon_entry.S | 13 ++++++++++++ arch/riscv/include/asm/riscv_nmon.h | 33 ++++++++++++++--------------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index 968a826d16..80f63a4a0a 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += start.o pbl-y += entry.o uncompress.o +pbl-y += nmon_entry.o pbl-$(CONFIG_BOARD_GENERIC_DT) += board-dt-2nd.o diff --git a/arch/riscv/boot/nmon_entry.S b/arch/riscv/boot/nmon_entry.S new file mode 100644 index 0000000000..9b30b50627 --- /dev/null +++ b/arch/riscv/boot/nmon_entry.S @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/linkage.h> +#include <asm/sections.h> + +#include "mach/debug_ll.h" +#include "asm/riscv_nmon.h" + +.section .text_bare_init + +ENTRY(__barebox_nmon_entry) + riscv_nmon + ret +ENDPROC(__barebox_nmon_entry) diff --git a/arch/riscv/include/asm/riscv_nmon.h b/arch/riscv/include/asm/riscv_nmon.h index caf213cdd8..11b19ab35b 100644 --- a/arch/riscv/include/asm/riscv_nmon.h +++ b/arch/riscv/include/asm/riscv_nmon.h @@ -20,9 +20,8 @@ .macro nmon_outs msg - la a1, \msg - - jal _nmon_outs + lla a1, \msg + jal a2, _nmon_outs .endm @@ -73,7 +72,7 @@ nmon_main: li a0, 'q' bne s0, a0, 3f - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 j nmon_exit @@ -90,12 +89,12 @@ nmon_main: j nmon_main_help nmon_cmd_d: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw nmon_outs msg_nl @@ -105,28 +104,28 @@ nmon_cmd_d: j nmon_main nmon_cmd_w: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw move s2, s0 li a0, ' ' - jal _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_outc_a0 + jal a2, _nmon_gethexw sw s0, 0(s2) j nmon_main nmon_cmd_g: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw move s2, s0 nmon_outs msg_nl @@ -136,7 +135,7 @@ nmon_cmd_g: _nmon_outc_a0: debug_ll_outc_a0 - jr ra + jr a2 _nmon_outs: @@ -202,7 +201,7 @@ _get_hex_digit: move s0, t2 _nmon_jr_ra_exit: - jr ra + jr a2 msg_prompt: .asciz "\r\nnmon> " -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- arch/riscv/boards/erizo/lowlevel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/boards/erizo/lowlevel.c b/arch/riscv/boards/erizo/lowlevel.c index d9edb530b7..185de6ed77 100644 --- a/arch/riscv/boards/erizo/lowlevel.c +++ b/arch/riscv/boards/erizo/lowlevel.c @@ -7,8 +7,11 @@ ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) { extern char __dtb_z_erizo_generic_start[]; + extern void __barebox_nmon_entry(void); debug_ll_ns16550_init(); + if (IS_ENABLED(CONFIG_NMON)) + __barebox_nmon_entry(); putc_ll('>'); /* On POR, we are running from read-only memory here. */ -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- drivers/serial/Makefile | 1 + drivers/serial/serial_litex.c | 96 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7ff41cd5c7..95c3387d3e 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o obj-$(CONFIG_DRIVER_SERIAL_LPUART) += serial_lpuart.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o +obj-$(CONFIG_MACH_LITEX) += serial_litex.o diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c new file mode 100644 index 0000000000..dec3d99fd0 --- /dev/null +++ b/drivers/serial/serial_litex.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2. +/* + * Copyright (C) 2019 Antony Pavlov <antonynpavlov@gmail.com> + * + */ + +#include <common.h> +#include <init.h> +#include <malloc.h> +#include <io.h> + +#include <mach/debug_ll.h> + +static inline uint32_t litex_serial_readb(struct console_device *cdev, + uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + return readb(base + offset); +} + +static inline void litex_serial_writeb(struct console_device *cdev, + uint32_t value, uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + writeb(value, base + offset); +} + +static void litex_serial_putc(struct console_device *cdev, char c) +{ + while (litex_serial_readb(cdev, UART_TXFULL)) + ; + + litex_serial_writeb(cdev, c, UART_RXTX); +} + +static int litex_serial_getc(struct console_device *cdev) +{ + int c; + + while (litex_serial_readb(cdev, UART_RXEMPTY)) + ; + + c = litex_serial_readb(cdev, UART_RXTX); + + /* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */ + litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING); + + return c; +} + +static int litex_serial_tstc(struct console_device *cdev) +{ + if (litex_serial_readb(cdev, UART_RXEMPTY)) { + return 0; + } + + return 1; +} + +static int litex_serial_probe(struct device_d *dev) +{ + struct resource *iores; + struct console_device *cdev; + + cdev = xzalloc(sizeof(struct console_device)); + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + dev->priv = IOMEM(iores->start); + cdev->dev = dev; + cdev->tstc = &litex_serial_tstc; + cdev->putc = &litex_serial_putc; + cdev->getc = &litex_serial_getc; + cdev->setbrg = NULL; + + console_register(cdev); + + return 0; +} + +static __maybe_unused struct of_device_id litex_serial_dt_ids[] = { + { + .compatible = "litex,uart", + }, { + /* sentinel */ + } +}; + +static struct driver_d litex_serial_driver = { + .name = "litex-uart", + .probe = litex_serial_probe, + .of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids), +}; +console_platform_driver(litex_serial_driver); -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
This patch adds driver to support GPIO functionality for 74xx-compatible ICs with MMIO access. Compatible models include: 1 bit: 741G125 (Input), 741G74 (Output) 2 bits: 742G125 (Input), 7474 (Output) 4 bits: 74125 (Input), 74175 (Output) 6 bits: 74365 (Input), 74174 (Output) 8 bits: 74244 (Input), 74273 (Output) 16 bits: 741624 (Input), 7416374 (Output) Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Cc: Alexander Shiyan <shc_work@mail.ru> --- drivers/gpio/Kconfig | 14 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-74xx-mmio.c | 170 ++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 261b6e6662..59cb00ff22 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -21,6 +21,20 @@ config GPIO_74164 shift registers. This driver can be used to provide access to more gpio outputs. +config GPIO_74XX_MMIO + tristate "GPIO driver for 74xx-ICs with MMIO access" + depends on OFDEVICE + select GPIO_GENERIC + help + Say yes here to support GPIO functionality for 74xx-compatible ICs + with MMIO access. Compatible models include: + 1 bit: 741G125 (Input), 741G74 (Output) + 2 bits: 742G125 (Input), 7474 (Output) + 4 bits: 74125 (Input), 74175 (Output) + 6 bits: 74365 (Input), 74174 (Output) + 8 bits: 74244 (Input), 74273 (Output) + 16 bits: 741624 (Input), 7416374 (Output) + config GPIO_CLPS711X bool "GPIO support for CLPS711X" depends on ARCH_CLPS711X || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 77dcf58f64..7ece8621d2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIO_74164) += gpio-74164.o +obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o obj-$(CONFIG_MACH_MIPS_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c new file mode 100644 index 0000000000..2c05d022f1 --- /dev/null +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * 74xx MMIO GPIO driver + * + * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> + * + * Ported to barebox from linux-v5.4-rc6 + * Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov@gmail.com> + * + */ + +#include <common.h> +#include <driver.h> +#include <errno.h> +#include <gpio.h> +#include <init.h> +#include <io.h> +#include <malloc.h> + +#include <linux/err.h> +#include <linux/basic_mmio_gpio.h> + +#define MMIO_74XX_DIR_IN (0 << 8) +#define MMIO_74XX_DIR_OUT (1 << 8) +#define MMIO_74XX_BIT_CNT(x) ((x) & 0xff) + +struct mmio_74xx_gpio_priv { + struct bgpio_chip bgc; + unsigned int flags; +}; + +static const struct of_device_id mmio_74xx_gpio_ids[] = { + { + .compatible = "ti,741g125", + .data = (const void *)(MMIO_74XX_DIR_IN | 1), + }, + { + .compatible = "ti,742g125", + .data = (const void *)(MMIO_74XX_DIR_IN | 2), + }, + { + .compatible = "ti,74125", + .data = (const void *)(MMIO_74XX_DIR_IN | 4), + }, + { + .compatible = "ti,74365", + .data = (const void *)(MMIO_74XX_DIR_IN | 6), + }, + { + .compatible = "ti,74244", + .data = (const void *)(MMIO_74XX_DIR_IN | 8), + }, + { + .compatible = "ti,741624", + .data = (const void *)(MMIO_74XX_DIR_IN | 16), + }, + { + .compatible = "ti,741g74", + .data = (const void *)(MMIO_74XX_DIR_OUT | 1), + }, + { + .compatible = "ti,7474", + .data = (const void *)(MMIO_74XX_DIR_OUT | 2), + }, + { + .compatible = "ti,74175", + .data = (const void *)(MMIO_74XX_DIR_OUT | 4), + }, + { + .compatible = "ti,74174", + .data = (const void *)(MMIO_74XX_DIR_OUT | 6), + }, + { + .compatible = "ti,74273", + .data = (const void *)(MMIO_74XX_DIR_OUT | 8), + }, + { + .compatible = "ti,7416374", + .data = (const void *)(MMIO_74XX_DIR_OUT | 16), + }, + { } +}; + +static inline +struct mmio_74xx_gpio_priv *to_mmio_74xx_gpio_priv(struct gpio_chip *gc) +{ + struct bgpio_chip *bgc = + container_of(gc, struct bgpio_chip, gc); + + return container_of(bgc, struct mmio_74xx_gpio_priv, bgc); +} + +static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); + + if (priv->flags & MMIO_74XX_DIR_OUT) + return GPIOF_DIR_OUT; + + return GPIOF_DIR_IN; +} + +static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); + + return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0; +} + +static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); + + if (priv->flags & MMIO_74XX_DIR_OUT) { + gc->ops->set(gc, gpio, val); + return 0; + } + + return -ENOTSUPP; +} + +static int mmio_74xx_gpio_probe(struct device_d *dev) +{ + struct mmio_74xx_gpio_priv *priv; + void __iomem *dat; + int err; + struct gpio_chip *gc; + + priv = xzalloc(sizeof(*priv)); + + err = dev_get_drvdata(dev, (const void **)&priv->flags); + if (err) + return err; + + dat = dev_request_mem_region(dev, 0); + if (IS_ERR(dat)) + return PTR_ERR(dat); + + err = bgpio_init(&priv->bgc, dev, + DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), + dat, NULL, NULL, NULL, NULL, 0); + if (err) + return err; + + gc = &priv->bgc.gc; + gc->ops->direction_input = mmio_74xx_dir_in; + gc->ops->direction_output = mmio_74xx_dir_out; + gc->ops->get_direction = mmio_74xx_get_direction; + gc->ngpio = MMIO_74XX_BIT_CNT(priv->flags); + + dev->priv = priv; + + return gpiochip_add(gc); +} + +static struct driver_d mmio_74xx_gpio_driver = { + .name = "74xx-mmio-gpio", + .of_compatible = DRV_OF_COMPAT(mmio_74xx_gpio_ids), + .probe = mmio_74xx_gpio_probe, +}; + +static int mmio_74xx_gpio_init(void) +{ + return platform_driver_register(&mmio_74xx_gpio_driver); +} +coredevice_initcall(mmio_74xx_gpio_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("74xx MMIO GPIO driver"); -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- drivers/spi/Kconfig | 3 + drivers/spi/Makefile | 1 + drivers/spi/litex_spiflash.c | 242 +++++++++++++++++++++++++++++++++++ 3 files changed, 246 insertions(+) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 323d93efeb..714d30e909 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -74,6 +74,9 @@ config DRIVER_SPI_IMX_2_3 depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6 || ARCH_IMX7 || ARCH_IMX8MQ default y +config DRIVER_SPI_LITEX_SPIFLASH + bool "Litex SPIFLASH bitbang master driver" + config DRIVER_SPI_MXS bool "i.MX (23,28) SPI Master driver" depends on ARCH_IMX28 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 908d514a01..ac95ffc1db 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_DRIVER_SPI_ATH79) += ath79_spi.o obj-$(CONFIG_DRIVER_SPI_GPIO) += gpio_spi.o obj-$(CONFIG_DRIVER_SPI_FSL_QUADSPI) += spi-fsl-qspi.o obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o +obj-$(CONFIG_DRIVER_SPI_LITEX_SPIFLASH) += litex_spiflash.o obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o diff --git a/drivers/spi/litex_spiflash.c b/drivers/spi/litex_spiflash.c new file mode 100644 index 0000000000..2d6858c580 --- /dev/null +++ b/drivers/spi/litex_spiflash.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Antony Pavlov <antonynpavlov@gmail.com> + * + */ + +#include <common.h> +#include <init.h> +#include <driver.h> +#include <spi/spi.h> +#include <io.h> +#include <clock.h> + +struct litex_spiflash_spi { + struct spi_master master; + void __iomem *regs; + u32 val; +}; + +#define SPIFLASH_BITBANG 0x0 +#define SPIFLASH_BB_MOSI BIT(0) +#define SPIFLASH_BB_CLK BIT(1) +#define SPIFLASH_BB_CSN BIT(2) +#define SPIFLASH_BB_DIR BIT(3) + +#define SPIFLASH_MISO 0x4 +#define SPIFLASH_BITBANG_EN 0x8 + +static inline u32 litex_spiflash_spi_rr(struct litex_spiflash_spi *sp, int reg) +{ + return readl(sp->regs + reg); +} + +static inline void litex_spiflash_spi_wr(struct litex_spiflash_spi *sp, u32 val, int reg) +{ + writel(val, sp->regs + reg); +} + +static inline void setbits(struct litex_spiflash_spi *sp, int bits, int on) +{ + /* + * We are the only user of SCSPTR so no locking is required. + * Reading bit 2 and 0 in SCSPTR gives pin state as input. + * Writing the same bits sets the output value. + * This makes regular read-modify-write difficult so we + * use sp->val to keep track of the latest register value. + */ + + if (on) + sp->val |= bits; + else + sp->val &= ~bits; + + litex_spiflash_spi_wr(sp, sp->val, SPIFLASH_BITBANG); +} + +static inline struct litex_spiflash_spi *litex_spiflash_spidev_to_sp(struct spi_device *spi) +{ + return container_of(spi->master, struct litex_spiflash_spi, master); +} + +static inline void setsck(struct spi_device *spi, int on) +{ + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); + + setbits(sc, SPIFLASH_BB_CLK, on); +} + +static inline void setmosi(struct spi_device *spi, int on) +{ + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); + + sc->val &= ~SPIFLASH_BB_DIR; + setbits(sc, SPIFLASH_BB_MOSI, on); +} + +static inline u32 getmiso(struct spi_device *spi) +{ + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); + + setbits(sc, SPIFLASH_BB_DIR, 1); + return !!((litex_spiflash_spi_rr(sc, SPIFLASH_MISO) & 1)); +} + +#define spidelay(nsecs) udelay(nsecs/1000) + +#include "spi-bitbang-txrx.h" + +static inline void litex_spiflash_spi_chipselect(struct litex_spiflash_spi *sc, int on) +{ + setbits(sc, SPIFLASH_BB_CSN, on); +} + +static int litex_spiflash_spi_setup(struct spi_device *spi) +{ + struct spi_master *master = spi->master; + struct device_d spi_dev = spi->dev; + + if (spi->bits_per_word != 8) { + dev_err(master->dev, "master doesn't support %d bits per word requested by %s\n", + spi->bits_per_word, spi_dev.name); + return -EINVAL; + } + + if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != SPI_MODE_0) { + dev_err(master->dev, "master doesn't support SPI_MODE%d requested by %s\n", + spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name); + return -EINVAL; + } + + return 0; +} + +static int litex_spiflash_spi_read(struct spi_device *spi, void *buf, size_t nbyte) +{ + ssize_t cnt = 0; + u8 *rxf_buf = buf; + + while (cnt < nbyte) { + *rxf_buf = bitbang_txrx_be_cpha1(spi, 1000, 1, 0, 8); + rxf_buf++; + cnt++; + } + + return cnt; +} + +static int litex_spiflash_spi_write(struct spi_device *spi, + const void *buf, size_t nbyte) +{ + ssize_t cnt = 0; + const u8 *txf_buf = buf; + + while (cnt < nbyte) { + bitbang_txrx_be_cpha1(spi, 1000, 1, (u32)*txf_buf, 8); + txf_buf++; + cnt++; + } + + return 0; +} + +static int litex_spiflash_spi_transfer(struct spi_device *spi, struct spi_message *mesg) +{ + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); + struct spi_transfer *t; + + mesg->actual_length = 0; + + /* activate chip select signal */ + litex_spiflash_spi_chipselect(sc, 0); + + list_for_each_entry(t, &mesg->transfers, transfer_list) { + + if (t->tx_buf) + litex_spiflash_spi_write(spi, t->tx_buf, t->len); + + if (t->rx_buf) + litex_spiflash_spi_read(spi, t->rx_buf, t->len); + + mesg->actual_length += t->len; + } + + /* inactivate chip select signal */ + litex_spiflash_spi_chipselect(sc, 1); + + return 0; +} + +static void litex_spiflash_spi_enable(struct litex_spiflash_spi *sp) +{ + u32 val; + + /* set SPIFLASH_BB_DIR = 0 */ + val = SPIFLASH_BB_CSN | SPIFLASH_BB_CLK | SPIFLASH_BB_MOSI; + litex_spiflash_spi_wr(sp, val, SPIFLASH_BITBANG); + + /* enable GPIO mode */ + litex_spiflash_spi_wr(sp, 1, SPIFLASH_BITBANG_EN); +} + +static void litex_spiflash_spi_disable(struct litex_spiflash_spi *sp) +{ + /* disable GPIO mode */ + litex_spiflash_spi_wr(sp, 0, SPIFLASH_BITBANG_EN); +} + +static int litex_spiflash_spi_probe(struct device_d *dev) +{ + struct resource *iores; + struct spi_master *master; + struct litex_spiflash_spi *litex_spiflash_spi; + + litex_spiflash_spi = xzalloc(sizeof(*litex_spiflash_spi)); + dev->priv = litex_spiflash_spi; + + master = &litex_spiflash_spi->master; + master->dev = dev; + + master->bus_num = dev->id; + master->setup = litex_spiflash_spi_setup; + master->transfer = litex_spiflash_spi_transfer; + master->num_chipselect = 1; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + litex_spiflash_spi->regs = IOMEM(iores->start); + + litex_spiflash_spi_enable(litex_spiflash_spi); + + /* inactivate chip select signal */ + litex_spiflash_spi_chipselect(litex_spiflash_spi, 1); + + spi_register_master(master); + + return 0; +} + +static void litex_spiflash_spi_remove(struct device_d *dev) +{ + struct litex_spiflash_spi *sp = dev->priv; + + litex_spiflash_spi_disable(sp); +} + +static __maybe_unused struct of_device_id litex_spiflash_spi_dt_ids[] = { + { + .compatible = "litex,spiflash", + }, + { + /* sentinel */ + } +}; + +static struct driver_d litex_spiflash_spi_driver = { + .name = "litex-spiflash", + .probe = litex_spiflash_spi_probe, + .remove = litex_spiflash_spi_remove, + .of_compatible = DRV_OF_COMPAT(litex_spiflash_spi_dt_ids), +}; +device_platform_driver(litex_spiflash_spi_driver); -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
LiteEth provides a small footprint and configurable Ethernet core. LiteEth is part of LiteX libraries whose aims are to lower entry level of complex FPGA cores by providing simple, elegant and efficient implementations of components used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller... Using Migen to describe the HDL allows the core to be highly and easily configurable. LiteEth can be used as LiteX library or can be integrated with your standard design flow by generating the verilog rtl that you will use as a standard core. See https://github.com/enjoy-digital/liteeth for details. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> Signed-off-by: Marek Czerski <m.czerski@ap-tech.pl> --- drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/liteeth.c | 376 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 385 insertions(+) Cc: Marek Czerski <m.czerski@ap-tech.pl> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 0d55ea7a3b..4818f52603 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -271,6 +271,14 @@ config TSE_USE_DEDICATED_DESC_MEM reserved with a malloc but directly mapped to the memory address (defined in config.h) +config DRIVER_NET_LITEETH + bool "LiteX ethernet driver" + select PHYLIB + select MDIO_BITBANG + help + This option enables support for the LiteX LiteEth + ethernet IP core. + source "drivers/net/phy/Kconfig" source "drivers/net/usb/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 656d45a868..bb751943f6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -36,3 +36,4 @@ obj-$(CONFIG_DRIVER_NET_TAP) += tap.o obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o obj-$(CONFIG_DRIVER_NET_AG71XX) += ag71xx.o +obj-$(CONFIG_DRIVER_NET_LITEETH) += liteeth.o diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c new file mode 100644 index 0000000000..137cb854c5 --- /dev/null +++ b/drivers/net/liteeth.c @@ -0,0 +1,376 @@ +/* + * LiteX Liteeth Ethernet + * + * Copyright 2017 Joel Stanley <joel@jms.id.au> + * + * Ported to barebox from linux kernel + * Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov@gmail.com> + * Copyright (C) 2021 Marek Czerski <m.czerski@ap-tech.pl> + * + */ + +#include <common.h> +#include <io.h> +#include <linux/iopoll.h> +#include <malloc.h> +#include <net.h> +#include <init.h> +#include <of_net.h> +#include <linux/phy.h> +#include <linux/mdio-bitbang.h> + +#define DRV_NAME "liteeth" + +#define LITEETH_WRITER_SLOT 0x00 +#define LITEETH_WRITER_LENGTH 0x04 +#define LITEETH_WRITER_ERRORS 0x08 +#define LITEETH_WRITER_EV_STATUS 0x0c +#define LITEETH_WRITER_EV_PENDING 0x10 +#define LITEETH_WRITER_EV_ENABLE 0x14 +#define LITEETH_READER_START 0x18 +#define LITEETH_READER_READY 0x1c +#define LITEETH_READER_LEVEL 0x20 +#define LITEETH_READER_SLOT 0x24 +#define LITEETH_READER_LENGTH 0x28 +#define LITEETH_READER_EV_STATUS 0x2c +#define LITEETH_READER_EV_PENDING 0x30 +#define LITEETH_READER_EV_ENABLE 0x34 +#define LITEETH_PREAMBLE_CRC 0x38 +#define LITEETH_PREAMBLE_ERRORS 0x3c +#define LITEETH_CRC_ERRORS 0x40 + +#define LITEETH_PHY_CRG_RESET 0x00 +#define LITEETH_MDIO_W 0x04 +#define MDIO_W_CLK BIT(0) +#define MDIO_W_OE BIT(1) +#define MDIO_W_DO BIT(2) + +#define LITEETH_MDIO_R 0x08 +#define MDIO_R_DI BIT(0) + +#define LITEETH_BUFFER_SIZE 0x800 +#define MAX_PKT_SIZE LITEETH_BUFFER_SIZE + +struct liteeth { + struct device_d *dev; + struct eth_device edev; + void __iomem *base; + void __iomem *mdio_base; + struct mii_bus *mii_bus; + struct mdiobb_ctrl mdiobb; + + /* Link management */ + int cur_duplex; + int cur_speed; + + /* Tx */ + int tx_slot; + int num_tx_slots; + void __iomem *tx_base; + + /* Rx */ + int rx_slot; + int num_rx_slots; + void __iomem *rx_base; +}; + +static inline void litex_write8(void __iomem *addr, u8 val) +{ + writeb(val, addr); +} + +static inline void litex_write16(void __iomem *addr, u16 val) +{ + writew(val, addr); +} + +static inline u8 litex_read8(void __iomem *addr) +{ + return readb(addr); +} + +static inline u32 litex_read32(void __iomem *addr) +{ + return readl(addr); +} + +static void liteeth_mdio_w_modify(struct liteeth *priv, u8 clear, u8 set) +{ + void __iomem *mdio_w = priv->mdio_base + LITEETH_MDIO_W; + + litex_write8(mdio_w, (litex_read8(mdio_w) & ~clear) | set); +} + +static void liteeth_mdio_ctrl(struct mdiobb_ctrl *ctrl, u8 mask, int set) +{ + struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb); + + liteeth_mdio_w_modify(priv, mask, set ? mask : 0); +} + +/* MDC pin control */ +static void liteeth_set_mdc(struct mdiobb_ctrl *ctrl, int level) +{ + liteeth_mdio_ctrl(ctrl, MDIO_W_CLK, level); +} + +/* Data I/O pin control */ +static void liteeth_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output) +{ + liteeth_mdio_ctrl(ctrl, MDIO_W_OE, output); +} + +/* Set data bit */ +static void liteeth_set_mdio_data(struct mdiobb_ctrl *ctrl, int value) +{ + liteeth_mdio_ctrl(ctrl, MDIO_W_DO, value); +} + +/* Get data bit */ +static int liteeth_get_mdio_data(struct mdiobb_ctrl *ctrl) +{ + struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb); + + return (litex_read8(priv->mdio_base + LITEETH_MDIO_R) & MDIO_R_DI) != 0; +} + +/* MDIO bus control struct */ +static struct mdiobb_ops bb_ops = { + .set_mdc = liteeth_set_mdc, + .set_mdio_dir = liteeth_set_mdio_dir, + .set_mdio_data = liteeth_set_mdio_data, + .get_mdio_data = liteeth_get_mdio_data, +}; + +static int liteeth_init_dev(struct eth_device *edev) +{ + return 0; +} + +static int liteeth_eth_open(struct eth_device *edev) +{ + struct liteeth *priv = edev->priv; + int ret; + + /* Disable events */ + litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0); + litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0); + + /* Clear pending events? */ + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, 1); + litex_write8(priv->base + LITEETH_READER_EV_PENDING, 1); + + ret = phy_device_connect(edev, priv->mii_bus, -1, NULL, 0, -1); + if (ret) + return ret; + + return 0; +} + +static int liteeth_eth_send(struct eth_device *edev, void *packet, + int packet_length) +{ + struct liteeth *priv = edev->priv; + void *txbuffer; + int ret; + u8 val; + u8 reg; + + reg = litex_read8(priv->base + LITEETH_READER_EV_PENDING); + if (reg) { + litex_write8(priv->base + LITEETH_READER_EV_PENDING, reg); + } + + /* Reject oversize packets */ + if (unlikely(packet_length > MAX_PKT_SIZE)) { + dev_err(priv->dev, "tx packet too big\n"); + goto drop; + } + + txbuffer = priv->tx_base + priv->tx_slot * LITEETH_BUFFER_SIZE; + memcpy(txbuffer, packet, packet_length); + litex_write8(priv->base + LITEETH_READER_SLOT, priv->tx_slot); + litex_write16(priv->base + LITEETH_READER_LENGTH, packet_length); + + ret = readb_poll_timeout(priv->base + LITEETH_READER_READY, + val, val, 1000); + if (ret == -ETIMEDOUT) { + dev_err(priv->dev, "LITEETH_READER_READY timed out\n"); + goto drop; + } + + litex_write8(priv->base + LITEETH_READER_START, 1); + + priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots; + +drop: + return 0; +} + +static int liteeth_eth_rx(struct eth_device *edev) +{ + struct liteeth *priv = edev->priv; + u8 rx_slot; + int len = 0; + u8 reg; + + reg = litex_read8(priv->base + LITEETH_WRITER_EV_PENDING); + if (!reg) { + goto done; + } + + len = litex_read32(priv->base + LITEETH_WRITER_LENGTH); + if (len == 0 || len > 2048) { + len = 0; + dev_err(priv->dev, "%s: invalid len %d\n", __func__, len); + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg); + goto done; + } + + rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT); + + memcpy(NetRxPackets[0], priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len); + + net_receive(edev, NetRxPackets[0], len); + + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg); + +done: + return len; +} + +static void liteeth_eth_halt(struct eth_device *edev) +{ + struct liteeth *priv = edev->priv; + + litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0); + litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0); +} + +static void liteeth_reset_hw(struct liteeth *priv) +{ + /* Reset, twice */ + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0); + udelay(10); + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 1); + udelay(10); + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0); + udelay(10); +} + +static int liteeth_get_ethaddr(struct eth_device *edev, unsigned char *m) +{ + return 0; +} + +static int liteeth_set_ethaddr(struct eth_device *edev, + const unsigned char *mac_addr) +{ + return 0; +} + +static int liteeth_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + struct eth_device *edev; + void __iomem *buf_base; + struct liteeth *priv; + int err; + + priv = xzalloc(sizeof(struct liteeth)); + edev = &priv->edev; + edev->priv = priv; + priv->dev = dev; + + priv->base = dev_request_mem_region(dev, 0); + if (IS_ERR(priv->base)) { + err = PTR_ERR(priv->base); + goto err; + } + + priv->mdio_base = dev_request_mem_region(dev, 1); + if (IS_ERR(priv->mdio_base)) { + err = PTR_ERR(priv->mdio_base); + goto err; + } + + buf_base = dev_request_mem_region(dev, 2); + if (IS_ERR(buf_base)) { + err = PTR_ERR(buf_base); + goto err; + } + + err = of_property_read_u32(np, "rx-fifo-depth", + &priv->num_rx_slots); + if (err) { + dev_err(dev, "unable to get rx-fifo-depth\n"); + goto err; + } + + err = of_property_read_u32(np, "tx-fifo-depth", + &priv->num_tx_slots); + if (err) { + dev_err(dev, "unable to get tx-fifo-depth\n"); + goto err; + } + + /* Rx slots */ + priv->rx_base = buf_base; + priv->rx_slot = 0; + + /* Tx slots come after Rx slots */ + priv->tx_base = buf_base + priv->num_rx_slots * LITEETH_BUFFER_SIZE; + priv->tx_slot = 0; + + edev->init = liteeth_init_dev; + edev->open = liteeth_eth_open; + edev->send = liteeth_eth_send; + edev->recv = liteeth_eth_rx; + edev->get_ethaddr = liteeth_get_ethaddr; + edev->set_ethaddr = liteeth_set_ethaddr; + edev->halt = liteeth_eth_halt; + edev->parent = dev; + + priv->mdiobb.ops = &bb_ops; + + priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb); + priv->mii_bus->parent = dev; + + liteeth_reset_hw(priv); + + err = eth_register(edev); + if (err) { + dev_err(dev, "failed to register edev\n"); + goto err; + } + + err = mdiobus_register(priv->mii_bus); + if (err) { + dev_err(dev, "failed to register mii_bus\n"); + goto err; + } + + dev_info(dev, DRV_NAME " driver registered\n"); + + return 0; + +err: + return err; +} + +static const struct of_device_id liteeth_dt_ids[] = { + { + .compatible = "litex,liteeth" + }, { + } +}; + +static struct driver_d liteeth_driver = { + .name = DRV_NAME, + .probe = liteeth_probe, + .of_compatible = DRV_OF_COMPAT(liteeth_dt_ids), +}; +device_platform_driver(liteeth_driver); + +MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>"); +MODULE_LICENSE("GPL"); -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
LiteX is a Migen-based System on Chip, supporting softcore VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU. See https://github.com/enjoy-digital/litex and https://github.com/litex-hub/linux-on-litex-vexriscv for details. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- arch/riscv/Kconfig | 9 ++ arch/riscv/Makefile | 1 + arch/riscv/dts/litex_soc_linux.dtsi | 49 +++++++ arch/riscv/mach-litex/Kconfig | 8 ++ arch/riscv/mach-litex/Makefile | 3 + arch/riscv/mach-litex/include/mach/debug_ll.h | 124 ++++++++++++++++++ 6 files changed, 194 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c0583f3153..40dfd7dd93 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -34,6 +34,14 @@ config MACH_ERIZO select RISCV_M_MODE select RISCV_TIMER +config MACH_LITEX + bool "litex family" + select ARCH_RV32I + select HAS_DEBUG_LL + select HAS_NMON + select USE_COMPRESSED_DTB + select RISCV_SBI + config MACH_VIRT bool "virt family" select BOARD_RISCV_GENERIC_DT @@ -83,6 +91,7 @@ config 64BIT select PHYS_ADDR_T_64BIT source "arch/riscv/mach-erizo/Kconfig" +source "arch/riscv/mach-litex/Kconfig" config BOARD_RISCV_GENERIC_DT select BOARD_GENERIC_DT diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index aba4526bba..bc22786368 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -20,6 +20,7 @@ cflags-y += $(riscv-cflags-y) LDFLAGS_barebox += -nostdlib machine-$(CONFIG_MACH_ERIZO) := erizo +machine-$(CONFIG_MACH_LITEX) := litex machine-$(CONFIG_MACH_VIRT) := virt LDFLAGS_barebox += $(riscv-ldflags-y) diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi new file mode 100644 index 0000000000..32382b8dc2 --- /dev/null +++ b/arch/riscv/dts/litex_soc_linux.dtsi @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; + +/ { + compatible = "litex,vexriscv-soc-linux"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + timebase-frequency = <100000000>; // 100 MHz + + cpu@0 { + device_type = "cpu"; + compatible = "spinalhdl,vexriscv", "riscv"; + reg = <0>; + }; + }; + + uart0: serial@f0001000 { + compatible = "litex,uart"; + reg = <0xf0001000 0x18>; + status = "disabled"; + }; + + mac0: mac@f0009000 { + compatible = "litex,liteeth"; + reg = <0xf0009000 0x7c /* base */ + 0xf0009800 0x0a /* mdio_base */ + 0xb0000000 0x2000>; /* buf_base */ + tx-fifo-depth = <2>; + rx-fifo-depth = <2>; + status = "disabled"; + }; + + spi0: spi@f000b800 { + compatible = "litex,spiflash"; + + #address-cells = <1>; + #size-cells = <0>; + + reg = <0xf000b800 0x100>; + status = "disabled"; + }; +}; diff --git a/arch/riscv/mach-litex/Kconfig b/arch/riscv/mach-litex/Kconfig new file mode 100644 index 0000000000..19d5927e44 --- /dev/null +++ b/arch/riscv/mach-litex/Kconfig @@ -0,0 +1,8 @@ +if MACH_LITEX + +choice + prompt "Board type" + +endchoice + +endif diff --git a/arch/riscv/mach-litex/Makefile b/arch/riscv/mach-litex/Makefile new file mode 100644 index 0000000000..d9c51e74c3 --- /dev/null +++ b/arch/riscv/mach-litex/Makefile @@ -0,0 +1,3 @@ +# just to build a built-in.o. Otherwise compilation fails when no o-files is +# created. +obj- += dummy.o diff --git a/arch/riscv/mach-litex/include/mach/debug_ll.h b/arch/riscv/mach-litex/include/mach/debug_ll.h new file mode 100644 index 0000000000..df7032716d --- /dev/null +++ b/arch/riscv/mach-litex/include/mach/debug_ll.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2019 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * + * 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. + * + */ + +#ifndef __MACH_LITEX_DEBUG_LL__ +#define __MACH_LITEX_DEBUG_LL__ + +/** @file + * This File contains declaration for early output support + */ + +#include <linux/kconfig.h> + +#define DEBUG_LL_UART_ADDR 0xf0001000 +#define UART_RXTX 0x00 +#define UART_TXFULL 0x04 +#define UART_RXEMPTY 0x08 +#define UART_EV_PENDING 0x10 +#define UART_EV_RX (1 << 1) +#define UART_EV_ENABLE 0x14 + + +#ifndef __ASSEMBLY__ + +/* + * C macros + */ + +#include <asm/io.h> + +static inline void PUTC_LL(char ch) +{ +#ifdef CONFIG_DEBUG_LL + /* wait for space */ + while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL)) + ; + + __raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX); +#endif /* CONFIG_DEBUG_LL */ +} +#else /* __ASSEMBLY__ */ +/* + * Macros for use in assembly language code + */ + +/* + * output a character in a0 + */ +.macro debug_ll_outc_a0 +#ifdef CONFIG_DEBUG_LL + + li t0, DEBUG_LL_UART_ADDR + +201: + lbu t1, UART_TXFULL(t0) /* uart tx full ? */ + andi t1, t1, 0xff + bnez t1, 201b /* try again */ + + sb a0, UART_RXTX(t0) /* write the character */ + +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * output a character + */ +.macro debug_ll_outc chr +#ifdef CONFIG_DEBUG_LL + li a0, \chr + debug_ll_outc_a0 +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * check character in input buffer + * return value: + * v0 = 0 no character in input buffer + * v0 != 0 character in input buffer + */ +.macro debug_ll_tstc +#ifdef CONFIG_DEBUG_LL + li t0, DEBUG_LL_UART_ADDR + + /* get line status and check for data present */ + lbu s0, UART_RXEMPTY(t0) + bnez s0, 243f + li s0, 1 + j 244f +243: li s0, 0 +244: nop +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * get character to v0 + */ +.macro debug_ll_getc +#ifdef CONFIG_DEBUG_LL + +204: + debug_ll_tstc + + /* try again */ + beqz s0, 204b + + /* read a character */ + lb s0, UART_RXTX(t0) + li t1, UART_EV_RX + sb t1, UART_EV_PENDING(t0) + +#endif /* CONFIG_DEBUG_LL */ +.endm +#endif /* __ASSEMBLY__ */ + +#endif /* __MACH_LITEX_DEBUG_LL__ */ -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Tested on Digilent Arty FPGA board. Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- arch/riscv/boards/Makefile | 1 + arch/riscv/boards/litex-linux/Makefile | 3 + arch/riscv/boards/litex-linux/lowlevel.c | 20 +++++ arch/riscv/dts/Makefile | 1 + arch/riscv/dts/litex-linux.dts | 96 ++++++++++++++++++++++++ arch/riscv/mach-litex/Kconfig | 3 + images/Makefile.riscv | 4 + 7 files changed, 128 insertions(+) diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile index 2ce9af41e0..d477cce362 100644 --- a/arch/riscv/boards/Makefile +++ b/arch/riscv/boards/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo/ +obj-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux/ diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile new file mode 100644 index 0000000000..3d217ffe0b --- /dev/null +++ b/arch/riscv/boards/litex-linux/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +pbl-y += lowlevel.o diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c new file mode 100644 index 0000000000..9ac1a3a42e --- /dev/null +++ b/arch/riscv/boards/litex-linux/lowlevel.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <asm/barebox-riscv.h> +#include <debug_ll.h> + +ENTRY_FUNCTION(start_litex_linux, a0, a1, a2) +{ + extern char __dtb_z_litex_linux_start[]; + extern void __barebox_nmon_entry(void); + + if (IS_ENABLED(CONFIG_NMON)) + __barebox_nmon_entry(); + putc_ll('>'); + + /* On POR, we are running from read-only memory here. */ + + barebox_riscv_entry(0x40000000, SZ_256M, + __dtb_z_litex_linux_start + get_runtime_offset()); +} diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index 4041c34e0c..dc5237b5bb 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -5,5 +5,6 @@ obj- += dummy.o pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o +pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts new file mode 100644 index 0000000000..aa7e072305 --- /dev/null +++ b/arch/riscv/dts/litex-linux.dts @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "litex_soc_linux.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "LiteX VexRiscV-SoC-Linux"; + compatible = "litex,vexriscv-soc-linux"; + + aliases { + rom = &rom; + sram = &sram; + }; + + /* ARTY board */ + rom: rom@00000000 { + compatible = "mmio-sram"; + reg = <0x00000000 0x00008000>; + read-only; + }; + + sram: sram@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x00004000>; + }; + + main_ram: memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x10000000>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&mac0 { + status = "okay"; +}; + +&spi0 { + status = "okay"; + + spiflash: w25q128@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "winbond,w25q128", "jedec,spi-nor"; + spi-max-frequency = <104000000>; + reg = <0>; + }; +}; + +/ { + ledsgpio: gpio@f0005000 { + compatible = "ti,74175"; + reg = <0xf0005000 0x4>; + gpio-controller; + #gpio-cells = <2>; + }; + + leds { + compatible = "gpio-leds"; + + ld0 { + label = "arty:green:ld0"; + gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + ld1 { + label = "arty:green:ld1"; + gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + ld2 { + label = "arty:green:ld2"; + gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + ld3 { + label = "arty:green:ld3"; + gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + swgpio: gpio@f0007000 { + compatible = "ti,74125"; + reg = <0xf0007000 0x4>; + gpio-controller; + #gpio-cells = <2>; + }; +}; diff --git a/arch/riscv/mach-litex/Kconfig b/arch/riscv/mach-litex/Kconfig index 19d5927e44..3ff03b0e02 100644 --- a/arch/riscv/mach-litex/Kconfig +++ b/arch/riscv/mach-litex/Kconfig @@ -3,6 +3,9 @@ if MACH_LITEX choice prompt "Board type" +config BOARD_LITEX_LINUX + bool "litex linux board" + endchoice endif diff --git a/images/Makefile.riscv b/images/Makefile.riscv index 463c6ce440..831858a54d 100644 --- a/images/Makefile.riscv +++ b/images/Makefile.riscv @@ -10,3 +10,7 @@ $(obj)/%.nmon: $(obj)/%.img FORCE pblb-$(CONFIG_BOARD_ERIZO_GENERIC) += start_erizo_generic FILE_barebox-erizo-generic.img = start_erizo_generic.pblb image-$(CONFIG_BOARD_ERIZO_GENERIC) += barebox-erizo-generic.img barebox-erizo-generic.nmon + +pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux +FILE_barebox-litex-linux.img = start_litex_linux.pblb +image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> --- arch/riscv/configs/litex_linux_defconfig | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/riscv/configs/litex_linux_defconfig b/arch/riscv/configs/litex_linux_defconfig new file mode 100644 index 0000000000..ab53df1c78 --- /dev/null +++ b/arch/riscv/configs/litex_linux_defconfig @@ -0,0 +1,76 @@ +CONFIG_MACH_LITEX=y +CONFIG_STACK_SIZE=0x20000 +CONFIG_MALLOC_SIZE=0xf00000 +CONFIG_MALLOC_TLSF=y +CONFIG_PANIC_HANG=y +CONFIG_BAUDRATE=1000000 +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +# CONFIG_TIMESTAMP is not set +CONFIG_BOOTM_SHOW_TYPE=y +CONFIG_BOOTM_VERBOSE=y +CONFIG_BOOTM_INITRD=y +CONFIG_BOOTM_OFTREE=y +CONFIG_BOOTM_OFTREE_UIMAGE=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_DEBUG_LL=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_IMD=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_GO=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_CMP=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MM=y +CONFIG_CMD_CLK=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_LED=y +CONFIG_CMD_SPI=y +CONFIG_CMD_LED_TRIGGER=y +CONFIG_CMD_OF_DUMP=y +CONFIG_CMD_TIME=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_NET=y +CONFIG_NET_NFS=y +CONFIG_NET_NETCONSOLE=y +CONFIG_DRIVER_NET_LITEETH=y +CONFIG_AR8327N_PHY=y +CONFIG_AT803X_PHY=y +CONFIG_DAVICOM_PHY=y +CONFIG_DP83867_PHY=y +CONFIG_LXT_PHY=y +CONFIG_MARVELL_PHY=y +CONFIG_MICREL_PHY=y +CONFIG_NATIONAL_PHY=y +CONFIG_REALTEK_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_DRIVER_SPI_LITEX_SPIFLASH=y +CONFIG_MTD=y +# CONFIG_MTD_OOB_DEVICE is not set +CONFIG_MTD_M25P80=y +CONFIG_CLOCKSOURCE_DUMMY_RATE=20000 +CONFIG_SRAM=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_LED_TRIGGERS=y +CONFIG_GPIO_74XX_MMIO=y +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_PINCTRL is not set +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_DIGEST_CRC32_GENERIC=y -- 2.31.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Hello Antony, On 05.05.21 12:08, Antony Pavlov wrote: > LiteX is a Migen-based System on Chip, supporting softcore > VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU. > > See https://github.com/enjoy-digital/litex and > https://github.com/litex-hub/linux-on-litex-vexriscv > for details. > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > arch/riscv/Kconfig | 9 ++ > arch/riscv/Makefile | 1 + > arch/riscv/dts/litex_soc_linux.dtsi | 49 +++++++ > arch/riscv/mach-litex/Kconfig | 8 ++ > arch/riscv/mach-litex/Makefile | 3 + > arch/riscv/mach-litex/include/mach/debug_ll.h | 124 ++++++++++++++++++ > 6 files changed, 194 insertions(+) > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index c0583f3153..40dfd7dd93 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -34,6 +34,14 @@ config MACH_ERIZO > select RISCV_M_MODE > select RISCV_TIMER > > +config MACH_LITEX > + bool "litex family" > + select ARCH_RV32I > + select HAS_DEBUG_LL > + select HAS_NMON > + select USE_COMPRESSED_DTB > + select RISCV_SBI > + > config MACH_VIRT > bool "virt family" > select BOARD_RISCV_GENERIC_DT > @@ -83,6 +91,7 @@ config 64BIT > select PHYS_ADDR_T_64BIT > > source "arch/riscv/mach-erizo/Kconfig" > +source "arch/riscv/mach-litex/Kconfig" > > config BOARD_RISCV_GENERIC_DT > select BOARD_GENERIC_DT > diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile > index aba4526bba..bc22786368 100644 > --- a/arch/riscv/Makefile > +++ b/arch/riscv/Makefile > @@ -20,6 +20,7 @@ cflags-y += $(riscv-cflags-y) > LDFLAGS_barebox += -nostdlib > > machine-$(CONFIG_MACH_ERIZO) := erizo > +machine-$(CONFIG_MACH_LITEX) := litex Could you rebase on barebox next? I dropped machine directories for RISC-V. They were only used for <mach/debug_ll.h> and there is an <asm/debug_ll.h> now that can be extended instead. This reduces boilerplate and allows building all RISC-V images in one go. > machine-$(CONFIG_MACH_VIRT) := virt > > LDFLAGS_barebox += $(riscv-ldflags-y) > diff --git a/arch/riscv/dts/litex_soc_linux.dtsi b/arch/riscv/dts/litex_soc_linux.dtsi > new file mode 100644 > index 0000000000..32382b8dc2 > --- /dev/null > +++ b/arch/riscv/dts/litex_soc_linux.dtsi Is "linux" a well-nown LiteX configuration? Otherwise would maybe litex-vexrisc.dtsi be a better name? > @@ -0,0 +1,49 @@ > +// SPDX-License-Identifier: GPL-2.0-only > + > +/dts-v1/; > + > +/ { > + compatible = "litex,vexriscv-soc-linux"; > + > + #address-cells = <1>; > + #size-cells = <1>; > + > + cpus { > + #address-cells = <1>; > + #size-cells = <0>; > + > + timebase-frequency = <100000000>; // 100 MHz > + > + cpu@0 { > + device_type = "cpu"; > + compatible = "spinalhdl,vexriscv", "riscv"; > + reg = <0>; > + }; > + }; > + > + uart0: serial@f0001000 { > + compatible = "litex,uart"; > + reg = <0xf0001000 0x18>; > + status = "disabled"; > + }; > + > + mac0: mac@f0009000 { > + compatible = "litex,liteeth"; > + reg = <0xf0009000 0x7c /* base */ > + 0xf0009800 0x0a /* mdio_base */ > + 0xb0000000 0x2000>; /* buf_base */ > + tx-fifo-depth = <2>; > + rx-fifo-depth = <2>; > + status = "disabled"; > + }; > + > + spi0: spi@f000b800 { > + compatible = "litex,spiflash"; > + > + #address-cells = <1>; > + #size-cells = <0>; > + > + reg = <0xf000b800 0x100>; > + status = "disabled"; > + }; > +}; > diff --git a/arch/riscv/mach-litex/Kconfig b/arch/riscv/mach-litex/Kconfig > new file mode 100644 > index 0000000000..19d5927e44 > --- /dev/null > +++ b/arch/riscv/mach-litex/Kconfig > @@ -0,0 +1,8 @@ > +if MACH_LITEX > + > +choice > + prompt "Board type" > + > +endchoice > + > +endif > diff --git a/arch/riscv/mach-litex/Makefile b/arch/riscv/mach-litex/Makefile > new file mode 100644 > index 0000000000..d9c51e74c3 > --- /dev/null > +++ b/arch/riscv/mach-litex/Makefile > @@ -0,0 +1,3 @@ > +# just to build a built-in.o. Otherwise compilation fails when no o-files is > +# created. > +obj- += dummy.o > diff --git a/arch/riscv/mach-litex/include/mach/debug_ll.h b/arch/riscv/mach-litex/include/mach/debug_ll.h > new file mode 100644 > index 0000000000..df7032716d > --- /dev/null > +++ b/arch/riscv/mach-litex/include/mach/debug_ll.h > @@ -0,0 +1,124 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2019 Antony Pavlov <antonynpavlov@gmail.com> > + * > + * This file is part of barebox. > + * > + * 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. > + * > + */ > + > +#ifndef __MACH_LITEX_DEBUG_LL__ > +#define __MACH_LITEX_DEBUG_LL__ > + > +/** @file > + * This File contains declaration for early output support > + */ > + > +#include <linux/kconfig.h> > + > +#define DEBUG_LL_UART_ADDR 0xf0001000 > +#define UART_RXTX 0x00 > +#define UART_TXFULL 0x04 > +#define UART_RXEMPTY 0x08 > +#define UART_EV_PENDING 0x10 > +#define UART_EV_RX (1 << 1) > +#define UART_EV_ENABLE 0x14 > + > + > +#ifndef __ASSEMBLY__ > + > +/* > + * C macros > + */ > + > +#include <asm/io.h> > + > +static inline void PUTC_LL(char ch) > +{ > +#ifdef CONFIG_DEBUG_LL > + /* wait for space */ > + while (__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_TXFULL)) > + ; > + > + __raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_RXTX); > +#endif /* CONFIG_DEBUG_LL */ > +} > +#else /* __ASSEMBLY__ */ > +/* > + * Macros for use in assembly language code > + */ > + > +/* > + * output a character in a0 > + */ > +.macro debug_ll_outc_a0 > +#ifdef CONFIG_DEBUG_LL > + > + li t0, DEBUG_LL_UART_ADDR > + > +201: > + lbu t1, UART_TXFULL(t0) /* uart tx full ? */ > + andi t1, t1, 0xff > + bnez t1, 201b /* try again */ > + > + sb a0, UART_RXTX(t0) /* write the character */ > + > +#endif /* CONFIG_DEBUG_LL */ > +.endm > + > +/* > + * output a character > + */ > +.macro debug_ll_outc chr > +#ifdef CONFIG_DEBUG_LL > + li a0, \chr > + debug_ll_outc_a0 > +#endif /* CONFIG_DEBUG_LL */ > +.endm > + > +/* > + * check character in input buffer > + * return value: > + * v0 = 0 no character in input buffer > + * v0 != 0 character in input buffer > + */ > +.macro debug_ll_tstc > +#ifdef CONFIG_DEBUG_LL > + li t0, DEBUG_LL_UART_ADDR > + > + /* get line status and check for data present */ > + lbu s0, UART_RXEMPTY(t0) > + bnez s0, 243f > + li s0, 1 > + j 244f > +243: li s0, 0 > +244: nop > +#endif /* CONFIG_DEBUG_LL */ > +.endm > + > +/* > + * get character to v0 > + */ > +.macro debug_ll_getc > +#ifdef CONFIG_DEBUG_LL > + > +204: > + debug_ll_tstc > + > + /* try again */ > + beqz s0, 204b > + > + /* read a character */ > + lb s0, UART_RXTX(t0) > + li t1, UART_EV_RX > + sb t1, UART_EV_PENDING(t0) > + > +#endif /* CONFIG_DEBUG_LL */ > +.endm > +#endif /* __ASSEMBLY__ */ > + > +#endif /* __MACH_LITEX_DEBUG_LL__ */ Given that we jump into C very early now, do we still need the assembly debug_ll helpers? Cheers, Ahmad -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Hello Antony, On 05.05.21 12:08, Antony Pavlov wrote: > Tested on Digilent Arty FPGA board. > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > arch/riscv/boards/Makefile | 1 + > arch/riscv/boards/litex-linux/Makefile | 3 + > arch/riscv/boards/litex-linux/lowlevel.c | 20 +++++ > arch/riscv/dts/Makefile | 1 + > arch/riscv/dts/litex-linux.dts | 96 ++++++++++++++++++++++++ > arch/riscv/mach-litex/Kconfig | 3 + > images/Makefile.riscv | 4 + > 7 files changed, 128 insertions(+) > > diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile > index 2ce9af41e0..d477cce362 100644 > --- a/arch/riscv/boards/Makefile > +++ b/arch/riscv/boards/Makefile > @@ -1,2 +1,3 @@ > # SPDX-License-Identifier: GPL-2.0 > obj-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo/ > +obj-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux/ > diff --git a/arch/riscv/boards/litex-linux/Makefile b/arch/riscv/boards/litex-linux/Makefile > new file mode 100644 > index 0000000000..3d217ffe0b > --- /dev/null > +++ b/arch/riscv/boards/litex-linux/Makefile > @@ -0,0 +1,3 @@ > +# SPDX-License-Identifier: GPL-2.0 > + > +pbl-y += lowlevel.o > diff --git a/arch/riscv/boards/litex-linux/lowlevel.c b/arch/riscv/boards/litex-linux/lowlevel.c > new file mode 100644 > index 0000000000..9ac1a3a42e > --- /dev/null > +++ b/arch/riscv/boards/litex-linux/lowlevel.c > @@ -0,0 +1,20 @@ > +// SPDX-License-Identifier: GPL-2.0-only > + > +#include <common.h> > +#include <asm/barebox-riscv.h> > +#include <debug_ll.h> > + > +ENTRY_FUNCTION(start_litex_linux, a0, a1, a2) > +{ > + extern char __dtb_z_litex_linux_start[]; > + extern void __barebox_nmon_entry(void); I'd suggest <asm/nmon.h>, so this need not be repeated. > + > + if (IS_ENABLED(CONFIG_NMON)) > + __barebox_nmon_entry(); > + putc_ll('>'); > + > + /* On POR, we are running from read-only memory here. */ > + > + barebox_riscv_entry(0x40000000, SZ_256M, > + __dtb_z_litex_linux_start + get_runtime_offset()); > +} > diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile > index 4041c34e0c..dc5237b5bb 100644 > --- a/arch/riscv/dts/Makefile > +++ b/arch/riscv/dts/Makefile > @@ -5,5 +5,6 @@ > obj- += dummy.o > > pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o > +pbl-$(CONFIG_BOARD_LITEX_LINUX) += litex-linux.dtb.o > > clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts > diff --git a/arch/riscv/dts/litex-linux.dts b/arch/riscv/dts/litex-linux.dts > new file mode 100644 > index 0000000000..aa7e072305 > --- /dev/null > +++ b/arch/riscv/dts/litex-linux.dts > @@ -0,0 +1,96 @@ > +// SPDX-License-Identifier: GPL-2.0-only > + > +#include "litex_soc_linux.dtsi" > + > +#include <dt-bindings/gpio/gpio.h> > + > +/ { > + model = "LiteX VexRiscV-SoC-Linux"; > + compatible = "litex,vexriscv-soc-linux"; > + > + aliases { > + rom = &rom; > + sram = &sram; > + }; > + > + /* ARTY board */ > + rom: rom@00000000 { > + compatible = "mmio-sram"; > + reg = <0x00000000 0x00008000>; > + read-only; > + }; > + > + sram: sram@20000000 { > + compatible = "mmio-sram"; > + reg = <0x20000000 0x00004000>; > + }; > + > + main_ram: memory@40000000 { > + device_type = "memory"; > + reg = <0x40000000 0x10000000>; > + }; > +}; > + > +&uart0 { > + status = "okay"; > +}; > + > +&mac0 { > + status = "okay"; > +}; > + > +&spi0 { > + status = "okay"; > + > + spiflash: w25q128@0 { > + #address-cells = <1>; > + #size-cells = <1>; > + compatible = "winbond,w25q128", "jedec,spi-nor"; > + spi-max-frequency = <104000000>; > + reg = <0>; > + }; > +}; > + > +/ { Any reason, this can't be merge into / { } above? > + ledsgpio: gpio@f0005000 { > + compatible = "ti,74175"; > + reg = <0xf0005000 0x4>; > + gpio-controller; > + #gpio-cells = <2>; > + }; > + > + leds { > + compatible = "gpio-leds"; > + > + ld0 { Nitpick: led-0 is what's required by the YAML schema. > + label = "arty:green:ld0"; > + gpios = <&ledsgpio 0 GPIO_ACTIVE_HIGH>; > + default-state = "off"; That's redundant, isn't it? > + }; > + > + ld1 { > + label = "arty:green:ld1"; > + gpios = <&ledsgpio 1 GPIO_ACTIVE_HIGH>; > + default-state = "off"; > + }; > + > + ld2 { > + label = "arty:green:ld2"; > + gpios = <&ledsgpio 2 GPIO_ACTIVE_HIGH>; > + default-state = "off"; > + }; > + > + ld3 { > + label = "arty:green:ld3"; > + gpios = <&ledsgpio 3 GPIO_ACTIVE_HIGH>; > + default-state = "off"; > + }; > + }; > + > + swgpio: gpio@f0007000 { > + compatible = "ti,74125"; > + reg = <0xf0007000 0x4>; > + gpio-controller; > + #gpio-cells = <2>; > + }; > +}; > diff --git a/arch/riscv/mach-litex/Kconfig b/arch/riscv/mach-litex/Kconfig > index 19d5927e44..3ff03b0e02 100644 > --- a/arch/riscv/mach-litex/Kconfig > +++ b/arch/riscv/mach-litex/Kconfig > @@ -3,6 +3,9 @@ if MACH_LITEX > choice > prompt "Board type" > > +config BOARD_LITEX_LINUX > + bool "litex linux board" > + > endchoice > > endif > diff --git a/images/Makefile.riscv b/images/Makefile.riscv > index 463c6ce440..831858a54d 100644 > --- a/images/Makefile.riscv > +++ b/images/Makefile.riscv > @@ -10,3 +10,7 @@ $(obj)/%.nmon: $(obj)/%.img FORCE > pblb-$(CONFIG_BOARD_ERIZO_GENERIC) += start_erizo_generic > FILE_barebox-erizo-generic.img = start_erizo_generic.pblb > image-$(CONFIG_BOARD_ERIZO_GENERIC) += barebox-erizo-generic.img barebox-erizo-generic.nmon > + > +pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux > +FILE_barebox-litex-linux.img = start_litex_linux.pblb > +image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img barebox-litex-linux sounds quite strange for me as someone who hasn't used LiteX. > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Hello, On 05.05.21 12:08, Antony Pavlov wrote: > After migrating to PBL we can't use nmon assembler macro > in C code anymore. Some changes are introduced to invoke > nmon from PBL C code: > > * use 'lla' macro instruction instead of 'la'; > * don't touch the 'ra' register, use 'a2' instead; > * add wrapper C function for nmon. > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > arch/riscv/boot/Makefile | 1 + > arch/riscv/boot/nmon_entry.S | 13 ++++++++++++ > arch/riscv/include/asm/riscv_nmon.h | 33 ++++++++++++++--------------- > 3 files changed, 30 insertions(+), 17 deletions(-) > > diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile > index 968a826d16..80f63a4a0a 100644 > --- a/arch/riscv/boot/Makefile > +++ b/arch/riscv/boot/Makefile > @@ -1,4 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0 > obj-y += start.o > pbl-y += entry.o uncompress.o > +pbl-y += nmon_entry.o > pbl-$(CONFIG_BOARD_GENERIC_DT) += board-dt-2nd.o > diff --git a/arch/riscv/boot/nmon_entry.S b/arch/riscv/boot/nmon_entry.S > new file mode 100644 > index 0000000000..9b30b50627 > --- /dev/null > +++ b/arch/riscv/boot/nmon_entry.S > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#include <linux/linkage.h> > +#include <asm/sections.h> > + > +#include "mach/debug_ll.h" > +#include "asm/riscv_nmon.h" > + > +.section .text_bare_init > + > +ENTRY(__barebox_nmon_entry) Perhaps drop the __? __ makes me think I should not call this or that there is a non __-prefixed versions, but both don't seem to be true as boards do directly call this. > + riscv_nmon > + ret > +ENDPROC(__barebox_nmon_entry) > diff --git a/arch/riscv/include/asm/riscv_nmon.h b/arch/riscv/include/asm/riscv_nmon.h > index caf213cdd8..11b19ab35b 100644 > --- a/arch/riscv/include/asm/riscv_nmon.h > +++ b/arch/riscv/include/asm/riscv_nmon.h > @@ -20,9 +20,8 @@ Please add #ifndef __ASSEMBLY__ void __barebox_nmon_entry(void); #endif here. With that addressed: Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de> > > .macro nmon_outs msg > > - la a1, \msg > - > - jal _nmon_outs > + lla a1, \msg > + jal a2, _nmon_outs > > .endm > > @@ -73,7 +72,7 @@ nmon_main: > li a0, 'q' > bne s0, a0, 3f > > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > j nmon_exit > > @@ -90,12 +89,12 @@ nmon_main: > j nmon_main_help > > nmon_cmd_d: > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > li a0, ' ' > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > - jal _nmon_gethexw > + jal a2, _nmon_gethexw > > nmon_outs msg_nl > > @@ -105,28 +104,28 @@ nmon_cmd_d: > j nmon_main > > nmon_cmd_w: > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > li a0, ' ' > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > - jal _nmon_gethexw > + jal a2, _nmon_gethexw > move s2, s0 > > li a0, ' ' > - jal _nmon_outc_a0 > - jal _nmon_gethexw > + jal a2, _nmon_outc_a0 > + jal a2, _nmon_gethexw > > sw s0, 0(s2) > j nmon_main > > nmon_cmd_g: > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > li a0, ' ' > - jal _nmon_outc_a0 > + jal a2, _nmon_outc_a0 > > - jal _nmon_gethexw > + jal a2, _nmon_gethexw > move s2, s0 > > nmon_outs msg_nl > @@ -136,7 +135,7 @@ nmon_cmd_g: > > _nmon_outc_a0: > debug_ll_outc_a0 > - jr ra > + jr a2 > > _nmon_outs: > > @@ -202,7 +201,7 @@ _get_hex_digit: > move s0, t2 > > _nmon_jr_ra_exit: > - jr ra > + jr a2 > > msg_prompt: > .asciz "\r\nnmon> " > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On 05.05.21 12:08, Antony Pavlov wrote: > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > arch/riscv/boards/erizo/lowlevel.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/arch/riscv/boards/erizo/lowlevel.c b/arch/riscv/boards/erizo/lowlevel.c > index d9edb530b7..185de6ed77 100644 > --- a/arch/riscv/boards/erizo/lowlevel.c > +++ b/arch/riscv/boards/erizo/lowlevel.c > @@ -7,8 +7,11 @@ > ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) > { > extern char __dtb_z_erizo_generic_start[]; > + extern void __barebox_nmon_entry(void); > > debug_ll_ns16550_init(); > + if (IS_ENABLED(CONFIG_NMON)) > + __barebox_nmon_entry(); Nitpick: How about moving the #ifdef into the header file, so you can do barebox_nmon_entry(); without ifdefing? Anyways: Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de> > putc_ll('>'); > > /* On POR, we are running from read-only memory here. */ > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On 05.05.21 12:08, Antony Pavlov wrote: > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > drivers/serial/Makefile | 1 + > drivers/serial/serial_litex.c | 96 +++++++++++++++++++++++++++++++++++ > 2 files changed, 97 insertions(+) > > diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile > index 7ff41cd5c7..95c3387d3e 100644 > --- a/drivers/serial/Makefile > +++ b/drivers/serial/Makefile > @@ -23,3 +23,4 @@ obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o > obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o > obj-$(CONFIG_DRIVER_SERIAL_LPUART) += serial_lpuart.o > obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o > +obj-$(CONFIG_MACH_LITEX) += serial_litex.o > diff --git a/drivers/serial/serial_litex.c b/drivers/serial/serial_litex.c > new file mode 100644 > index 0000000000..dec3d99fd0 > --- /dev/null > +++ b/drivers/serial/serial_litex.c > @@ -0,0 +1,96 @@ > +// SPDX-License-Identifier: GPL-2. > +/* > + * Copyright (C) 2019 Antony Pavlov <antonynpavlov@gmail.com> > + * > + */ > + > +#include <common.h> > +#include <init.h> > +#include <malloc.h> That header is unused, isn't it? > +#include <io.h> > + > +#include <mach/debug_ll.h> This seems unused as well. > +static inline uint32_t litex_serial_readb(struct console_device *cdev, > + uint32_t offset) > +{ > + void __iomem *base = cdev->dev->priv; > + > + return readb(base + offset); > +} > + > +static inline void litex_serial_writeb(struct console_device *cdev, > + uint32_t value, uint32_t offset) > +{ > + void __iomem *base = cdev->dev->priv; > + > + writeb(value, base + offset); > +} > + > +static void litex_serial_putc(struct console_device *cdev, char c) > +{ > + while (litex_serial_readb(cdev, UART_TXFULL)) > + ; > + > + litex_serial_writeb(cdev, c, UART_RXTX); > +} > + > +static int litex_serial_getc(struct console_device *cdev) > +{ > + int c; > + > + while (litex_serial_readb(cdev, UART_RXEMPTY)) > + ; > + > + c = litex_serial_readb(cdev, UART_RXTX); > + > + /* refresh UART_RXEMPTY by writing UART_EV_RX to UART_EV_PENDING */ > + litex_serial_writeb(cdev, UART_EV_RX, UART_EV_PENDING); > + > + return c; > +} > + > +static int litex_serial_tstc(struct console_device *cdev) > +{ > + if (litex_serial_readb(cdev, UART_RXEMPTY)) { > + return 0; > + } > + > + return 1; return directly? > +} > + > +static int litex_serial_probe(struct device_d *dev) > +{ > + struct resource *iores; > + struct console_device *cdev; > + > + cdev = xzalloc(sizeof(struct console_device)); > + iores = dev_request_mem_resource(dev, 0); > + if (IS_ERR(iores)) > + return PTR_ERR(iores); blank line. > + dev->priv = IOMEM(iores->start); > + cdev->dev = dev; > + cdev->tstc = &litex_serial_tstc; > + cdev->putc = &litex_serial_putc; > + cdev->getc = &litex_serial_getc; > + cdev->setbrg = NULL; > + > + console_register(cdev); > + > + return 0; > +} > + > +static __maybe_unused struct of_device_id litex_serial_dt_ids[] = { > + { > + .compatible = "litex,uart", > + }, { > + /* sentinel */ > + } > +}; > + > +static struct driver_d litex_serial_driver = { > + .name = "litex-uart", > + .probe = litex_serial_probe, > + .of_compatible = DRV_OF_COMPAT(litex_serial_dt_ids), > +}; > +console_platform_driver(litex_serial_driver); -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On 05.05.21 12:08, Antony Pavlov wrote: > This patch adds driver to support GPIO functionality > for 74xx-compatible ICs with MMIO access. > > Compatible models include: > 1 bit: 741G125 (Input), 741G74 (Output) > 2 bits: 742G125 (Input), 7474 (Output) > 4 bits: 74125 (Input), 74175 (Output) > 6 bits: 74365 (Input), 74174 (Output) > 8 bits: 74244 (Input), 74273 (Output) > 16 bits: 741624 (Input), 7416374 (Output) > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > Cc: Alexander Shiyan <shc_work@mail.ru> > --- > drivers/gpio/Kconfig | 14 +++ > drivers/gpio/Makefile | 1 + > drivers/gpio/gpio-74xx-mmio.c | 170 ++++++++++++++++++++++++++++++++++ > 3 files changed, 185 insertions(+) > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index 261b6e6662..59cb00ff22 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -21,6 +21,20 @@ config GPIO_74164 > shift registers. This driver can be used to provide access > to more gpio outputs. > > +config GPIO_74XX_MMIO > + tristate "GPIO driver for 74xx-ICs with MMIO access" > + depends on OFDEVICE > + select GPIO_GENERIC > + help > + Say yes here to support GPIO functionality for 74xx-compatible ICs > + with MMIO access. Compatible models include: > + 1 bit: 741G125 (Input), 741G74 (Output) > + 2 bits: 742G125 (Input), 7474 (Output) > + 4 bits: 74125 (Input), 74175 (Output) > + 6 bits: 74365 (Input), 74174 (Output) > + 8 bits: 74244 (Input), 74273 (Output) > + 16 bits: 741624 (Input), 7416374 (Output) > + > config GPIO_CLPS711X > bool "GPIO support for CLPS711X" > depends on ARCH_CLPS711X || COMPILE_TEST > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > index 77dcf58f64..7ece8621d2 100644 > --- a/drivers/gpio/Makefile > +++ b/drivers/gpio/Makefile > @@ -1,6 +1,7 @@ > obj-$(CONFIG_GPIOLIB) += gpiolib.o > > obj-$(CONFIG_GPIO_74164) += gpio-74164.o > +obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o > obj-$(CONFIG_MACH_MIPS_ATH79) += gpio-ath79.o > obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o > obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o > diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c > new file mode 100644 > index 0000000000..2c05d022f1 > --- /dev/null > +++ b/drivers/gpio/gpio-74xx-mmio.c > @@ -0,0 +1,170 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * 74xx MMIO GPIO driver > + * > + * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> > + * > + * Ported to barebox from linux-v5.4-rc6 > + * Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov@gmail.com> > + * > + */ > + > +#include <common.h> > +#include <driver.h> > +#include <errno.h> > +#include <gpio.h> > +#include <init.h> > +#include <io.h> > +#include <malloc.h> > + > +#include <linux/err.h> > +#include <linux/basic_mmio_gpio.h> > + > +#define MMIO_74XX_DIR_IN (0 << 8) > +#define MMIO_74XX_DIR_OUT (1 << 8) > +#define MMIO_74XX_BIT_CNT(x) ((x) & 0xff) > + > +struct mmio_74xx_gpio_priv { > + struct bgpio_chip bgc; > + unsigned int flags; > +}; > + > +static const struct of_device_id mmio_74xx_gpio_ids[] = { > + { > + .compatible = "ti,741g125", > + .data = (const void *)(MMIO_74XX_DIR_IN | 1), > + }, > + { > + .compatible = "ti,742g125", > + .data = (const void *)(MMIO_74XX_DIR_IN | 2), > + }, > + { > + .compatible = "ti,74125", > + .data = (const void *)(MMIO_74XX_DIR_IN | 4), > + }, > + { > + .compatible = "ti,74365", > + .data = (const void *)(MMIO_74XX_DIR_IN | 6), > + }, > + { > + .compatible = "ti,74244", > + .data = (const void *)(MMIO_74XX_DIR_IN | 8), > + }, > + { > + .compatible = "ti,741624", > + .data = (const void *)(MMIO_74XX_DIR_IN | 16), > + }, > + { > + .compatible = "ti,741g74", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 1), > + }, > + { > + .compatible = "ti,7474", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 2), > + }, > + { > + .compatible = "ti,74175", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 4), > + }, > + { > + .compatible = "ti,74174", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 6), > + }, > + { > + .compatible = "ti,74273", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 8), > + }, > + { > + .compatible = "ti,7416374", > + .data = (const void *)(MMIO_74XX_DIR_OUT | 16), > + }, > + { } > +}; > + > +static inline > +struct mmio_74xx_gpio_priv *to_mmio_74xx_gpio_priv(struct gpio_chip *gc) > +{ > + struct bgpio_chip *bgc = > + container_of(gc, struct bgpio_chip, gc); > + > + return container_of(bgc, struct mmio_74xx_gpio_priv, bgc); > +} > + > +static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned int offset) > +{ > + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); > + > + if (priv->flags & MMIO_74XX_DIR_OUT) > + return GPIOF_DIR_OUT; > + > + return GPIOF_DIR_IN; > +} > + > +static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio) > +{ > + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); > + > + return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0; > +} > + > +static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) > +{ > + struct mmio_74xx_gpio_priv *priv = to_mmio_74xx_gpio_priv(gc); > + > + if (priv->flags & MMIO_74XX_DIR_OUT) { > + gc->ops->set(gc, gpio, val); > + return 0; > + } > + > + return -ENOTSUPP; > +} > + > +static int mmio_74xx_gpio_probe(struct device_d *dev) > +{ > + struct mmio_74xx_gpio_priv *priv; > + void __iomem *dat; > + int err; > + struct gpio_chip *gc; > + > + priv = xzalloc(sizeof(*priv)); > + > + err = dev_get_drvdata(dev, (const void **)&priv->flags); > + if (err) > + return err; Not 64-bit safe. Please use device_get_match_data() instead. > + > + dat = dev_request_mem_region(dev, 0); > + if (IS_ERR(dat)) > + return PTR_ERR(dat); > + > + err = bgpio_init(&priv->bgc, dev, > + DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), > + dat, NULL, NULL, NULL, NULL, 0); > + if (err) > + return err; > + > + gc = &priv->bgc.gc; > + gc->ops->direction_input = mmio_74xx_dir_in; > + gc->ops->direction_output = mmio_74xx_dir_out; > + gc->ops->get_direction = mmio_74xx_get_direction; > + gc->ngpio = MMIO_74XX_BIT_CNT(priv->flags); > + > + dev->priv = priv; > + > + return gpiochip_add(gc); > +} > + > +static struct driver_d mmio_74xx_gpio_driver = { > + .name = "74xx-mmio-gpio", > + .of_compatible = DRV_OF_COMPAT(mmio_74xx_gpio_ids), > + .probe = mmio_74xx_gpio_probe, > +}; > + > +static int mmio_74xx_gpio_init(void) > +{ > + return platform_driver_register(&mmio_74xx_gpio_driver); > +} > +coredevice_initcall(mmio_74xx_gpio_init); You can abbreviate this with coredevice_platform_driver. Cheers, Ahmad > + > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); > +MODULE_DESCRIPTION("74xx MMIO GPIO driver"); > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, 5 May 2021 12:19:02 +0200 Ahmad Fatoum <a.fatoum@pengutronix.de> wrote: Hi Ahmad! You are send your e-mails too fast, I can't keep up with you ;) I see that your latest RISC-V changes are already in pengutronix next branch. I'll try to take into account your notest and rebase my LiteX branch on top of pengutronix next branch tomorrow. > > --- a/images/Makefile.riscv > > +++ b/images/Makefile.riscv > > @@ -10,3 +10,7 @@ $(obj)/%.nmon: $(obj)/%.img FORCE > > pblb-$(CONFIG_BOARD_ERIZO_GENERIC) += start_erizo_generic > > FILE_barebox-erizo-generic.img = start_erizo_generic.pblb > > image-$(CONFIG_BOARD_ERIZO_GENERIC) += barebox-erizo-generic.img barebox-erizo-generic.nmon > > + > > +pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux > > +FILE_barebox-litex-linux.img = start_litex_linux.pblb > > +image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img > > barebox-litex-linux sounds quite strange for me as someone who hasn't > used LiteX. There are several LiteX SoCs. Some of them are linux-targeted the others are RTOS targeted (e.g. Zephyr RTOS), these SoCs can use different IP-block sets and different IP-block base addresses. So in barebox-litex-linux.img the part "litex-linux" is short name for SoC "linux-on-litex-vexriscv". -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Hello Antony, On 05.05.21 12:08, Antony Pavlov wrote: > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > drivers/spi/Kconfig | 3 + > drivers/spi/Makefile | 1 + > drivers/spi/litex_spiflash.c | 242 +++++++++++++++++++++++++++++++++++ > 3 files changed, 246 insertions(+) > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > index 323d93efeb..714d30e909 100644 > --- a/drivers/spi/Kconfig > +++ b/drivers/spi/Kconfig > @@ -74,6 +74,9 @@ config DRIVER_SPI_IMX_2_3 > depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6 || ARCH_IMX7 || ARCH_IMX8MQ > default y > > +config DRIVER_SPI_LITEX_SPIFLASH > + bool "Litex SPIFLASH bitbang master driver" The SPI controller is called SPIFLASH? > + > config DRIVER_SPI_MXS > bool "i.MX (23,28) SPI Master driver" > depends on ARCH_IMX28 > diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile > index 908d514a01..ac95ffc1db 100644 > --- a/drivers/spi/Makefile > +++ b/drivers/spi/Makefile > @@ -4,6 +4,7 @@ obj-$(CONFIG_DRIVER_SPI_ATH79) += ath79_spi.o > obj-$(CONFIG_DRIVER_SPI_GPIO) += gpio_spi.o > obj-$(CONFIG_DRIVER_SPI_FSL_QUADSPI) += spi-fsl-qspi.o > obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o > +obj-$(CONFIG_DRIVER_SPI_LITEX_SPIFLASH) += litex_spiflash.o > obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o > obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o > obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o > diff --git a/drivers/spi/litex_spiflash.c b/drivers/spi/litex_spiflash.c > new file mode 100644 > index 0000000000..2d6858c580 > --- /dev/null > +++ b/drivers/spi/litex_spiflash.c > @@ -0,0 +1,242 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (C) 2020 Antony Pavlov <antonynpavlov@gmail.com> > + * > + */ > + > +#include <common.h> > +#include <init.h> > +#include <driver.h> > +#include <spi/spi.h> > +#include <io.h> > +#include <clock.h> Unused now, I think. > + > +struct litex_spiflash_spi { > + struct spi_master master; > + void __iomem *regs; > + u32 val; > +}; > + > +#define SPIFLASH_BITBANG 0x0 > +#define SPIFLASH_BB_MOSI BIT(0) > +#define SPIFLASH_BB_CLK BIT(1) > +#define SPIFLASH_BB_CSN BIT(2) > +#define SPIFLASH_BB_DIR BIT(3) > + > +#define SPIFLASH_MISO 0x4 > +#define SPIFLASH_BITBANG_EN 0x8 > + > +static inline u32 litex_spiflash_spi_rr(struct litex_spiflash_spi *sp, int reg) > +{ > + return readl(sp->regs + reg); > +} > + > +static inline void litex_spiflash_spi_wr(struct litex_spiflash_spi *sp, u32 val, int reg) > +{ > + writel(val, sp->regs + reg); > +} > + > +static inline void setbits(struct litex_spiflash_spi *sp, int bits, int on) > +{ > + /* > + * We are the only user of SCSPTR so no locking is required. > + * Reading bit 2 and 0 in SCSPTR gives pin state as input. > + * Writing the same bits sets the output value. > + * This makes regular read-modify-write difficult so we > + * use sp->val to keep track of the latest register value. > + */ > + > + if (on) > + sp->val |= bits; > + else > + sp->val &= ~bits; > + > + litex_spiflash_spi_wr(sp, sp->val, SPIFLASH_BITBANG); > +} > + > +static inline struct litex_spiflash_spi *litex_spiflash_spidev_to_sp(struct spi_device *spi) > +{ > + return container_of(spi->master, struct litex_spiflash_spi, master); > +} > + > +static inline void setsck(struct spi_device *spi, int on) > +{ > + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); > + > + setbits(sc, SPIFLASH_BB_CLK, on); > +} > + > +static inline void setmosi(struct spi_device *spi, int on) > +{ > + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); > + > + sc->val &= ~SPIFLASH_BB_DIR; > + setbits(sc, SPIFLASH_BB_MOSI, on); > +} > + > +static inline u32 getmiso(struct spi_device *spi) > +{ > + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); > + > + setbits(sc, SPIFLASH_BB_DIR, 1); > + return !!((litex_spiflash_spi_rr(sc, SPIFLASH_MISO) & 1)); > +} > + > +#define spidelay(nsecs) udelay(nsecs/1000) Unused. > + > +#include "spi-bitbang-txrx.h" > + > +static inline void litex_spiflash_spi_chipselect(struct litex_spiflash_spi *sc, int on) > +{ > + setbits(sc, SPIFLASH_BB_CSN, on); > +} > + > +static int litex_spiflash_spi_setup(struct spi_device *spi) > +{ > + struct spi_master *master = spi->master; > + struct device_d spi_dev = spi->dev; > + > + if (spi->bits_per_word != 8) { > + dev_err(master->dev, "master doesn't support %d bits per word requested by %s\n", > + spi->bits_per_word, spi_dev.name); > + return -EINVAL; > + } > + > + if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != SPI_MODE_0) { > + dev_err(master->dev, "master doesn't support SPI_MODE%d requested by %s\n", > + spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int litex_spiflash_spi_read(struct spi_device *spi, void *buf, size_t nbyte) > +{ > + ssize_t cnt = 0; > + u8 *rxf_buf = buf; > + > + while (cnt < nbyte) { > + *rxf_buf = bitbang_txrx_be_cpha1(spi, 1000, 1, 0, 8); > + rxf_buf++; > + cnt++; > + } > + > + return cnt; > +} > + > +static int litex_spiflash_spi_write(struct spi_device *spi, > + const void *buf, size_t nbyte) > +{ > + ssize_t cnt = 0; > + const u8 *txf_buf = buf; > + > + while (cnt < nbyte) { > + bitbang_txrx_be_cpha1(spi, 1000, 1, (u32)*txf_buf, 8); > + txf_buf++; > + cnt++; > + } > + > + return 0; > +} > + > +static int litex_spiflash_spi_transfer(struct spi_device *spi, struct spi_message *mesg) > +{ > + struct litex_spiflash_spi *sc = litex_spiflash_spidev_to_sp(spi); > + struct spi_transfer *t; > + > + mesg->actual_length = 0; > + > + /* activate chip select signal */ > + litex_spiflash_spi_chipselect(sc, 0); > + > + list_for_each_entry(t, &mesg->transfers, transfer_list) { > + > + if (t->tx_buf) > + litex_spiflash_spi_write(spi, t->tx_buf, t->len); > + > + if (t->rx_buf) > + litex_spiflash_spi_read(spi, t->rx_buf, t->len); > + > + mesg->actual_length += t->len; > + } > + > + /* inactivate chip select signal */ > + litex_spiflash_spi_chipselect(sc, 1); > + > + return 0; > +} > + > +static void litex_spiflash_spi_enable(struct litex_spiflash_spi *sp) > +{ > + u32 val; > + > + /* set SPIFLASH_BB_DIR = 0 */ > + val = SPIFLASH_BB_CSN | SPIFLASH_BB_CLK | SPIFLASH_BB_MOSI; > + litex_spiflash_spi_wr(sp, val, SPIFLASH_BITBANG); > + > + /* enable GPIO mode */ > + litex_spiflash_spi_wr(sp, 1, SPIFLASH_BITBANG_EN); > +} > + > +static void litex_spiflash_spi_disable(struct litex_spiflash_spi *sp) > +{ > + /* disable GPIO mode */ > + litex_spiflash_spi_wr(sp, 0, SPIFLASH_BITBANG_EN); > +} > + > +static int litex_spiflash_spi_probe(struct device_d *dev) > +{ > + struct resource *iores; > + struct spi_master *master; > + struct litex_spiflash_spi *litex_spiflash_spi; > + > + litex_spiflash_spi = xzalloc(sizeof(*litex_spiflash_spi)); > + dev->priv = litex_spiflash_spi; > + > + master = &litex_spiflash_spi->master; > + master->dev = dev; > + > + master->bus_num = dev->id; > + master->setup = litex_spiflash_spi_setup; > + master->transfer = litex_spiflash_spi_transfer; > + master->num_chipselect = 1; > + > + iores = dev_request_mem_resource(dev, 0); > + if (IS_ERR(iores)) > + return PTR_ERR(iores); > + litex_spiflash_spi->regs = IOMEM(iores->start); > + > + litex_spiflash_spi_enable(litex_spiflash_spi); > + > + /* inactivate chip select signal */ Nitpick s/inactivate/deactivate/ > + litex_spiflash_spi_chipselect(litex_spiflash_spi, 1); > + > + spi_register_master(master); > + > + return 0; > +} > + > +static void litex_spiflash_spi_remove(struct device_d *dev) > +{ > + struct litex_spiflash_spi *sp = dev->priv; > + > + litex_spiflash_spi_disable(sp); > +} > + > +static __maybe_unused struct of_device_id litex_spiflash_spi_dt_ids[] = { > + { > + .compatible = "litex,spiflash", > + }, > + { > + /* sentinel */ > + } > +}; > + > +static struct driver_d litex_spiflash_spi_driver = { > + .name = "litex-spiflash", > + .probe = litex_spiflash_spi_probe, > + .remove = litex_spiflash_spi_remove, > + .of_compatible = DRV_OF_COMPAT(litex_spiflash_spi_dt_ids), > +}; > +device_platform_driver(litex_spiflash_spi_driver); > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, 2021-05-05 at 13:08 +0300, Antony Pavlov wrote: > LiteX is a Migen-based System on Chip, supporting softcore > VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU. > > See https://github.com/enjoy-digital/litex and > https://github.com/litex-hub/linux-on-litex-vexriscv > for details. > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > --- > > > +config MACH_LITEX > + bool "litex family" > + select ARCH_RV32I > + select HAS_DEBUG_LL > + select HAS_NMON > + select USE_COMPRESSED_DTB > + select RISCV_SBI > + Hmm, there is also https://github.com/litex-hub/linux-on-litex-rocket/ which uses the 64-bit RocketChip CPU. How would that fit into this naming scheme? Would it be a different MACH? > +/dts-v1/; > + > +/ { > + compatible = "litex,vexriscv-soc-linux"; > + > + #address-cells = <1>; > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, 5 May 2021 12:39:14 +0200 Ahmad Fatoum <a.fatoum@pengutronix.de> wrote: Hi Ahmad! > Hello Antony, > > On 05.05.21 12:08, Antony Pavlov wrote: > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > > --- > > drivers/spi/Kconfig | 3 + > > drivers/spi/Makefile | 1 + > > drivers/spi/litex_spiflash.c | 242 +++++++++++++++++++++++++++++++++++ > > 3 files changed, 246 insertions(+) > > > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > > index 323d93efeb..714d30e909 100644 > > --- a/drivers/spi/Kconfig > > +++ b/drivers/spi/Kconfig > > @@ -74,6 +74,9 @@ config DRIVER_SPI_IMX_2_3 > > depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6 || ARCH_IMX7 || ARCH_IMX8MQ > > default y > > > > +config DRIVER_SPI_LITEX_SPIFLASH > > + bool "Litex SPIFLASH bitbang master driver" > > The SPI controller is called SPIFLASH? Yes. Simple SPI flash controller is part of litex repo: https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/spi_flash.py There is another LiteX SPI controller: https://github.com/litex-hub/litespi ... > > --- /dev/null > > +++ b/drivers/spi/litex_spiflash.c > > @@ -0,0 +1,242 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (C) 2020 Antony Pavlov <antonynpavlov@gmail.com> > > + * > > + */ > > + > > +#include <common.h> > > +#include <init.h> > > +#include <driver.h> > > +#include <spi/spi.h> > > +#include <io.h> > > +#include <clock.h> > > Unused now, I think. Yes, clock.h is unused. ... > > + > > +#define spidelay(nsecs) udelay(nsecs/1000) > > Unused. > > > + > > +#include "spi-bitbang-txrx.h" No, spidelay() is used inside of spi-bitbang-txrx.h. ... > > + > > + litex_spiflash_spi_enable(litex_spiflash_spi); > > + > > + /* inactivate chip select signal */ > > Nitpick s/inactivate/deactivate/ Quora.com says that there is no big difference (see https://www.quora.com/What-is-the-difference-between-deactivate-and-inactivate) but 'git grep' on linux kernel sources says that deactivate is more popular. -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, 05 May 2021 12:45:23 +0200 Jan Lübbe <jlu@pengutronix.de> wrote: > On Wed, 2021-05-05 at 13:08 +0300, Antony Pavlov wrote: > > LiteX is a Migen-based System on Chip, supporting softcore > > VexRiscv CPU, a 32-bits Linux Capable RISC-V CPU. > > > > See https://github.com/enjoy-digital/litex and > > https://github.com/litex-hub/linux-on-litex-vexriscv > > for details. > > > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > > --- > > > > > > > > +config MACH_LITEX > > + bool "litex family" > > + select ARCH_RV32I > > + select HAS_DEBUG_LL > > + select HAS_NMON > > + select USE_COMPRESSED_DTB > > + select RISCV_SBI > > + > > > Hmm, there is also https://github.com/litex-hub/linux-on-litex-rocket/ which > uses the 64-bit RocketChip CPU. How would that fit into this naming scheme? > Would it be a different MACH? Rocket is a 64-bit core, VexRiscv is a 32-bit core. All LiteX family SoC use the same peripheral IP cores, but different CPU cores. The situation is similar to MIPS Malta FPGA devboard, main FPGA can be burned with very different CPU bitstreams: config MIPS_MALTA bool "MIPS Malta board" ... select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 select SYS_HAS_CPU_MIPS32_R3_5 select SYS_HAS_CPU_MIPS32_R5 select SYS_HAS_CPU_MIPS32_R6 select SYS_HAS_CPU_MIPS64_R1 select SYS_HAS_CPU_MIPS64_R2 select SYS_HAS_CPU_MIPS64_R6 select SYS_HAS_CPU_NEVADA select SYS_HAS_CPU_RM7000 I'll investigate the problem more carefully. Thanks for noting! -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, May 05, 2021 at 01:08:57PM +0300, Antony Pavlov wrote: > LiteEth provides a small footprint and configurable Ethernet core. > > LiteEth is part of LiteX libraries whose aims are to lower entry level of > complex FPGA cores by providing simple, elegant and efficient implementations > of components used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller... > > Using Migen to describe the HDL allows the core to be highly and easily configurable. > > LiteEth can be used as LiteX library or can be integrated with your standard > design flow by generating the verilog rtl that you will use as a standard core. > > See https://github.com/enjoy-digital/liteeth for details. > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > Signed-off-by: Marek Czerski <m.czerski@ap-tech.pl> > --- > drivers/net/Kconfig | 8 + > drivers/net/Makefile | 1 + > drivers/net/liteeth.c | 376 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 385 insertions(+) > > Cc: Marek Czerski <m.czerski@ap-tech.pl> > > diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig > index 0d55ea7a3b..4818f52603 100644 > --- a/drivers/net/Kconfig > +++ b/drivers/net/Kconfig > @@ -271,6 +271,14 @@ config TSE_USE_DEDICATED_DESC_MEM > reserved with a malloc but directly mapped to the memory > address (defined in config.h) > > +config DRIVER_NET_LITEETH > + bool "LiteX ethernet driver" > + select PHYLIB > + select MDIO_BITBANG > + help > + This option enables support for the LiteX LiteEth > + ethernet IP core. > + > source "drivers/net/phy/Kconfig" > source "drivers/net/usb/Kconfig" > > diff --git a/drivers/net/Makefile b/drivers/net/Makefile > index 656d45a868..bb751943f6 100644 > --- a/drivers/net/Makefile > +++ b/drivers/net/Makefile > @@ -36,3 +36,4 @@ obj-$(CONFIG_DRIVER_NET_TAP) += tap.o > obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o > obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o > obj-$(CONFIG_DRIVER_NET_AG71XX) += ag71xx.o > +obj-$(CONFIG_DRIVER_NET_LITEETH) += liteeth.o > diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c > new file mode 100644 > index 0000000000..137cb854c5 > --- /dev/null > +++ b/drivers/net/liteeth.c > @@ -0,0 +1,376 @@ > +/* Could you please add an SPDX-License-Identifier header [1] here? (Maybe also for other newly introduced files in this series, haven't checked.) [1]: https://www.kernel.org/doc/html/latest/process/license-rules.html - Roland > + * LiteX Liteeth Ethernet > + * > + * Copyright 2017 Joel Stanley <joel@jms.id.au> > + * > + * Ported to barebox from linux kernel > + * Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov@gmail.com> > + * Copyright (C) 2021 Marek Czerski <m.czerski@ap-tech.pl> > + * > + */ > + > +#include <common.h> > +#include <io.h> > +#include <linux/iopoll.h> > +#include <malloc.h> > +#include <net.h> > +#include <init.h> > +#include <of_net.h> > +#include <linux/phy.h> > +#include <linux/mdio-bitbang.h> > + > +#define DRV_NAME "liteeth" > + > +#define LITEETH_WRITER_SLOT 0x00 > +#define LITEETH_WRITER_LENGTH 0x04 > +#define LITEETH_WRITER_ERRORS 0x08 > +#define LITEETH_WRITER_EV_STATUS 0x0c > +#define LITEETH_WRITER_EV_PENDING 0x10 > +#define LITEETH_WRITER_EV_ENABLE 0x14 > +#define LITEETH_READER_START 0x18 > +#define LITEETH_READER_READY 0x1c > +#define LITEETH_READER_LEVEL 0x20 > +#define LITEETH_READER_SLOT 0x24 > +#define LITEETH_READER_LENGTH 0x28 > +#define LITEETH_READER_EV_STATUS 0x2c > +#define LITEETH_READER_EV_PENDING 0x30 > +#define LITEETH_READER_EV_ENABLE 0x34 > +#define LITEETH_PREAMBLE_CRC 0x38 > +#define LITEETH_PREAMBLE_ERRORS 0x3c > +#define LITEETH_CRC_ERRORS 0x40 > + > +#define LITEETH_PHY_CRG_RESET 0x00 > +#define LITEETH_MDIO_W 0x04 > +#define MDIO_W_CLK BIT(0) > +#define MDIO_W_OE BIT(1) > +#define MDIO_W_DO BIT(2) > + > +#define LITEETH_MDIO_R 0x08 > +#define MDIO_R_DI BIT(0) > + > +#define LITEETH_BUFFER_SIZE 0x800 > +#define MAX_PKT_SIZE LITEETH_BUFFER_SIZE > + > +struct liteeth { > + struct device_d *dev; > + struct eth_device edev; > + void __iomem *base; > + void __iomem *mdio_base; > + struct mii_bus *mii_bus; > + struct mdiobb_ctrl mdiobb; > + > + /* Link management */ > + int cur_duplex; > + int cur_speed; > + > + /* Tx */ > + int tx_slot; > + int num_tx_slots; > + void __iomem *tx_base; > + > + /* Rx */ > + int rx_slot; > + int num_rx_slots; > + void __iomem *rx_base; > +}; > + > +static inline void litex_write8(void __iomem *addr, u8 val) > +{ > + writeb(val, addr); > +} > + > +static inline void litex_write16(void __iomem *addr, u16 val) > +{ > + writew(val, addr); > +} > + > +static inline u8 litex_read8(void __iomem *addr) > +{ > + return readb(addr); > +} > + > +static inline u32 litex_read32(void __iomem *addr) > +{ > + return readl(addr); > +} > + > +static void liteeth_mdio_w_modify(struct liteeth *priv, u8 clear, u8 set) > +{ > + void __iomem *mdio_w = priv->mdio_base + LITEETH_MDIO_W; > + > + litex_write8(mdio_w, (litex_read8(mdio_w) & ~clear) | set); > +} > + > +static void liteeth_mdio_ctrl(struct mdiobb_ctrl *ctrl, u8 mask, int set) > +{ > + struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb); > + > + liteeth_mdio_w_modify(priv, mask, set ? mask : 0); > +} > + > +/* MDC pin control */ > +static void liteeth_set_mdc(struct mdiobb_ctrl *ctrl, int level) > +{ > + liteeth_mdio_ctrl(ctrl, MDIO_W_CLK, level); > +} > + > +/* Data I/O pin control */ > +static void liteeth_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output) > +{ > + liteeth_mdio_ctrl(ctrl, MDIO_W_OE, output); > +} > + > +/* Set data bit */ > +static void liteeth_set_mdio_data(struct mdiobb_ctrl *ctrl, int value) > +{ > + liteeth_mdio_ctrl(ctrl, MDIO_W_DO, value); > +} > + > +/* Get data bit */ > +static int liteeth_get_mdio_data(struct mdiobb_ctrl *ctrl) > +{ > + struct liteeth *priv = container_of(ctrl, struct liteeth, mdiobb); > + > + return (litex_read8(priv->mdio_base + LITEETH_MDIO_R) & MDIO_R_DI) != 0; > +} > + > +/* MDIO bus control struct */ > +static struct mdiobb_ops bb_ops = { > + .set_mdc = liteeth_set_mdc, > + .set_mdio_dir = liteeth_set_mdio_dir, > + .set_mdio_data = liteeth_set_mdio_data, > + .get_mdio_data = liteeth_get_mdio_data, > +}; > + > +static int liteeth_init_dev(struct eth_device *edev) > +{ > + return 0; > +} > + > +static int liteeth_eth_open(struct eth_device *edev) > +{ > + struct liteeth *priv = edev->priv; > + int ret; > + > + /* Disable events */ > + litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0); > + litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0); > + > + /* Clear pending events? */ > + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, 1); > + litex_write8(priv->base + LITEETH_READER_EV_PENDING, 1); > + > + ret = phy_device_connect(edev, priv->mii_bus, -1, NULL, 0, -1); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int liteeth_eth_send(struct eth_device *edev, void *packet, > + int packet_length) > +{ > + struct liteeth *priv = edev->priv; > + void *txbuffer; > + int ret; > + u8 val; > + u8 reg; > + > + reg = litex_read8(priv->base + LITEETH_READER_EV_PENDING); > + if (reg) { > + litex_write8(priv->base + LITEETH_READER_EV_PENDING, reg); > + } > + > + /* Reject oversize packets */ > + if (unlikely(packet_length > MAX_PKT_SIZE)) { > + dev_err(priv->dev, "tx packet too big\n"); > + goto drop; > + } > + > + txbuffer = priv->tx_base + priv->tx_slot * LITEETH_BUFFER_SIZE; > + memcpy(txbuffer, packet, packet_length); > + litex_write8(priv->base + LITEETH_READER_SLOT, priv->tx_slot); > + litex_write16(priv->base + LITEETH_READER_LENGTH, packet_length); > + > + ret = readb_poll_timeout(priv->base + LITEETH_READER_READY, > + val, val, 1000); > + if (ret == -ETIMEDOUT) { > + dev_err(priv->dev, "LITEETH_READER_READY timed out\n"); > + goto drop; > + } > + > + litex_write8(priv->base + LITEETH_READER_START, 1); > + > + priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots; > + > +drop: > + return 0; > +} > + > +static int liteeth_eth_rx(struct eth_device *edev) > +{ > + struct liteeth *priv = edev->priv; > + u8 rx_slot; > + int len = 0; > + u8 reg; > + > + reg = litex_read8(priv->base + LITEETH_WRITER_EV_PENDING); > + if (!reg) { > + goto done; > + } > + > + len = litex_read32(priv->base + LITEETH_WRITER_LENGTH); > + if (len == 0 || len > 2048) { > + len = 0; > + dev_err(priv->dev, "%s: invalid len %d\n", __func__, len); > + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg); > + goto done; > + } > + > + rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT); > + > + memcpy(NetRxPackets[0], priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len); > + > + net_receive(edev, NetRxPackets[0], len); > + > + litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg); > + > +done: > + return len; > +} > + > +static void liteeth_eth_halt(struct eth_device *edev) > +{ > + struct liteeth *priv = edev->priv; > + > + litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0); > + litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0); > +} > + > +static void liteeth_reset_hw(struct liteeth *priv) > +{ > + /* Reset, twice */ > + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0); > + udelay(10); > + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 1); > + udelay(10); > + litex_write8(priv->base + LITEETH_PHY_CRG_RESET, 0); > + udelay(10); > +} > + > +static int liteeth_get_ethaddr(struct eth_device *edev, unsigned char *m) > +{ > + return 0; > +} > + > +static int liteeth_set_ethaddr(struct eth_device *edev, > + const unsigned char *mac_addr) > +{ > + return 0; > +} > + > +static int liteeth_probe(struct device_d *dev) > +{ > + struct device_node *np = dev->device_node; > + struct eth_device *edev; > + void __iomem *buf_base; > + struct liteeth *priv; > + int err; > + > + priv = xzalloc(sizeof(struct liteeth)); > + edev = &priv->edev; > + edev->priv = priv; > + priv->dev = dev; > + > + priv->base = dev_request_mem_region(dev, 0); > + if (IS_ERR(priv->base)) { > + err = PTR_ERR(priv->base); > + goto err; > + } > + > + priv->mdio_base = dev_request_mem_region(dev, 1); > + if (IS_ERR(priv->mdio_base)) { > + err = PTR_ERR(priv->mdio_base); > + goto err; > + } > + > + buf_base = dev_request_mem_region(dev, 2); > + if (IS_ERR(buf_base)) { > + err = PTR_ERR(buf_base); > + goto err; > + } > + > + err = of_property_read_u32(np, "rx-fifo-depth", > + &priv->num_rx_slots); > + if (err) { > + dev_err(dev, "unable to get rx-fifo-depth\n"); > + goto err; > + } > + > + err = of_property_read_u32(np, "tx-fifo-depth", > + &priv->num_tx_slots); > + if (err) { > + dev_err(dev, "unable to get tx-fifo-depth\n"); > + goto err; > + } > + > + /* Rx slots */ > + priv->rx_base = buf_base; > + priv->rx_slot = 0; > + > + /* Tx slots come after Rx slots */ > + priv->tx_base = buf_base + priv->num_rx_slots * LITEETH_BUFFER_SIZE; > + priv->tx_slot = 0; > + > + edev->init = liteeth_init_dev; > + edev->open = liteeth_eth_open; > + edev->send = liteeth_eth_send; > + edev->recv = liteeth_eth_rx; > + edev->get_ethaddr = liteeth_get_ethaddr; > + edev->set_ethaddr = liteeth_set_ethaddr; > + edev->halt = liteeth_eth_halt; > + edev->parent = dev; > + > + priv->mdiobb.ops = &bb_ops; > + > + priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb); > + priv->mii_bus->parent = dev; > + > + liteeth_reset_hw(priv); > + > + err = eth_register(edev); > + if (err) { > + dev_err(dev, "failed to register edev\n"); > + goto err; > + } > + > + err = mdiobus_register(priv->mii_bus); > + if (err) { > + dev_err(dev, "failed to register mii_bus\n"); > + goto err; > + } > + > + dev_info(dev, DRV_NAME " driver registered\n"); > + > + return 0; > + > +err: > + return err; > +} > + > +static const struct of_device_id liteeth_dt_ids[] = { > + { > + .compatible = "litex,liteeth" > + }, { > + } > +}; > + > +static struct driver_d liteeth_driver = { > + .name = DRV_NAME, > + .probe = liteeth_probe, > + .of_compatible = DRV_OF_COMPAT(liteeth_dt_ids), > +}; > +device_platform_driver(liteeth_driver); > + > +MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>"); > +MODULE_LICENSE("GPL"); > -- > 2.31.1 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox > -- Roland Hieber, Pengutronix e.K. | r.hieber@pengutronix.de | Steuerwalder Str. 21 | https://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Thu, 6 May 2021 12:10:38 +0200 Roland Hieber <rhi@pengutronix.de> wrote: Hi ! > On Wed, May 05, 2021 at 01:08:57PM +0300, Antony Pavlov wrote: > > LiteEth provides a small footprint and configurable Ethernet core. > > > > LiteEth is part of LiteX libraries whose aims are to lower entry level of > > complex FPGA cores by providing simple, elegant and efficient implementations > > of components used in today's SoC such as Ethernet, SATA, PCIe, SDRAM Controller... > > > > Using Migen to describe the HDL allows the core to be highly and easily configurable. > > > > LiteEth can be used as LiteX library or can be integrated with your standard > > design flow by generating the verilog rtl that you will use as a standard core. > > > > See https://github.com/enjoy-digital/liteeth for details. > > > > Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com> > > Signed-off-by: Marek Czerski <m.czerski@ap-tech.pl> > > --- > > drivers/net/Kconfig | 8 + > > drivers/net/Makefile | 1 + > > drivers/net/liteeth.c | 376 ++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 385 insertions(+) > > > > Cc: Marek Czerski <m.czerski@ap-tech.pl> > > ... > > diff --git a/drivers/net/Makefile b/drivers/net/Makefile > > index 656d45a868..bb751943f6 100644 > > --- a/drivers/net/Makefile > > +++ b/drivers/net/Makefile > > @@ -36,3 +36,4 @@ obj-$(CONFIG_DRIVER_NET_TAP) += tap.o > > obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o > > obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o > > obj-$(CONFIG_DRIVER_NET_AG71XX) += ag71xx.o > > +obj-$(CONFIG_DRIVER_NET_LITEETH) += liteeth.o > > diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c > > new file mode 100644 > > index 0000000000..137cb854c5 > > --- /dev/null > > +++ b/drivers/net/liteeth.c > > @@ -0,0 +1,376 @@ > > +/* > > Could you please add an SPDX-License-Identifier header [1] here? (Maybe > also for other newly introduced files in this series, haven't checked.) > > [1]: https://www.kernel.org/doc/html/latest/process/license-rules.html > Original driver by Joel Stanley contains MODULE_LICENSE("GPL"). This is a bit confusing because I can't determine exact GPL version. To: Joel Stanley Can I add `SPDX-License-Identifier: GPL-2.0-or-later` or `SPDX-License-Identifier: GPL-2.0-only` to the LiteEth barebox driver header? > > + * LiteX Liteeth Ethernet > > + * > > + * Copyright 2017 Joel Stanley <joel@jms.id.au> > > + * > > + * Ported to barebox from linux kernel > > + * Copyright (C) 2019-2021 Antony Pavlov <antonynpavlov@gmail.com> > > + * Copyright (C) 2021 Marek Czerski <m.czerski@ap-tech.pl> > > + * > > + */ -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox