diff options
author | Tom Rini <trini@konsulko.com> | 2021-01-18 16:04:28 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-01-18 16:04:28 +0300 |
commit | 59e4e391df8c254299b1342c3cfa3390e9f1e895 (patch) | |
tree | 2dcb7f6fc8b1caab173f2abdbe78f368d254d08c /drivers | |
parent | b5b0237d0216db34605ca54b83588fcfcf5e63a8 (diff) | |
parent | 9e550e18305fb31af83bfb72d16e86d8c054fb65 (diff) | |
download | u-boot-59e4e391df8c254299b1342c3cfa3390e9f1e895.tar.xz |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-riscv
- Update qemu-riscv.rst build instructions.
- Add support for SPI on Kendryte K210.
- Add Microchip PolarFire SoC Icicle Kit support.
- Add support for an early timer.
- Select TIMER_EARLY to avoid infinite recursion for Trace.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/Kconfig | 1 | ||||
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/microchip/Kconfig | 5 | ||||
-rw-r--r-- | drivers/clk/microchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk.c | 123 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk.h | 44 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk_cfg.c | 152 | ||||
-rw-r--r-- | drivers/clk/microchip/mpfs_clk_periph.c | 187 | ||||
-rw-r--r-- | drivers/net/macb.c | 144 | ||||
-rw-r--r-- | drivers/net/macb.h | 6 | ||||
-rw-r--r-- | drivers/timer/andes_plmt_timer.c | 21 | ||||
-rw-r--r-- | drivers/timer/riscv_timer.c | 21 | ||||
-rw-r--r-- | drivers/timer/sifive_clint_timer.c | 21 |
13 files changed, 707 insertions, 20 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index db06f276ec..4aeaa0cd58 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -165,6 +165,7 @@ source "drivers/clk/exynos/Kconfig" source "drivers/clk/imx/Kconfig" source "drivers/clk/kendryte/Kconfig" source "drivers/clk/meson/Kconfig" +source "drivers/clk/microchip/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" source "drivers/clk/renesas/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f8383e523d..645709b855 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o obj-$(CONFIG_CLK_K210) += kendryte/ obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o +obj-$(CONFIG_CLK_MPFS) += microchip/ obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig new file mode 100644 index 0000000000..b70241559d --- /dev/null +++ b/drivers/clk/microchip/Kconfig @@ -0,0 +1,5 @@ +config CLK_MPFS + bool "Clock support for Microchip PolarFire SoC" + depends on CLK && CLK_CCF + help + This enables support clock driver for Microchip PolarFire SoC platform. diff --git a/drivers/clk/microchip/Makefile b/drivers/clk/microchip/Makefile new file mode 100644 index 0000000000..904b345d75 --- /dev/null +++ b/drivers/clk/microchip/Makefile @@ -0,0 +1 @@ +obj-y += mpfs_clk.o mpfs_clk_cfg.o mpfs_clk_periph.o diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c new file mode 100644 index 0000000000..722c79b7c0 --- /dev/null +++ b/drivers/clk/microchip/mpfs_clk.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <dm/device.h> +#include <dm/devres.h> +#include <dm/uclass.h> +#include <linux/err.h> + +#include "mpfs_clk.h" + +/* All methods are delegated to CCF clocks */ + +static ulong mpfs_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_get_rate(c); +} + +static ulong mpfs_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return clk_set_rate(c, rate); +} + +static int mpfs_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *p; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + + err = clk_get_by_id(parent->id, &p); + if (err) + return err; + + return clk_set_parent(c, p); +} + +static int mpfs_clk_endisable(struct clk *clk, bool enable) +{ + struct clk *c; + int err = clk_get_by_id(clk->id, &c); + + if (err) + return err; + return enable ? clk_enable(c) : clk_disable(c); +} + +static int mpfs_clk_enable(struct clk *clk) +{ + return mpfs_clk_endisable(clk, true); +} + +static int mpfs_clk_disable(struct clk *clk) +{ + return mpfs_clk_endisable(clk, false); +} + +static int mpfs_clk_probe(struct udevice *dev) +{ + int ret; + void __iomem *base; + u32 clk_rate; + const char *parent_clk_name; + struct clk *clk = dev_get_priv(dev); + + base = dev_read_addr_ptr(dev); + if (!base) + return -EINVAL; + + ret = clk_get_by_index(dev, 0, clk); + if (ret) + return ret; + + dev_read_u32(clk->dev, "clock-frequency", &clk_rate); + parent_clk_name = clk->dev->name; + + ret = mpfs_clk_register_cfgs(base, clk_rate, parent_clk_name); + if (ret) + return ret; + + ret = mpfs_clk_register_periphs(base, clk_rate, "clk_ahb"); + + return ret; +} + +static const struct clk_ops mpfs_clk_ops = { + .set_rate = mpfs_clk_set_rate, + .get_rate = mpfs_clk_get_rate, + .set_parent = mpfs_clk_set_parent, + .enable = mpfs_clk_enable, + .disable = mpfs_clk_disable, +}; + +static const struct udevice_id mpfs_of_match[] = { + { .compatible = "microchip,mpfs-clkcfg" }, + { } +}; + +U_BOOT_DRIVER(mpfs_clk) = { + .name = "mpfs_clk", + .id = UCLASS_CLK, + .of_match = mpfs_of_match, + .ops = &mpfs_clk_ops, + .probe = mpfs_clk_probe, + .priv_auto = sizeof(struct clk), +}; diff --git a/drivers/clk/microchip/mpfs_clk.h b/drivers/clk/microchip/mpfs_clk.h new file mode 100644 index 0000000000..8e3fc55ae3 --- /dev/null +++ b/drivers/clk/microchip/mpfs_clk.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ +#ifndef __MICROCHIP_MPFS_CLK_H +#define __MICROCHIP_MPFS_CLK_H + +#include <linux/clk-provider.h> +/** + * mpfs_clk_register_cfgs() - register configuration clocks + * + * @base: base address of the mpfs system register. + * @clk_rate: the mpfs pll clock rate. + * @parent_name: a pointer to parent clock name. + * @return zero on success, or a negative error code. + */ +int mpfs_clk_register_cfgs(void __iomem *base, u32 clk_rate, + const char *parent_name); +/** + * mpfs_clk_register_periphs() - register peripheral clocks + * + * @base: base address of the mpfs system register. + * @clk_rate: the mpfs pll clock rate. + * @parent_name: a pointer to parent clock name. + * @return zero on success, or a negative error code. + */ +int mpfs_clk_register_periphs(void __iomem *base, u32 clk_rate, + const char *parent_name); +/** + * divider_get_val() - get the clock divider value + * + * @rate: requested clock rate. + * @parent_rate: parent clock rate. + * @table: a pointer to clock divider table. + * @width: width of the divider bit field. + * @flags: common clock framework flags. + * @return divider value on success, or a negative error code. + */ +int divider_get_val(unsigned long rate, unsigned long parent_rate, + const struct clk_div_table *table, + u8 width, unsigned long flags); + +#endif /* __MICROCHIP_MPFS_CLK_H */ diff --git a/drivers/clk/microchip/mpfs_clk_cfg.c b/drivers/clk/microchip/mpfs_clk_cfg.c new file mode 100644 index 0000000000..fefddd1413 --- /dev/null +++ b/drivers/clk/microchip/mpfs_clk_cfg.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <asm/io.h> +#include <dm/device.h> +#include <dm/devres.h> +#include <dm/uclass.h> +#include <dt-bindings/clock/microchip-mpfs-clock.h> +#include <linux/err.h> + +#include "mpfs_clk.h" + +#define MPFS_CFG_CLOCK "mpfs_cfg_clock" + +#define REG_CLOCK_CONFIG_CR 0x08 + +/* CPU and AXI clock divisors */ +static const struct clk_div_table mpfs_div_cpu_axi_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 0, 0 } +}; + +/* AHB clock divisors */ +static const struct clk_div_table mpfs_div_ahb_table[] = { + { 1, 2 }, { 2, 4}, { 3, 8 }, + { 0, 0 } +}; + +/** + * struct mpfs_cfg_clock - per instance of configuration clock + * @id: index of a configuration clock + * @name: name of a configuration clock + * @shift: shift to the divider bit field of a configuration clock + * @width: width of the divider bit field of a configation clock + * @table: clock divider table instance + * @flags: common clock framework flags + */ +struct mpfs_cfg_clock { + unsigned int id; + const char *name; + u8 shift; + u8 width; + const struct clk_div_table *table; + unsigned long flags; +}; + +/** + * struct mpfs_cfg_hw_clock - hardware configuration clock (cpu, axi, ahb) + * @cfg: configuration clock instance + * @sys_base: base address of the mpfs system register + * @prate: the pll clock rate + * @hw: clock instance + */ +struct mpfs_cfg_hw_clock { + struct mpfs_cfg_clock cfg; + void __iomem *sys_base; + u32 prate; + struct clk hw; +}; + +#define to_mpfs_cfg_clk(_hw) container_of(_hw, struct mpfs_cfg_hw_clock, hw) + +static ulong mpfs_cfg_clk_recalc_rate(struct clk *hw) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + void __iomem *base_addr = cfg_hw->sys_base; + unsigned long rate; + u32 val; + + val = readl(base_addr + REG_CLOCK_CONFIG_CR) >> cfg->shift; + val &= clk_div_mask(cfg->width); + rate = cfg_hw->prate / (1u << val); + hw->rate = rate; + + return rate; +} + +static ulong mpfs_cfg_clk_set_rate(struct clk *hw, ulong rate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + void __iomem *base_addr = cfg_hw->sys_base; + u32 val; + int divider_setting; + + divider_setting = divider_get_val(rate, cfg_hw->prate, cfg->table, cfg->width, cfg->flags); + + if (divider_setting < 0) + return divider_setting; + + val = readl(base_addr + REG_CLOCK_CONFIG_CR); + val &= ~(clk_div_mask(cfg->width) << cfg_hw->cfg.shift); + val |= divider_setting << cfg->shift; + writel(val, base_addr + REG_CLOCK_CONFIG_CR); + + return clk_get_rate(hw); +} + +#define CLK_CFG(_id, _name, _shift, _width, _table, _flags) { \ + .cfg.id = _id, \ + .cfg.name = _name, \ + .cfg.shift = _shift, \ + .cfg.width = _width, \ + .cfg.table = _table, \ + .cfg.flags = _flags, \ + } + +static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = { + CLK_CFG(CLK_CPU, "clk_cpu", 0, 2, mpfs_div_cpu_axi_table, 0), + CLK_CFG(CLK_AXI, "clk_axi", 2, 2, mpfs_div_cpu_axi_table, 0), + CLK_CFG(CLK_AHB, "clk_ahb", 4, 2, mpfs_div_ahb_table, 0), +}; + +int mpfs_clk_register_cfgs(void __iomem *base, u32 clk_rate, + const char *parent_name) +{ + int ret; + int i, id, num_clks; + const char *name; + struct clk *hw; + + num_clks = ARRAY_SIZE(mpfs_cfg_clks); + for (i = 0; i < num_clks; i++) { + hw = &mpfs_cfg_clks[i].hw; + mpfs_cfg_clks[i].sys_base = base; + mpfs_cfg_clks[i].prate = clk_rate; + name = mpfs_cfg_clks[i].cfg.name; + ret = clk_register(hw, MPFS_CFG_CLOCK, name, parent_name); + if (ret) + ERR_PTR(ret); + id = mpfs_cfg_clks[i].cfg.id; + clk_dm(id, hw); + } + return 0; +} + +const struct clk_ops mpfs_cfg_clk_ops = { + .set_rate = mpfs_cfg_clk_set_rate, + .get_rate = mpfs_cfg_clk_recalc_rate, +}; + +U_BOOT_DRIVER(mpfs_cfg_clock) = { + .name = MPFS_CFG_CLOCK, + .id = UCLASS_CLK, + .ops = &mpfs_cfg_clk_ops, +}; diff --git a/drivers/clk/microchip/mpfs_clk_periph.c b/drivers/clk/microchip/mpfs_clk_periph.c new file mode 100644 index 0000000000..61d90eb4a8 --- /dev/null +++ b/drivers/clk/microchip/mpfs_clk_periph.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <asm/io.h> +#include <dm/device.h> +#include <dm/devres.h> +#include <dm/uclass.h> +#include <dt-bindings/clock/microchip-mpfs-clock.h> +#include <linux/err.h> + +#include "mpfs_clk.h" + +#define MPFS_PERIPH_CLOCK "mpfs_periph_clock" + +#define REG_CLOCK_CONFIG_CR 0x08 +#define REG_SUBBLK_CLOCK_CR 0x84 +#define REG_SUBBLK_RESET_CR 0x88 + +#define CFG_CPU_SHIFT 0x0 +#define CFG_AXI_SHIFT 0x2 +#define CFG_AHB_SHIFT 0x4 +#define CFG_WIDTH 0x2 + +/** + * struct mpfs_periph_clock - per instance of peripheral clock + * @id: index of a peripheral clock + * @name: name of a peripheral clock + * @shift: shift to a peripheral clock bit field + * @flags: common clock framework flags + */ +struct mpfs_periph_clock { + unsigned int id; + const char *name; + u8 shift; + unsigned long flags; +}; + +/** + * struct mpfs_periph_hw_clock - hardware peripheral clock + * @periph: peripheral clock instance + * @sys_base: base address of the mpfs system register + * @prate: the pll clock rate + * @hw: clock instance + */ +struct mpfs_periph_hw_clock { + struct mpfs_periph_clock periph; + void __iomem *sys_base; + u32 prate; + struct clk hw; +}; + +#define to_mpfs_periph_clk(_hw) container_of(_hw, struct mpfs_periph_hw_clock, hw) + +static int mpfs_periph_clk_enable(struct clk *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + void __iomem *base_addr = periph_hw->sys_base; + u32 reg, val; + + if (periph->flags != CLK_IS_CRITICAL) { + reg = readl(base_addr + REG_SUBBLK_RESET_CR); + val = reg & ~(1u << periph->shift); + writel(val, base_addr + REG_SUBBLK_RESET_CR); + + reg = readl(base_addr + REG_SUBBLK_CLOCK_CR); + val = reg | (1u << periph->shift); + writel(val, base_addr + REG_SUBBLK_CLOCK_CR); + } + + return 0; +} + +static int mpfs_periph_clk_disable(struct clk *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + void __iomem *base_addr = periph_hw->sys_base; + u32 reg, val; + + if (periph->flags != CLK_IS_CRITICAL) { + reg = readl(base_addr + REG_SUBBLK_RESET_CR); + val = reg | (1u << periph->shift); + writel(val, base_addr + REG_SUBBLK_RESET_CR); + + reg = readl(base_addr + REG_SUBBLK_CLOCK_CR); + val = reg & ~(1u << periph->shift); + writel(val, base_addr + REG_SUBBLK_CLOCK_CR); + } + + return 0; +} + +static ulong mpfs_periph_clk_recalc_rate(struct clk *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + void __iomem *base_addr = periph_hw->sys_base; + unsigned long rate; + u32 val; + + val = readl(base_addr + REG_CLOCK_CONFIG_CR) >> CFG_AHB_SHIFT; + val &= clk_div_mask(CFG_WIDTH); + rate = periph_hw->prate / (1u << val); + hw->rate = rate; + + return rate; +} + +#define CLK_PERIPH(_id, _name, _shift, _flags) { \ + .periph.id = _id, \ + .periph.name = _name, \ + .periph.shift = _shift, \ + .periph.flags = _flags, \ + } + +static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { + CLK_PERIPH(CLK_ENVM, "clk_periph_envm", 0, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_MAC0, "clk_periph_mac0", 1, 0), + CLK_PERIPH(CLK_MAC1, "clk_periph_mac1", 2, 0), + CLK_PERIPH(CLK_MMC, "clk_periph_mmc", 3, 0), + CLK_PERIPH(CLK_TIMER, "clk_periph_timer", 4, 0), + CLK_PERIPH(CLK_MMUART0, "clk_periph_mmuart0", 5, 0), + CLK_PERIPH(CLK_MMUART1, "clk_periph_mmuart1", 6, 0), + CLK_PERIPH(CLK_MMUART2, "clk_periph_mmuart2", 7, 0), + CLK_PERIPH(CLK_MMUART3, "clk_periph_mmuart3", 8, 0), + CLK_PERIPH(CLK_MMUART4, "clk_periph_mmuart4", 9, 0), + CLK_PERIPH(CLK_SPI0, "clk_periph_spi0", 10, 0), + CLK_PERIPH(CLK_SPI1, "clk_periph_spi1", 11, 0), + CLK_PERIPH(CLK_I2C0, "clk_periph_i2c0", 12, 0), + CLK_PERIPH(CLK_I2C1, "clk_periph_i2c1", 13, 0), + CLK_PERIPH(CLK_CAN0, "clk_periph_can0", 14, 0), + CLK_PERIPH(CLK_CAN1, "clk_periph_can1", 15, 0), + CLK_PERIPH(CLK_USB, "clk_periph_usb", 16, 0), + CLK_PERIPH(CLK_RTC, "clk_periph_rtc", 18, 0), + CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", 19, 0), + CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", 20, 0), + CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", 21, 0), + CLK_PERIPH(CLK_GPIO2, "clk_periph_gpio2", 22, 0), + CLK_PERIPH(CLK_DDRC, "clk_periph_ddrc", 23, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_FIC0, "clk_periph_fic0", 24, 0), + CLK_PERIPH(CLK_FIC1, "clk_periph_fic1", 25, 0), + CLK_PERIPH(CLK_FIC2, "clk_periph_fic2", 26, 0), + CLK_PERIPH(CLK_FIC3, "clk_periph_fic3", 27, 0), + CLK_PERIPH(CLK_ATHENA, "clk_periph_athena", 28, 0), + CLK_PERIPH(CLK_CFM, "clk_periph_cfm", 29, 0), +}; + +int mpfs_clk_register_periphs(void __iomem *base, u32 clk_rate, + const char *parent_name) +{ + int ret; + int i, id, num_clks; + const char *name; + struct clk *hw; + + num_clks = ARRAY_SIZE(mpfs_periph_clks); + for (i = 0; i < num_clks; i++) { + hw = &mpfs_periph_clks[i].hw; + mpfs_periph_clks[i].sys_base = base; + mpfs_periph_clks[i].prate = clk_rate; + name = mpfs_periph_clks[i].periph.name; + ret = clk_register(hw, MPFS_PERIPH_CLOCK, name, parent_name); + if (ret) + ERR_PTR(ret); + id = mpfs_periph_clks[i].periph.id; + clk_dm(id, hw); + } + + return 0; +} + +const struct clk_ops mpfs_periph_clk_ops = { + .enable = mpfs_periph_clk_enable, + .disable = mpfs_periph_clk_disable, + .get_rate = mpfs_periph_clk_recalc_rate, +}; + +U_BOOT_DRIVER(mpfs_periph_clock) = { + .name = MPFS_PERIPH_CLOCK, + .id = UCLASS_CLK, + .ops = &mpfs_periph_clk_ops, +}; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index e287c29e69..2225b33ff6 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -83,7 +83,16 @@ struct macb_dma_desc { u32 ctrl; }; -#define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) +struct macb_dma_desc_64 { + u32 addrh; + u32 unused; +}; + +#define HW_DMA_CAP_32B 0 +#define HW_DMA_CAP_64B 1 + +#define DMA_DESC_SIZE 16 +#define DMA_DESC_BYTES(n) ((n) * DMA_DESC_SIZE) #define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) #define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) #define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1)) @@ -137,6 +146,7 @@ struct macb_device { struct macb_config { unsigned int dma_burst_length; + unsigned int hw_dma_cap; int (*clk_init)(struct udevice *dev, ulong rate); }; @@ -307,6 +317,24 @@ static inline void macb_invalidate_rx_buffer(struct macb_device *macb) #if defined(CONFIG_CMD_NET) +static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc) +{ + return (struct macb_dma_desc_64 *)((void *)desc + + sizeof(struct macb_dma_desc)); +} + +static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc, + ulong addr) +{ + struct macb_dma_desc_64 *desc_64; + + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + desc_64 = macb_64b_desc(desc); + desc_64->addrh = upper_32_bits(addr); + } + desc->addr = lower_32_bits(addr); +} + static int _macb_send(struct macb_device *macb, const char *name, void *packet, int length) { @@ -325,8 +353,12 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet, macb->tx_head++; } + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + tx_head = tx_head * 2; + macb->tx_ring[tx_head].ctrl = ctrl; - macb->tx_ring[tx_head].addr = paddr; + macb_set_addr(macb, &macb->tx_ring[tx_head], paddr); + barrier(); macb_flush_ring_desc(macb, TX); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); @@ -363,19 +395,28 @@ static void reclaim_rx_buffers(struct macb_device *macb, unsigned int new_tail) { unsigned int i; + unsigned int count; i = macb->rx_tail; macb_invalidate_ring_desc(macb, RX); while (i > new_tail) { - macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED); i++; if (i > MACB_RX_RING_SIZE) i = 0; } while (i < new_tail) { - macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED); i++; } @@ -390,16 +431,25 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp) void *buffer; int length; u32 status; + u8 flag = false; macb->wrapped = false; for (;;) { macb_invalidate_ring_desc(macb, RX); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + next_rx_tail = next_rx_tail * 2; + if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED))) return -EAGAIN; status = macb->rx_ring[next_rx_tail].ctrl; if (status & MACB_BIT(RX_SOF)) { + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + next_rx_tail = next_rx_tail / 2; + flag = true; + } + if (next_rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, next_rx_tail); macb->wrapped = false; @@ -426,11 +476,22 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp) *packetp = buffer; } + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + if (!flag) + next_rx_tail = next_rx_tail / 2; + } + if (++next_rx_tail >= MACB_RX_RING_SIZE) next_rx_tail = 0; macb->next_rx_tail = next_rx_tail; return length; } else { + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + if (!flag) + next_rx_tail = next_rx_tail / 2; + flag = false; + } + if (++next_rx_tail >= MACB_RX_RING_SIZE) { macb->wrapped = true; next_rx_tail = 0; @@ -470,6 +531,12 @@ static int macb_phy_find(struct macb_device *macb, const char *name) int i; u16 phy_id; + phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1); + if (phy_id != 0xffff) { + printf("%s: PHY present at %d\n", name, macb->phy_addr); + return 0; + } + /* Search for PHY... */ for (i = 0; i < 32; i++) { macb->phy_addr = i; @@ -718,6 +785,7 @@ static int gmac_init_multi_queues(struct macb_device *macb) { int i, num_queues = 1; u32 queue_mask; + unsigned long paddr; /* bit 0 is never set but queue 0 always exists */ queue_mask = gem_readl(macb, DCFG6) & 0xff; @@ -731,10 +799,18 @@ static int gmac_init_multi_queues(struct macb_device *macb) macb->dummy_desc->addr = 0; flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN)); - - for (i = 1; i < num_queues; i++) - gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); - + paddr = macb->dummy_desc_dma; + + for (i = 1; i < num_queues; i++) { + gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1); + gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + gem_writel_queue_TBQPH(macb, upper_32_bits(paddr), + i - 1); + gem_writel_queue_RBQPH(macb, upper_32_bits(paddr), + i - 1); + } + } return 0; } @@ -760,6 +836,9 @@ static void gmac_configure_dma(struct macb_device *macb) dmacfg &= ~GEM_BIT(ENDIA_DESC); dmacfg &= ~GEM_BIT(ADDR64); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + dmacfg |= GEM_BIT(ADDR64); + gem_writel(macb, DMACFG, dmacfg); } @@ -775,6 +854,7 @@ static int _macb_init(struct macb_device *macb, const char *name) unsigned long paddr; int ret; int i; + int count; /* * macb_halt should have been called at some point before now, @@ -786,20 +866,28 @@ static int _macb_init(struct macb_device *macb, const char *name) for (i = 0; i < MACB_RX_RING_SIZE; i++) { if (i == (MACB_RX_RING_SIZE - 1)) paddr |= MACB_BIT(RX_WRAP); - macb->rx_ring[i].addr = paddr; - macb->rx_ring[i].ctrl = 0; + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb->rx_ring[count].ctrl = 0; + macb_set_addr(macb, &macb->rx_ring[count], paddr); paddr += macb->rx_buffer_size; } macb_flush_ring_desc(macb, RX); macb_flush_rx_buffer(macb); for (i = 0; i < MACB_TX_RING_SIZE; i++) { - macb->tx_ring[i].addr = 0; + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) + count = i * 2; + else + count = i; + macb_set_addr(macb, &macb->tx_ring[count], 0); if (i == (MACB_TX_RING_SIZE - 1)) - macb->tx_ring[i].ctrl = MACB_BIT(TX_USED) | + macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) | MACB_BIT(TX_WRAP); else - macb->tx_ring[i].ctrl = MACB_BIT(TX_USED); + macb->tx_ring[count].ctrl = MACB_BIT(TX_USED); } macb_flush_ring_desc(macb, TX); @@ -812,8 +900,12 @@ static int _macb_init(struct macb_device *macb, const char *name) gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT); #endif - macb_writel(macb, RBQP, macb->rx_ring_dma); - macb_writel(macb, TBQP, macb->tx_ring_dma); + macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma)); + macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma)); + if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) { + macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma)); + macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma)); + } if (macb_is_gem(macb)) { /* Initialize DMA properties */ @@ -1217,6 +1309,7 @@ static int macb_enable_clk(struct udevice *dev) static const struct macb_config default_gem_config = { .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = NULL, }; @@ -1224,11 +1317,12 @@ static int macb_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct macb_device *macb = dev_get_priv(dev); + struct ofnode_phandle_args phandle_args; const char *phy_mode; int ret; - phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", - NULL); + phy_mode = dev_read_prop(dev, "phy-mode", NULL); + if (phy_mode) macb->phy_interface = phy_get_interface_by_name(phy_mode); if (macb->phy_interface == -1) { @@ -1236,6 +1330,12 @@ static int macb_eth_probe(struct udevice *dev) return -EINVAL; } + /* Read phyaddr from DT */ + if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, + &phandle_args)) + macb->phy_addr = ofnode_read_u32_default(phandle_args.node, + "reg", -1); + macb->regs = (void *)pdata->iobase; macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678); @@ -1304,13 +1404,21 @@ static int macb_eth_of_to_plat(struct udevice *dev) return macb_late_eth_of_to_plat(dev); } +static const struct macb_config microchip_config = { + .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_64B, + .clk_init = NULL, +}; + static const struct macb_config sama5d4_config = { .dma_burst_length = 4, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = NULL, }; static const struct macb_config sifive_config = { .dma_burst_length = 16, + .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = macb_sifive_clk_init, }; @@ -1324,6 +1432,8 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,zynq-gem" }, { .compatible = "sifive,fu540-c000-gem", .data = (ulong)&sifive_config }, + { .compatible = "microchip,mpfs-mss-gem", + .data = (ulong)µchip_config }, { } }; diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 9b16383eba..72b84ae96e 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -768,5 +768,11 @@ #define GEM_RX_CSUM_CHECKED_MASK 2 #define gem_writel_queue_TBQP(port, value, queue_num) \ writel((value), (port)->regs + GEM_TBQP(queue_num)) +#define gem_writel_queue_TBQPH(port, value, queue_num) \ + writel((value), (port)->regs + GEM_TBQPH(queue_num)) +#define gem_writel_queue_RBQP(port, value, queue_num) \ + writel((value), (port)->regs + GEM_RBQP(queue_num)) +#define gem_writel_queue_RBQPH(port, value, queue_num) \ + writel((value), (port)->regs + GEM_RBQPH(queue_num)) #endif /* __DRIVERS_MACB_H__ */ diff --git a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c index db2cf86f63..a3797b22c7 100644 --- a/drivers/timer/andes_plmt_timer.c +++ b/drivers/timer/andes_plmt_timer.c @@ -18,11 +18,30 @@ /* mtime register */ #define MTIME_REG(base) ((ulong)(base)) -static u64 andes_plmt_get_count(struct udevice *dev) +static u64 notrace andes_plmt_get_count(struct udevice *dev) { return readq((void __iomem *)MTIME_REG(dev_get_priv(dev))); } +#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY) +/** + * timer_early_get_rate() - Get the timer rate before driver model + */ +unsigned long notrace timer_early_get_rate(void) +{ + return RISCV_MMODE_TIMER_FREQ; +} + +/** + * timer_early_get_count() - Get the timer count before driver model + * + */ +u64 notrace timer_early_get_count(void) +{ + return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE)); +} +#endif + static const struct timer_ops andes_plmt_ops = { .get_count = andes_plmt_get_count, }; diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c index 21ae184057..3627ed79b8 100644 --- a/drivers/timer/riscv_timer.c +++ b/drivers/timer/riscv_timer.c @@ -16,7 +16,7 @@ #include <timer.h> #include <asm/csr.h> -static u64 riscv_timer_get_count(struct udevice *dev) +static u64 notrace riscv_timer_get_count(struct udevice *dev) { __maybe_unused u32 hi, lo; @@ -31,6 +31,25 @@ static u64 riscv_timer_get_count(struct udevice *dev) return ((u64)hi << 32) | lo; } +#if CONFIG_IS_ENABLED(RISCV_SMODE) && IS_ENABLED(CONFIG_TIMER_EARLY) +/** + * timer_early_get_rate() - Get the timer rate before driver model + */ +unsigned long notrace timer_early_get_rate(void) +{ + return RISCV_SMODE_TIMER_FREQ; +} + +/** + * timer_early_get_count() - Get the timer count before driver model + * + */ +u64 notrace timer_early_get_count(void) +{ + return riscv_timer_get_count(NULL); +} +#endif + static int riscv_timer_probe(struct udevice *dev) { struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c index de23b85404..de7b4b95c9 100644 --- a/drivers/timer/sifive_clint_timer.c +++ b/drivers/timer/sifive_clint_timer.c @@ -15,11 +15,30 @@ /* mtime register */ #define MTIME_REG(base) ((ulong)(base) + 0xbff8) -static u64 sifive_clint_get_count(struct udevice *dev) +static u64 notrace sifive_clint_get_count(struct udevice *dev) { return readq((void __iomem *)MTIME_REG(dev_get_priv(dev))); } +#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY) +/** + * timer_early_get_rate() - Get the timer rate before driver model + */ +unsigned long notrace timer_early_get_rate(void) +{ + return RISCV_MMODE_TIMER_FREQ; +} + +/** + * timer_early_get_count() - Get the timer count before driver model + * + */ +u64 notrace timer_early_get_count(void) +{ + return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE)); +} +#endif + static const struct timer_ops sifive_clint_ops = { .get_count = sifive_clint_get_count, }; |